feat: 使用 create_agent 接口替换老版本的 create_react_agent

This commit is contained in:
Wenjie Zhang 2025-10-25 20:01:23 +08:00
parent fdc4f174a9
commit a8491c5beb
6 changed files with 54 additions and 42 deletions

View File

@ -11,16 +11,13 @@
## Next
- [ ] 修改现有的智能体Demo并尽量将默认助手的特性兼容到 LangGraph 的 [`create_agent`](https://docs.langchain.com/oss/python/langchain/agents) 中
- [x] 修改现有的智能体Demo并尽量将默认助手的特性兼容到 LangGraph 的 [`create_agent`](https://docs.langchain.com/oss/python/langchain/agents) 中
- [ ] 基于 create_agent 创建 SQL Viewer 智能体 <Badge type="info" text="0.3.5" />
- [ ] 优化 MCP 逻辑,支持 common + special 创建方式 <Badge type="info" text="0.3.5" />
- [ ] 添加对于上传文件的支持
- [ ] 统一图谱数据结构,优化可视化方式 [#298](https://github.com/xerrors/Yuxi-Know/issues/298) <Badge type="info" text="0.4" />
- [ ] 集成智能体评估,首先使用命令行来实现,然后考虑放在 UI 里面展示
- [ ] 开发与生产环境隔离,构建生产镜像 <Badge type="info" text="0.4" />
- [x] 支持 MinerU 2.5 的解析方法 <Badge type="info" text="0.3.5" />
- [x] 文件管理1文件选择的时候会跨数据库2文件校验会算上失败的文件
- [x] Tasker 中获取历史任务的时候,仅获取 top100 个 task。
## Later
@ -37,3 +34,6 @@
- [x] 优化对文档信息的检索展示(检索结果页、详情页)
- [x] 当前 ReAct 智能体有消息顺序错乱的 bug且不会默认调用工具
- [x] 优化全局配置的管理模型,优化配置管理
- [x] 支持 MinerU 2.5 的解析方法 <Badge type="info" text="0.3.5" />
- [x] 文件管理1文件选择的时候会跨数据库2文件校验会算上失败的文件
- [x] Tasker 中获取历史任务的时候,仅获取 top100 个 task。

View File

@ -10,11 +10,6 @@ from .tools import get_tools
@dataclass(kw_only=True)
class Context(BaseContext):
model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
default="siliconflow/Qwen/Qwen3-235B-A22B-Instruct-2507",
metadata={"name": "智能体模型", "options": [], "description": "智能体的驱动模型"},
)
tools: Annotated[list[dict], {"__template_metadata__": {"kind": "tools"}}] = field(
default_factory=list,
metadata={

View File

@ -1,12 +1,10 @@
"""Define the configurable parameters for the agent."""
from __future__ import annotations
import os
import uuid
from dataclasses import MISSING, dataclass, field, fields
from pathlib import Path
from typing import get_args, get_origin
from typing import Annotated, get_args, get_origin
import yaml
@ -46,8 +44,13 @@ class BaseContext:
metadata={"name": "系统提示词", "description": "用来描述智能体的角色和行为"},
)
model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
default="siliconflow/Qwen/Qwen3-235B-A22B-Instruct-2507",
metadata={"name": "智能体模型", "options": [], "description": "智能体的驱动模型"},
)
@classmethod
def from_file(cls, module_name: str, input_context: dict = None) -> BaseContext:
def from_file(cls, module_name: str, input_context: dict = None) -> "BaseContext":
"""Load configuration from a YAML file. 用于持久化配置"""
# 从文件加载配置

View File

@ -1,12 +1,10 @@
from pathlib import Path
from langchain.messages import AnyMessage, SystemMessage
from langgraph.prebuilt import create_react_agent
from langgraph.runtime import get_runtime
from langchain.agents import create_agent
from langchain.agents.middleware import ModelRequest, ModelResponse, dynamic_prompt, wrap_model_call
from src import config as sys_config
from src.agents.common.base import BaseAgent
from src.agents.common.context import BaseContext
from src.agents.common.models import load_chat_model
from src.agents.common.tools import get_buildin_tools
from src.utils import logger
@ -14,14 +12,24 @@ from src.utils import logger
model = load_chat_model("siliconflow/Qwen/Qwen3-235B-A22B-Instruct-2507")
def prompt(state) -> list[AnyMessage]:
runtime = get_runtime(BaseContext)
system_msg = SystemMessage(content=runtime.context.system_prompt)
return [system_msg] + state["messages"]
@dynamic_prompt
def context_aware_prompt(request: ModelRequest) -> str:
runtime = request.runtime
return runtime.context.system_prompt
@wrap_model_call
async def context_based_model(request: ModelRequest, handler) -> ModelResponse:
# 从 runtime context 读取配置
model_spec = request.runtime.context.model
model = load_chat_model(model_spec)
request = request.override(model=model)
return await handler(request)
class ReActAgent(BaseAgent):
name = "ReAct (all tools)"
name = "智能体 Demo"
description = "A react agent that can answer questions and help with tasks."
def __init__(self, **kwargs):
@ -30,15 +38,21 @@ class ReActAgent(BaseAgent):
self.workdir = Path(sys_config.save_dir) / "agents" / self.module_name
self.workdir.mkdir(parents=True, exist_ok=True)
def get_tools(self):
return get_buildin_tools()
async def get_graph(self, **kwargs):
if self.graph:
return self.graph
available_tools = get_buildin_tools()
self.checkpointer = await self._get_checkpointer()
# 创建 ReActAgent
graph = create_react_agent(model, tools=available_tools, prompt=prompt, checkpointer=self.checkpointer)
graph = create_agent(
model=model,
tools=self.get_tools(),
middleware=[context_aware_prompt, context_based_model],
checkpointer=await self._get_checkpointer(),
)
self.graph = graph
logger.info("ReActAgent 使用内存 checkpointer 构建成功")
return graph

View File

@ -46,21 +46,21 @@ class KnowledgeBaseManager:
logger.info("KnowledgeBaseManager initialized")
# 在后台运行数据一致性检测(不阻塞初始化)
try:
# 尝试获取当前事件循环,如果没有则创建新的
try:
loop = asyncio.get_event_loop()
if loop.is_running():
# 如果已经在事件循环中,创建任务
asyncio.create_task(self.detect_data_inconsistencies())
else:
# 如果事件循环未运行,直接运行
loop.run_until_complete(self.detect_data_inconsistencies())
except RuntimeError:
# 没有事件循环,创建一个来运行检测
asyncio.run(self.detect_data_inconsistencies())
except Exception as e:
logger.warning(f"初始化时运行数据一致性检测失败: {e}")
# try:
# # 尝试获取当前事件循环,如果没有则创建新的
# try:
# loop = asyncio.get_event_loop()
# if loop.is_running():
# # 如果已经在事件循环中,创建任务
# asyncio.create_task(self.detect_data_inconsistencies())
# else:
# # 如果事件循环未运行,直接运行
# loop.run_until_complete(self.detect_data_inconsistencies())
# except RuntimeError:
# # 没有事件循环,创建一个来运行检测
# asyncio.run(self.detect_data_inconsistencies())
# except Exception as e:
# logger.warning(f"初始化时运行数据一致性检测失败: {e}")
def _load_global_metadata(self):
"""加载全局元数据"""

View File

@ -18,7 +18,7 @@
<!-- 侧边栏内容 -->
<div class="sidebar-content">
<div class="agent-info" v-if="selectedAgent">
<div class="agent-basic-info">
<div class="agent-basic-info" @click="console.log(configurableItems)">
<p class="agent-description">{{ selectedAgent.description }}</p>
</div>