diff --git a/src/agents/registry.py b/src/agents/registry.py index dad31457..e3ee149f 100644 --- a/src/agents/registry.py +++ b/src/agents/registry.py @@ -285,10 +285,9 @@ class BaseAgent: name = "base_agent" description = "base_agent" config_schema: Configuration = Configuration - requirements: list[str] def __init__(self, **kwargs): - self.check_requirements() + pass @property def module_name(self) -> str: @@ -306,19 +305,11 @@ class BaseAgent: "name": self.name if hasattr(self, "name") else "Unknown", "description": self.description if hasattr(self, "description") else "Unknown", "config_schema": self.config_schema.to_dict(), - "requirements": self.requirements if hasattr(self, "requirements") else [], "all_tools": self.all_tools if hasattr(self, "all_tools") else [], "has_checkpointer": await self.check_checkpointer(), - "met_requirements": self.check_requirements(), } - def check_requirements(self): - if not hasattr(self, "requirements") or not self.requirements: - return True - for requirement in self.requirements: - if requirement not in os.environ: - raise ValueError(f"没有配置{requirement} 环境变量,请在 src/.env 文件中配置,并重新启动服务") - return True + async def stream_values(self, messages: list[str], config_schema: RunnableConfig = None, **kwargs): graph = await self.get_graph() diff --git a/src/agents/tools_factory.py b/src/agents/tools_factory.py index d168a127..4ebc2d4b 100644 --- a/src/agents/tools_factory.py +++ b/src/agents/tools_factory.py @@ -1,5 +1,7 @@ import json import asyncio +import inspect +import types from collections.abc import Callable from typing import Annotated, Any @@ -11,6 +13,10 @@ from src import config, graph_base, knowledge_base from src.utils import logger +# 工具注册表 - 移到前面以避免NameError +_TOOLS_REGISTRY = {} + + class KnowledgeRetrieverModel(BaseModel): query_text: str = Field( description=( @@ -19,13 +25,13 @@ class KnowledgeRetrieverModel(BaseModel): ) ) -def get_all_tools(): - """获取所有工具""" +def get_runnable_tools(): + """获取所有可运行的工具(给大模型使用)""" tools = _TOOLS_REGISTRY.copy() # 获取所有知识库 for db_Id, retrieve_info in knowledge_base.get_retrievers().items(): - name = f"retrieve_{db_Id[:8]}" # Deepseek does not support non-alphanumeric characters in tool names + _id = f"retrieve_{db_Id[:8]}" # Deepseek does not support non-alphanumeric characters in tool names description = ( f"使用 {retrieve_info['name']} 知识库进行检索。\n" f"下面是这个知识库的描述:\n{retrieve_info['description']}" @@ -46,15 +52,48 @@ def get_all_tools(): return f"检索失败: {str(e)}" # 使用 StructuredTool.from_function 创建异步工具 - tools[name] = StructuredTool.from_function( + tools[_id] = StructuredTool.from_function( coroutine=async_retriever_wrapper, # 指定为协程 - name=name, + name=_id, description=description, - args_schema=KnowledgeRetrieverModel + args_schema=KnowledgeRetrieverModel, + metadata=retrieve_info ) return tools +def get_all_tools_info(): + """获取所有工具的信息(用于前端展示)""" + tools_info = {} + + tools = get_runnable_tools() + + # 获取注册的工具信息 + for _id, tool_obj in tools.items(): + + metadata = getattr(tool_obj, 'metadata', {}) or {} + info = { + "id": _id, + "name": metadata.get('name', _id), + "description": metadata.get('description') or getattr(tool_obj, 'description', ''), + 'metadata': metadata, + "args": [] + } + + # 获取工具参数信息 + if hasattr(tool_obj, 'args_schema') and tool_obj.args_schema: + schema = tool_obj.args_schema.schema() + if 'properties' in schema: + for arg_name, arg_info in schema['properties'].items(): + info["args"].append({ + "name": arg_name, + "type": arg_info.get('type', ''), + "description": arg_info.get('description', '') + }) + tools_info[info['id']] = info + + return tools_info + class BaseToolOutput: """ LLM 要求 Tool 的输出为 str,但 Tool 用在别处时希望它正常返回结构化数据。 @@ -103,13 +142,11 @@ def query_knowledge_graph(query: Annotated[str, "The keyword to query knowledge """Use this to query knowledge graph.""" return graph_base.query_node(query, hops=2) - - - -_TOOLS_REGISTRY = { +# 更新工具注册表 +_TOOLS_REGISTRY.update({ "Calculator": calculator, "QueryKnowledgeGraph": query_knowledge_graph, -} +}) if config.enable_web_search: _TOOLS_REGISTRY["WebSearchWithTavily"] = TavilySearch(max_results=10) diff --git a/web/src/apis/auth_api.js b/web/src/apis/auth_api.js index 743bfe5f..69e93641 100644 --- a/web/src/apis/auth_api.js +++ b/web/src/apis/auth_api.js @@ -9,39 +9,6 @@ import { useUserStore } from '@/stores/user' // 聊天相关API export const chatApi = { - /** - * 发送聊天消息 - * @param {Object} params - 聊天参数 - * @returns {Promise} - 聊天响应流 - */ - sendMessage: (params) => { - return fetch('/api/chat/', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...useUserStore().getAuthHeaders() - }, - body: JSON.stringify(params), - }) - }, - - /** - * 发送可中断的聊天消息 - * @param {Object} params - 聊天参数 - * @param {AbortSignal} signal - 用于中断请求的信号控制器 - * @returns {Promise} - 聊天响应流 - */ - sendMessageWithAbort: (params, signal) => { - return fetch('/api/chat/', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...useUserStore().getAuthHeaders() - }, - body: JSON.stringify(params), - signal // 添加 signal 用于中断请求 - }) - }, /** * 发送聊天消息到指定智能体(流式响应) @@ -105,13 +72,7 @@ export const chatApi = { * @param {string} provider - 模型提供商 * @returns {Promise} - 模型列表 */ - getProviderModels: (provider) => { - return fetch(`/api/chat/models?model_provider=${provider}`, { - headers: { - ...useUserStore().getAuthHeaders() - } - }).then(response => response.json()) - }, + getProviderModels: (provider) => apiGet(`/api/chat/models?model_provider=${provider}`, {}, true), /** * 更新模型提供商的模型列表 @@ -119,16 +80,7 @@ export const chatApi = { * @param {Array} models - 选中的模型列表 * @returns {Promise} - 更新结果 */ - updateProviderModels: (provider, models) => { - return fetch(`/api/chat/models/update?model_provider=${provider}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...useUserStore().getAuthHeaders() - }, - body: JSON.stringify(models) - }).then(response => response.json()) - } + updateProviderModels: (provider, models) => apiPost(`/api/chat/models/update?model_provider=${provider}`, models, {}, true) } // 用户设置API diff --git a/web/src/apis/knowledge_api.js b/web/src/apis/knowledge_api.js index 52cf1cc3..0451b2e1 100644 --- a/web/src/apis/knowledge_api.js +++ b/web/src/apis/knowledge_api.js @@ -179,14 +179,14 @@ export const fileApi = { */ uploadFile: async (file, dbId = null) => { checkAdminPermission() - + const formData = new FormData() formData.append('file', file) - - const url = dbId + + const url = dbId ? `/api/knowledge/files/upload?db_id=${dbId}` : '/api/knowledge/files/upload' - + return apiPost(url, formData, { headers: { 'Content-Type': 'multipart/form-data' @@ -219,4 +219,3 @@ export const typeApi = { } } - \ No newline at end of file diff --git a/web/src/apis/system_api.js b/web/src/apis/system_api.js index b4361c59..a3530934 100644 --- a/web/src/apis/system_api.js +++ b/web/src/apis/system_api.js @@ -177,7 +177,7 @@ export const agentConfigApi = { */ setDefaultAgent: async (agentId) => { checkAdminPermission() - return apiPost('/api/chat/agent/default', { agent_id: agentId }, {}, true) + return apiPost('/api/chat/set_default_agent', { agent_id: agentId }, {}, true) } } diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue deleted file mode 100644 index 97c3addb..00000000 --- a/web/src/components/ChatComponent.vue +++ /dev/null @@ -1,1158 +0,0 @@ - - - - - - - - - - - diff --git a/web/src/components/ModelSelectorComponent.vue b/web/src/components/ModelSelectorComponent.vue index 7b2b090d..4d350491 100644 --- a/web/src/components/ModelSelectorComponent.vue +++ b/web/src/components/ModelSelectorComponent.vue @@ -1,5 +1,5 @@