diff --git a/src/agents/chatbot/graph.py b/src/agents/chatbot/graph.py index 9d4ab4cd..902a4eea 100644 --- a/src/agents/chatbot/graph.py +++ b/src/agents/chatbot/graph.py @@ -51,9 +51,11 @@ class ChatbotAgent(BaseAgent): system_prompt = f"{conf.system_prompt} Now is {get_cur_time_with_utc()}" model = load_chat_model(conf.model) - model_with_tools = model.bind_tools(self._get_tools(conf.tools)) - res = model_with_tools.invoke( + if tools := self._get_tools(conf.tools): + model = model.bind_tools(tools) + + res = model.invoke( [{"role": "system", "content": system_prompt}, *state["messages"]] ) return {"messages": [res]} diff --git a/src/agents/tools_factory.py b/src/agents/tools_factory.py index b93960d5..69c4461c 100644 --- a/src/agents/tools_factory.py +++ b/src/agents/tools_factory.py @@ -81,7 +81,7 @@ def get_all_tools(): # 获取所有知识库 for db_Id, retrieve_info in knowledge_base.get_retrievers().items(): - name = f"retrieve_{retrieve_info['name']}" + name = f"retrieve_{db_Id}" # Deepseek does not support non-alphanumeric characters in tool names description = ( f"使用 {retrieve_info['name']} 知识库进行检索。\n" f"下面是这个知识库的描述:\n{retrieve_info['description']}" diff --git a/web/src/views/AgentView.vue b/web/src/views/AgentView.vue index d8db097d..fa290037 100644 --- a/web/src/views/AgentView.vue +++ b/web/src/views/AgentView.vue @@ -62,6 +62,18 @@

{{ selectedAgent.description }}

{{ selectedAgent }}
+ +
+

所需环境变量:

+
+ + {{ req }} + +
+
+ + +
@@ -78,7 +90,7 @@
-

注意,部分模型对于 Tool Calling 的支持不稳定,建议采用{{ value.options }}

+ - - - + +
+
+ 已选择 {{ getSelectedCount(key) }} 项 + + 清空 + +
+
+
+
+ {{ option }} +
+ + +
+
+
+
+
+ +
@@ -128,15 +164,6 @@
- -
-

所需环境变量:

-
- - {{ req }} - -
-
@@ -163,7 +190,9 @@ import { LinkOutlined, StarOutlined, MenuOutlined, - StarFilled + StarFilled, + CheckCircleOutlined, + PlusCircleOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; import AgentChatComponent from '@/components/AgentChatComponent.vue'; @@ -215,6 +244,42 @@ const setAsDefaultAgent = async () => { } }; +// 多选组件相关方法 +const ensureArray = (key) => { + if (!agentConfig.value[key] || !Array.isArray(agentConfig.value[key])) { + agentConfig.value[key] = []; + } +}; + +const isOptionSelected = (key, option) => { + ensureArray(key); + return agentConfig.value[key].includes(option); +}; + +const getSelectedCount = (key) => { + ensureArray(key); + return agentConfig.value[key].length; +}; + +const toggleOption = (key, option) => { + ensureArray(key); + + const currentOptions = [...agentConfig.value[key]]; + const index = currentOptions.indexOf(option); + + if (index > -1) { + currentOptions.splice(index, 1); + } else { + currentOptions.push(option); + } + + agentConfig.value[key] = currentOptions; +}; + +const clearSelection = (key) => { + agentConfig.value[key] = []; +}; + // 获取默认智能体ID const fetchDefaultAgent = async () => { try { @@ -278,6 +343,9 @@ const loadAgentConfig = async () => { // 根据类型设置默认值 if (typeof item.default === 'boolean') { agentConfig.value[key] = item.default; + } else if (item.type === 'list') { + // 对于 list 类型,确保初始化为数组 + agentConfig.value[key] = Array.isArray(item.default) ? item.default : []; } else { agentConfig.value[key] = item.default || ''; } @@ -290,7 +358,13 @@ const loadAgentConfig = async () => { // 合并服务器配置 Object.keys(response.config).forEach(key => { if (key in agentConfig.value) { - agentConfig.value[key] = response.config[key]; + const item = items[key]; + // 对于 list 类型,确保是数组 + if (item && item.type === 'list') { + agentConfig.value[key] = Array.isArray(response.config[key]) ? response.config[key] : []; + } else { + agentConfig.value[key] = response.config[key]; + } } }); console.log(`从服务器加载 ${selectedAgentId.value} 配置成功, ${JSON.stringify(agentConfig.value)}`); @@ -568,7 +642,6 @@ const toggleSidebar = () => { // 添加requirements相关样式 .info-section { margin-top: 16px; - border-top: 1px solid var(--main-light-3); padding-top: 12px; h3 { @@ -693,6 +766,92 @@ const toggleSidebar = () => { font-size: 14px; } } + +// 多选卡片样式 +.multi-select-cards { + .multi-select-label { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; + font-size: 12px; + color: var(--gray-600); + height: 24px; + } + + .options-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + gap: 8px; + } + + .option-card { + border: 1px solid var(--gray-300); + border-radius: 8px; + padding: 8px 12px; + cursor: pointer; + transition: all 0.2s ease; + background: white; + user-select: none; + + &:hover { + border-color: var(--main-color); + } + + &.selected { + border-color: var(--main-color); + background: var(--main-10); + + .option-indicator { + color: var(--main-color); + } + + .option-text { + color: var(--main-color); + font-weight: 500; + } + } + + &.unselected { + .option-indicator { + color: var(--gray-400); + } + + .option-text { + color: var(--gray-700); + } + } + + .option-content { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; + } + + .option-text { + flex: 1; + font-size: 14px; + line-height: 1.4; + word-break: break-word; + } + + .option-indicator { + flex-shrink: 0; + font-size: 16px; + transition: color 0.2s ease; + } + } +} + +// 响应式适配 +@media (max-width: 768px) { + .multi-select-cards { + .options-grid { + grid-template-columns: 1fr; + } + } +}