2026-04-21 11:02:16 +08:00
|
|
|
|
"""
|
2026-05-08 22:30:26 +08:00
|
|
|
|
AI Agent 服务类
|
2026-04-21 11:02:16 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
2026-05-08 22:30:26 +08:00
|
|
|
|
from typing import AsyncGenerator, Dict, Any
|
2026-04-21 11:02:16 +08:00
|
|
|
|
|
2026-05-05 23:17:00 +08:00
|
|
|
|
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
|
|
|
|
|
|
|
2026-05-07 02:56:35 +08:00
|
|
|
|
from backend.app.model_services import get_cached_chat_services
|
|
|
|
|
|
from backend.app.main_graph.main_graph_builder import build_agent_graph
|
2026-05-08 22:30:26 +08:00
|
|
|
|
from backend.app.logger import info
|
|
|
|
|
|
from backend.app.memory.mem0_client import Mem0Client
|
|
|
|
|
|
|
|
|
|
|
|
from .service_config import ServiceConfig
|
|
|
|
|
|
from .stream_handler import run_graph_stream
|
2026-05-05 23:17:00 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-04-21 11:02:16 +08:00
|
|
|
|
class AIAgentService:
|
|
|
|
|
|
def __init__(self, checkpointer):
|
|
|
|
|
|
self.checkpointer = checkpointer
|
2026-05-07 00:48:17 +08:00
|
|
|
|
self.graph = None
|
2026-05-08 22:30:26 +08:00
|
|
|
|
self.config: ServiceConfig = None
|
2026-05-01 15:43:45 +08:00
|
|
|
|
self.mem0_client = None
|
2026-04-21 11:02:16 +08:00
|
|
|
|
|
2026-05-08 22:30:26 +08:00
|
|
|
|
async def initialize(self) -> "AIAgentService":
|
|
|
|
|
|
"""初始化 Agent 服务"""
|
2026-05-05 13:30:31 +08:00
|
|
|
|
self.mem0_client = Mem0Client()
|
2026-05-08 22:30:26 +08:00
|
|
|
|
|
2026-05-05 17:30:55 +08:00
|
|
|
|
self.chat_services = get_cached_chat_services()
|
|
|
|
|
|
info(f"✅ 加载了 {len(self.chat_services)} 个可用模型: {list(self.chat_services.keys())}")
|
2026-05-08 22:30:26 +08:00
|
|
|
|
|
2026-05-07 00:48:17 +08:00
|
|
|
|
graph_builder = build_agent_graph(
|
2026-05-05 17:30:55 +08:00
|
|
|
|
chat_services=self.chat_services,
|
|
|
|
|
|
mem0_client=self.mem0_client
|
|
|
|
|
|
)
|
|
|
|
|
|
self.graph = graph_builder.compile(checkpointer=self.checkpointer)
|
2026-05-08 22:30:26 +08:00
|
|
|
|
|
|
|
|
|
|
self.config = ServiceConfig(self.chat_services)
|
2026-05-07 00:48:17 +08:00
|
|
|
|
info(f"✅ Agent 图初始化完成")
|
2026-05-08 22:30:26 +08:00
|
|
|
|
|
2026-04-21 11:02:16 +08:00
|
|
|
|
return self
|
|
|
|
|
|
|
2026-05-08 22:30:26 +08:00
|
|
|
|
def _resolve_and_build(
|
2026-05-05 17:30:55 +08:00
|
|
|
|
self, message: str, thread_id: str, model: str, user_id: str
|
2026-05-08 22:30:26 +08:00
|
|
|
|
):
|
|
|
|
|
|
"""解析模型并构建调用参数"""
|
|
|
|
|
|
resolved_model = self.config.resolve_model(model)
|
|
|
|
|
|
return resolved_model, self.config.build_invocation(
|
|
|
|
|
|
message, thread_id, resolved_model, user_id
|
|
|
|
|
|
)
|
2026-04-21 11:02:16 +08:00
|
|
|
|
|
2026-05-05 17:30:55 +08:00
|
|
|
|
async def process_message(
|
|
|
|
|
|
self, message: str, thread_id: str, model: str = "", user_id: str = "default_user"
|
|
|
|
|
|
) -> dict:
|
|
|
|
|
|
"""处理用户消息,返回包含回复、token统计和耗时的字典"""
|
2026-05-08 22:30:26 +08:00
|
|
|
|
resolved_model, (config, input_state) = self._resolve_and_build(
|
|
|
|
|
|
message, thread_id, model, user_id
|
|
|
|
|
|
)
|
2026-05-05 17:30:55 +08:00
|
|
|
|
|
|
|
|
|
|
result = await self.graph.ainvoke(input_state, config=config)
|
2026-05-08 02:05:35 +08:00
|
|
|
|
|
|
|
|
|
|
reply = result.get("final_reply", "")
|
|
|
|
|
|
if not reply and result.get("messages"):
|
2026-05-01 00:13:13 +08:00
|
|
|
|
reply = result["messages"][-1].content
|
2026-05-08 02:05:35 +08:00
|
|
|
|
|
2026-04-21 11:02:16 +08:00
|
|
|
|
return {
|
|
|
|
|
|
"reply": reply,
|
2026-05-08 22:30:26 +08:00
|
|
|
|
"token_usage": result.get("last_token_usage", {}),
|
|
|
|
|
|
"elapsed_time": result.get("last_elapsed_time", 0.0),
|
2026-05-08 02:05:35 +08:00
|
|
|
|
"model_used": resolved_model,
|
2026-05-08 22:30:26 +08:00
|
|
|
|
"metadata": result.get("metadata", {}),
|
2026-04-21 11:02:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-05 17:30:55 +08:00
|
|
|
|
async def process_message_stream(
|
|
|
|
|
|
self, message: str, thread_id: str, model: str = "", user_id: str = "default_user"
|
|
|
|
|
|
) -> AsyncGenerator[Dict[str, Any], None]:
|
2026-05-08 22:30:26 +08:00
|
|
|
|
"""流式处理消息"""
|
|
|
|
|
|
resolved_model, (config, input_state) = self._resolve_and_build(
|
|
|
|
|
|
message, thread_id, model, user_id
|
|
|
|
|
|
)
|
2026-05-05 17:30:55 +08:00
|
|
|
|
|
2026-05-07 00:48:17 +08:00
|
|
|
|
info(f"🚀 开始执行 Agent 图,指定模型: {resolved_model}")
|
2026-05-07 02:56:35 +08:00
|
|
|
|
|
2026-05-08 22:30:26 +08:00
|
|
|
|
async for event in run_graph_stream(self.graph, input_state, config):
|
|
|
|
|
|
if event.get("type") != "done":
|
|
|
|
|
|
yield event
|
|
|
|
|
|
else:
|
|
|
|
|
|
yield {**event, "model_used": resolved_model}
|