[modify] manage multi agent logic
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
"""多 Agent 控制器"""
|
||||
import uuid
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Query, Path
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -7,9 +9,9 @@ from app.db import get_db
|
||||
from app.dependencies import get_current_user
|
||||
from app.core.response_utils import success
|
||||
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.services.multi_agent_service import MultiAgentService
|
||||
from app.services.multi_agent_service import MultiAgentService, get_multi_agent_service
|
||||
from app.models import User
|
||||
|
||||
router = APIRouter(prefix="/apps", tags=["Multi-Agent"])
|
||||
@@ -18,36 +20,35 @@ logger = get_business_logger()
|
||||
|
||||
# ==================== 多 Agent 配置管理 ====================
|
||||
|
||||
@router.post(
|
||||
"/{app_id}/multi-agent",
|
||||
summary="创建多 Agent 配置"
|
||||
)
|
||||
def create_multi_agent_config(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
data: multi_agent_schema.MultiAgentConfigCreate = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""创建多 Agent 配置
|
||||
# @router.post(
|
||||
# "/{app_id}/multi-agent",
|
||||
# summary="创建多 Agent 配置"
|
||||
# )
|
||||
# def create_multi_agent_config(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# data: multi_agent_schema.MultiAgentConfigCreate = ...,
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """创建多 Agent 配置
|
||||
|
||||
支持四种编排模式:
|
||||
- sequential: 顺序执行
|
||||
- parallel: 并行执行
|
||||
- conditional: 条件路由
|
||||
- loop: 循环执行
|
||||
"""
|
||||
service = MultiAgentService(db)
|
||||
config = service.create_config(
|
||||
app_id=app_id,
|
||||
data=data,
|
||||
created_by=current_user.id
|
||||
)
|
||||
|
||||
return success(
|
||||
data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config),
|
||||
msg="多 Agent 配置创建成功"
|
||||
)
|
||||
# 支持四种编排模式:
|
||||
# - sequential: 顺序执行
|
||||
# - parallel: 并行执行
|
||||
# - conditional: 条件路由
|
||||
# - loop: 循环执行
|
||||
# """
|
||||
# service = MultiAgentService(db)
|
||||
# config = service.create_config(
|
||||
# app_id=app_id,
|
||||
# data=data,
|
||||
# created_by=current_user.id
|
||||
# )
|
||||
|
||||
# return success(
|
||||
# data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config),
|
||||
# msg="多 Agent 配置创建成功"
|
||||
# )
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -69,8 +70,8 @@ def get_multi_agent_configs(
|
||||
# 返回默认模板
|
||||
default_template = {
|
||||
"app_id": str(app_id),
|
||||
"master_agent_id": None,
|
||||
"master_agent_name": None,
|
||||
"default_model_config_id": None,
|
||||
"model_parameters": None,
|
||||
"orchestration_mode": "conditional",
|
||||
"sub_agents": [],
|
||||
"routing_rules": [],
|
||||
@@ -96,464 +97,464 @@ def get_multi_agent_configs(
|
||||
)
|
||||
def update_multi_agent_config(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
data: multi_agent_schema.MultiAgentConfigUpdate = ...,
|
||||
data: MultiAgentConfigUpdate = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
multi_agent_service: Annotated[MultiAgentService, Depends(get_multi_agent_service)] = None,
|
||||
):
|
||||
"""更新多 Agent 配置"""
|
||||
service = MultiAgentService(db)
|
||||
config = service.update_config(app_id, data)
|
||||
|
||||
config = multi_agent_service.update_config(app_id, data)
|
||||
print("="*50)
|
||||
print(config.default_model_config_id)
|
||||
return success(
|
||||
data=multi_agent_schema.MultiAgentConfigSchema.model_validate(config),
|
||||
data=MultiAgentConfigSchema.model_validate(config),
|
||||
msg="多 Agent 配置更新成功"
|
||||
)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/{app_id}/multi-agent",
|
||||
summary="删除多 Agent 配置"
|
||||
)
|
||||
def delete_multi_agent_config(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""删除多 Agent 配置"""
|
||||
service = MultiAgentService(db)
|
||||
service.delete_config(app_id)
|
||||
# @router.delete(
|
||||
# "/{app_id}/multi-agent",
|
||||
# summary="删除多 Agent 配置"
|
||||
# )
|
||||
# def delete_multi_agent_config(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """删除多 Agent 配置"""
|
||||
# service = MultiAgentService(db)
|
||||
# service.delete_config(app_id)
|
||||
|
||||
return success(msg="多 Agent 配置删除成功")
|
||||
# return success(msg="多 Agent 配置删除成功")
|
||||
|
||||
# ==================== 多 Agent 运行 ====================
|
||||
|
||||
@router.post(
|
||||
"/{app_id}/multi-agent/run",
|
||||
summary="运行多 Agent 任务"
|
||||
)
|
||||
async def run_multi_agent(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
request: multi_agent_schema.MultiAgentRunRequest = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""运行多 Agent 任务
|
||||
# @router.post(
|
||||
# "/{app_id}/multi-agent/run",
|
||||
# summary="运行多 Agent 任务"
|
||||
# )
|
||||
# async def run_multi_agent(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# request: multi_agent_schema.MultiAgentRunRequest = ...,
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """运行多 Agent 任务
|
||||
|
||||
根据配置的编排模式执行多个 Agent:
|
||||
- sequential: 按优先级顺序执行
|
||||
- parallel: 并行执行所有 Agent
|
||||
- conditional: 根据条件选择 Agent
|
||||
- loop: 循环执行直到满足条件
|
||||
"""
|
||||
service = MultiAgentService(db)
|
||||
result = await service.run(app_id, request)
|
||||
# 根据配置的编排模式执行多个 Agent:
|
||||
# - sequential: 按优先级顺序执行
|
||||
# - parallel: 并行执行所有 Agent
|
||||
# - conditional: 根据条件选择 Agent
|
||||
# """
|
||||
# service = MultiAgentService(db)
|
||||
# result = await service.run(app_id, request)
|
||||
|
||||
return success(
|
||||
data=multi_agent_schema.MultiAgentRunResponse(**result),
|
||||
msg="多 Agent 任务执行成功"
|
||||
)
|
||||
# return success(
|
||||
# data=multi_agent_schema.MultiAgentRunResponse(**result),
|
||||
# msg="多 Agent 任务执行成功"
|
||||
# )
|
||||
|
||||
|
||||
# ==================== 智能路由测试 ====================
|
||||
# # ==================== 智能路由测试 ====================
|
||||
|
||||
@router.post(
|
||||
"/{app_id}/multi-agent/test-routing",
|
||||
summary="测试智能路由(支持 Master Agent 模式)"
|
||||
)
|
||||
async def test_routing(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
request: multi_agent_schema.RoutingTestRequest = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""测试智能路由功能(重构版 - 支持 Master Agent)
|
||||
# @router.post(
|
||||
# "/{app_id}/multi-agent/test-routing",
|
||||
# summary="测试智能路由(支持 Master Agent 模式)"
|
||||
# )
|
||||
# async def test_routing(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# request: multi_agent_schema.RoutingTestRequest = ...,
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """测试智能路由功能(重构版 - 支持 Master Agent)
|
||||
|
||||
支持三种路由模式:
|
||||
- master_agent: 使用 Master Agent 决策(推荐)
|
||||
- llm_router: 使用旧 LLM 路由器(向后兼容)
|
||||
- rule_only: 仅使用规则路由(最快)
|
||||
# 支持三种路由模式:
|
||||
# - master_agent: 使用 Master Agent 决策(推荐)
|
||||
# - llm_router: 使用旧 LLM 路由器(向后兼容)
|
||||
# - rule_only: 仅使用规则路由(最快)
|
||||
|
||||
参数:
|
||||
- message: 测试消息
|
||||
- conversation_id: 会话 ID(可选)
|
||||
- routing_model_id: 路由模型 ID(可选)
|
||||
- use_llm: 是否启用 LLM(默认 False)
|
||||
- keyword_threshold: 关键词置信度阈值(默认 0.8)
|
||||
- force_new: 是否强制重新路由(默认 False)
|
||||
"""
|
||||
from app.services.conversation_state_manager import ConversationStateManager
|
||||
from app.services.llm_router import LLMRouter
|
||||
from app.models import ModelConfig
|
||||
# 参数:
|
||||
# - message: 测试消息
|
||||
# - conversation_id: 会话 ID(可选)
|
||||
# - routing_model_id: 路由模型 ID(可选)
|
||||
# - use_llm: 是否启用 LLM(默认 False)
|
||||
# - keyword_threshold: 关键词置信度阈值(默认 0.8)
|
||||
# - force_new: 是否强制重新路由(默认 False)
|
||||
# """
|
||||
# from app.services.conversation_state_manager import ConversationStateManager
|
||||
# from app.services.llm_router import LLMRouter
|
||||
# from app.models import ModelConfig
|
||||
|
||||
# 1. 获取多 Agent 配置
|
||||
service = MultiAgentService(db)
|
||||
config = service.get_config(app_id)
|
||||
# # 1. 获取多 Agent 配置
|
||||
# service = MultiAgentService(db)
|
||||
# config = service.get_config(app_id)
|
||||
|
||||
if not config:
|
||||
return success(
|
||||
data=None,
|
||||
msg="应用未配置多 Agent,无法测试路由"
|
||||
)
|
||||
# if not config:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg="应用未配置多 Agent,无法测试路由"
|
||||
# )
|
||||
|
||||
# 2. 准备子 Agent 信息
|
||||
sub_agents = {}
|
||||
for sub_agent_info in config.sub_agents:
|
||||
agent_id = sub_agent_info["agent_id"]
|
||||
sub_agents[agent_id] = {
|
||||
"name": sub_agent_info.get("name", agent_id),
|
||||
"role": sub_agent_info.get("role", "")
|
||||
}
|
||||
# # 2. 准备子 Agent 信息
|
||||
# sub_agents = {}
|
||||
# for sub_agent_info in config.sub_agents:
|
||||
# agent_id = sub_agent_info["agent_id"]
|
||||
# sub_agents[agent_id] = {
|
||||
# "name": sub_agent_info.get("name", agent_id),
|
||||
# "role": sub_agent_info.get("role", "")
|
||||
# }
|
||||
|
||||
# 3. 获取路由模型(如果指定)
|
||||
routing_model = None
|
||||
if request.routing_model_id:
|
||||
routing_model = db.get(ModelConfig, request.routing_model_id)
|
||||
if not routing_model:
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"路由模型不存在: {request.routing_model_id}"
|
||||
)
|
||||
# # 3. 获取路由模型(如果指定)
|
||||
# routing_model = None
|
||||
# if request.routing_model_id:
|
||||
# routing_model = db.get(ModelConfig, request.routing_model_id)
|
||||
# if not routing_model:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"路由模型不存在: {request.routing_model_id}"
|
||||
# )
|
||||
|
||||
# 4. 初始化路由器
|
||||
state_manager = ConversationStateManager()
|
||||
router = LLMRouter(
|
||||
db=db,
|
||||
state_manager=state_manager,
|
||||
routing_rules=config.routing_rules or [],
|
||||
sub_agents=sub_agents,
|
||||
routing_model_config=routing_model,
|
||||
use_llm=request.use_llm and routing_model is not None
|
||||
)
|
||||
# # 4. 初始化路由器
|
||||
# state_manager = ConversationStateManager()
|
||||
# router = LLMRouter(
|
||||
# db=db,
|
||||
# state_manager=state_manager,
|
||||
# routing_rules=config.routing_rules or [],
|
||||
# sub_agents=sub_agents,
|
||||
# routing_model_config=routing_model,
|
||||
# use_llm=request.use_llm and routing_model is not None
|
||||
# )
|
||||
|
||||
# 5. 设置阈值
|
||||
if request.keyword_threshold:
|
||||
router.keyword_high_confidence_threshold = request.keyword_threshold
|
||||
# # 5. 设置阈值
|
||||
# if request.keyword_threshold:
|
||||
# router.keyword_high_confidence_threshold = request.keyword_threshold
|
||||
|
||||
# 6. 执行路由
|
||||
try:
|
||||
routing_result = await router.route(
|
||||
message=request.message,
|
||||
conversation_id=str(request.conversation_id) if request.conversation_id else None,
|
||||
force_new=request.force_new
|
||||
)
|
||||
# # 6. 执行路由
|
||||
# try:
|
||||
# routing_result = await router.route(
|
||||
# message=request.message,
|
||||
# conversation_id=str(request.conversation_id) if request.conversation_id else None,
|
||||
# force_new=request.force_new
|
||||
# )
|
||||
|
||||
# 7. 获取 Agent 信息
|
||||
agent_id = routing_result["agent_id"]
|
||||
agent_info = sub_agents.get(agent_id, {})
|
||||
# # 7. 获取 Agent 信息
|
||||
# agent_id = routing_result["agent_id"]
|
||||
# agent_info = sub_agents.get(agent_id, {})
|
||||
|
||||
# 8. 构建响应
|
||||
response_data = {
|
||||
"message": request.message,
|
||||
"routing_result": {
|
||||
"agent_id": agent_id,
|
||||
"agent_name": agent_info.get("name", agent_id),
|
||||
"agent_role": agent_info.get("role", ""),
|
||||
"confidence": routing_result["confidence"],
|
||||
"strategy": routing_result["strategy"],
|
||||
"topic": routing_result["topic"],
|
||||
"topic_changed": routing_result["topic_changed"],
|
||||
"reason": routing_result["reason"],
|
||||
"routing_method": routing_result["routing_method"]
|
||||
},
|
||||
"cmulti-agent/batch-test-routingonfig_info": {
|
||||
"use_llm": request.use_llm and routing_model is not None,
|
||||
"routing_model": routing_model.name if routing_model else None,
|
||||
"keyword_threshold": router.keyword_high_confidence_threshold,
|
||||
"total_sub_agents": len(sub_agents)
|
||||
}
|
||||
}
|
||||
# # 8. 构建响应
|
||||
# response_data = {
|
||||
# "message": request.message,
|
||||
# "routing_result": {
|
||||
# "agent_id": agent_id,
|
||||
# "agent_name": agent_info.get("name", agent_id),
|
||||
# "agent_role": agent_info.get("role", ""),
|
||||
# "confidence": routing_result["confidence"],
|
||||
# "strategy": routing_result["strategy"],
|
||||
# "topic": routing_result["topic"],
|
||||
# "topic_changed": routing_result["topic_changed"],
|
||||
# "reason": routing_result["reason"],
|
||||
# "routing_method": routing_result["routing_method"]
|
||||
# },
|
||||
# "cmulti-agent/batch-test-routingonfig_info": {
|
||||
# "use_llm": request.use_llm and routing_model is not None,
|
||||
# "routing_model": routing_model.name if routing_model else None,
|
||||
# "keyword_threshold": router.keyword_high_confidence_threshold,
|
||||
# "total_sub_agents": len(sub_agents)
|
||||
# }
|
||||
# }
|
||||
|
||||
return success(
|
||||
data=response_data,
|
||||
msg="路由测试成功"
|
||||
)
|
||||
# return success(
|
||||
# data=response_data,
|
||||
# msg="路由测试成功"
|
||||
# )
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"路由测试失败: {str(e)}")
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"路由测试失败: {str(e)}"
|
||||
)
|
||||
# except Exception as e:
|
||||
# logger.error(f"路由测试失败: {str(e)}")
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"路由测试失败: {str(e)}"
|
||||
# )
|
||||
|
||||
|
||||
@router.post(
|
||||
"/{app_id}/multi-agent/test-master-agent",
|
||||
summary="测试 Master Agent 决策"
|
||||
)
|
||||
async def test_master_agent(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
request: multi_agent_schema.RoutingTestRequest = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""测试 Master Agent 的路由决策能力
|
||||
# @router.post(
|
||||
# "/{app_id}/multi-agent/test-master-agent",
|
||||
# summary="测试 Master Agent 决策"
|
||||
# )
|
||||
# async def test_master_agent(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# request: multi_agent_schema.RoutingTestRequest = ...,
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """测试 Master Agent 的路由决策能力
|
||||
|
||||
这个接口专门用于测试新的 Master Agent 路由器,
|
||||
可以看到 Master Agent 的完整决策过程。
|
||||
# 这个接口专门用于测试新的 Master Agent 路由器,
|
||||
# 可以看到 Master Agent 的完整决策过程。
|
||||
|
||||
返回信息包括:
|
||||
- 选中的 Agent
|
||||
- 置信度
|
||||
- 决策理由
|
||||
- 是否需要协作
|
||||
- 路由策略(master_agent / rule_fast_path / fallback)
|
||||
"""
|
||||
from app.services.conversation_state_manager import ConversationStateManager
|
||||
from app.services.master_agent_router import MasterAgentRouter
|
||||
from app.models import ModelConfig
|
||||
# 返回信息包括:
|
||||
# - 选中的 Agent
|
||||
# - 置信度
|
||||
# - 决策理由
|
||||
# - 是否需要协作
|
||||
# - 路由策略(master_agent / rule_fast_path / fallback)
|
||||
# """
|
||||
# from app.services.conversation_state_manager import ConversationStateManager
|
||||
# from app.services.master_agent_router import MasterAgentRouter
|
||||
# from app.models import ModelConfig
|
||||
|
||||
# 1. 获取多 Agent 配置
|
||||
service = MultiAgentService(db)
|
||||
config = service.get_config(app_id)
|
||||
# # 1. 获取多 Agent 配置
|
||||
# service = MultiAgentService(db)
|
||||
# config = service.get_config(app_id)
|
||||
|
||||
if not config:
|
||||
return success(
|
||||
data=None,
|
||||
msg="应用未配置多 Agent,无法测试"
|
||||
)
|
||||
# if not config:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg="应用未配置多 Agent,无法测试"
|
||||
# )
|
||||
|
||||
# 2. 加载 Master Agent
|
||||
from app.models import AppRelease, App
|
||||
# # 2. 加载 Master Agent
|
||||
# from app.models import AppRelease, App
|
||||
|
||||
master_release = db.get(AppRelease, config.master_agent_id)
|
||||
if not master_release:
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"Master Agent 发布版本不存在: {config.master_agent_id}"
|
||||
)
|
||||
# master_release = db.get(AppRelease, config.master_agent_id)
|
||||
# if not master_release:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"Master Agent 发布版本不存在: {config.master_agent_id}"
|
||||
# )
|
||||
|
||||
# 获取应用信息
|
||||
app = db.get(App, master_release.app_id)
|
||||
if not app:
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"应用不存在: {master_release.app_id}"
|
||||
)
|
||||
# # 获取应用信息
|
||||
# app = db.get(App, master_release.app_id)
|
||||
# if not app:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"应用不存在: {master_release.app_id}"
|
||||
# )
|
||||
|
||||
# 创建 Master Agent 代理对象
|
||||
class AgentConfigProxy:
|
||||
def __init__(self, release, app, config_data):
|
||||
self.id = release.id
|
||||
self.app_id = release.app_id
|
||||
self.app = app
|
||||
self.name = release.name
|
||||
self.description = release.description
|
||||
self.system_prompt = config_data.get("system_prompt")
|
||||
self.default_model_config_id = release.default_model_config_id
|
||||
# # 创建 Master Agent 代理对象
|
||||
# class AgentConfigProxy:
|
||||
# def __init__(self, release, app, config_data):
|
||||
# self.id = release.id
|
||||
# self.app_id = release.app_id
|
||||
# self.app = app
|
||||
# self.name = release.name
|
||||
# self.description = release.description
|
||||
# self.system_prompt = config_data.get("system_prompt")
|
||||
# self.default_model_config_id = release.default_model_config_id
|
||||
|
||||
config_data = master_release.config or {}
|
||||
master_agent_config = AgentConfigProxy(master_release, app, config_data)
|
||||
# config_data = master_release.config or {}
|
||||
# master_agent_config = AgentConfigProxy(master_release, app, config_data)
|
||||
|
||||
# 3. 获取 Master Agent 的模型配置
|
||||
master_model_config = db.get(ModelConfig, master_agent_config.default_model_config_id)
|
||||
if not master_model_config:
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"Master Agent 模型配置不存在: {master_agent_config.default_model_config_id}"
|
||||
)
|
||||
# # 3. 获取 Master Agent 的模型配置
|
||||
# master_model_config = db.get(ModelConfig, master_agent_config.default_model_config_id)
|
||||
# if not master_model_config:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"Master Agent 模型配置不存在: {master_agent_config.default_model_config_id}"
|
||||
# )
|
||||
|
||||
# 4. 准备子 Agent 信息
|
||||
sub_agents = {}
|
||||
for sub_agent_info in config.sub_agents:
|
||||
agent_id = sub_agent_info["agent_id"]
|
||||
# # 4. 准备子 Agent 信息
|
||||
# sub_agents = {}
|
||||
# for sub_agent_info in config.sub_agents:
|
||||
# agent_id = sub_agent_info["agent_id"]
|
||||
|
||||
# 加载子 Agent
|
||||
sub_release = db.get(AppRelease, uuid.UUID(agent_id))
|
||||
if sub_release:
|
||||
sub_app = db.get(App, sub_release.app_id)
|
||||
sub_config_data = sub_release.config or {}
|
||||
sub_agent_config = AgentConfigProxy(sub_release, sub_app, sub_config_data)
|
||||
# # 加载子 Agent
|
||||
# sub_release = db.get(AppRelease, uuid.UUID(agent_id))
|
||||
# if sub_release:
|
||||
# sub_app = db.get(App, sub_release.app_id)
|
||||
# sub_config_data = sub_release.config or {}
|
||||
# sub_agent_config = AgentConfigProxy(sub_release, sub_app, sub_config_data)
|
||||
|
||||
sub_agents[agent_id] = {
|
||||
"config": sub_agent_config,
|
||||
"info": sub_agent_info
|
||||
}
|
||||
# sub_agents[agent_id] = {
|
||||
# "config": sub_agent_config,
|
||||
# "info": sub_agent_info
|
||||
# }
|
||||
|
||||
# 5. 初始化 Master Agent 路由器
|
||||
state_manager = ConversationStateManager()
|
||||
router = MasterAgentRouter(
|
||||
db=db,
|
||||
master_agent_config=master_agent_config,
|
||||
master_model_config=master_model_config,
|
||||
sub_agents=sub_agents,
|
||||
state_manager=state_manager,
|
||||
enable_rule_fast_path=True
|
||||
)
|
||||
# # 5. 初始化 Master Agent 路由器
|
||||
# state_manager = ConversationStateManager()
|
||||
# router = MasterAgentRouter(
|
||||
# db=db,
|
||||
# master_agent_config=master_agent_config,
|
||||
# master_model_config=master_model_config,
|
||||
# sub_agents=sub_agents,
|
||||
# state_manager=state_manager,
|
||||
# enable_rule_fast_path=True
|
||||
# )
|
||||
|
||||
# 6. 执行路由决策
|
||||
try:
|
||||
decision = await router.route(
|
||||
message=request.message,
|
||||
conversation_id=str(request.conversation_id) if request.conversation_id else None,
|
||||
variables=None
|
||||
)
|
||||
# # 6. 执行路由决策
|
||||
# try:
|
||||
# decision = await router.route(
|
||||
# message=request.message,
|
||||
# conversation_id=str(request.conversation_id) if request.conversation_id else None,
|
||||
# variables=None
|
||||
# )
|
||||
|
||||
# 7. 获取选中的 Agent 信息
|
||||
agent_id = decision["selected_agent_id"]
|
||||
agent_info = sub_agents.get(agent_id, {}).get("info", {})
|
||||
# # 7. 获取选中的 Agent 信息
|
||||
# agent_id = decision["selected_agent_id"]
|
||||
# agent_info = sub_agents.get(agent_id, {}).get("info", {})
|
||||
|
||||
# 8. 构建响应
|
||||
response_data = {
|
||||
"message": request.message,
|
||||
"master_agent": {
|
||||
"name": master_agent_config.name,
|
||||
"model": master_model_config.name
|
||||
},
|
||||
"decision": {
|
||||
"selected_agent_id": agent_id,
|
||||
"selected_agent_name": agent_info.get("name", "未知"),
|
||||
"selected_agent_role": agent_info.get("role", ""),
|
||||
"confidence": decision["confidence"],
|
||||
"reasoning": decision.get("reasoning", ""),
|
||||
"topic": decision.get("topic", ""),
|
||||
"strategy": decision["strategy"],
|
||||
"routing_method": decision.get("routing_method", ""),
|
||||
"need_collaboration": decision.get("need_collaboration", False),
|
||||
"collaboration_agents": decision.get("collaboration_agents", [])
|
||||
},
|
||||
"config_info": {
|
||||
"total_sub_agents": len(sub_agents),
|
||||
"enable_rule_fast_path": True
|
||||
}
|
||||
}
|
||||
# # 8. 构建响应
|
||||
# response_data = {
|
||||
# "message": request.message,
|
||||
# "master_agent": {
|
||||
# "name": master_agent_config.name,
|
||||
# "model": master_model_config.name
|
||||
# },
|
||||
# "decision": {
|
||||
# "selected_agent_id": agent_id,
|
||||
# "selected_agent_name": agent_info.get("name", "未知"),
|
||||
# "selected_agent_role": agent_info.get("role", ""),
|
||||
# "confidence": decision["confidence"],
|
||||
# "reasoning": decision.get("reasoning", ""),
|
||||
# "topic": decision.get("topic", ""),
|
||||
# "strategy": decision["strategy"],
|
||||
# "routing_method": decision.get("routing_method", ""),
|
||||
# "need_collaboration": decision.get("need_collaboration", False),
|
||||
# "collaboration_agents": decision.get("collaboration_agents", [])
|
||||
# },
|
||||
# "config_info": {
|
||||
# "total_sub_agents": len(sub_agents),
|
||||
# "enable_rule_fast_path": True
|
||||
# }
|
||||
# }
|
||||
|
||||
return success(
|
||||
data=response_data,
|
||||
msg="Master Agent 决策测试成功"
|
||||
)
|
||||
# return success(
|
||||
# data=response_data,
|
||||
# msg="Master Agent 决策测试成功"
|
||||
# )
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Master Agent 决策测试失败: {str(e)}")
|
||||
return success(
|
||||
data=None,
|
||||
msg=f"测试失败: {str(e)}"
|
||||
)
|
||||
# except Exception as e:
|
||||
# logger.error(f"Master Agent 决策测试失败: {str(e)}")
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg=f"测试失败: {str(e)}"
|
||||
# )
|
||||
|
||||
|
||||
@router.post(
|
||||
"/{app_id}/multi-agent/batch-test-routing",
|
||||
summary="批量测试智能路由"
|
||||
)
|
||||
async def batch_test_routing(
|
||||
app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
request: multi_agent_schema.BatchRoutingTestRequest = ...,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""批量测试智能路由功能
|
||||
# @router.post(
|
||||
# "/{app_id}/multi-agent/batch-test-routing",
|
||||
# summary="批量测试智能路由"
|
||||
# )
|
||||
# async def batch_test_routing(
|
||||
# app_id: uuid.UUID = Path(..., description="应用 ID"),
|
||||
# request: multi_agent_schema.BatchRoutingTestRequest = ...,
|
||||
# current_user: User = Depends(get_current_user),
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """批量测试智能路由功能
|
||||
|
||||
用于测试多条消息的路由效果,并统计准确率
|
||||
# 用于测试多条消息的路由效果,并统计准确率
|
||||
|
||||
参数:
|
||||
- test_cases: 测试用例列表
|
||||
- routing_model_id: 路由模型 ID(可选)
|
||||
- use_llm: 是否启用 LLM
|
||||
- keyword_threshold: 关键词置信度阈值
|
||||
"""
|
||||
from app.services.conversation_state_manager import ConversationStateManager
|
||||
from app.services.llm_router import LLMRouter
|
||||
from app.models import ModelConfig
|
||||
# 参数:
|
||||
# - test_cases: 测试用例列表
|
||||
# - routing_model_id: 路由模型 ID(可选)
|
||||
# - use_llm: 是否启用 LLM
|
||||
# - keyword_threshold: 关键词置信度阈值
|
||||
# """
|
||||
# from app.services.conversation_state_manager import ConversationStateManager
|
||||
# from app.services.llm_router import LLMRouter
|
||||
# from app.models import ModelConfig
|
||||
|
||||
# 1. 获取多 Agent 配置
|
||||
service = MultiAgentService(db)
|
||||
config = service.get_config(app_id)
|
||||
# # 1. 获取多 Agent 配置
|
||||
# service = MultiAgentService(db)
|
||||
# config = service.get_config(app_id)
|
||||
|
||||
if not config:
|
||||
return success(
|
||||
data=None,
|
||||
msg="应用未配置多 Agent,无法测试路由"
|
||||
)
|
||||
# if not config:
|
||||
# return success(
|
||||
# data=None,
|
||||
# msg="应用未配置多 Agent,无法测试路由"
|
||||
# )
|
||||
|
||||
# 2. 准备子 Agent 信息
|
||||
sub_agents = {}
|
||||
for sub_agent_info in config.sub_agents:
|
||||
agent_id = sub_agent_info["agent_id"]
|
||||
sub_agents[agent_id] = {
|
||||
"name": sub_agent_info.get("name", agent_id),
|
||||
"role": sub_agent_info.get("role", "")
|
||||
}
|
||||
# # 2. 准备子 Agent 信息
|
||||
# sub_agents = {}
|
||||
# for sub_agent_info in config.sub_agents:
|
||||
# agent_id = sub_agent_info["agent_id"]
|
||||
# sub_agents[agent_id] = {
|
||||
# "name": sub_agent_info.get("name", agent_id),
|
||||
# "role": sub_agent_info.get("role", "")
|
||||
# }
|
||||
|
||||
# 3. 获取路由模型
|
||||
routing_model = None
|
||||
if request.routing_model_id:
|
||||
routing_model = db.get(ModelConfig, request.routing_model_id)
|
||||
# # 3. 获取路由模型
|
||||
# routing_model = None
|
||||
# if request.routing_model_id:
|
||||
# routing_model = db.get(ModelConfig, request.routing_model_id)
|
||||
|
||||
# 4. 初始化路由器
|
||||
state_manager = ConversationStateManager()
|
||||
router = LLMRouter(
|
||||
db=db,
|
||||
state_manager=state_manager,
|
||||
routing_rules=config.routing_rules or [],
|
||||
sub_agents=sub_agents,
|
||||
routing_model_config=routing_model,
|
||||
use_llm=request.use_llm and routing_model is not None
|
||||
)
|
||||
# # 4. 初始化路由器
|
||||
# state_manager = ConversationStateManager()
|
||||
# router = LLMRouter(
|
||||
# db=db,
|
||||
# state_manager=state_manager,
|
||||
# routing_rules=config.routing_rules or [],
|
||||
# sub_agents=sub_agents,
|
||||
# routing_model_config=routing_model,
|
||||
# use_llm=request.use_llm and routing_model is not None
|
||||
# )
|
||||
|
||||
if request.keyword_threshold:
|
||||
router.keyword_high_confidence_threshold = request.keyword_threshold
|
||||
# if request.keyword_threshold:
|
||||
# router.keyword_high_confidence_threshold = request.keyword_threshold
|
||||
|
||||
# 5. 批量测试
|
||||
results = []
|
||||
correct_count = 0
|
||||
total_count = len(request.test_cases)
|
||||
# # 5. 批量测试
|
||||
# results = []
|
||||
# correct_count = 0
|
||||
# total_count = len(request.test_cases)
|
||||
|
||||
for test_case in request.test_cases:
|
||||
try:
|
||||
routing_result = await router.route(
|
||||
message=test_case.message,
|
||||
conversation_id=str(uuid.uuid4()) # 每个测试用例使用独立会话
|
||||
)
|
||||
# for test_case in request.test_cases:
|
||||
# try:
|
||||
# routing_result = await router.route(
|
||||
# message=test_case.message,
|
||||
# conversation_id=str(uuid.uuid4()) # 每个测试用例使用独立会话
|
||||
# )
|
||||
|
||||
agent_id = routing_result["agent_id"]
|
||||
agent_info = sub_agents.get(agent_id, {})
|
||||
# agent_id = routing_result["agent_id"]
|
||||
# agent_info = sub_agents.get(agent_id, {})
|
||||
|
||||
# 判断是否正确
|
||||
is_correct = None
|
||||
if test_case.expected_agent_id:
|
||||
is_correct = (agent_id == str(test_case.expected_agent_id))
|
||||
if is_correct:
|
||||
correct_count += 1
|
||||
# # 判断是否正确
|
||||
# is_correct = None
|
||||
# if test_case.expected_agent_id:
|
||||
# is_correct = (agent_id == str(test_case.expected_agent_id))
|
||||
# if is_correct:
|
||||
# correct_count += 1
|
||||
|
||||
results.append({
|
||||
"message": test_case.message,
|
||||
"description": test_case.description,
|
||||
"routed_agent_id": agent_id,
|
||||
"routed_agent_name": agent_info.get("name"),
|
||||
"expected_agent_id": str(test_case.expected_agent_id) if test_case.expected_agent_id else None,
|
||||
"is_correct": is_correct,
|
||||
"confidence": routing_result["confidence"],
|
||||
"routing_method": routing_result["routing_method"],
|
||||
"strategy": routing_result["strategy"]
|
||||
})
|
||||
# results.append({
|
||||
# "message": test_case.message,
|
||||
# "description": test_case.description,
|
||||
# "routed_agent_id": agent_id,
|
||||
# "routed_agent_name": agent_info.get("name"),
|
||||
# "expected_agent_id": str(test_case.expected_agent_id) if test_case.expected_agent_id else None,
|
||||
# "is_correct": is_correct,
|
||||
# "confidence": routing_result["confidence"],
|
||||
# "routing_method": routing_result["routing_method"],
|
||||
# "strategy": routing_result["strategy"]
|
||||
# })
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"测试用例失败: {test_case.message}, 错误: {str(e)}")
|
||||
results.append({
|
||||
"message": test_case.message,
|
||||
"description": test_case.description,
|
||||
"error": str(e)
|
||||
})
|
||||
# except Exception as e:
|
||||
# logger.error(f"测试用例失败: {test_case.message}, 错误: {str(e)}")
|
||||
# results.append({
|
||||
# "message": test_case.message,
|
||||
# "description": test_case.description,
|
||||
# "error": str(e)
|
||||
# })
|
||||
|
||||
# 6. 统计
|
||||
accuracy = None
|
||||
if correct_count > 0:
|
||||
total_with_expected = sum(1 for r in results if r.get("expected_agent_id"))
|
||||
if total_with_expected > 0:
|
||||
accuracy = correct_count / total_with_expected * 100
|
||||
# # 6. 统计
|
||||
# accuracy = None
|
||||
# if correct_count > 0:
|
||||
# total_with_expected = sum(1 for r in results if r.get("expected_agent_id"))
|
||||
# if total_with_expected > 0:
|
||||
# accuracy = correct_count / total_with_expected * 100
|
||||
|
||||
response_data = {
|
||||
"total_count": total_count,
|
||||
"correct_count": correct_count,
|
||||
"accuracy": accuracy,
|
||||
"results": results,
|
||||
"config_info": {
|
||||
"use_llm": request.use_llm and routing_model is not None,
|
||||
"routing_model": routing_model.name if routing_model else None,
|
||||
"keyword_threshold": router.keyword_high_confidence_threshold
|
||||
}
|
||||
}
|
||||
# response_data = {
|
||||
# "total_count": total_count,
|
||||
# "correct_count": correct_count,
|
||||
# "accuracy": accuracy,
|
||||
# "results": results,
|
||||
# "config_info": {
|
||||
# "use_llm": request.use_llm and routing_model is not None,
|
||||
# "routing_model": routing_model.name if routing_model else None,
|
||||
# "keyword_threshold": router.keyword_high_confidence_threshold
|
||||
# }
|
||||
# }
|
||||
|
||||
return success(
|
||||
data=response_data,
|
||||
msg=f"批量测试完成,准确率: {accuracy:.1f}%" if accuracy else "批量测试完成"
|
||||
)
|
||||
# return success(
|
||||
# data=response_data,
|
||||
# msg=f"批量测试完成,准确率: {accuracy:.1f}%" if accuracy else "批量测试完成"
|
||||
# )
|
||||
|
||||
@@ -4,6 +4,8 @@ import datetime
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer
|
||||
|
||||
from app.schemas import ModelParameters
|
||||
|
||||
|
||||
# ==================== 子 Agent 配置 ====================
|
||||
|
||||
@@ -82,6 +84,11 @@ class MultiAgentConfigUpdate(BaseModel):
|
||||
"""更新多 Agent 配置"""
|
||||
master_agent_id: Optional[uuid.UUID] = None
|
||||
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(
|
||||
None,
|
||||
pattern="^(sequential|parallel|conditional|loop)$"
|
||||
@@ -104,6 +111,11 @@ class MultiAgentConfigSchema(BaseModel):
|
||||
app_id: uuid.UUID
|
||||
master_agent_id: uuid.UUID
|
||||
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
|
||||
sub_agents: List[Dict[str, Any]]
|
||||
routing_rules: Optional[List[Dict[str, Any]]]
|
||||
|
||||
@@ -5,9 +5,11 @@ import uuid
|
||||
from typing import Dict, Any, List, Optional, Tuple
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.schemas import ModelParameters
|
||||
from app.services.conversation_state_manager import ConversationStateManager
|
||||
from app.models import ModelConfig, AgentConfig
|
||||
from app.core.logging_config import get_business_logger
|
||||
from app.services.model_service import ModelApiKeyService
|
||||
|
||||
logger = get_business_logger()
|
||||
|
||||
@@ -30,8 +32,8 @@ class MasterAgentRouter:
|
||||
def __init__(
|
||||
self,
|
||||
db: Session,
|
||||
master_agent_config: AgentConfig,
|
||||
master_model_config: ModelConfig,
|
||||
model_parameters: ModelParameters,
|
||||
sub_agents: Dict[str, Any],
|
||||
state_manager: ConversationStateManager,
|
||||
enable_rule_fast_path: bool = True
|
||||
@@ -40,15 +42,14 @@ class MasterAgentRouter:
|
||||
|
||||
Args:
|
||||
db: 数据库会话
|
||||
master_agent_config: Master Agent 配置
|
||||
master_model_config: Master Agent 使用的模型配置
|
||||
sub_agents: 子 Agent 配置字典
|
||||
state_manager: 会话状态管理器
|
||||
enable_rule_fast_path: 是否启用规则快速路径(性能优化)
|
||||
"""
|
||||
self.db = db
|
||||
self.master_agent_config = master_agent_config
|
||||
self.master_model_config = master_model_config
|
||||
self.model_parameters = model_parameters
|
||||
self.sub_agents = sub_agents
|
||||
self.state_manager = state_manager
|
||||
self.enable_rule_fast_path = enable_rule_fast_path
|
||||
@@ -56,7 +57,6 @@ class MasterAgentRouter:
|
||||
logger.info(
|
||||
"Master Agent 路由器初始化",
|
||||
extra={
|
||||
"master_agent": master_agent_config.name,
|
||||
"sub_agent_count": len(sub_agents),
|
||||
"enable_rule_fast_path": enable_rule_fast_path
|
||||
}
|
||||
@@ -349,10 +349,7 @@ class MasterAgentRouter:
|
||||
from app.models import ModelApiKey, ModelType
|
||||
|
||||
# 获取 API Key 配置
|
||||
api_key_config = self.db.query(ModelApiKey).filter(
|
||||
ModelApiKey.model_config_id == self.master_model_config.id,
|
||||
ModelApiKey.is_active == True
|
||||
).first()
|
||||
api_key_config = ModelApiKeyService.get_a_api_key(self.db, self.master_model_config.id)
|
||||
|
||||
if not api_key_config:
|
||||
raise Exception("Master Agent 模型没有可用的 API Key")
|
||||
@@ -364,15 +361,20 @@ class MasterAgentRouter:
|
||||
"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
|
||||
model_config = RedBearModelConfig(
|
||||
model_name=api_key_config.model_name,
|
||||
provider=api_key_config.provider,
|
||||
api_key=api_key_config.api_key,
|
||||
base_url=api_key_config.api_base,
|
||||
temperature=0.3, # 决策任务使用较低温度
|
||||
max_tokens=1000
|
||||
extra_params = extra_params
|
||||
)
|
||||
|
||||
# 创建 LLM 实例
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Dict, Any, List, Optional, AsyncIterator, Tuple
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
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.master_agent_router import MasterAgentRouter
|
||||
from app.services.conversation_state_manager import ConversationStateManager
|
||||
@@ -31,7 +32,10 @@ class MultiAgentOrchestrator:
|
||||
self.registry = AgentRegistry(db)
|
||||
|
||||
# 加载主 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
|
||||
self.sub_agents = {}
|
||||
@@ -47,18 +51,18 @@ class MultiAgentOrchestrator:
|
||||
self.state_manager = ConversationStateManager()
|
||||
|
||||
# 获取 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)
|
||||
|
||||
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:
|
||||
raise BusinessException("Master Agent 模型配置不存在", BizCode.AGENT_CONFIG_MISSING)
|
||||
|
||||
# 初始化 Master Agent 路由器
|
||||
self.router = MasterAgentRouter(
|
||||
db=db,
|
||||
master_agent_config=self.master_agent,
|
||||
master_model_config=self.master_model_config,
|
||||
model_parameters=self.model_parameters,
|
||||
sub_agents=self.sub_agents,
|
||||
state_manager=self.state_manager,
|
||||
enable_rule_fast_path=config.execution_config.get("enable_rule_fast_path", True)
|
||||
@@ -68,7 +72,6 @@ class MultiAgentOrchestrator:
|
||||
"多 Agent 编排器初始化完成",
|
||||
extra={
|
||||
"config_id": str(config.id),
|
||||
"master_agent": self.master_agent.name,
|
||||
"model": self.master_model_config.name,
|
||||
"sub_agent_count": len(self.sub_agents)
|
||||
}
|
||||
@@ -122,7 +125,7 @@ class MultiAgentOrchestrator:
|
||||
task_analysis["use_llm_routing"] = use_llm_routing
|
||||
|
||||
# 2. 根据模式执行(流式)
|
||||
if self.config.orchestration_mode == "conditional":
|
||||
if self.config.orchestration_mode == OrchestrationMode.CONDITIONAL:
|
||||
async for event in self._execute_conditional_stream(
|
||||
task_analysis,
|
||||
conversation_id,
|
||||
@@ -135,7 +138,7 @@ class MultiAgentOrchestrator:
|
||||
yield event
|
||||
else:
|
||||
# 其他模式暂时使用非流式执行,然后一次性返回
|
||||
if self.config.orchestration_mode == "sequential":
|
||||
if self.config.orchestration_mode == OrchestrationMode.SEQUENTIAL:
|
||||
results = await self._execute_sequential(
|
||||
task_analysis,
|
||||
conversation_id,
|
||||
@@ -145,7 +148,7 @@ class MultiAgentOrchestrator:
|
||||
storage_type,
|
||||
user_rag_memory_id
|
||||
)
|
||||
elif self.config.orchestration_mode == "parallel":
|
||||
elif self.config.orchestration_mode == OrchestrationMode.PARALLEL:
|
||||
results = await self._execute_parallel(
|
||||
task_analysis,
|
||||
conversation_id,
|
||||
@@ -155,16 +158,16 @@ class MultiAgentOrchestrator:
|
||||
storage_type,
|
||||
user_rag_memory_id
|
||||
)
|
||||
elif self.config.orchestration_mode == "loop":
|
||||
results = await self._execute_loop(
|
||||
task_analysis,
|
||||
conversation_id,
|
||||
user_id,
|
||||
web_search,
|
||||
memory,
|
||||
storage_type,
|
||||
user_rag_memory_id
|
||||
)
|
||||
# elif self.config.orchestration_mode == "loop":
|
||||
# results = await self._execute_loop(
|
||||
# task_analysis,
|
||||
# conversation_id,
|
||||
# user_id,
|
||||
# web_search,
|
||||
# memory,
|
||||
# storage_type,
|
||||
# user_rag_memory_id
|
||||
# )
|
||||
else:
|
||||
raise BusinessException(
|
||||
f"不支持的编排模式: {self.config.orchestration_mode}",
|
||||
@@ -968,17 +971,17 @@ class MultiAgentOrchestrator:
|
||||
else:
|
||||
# 2. 降级:使用旧的路由逻辑
|
||||
logger.warning("未获取到 Master Agent 决策,使用旧路由逻辑(流式)")
|
||||
use_llm = task_analysis.get("use_llm_routing", True)
|
||||
selected_agent_info = await self._route_by_rules(
|
||||
message,
|
||||
task_analysis["sub_agents"],
|
||||
use_llm=use_llm,
|
||||
conversation_id=str(conversation_id) if conversation_id else None
|
||||
)
|
||||
|
||||
if not selected_agent_info:
|
||||
selected_agent_info = task_analysis["sub_agents"][0]
|
||||
logger.info("未匹配到路由规则,使用默认 Agent")
|
||||
# use_llm = task_analysis.get("use_llm_routing", True)
|
||||
# selected_agent_info = await self._route_by_rules(
|
||||
# message,
|
||||
# task_analysis["sub_agents"],
|
||||
# use_llm=use_llm,
|
||||
# conversation_id=str(conversation_id) if conversation_id else None
|
||||
# )
|
||||
#
|
||||
# if not selected_agent_info:
|
||||
selected_agent_info = task_analysis["sub_agents"][0]
|
||||
logger.info("未匹配到路由规则,使用默认 Agent")
|
||||
|
||||
agent_id = selected_agent_info["agent_id"]
|
||||
|
||||
@@ -1334,11 +1337,11 @@ class MultiAgentOrchestrator:
|
||||
"""
|
||||
strategy = self.config.aggregation_strategy
|
||||
|
||||
if strategy == "merge":
|
||||
if strategy == AggregationStrategy.MERGE:
|
||||
return self._merge_results(results)
|
||||
elif strategy == "vote":
|
||||
elif strategy == AggregationStrategy.VOTE:
|
||||
return self._vote_results(results)
|
||||
elif strategy == "priority":
|
||||
elif strategy == AggregationStrategy.PRIORITY:
|
||||
return self._priority_results(results)
|
||||
else:
|
||||
return self._merge_results(results)
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
"""多 Agent 配置管理服务"""
|
||||
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 import select, desc
|
||||
|
||||
from app.db import get_db
|
||||
from app.models import MultiAgentConfig, App, AgentConfig
|
||||
from app.schemas.multi_agent_schema import (
|
||||
MultiAgentConfigCreate,
|
||||
MultiAgentConfigUpdate,
|
||||
MultiAgentRunRequest
|
||||
)
|
||||
from app.services.model_service import ModelApiKeyService
|
||||
from app.services.multi_agent_orchestrator import MultiAgentOrchestrator
|
||||
from app.core.exceptions import ResourceNotFoundException, BusinessException
|
||||
from app.core.error_codes import BizCode
|
||||
@@ -158,9 +162,10 @@ class MultiAgentService:
|
||||
if not config:
|
||||
return None
|
||||
|
||||
# 转换 master_agent_id (release_id) 为 app_id
|
||||
master_release = self.db.get(AppRelease, config.master_agent_id)
|
||||
master_app_id = master_release.app_id if master_release else config.master_agent_id
|
||||
#兼容代码
|
||||
if not config.default_model_config_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
|
||||
converted_sub_agents = []
|
||||
@@ -181,8 +186,8 @@ class MultiAgentService:
|
||||
return {
|
||||
"id": config.id,
|
||||
"app_id": config.app_id,
|
||||
"master_agent_id": master_app_id,
|
||||
"master_agent_name": config.master_agent_name,
|
||||
"default_model_config_id": config.default_model_config_id,
|
||||
"model_parameters": config.model_parameters,
|
||||
"orchestration_mode": config.orchestration_mode,
|
||||
"sub_agents": converted_sub_agents,
|
||||
"routing_rules": config.routing_rules,
|
||||
@@ -253,6 +258,52 @@ class MultiAgentService:
|
||||
return None
|
||||
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(
|
||||
self,
|
||||
app_id: uuid.UUID,
|
||||
@@ -268,57 +319,12 @@ class MultiAgentService:
|
||||
更新后的配置
|
||||
"""
|
||||
config = self.get_config(app_id)
|
||||
newConfig = self.check_config_data(app_id, data)
|
||||
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
|
||||
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
|
||||
)
|
||||
|
||||
config = newConfig
|
||||
self.db.add(config)
|
||||
self.db.commit()
|
||||
self.db.refresh(config)
|
||||
|
||||
logger.info(
|
||||
"创建多 Agent 配置成功",
|
||||
extra={
|
||||
@@ -329,53 +335,14 @@ class MultiAgentService:
|
||||
}
|
||||
)
|
||||
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.refresh(config)
|
||||
|
||||
@@ -490,111 +457,111 @@ class MultiAgentService:
|
||||
):
|
||||
yield event
|
||||
|
||||
def add_sub_agent(
|
||||
self,
|
||||
app_id: uuid.UUID,
|
||||
agent_id: uuid.UUID,
|
||||
name: str,
|
||||
role: Optional[str] = None,
|
||||
priority: int = 1,
|
||||
capabilities: Optional[List[str]] = None
|
||||
) -> MultiAgentConfig:
|
||||
"""添加子 Agent
|
||||
# def add_sub_agent(
|
||||
# self,
|
||||
# app_id: uuid.UUID,
|
||||
# agent_id: uuid.UUID,
|
||||
# name: str,
|
||||
# role: Optional[str] = None,
|
||||
# priority: int = 1,
|
||||
# capabilities: Optional[List[str]] = None
|
||||
# ) -> MultiAgentConfig:
|
||||
# """添加子 Agent
|
||||
|
||||
Args:
|
||||
app_id: 应用 ID
|
||||
agent_id: Agent ID
|
||||
name: Agent 名称
|
||||
role: 角色描述
|
||||
priority: 优先级
|
||||
capabilities: 能力列表
|
||||
# Args:
|
||||
# app_id: 应用 ID
|
||||
# agent_id: Agent ID
|
||||
# name: Agent 名称
|
||||
# role: 角色描述
|
||||
# priority: 优先级
|
||||
# capabilities: 能力列表
|
||||
|
||||
Returns:
|
||||
更新后的配置
|
||||
"""
|
||||
config = self.get_config(app_id)
|
||||
if not config:
|
||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||
# Returns:
|
||||
# 更新后的配置
|
||||
# """
|
||||
# config = self.get_config(app_id)
|
||||
# if not config:
|
||||
# raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||
|
||||
# 验证 Agent 存在
|
||||
agent = self.db.get(AgentConfig, agent_id)
|
||||
if not agent:
|
||||
raise ResourceNotFoundException("Agent", str(agent_id))
|
||||
# # 验证 Agent 存在
|
||||
# agent = self.db.get(AgentConfig, agent_id)
|
||||
# if not agent:
|
||||
# raise ResourceNotFoundException("Agent", str(agent_id))
|
||||
|
||||
# 检查是否已存在
|
||||
for sub_agent in config.sub_agents:
|
||||
if sub_agent["agent_id"] == str(agent_id):
|
||||
raise BusinessException("Agent 已存在于配置中", BizCode.DUPLICATE_RESOURCE)
|
||||
# # 检查是否已存在
|
||||
# for sub_agent in config.sub_agents:
|
||||
# if sub_agent["agent_id"] == str(agent_id):
|
||||
# raise BusinessException("Agent 已存在于配置中", BizCode.DUPLICATE_RESOURCE)
|
||||
|
||||
# 添加子 Agent
|
||||
new_sub_agent = {
|
||||
"agent_id": str(agent_id),
|
||||
"name": name,
|
||||
"role": role,
|
||||
"priority": priority,
|
||||
"capabilities": capabilities or []
|
||||
}
|
||||
# # 添加子 Agent
|
||||
# new_sub_agent = {
|
||||
# "agent_id": str(agent_id),
|
||||
# "name": name,
|
||||
# "role": role,
|
||||
# "priority": priority,
|
||||
# "capabilities": capabilities or []
|
||||
# }
|
||||
|
||||
config.sub_agents.append(new_sub_agent)
|
||||
# config.sub_agents.append(new_sub_agent)
|
||||
|
||||
# 标记为已修改
|
||||
self.db.add(config)
|
||||
self.db.commit()
|
||||
self.db.refresh(config)
|
||||
# # 标记为已修改
|
||||
# self.db.add(config)
|
||||
# self.db.commit()
|
||||
# self.db.refresh(config)
|
||||
|
||||
logger.info(
|
||||
"添加子 Agent 成功",
|
||||
extra={
|
||||
"config_id": str(config.id),
|
||||
"agent_id": str(agent_id),
|
||||
"agent_name": name
|
||||
}
|
||||
)
|
||||
# logger.info(
|
||||
# "添加子 Agent 成功",
|
||||
# extra={
|
||||
# "config_id": str(config.id),
|
||||
# "agent_id": str(agent_id),
|
||||
# "agent_name": name
|
||||
# }
|
||||
# )
|
||||
|
||||
return config
|
||||
# return config
|
||||
|
||||
def remove_sub_agent(
|
||||
self,
|
||||
app_id: uuid.UUID,
|
||||
agent_id: uuid.UUID
|
||||
) -> MultiAgentConfig:
|
||||
"""移除子 Agent
|
||||
# def remove_sub_agent(
|
||||
# self,
|
||||
# app_id: uuid.UUID,
|
||||
# agent_id: uuid.UUID
|
||||
# ) -> MultiAgentConfig:
|
||||
# """移除子 Agent
|
||||
|
||||
Args:
|
||||
app_id: 应用 ID
|
||||
agent_id: Agent ID
|
||||
# Args:
|
||||
# app_id: 应用 ID
|
||||
# agent_id: Agent ID
|
||||
|
||||
Returns:
|
||||
更新后的配置
|
||||
"""
|
||||
config = self.get_config(app_id)
|
||||
if not config:
|
||||
raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||
# Returns:
|
||||
# 更新后的配置
|
||||
# """
|
||||
# config = self.get_config(app_id)
|
||||
# if not config:
|
||||
# raise ResourceNotFoundException("多 Agent 配置", str(app_id))
|
||||
|
||||
# 查找并移除
|
||||
original_count = len(config.sub_agents)
|
||||
config.sub_agents = [
|
||||
sub_agent for sub_agent in config.sub_agents
|
||||
if sub_agent["agent_id"] != str(agent_id)
|
||||
]
|
||||
# # 查找并移除
|
||||
# original_count = len(config.sub_agents)
|
||||
# config.sub_agents = [
|
||||
# sub_agent for sub_agent in config.sub_agents
|
||||
# if sub_agent["agent_id"] != str(agent_id)
|
||||
# ]
|
||||
|
||||
if len(config.sub_agents) == original_count:
|
||||
raise ResourceNotFoundException("子 Agent", str(agent_id))
|
||||
# if len(config.sub_agents) == original_count:
|
||||
# raise ResourceNotFoundException("子 Agent", str(agent_id))
|
||||
|
||||
# 标记为已修改
|
||||
self.db.add(config)
|
||||
self.db.commit()
|
||||
self.db.refresh(config)
|
||||
# # 标记为已修改
|
||||
# self.db.add(config)
|
||||
# self.db.commit()
|
||||
# self.db.refresh(config)
|
||||
|
||||
logger.info(
|
||||
"移除子 Agent 成功",
|
||||
extra={
|
||||
"config_id": str(config.id),
|
||||
"agent_id": str(agent_id)
|
||||
}
|
||||
)
|
||||
# logger.info(
|
||||
# "移除子 Agent 成功",
|
||||
# extra={
|
||||
# "config_id": str(config.id),
|
||||
# "agent_id": str(agent_id)
|
||||
# }
|
||||
# )
|
||||
|
||||
return config
|
||||
# return config
|
||||
|
||||
def list_configs(
|
||||
self,
|
||||
@@ -629,3 +596,11 @@ class MultiAgentService:
|
||||
configs = list(self.db.scalars(stmt).all())
|
||||
|
||||
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