refactor(agent): 移除不必要的要求检查,简化 BaseAgent 初始化逻辑;更新工具注册逻辑,添加获取可运行工具信息的功能;重构聊天 API,优化代码结构和可读性。
This commit is contained in:
parent
75c52a3855
commit
9f5924b8e6
@ -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()
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<a-dropdown>
|
||||
<a-dropdown trigger="click">
|
||||
<a class="model-select" @click.prevent>
|
||||
<!-- <BulbOutlined /> -->
|
||||
<a-tooltip :title="model_name" placement="right">
|
||||
@ -84,6 +84,7 @@ const handleSelectModel = (provider, name) => {
|
||||
.model-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user