- supervisor, memory, skills 模块 - LLM 工厂 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
157 lines
5.1 KiB
Python
157 lines
5.1 KiB
Python
"""
|
|
Supervisor - 多智能体调度器
|
|
"""
|
|
import asyncio
|
|
from typing import List, Dict, Any
|
|
from app.agent.core.agent import AgentCore
|
|
|
|
|
|
class Supervisor:
|
|
"""多智能体调度器"""
|
|
|
|
def __init__(self, supervisor_agent: AgentCore, members: List[AgentCore], strategy: str = "parallel"):
|
|
"""
|
|
初始化调度器
|
|
|
|
Args:
|
|
supervisor_agent: 主智能体
|
|
members: 子智能体列表
|
|
strategy: 调度策略 (parallel/sequential)
|
|
"""
|
|
self.supervisor = supervisor_agent
|
|
self.members = members
|
|
self.strategy = strategy
|
|
|
|
async def run(self, task: str, user_id: int, session_id: str) -> Dict[str, Any]:
|
|
"""
|
|
执行多智能体协作
|
|
|
|
Args:
|
|
task: 用户任务
|
|
user_id: 用户 ID
|
|
session_id: 会话 ID
|
|
|
|
Returns:
|
|
Dict: 包含主响应和子任务结果
|
|
"""
|
|
# 1. 任务分解
|
|
subtasks = await self._decompose_task(task)
|
|
|
|
# 2. 分配任务
|
|
if self.strategy == "parallel":
|
|
results = await self._dispatch_parallel(subtasks, user_id, session_id)
|
|
else:
|
|
results = await self._dispatch_sequential(subtasks, user_id, session_id)
|
|
|
|
# 3. 汇总结果
|
|
final_result = await self._aggregate(results)
|
|
|
|
return {
|
|
"main_response": final_result,
|
|
"subtask_results": results,
|
|
"strategy": self.strategy
|
|
}
|
|
|
|
async def _decompose_task(self, task: str) -> List[Dict[str, str]]:
|
|
"""任务分解"""
|
|
# 调用 LLM 分解任务
|
|
prompt = f"""分解以下任务为子任务,返回 JSON 数组格式:
|
|
任务: {task}
|
|
|
|
返回格式示例:
|
|
[{{"task": "子任务1描述", "agent_type": "适合的智能体类型"}}, {{"task": "子任务2描述", "agent_type": "适合的智能体类型"}}]
|
|
|
|
请直接返回 JSON 数组,不要其他内容。"""
|
|
|
|
response = await self.supervisor.llm.generate(prompt, [])
|
|
|
|
try:
|
|
import json
|
|
# 尝试解析 JSON
|
|
subtasks = json.loads(response)
|
|
return subtasks
|
|
except:
|
|
# 解析失败,创建默认子任务
|
|
return [{"task": task, "agent_type": "general"}]
|
|
|
|
async def _dispatch_parallel(self, subtasks: List[Dict], user_id: int, session_id: str) -> List[Dict]:
|
|
"""并行分发任务"""
|
|
tasks = []
|
|
for i, subtask in enumerate(subtasks):
|
|
if i < len(self.members):
|
|
member = self.members[i]
|
|
else:
|
|
# 如果子任务多于成员,使用轮询
|
|
member = self.members[i % len(self.members)]
|
|
|
|
tasks.append(member.run(subtask['task'], user_id, session_id))
|
|
|
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
|
|
# 处理结果
|
|
formatted_results = []
|
|
for i, result in enumerate(results):
|
|
if isinstance(result, Exception):
|
|
formatted_results.append({
|
|
"task": subtasks[i]['task'],
|
|
"success": False,
|
|
"error": str(result)
|
|
})
|
|
else:
|
|
formatted_results.append({
|
|
"task": subtasks[i]['task'],
|
|
"success": True,
|
|
"content": result.content,
|
|
"tool_calls": result.tool_calls
|
|
})
|
|
|
|
return formatted_results
|
|
|
|
async def _dispatch_sequential(self, subtasks: List[Dict], user_id: int, session_id: str) -> List[Dict]:
|
|
"""顺序分发任务"""
|
|
results = []
|
|
context = ""
|
|
|
|
for i, subtask in enumerate(subtasks):
|
|
# 选择子智能体
|
|
if i < len(self.members):
|
|
member = self.members[i]
|
|
else:
|
|
member = self.members[i % len(self.members)]
|
|
|
|
# 传递前一个结果作为上下文
|
|
enhanced_task = f"{context}\n\n当前任务: {subtask['task']}" if context else subtask['task']
|
|
|
|
result = await member.run(enhanced_task, user_id, session_id)
|
|
|
|
results.append({
|
|
"task": subtask['task'],
|
|
"success": True,
|
|
"content": result.content,
|
|
"tool_calls": result.tool_calls
|
|
})
|
|
|
|
# 累加上下文
|
|
context += f"\n\n=== 任务: {subtask['task']} ===\n{result.content}"
|
|
|
|
return results
|
|
|
|
async def _aggregate(self, results: List[Dict]) -> str:
|
|
"""汇总结果"""
|
|
# 过滤成功的结果
|
|
success_results = [r for r in results if r.get('success')]
|
|
|
|
if not success_results:
|
|
return "所有子任务执行失败"
|
|
|
|
if len(success_results) == 1:
|
|
return success_results[0].get('content', '')
|
|
|
|
# 调用 LLM 汇总
|
|
summary_prompt = "请汇总以下所有任务的结果,生成一个完整的回复:\n\n"
|
|
for i, result in enumerate(success_results, 1):
|
|
summary_prompt += f"=== 任务 {i}: {result.get('task', '')} ===\n{result.get('content', '')}\n\n"
|
|
|
|
final_response = await self.supervisor.llm.generate(summary_prompt, [])
|
|
return final_response
|