From 8804c7446c14744c045ca10fbc24ca0b50decaf2 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Fri, 20 Mar 2026 12:38:42 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E5=85=83?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=96=87=E4=BB=B6=EF=BC=8C=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E4=BB=8E=E6=99=BA=E8=83=BD=E4=BD=93=E7=B1=BB=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=85=83=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package/yuxi/agents/base.py | 57 ++++--------------- .../yuxi/agents/buildin/chatbot/graph.py | 9 +++ .../yuxi/agents/buildin/chatbot/metadata.toml | 9 --- backend/server/routers/chat_router.py | 6 +- web/src/components/AgentChatComponent.vue | 2 +- web/src/components/AgentConfigSidebar.vue | 8 --- 6 files changed, 23 insertions(+), 68 deletions(-) delete mode 100644 backend/package/yuxi/agents/buildin/chatbot/metadata.toml diff --git a/backend/package/yuxi/agents/base.py b/backend/package/yuxi/agents/base.py index 3084779a..dfc7c6f0 100644 --- a/backend/package/yuxi/agents/base.py +++ b/backend/package/yuxi/agents/base.py @@ -1,9 +1,7 @@ from __future__ import annotations import asyncio -import importlib.util import os -import tomllib as tomli from abc import abstractmethod from inspect import isawaitable from pathlib import Path @@ -34,7 +32,6 @@ class BaseAgent: self._async_conn = None self.workdir = Path(sys_config.save_dir) / "agents" / self.module_name self.workdir.mkdir(parents=True, exist_ok=True) - self._metadata_cache = None # Cache for metadata to avoid repeated file reads @property def module_name(self) -> str: @@ -47,7 +44,7 @@ class BaseAgent: return self.__class__.__name__ async def get_info(self, include_configurable_items: bool = True): - # Load metadata from file + # metadata 固定在代码中,由各 Agent 的类属性提供 metadata = self.load_metadata() configurable_items = {} if include_configurable_items: @@ -56,11 +53,11 @@ class BaseAgent: # Merge metadata with class attributes, metadata takes precedence return { "id": self.id, - "name": metadata.get("name", getattr(self, "name", "Unknown")), - "description": metadata.get("description", getattr(self, "description", "Unknown")), - "examples": metadata.get("examples", []), + "name": getattr(self, "name", "Unknown"), + "description": getattr(self, "description", "Unknown"), + "metadata": metadata, + # "examples": metadata.get("examples", []), "configurable_items": configurable_items, - "has_checkpointer": await self.check_checkpointer(), "capabilities": getattr(self, "capabilities", []), # 智能体能力列表 } @@ -116,7 +113,6 @@ class BaseAgent: async def check_checkpointer(self): app = await self.get_graph() if not hasattr(app, "checkpointer") or app.checkpointer is None: - logger.warning(f"智能体 {self.name} 的 Graph 未配置 checkpointer,无法获取历史记录") return False return True @@ -253,40 +249,9 @@ class BaseAgent: return AsyncSqliteSaver(await self.get_async_conn()) def load_metadata(self) -> dict: - """Load metadata from metadata.toml file in the agent's source directory.""" - if self._metadata_cache is not None: - return self._metadata_cache - - # Try to find metadata.toml in the agent's source directory - try: - # Get the agent's source file directory - agent_module = self.__class__.__module__ - - # Use importlib to get the module's file path - spec = importlib.util.find_spec(agent_module) - if spec and spec.origin: - agent_file = Path(spec.origin) - agent_dir = agent_file.parent - else: - # Fallback: construct path from module name - module_path = agent_module.replace(".", "/") - agent_file = Path(f"package/yuxi/{module_path}.py") - agent_dir = agent_file.parent - - metadata_file = agent_dir / "metadata.toml" - - if metadata_file.exists(): - with open(metadata_file, "rb") as f: - metadata = tomli.load(f) - self._metadata_cache = metadata - logger.debug(f"Loaded metadata from {metadata_file}") - return metadata - else: - logger.debug(f"No metadata.toml found for {self.module_name} at {metadata_file}") - self._metadata_cache = {} - return {} - - except Exception as e: - logger.error(f"Error loading metadata for {self.module_name}: {e}") - self._metadata_cache = {} - return {} + """Load metadata from agent class attribute.""" + metadata = getattr(self, "metadata", {}) + if isinstance(metadata, dict): + return metadata + logger.warning(f"Agent {self.module_name} metadata is not a dict, fallback to empty metadata") + return {} diff --git a/backend/package/yuxi/agents/buildin/chatbot/graph.py b/backend/package/yuxi/agents/buildin/chatbot/graph.py index a2ba8d55..39ef8086 100644 --- a/backend/package/yuxi/agents/buildin/chatbot/graph.py +++ b/backend/package/yuxi/agents/buildin/chatbot/graph.py @@ -29,6 +29,15 @@ class ChatbotAgent(BaseAgent): name = "智能体助手" description = "基础的对话机器人,可以回答问题,可在配置中启用需要的工具。" capabilities = ["file_upload", "files", "todo"] # 支持文件上传功能 + metadata = { + "examples": [ + "你好,请介绍一下你自己", + "帮我写一封商务邮件", + "解释一下什么是机器学习", + "推荐几本好书", + "如何提高工作效率?" + ] + } def __init__(self, **kwargs): super().__init__(**kwargs) diff --git a/backend/package/yuxi/agents/buildin/chatbot/metadata.toml b/backend/package/yuxi/agents/buildin/chatbot/metadata.toml deleted file mode 100644 index dbb2ed9c..00000000 --- a/backend/package/yuxi/agents/buildin/chatbot/metadata.toml +++ /dev/null @@ -1,9 +0,0 @@ -name = "智能聊天助手" -description = "基础的AI对话助手,支持工具调用,MCP,并具备丰富的知识库。" -examples = [ - "你好,请介绍一下你自己", - "帮我写一封商务邮件", - "解释一下什么是机器学习", - "推荐几本好书", - "如何提高工作效率?" -] \ No newline at end of file diff --git a/backend/server/routers/chat_router.py b/backend/server/routers/chat_router.py index 8284a4a2..e375d94c 100644 --- a/backend/server/routers/chat_router.py +++ b/backend/server/routers/chat_router.py @@ -159,8 +159,7 @@ async def get_agent(current_user: User = Depends(get_required_user)): "id": agent_info["id"], "name": agent_info.get("name", "Unknown"), "description": agent_info.get("description", ""), - "examples": agent_info.get("examples", []), - "has_checkpointer": agent_info.get("has_checkpointer", False), + "metadata": agent_info.get("metadata", {}), "capabilities": agent_info.get("capabilities", []), # 智能体能力列表 } for agent_info in agents_info @@ -184,9 +183,8 @@ async def get_single_agent(agent_id: str, current_user: User = Depends(get_requi "id": agent_info["id"], "name": agent_info.get("name", "Unknown"), "description": agent_info.get("description", ""), - "examples": agent_info.get("examples", []), + "metadata": agent_info.get("metadata", {}), "configurable_items": agent_info.get("configurable_items", []), - "has_checkpointer": agent_info.get("has_checkpointer", False), "capabilities": agent_info.get("capabilities", []), } diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index ab9eac6b..f334da94 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -286,7 +286,7 @@ const exampleQuestions = computed(() => { let examples = [] if (agentId && agents.value && agents.value.length > 0) { const agent = agents.value.find((a) => a.id === agentId) - examples = agent ? agent.examples || [] : [] + examples = agent ? agent.metadata?.examples || [] : [] } return examples.map((text, index) => ({ id: index + 1, diff --git a/web/src/components/AgentConfigSidebar.vue b/web/src/components/AgentConfigSidebar.vue index b29f299d..3add54b6 100644 --- a/web/src/components/AgentConfigSidebar.vue +++ b/web/src/components/AgentConfigSidebar.vue @@ -71,14 +71,6 @@ show-icon class="config-alert" /> - -