feat: 新增 core/agents 模块和 nanobot
- 新增 agents 模块,包含 agent、api、skills 等子模块 - 新增 nanobot 项目,支持多渠道集成 - 添加启动脚本 start-all.bat 和 start-all.sh Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
225
core/agents/agent/team_agent.py
Normal file
225
core/agents/agent/team_agent.py
Normal file
@@ -0,0 +1,225 @@
|
||||
"""Team agent for multi-agent collaboration."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TeamAgent:
|
||||
"""Team agent that manages multiple agents for collaborative problem solving.
|
||||
|
||||
Supports different strategies:
|
||||
- parallel: All agents respond in parallel, results are aggregated
|
||||
- sequential: Agents respond one by one in sequence
|
||||
- supervisor: A supervisor agent coordinates the work
|
||||
"""
|
||||
|
||||
def __init__(self, provider: Any, model: str, workspace: Any):
|
||||
"""Initialize the team agent.
|
||||
|
||||
Args:
|
||||
provider: LLM provider
|
||||
model: Model name to use
|
||||
workspace: Workspace path
|
||||
"""
|
||||
self.provider = provider
|
||||
self.model = model
|
||||
self.workspace = workspace
|
||||
|
||||
async def chat(
|
||||
self,
|
||||
message: str,
|
||||
session_id: str = "default",
|
||||
supervisor_agent_id: int = 0,
|
||||
member_agent_ids: list[int] | None = None,
|
||||
strategy: str = "parallel",
|
||||
) -> dict[str, Any]:
|
||||
"""Process a team chat message.
|
||||
|
||||
Args:
|
||||
message: User message
|
||||
session_id: Session identifier
|
||||
supervisor_agent_id: Supervisor agent ID (for future use)
|
||||
member_agent_ids: List of member agent IDs to involve
|
||||
strategy: Collaboration strategy (parallel/sequential/supervisor)
|
||||
|
||||
Returns:
|
||||
Dict with response and subtask_results
|
||||
"""
|
||||
member_agent_ids = member_agent_ids or []
|
||||
|
||||
logger.info(f"Team chat: strategy={strategy}, members={member_agent_ids}, message={message[:50]}...")
|
||||
|
||||
if strategy == "parallel":
|
||||
return await self._parallel_chat(message, member_agent_ids, session_id)
|
||||
elif strategy == "sequential":
|
||||
return await self._sequential_chat(message, member_agent_ids, session_id)
|
||||
else:
|
||||
# Default to parallel
|
||||
return await self._parallel_chat(message, member_agent_ids, session_id)
|
||||
|
||||
async def _parallel_chat(
|
||||
self,
|
||||
message: str,
|
||||
member_agent_ids: list[int],
|
||||
session_id: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Execute parallel chat with multiple agents.
|
||||
|
||||
Args:
|
||||
message: User message
|
||||
member_agent_ids: List of member agent IDs
|
||||
session_id: Session identifier
|
||||
|
||||
Returns:
|
||||
Aggregated response from all agents
|
||||
"""
|
||||
if not member_agent_ids:
|
||||
return {
|
||||
"response": "No member agents specified for team chat.",
|
||||
"subtask_results": [],
|
||||
}
|
||||
|
||||
# Create tasks for each agent
|
||||
tasks = []
|
||||
for agent_id in member_agent_ids:
|
||||
task = self._call_agent(agent_id, message, session_id)
|
||||
tasks.append(task)
|
||||
|
||||
# Execute all tasks in parallel
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
# Aggregate results
|
||||
subtask_results = []
|
||||
responses = []
|
||||
|
||||
for i, result in enumerate(results):
|
||||
agent_id = member_agent_ids[i]
|
||||
|
||||
if isinstance(result, Exception):
|
||||
error_msg = f"Agent {agent_id} error: {str(result)}"
|
||||
logger.error(error_msg)
|
||||
subtask_results.append({
|
||||
"agent_id": agent_id,
|
||||
"status": "error",
|
||||
"result": str(result),
|
||||
})
|
||||
else:
|
||||
subtask_results.append({
|
||||
"agent_id": agent_id,
|
||||
"status": "success",
|
||||
"result": result,
|
||||
})
|
||||
responses.append(result)
|
||||
|
||||
# Combine responses
|
||||
if responses:
|
||||
combined_response = self._aggregate_responses(responses)
|
||||
else:
|
||||
combined_response = "All agents failed to respond."
|
||||
|
||||
return {
|
||||
"response": combined_response,
|
||||
"subtask_results": subtask_results,
|
||||
}
|
||||
|
||||
async def _sequential_chat(
|
||||
self,
|
||||
message: str,
|
||||
member_agent_ids: list[int],
|
||||
session_id: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Execute sequential chat with multiple agents.
|
||||
|
||||
Args:
|
||||
message: User message
|
||||
member_agent_ids: List of member agent IDs
|
||||
session_id: Session identifier
|
||||
|
||||
Returns:
|
||||
Aggregated response from all agents
|
||||
"""
|
||||
if not member_agent_ids:
|
||||
return {
|
||||
"response": "No member agents specified for team chat.",
|
||||
"subtask_results": [],
|
||||
}
|
||||
|
||||
subtask_results = []
|
||||
responses = []
|
||||
|
||||
for agent_id in member_agent_ids:
|
||||
try:
|
||||
result = await self._call_agent(agent_id, message, session_id)
|
||||
subtask_results.append({
|
||||
"agent_id": agent_id,
|
||||
"status": "success",
|
||||
"result": result,
|
||||
})
|
||||
responses.append(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Agent {agent_id} error: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
subtask_results.append({
|
||||
"agent_id": agent_id,
|
||||
"status": "error",
|
||||
"result": str(e),
|
||||
})
|
||||
|
||||
# Combine responses
|
||||
if responses:
|
||||
combined_response = self._aggregate_responses(responses)
|
||||
else:
|
||||
combined_response = "All agents failed to respond."
|
||||
|
||||
return {
|
||||
"response": combined_response,
|
||||
"subtask_results": subtask_results,
|
||||
}
|
||||
|
||||
async def _call_agent(
|
||||
self,
|
||||
agent_id: int,
|
||||
message: str,
|
||||
session_id: str,
|
||||
) -> str:
|
||||
"""Call an individual agent.
|
||||
|
||||
For now, this is a placeholder that simulates agent responses.
|
||||
In a real implementation, this would call the actual agent.
|
||||
|
||||
Args:
|
||||
agent_id: Agent ID
|
||||
message: User message
|
||||
session_id: Session identifier
|
||||
|
||||
Returns:
|
||||
Agent response
|
||||
"""
|
||||
# Simulate agent processing delay
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
# Return a simulated response
|
||||
return f"Agent {agent_id} processed: {message[:30]}..."
|
||||
|
||||
def _aggregate_responses(self, responses: list[str]) -> str:
|
||||
"""Aggregate multiple agent responses into a single response.
|
||||
|
||||
Args:
|
||||
responses: List of individual agent responses
|
||||
|
||||
Returns:
|
||||
Combined response
|
||||
"""
|
||||
if len(responses) == 1:
|
||||
return responses[0]
|
||||
|
||||
header = f"【团队协作结果】共 {len(responses)} 位智能体参与了讨论:\n\n"
|
||||
body = ""
|
||||
|
||||
for i, resp in enumerate(responses, 1):
|
||||
body += f"--- 智能体 {i} ---\n{resp}\n\n"
|
||||
|
||||
return header + body
|
||||
Reference in New Issue
Block a user