133 lines
4.0 KiB
Python
133 lines
4.0 KiB
Python
|
|
"""
|
|||
|
|
Goal/Task 异步任务 — Celery 任务定义
|
|||
|
|
|
|||
|
|
Main Agent 的目标分解、任务执行、自主循环等重量级操作通过 Celery 异步执行。
|
|||
|
|
"""
|
|||
|
|
from app.core.tools_bootstrap import ensure_builtin_tools_registered
|
|||
|
|
|
|||
|
|
ensure_builtin_tools_registered()
|
|||
|
|
|
|||
|
|
from app.core.celery_app import celery_app
|
|||
|
|
from app.core.database import SessionLocal
|
|||
|
|
from app.models.goal import Goal
|
|||
|
|
from app.models.execution import Execution
|
|||
|
|
from app.services.main_agent_service import MainAgentService
|
|||
|
|
import asyncio
|
|||
|
|
import logging
|
|||
|
|
import time
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@celery_app.task(bind=True)
|
|||
|
|
def decompose_goal_task(self, goal_id: str):
|
|||
|
|
"""
|
|||
|
|
异步分解目标:使用 LLM 将 Goal 分解为 Task 树。
|
|||
|
|
|
|||
|
|
在 Celery Worker 中执行,避免 API 请求超时。
|
|||
|
|
"""
|
|||
|
|
db = SessionLocal()
|
|||
|
|
try:
|
|||
|
|
service = MainAgentService(db)
|
|||
|
|
goal = asyncio.run(service.decompose_goal(goal_id))
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"status": "completed",
|
|||
|
|
"goal_id": goal_id,
|
|||
|
|
"goal_title": goal.title,
|
|||
|
|
}
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Goal decomposition failed: {e}", exc_info=True)
|
|||
|
|
db.rollback()
|
|||
|
|
return {"status": "failed", "goal_id": goal_id, "error": str(e)}
|
|||
|
|
finally:
|
|||
|
|
db.close()
|
|||
|
|
|
|||
|
|
|
|||
|
|
@celery_app.task(bind=True)
|
|||
|
|
def execute_goal_task(self, goal_id: str):
|
|||
|
|
"""
|
|||
|
|
异步执行 Goal:启动 Main Agent 管理目标全生命周期。
|
|||
|
|
|
|||
|
|
1. 分解目标(如果尚未分解)
|
|||
|
|
2. 持续执行 task 直到完成或阻塞
|
|||
|
|
3. 更新 Goal 状态
|
|||
|
|
"""
|
|||
|
|
db = SessionLocal()
|
|||
|
|
start_time = time.time()
|
|||
|
|
try:
|
|||
|
|
goal = db.query(Goal).filter(Goal.id == goal_id).first()
|
|||
|
|
if not goal:
|
|||
|
|
return {"status": "failed", "goal_id": goal_id, "error": "目标不存在"}
|
|||
|
|
|
|||
|
|
# 更新状态
|
|||
|
|
goal.status = "active"
|
|||
|
|
db.commit()
|
|||
|
|
|
|||
|
|
service = MainAgentService(db)
|
|||
|
|
result = asyncio.run(service.start_goal_execution(goal_id))
|
|||
|
|
|
|||
|
|
elapsed = int((time.time() - start_time) * 1000)
|
|||
|
|
return {
|
|||
|
|
"status": "completed",
|
|||
|
|
"goal_id": goal_id,
|
|||
|
|
"elapsed_ms": elapsed,
|
|||
|
|
**result,
|
|||
|
|
}
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Goal execution failed: {e}", exc_info=True)
|
|||
|
|
goal = db.query(Goal).filter(Goal.id == goal_id).first()
|
|||
|
|
if goal:
|
|||
|
|
goal.status = "failed"
|
|||
|
|
db.commit()
|
|||
|
|
return {"status": "failed", "goal_id": goal_id, "error": str(e)}
|
|||
|
|
finally:
|
|||
|
|
db.close()
|
|||
|
|
|
|||
|
|
|
|||
|
|
@celery_app.task(bind=True)
|
|||
|
|
def execute_task_celery(self, task_id: str):
|
|||
|
|
"""
|
|||
|
|
异步执行单个 Task。
|
|||
|
|
|
|||
|
|
Main Agent 创建 Execution 记录后将任务交给 Celery Worker 执行。
|
|||
|
|
"""
|
|||
|
|
db = SessionLocal()
|
|||
|
|
start_time = time.time()
|
|||
|
|
try:
|
|||
|
|
service = MainAgentService(db)
|
|||
|
|
result = asyncio.run(service.execute_task(task_id))
|
|||
|
|
|
|||
|
|
elapsed = int((time.time() - start_time) * 1000)
|
|||
|
|
return {
|
|||
|
|
"status": result.get("status", "completed"),
|
|||
|
|
"task_id": task_id,
|
|||
|
|
"elapsed_ms": elapsed,
|
|||
|
|
**result,
|
|||
|
|
}
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Task execution failed: {e}", exc_info=True)
|
|||
|
|
return {"status": "failed", "task_id": task_id, "error": str(e)}
|
|||
|
|
finally:
|
|||
|
|
db.close()
|
|||
|
|
|
|||
|
|
|
|||
|
|
@celery_app.task(bind=True)
|
|||
|
|
def autonomy_tick_task(self, goal_id: str):
|
|||
|
|
"""
|
|||
|
|
自主循环单次心跳:检查进度 → 执行可运行任务 → 处理失败 → 通知。
|
|||
|
|
|
|||
|
|
由 Celery Beat 定时调度(根据 Goal.autonomy_config.check_interval_minutes)。
|
|||
|
|
"""
|
|||
|
|
db = SessionLocal()
|
|||
|
|
try:
|
|||
|
|
service = MainAgentService(db)
|
|||
|
|
result = asyncio.run(service.autonomy_tick(goal_id))
|
|||
|
|
logger.info(f"Autonomy tick for goal {goal_id}: {result.get('status', 'unknown')}")
|
|||
|
|
return {"status": "completed", "goal_id": goal_id, **result}
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Autonomy tick failed for goal {goal_id}: {e}", exc_info=True)
|
|||
|
|
return {"status": "failed", "goal_id": goal_id, "error": str(e)}
|
|||
|
|
finally:
|
|||
|
|
db.close()
|