[modify] manage multi agent logic

This commit is contained in:
Mark
2025-12-27 13:57:03 +08:00
parent 3bcde42ebb
commit 9edfd6c16f
5 changed files with 1284 additions and 1291 deletions

View File

@@ -1,5 +1,7 @@
"""多 Agent 控制器""" """多 Agent 控制器"""
import uuid import uuid
from typing import Annotated
from fastapi import APIRouter, Depends, Query, Path from fastapi import APIRouter, Depends, Query, Path
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -7,9 +9,9 @@ from app.db import get_db
from app.dependencies import get_current_user from app.dependencies import get_current_user
from app.core.response_utils import success from app.core.response_utils import success
from app.core.logging_config import get_business_logger from app.core.logging_config import get_business_logger
from app.schemas import multi_agent_schema from app.schemas import multi_agent_schema, MultiAgentConfigUpdate, MultiAgentConfigSchema
from app.schemas.response_schema import PageData, PageMeta from app.schemas.response_schema import PageData, PageMeta
from app.services.multi_agent_service import MultiAgentService from app.services.multi_agent_service import MultiAgentService, get_multi_agent_service
from app.models import User from app.models import User
router = APIRouter(prefix="/apps", tags=["Multi-Agent"]) router = APIRouter(prefix="/apps", tags=["Multi-Agent"])
@@ -18,36 +20,35 @@ logger = get_business_logger()
# ==================== 多 Agent 配置管理 ==================== # ==================== 多 Agent 配置管理 ====================
@router.post( # @router.post(
"/{app_id}/multi-agent", # "/{app_id}/multi-agent",
summary="创建多 Agent 配置" # summary="创建多 Agent 配置"
) # )
def create_multi_agent_config( # def create_multi_agent_config(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
data: multi_agent_schema.MultiAgentConfigCreate = ..., # data: multi_agent_schema.MultiAgentConfigCreate = ...,
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""创建多 Agent 配置 # """创建多 Agent 配置
支持四种编排模式: # 支持四种编排模式:
- sequential: 顺序执行 # - sequential: 顺序执行
- parallel: 并行执行 # - parallel: 并行执行
- conditional: 条件路由 # - conditional: 条件路由
- loop: 循环执行 # - loop: 循环执行
""" # """
service = MultiAgentService(db) # service = MultiAgentService(db)
config = service.create_config( # config = service.create_config(
app_id=app_id, # app_id=app_id,
data=data, # data=data,
created_by=current_user.id # created_by=current_user.id
) # )
return success(
data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config),
msg="多 Agent 配置创建成功"
)
# return success(
# data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config),
# msg="多 Agent 配置创建成功"
# )
@router.get( @router.get(
@@ -69,8 +70,8 @@ def get_multi_agent_configs(
# 返回默认模板 # 返回默认模板
default_template = { default_template = {
"app_id": str(app_id), "app_id": str(app_id),
"master_agent_id": None, "default_model_config_id": None,
"master_agent_name": None, "model_parameters": None,
"orchestration_mode": "conditional", "orchestration_mode": "conditional",
"sub_agents": [], "sub_agents": [],
"routing_rules": [], "routing_rules": [],
@@ -96,464 +97,464 @@ def get_multi_agent_configs(
) )
def update_multi_agent_config( def update_multi_agent_config(
app_id: uuid.UUID = Path(..., description="应用 ID"), app_id: uuid.UUID = Path(..., description="应用 ID"),
data: multi_agent_schema.MultiAgentConfigUpdate = ..., data: MultiAgentConfigUpdate = ...,
current_user: User = Depends(get_current_user), current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), db: Session = Depends(get_db),
multi_agent_service: Annotated[MultiAgentService, Depends(get_multi_agent_service)] = None,
): ):
"""更新多 Agent 配置""" """更新多 Agent 配置"""
service = MultiAgentService(db) config = multi_agent_service.update_config(app_id, data)
config = service.update_config(app_id, data) print("="*50)
print(config.default_model_config_id)
return success( return success(
data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config), data=MultiAgentConfigSchema.model_validate(config),
msg="多 Agent 配置更新成功" msg="多 Agent 配置更新成功"
) )
@router.delete( # @router.delete(
"/{app_id}/multi-agent", # "/{app_id}/multi-agent",
summary="删除多 Agent 配置" # summary="删除多 Agent 配置"
) # )
def delete_multi_agent_config( # def delete_multi_agent_config(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""删除多 Agent 配置""" # """删除多 Agent 配置"""
service = MultiAgentService(db) # service = MultiAgentService(db)
service.delete_config(app_id) # service.delete_config(app_id)
return success(msg="多 Agent 配置删除成功") # return success(msg="多 Agent 配置删除成功")
# ==================== 多 Agent 运行 ==================== # ==================== 多 Agent 运行 ====================
@router.post( # @router.post(
"/{app_id}/multi-agent/run", # "/{app_id}/multi-agent/run",
summary="运行多 Agent 任务" # summary="运行多 Agent 任务"
) # )
async def run_multi_agent( # async def run_multi_agent(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
request: multi_agent_schema.MultiAgentRunRequest = ..., # request: multi_agent_schema.MultiAgentRunRequest = ...,
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""运行多 Agent 任务 # """运行多 Agent 任务
根据配置的编排模式执行多个 Agent # 根据配置的编排模式执行多个 Agent
- sequential: 按优先级顺序执行 # - sequential: 按优先级顺序执行
- parallel: 并行执行所有 Agent # - parallel: 并行执行所有 Agent
- conditional: 根据条件选择 Agent # - conditional: 根据条件选择 Agent
- loop: 循环执行直到满足条件 # """
""" # service = MultiAgentService(db)
service = MultiAgentService(db) # result = await service.run(app_id, request)
result = await service.run(app_id, request)
return success( # return success(
data=multi_agent_schema.MultiAgentRunResponse(**result), # data=multi_agent_schema.MultiAgentRunResponse(**result),
msg="多 Agent 任务执行成功" # msg="多 Agent 任务执行成功"
) # )
# ==================== 智能路由测试 ==================== # # ==================== 智能路由测试 ====================
@router.post( # @router.post(
"/{app_id}/multi-agent/test-routing", # "/{app_id}/multi-agent/test-routing",
summary="测试智能路由(支持 Master Agent 模式)" # summary="测试智能路由(支持 Master Agent 模式)"
) # )
async def test_routing( # async def test_routing(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
request: multi_agent_schema.RoutingTestRequest = ..., # request: multi_agent_schema.RoutingTestRequest = ...,
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""测试智能路由功能(重构版 - 支持 Master Agent # """测试智能路由功能(重构版 - 支持 Master Agent
支持三种路由模式: # 支持三种路由模式:
- master_agent: 使用 Master Agent 决策(推荐) # - master_agent: 使用 Master Agent 决策(推荐)
- llm_router: 使用旧 LLM 路由器(向后兼容) # - llm_router: 使用旧 LLM 路由器(向后兼容)
- rule_only: 仅使用规则路由(最快) # - rule_only: 仅使用规则路由(最快)
参数: # 参数:
- message: 测试消息 # - message: 测试消息
- conversation_id: 会话 ID可选 # - conversation_id: 会话 ID可选
- routing_model_id: 路由模型 ID可选 # - routing_model_id: 路由模型 ID可选
- use_llm: 是否启用 LLM默认 False # - use_llm: 是否启用 LLM默认 False
- keyword_threshold: 关键词置信度阈值(默认 0.8 # - keyword_threshold: 关键词置信度阈值(默认 0.8
- force_new: 是否强制重新路由(默认 False # - force_new: 是否强制重新路由(默认 False
""" # """
from app.services.conversation_state_manager import ConversationStateManager # from app.services.conversation_state_manager import ConversationStateManager
from app.services.llm_router import LLMRouter # from app.services.llm_router import LLMRouter
from app.models import ModelConfig # from app.models import ModelConfig
# 1. 获取多 Agent 配置 # # 1. 获取多 Agent 配置
service = MultiAgentService(db) # service = MultiAgentService(db)
config = service.get_config(app_id) # config = service.get_config(app_id)
if not config: # if not config:
return success( # return success(
data=None, # data=None,
msg="应用未配置多 Agent无法测试路由" # msg="应用未配置多 Agent无法测试路由"
) # )
# 2. 准备子 Agent 信息 # # 2. 准备子 Agent 信息
sub_agents = {} # sub_agents = {}
for sub_agent_info in config.sub_agents: # for sub_agent_info in config.sub_agents:
agent_id = sub_agent_info["agent_id"] # agent_id = sub_agent_info["agent_id"]
sub_agents[agent_id] = { # sub_agents[agent_id] = {
"name": sub_agent_info.get("name", agent_id), # "name": sub_agent_info.get("name", agent_id),
"role": sub_agent_info.get("role", "") # "role": sub_agent_info.get("role", "")
} # }
# 3. 获取路由模型(如果指定) # # 3. 获取路由模型(如果指定)
routing_model = None # routing_model = None
if request.routing_model_id: # if request.routing_model_id:
routing_model = db.get(ModelConfig, request.routing_model_id) # routing_model = db.get(ModelConfig, request.routing_model_id)
if not routing_model: # if not routing_model:
return success( # return success(
data=None, # data=None,
msg=f"路由模型不存在: {request.routing_model_id}" # msg=f"路由模型不存在: {request.routing_model_id}"
) # )
# 4. 初始化路由器 # # 4. 初始化路由器
state_manager = ConversationStateManager() # state_manager = ConversationStateManager()
router = LLMRouter( # router = LLMRouter(
db=db, # db=db,
state_manager=state_manager, # state_manager=state_manager,
routing_rules=config.routing_rules or [], # routing_rules=config.routing_rules or [],
sub_agents=sub_agents, # sub_agents=sub_agents,
routing_model_config=routing_model, # routing_model_config=routing_model,
use_llm=request.use_llm and routing_model is not None # use_llm=request.use_llm and routing_model is not None
) # )
# 5. 设置阈值 # # 5. 设置阈值
if request.keyword_threshold: # if request.keyword_threshold:
router.keyword_high_confidence_threshold = request.keyword_threshold # router.keyword_high_confidence_threshold = request.keyword_threshold
# 6. 执行路由 # # 6. 执行路由
try: # try:
routing_result = await router.route( # routing_result = await router.route(
message=request.message, # message=request.message,
conversation_id=str(request.conversation_id) if request.conversation_id else None, # conversation_id=str(request.conversation_id) if request.conversation_id else None,
force_new=request.force_new # force_new=request.force_new
) # )
# 7. 获取 Agent 信息 # # 7. 获取 Agent 信息
agent_id = routing_result["agent_id"] # agent_id = routing_result["agent_id"]
agent_info = sub_agents.get(agent_id, {}) # agent_info = sub_agents.get(agent_id, {})
# 8. 构建响应 # # 8. 构建响应
response_data = { # response_data = {
"message": request.message, # "message": request.message,
"routing_result": { # "routing_result": {
"agent_id": agent_id, # "agent_id": agent_id,
"agent_name": agent_info.get("name", agent_id), # "agent_name": agent_info.get("name", agent_id),
"agent_role": agent_info.get("role", ""), # "agent_role": agent_info.get("role", ""),
"confidence": routing_result["confidence"], # "confidence": routing_result["confidence"],
"strategy": routing_result["strategy"], # "strategy": routing_result["strategy"],
"topic": routing_result["topic"], # "topic": routing_result["topic"],
"topic_changed": routing_result["topic_changed"], # "topic_changed": routing_result["topic_changed"],
"reason": routing_result["reason"], # "reason": routing_result["reason"],
"routing_method": routing_result["routing_method"] # "routing_method": routing_result["routing_method"]
}, # },
"cmulti-agent/batch-test-routingonfig_info": { # "cmulti-agent/batch-test-routingonfig_info": {
"use_llm": request.use_llm and routing_model is not None, # "use_llm": request.use_llm and routing_model is not None,
"routing_model": routing_model.name if routing_model else None, # "routing_model": routing_model.name if routing_model else None,
"keyword_threshold": router.keyword_high_confidence_threshold, # "keyword_threshold": router.keyword_high_confidence_threshold,
"total_sub_agents": len(sub_agents) # "total_sub_agents": len(sub_agents)
} # }
} # }
return success( # return success(
data=response_data, # data=response_data,
msg="路由测试成功" # msg="路由测试成功"
) # )
except Exception as e: # except Exception as e:
logger.error(f"路由测试失败: {str(e)}") # logger.error(f"路由测试失败: {str(e)}")
return success( # return success(
data=None, # data=None,
msg=f"路由测试失败: {str(e)}" # msg=f"路由测试失败: {str(e)}"
) # )
@router.post( # @router.post(
"/{app_id}/multi-agent/test-master-agent", # "/{app_id}/multi-agent/test-master-agent",
summary="测试 Master Agent 决策" # summary="测试 Master Agent 决策"
) # )
async def test_master_agent( # async def test_master_agent(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
request: multi_agent_schema.RoutingTestRequest = ..., # request: multi_agent_schema.RoutingTestRequest = ...,
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""测试 Master Agent 的路由决策能力 # """测试 Master Agent 的路由决策能力
这个接口专门用于测试新的 Master Agent 路由器, # 这个接口专门用于测试新的 Master Agent 路由器,
可以看到 Master Agent 的完整决策过程。 # 可以看到 Master Agent 的完整决策过程。
返回信息包括: # 返回信息包括:
- 选中的 Agent # - 选中的 Agent
- 置信度 # - 置信度
- 决策理由 # - 决策理由
- 是否需要协作 # - 是否需要协作
- 路由策略master_agent / rule_fast_path / fallback # - 路由策略master_agent / rule_fast_path / fallback
""" # """
from app.services.conversation_state_manager import ConversationStateManager # from app.services.conversation_state_manager import ConversationStateManager
from app.services.master_agent_router import MasterAgentRouter # from app.services.master_agent_router import MasterAgentRouter
from app.models import ModelConfig # from app.models import ModelConfig
# 1. 获取多 Agent 配置 # # 1. 获取多 Agent 配置
service = MultiAgentService(db) # service = MultiAgentService(db)
config = service.get_config(app_id) # config = service.get_config(app_id)
if not config: # if not config:
return success( # return success(
data=None, # data=None,
msg="应用未配置多 Agent无法测试" # msg="应用未配置多 Agent无法测试"
) # )
# 2. 加载 Master Agent # # 2. 加载 Master Agent
from app.models import AppRelease, App # from app.models import AppRelease, App
master_release = db.get(AppRelease, config.master_agent_id) # master_release = db.get(AppRelease, config.master_agent_id)
if not master_release: # if not master_release:
return success( # return success(
data=None, # data=None,
msg=f"Master Agent 发布版本不存在: {config.master_agent_id}" # msg=f"Master Agent 发布版本不存在: {config.master_agent_id}"
) # )
# 获取应用信息 # # 获取应用信息
app = db.get(App, master_release.app_id) # app = db.get(App, master_release.app_id)
if not app: # if not app:
return success( # return success(
data=None, # data=None,
msg=f"应用不存在: {master_release.app_id}" # msg=f"应用不存在: {master_release.app_id}"
) # )
# 创建 Master Agent 代理对象 # # 创建 Master Agent 代理对象
class AgentConfigProxy: # class AgentConfigProxy:
def __init__(self, release, app, config_data): # def __init__(self, release, app, config_data):
self.id = release.id # self.id = release.id
self.app_id = release.app_id # self.app_id = release.app_id
self.app = app # self.app = app
self.name = release.name # self.name = release.name
self.description = release.description # self.description = release.description
self.system_prompt = config_data.get("system_prompt") # self.system_prompt = config_data.get("system_prompt")
self.default_model_config_id = release.default_model_config_id # self.default_model_config_id = release.default_model_config_id
config_data = master_release.config or {} # config_data = master_release.config or {}
master_agent_config = AgentConfigProxy(master_release, app, config_data) # master_agent_config = AgentConfigProxy(master_release, app, config_data)
# 3. 获取 Master Agent 的模型配置 # # 3. 获取 Master Agent 的模型配置
master_model_config = db.get(ModelConfig, master_agent_config.default_model_config_id) # master_model_config = db.get(ModelConfig, master_agent_config.default_model_config_id)
if not master_model_config: # if not master_model_config:
return success( # return success(
data=None, # data=None,
msg=f"Master Agent 模型配置不存在: {master_agent_config.default_model_config_id}" # msg=f"Master Agent 模型配置不存在: {master_agent_config.default_model_config_id}"
) # )
# 4. 准备子 Agent 信息 # # 4. 准备子 Agent 信息
sub_agents = {} # sub_agents = {}
for sub_agent_info in config.sub_agents: # for sub_agent_info in config.sub_agents:
agent_id = sub_agent_info["agent_id"] # agent_id = sub_agent_info["agent_id"]
# 加载子 Agent # # 加载子 Agent
sub_release = db.get(AppRelease, uuid.UUID(agent_id)) # sub_release = db.get(AppRelease, uuid.UUID(agent_id))
if sub_release: # if sub_release:
sub_app = db.get(App, sub_release.app_id) # sub_app = db.get(App, sub_release.app_id)
sub_config_data = sub_release.config or {} # sub_config_data = sub_release.config or {}
sub_agent_config = AgentConfigProxy(sub_release, sub_app, sub_config_data) # sub_agent_config = AgentConfigProxy(sub_release, sub_app, sub_config_data)
sub_agents[agent_id] = { # sub_agents[agent_id] = {
"config": sub_agent_config, # "config": sub_agent_config,
"info": sub_agent_info # "info": sub_agent_info
} # }
# 5. 初始化 Master Agent 路由器 # # 5. 初始化 Master Agent 路由器
state_manager = ConversationStateManager() # state_manager = ConversationStateManager()
router = MasterAgentRouter( # router = MasterAgentRouter(
db=db, # db=db,
master_agent_config=master_agent_config, # master_agent_config=master_agent_config,
master_model_config=master_model_config, # master_model_config=master_model_config,
sub_agents=sub_agents, # sub_agents=sub_agents,
state_manager=state_manager, # state_manager=state_manager,
enable_rule_fast_path=True # enable_rule_fast_path=True
) # )
# 6. 执行路由决策 # # 6. 执行路由决策
try: # try:
decision = await router.route( # decision = await router.route(
message=request.message, # message=request.message,
conversation_id=str(request.conversation_id) if request.conversation_id else None, # conversation_id=str(request.conversation_id) if request.conversation_id else None,
variables=None # variables=None
) # )
# 7. 获取选中的 Agent 信息 # # 7. 获取选中的 Agent 信息
agent_id = decision["selected_agent_id"] # agent_id = decision["selected_agent_id"]
agent_info = sub_agents.get(agent_id, {}).get("info", {}) # agent_info = sub_agents.get(agent_id, {}).get("info", {})
# 8. 构建响应 # # 8. 构建响应
response_data = { # response_data = {
"message": request.message, # "message": request.message,
"master_agent": { # "master_agent": {
"name": master_agent_config.name, # "name": master_agent_config.name,
"model": master_model_config.name # "model": master_model_config.name
}, # },
"decision": { # "decision": {
"selected_agent_id": agent_id, # "selected_agent_id": agent_id,
"selected_agent_name": agent_info.get("name", "未知"), # "selected_agent_name": agent_info.get("name", "未知"),
"selected_agent_role": agent_info.get("role", ""), # "selected_agent_role": agent_info.get("role", ""),
"confidence": decision["confidence"], # "confidence": decision["confidence"],
"reasoning": decision.get("reasoning", ""), # "reasoning": decision.get("reasoning", ""),
"topic": decision.get("topic", ""), # "topic": decision.get("topic", ""),
"strategy": decision["strategy"], # "strategy": decision["strategy"],
"routing_method": decision.get("routing_method", ""), # "routing_method": decision.get("routing_method", ""),
"need_collaboration": decision.get("need_collaboration", False), # "need_collaboration": decision.get("need_collaboration", False),
"collaboration_agents": decision.get("collaboration_agents", []) # "collaboration_agents": decision.get("collaboration_agents", [])
}, # },
"config_info": { # "config_info": {
"total_sub_agents": len(sub_agents), # "total_sub_agents": len(sub_agents),
"enable_rule_fast_path": True # "enable_rule_fast_path": True
} # }
} # }
return success( # return success(
data=response_data, # data=response_data,
msg="Master Agent 决策测试成功" # msg="Master Agent 决策测试成功"
) # )
except Exception as e: # except Exception as e:
logger.error(f"Master Agent 决策测试失败: {str(e)}") # logger.error(f"Master Agent 决策测试失败: {str(e)}")
return success( # return success(
data=None, # data=None,
msg=f"测试失败: {str(e)}" # msg=f"测试失败: {str(e)}"
) # )
@router.post( # @router.post(
"/{app_id}/multi-agent/batch-test-routing", # "/{app_id}/multi-agent/batch-test-routing",
summary="批量测试智能路由" # summary="批量测试智能路由"
) # )
async def batch_test_routing( # async def batch_test_routing(
app_id: uuid.UUID = Path(..., description="应用 ID"), # app_id: uuid.UUID = Path(..., description="应用 ID"),
request: multi_agent_schema.BatchRoutingTestRequest = ..., # request: multi_agent_schema.BatchRoutingTestRequest = ...,
current_user: User = Depends(get_current_user), # current_user: User = Depends(get_current_user),
db: Session = Depends(get_db), # db: Session = Depends(get_db),
): # ):
"""批量测试智能路由功能 # """批量测试智能路由功能
用于测试多条消息的路由效果,并统计准确率 # 用于测试多条消息的路由效果,并统计准确率
参数: # 参数:
- test_cases: 测试用例列表 # - test_cases: 测试用例列表
- routing_model_id: 路由模型 ID可选 # - routing_model_id: 路由模型 ID可选
- use_llm: 是否启用 LLM # - use_llm: 是否启用 LLM
- keyword_threshold: 关键词置信度阈值 # - keyword_threshold: 关键词置信度阈值
""" # """
from app.services.conversation_state_manager import ConversationStateManager # from app.services.conversation_state_manager import ConversationStateManager
from app.services.llm_router import LLMRouter # from app.services.llm_router import LLMRouter
from app.models import ModelConfig # from app.models import ModelConfig
# 1. 获取多 Agent 配置 # # 1. 获取多 Agent 配置
service = MultiAgentService(db) # service = MultiAgentService(db)
config = service.get_config(app_id) # config = service.get_config(app_id)
if not config: # if not config:
return success( # return success(
data=None, # data=None,
msg="应用未配置多 Agent无法测试路由" # msg="应用未配置多 Agent无法测试路由"
) # )
# 2. 准备子 Agent 信息 # # 2. 准备子 Agent 信息
sub_agents = {} # sub_agents = {}
for sub_agent_info in config.sub_agents: # for sub_agent_info in config.sub_agents:
agent_id = sub_agent_info["agent_id"] # agent_id = sub_agent_info["agent_id"]
sub_agents[agent_id] = { # sub_agents[agent_id] = {
"name": sub_agent_info.get("name", agent_id), # "name": sub_agent_info.get("name", agent_id),
"role": sub_agent_info.get("role", "") # "role": sub_agent_info.get("role", "")
} # }
# 3. 获取路由模型 # # 3. 获取路由模型
routing_model = None # routing_model = None
if request.routing_model_id: # if request.routing_model_id:
routing_model = db.get(ModelConfig, request.routing_model_id) # routing_model = db.get(ModelConfig, request.routing_model_id)
# 4. 初始化路由器 # # 4. 初始化路由器
state_manager = ConversationStateManager() # state_manager = ConversationStateManager()
router = LLMRouter( # router = LLMRouter(
db=db, # db=db,
state_manager=state_manager, # state_manager=state_manager,
routing_rules=config.routing_rules or [], # routing_rules=config.routing_rules or [],
sub_agents=sub_agents, # sub_agents=sub_agents,
routing_model_config=routing_model, # routing_model_config=routing_model,
use_llm=request.use_llm and routing_model is not None # use_llm=request.use_llm and routing_model is not None
) # )
if request.keyword_threshold: # if request.keyword_threshold:
router.keyword_high_confidence_threshold = request.keyword_threshold # router.keyword_high_confidence_threshold = request.keyword_threshold
# 5. 批量测试 # # 5. 批量测试
results = [] # results = []
correct_count = 0 # correct_count = 0
total_count = len(request.test_cases) # total_count = len(request.test_cases)
for test_case in request.test_cases: # for test_case in request.test_cases:
try: # try:
routing_result = await router.route( # routing_result = await router.route(
message=test_case.message, # message=test_case.message,
conversation_id=str(uuid.uuid4()) # 每个测试用例使用独立会话 # conversation_id=str(uuid.uuid4()) # 每个测试用例使用独立会话
) # )
agent_id = routing_result["agent_id"] # agent_id = routing_result["agent_id"]
agent_info = sub_agents.get(agent_id, {}) # agent_info = sub_agents.get(agent_id, {})
# 判断是否正确 # # 判断是否正确
is_correct = None # is_correct = None
if test_case.expected_agent_id: # if test_case.expected_agent_id:
is_correct = (agent_id == str(test_case.expected_agent_id)) # is_correct = (agent_id == str(test_case.expected_agent_id))
if is_correct: # if is_correct:
correct_count += 1 # correct_count += 1
results.append({ # results.append({
"message": test_case.message, # "message": test_case.message,
"description": test_case.description, # "description": test_case.description,
"routed_agent_id": agent_id, # "routed_agent_id": agent_id,
"routed_agent_name": agent_info.get("name"), # "routed_agent_name": agent_info.get("name"),
"expected_agent_id": str(test_case.expected_agent_id) if test_case.expected_agent_id else None, # "expected_agent_id": str(test_case.expected_agent_id) if test_case.expected_agent_id else None,
"is_correct": is_correct, # "is_correct": is_correct,
"confidence": routing_result["confidence"], # "confidence": routing_result["confidence"],
"routing_method": routing_result["routing_method"], # "routing_method": routing_result["routing_method"],
"strategy": routing_result["strategy"] # "strategy": routing_result["strategy"]
}) # })
except Exception as e: # except Exception as e:
logger.error(f"测试用例失败: {test_case.message}, 错误: {str(e)}") # logger.error(f"测试用例失败: {test_case.message}, 错误: {str(e)}")
results.append({ # results.append({
"message": test_case.message, # "message": test_case.message,
"description": test_case.description, # "description": test_case.description,
"error": str(e) # "error": str(e)
}) # })
# 6. 统计 # # 6. 统计
accuracy = None # accuracy = None
if correct_count > 0: # if correct_count > 0:
total_with_expected = sum(1 for r in results if r.get("expected_agent_id")) # total_with_expected = sum(1 for r in results if r.get("expected_agent_id"))
if total_with_expected > 0: # if total_with_expected > 0:
accuracy = correct_count / total_with_expected * 100 # accuracy = correct_count / total_with_expected * 100
response_data = { # response_data = {
"total_count": total_count, # "total_count": total_count,
"correct_count": correct_count, # "correct_count": correct_count,
"accuracy": accuracy, # "accuracy": accuracy,
"results": results, # "results": results,
"config_info": { # "config_info": {
"use_llm": request.use_llm and routing_model is not None, # "use_llm": request.use_llm and routing_model is not None,
"routing_model": routing_model.name if routing_model else None, # "routing_model": routing_model.name if routing_model else None,
"keyword_threshold": router.keyword_high_confidence_threshold # "keyword_threshold": router.keyword_high_confidence_threshold
} # }
} # }
return success( # return success(
data=response_data, # data=response_data,
msg=f"批量测试完成,准确率: {accuracy:.1f}%" if accuracy else "批量测试完成" # msg=f"批量测试完成,准确率: {accuracy:.1f}%" if accuracy else "批量测试完成"
) # )

View File

@@ -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 配置 ====================
@@ -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)$"
@@ -104,6 +111,11 @@ class MultiAgentConfigSchema(BaseModel):
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]]]

View File

@@ -5,9 +5,11 @@ 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()
@@ -30,8 +32,8 @@ class MasterAgentRouter:
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
@@ -40,15 +42,14 @@ class MasterAgentRouter:
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
@@ -56,7 +57,6 @@ class MasterAgentRouter:
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
} }
@@ -349,10 +349,7 @@ class MasterAgentRouter:
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")
@@ -364,15 +361,20 @@ 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 实例

View File

@@ -6,6 +6,7 @@ from typing import Dict, Any, List, Optional, AsyncIterator, Tuple
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.models import MultiAgentConfig, AgentConfig, ModelConfig from app.models import MultiAgentConfig, AgentConfig, ModelConfig
from app.models.multi_agent_model import AggregationStrategy, OrchestrationMode
from app.services.agent_registry import AgentRegistry from app.services.agent_registry import AgentRegistry
from app.services.master_agent_router import MasterAgentRouter from app.services.master_agent_router import MasterAgentRouter
from app.services.conversation_state_manager import ConversationStateManager from app.services.conversation_state_manager import ConversationStateManager
@@ -31,7 +32,10 @@ class MultiAgentOrchestrator:
self.registry = AgentRegistry(db) self.registry = AgentRegistry(db)
# 加载主 Agent # 加载主 Agent
self.master_agent = self._load_agent(config.master_agent_id) # self.master_agent = self._load_agent(config.master_agent_id)
# self. config.d
self.default_model_config_id = config.default_model_config_id
self.model_parameters = config.model_parameters
# 加载子 Agent # 加载子 Agent
self.sub_agents = {} self.sub_agents = {}
@@ -47,18 +51,18 @@ class MultiAgentOrchestrator:
self.state_manager = ConversationStateManager() self.state_manager = ConversationStateManager()
# 获取 Master Agent 的模型配置 # 获取 Master Agent 的模型配置
if not hasattr(self.master_agent, 'default_model_config_id'): if not self.default_model_config_id:
raise BusinessException("Master Agent 缺少模型配置", BizCode.AGENT_CONFIG_MISSING) raise BusinessException("Master Agent 缺少模型配置", BizCode.AGENT_CONFIG_MISSING)
self.master_model_config = self.db.get(ModelConfig, self.master_agent.default_model_config_id) self.master_model_config = self.db.get(ModelConfig, self.default_model_config_id)
if not self.master_model_config: if not self.master_model_config:
raise BusinessException("Master Agent 模型配置不存在", BizCode.AGENT_CONFIG_MISSING) raise BusinessException("Master Agent 模型配置不存在", BizCode.AGENT_CONFIG_MISSING)
# 初始化 Master Agent 路由器 # 初始化 Master Agent 路由器
self.router = MasterAgentRouter( self.router = MasterAgentRouter(
db=db, db=db,
master_agent_config=self.master_agent,
master_model_config=self.master_model_config, master_model_config=self.master_model_config,
model_parameters=self.model_parameters,
sub_agents=self.sub_agents, sub_agents=self.sub_agents,
state_manager=self.state_manager, state_manager=self.state_manager,
enable_rule_fast_path=config.execution_config.get("enable_rule_fast_path", True) enable_rule_fast_path=config.execution_config.get("enable_rule_fast_path", True)
@@ -68,7 +72,6 @@ class MultiAgentOrchestrator:
"多 Agent 编排器初始化完成", "多 Agent 编排器初始化完成",
extra={ extra={
"config_id": str(config.id), "config_id": str(config.id),
"master_agent": self.master_agent.name,
"model": self.master_model_config.name, "model": self.master_model_config.name,
"sub_agent_count": len(self.sub_agents) "sub_agent_count": len(self.sub_agents)
} }
@@ -122,7 +125,7 @@ class MultiAgentOrchestrator:
task_analysis["use_llm_routing"] = use_llm_routing task_analysis["use_llm_routing"] = use_llm_routing
# 2. 根据模式执行(流式) # 2. 根据模式执行(流式)
if self.config.orchestration_mode == "conditional": if self.config.orchestration_mode == OrchestrationMode.CONDITIONAL:
async for event in self._execute_conditional_stream( async for event in self._execute_conditional_stream(
task_analysis, task_analysis,
conversation_id, conversation_id,
@@ -135,7 +138,7 @@ class MultiAgentOrchestrator:
yield event yield event
else: else:
# 其他模式暂时使用非流式执行,然后一次性返回 # 其他模式暂时使用非流式执行,然后一次性返回
if self.config.orchestration_mode == "sequential": if self.config.orchestration_mode == OrchestrationMode.SEQUENTIAL:
results = await self._execute_sequential( results = await self._execute_sequential(
task_analysis, task_analysis,
conversation_id, conversation_id,
@@ -145,7 +148,7 @@ class MultiAgentOrchestrator:
storage_type, storage_type,
user_rag_memory_id user_rag_memory_id
) )
elif self.config.orchestration_mode == "parallel": elif self.config.orchestration_mode == OrchestrationMode.PARALLEL:
results = await self._execute_parallel( results = await self._execute_parallel(
task_analysis, task_analysis,
conversation_id, conversation_id,
@@ -155,16 +158,16 @@ class MultiAgentOrchestrator:
storage_type, storage_type,
user_rag_memory_id user_rag_memory_id
) )
elif self.config.orchestration_mode == "loop": # elif self.config.orchestration_mode == "loop":
results = await self._execute_loop( # results = await self._execute_loop(
task_analysis, # task_analysis,
conversation_id, # conversation_id,
user_id, # user_id,
web_search, # web_search,
memory, # memory,
storage_type, # storage_type,
user_rag_memory_id # user_rag_memory_id
) # )
else: else:
raise BusinessException( raise BusinessException(
f"不支持的编排模式: {self.config.orchestration_mode}", f"不支持的编排模式: {self.config.orchestration_mode}",
@@ -968,17 +971,17 @@ class MultiAgentOrchestrator:
else: else:
# 2. 降级:使用旧的路由逻辑 # 2. 降级:使用旧的路由逻辑
logger.warning("未获取到 Master Agent 决策,使用旧路由逻辑(流式)") logger.warning("未获取到 Master Agent 决策,使用旧路由逻辑(流式)")
use_llm = task_analysis.get("use_llm_routing", True) # use_llm = task_analysis.get("use_llm_routing", True)
selected_agent_info = await self._route_by_rules( # selected_agent_info = await self._route_by_rules(
message, # message,
task_analysis["sub_agents"], # task_analysis["sub_agents"],
use_llm=use_llm, # use_llm=use_llm,
conversation_id=str(conversation_id) if conversation_id else None # conversation_id=str(conversation_id) if conversation_id else None
) # )
#
if not selected_agent_info: # if not selected_agent_info:
selected_agent_info = task_analysis["sub_agents"][0] selected_agent_info = task_analysis["sub_agents"][0]
logger.info("未匹配到路由规则,使用默认 Agent") logger.info("未匹配到路由规则,使用默认 Agent")
agent_id = selected_agent_info["agent_id"] agent_id = selected_agent_info["agent_id"]
@@ -1334,11 +1337,11 @@ class MultiAgentOrchestrator:
""" """
strategy = self.config.aggregation_strategy strategy = self.config.aggregation_strategy
if strategy == "merge": if strategy == AggregationStrategy.MERGE:
return self._merge_results(results) return self._merge_results(results)
elif strategy == "vote": elif strategy == AggregationStrategy.VOTE:
return self._vote_results(results) return self._vote_results(results)
elif strategy == "priority": elif strategy == AggregationStrategy.PRIORITY:
return self._priority_results(results) return self._priority_results(results)
else: else:
return self._merge_results(results) return self._merge_results(results)

View File

@@ -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
@@ -158,9 +162,10 @@ class MultiAgentService:
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 = []
@@ -181,8 +186,8 @@ class MultiAgentService:
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,
@@ -253,6 +258,52 @@ class MultiAgentService:
return None return None
return release return release
def check_config_data(self,app_id: uuid.UUID, data: MultiAgentConfigUpdate) -> MultiAgentConfig:
# 1. 验证应用存在
app = self.db.get(App, app_id)
if not app:
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
sub_agent.agent_id = agent_app_release.id
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
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
# 处理 execution_config可能是 None、字典或 Pydantic 模型)
if data.execution_config is None:
execution_config_data = {}
elif 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 = MultiAgentConfig(
app_id=app_id,
master_agent_id=data.master_agent_id,
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,
sub_agents=sub_agents_data,
# routing_rules=routing_rules_data,
execution_config=execution_config_data,
aggregation_strategy=data.aggregation_strategy
)
return config
def update_config( def update_config(
self, self,
app_id: uuid.UUID, app_id: uuid.UUID,
@@ -268,57 +319,12 @@ class MultiAgentService:
更新后的配置 更新后的配置
""" """
config = self.get_config(app_id) config = self.get_config(app_id)
newConfig = self.check_config_data(app_id, data)
if not config: if not config:
# 1. 验证应用存在 config = newConfig
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
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
sub_agent.agent_id = agent_app_release.id
# 5. 创建配置(转换 UUID 为字符串以支持 JSON 序列化)
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
# 处理 execution_config可能是 None、字典或 Pydantic 模型)
if data.execution_config is None:
execution_config_data = {}
elif 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 = MultiAgentConfig(
app_id=app_id,
master_agent_id=data.master_agent_id,
master_agent_name=data.master_agent_name,
orchestration_mode=data.orchestration_mode,
sub_agents=sub_agents_data,
# routing_rules=routing_rules_data,
execution_config=execution_config_data,
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={
@@ -329,53 +335,14 @@ 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
if data.master_agent_name is not None:
config.master_agent_name = data.master_agent_name
if data.orchestration_mode is not None:
config.orchestration_mode = data.orchestration_mode
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
config.default_model_config_id = newConfig.default_model_config_id
config.model_parameters = newConfig.model_parameters
config.orchestration_mode = newConfig.orchestration_mode
config.sub_agents = newConfig.sub_agents
config.routing_rules = newConfig.routing_rules
config.execution_config = newConfig.execution_config
config.aggregation_strategy = newConfig.aggregation_strategy
self.db.commit() self.db.commit()
self.db.refresh(config) self.db.refresh(config)
@@ -490,111 +457,111 @@ class MultiAgentService:
): ):
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,
@@ -629,3 +596,11 @@ class MultiAgentService:
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)