refactor: 移除元数据文件,改为从智能体类属性加载元数据,并更新相关引用
This commit is contained in:
parent
1bc6285fb1
commit
8804c7446c
@ -1,9 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import importlib.util
|
|
||||||
import os
|
import os
|
||||||
import tomllib as tomli
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from inspect import isawaitable
|
from inspect import isawaitable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -34,7 +32,6 @@ class BaseAgent:
|
|||||||
self._async_conn = None
|
self._async_conn = None
|
||||||
self.workdir = Path(sys_config.save_dir) / "agents" / self.module_name
|
self.workdir = Path(sys_config.save_dir) / "agents" / self.module_name
|
||||||
self.workdir.mkdir(parents=True, exist_ok=True)
|
self.workdir.mkdir(parents=True, exist_ok=True)
|
||||||
self._metadata_cache = None # Cache for metadata to avoid repeated file reads
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module_name(self) -> str:
|
def module_name(self) -> str:
|
||||||
@ -47,7 +44,7 @@ class BaseAgent:
|
|||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
async def get_info(self, include_configurable_items: bool = True):
|
async def get_info(self, include_configurable_items: bool = True):
|
||||||
# Load metadata from file
|
# metadata 固定在代码中,由各 Agent 的类属性提供
|
||||||
metadata = self.load_metadata()
|
metadata = self.load_metadata()
|
||||||
configurable_items = {}
|
configurable_items = {}
|
||||||
if include_configurable_items:
|
if include_configurable_items:
|
||||||
@ -56,11 +53,11 @@ class BaseAgent:
|
|||||||
# Merge metadata with class attributes, metadata takes precedence
|
# Merge metadata with class attributes, metadata takes precedence
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"name": metadata.get("name", getattr(self, "name", "Unknown")),
|
"name": getattr(self, "name", "Unknown"),
|
||||||
"description": metadata.get("description", getattr(self, "description", "Unknown")),
|
"description": getattr(self, "description", "Unknown"),
|
||||||
"examples": metadata.get("examples", []),
|
"metadata": metadata,
|
||||||
|
# "examples": metadata.get("examples", []),
|
||||||
"configurable_items": configurable_items,
|
"configurable_items": configurable_items,
|
||||||
"has_checkpointer": await self.check_checkpointer(),
|
|
||||||
"capabilities": getattr(self, "capabilities", []), # 智能体能力列表
|
"capabilities": getattr(self, "capabilities", []), # 智能体能力列表
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +113,6 @@ class BaseAgent:
|
|||||||
async def check_checkpointer(self):
|
async def check_checkpointer(self):
|
||||||
app = await self.get_graph()
|
app = await self.get_graph()
|
||||||
if not hasattr(app, "checkpointer") or app.checkpointer is None:
|
if not hasattr(app, "checkpointer") or app.checkpointer is None:
|
||||||
logger.warning(f"智能体 {self.name} 的 Graph 未配置 checkpointer,无法获取历史记录")
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -253,40 +249,9 @@ class BaseAgent:
|
|||||||
return AsyncSqliteSaver(await self.get_async_conn())
|
return AsyncSqliteSaver(await self.get_async_conn())
|
||||||
|
|
||||||
def load_metadata(self) -> dict:
|
def load_metadata(self) -> dict:
|
||||||
"""Load metadata from metadata.toml file in the agent's source directory."""
|
"""Load metadata from agent class attribute."""
|
||||||
if self._metadata_cache is not None:
|
metadata = getattr(self, "metadata", {})
|
||||||
return self._metadata_cache
|
if isinstance(metadata, dict):
|
||||||
|
return metadata
|
||||||
# Try to find metadata.toml in the agent's source directory
|
logger.warning(f"Agent {self.module_name} metadata is not a dict, fallback to empty metadata")
|
||||||
try:
|
return {}
|
||||||
# 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 {}
|
|
||||||
|
|||||||
@ -29,6 +29,15 @@ class ChatbotAgent(BaseAgent):
|
|||||||
name = "智能体助手"
|
name = "智能体助手"
|
||||||
description = "基础的对话机器人,可以回答问题,可在配置中启用需要的工具。"
|
description = "基础的对话机器人,可以回答问题,可在配置中启用需要的工具。"
|
||||||
capabilities = ["file_upload", "files", "todo"] # 支持文件上传功能
|
capabilities = ["file_upload", "files", "todo"] # 支持文件上传功能
|
||||||
|
metadata = {
|
||||||
|
"examples": [
|
||||||
|
"你好,请介绍一下你自己",
|
||||||
|
"帮我写一封商务邮件",
|
||||||
|
"解释一下什么是机器学习",
|
||||||
|
"推荐几本好书",
|
||||||
|
"如何提高工作效率?"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
name = "智能聊天助手"
|
|
||||||
description = "基础的AI对话助手,支持工具调用,MCP,并具备丰富的知识库。"
|
|
||||||
examples = [
|
|
||||||
"你好,请介绍一下你自己",
|
|
||||||
"帮我写一封商务邮件",
|
|
||||||
"解释一下什么是机器学习",
|
|
||||||
"推荐几本好书",
|
|
||||||
"如何提高工作效率?"
|
|
||||||
]
|
|
||||||
@ -159,8 +159,7 @@ async def get_agent(current_user: User = Depends(get_required_user)):
|
|||||||
"id": agent_info["id"],
|
"id": agent_info["id"],
|
||||||
"name": agent_info.get("name", "Unknown"),
|
"name": agent_info.get("name", "Unknown"),
|
||||||
"description": agent_info.get("description", ""),
|
"description": agent_info.get("description", ""),
|
||||||
"examples": agent_info.get("examples", []),
|
"metadata": agent_info.get("metadata", {}),
|
||||||
"has_checkpointer": agent_info.get("has_checkpointer", False),
|
|
||||||
"capabilities": agent_info.get("capabilities", []), # 智能体能力列表
|
"capabilities": agent_info.get("capabilities", []), # 智能体能力列表
|
||||||
}
|
}
|
||||||
for agent_info in agents_info
|
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"],
|
"id": agent_info["id"],
|
||||||
"name": agent_info.get("name", "Unknown"),
|
"name": agent_info.get("name", "Unknown"),
|
||||||
"description": agent_info.get("description", ""),
|
"description": agent_info.get("description", ""),
|
||||||
"examples": agent_info.get("examples", []),
|
"metadata": agent_info.get("metadata", {}),
|
||||||
"configurable_items": agent_info.get("configurable_items", []),
|
"configurable_items": agent_info.get("configurable_items", []),
|
||||||
"has_checkpointer": agent_info.get("has_checkpointer", False),
|
|
||||||
"capabilities": agent_info.get("capabilities", []),
|
"capabilities": agent_info.get("capabilities", []),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -286,7 +286,7 @@ const exampleQuestions = computed(() => {
|
|||||||
let examples = []
|
let examples = []
|
||||||
if (agentId && agents.value && agents.value.length > 0) {
|
if (agentId && agents.value && agents.value.length > 0) {
|
||||||
const agent = agents.value.find((a) => a.id === agentId)
|
const agent = agents.value.find((a) => a.id === agentId)
|
||||||
examples = agent ? agent.examples || [] : []
|
examples = agent ? agent.metadata?.examples || [] : []
|
||||||
}
|
}
|
||||||
return examples.map((text, index) => ({
|
return examples.map((text, index) => ({
|
||||||
id: index + 1,
|
id: index + 1,
|
||||||
|
|||||||
@ -71,14 +71,6 @@
|
|||||||
show-icon
|
show-icon
|
||||||
class="config-alert"
|
class="config-alert"
|
||||||
/>
|
/>
|
||||||
<a-alert
|
|
||||||
v-if="!selectedAgent.has_checkpointer"
|
|
||||||
type="error"
|
|
||||||
message="该智能体没有配置 Checkpointer,功能无法正常使用"
|
|
||||||
show-icon
|
|
||||||
class="config-alert"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 统一显示所有配置项 -->
|
<!-- 统一显示所有配置项 -->
|
||||||
<template v-for="(value, key) in configurableItems" :key="key">
|
<template v-for="(value, key) in configurableItems" :key="key">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user