[modify] manage multi agent logic
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@ import datetime
|
|||||||
from typing import Optional, List, Dict, Any, Union
|
from typing import Optional, List, Dict, Any, Union
|
||||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer
|
from pydantic import BaseModel, Field, ConfigDict, field_serializer
|
||||||
|
|
||||||
|
from app.schemas import ModelParameters
|
||||||
|
|
||||||
|
|
||||||
# ==================== 子 Agent 配置 ====================
|
# ==================== 子 Agent 配置 ====================
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ class ExecutionConfig(BaseModel):
|
|||||||
parallel_limit: int = Field(default=3, ge=1, le=10, description="并行限制")
|
parallel_limit: int = Field(default=3, ge=1, le=10, description="并行限制")
|
||||||
retry_on_failure: bool = Field(default=True, description="失败时是否重试")
|
retry_on_failure: bool = Field(default=True, description="失败时是否重试")
|
||||||
max_retries: int = Field(default=3, ge=0, le=10, description="最大重试次数")
|
max_retries: int = Field(default=3, ge=0, le=10, description="最大重试次数")
|
||||||
|
|
||||||
# 新增:路由模式配置
|
# 新增:路由模式配置
|
||||||
routing_mode: str = Field(
|
routing_mode: str = Field(
|
||||||
default="master_agent",
|
default="master_agent",
|
||||||
@@ -41,14 +43,14 @@ class ExecutionConfig(BaseModel):
|
|||||||
default=True,
|
default=True,
|
||||||
description="是否启用规则快速路径(性能优化,高置信度关键词直接返回)"
|
description="是否启用规则快速路径(性能优化,高置信度关键词直接返回)"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 新增:结果整合模式配置
|
# 新增:结果整合模式配置
|
||||||
result_merge_mode: str = Field(
|
result_merge_mode: str = Field(
|
||||||
default="smart",
|
default="smart",
|
||||||
pattern="^(smart|master)$",
|
pattern="^(smart|master)$",
|
||||||
description="结果整合模式:smart(规则去重,快速)| master(Master Agent 智能整合,连贯)"
|
description="结果整合模式:smart(规则去重,快速)| master(Master Agent 智能整合,连贯)"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 新增:子 Agent 执行模式配置
|
# 新增:子 Agent 执行模式配置
|
||||||
sub_agent_execution_mode: str = Field(
|
sub_agent_execution_mode: str = Field(
|
||||||
default="parallel",
|
default="parallel",
|
||||||
@@ -82,6 +84,11 @@ class MultiAgentConfigUpdate(BaseModel):
|
|||||||
"""更新多 Agent 配置"""
|
"""更新多 Agent 配置"""
|
||||||
master_agent_id: Optional[uuid.UUID] = None
|
master_agent_id: Optional[uuid.UUID] = None
|
||||||
master_agent_name: Optional[str] = Field(None, max_length=100, description="主 Agent 名称")
|
master_agent_name: Optional[str] = Field(None, max_length=100, description="主 Agent 名称")
|
||||||
|
default_model_config_id : uuid.UUID = Field(description="默认模型配置ID")
|
||||||
|
model_parameters: ModelParameters | None = Field(
|
||||||
|
default_factory=ModelParameters,
|
||||||
|
description="模型参数配置(temperature、max_tokens 等)"
|
||||||
|
)
|
||||||
orchestration_mode: Optional[str] = Field(
|
orchestration_mode: Optional[str] = Field(
|
||||||
None,
|
None,
|
||||||
pattern="^(sequential|parallel|conditional|loop)$"
|
pattern="^(sequential|parallel|conditional|loop)$"
|
||||||
@@ -99,11 +106,16 @@ class MultiAgentConfigUpdate(BaseModel):
|
|||||||
class MultiAgentConfigSchema(BaseModel):
|
class MultiAgentConfigSchema(BaseModel):
|
||||||
"""多 Agent 配置输出"""
|
"""多 Agent 配置输出"""
|
||||||
model_config = ConfigDict(from_attributes=True)
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
id: uuid.UUID
|
id: uuid.UUID
|
||||||
app_id: uuid.UUID
|
app_id: uuid.UUID
|
||||||
master_agent_id: uuid.UUID
|
master_agent_id: uuid.UUID
|
||||||
master_agent_name: Optional[str]
|
master_agent_name: Optional[str]
|
||||||
|
default_model_config_id : uuid.UUID | None = Field(description="默认模型配置ID")
|
||||||
|
model_parameters: ModelParameters | None = Field(
|
||||||
|
default_factory=ModelParameters,
|
||||||
|
description="模型参数配置(temperature、max_tokens 等)"
|
||||||
|
)
|
||||||
orchestration_mode: str
|
orchestration_mode: str
|
||||||
sub_agents: List[Dict[str, Any]]
|
sub_agents: List[Dict[str, Any]]
|
||||||
routing_rules: Optional[List[Dict[str, Any]]]
|
routing_rules: Optional[List[Dict[str, Any]]]
|
||||||
@@ -112,11 +124,11 @@ class MultiAgentConfigSchema(BaseModel):
|
|||||||
is_active: bool
|
is_active: bool
|
||||||
created_at: datetime.datetime
|
created_at: datetime.datetime
|
||||||
updated_at: datetime.datetime
|
updated_at: datetime.datetime
|
||||||
|
|
||||||
@field_serializer("created_at", when_used="json")
|
@field_serializer("created_at", when_used="json")
|
||||||
def _serialize_created_at(self, dt: datetime.datetime):
|
def _serialize_created_at(self, dt: datetime.datetime):
|
||||||
return int(dt.timestamp() * 1000) if dt else None
|
return int(dt.timestamp() * 1000) if dt else None
|
||||||
|
|
||||||
@field_serializer("updated_at", when_used="json")
|
@field_serializer("updated_at", when_used="json")
|
||||||
def _serialize_updated_at(self, dt: datetime.datetime):
|
def _serialize_updated_at(self, dt: datetime.datetime):
|
||||||
return int(dt.timestamp() * 1000) if dt else None
|
return int(dt.timestamp() * 1000) if dt else None
|
||||||
|
|||||||
@@ -5,63 +5,63 @@ import uuid
|
|||||||
from typing import Dict, Any, List, Optional, Tuple
|
from typing import Dict, Any, List, Optional, Tuple
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.schemas import ModelParameters
|
||||||
from app.services.conversation_state_manager import ConversationStateManager
|
from app.services.conversation_state_manager import ConversationStateManager
|
||||||
from app.models import ModelConfig, AgentConfig
|
from app.models import ModelConfig, AgentConfig
|
||||||
from app.core.logging_config import get_business_logger
|
from app.core.logging_config import get_business_logger
|
||||||
|
from app.services.model_service import ModelApiKeyService
|
||||||
|
|
||||||
logger = get_business_logger()
|
logger = get_business_logger()
|
||||||
|
|
||||||
|
|
||||||
class MasterAgentRouter:
|
class MasterAgentRouter:
|
||||||
"""Master Agent 路由器
|
"""Master Agent 路由器
|
||||||
|
|
||||||
让 Master Agent 作为"大脑",负责:
|
让 Master Agent 作为"大脑",负责:
|
||||||
1. 分析用户意图
|
1. 分析用户意图
|
||||||
2. 选择最合适的 Sub Agent
|
2. 选择最合适的 Sub Agent
|
||||||
3. 决定是否需要多 Agent 协作
|
3. 决定是否需要多 Agent 协作
|
||||||
4. 管理会话上下文
|
4. 管理会话上下文
|
||||||
|
|
||||||
优势:
|
优势:
|
||||||
- 更智能的决策(基于完整上下文)
|
- 更智能的决策(基于完整上下文)
|
||||||
- 减少 LLM 调用次数
|
- 减少 LLM 调用次数
|
||||||
- 架构更清晰(Master Agent 真正起作用)
|
- 架构更清晰(Master Agent 真正起作用)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
db: Session,
|
db: Session,
|
||||||
master_agent_config: AgentConfig,
|
|
||||||
master_model_config: ModelConfig,
|
master_model_config: ModelConfig,
|
||||||
|
model_parameters: ModelParameters,
|
||||||
sub_agents: Dict[str, Any],
|
sub_agents: Dict[str, Any],
|
||||||
state_manager: ConversationStateManager,
|
state_manager: ConversationStateManager,
|
||||||
enable_rule_fast_path: bool = True
|
enable_rule_fast_path: bool = True
|
||||||
):
|
):
|
||||||
"""初始化 Master Agent 路由器
|
"""初始化 Master Agent 路由器
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
db: 数据库会话
|
db: 数据库会话
|
||||||
master_agent_config: Master Agent 配置
|
|
||||||
master_model_config: Master Agent 使用的模型配置
|
master_model_config: Master Agent 使用的模型配置
|
||||||
sub_agents: 子 Agent 配置字典
|
sub_agents: 子 Agent 配置字典
|
||||||
state_manager: 会话状态管理器
|
state_manager: 会话状态管理器
|
||||||
enable_rule_fast_path: 是否启用规则快速路径(性能优化)
|
enable_rule_fast_path: 是否启用规则快速路径(性能优化)
|
||||||
"""
|
"""
|
||||||
self.db = db
|
self.db = db
|
||||||
self.master_agent_config = master_agent_config
|
|
||||||
self.master_model_config = master_model_config
|
self.master_model_config = master_model_config
|
||||||
|
self.model_parameters = model_parameters
|
||||||
self.sub_agents = sub_agents
|
self.sub_agents = sub_agents
|
||||||
self.state_manager = state_manager
|
self.state_manager = state_manager
|
||||||
self.enable_rule_fast_path = enable_rule_fast_path
|
self.enable_rule_fast_path = enable_rule_fast_path
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Master Agent 路由器初始化",
|
"Master Agent 路由器初始化",
|
||||||
extra={
|
extra={
|
||||||
"master_agent": master_agent_config.name,
|
|
||||||
"sub_agent_count": len(sub_agents),
|
"sub_agent_count": len(sub_agents),
|
||||||
"enable_rule_fast_path": enable_rule_fast_path
|
"enable_rule_fast_path": enable_rule_fast_path
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def route(
|
async def route(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
@@ -69,12 +69,12 @@ class MasterAgentRouter:
|
|||||||
variables: Optional[Dict[str, Any]] = None
|
variables: Optional[Dict[str, Any]] = None
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""智能路由决策
|
"""智能路由决策
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: 用户消息
|
message: 用户消息
|
||||||
conversation_id: 会话 ID
|
conversation_id: 会话 ID
|
||||||
variables: 变量参数
|
variables: 变量参数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
路由决策结果
|
路由决策结果
|
||||||
"""
|
"""
|
||||||
@@ -85,12 +85,12 @@ class MasterAgentRouter:
|
|||||||
"conversation_id": conversation_id
|
"conversation_id": conversation_id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# 1. 获取会话状态
|
# 1. 获取会话状态
|
||||||
state = None
|
state = None
|
||||||
if conversation_id:
|
if conversation_id:
|
||||||
state = self.state_manager.get_state(conversation_id)
|
state = self.state_manager.get_state(conversation_id)
|
||||||
|
|
||||||
# 2. 尝试规则快速路径(可选的性能优化)
|
# 2. 尝试规则快速路径(可选的性能优化)
|
||||||
if self.enable_rule_fast_path:
|
if self.enable_rule_fast_path:
|
||||||
rule_result = self._try_rule_fast_path(message, state)
|
rule_result = self._try_rule_fast_path(message, state)
|
||||||
@@ -102,7 +102,7 @@ class MasterAgentRouter:
|
|||||||
"confidence": rule_result["confidence"]
|
"confidence": rule_result["confidence"]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# 更新会话状态
|
# 更新会话状态
|
||||||
if conversation_id:
|
if conversation_id:
|
||||||
self.state_manager.update_state(
|
self.state_manager.update_state(
|
||||||
@@ -112,12 +112,12 @@ class MasterAgentRouter:
|
|||||||
rule_result.get("topic"),
|
rule_result.get("topic"),
|
||||||
rule_result["confidence"]
|
rule_result["confidence"]
|
||||||
)
|
)
|
||||||
|
|
||||||
return rule_result
|
return rule_result
|
||||||
|
|
||||||
# 3. 调用 Master Agent 做决策
|
# 3. 调用 Master Agent 做决策
|
||||||
decision = await self._master_agent_decide(message, state, variables)
|
decision = await self._master_agent_decide(message, state, variables)
|
||||||
|
|
||||||
# 4. 更新会话状态
|
# 4. 更新会话状态
|
||||||
if conversation_id:
|
if conversation_id:
|
||||||
self.state_manager.update_state(
|
self.state_manager.update_state(
|
||||||
@@ -127,7 +127,7 @@ class MasterAgentRouter:
|
|||||||
decision.get("topic"),
|
decision.get("topic"),
|
||||||
decision["confidence"]
|
decision["confidence"]
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Master Agent 路由完成",
|
"Master Agent 路由完成",
|
||||||
extra={
|
extra={
|
||||||
@@ -136,22 +136,22 @@ class MasterAgentRouter:
|
|||||||
"confidence": decision["confidence"]
|
"confidence": decision["confidence"]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return decision
|
return decision
|
||||||
|
|
||||||
def _try_rule_fast_path(
|
def _try_rule_fast_path(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
state: Optional[Dict[str, Any]]
|
state: Optional[Dict[str, Any]]
|
||||||
) -> Optional[Dict[str, Any]]:
|
) -> Optional[Dict[str, Any]]:
|
||||||
"""尝试规则快速路径(性能优化)
|
"""尝试规则快速路径(性能优化)
|
||||||
|
|
||||||
对于明确的关键词匹配,直接返回结果,不调用 Master Agent
|
对于明确的关键词匹配,直接返回结果,不调用 Master Agent
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: 用户消息
|
message: 用户消息
|
||||||
state: 会话状态
|
state: 会话状态
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
如果命中规则返回决策结果,否则返回 None
|
如果命中规则返回决策结果,否则返回 None
|
||||||
"""
|
"""
|
||||||
@@ -178,15 +178,15 @@ class MasterAgentRouter:
|
|||||||
"confidence_threshold": 0.9
|
"confidence_threshold": 0.9
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
message_lower = message.lower()
|
message_lower = message.lower()
|
||||||
|
|
||||||
for rule in high_confidence_rules:
|
for rule in high_confidence_rules:
|
||||||
matched_keywords = [kw for kw in rule["keywords"] if kw in message_lower]
|
matched_keywords = [kw for kw in rule["keywords"] if kw in message_lower]
|
||||||
|
|
||||||
if matched_keywords:
|
if matched_keywords:
|
||||||
confidence = len(matched_keywords) / len(rule["keywords"])
|
confidence = len(matched_keywords) / len(rule["keywords"])
|
||||||
|
|
||||||
if confidence >= rule["confidence_threshold"]:
|
if confidence >= rule["confidence_threshold"]:
|
||||||
# 查找对应的 agent
|
# 查找对应的 agent
|
||||||
for agent_id, agent_data in self.sub_agents.items():
|
for agent_id, agent_data in self.sub_agents.items():
|
||||||
@@ -201,9 +201,9 @@ class MasterAgentRouter:
|
|||||||
"need_collaboration": False,
|
"need_collaboration": False,
|
||||||
"routing_method": "rule"
|
"routing_method": "rule"
|
||||||
}
|
}
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _master_agent_decide(
|
async def _master_agent_decide(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
@@ -211,35 +211,35 @@ class MasterAgentRouter:
|
|||||||
variables: Optional[Dict[str, Any]]
|
variables: Optional[Dict[str, Any]]
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""让 Master Agent 做路由决策
|
"""让 Master Agent 做路由决策
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: 用户消息
|
message: 用户消息
|
||||||
state: 会话状态
|
state: 会话状态
|
||||||
variables: 变量参数
|
variables: 变量参数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
决策结果
|
决策结果
|
||||||
"""
|
"""
|
||||||
# 1. 构建决策 prompt
|
# 1. 构建决策 prompt
|
||||||
prompt = self._build_decision_prompt(message, state, variables)
|
prompt = self._build_decision_prompt(message, state, variables)
|
||||||
|
|
||||||
# 2. 调用 Master Agent 的 LLM
|
# 2. 调用 Master Agent 的 LLM
|
||||||
try:
|
try:
|
||||||
response = await self._call_master_agent_llm(prompt)
|
response = await self._call_master_agent_llm(prompt)
|
||||||
|
|
||||||
# 3. 解析决策
|
# 3. 解析决策
|
||||||
decision = self._parse_decision(response)
|
decision = self._parse_decision(response)
|
||||||
|
|
||||||
# 4. 验证决策
|
# 4. 验证决策
|
||||||
decision = self._validate_decision(decision)
|
decision = self._validate_decision(decision)
|
||||||
|
|
||||||
return decision
|
return decision
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Master Agent 决策失败: {str(e)}")
|
logger.error(f"Master Agent 决策失败: {str(e)}")
|
||||||
# 降级到默认 agent
|
# 降级到默认 agent
|
||||||
return self._get_fallback_decision(message)
|
return self._get_fallback_decision(message)
|
||||||
|
|
||||||
def _build_decision_prompt(
|
def _build_decision_prompt(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
@@ -247,12 +247,12 @@ class MasterAgentRouter:
|
|||||||
variables: Optional[Dict[str, Any]]
|
variables: Optional[Dict[str, Any]]
|
||||||
) -> str:
|
) -> str:
|
||||||
"""构建 Master Agent 的决策 prompt
|
"""构建 Master Agent 的决策 prompt
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: 用户消息
|
message: 用户消息
|
||||||
state: 会话状态
|
state: 会话状态
|
||||||
variables: 变量参数
|
variables: 变量参数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
prompt 字符串
|
prompt 字符串
|
||||||
"""
|
"""
|
||||||
@@ -260,29 +260,29 @@ class MasterAgentRouter:
|
|||||||
agent_descriptions = []
|
agent_descriptions = []
|
||||||
for agent_id, agent_data in self.sub_agents.items():
|
for agent_id, agent_data in self.sub_agents.items():
|
||||||
agent_info = agent_data.get("info", {})
|
agent_info = agent_data.get("info", {})
|
||||||
|
|
||||||
name = agent_info.get("name", "未命名")
|
name = agent_info.get("name", "未命名")
|
||||||
role = agent_info.get("role", "")
|
role = agent_info.get("role", "")
|
||||||
capabilities = agent_info.get("capabilities", [])
|
capabilities = agent_info.get("capabilities", [])
|
||||||
|
|
||||||
# 简化格式:一行描述
|
# 简化格式:一行描述
|
||||||
desc = f"- {agent_id}: {name}"
|
desc = f"- {agent_id}: {name}"
|
||||||
if role:
|
if role:
|
||||||
desc += f" ({role})"
|
desc += f" ({role})"
|
||||||
if capabilities:
|
if capabilities:
|
||||||
desc += f" - {', '.join(capabilities[:3])}" # 只取前3个能力
|
desc += f" - {', '.join(capabilities[:3])}" # 只取前3个能力
|
||||||
|
|
||||||
agent_descriptions.append(desc)
|
agent_descriptions.append(desc)
|
||||||
|
|
||||||
agents_text = "\n".join(agent_descriptions)
|
agents_text = "\n".join(agent_descriptions)
|
||||||
|
|
||||||
# 2. 构建会话上下文
|
# 2. 构建会话上下文
|
||||||
context_text = ""
|
context_text = ""
|
||||||
if state:
|
if state:
|
||||||
current_agent = state.get("current_agent_id")
|
current_agent = state.get("current_agent_id")
|
||||||
last_topic = state.get("last_topic")
|
last_topic = state.get("last_topic")
|
||||||
same_turns = state.get("same_agent_turns", 0)
|
same_turns = state.get("same_agent_turns", 0)
|
||||||
|
|
||||||
if current_agent:
|
if current_agent:
|
||||||
context_text = f"""
|
context_text = f"""
|
||||||
当前会话上下文:
|
当前会话上下文:
|
||||||
@@ -290,10 +290,10 @@ class MasterAgentRouter:
|
|||||||
- 上一个主题: {last_topic}
|
- 上一个主题: {last_topic}
|
||||||
- 连续使用轮数: {same_turns}
|
- 连续使用轮数: {same_turns}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 获取第一个可用的 agent_id 作为示例
|
# 获取第一个可用的 agent_id 作为示例
|
||||||
example_agent_id = next(iter(self.sub_agents.keys())) if self.sub_agents else "agent_id"
|
example_agent_id = next(iter(self.sub_agents.keys())) if self.sub_agents else "agent_id"
|
||||||
|
|
||||||
# 3. 构建完整 prompt(简化版,提升性能)
|
# 3. 构建完整 prompt(简化版,提升性能)
|
||||||
prompt = f"""路由任务:分析问题并选择合适的 Agent。
|
prompt = f"""路由任务:分析问题并选择合适的 Agent。
|
||||||
|
|
||||||
@@ -331,15 +331,15 @@ class MasterAgentRouter:
|
|||||||
6. 只做路由决策,不要回答问题内容
|
6. 只做路由决策,不要回答问题内容
|
||||||
|
|
||||||
请返回 JSON:"""
|
请返回 JSON:"""
|
||||||
|
|
||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
async def _call_master_agent_llm(self, prompt: str) -> str:
|
async def _call_master_agent_llm(self, prompt: str) -> str:
|
||||||
"""调用 Master Agent 的 LLM
|
"""调用 Master Agent 的 LLM
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
prompt: 提示词
|
prompt: 提示词
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
LLM 响应
|
LLM 响应
|
||||||
"""
|
"""
|
||||||
@@ -347,16 +347,13 @@ class MasterAgentRouter:
|
|||||||
from app.core.models import RedBearLLM
|
from app.core.models import RedBearLLM
|
||||||
from app.core.models.base import RedBearModelConfig
|
from app.core.models.base import RedBearModelConfig
|
||||||
from app.models import ModelApiKey, ModelType
|
from app.models import ModelApiKey, ModelType
|
||||||
|
|
||||||
# 获取 API Key 配置
|
# 获取 API Key 配置
|
||||||
api_key_config = self.db.query(ModelApiKey).filter(
|
api_key_config = ModelApiKeyService.get_a_api_key(self.db, self.master_model_config.id)
|
||||||
ModelApiKey.model_config_id == self.master_model_config.id,
|
|
||||||
ModelApiKey.is_active == True
|
|
||||||
).first()
|
|
||||||
|
|
||||||
if not api_key_config:
|
if not api_key_config:
|
||||||
raise Exception("Master Agent 模型没有可用的 API Key")
|
raise Exception("Master Agent 模型没有可用的 API Key")
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"调用 Master Agent LLM",
|
"调用 Master Agent LLM",
|
||||||
extra={
|
extra={
|
||||||
@@ -364,39 +361,44 @@ class MasterAgentRouter:
|
|||||||
"model_name": api_key_config.model_name
|
"model_name": api_key_config.model_name
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
temperature = 0.3 # 决策任务使用较低温度
|
||||||
|
max_tokens = 1000
|
||||||
|
extra_params = None
|
||||||
|
if self.model_parameters:
|
||||||
|
extra_params = {"temperature": temperature,
|
||||||
|
"max_tokens":max_tokens
|
||||||
|
}
|
||||||
# 创建 RedBearModelConfig
|
# 创建 RedBearModelConfig
|
||||||
model_config = RedBearModelConfig(
|
model_config = RedBearModelConfig(
|
||||||
model_name=api_key_config.model_name,
|
model_name=api_key_config.model_name,
|
||||||
provider=api_key_config.provider,
|
provider=api_key_config.provider,
|
||||||
api_key=api_key_config.api_key,
|
api_key=api_key_config.api_key,
|
||||||
base_url=api_key_config.api_base,
|
base_url=api_key_config.api_base,
|
||||||
temperature=0.3, # 决策任务使用较低温度
|
extra_params = extra_params
|
||||||
max_tokens=1000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 创建 LLM 实例
|
# 创建 LLM 实例
|
||||||
llm = RedBearLLM(model_config, type=ModelType.CHAT)
|
llm = RedBearLLM(model_config, type=ModelType.CHAT)
|
||||||
|
|
||||||
# 调用模型
|
# 调用模型
|
||||||
response = await llm.ainvoke(prompt)
|
response = await llm.ainvoke(prompt)
|
||||||
|
|
||||||
# 提取响应内容
|
# 提取响应内容
|
||||||
if hasattr(response, 'content'):
|
if hasattr(response, 'content'):
|
||||||
return response.content
|
return response.content
|
||||||
else:
|
else:
|
||||||
return str(response)
|
return str(response)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Master Agent LLM 调用失败: {str(e)}")
|
logger.error(f"Master Agent LLM 调用失败: {str(e)}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _parse_decision(self, response: str) -> Dict[str, Any]:
|
def _parse_decision(self, response: str) -> Dict[str, Any]:
|
||||||
"""解析 Master Agent 的决策
|
"""解析 Master Agent 的决策
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
response: LLM 响应
|
response: LLM 响应
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
决策字典
|
决策字典
|
||||||
"""
|
"""
|
||||||
@@ -405,29 +407,29 @@ class MasterAgentRouter:
|
|||||||
json_match = re.search(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', response, re.DOTALL)
|
json_match = re.search(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', response, re.DOTALL)
|
||||||
if json_match:
|
if json_match:
|
||||||
decision = json.loads(json_match.group())
|
decision = json.loads(json_match.group())
|
||||||
|
|
||||||
# 添加默认值
|
# 添加默认值
|
||||||
decision.setdefault("confidence", 0.8)
|
decision.setdefault("confidence", 0.8)
|
||||||
decision.setdefault("strategy", "master_agent")
|
decision.setdefault("strategy", "master_agent")
|
||||||
decision.setdefault("routing_method", "master_agent")
|
decision.setdefault("routing_method", "master_agent")
|
||||||
decision.setdefault("need_collaboration", False)
|
decision.setdefault("need_collaboration", False)
|
||||||
decision.setdefault("collaboration_agents", [])
|
decision.setdefault("collaboration_agents", [])
|
||||||
|
|
||||||
return decision
|
return decision
|
||||||
else:
|
else:
|
||||||
raise ValueError("无法从响应中提取 JSON")
|
raise ValueError("无法从响应中提取 JSON")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"解析 Master Agent 决策失败: {str(e)}")
|
logger.error(f"解析 Master Agent 决策失败: {str(e)}")
|
||||||
logger.debug(f"原始响应: {response}")
|
logger.debug(f"原始响应: {response}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _validate_decision(self, decision: Dict[str, Any]) -> Dict[str, Any]:
|
def _validate_decision(self, decision: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""验证决策的有效性
|
"""验证决策的有效性
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
decision: 决策字典
|
decision: 决策字典
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
验证后的决策
|
验证后的决策
|
||||||
"""
|
"""
|
||||||
@@ -439,26 +441,26 @@ class MasterAgentRouter:
|
|||||||
decision["selected_agent_id"] = self._get_default_agent_id()
|
decision["selected_agent_id"] = self._get_default_agent_id()
|
||||||
decision["confidence"] = 0.5
|
decision["confidence"] = 0.5
|
||||||
decision["reasoning"] = "原始选择无效,使用默认 Agent"
|
decision["reasoning"] = "原始选择无效,使用默认 Agent"
|
||||||
|
|
||||||
# 验证 confidence
|
# 验证 confidence
|
||||||
confidence = decision.get("confidence", 0.8)
|
confidence = decision.get("confidence", 0.8)
|
||||||
if not isinstance(confidence, (int, float)) or confidence < 0 or confidence > 1:
|
if not isinstance(confidence, (int, float)) or confidence < 0 or confidence > 1:
|
||||||
decision["confidence"] = 0.8
|
decision["confidence"] = 0.8
|
||||||
|
|
||||||
# 验证协作 agents
|
# 验证协作 agents
|
||||||
if decision.get("need_collaboration"):
|
if decision.get("need_collaboration"):
|
||||||
# 检查是否是问题拆分模式
|
# 检查是否是问题拆分模式
|
||||||
if decision.get("need_decomposition") or decision.get("sub_questions"):
|
if decision.get("need_decomposition") or decision.get("sub_questions"):
|
||||||
# 问题拆分模式
|
# 问题拆分模式
|
||||||
sub_questions = decision.get("sub_questions", [])
|
sub_questions = decision.get("sub_questions", [])
|
||||||
|
|
||||||
# 验证每个子问题
|
# 验证每个子问题
|
||||||
valid_sub_questions = []
|
valid_sub_questions = []
|
||||||
for sub_q in sub_questions:
|
for sub_q in sub_questions:
|
||||||
if isinstance(sub_q, dict):
|
if isinstance(sub_q, dict):
|
||||||
agent_id = sub_q.get("agent_id")
|
agent_id = sub_q.get("agent_id")
|
||||||
question = sub_q.get("question")
|
question = sub_q.get("question")
|
||||||
|
|
||||||
if agent_id in self.sub_agents and question:
|
if agent_id in self.sub_agents and question:
|
||||||
# 确保有必要的字段
|
# 确保有必要的字段
|
||||||
sub_q.setdefault("order", len(valid_sub_questions) + 1)
|
sub_q.setdefault("order", len(valid_sub_questions) + 1)
|
||||||
@@ -475,9 +477,9 @@ class MasterAgentRouter:
|
|||||||
"available_agents": list(self.sub_agents.keys())
|
"available_agents": list(self.sub_agents.keys())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
decision["sub_questions"] = valid_sub_questions
|
decision["sub_questions"] = valid_sub_questions
|
||||||
|
|
||||||
# 如果所有子问题都验证失败,降级处理
|
# 如果所有子问题都验证失败,降级处理
|
||||||
if not valid_sub_questions and sub_questions:
|
if not valid_sub_questions and sub_questions:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
@@ -496,10 +498,10 @@ class MasterAgentRouter:
|
|||||||
first_agent_id = next(iter(self.sub_agents.keys()))
|
first_agent_id = next(iter(self.sub_agents.keys()))
|
||||||
decision["selected_agent_id"] = first_agent_id
|
decision["selected_agent_id"] = first_agent_id
|
||||||
logger.info(f"降级使用默认 Agent: {first_agent_id}")
|
logger.info(f"降级使用默认 Agent: {first_agent_id}")
|
||||||
|
|
||||||
# 设置协作策略为 decomposition
|
# 设置协作策略为 decomposition
|
||||||
decision["collaboration_strategy"] = "decomposition"
|
decision["collaboration_strategy"] = "decomposition"
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"问题拆分决策验证完成",
|
"问题拆分决策验证完成",
|
||||||
extra={
|
extra={
|
||||||
@@ -510,7 +512,7 @@ class MasterAgentRouter:
|
|||||||
else:
|
else:
|
||||||
# 普通协作模式
|
# 普通协作模式
|
||||||
collaboration_agents = decision.get("collaboration_agents", [])
|
collaboration_agents = decision.get("collaboration_agents", [])
|
||||||
|
|
||||||
# 如果是简单列表格式,转换为详细格式
|
# 如果是简单列表格式,转换为详细格式
|
||||||
if collaboration_agents and isinstance(collaboration_agents[0], str):
|
if collaboration_agents and isinstance(collaboration_agents[0], str):
|
||||||
collaboration_agents = [
|
collaboration_agents = [
|
||||||
@@ -522,7 +524,7 @@ class MasterAgentRouter:
|
|||||||
}
|
}
|
||||||
for i, agent_id in enumerate(collaboration_agents)
|
for i, agent_id in enumerate(collaboration_agents)
|
||||||
]
|
]
|
||||||
|
|
||||||
# 验证每个协作 agent
|
# 验证每个协作 agent
|
||||||
valid_agents = []
|
valid_agents = []
|
||||||
for agent_info in collaboration_agents:
|
for agent_info in collaboration_agents:
|
||||||
@@ -541,13 +543,13 @@ class MasterAgentRouter:
|
|||||||
"task": "协作处理",
|
"task": "协作处理",
|
||||||
"order": len(valid_agents) + 1
|
"order": len(valid_agents) + 1
|
||||||
})
|
})
|
||||||
|
|
||||||
decision["collaboration_agents"] = valid_agents
|
decision["collaboration_agents"] = valid_agents
|
||||||
|
|
||||||
# 设置默认协作策略
|
# 设置默认协作策略
|
||||||
if not decision.get("collaboration_strategy"):
|
if not decision.get("collaboration_strategy"):
|
||||||
decision["collaboration_strategy"] = "sequential"
|
decision["collaboration_strategy"] = "sequential"
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"协作决策验证完成",
|
"协作决策验证完成",
|
||||||
extra={
|
extra={
|
||||||
@@ -555,20 +557,20 @@ class MasterAgentRouter:
|
|||||||
"strategy": decision.get("collaboration_strategy")
|
"strategy": decision.get("collaboration_strategy")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return decision
|
return decision
|
||||||
|
|
||||||
def _get_fallback_decision(self, message: str) -> Dict[str, Any]:
|
def _get_fallback_decision(self, message: str) -> Dict[str, Any]:
|
||||||
"""获取降级决策(当 Master Agent 失败时)
|
"""获取降级决策(当 Master Agent 失败时)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: 用户消息
|
message: 用户消息
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
降级决策
|
降级决策
|
||||||
"""
|
"""
|
||||||
default_agent_id = self._get_default_agent_id()
|
default_agent_id = self._get_default_agent_id()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"selected_agent_id": default_agent_id,
|
"selected_agent_id": default_agent_id,
|
||||||
"confidence": 0.5,
|
"confidence": 0.5,
|
||||||
@@ -579,15 +581,15 @@ class MasterAgentRouter:
|
|||||||
"collaboration_agents": [],
|
"collaboration_agents": [],
|
||||||
"routing_method": "fallback"
|
"routing_method": "fallback"
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_default_agent_id(self) -> str:
|
def _get_default_agent_id(self) -> str:
|
||||||
"""获取默认 Agent ID
|
"""获取默认 Agent ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
默认 Agent ID
|
默认 Agent ID
|
||||||
"""
|
"""
|
||||||
if self.sub_agents:
|
if self.sub_agents:
|
||||||
# 返回第一个 agent
|
# 返回第一个 agent
|
||||||
return next(iter(self.sub_agents.keys()))
|
return next(iter(self.sub_agents.keys()))
|
||||||
|
|
||||||
return "default-agent"
|
return "default-agent"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,19 @@
|
|||||||
"""多 Agent 配置管理服务"""
|
"""多 Agent 配置管理服务"""
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Optional, List, Tuple, Any
|
from typing import Optional, List, Tuple, Any, Annotated
|
||||||
|
|
||||||
|
from fastapi import Depends
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy import select, desc
|
from sqlalchemy import select, desc
|
||||||
|
|
||||||
|
from app.db import get_db
|
||||||
from app.models import MultiAgentConfig, App, AgentConfig
|
from app.models import MultiAgentConfig, App, AgentConfig
|
||||||
from app.schemas.multi_agent_schema import (
|
from app.schemas.multi_agent_schema import (
|
||||||
MultiAgentConfigCreate,
|
MultiAgentConfigCreate,
|
||||||
MultiAgentConfigUpdate,
|
MultiAgentConfigUpdate,
|
||||||
MultiAgentRunRequest
|
MultiAgentRunRequest
|
||||||
)
|
)
|
||||||
|
from app.services.model_service import ModelApiKeyService
|
||||||
from app.services.multi_agent_orchestrator import MultiAgentOrchestrator
|
from app.services.multi_agent_orchestrator import MultiAgentOrchestrator
|
||||||
from app.core.exceptions import ResourceNotFoundException, BusinessException
|
from app.core.exceptions import ResourceNotFoundException, BusinessException
|
||||||
from app.core.error_codes import BizCode
|
from app.core.error_codes import BizCode
|
||||||
@@ -21,10 +25,10 @@ logger = get_business_logger()
|
|||||||
|
|
||||||
def convert_uuids_to_str(obj: Any) -> Any:
|
def convert_uuids_to_str(obj: Any) -> Any:
|
||||||
"""递归转换对象中的所有 UUID 为字符串
|
"""递归转换对象中的所有 UUID 为字符串
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
obj: 要转换的对象(dict, list, UUID 等)
|
obj: 要转换的对象(dict, list, UUID 等)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
转换后的对象
|
转换后的对象
|
||||||
"""
|
"""
|
||||||
@@ -40,10 +44,10 @@ def convert_uuids_to_str(obj: Any) -> Any:
|
|||||||
|
|
||||||
class MultiAgentService:
|
class MultiAgentService:
|
||||||
"""多 Agent 配置管理服务"""
|
"""多 Agent 配置管理服务"""
|
||||||
|
|
||||||
def __init__(self, db: Session):
|
def __init__(self, db: Session):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
def create_config(
|
def create_config(
|
||||||
self,
|
self,
|
||||||
app_id: uuid.UUID,
|
app_id: uuid.UUID,
|
||||||
@@ -51,12 +55,12 @@ class MultiAgentService:
|
|||||||
created_by: uuid.UUID
|
created_by: uuid.UUID
|
||||||
) -> MultiAgentConfig:
|
) -> MultiAgentConfig:
|
||||||
"""创建多 Agent 配置
|
"""创建多 Agent 配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
data: 配置数据
|
data: 配置数据
|
||||||
created_by: 创建者 ID
|
created_by: 创建者 ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
多 Agent 配置
|
多 Agent 配置
|
||||||
"""
|
"""
|
||||||
@@ -64,7 +68,7 @@ class MultiAgentService:
|
|||||||
app = self.db.get(App, app_id)
|
app = self.db.get(App, app_id)
|
||||||
if not app:
|
if not app:
|
||||||
raise ResourceNotFoundException("应用", str(app_id))
|
raise ResourceNotFoundException("应用", str(app_id))
|
||||||
|
|
||||||
# 2. 检查是否已有有效配置
|
# 2. 检查是否已有有效配置
|
||||||
existing = self.db.scalars(
|
existing = self.db.scalars(
|
||||||
select(MultiAgentConfig)
|
select(MultiAgentConfig)
|
||||||
@@ -76,22 +80,22 @@ class MultiAgentService:
|
|||||||
).first()
|
).first()
|
||||||
if existing:
|
if existing:
|
||||||
raise BusinessException("应用已有多 Agent 配置", BizCode.DUPLICATE_RESOURCE)
|
raise BusinessException("应用已有多 Agent 配置", BizCode.DUPLICATE_RESOURCE)
|
||||||
|
|
||||||
# 3. 验证主 Agent 存在
|
# 3. 验证主 Agent 存在
|
||||||
master_agent = self.db.get(AgentConfig, data.master_agent_id)
|
master_agent = self.db.get(AgentConfig, data.master_agent_id)
|
||||||
if not master_agent:
|
if not master_agent:
|
||||||
raise ResourceNotFoundException("主 Agent", str(data.master_agent_id))
|
raise ResourceNotFoundException("主 Agent", str(data.master_agent_id))
|
||||||
|
|
||||||
# 4. 验证子 Agent 存在
|
# 4. 验证子 Agent 存在
|
||||||
for sub_agent in data.sub_agents:
|
for sub_agent in data.sub_agents:
|
||||||
agent = self.db.get(AgentConfig, sub_agent.agent_id)
|
agent = self.db.get(AgentConfig, sub_agent.agent_id)
|
||||||
if not agent:
|
if not agent:
|
||||||
raise ResourceNotFoundException("子 Agent", str(sub_agent.agent_id))
|
raise ResourceNotFoundException("子 Agent", str(sub_agent.agent_id))
|
||||||
|
|
||||||
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
|
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
|
||||||
sub_agents_data = [convert_uuids_to_str(sub_agent.model_dump()) for sub_agent in data.sub_agents]
|
sub_agents_data = [convert_uuids_to_str(sub_agent.model_dump()) for sub_agent in data.sub_agents]
|
||||||
routing_rules_data = [convert_uuids_to_str(rule.model_dump()) for rule in data.routing_rules] if data.routing_rules else None
|
routing_rules_data = [convert_uuids_to_str(rule.model_dump()) for rule in data.routing_rules] if data.routing_rules else None
|
||||||
|
|
||||||
# 处理 execution_config(可能是 None、字典或 Pydantic 模型)
|
# 处理 execution_config(可能是 None、字典或 Pydantic 模型)
|
||||||
if data.execution_config is None:
|
if data.execution_config is None:
|
||||||
execution_config_data = {}
|
execution_config_data = {}
|
||||||
@@ -99,7 +103,7 @@ class MultiAgentService:
|
|||||||
execution_config_data = convert_uuids_to_str(data.execution_config)
|
execution_config_data = convert_uuids_to_str(data.execution_config)
|
||||||
else:
|
else:
|
||||||
execution_config_data = convert_uuids_to_str(data.execution_config.model_dump())
|
execution_config_data = convert_uuids_to_str(data.execution_config.model_dump())
|
||||||
|
|
||||||
config = MultiAgentConfig(
|
config = MultiAgentConfig(
|
||||||
app_id=app_id,
|
app_id=app_id,
|
||||||
master_agent_id=data.master_agent_id,
|
master_agent_id=data.master_agent_id,
|
||||||
@@ -110,11 +114,11 @@ class MultiAgentService:
|
|||||||
execution_config=execution_config_data,
|
execution_config=execution_config_data,
|
||||||
aggregation_strategy=data.aggregation_strategy
|
aggregation_strategy=data.aggregation_strategy
|
||||||
)
|
)
|
||||||
|
|
||||||
self.db.add(config)
|
self.db.add(config)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.db.refresh(config)
|
self.db.refresh(config)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"创建多 Agent 配置成功",
|
"创建多 Agent 配置成功",
|
||||||
extra={
|
extra={
|
||||||
@@ -124,15 +128,15 @@ class MultiAgentService:
|
|||||||
"sub_agent_count": len(data.sub_agents)
|
"sub_agent_count": len(data.sub_agents)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def get_config(self, app_id: uuid.UUID) -> Optional[MultiAgentConfig]:
|
def get_config(self, app_id: uuid.UUID) -> Optional[MultiAgentConfig]:
|
||||||
"""获取多 Agent 配置
|
"""获取多 Agent 配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
多 Agent 配置,如果不存在返回 None
|
多 Agent 配置,如果不存在返回 None
|
||||||
"""
|
"""
|
||||||
@@ -144,24 +148,25 @@ class MultiAgentService:
|
|||||||
)
|
)
|
||||||
.order_by(MultiAgentConfig.updated_at.desc())
|
.order_by(MultiAgentConfig.updated_at.desc())
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
def get_multi_agent_configs(self, app_id: uuid.UUID) -> Optional[dict]:
|
def get_multi_agent_configs(self, app_id: uuid.UUID) -> Optional[dict]:
|
||||||
"""通过 app_id 获取最新有效的多智能体配置,并将 agent_id 转换为 app_id
|
"""通过 app_id 获取最新有效的多智能体配置,并将 agent_id 转换为 app_id
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
转换后的配置字典,如果不存在返回 None
|
转换后的配置字典,如果不存在返回 None
|
||||||
"""
|
"""
|
||||||
config = self.get_config(app_id)
|
config = self.get_config(app_id)
|
||||||
if not config:
|
if not config:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 转换 master_agent_id (release_id) 为 app_id
|
#兼容代码
|
||||||
master_release = self.db.get(AppRelease, config.master_agent_id)
|
if not config.default_model_config_id:
|
||||||
master_app_id = master_release.app_id if master_release else config.master_agent_id
|
master_release = self.db.get(AppRelease, config.master_agent_id)
|
||||||
|
config.default_model_config_id = master_release.default_model_config_id if master_release else None
|
||||||
|
|
||||||
# 转换 sub_agents 中的 agent_id (release_id) 为 app_id
|
# 转换 sub_agents 中的 agent_id (release_id) 为 app_id
|
||||||
converted_sub_agents = []
|
converted_sub_agents = []
|
||||||
for sub_agent in config.sub_agents:
|
for sub_agent in config.sub_agents:
|
||||||
@@ -176,13 +181,13 @@ class MultiAgentService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"转换 sub_agent agent_id 失败: {release_id}, 错误: {str(e)}")
|
logger.warning(f"转换 sub_agent agent_id 失败: {release_id}, 错误: {str(e)}")
|
||||||
converted_sub_agents.append(sub_agent_copy)
|
converted_sub_agents.append(sub_agent_copy)
|
||||||
|
|
||||||
# 构建返回的配置字典
|
# 构建返回的配置字典
|
||||||
return {
|
return {
|
||||||
"id": config.id,
|
"id": config.id,
|
||||||
"app_id": config.app_id,
|
"app_id": config.app_id,
|
||||||
"master_agent_id": master_app_id,
|
"default_model_config_id": config.default_model_config_id,
|
||||||
"master_agent_name": config.master_agent_name,
|
"model_parameters": config.model_parameters,
|
||||||
"orchestration_mode": config.orchestration_mode,
|
"orchestration_mode": config.orchestration_mode,
|
||||||
"sub_agents": converted_sub_agents,
|
"sub_agents": converted_sub_agents,
|
||||||
"routing_rules": config.routing_rules,
|
"routing_rules": config.routing_rules,
|
||||||
@@ -192,133 +197,134 @@ class MultiAgentService:
|
|||||||
"created_at": config.created_at,
|
"created_at": config.created_at,
|
||||||
"updated_at": config.updated_at
|
"updated_at": config.updated_at
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_published_config_by_agent_id(self, agent_id: uuid.UUID) -> Optional[dict]:
|
def get_published_config_by_agent_id(self, agent_id: uuid.UUID) -> Optional[dict]:
|
||||||
"""通过 agent_id 获取当前发布版本的完整配置
|
"""通过 agent_id 获取当前发布版本的完整配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
agent_id: Agent 配置 ID
|
agent_id: Agent 配置 ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
当前发布版本的配置字典,如果没有发布版本则返回 None
|
当前发布版本的配置字典,如果没有发布版本则返回 None
|
||||||
"""
|
"""
|
||||||
from app.models import AppRelease
|
from app.models import AppRelease
|
||||||
|
|
||||||
# 查询 Agent 配置
|
# 查询 Agent 配置
|
||||||
agent_config = self.db.get(AgentConfig, agent_id)
|
agent_config = self.db.get(AgentConfig, agent_id)
|
||||||
if not agent_config:
|
if not agent_config:
|
||||||
logger.warning(f"Agent 配置不存在: {agent_id}")
|
logger.warning(f"Agent 配置不存在: {agent_id}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 获取关联的应用
|
# 获取关联的应用
|
||||||
app = self.db.get(App, agent_config.app_id)
|
app = self.db.get(App, agent_config.app_id)
|
||||||
if not app or not app.current_release_id:
|
if not app or not app.current_release_id:
|
||||||
logger.warning(f"应用未发布或不存在: app_id={agent_config.app_id}")
|
logger.warning(f"应用未发布或不存在: app_id={agent_config.app_id}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 获取当前发布版本
|
# 获取当前发布版本
|
||||||
release = self.db.get(AppRelease, app.current_release_id)
|
release = self.db.get(AppRelease, app.current_release_id)
|
||||||
if not release:
|
if not release:
|
||||||
logger.warning(f"发布版本不存在: release_id={app.current_release_id}")
|
logger.warning(f"发布版本不存在: release_id={app.current_release_id}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 从发布版本的 config 中获取完整配置
|
# 从发布版本的 config 中获取完整配置
|
||||||
# config 是一个 JSON 对象,包含了发布时的配置快照
|
# config 是一个 JSON 对象,包含了发布时的配置快照
|
||||||
config_data = release.config
|
config_data = release.config
|
||||||
if config_data and isinstance(config_data, dict):
|
if config_data and isinstance(config_data, dict):
|
||||||
return config_data
|
return config_data
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_published_by_agent_id(self, agent_id: uuid.UUID) -> Optional[AppRelease]:
|
def get_published_by_agent_id(self, agent_id: uuid.UUID) -> Optional[AppRelease]:
|
||||||
"""通过 agent_id 获取当前发布版本的完整配置
|
"""通过 agent_id 获取当前发布版本的完整配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
agent_id: Agent 配置 ID
|
agent_id: Agent 配置 ID
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
当前发布版本的配置字典,如果没有发布版本则返回 None
|
当前发布版本的配置字典,如果没有发布版本则返回 None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 获取关联的应用
|
# 获取关联的应用
|
||||||
app = self.db.get(App, agent_id)
|
app = self.db.get(App, agent_id)
|
||||||
if not app or not app.current_release_id:
|
if not app or not app.current_release_id:
|
||||||
logger.warning(f"应用未发布或不存在: app_id={agent_id}")
|
logger.warning(f"应用未发布或不存在: app_id={agent_id}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 获取当前发布版本
|
# 获取当前发布版本
|
||||||
release = self.db.get(AppRelease, app.current_release_id)
|
release = self.db.get(AppRelease, app.current_release_id)
|
||||||
if not release:
|
if not release:
|
||||||
logger.warning(f"发布版本不存在: release_id={app.current_release_id}")
|
logger.warning(f"发布版本不存在: release_id={app.current_release_id}")
|
||||||
return None
|
return None
|
||||||
return release
|
return release
|
||||||
|
|
||||||
def update_config(
|
|
||||||
self,
|
|
||||||
app_id: uuid.UUID,
|
|
||||||
data: MultiAgentConfigUpdate
|
|
||||||
) -> MultiAgentConfig:
|
|
||||||
"""更新多 Agent 配置
|
|
||||||
|
|
||||||
Args:
|
|
||||||
app_id: 应用 ID
|
|
||||||
data: 更新数据
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
更新后的配置
|
|
||||||
"""
|
|
||||||
config = self.get_config(app_id)
|
|
||||||
if not config:
|
|
||||||
# 1. 验证应用存在
|
|
||||||
app = self.db.get(App, app_id)
|
|
||||||
if not app:
|
|
||||||
raise ResourceNotFoundException("应用", str(app_id))
|
|
||||||
|
|
||||||
# 2. 验证主 Agent 存在并获取发布版本 ID
|
|
||||||
master_app_release = self.get_published_by_agent_id(data.master_agent_id)
|
|
||||||
if not master_app_release:
|
|
||||||
raise ResourceNotFoundException("主 Agent 未发布或不存在", str(data.master_agent_id))
|
|
||||||
|
|
||||||
# 使用发布版本 ID
|
|
||||||
data.master_agent_id = master_app_release.id
|
|
||||||
|
|
||||||
# 3. 验证子 Agent 存在并获取发布版本 ID
|
def check_config_data(self,app_id: uuid.UUID, data: MultiAgentConfigUpdate) -> MultiAgentConfig:
|
||||||
for sub_agent in data.sub_agents:
|
# 1. 验证应用存在
|
||||||
agent_app_release = self.get_published_by_agent_id(sub_agent.agent_id)
|
app = self.db.get(App, app_id)
|
||||||
if not agent_app_release:
|
if not app:
|
||||||
raise ResourceNotFoundException("子 Agent 未发布或不存在", str(sub_agent.agent_id))
|
raise ResourceNotFoundException("应用", str(app_id))
|
||||||
|
|
||||||
|
# 2. 验证模型配置
|
||||||
|
model_api_key = ModelApiKeyService.get_a_api_key(self.db,data.default_model_config_id)
|
||||||
|
if not model_api_key:
|
||||||
|
raise ResourceNotFoundException("模型配置", str(data.default_model_config_id))
|
||||||
|
|
||||||
|
# 3. 验证子 Agent 存在并获取发布版本 ID
|
||||||
|
for sub_agent in data.sub_agents:
|
||||||
|
agent_app_release = self.get_published_by_agent_id(sub_agent.agent_id)
|
||||||
|
if not agent_app_release:
|
||||||
|
raise ResourceNotFoundException("子 Agent 未发布或不存在", str(sub_agent.agent_id))
|
||||||
|
|
||||||
# 使用发布版本 ID
|
# 使用发布版本 ID
|
||||||
sub_agent.agent_id = agent_app_release.id
|
sub_agent.agent_id = agent_app_release.id
|
||||||
|
|
||||||
|
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
|
||||||
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
|
sub_agents_data = [convert_uuids_to_str(sub_agent.model_dump()) for sub_agent in data.sub_agents]
|
||||||
sub_agents_data = [convert_uuids_to_str(sub_agent.model_dump()) for sub_agent in data.sub_agents]
|
# routing_rules_data = [convert_uuids_to_str(rule.model_dump()) for rule in data.routing_rules] if data.routing_rules else None
|
||||||
# routing_rules_data = [convert_uuids_to_str(rule.model_dump()) for rule in data.routing_rules] if data.routing_rules else None
|
|
||||||
|
# 处理 execution_config(可能是 None、字典或 Pydantic 模型)
|
||||||
# 处理 execution_config(可能是 None、字典或 Pydantic 模型)
|
if data.execution_config is None:
|
||||||
if data.execution_config is None:
|
execution_config_data = {}
|
||||||
execution_config_data = {}
|
elif isinstance(data.execution_config, dict):
|
||||||
elif isinstance(data.execution_config, dict):
|
|
||||||
execution_config_data = convert_uuids_to_str(data.execution_config)
|
execution_config_data = convert_uuids_to_str(data.execution_config)
|
||||||
else:
|
else:
|
||||||
execution_config_data = convert_uuids_to_str(data.execution_config.model_dump())
|
execution_config_data = convert_uuids_to_str(data.execution_config.model_dump())
|
||||||
|
|
||||||
config = MultiAgentConfig(
|
config = MultiAgentConfig(
|
||||||
app_id=app_id,
|
app_id=app_id,
|
||||||
master_agent_id=data.master_agent_id,
|
master_agent_id=data.master_agent_id,
|
||||||
master_agent_name=data.master_agent_name,
|
master_agent_name=data.master_agent_name,
|
||||||
|
default_model_config_id=data.default_model_config_id,
|
||||||
|
model_parameters=data.model_parameters,
|
||||||
orchestration_mode=data.orchestration_mode,
|
orchestration_mode=data.orchestration_mode,
|
||||||
sub_agents=sub_agents_data,
|
sub_agents=sub_agents_data,
|
||||||
# routing_rules=routing_rules_data,
|
# routing_rules=routing_rules_data,
|
||||||
execution_config=execution_config_data,
|
execution_config=execution_config_data,
|
||||||
aggregation_strategy=data.aggregation_strategy
|
aggregation_strategy=data.aggregation_strategy
|
||||||
)
|
)
|
||||||
|
return config
|
||||||
|
|
||||||
|
def update_config(
|
||||||
|
self,
|
||||||
|
app_id: uuid.UUID,
|
||||||
|
data: MultiAgentConfigUpdate
|
||||||
|
) -> MultiAgentConfig:
|
||||||
|
"""更新多 Agent 配置
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app_id: 应用 ID
|
||||||
|
data: 更新数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
更新后的配置
|
||||||
|
"""
|
||||||
|
config = self.get_config(app_id)
|
||||||
|
newConfig = self.check_config_data(app_id, data)
|
||||||
|
if not config:
|
||||||
|
config = newConfig
|
||||||
self.db.add(config)
|
self.db.add(config)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.db.refresh(config)
|
self.db.refresh(config)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"创建多 Agent 配置成功",
|
"创建多 Agent 配置成功",
|
||||||
extra={
|
extra={
|
||||||
@@ -329,56 +335,17 @@ class MultiAgentService:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return config
|
return config
|
||||||
# raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
|
||||||
|
|
||||||
# 更新字段
|
|
||||||
if data.master_agent_id is not None:
|
|
||||||
# 验证主 Agent 存在
|
|
||||||
# 3. 验证主 Agent 存在并获取发布配置
|
|
||||||
master_app_release = self.get_published_by_agent_id(data.master_agent_id)
|
|
||||||
if not master_app_release:
|
|
||||||
raise ResourceNotFoundException("主 Agent 未发布或", str(data.master_agent_id))
|
|
||||||
|
|
||||||
config.master_agent_id = master_app_release.id
|
config.default_model_config_id = newConfig.default_model_config_id
|
||||||
|
config.model_parameters = newConfig.model_parameters
|
||||||
if data.master_agent_name is not None:
|
config.orchestration_mode = newConfig.orchestration_mode
|
||||||
config.master_agent_name = data.master_agent_name
|
config.sub_agents = newConfig.sub_agents
|
||||||
|
config.routing_rules = newConfig.routing_rules
|
||||||
if data.orchestration_mode is not None:
|
config.execution_config = newConfig.execution_config
|
||||||
config.orchestration_mode = data.orchestration_mode
|
config.aggregation_strategy = newConfig.aggregation_strategy
|
||||||
|
|
||||||
if data.sub_agents is not None:
|
|
||||||
# 验证子 Agent 存在,并获取其发布的 config_id
|
|
||||||
updated_sub_agents = []
|
|
||||||
for sub_agent in data.sub_agents:
|
|
||||||
agent_app_release = self.get_published_by_agent_id(sub_agent.agent_id)
|
|
||||||
if not agent_app_release:
|
|
||||||
raise ResourceNotFoundException("子 Agent 未发布或", str(sub_agent.agent_id))
|
|
||||||
sub_agent.agent_id = agent_app_release.id
|
|
||||||
sub_agent_dict = convert_uuids_to_str(sub_agent.model_dump())
|
|
||||||
updated_sub_agents.append(sub_agent_dict)
|
|
||||||
|
|
||||||
config.sub_agents = updated_sub_agents
|
|
||||||
|
|
||||||
# if data.routing_rules is not None:
|
|
||||||
# config.routing_rules = [convert_uuids_to_str(rule.model_dump()) for rule in data.routing_rules] if data.routing_rules else None
|
|
||||||
|
|
||||||
if data.execution_config is not None:
|
|
||||||
if isinstance(data.execution_config, dict):
|
|
||||||
execution_config_data = convert_uuids_to_str(data.execution_config)
|
|
||||||
else:
|
|
||||||
execution_config_data = convert_uuids_to_str(data.execution_config.model_dump())
|
|
||||||
config.execution_config = execution_config_data
|
|
||||||
|
|
||||||
if data.aggregation_strategy is not None:
|
|
||||||
config.aggregation_strategy = data.aggregation_strategy
|
|
||||||
|
|
||||||
if data.is_active is not None:
|
|
||||||
config.is_active = data.is_active
|
|
||||||
|
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.db.refresh(config)
|
self.db.refresh(config)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"更新多 Agent 配置成功",
|
"更新多 Agent 配置成功",
|
||||||
extra={
|
extra={
|
||||||
@@ -386,23 +353,23 @@ class MultiAgentService:
|
|||||||
"app_id": str(app_id)
|
"app_id": str(app_id)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def delete_config(self, app_id: uuid.UUID) -> None:
|
def delete_config(self, app_id: uuid.UUID) -> None:
|
||||||
"""删除多 Agent 配置
|
"""删除多 Agent 配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
"""
|
"""
|
||||||
config = self.get_config(app_id)
|
config = self.get_config(app_id)
|
||||||
if not config:
|
if not config:
|
||||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||||
|
|
||||||
# 逻辑删除多 Agent 配置
|
# 逻辑删除多 Agent 配置
|
||||||
config.is_active = False
|
config.is_active = False
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"删除多 Agent 配置成功",
|
"删除多 Agent 配置成功",
|
||||||
extra={
|
extra={
|
||||||
@@ -410,18 +377,18 @@ class MultiAgentService:
|
|||||||
"app_id": str(app_id)
|
"app_id": str(app_id)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def run(
|
async def run(
|
||||||
self,
|
self,
|
||||||
app_id: uuid.UUID,
|
app_id: uuid.UUID,
|
||||||
request: MultiAgentRunRequest
|
request: MultiAgentRunRequest
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""运行多 Agent 任务
|
"""运行多 Agent 任务
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
request: 运行请求
|
request: 运行请求
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
执行结果
|
执行结果
|
||||||
"""
|
"""
|
||||||
@@ -429,13 +396,13 @@ class MultiAgentService:
|
|||||||
config = self.get_config(app_id)
|
config = self.get_config(app_id)
|
||||||
if not config:
|
if not config:
|
||||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||||
|
|
||||||
if not config.is_active:
|
if not config.is_active:
|
||||||
raise BusinessException("多 Agent 配置已禁用", BizCode.RESOURCE_DISABLED)
|
raise BusinessException("多 Agent 配置已禁用", BizCode.RESOURCE_DISABLED)
|
||||||
|
|
||||||
# 2. 创建编排器
|
# 2. 创建编排器
|
||||||
orchestrator = MultiAgentOrchestrator(self.db, config)
|
orchestrator = MultiAgentOrchestrator(self.db, config)
|
||||||
|
|
||||||
# 3. 执行任务
|
# 3. 执行任务
|
||||||
result = await orchestrator.execute(
|
result = await orchestrator.execute(
|
||||||
message=request.message,
|
message=request.message,
|
||||||
@@ -446,9 +413,9 @@ class MultiAgentService:
|
|||||||
web_search=getattr(request, 'web_search', False), # 网络搜索参数
|
web_search=getattr(request, 'web_search', False), # 网络搜索参数
|
||||||
memory=getattr(request, 'memory', True) # 记忆功能参数
|
memory=getattr(request, 'memory', True) # 记忆功能参数
|
||||||
)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def run_stream(
|
async def run_stream(
|
||||||
self,
|
self,
|
||||||
app_id: uuid.UUID,
|
app_id: uuid.UUID,
|
||||||
@@ -457,11 +424,11 @@ class MultiAgentService:
|
|||||||
user_rag_memory_id :str
|
user_rag_memory_id :str
|
||||||
):
|
):
|
||||||
"""运行多 Agent 任务(流式返回)
|
"""运行多 Agent 任务(流式返回)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app_id: 应用 ID
|
app_id: 应用 ID
|
||||||
request: 运行请求
|
request: 运行请求
|
||||||
|
|
||||||
Yields:
|
Yields:
|
||||||
SSE 格式的事件流
|
SSE 格式的事件流
|
||||||
"""
|
"""
|
||||||
@@ -469,13 +436,13 @@ class MultiAgentService:
|
|||||||
config = self.get_config(app_id)
|
config = self.get_config(app_id)
|
||||||
if not config:
|
if not config:
|
||||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||||
|
|
||||||
if not config.is_active:
|
if not config.is_active:
|
||||||
raise BusinessException("多 Agent 配置已禁用", BizCode.RESOURCE_DISABLED)
|
raise BusinessException("多 Agent 配置已禁用", BizCode.RESOURCE_DISABLED)
|
||||||
|
|
||||||
# 2. 创建编排器
|
# 2. 创建编排器
|
||||||
orchestrator = MultiAgentOrchestrator(self.db, config)
|
orchestrator = MultiAgentOrchestrator(self.db, config)
|
||||||
|
|
||||||
# 3. 流式执行任务
|
# 3. 流式执行任务
|
||||||
async for event in orchestrator.execute_stream(
|
async for event in orchestrator.execute_stream(
|
||||||
message=request.message,
|
message=request.message,
|
||||||
@@ -489,113 +456,113 @@ class MultiAgentService:
|
|||||||
user_rag_memory_id=user_rag_memory_id
|
user_rag_memory_id=user_rag_memory_id
|
||||||
):
|
):
|
||||||
yield event
|
yield event
|
||||||
|
|
||||||
def add_sub_agent(
|
# def add_sub_agent(
|
||||||
self,
|
# self,
|
||||||
app_id: uuid.UUID,
|
# app_id: uuid.UUID,
|
||||||
agent_id: uuid.UUID,
|
# agent_id: uuid.UUID,
|
||||||
name: str,
|
# name: str,
|
||||||
role: Optional[str] = None,
|
# role: Optional[str] = None,
|
||||||
priority: int = 1,
|
# priority: int = 1,
|
||||||
capabilities: Optional[List[str]] = None
|
# capabilities: Optional[List[str]] = None
|
||||||
) -> MultiAgentConfig:
|
# ) -> MultiAgentConfig:
|
||||||
"""添加子 Agent
|
# """添加子 Agent
|
||||||
|
|
||||||
Args:
|
# Args:
|
||||||
app_id: 应用 ID
|
# app_id: 应用 ID
|
||||||
agent_id: Agent ID
|
# agent_id: Agent ID
|
||||||
name: Agent 名称
|
# name: Agent 名称
|
||||||
role: 角色描述
|
# role: 角色描述
|
||||||
priority: 优先级
|
# priority: 优先级
|
||||||
capabilities: 能力列表
|
# capabilities: 能力列表
|
||||||
|
|
||||||
Returns:
|
# Returns:
|
||||||
更新后的配置
|
# 更新后的配置
|
||||||
"""
|
# """
|
||||||
config = self.get_config(app_id)
|
# config = self.get_config(app_id)
|
||||||
if not config:
|
# if not config:
|
||||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
# raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||||
|
|
||||||
# 验证 Agent 存在
|
# # 验证 Agent 存在
|
||||||
agent = self.db.get(AgentConfig, agent_id)
|
# agent = self.db.get(AgentConfig, agent_id)
|
||||||
if not agent:
|
# if not agent:
|
||||||
raise ResourceNotFoundException("Agent", str(agent_id))
|
# raise ResourceNotFoundException("Agent", str(agent_id))
|
||||||
|
|
||||||
# 检查是否已存在
|
# # 检查是否已存在
|
||||||
for sub_agent in config.sub_agents:
|
# for sub_agent in config.sub_agents:
|
||||||
if sub_agent["agent_id"] == str(agent_id):
|
# if sub_agent["agent_id"] == str(agent_id):
|
||||||
raise BusinessException("Agent 已存在于配置中", BizCode.DUPLICATE_RESOURCE)
|
# raise BusinessException("Agent 已存在于配置中", BizCode.DUPLICATE_RESOURCE)
|
||||||
|
|
||||||
# 添加子 Agent
|
# # 添加子 Agent
|
||||||
new_sub_agent = {
|
# new_sub_agent = {
|
||||||
"agent_id": str(agent_id),
|
# "agent_id": str(agent_id),
|
||||||
"name": name,
|
# "name": name,
|
||||||
"role": role,
|
# "role": role,
|
||||||
"priority": priority,
|
# "priority": priority,
|
||||||
"capabilities": capabilities or []
|
# "capabilities": capabilities or []
|
||||||
}
|
# }
|
||||||
|
|
||||||
config.sub_agents.append(new_sub_agent)
|
# config.sub_agents.append(new_sub_agent)
|
||||||
|
|
||||||
# 标记为已修改
|
# # 标记为已修改
|
||||||
self.db.add(config)
|
# self.db.add(config)
|
||||||
self.db.commit()
|
# self.db.commit()
|
||||||
self.db.refresh(config)
|
# self.db.refresh(config)
|
||||||
|
|
||||||
logger.info(
|
# logger.info(
|
||||||
"添加子 Agent 成功",
|
# "添加子 Agent 成功",
|
||||||
extra={
|
# extra={
|
||||||
"config_id": str(config.id),
|
# "config_id": str(config.id),
|
||||||
"agent_id": str(agent_id),
|
# "agent_id": str(agent_id),
|
||||||
"agent_name": name
|
# "agent_name": name
|
||||||
}
|
# }
|
||||||
)
|
# )
|
||||||
|
|
||||||
return config
|
# return config
|
||||||
|
|
||||||
def remove_sub_agent(
|
# def remove_sub_agent(
|
||||||
self,
|
# self,
|
||||||
app_id: uuid.UUID,
|
# app_id: uuid.UUID,
|
||||||
agent_id: uuid.UUID
|
# agent_id: uuid.UUID
|
||||||
) -> MultiAgentConfig:
|
# ) -> MultiAgentConfig:
|
||||||
"""移除子 Agent
|
# """移除子 Agent
|
||||||
|
|
||||||
Args:
|
# Args:
|
||||||
app_id: 应用 ID
|
# app_id: 应用 ID
|
||||||
agent_id: Agent ID
|
# agent_id: Agent ID
|
||||||
|
|
||||||
Returns:
|
# Returns:
|
||||||
更新后的配置
|
# 更新后的配置
|
||||||
"""
|
# """
|
||||||
config = self.get_config(app_id)
|
# config = self.get_config(app_id)
|
||||||
if not config:
|
# if not config:
|
||||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
# raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||||
|
|
||||||
# 查找并移除
|
# # 查找并移除
|
||||||
original_count = len(config.sub_agents)
|
# original_count = len(config.sub_agents)
|
||||||
config.sub_agents = [
|
# config.sub_agents = [
|
||||||
sub_agent for sub_agent in config.sub_agents
|
# sub_agent for sub_agent in config.sub_agents
|
||||||
if sub_agent["agent_id"] != str(agent_id)
|
# if sub_agent["agent_id"] != str(agent_id)
|
||||||
]
|
# ]
|
||||||
|
|
||||||
if len(config.sub_agents) == original_count:
|
# if len(config.sub_agents) == original_count:
|
||||||
raise ResourceNotFoundException("子 Agent", str(agent_id))
|
# raise ResourceNotFoundException("子 Agent", str(agent_id))
|
||||||
|
|
||||||
# 标记为已修改
|
# # 标记为已修改
|
||||||
self.db.add(config)
|
# self.db.add(config)
|
||||||
self.db.commit()
|
# self.db.commit()
|
||||||
self.db.refresh(config)
|
# self.db.refresh(config)
|
||||||
|
|
||||||
logger.info(
|
# logger.info(
|
||||||
"移除子 Agent 成功",
|
# "移除子 Agent 成功",
|
||||||
extra={
|
# extra={
|
||||||
"config_id": str(config.id),
|
# "config_id": str(config.id),
|
||||||
"agent_id": str(agent_id)
|
# "agent_id": str(agent_id)
|
||||||
}
|
# }
|
||||||
)
|
# )
|
||||||
|
|
||||||
return config
|
# return config
|
||||||
|
|
||||||
def list_configs(
|
def list_configs(
|
||||||
self,
|
self,
|
||||||
workspace_id: uuid.UUID,
|
workspace_id: uuid.UUID,
|
||||||
@@ -603,12 +570,12 @@ class MultiAgentService:
|
|||||||
pagesize: int = 20
|
pagesize: int = 20
|
||||||
) -> Tuple[List[MultiAgentConfig], int]:
|
) -> Tuple[List[MultiAgentConfig], int]:
|
||||||
"""列出多 Agent 配置
|
"""列出多 Agent 配置
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
workspace_id: 工作空间 ID
|
workspace_id: 工作空间 ID
|
||||||
page: 页码
|
page: 页码
|
||||||
pagesize: 每页数量
|
pagesize: 每页数量
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
配置列表和总数
|
配置列表和总数
|
||||||
"""
|
"""
|
||||||
@@ -619,13 +586,21 @@ class MultiAgentService:
|
|||||||
.where(App.workspace_id == workspace_id)
|
.where(App.workspace_id == workspace_id)
|
||||||
.order_by(desc(MultiAgentConfig.created_at))
|
.order_by(desc(MultiAgentConfig.created_at))
|
||||||
)
|
)
|
||||||
|
|
||||||
# 总数
|
# 总数
|
||||||
count_stmt = stmt.with_only_columns(MultiAgentConfig.id)
|
count_stmt = stmt.with_only_columns(MultiAgentConfig.id)
|
||||||
total = len(self.db.execute(count_stmt).all())
|
total = len(self.db.execute(count_stmt).all())
|
||||||
|
|
||||||
# 分页
|
# 分页
|
||||||
stmt = stmt.offset((page - 1) * pagesize).limit(pagesize)
|
stmt = stmt.offset((page - 1) * pagesize).limit(pagesize)
|
||||||
configs = list(self.db.scalars(stmt).all())
|
configs = list(self.db.scalars(stmt).all())
|
||||||
|
|
||||||
return configs, total
|
return configs, total
|
||||||
|
|
||||||
|
# ==================== 依赖注入函数 ====================
|
||||||
|
|
||||||
|
def get_multi_agent_service(
|
||||||
|
db: Annotated[Session, Depends(get_db)]
|
||||||
|
) -> MultiAgentService:
|
||||||
|
"""获取工作流服务(依赖注入)"""
|
||||||
|
return MultiAgentService(db)
|
||||||
|
|||||||
Reference in New Issue
Block a user