# 背景 文件名:2025-11-20_2_add_user_tools_to_ai.md 创建于:2025-11-20_15:25:43 创建者:admin 主分支:main 任务分支:无(不创建分支) Yolo模式:Off # 任务描述 为 AI 聊天插件(ChatAI.py)添加用户 ID 与用户名转换的工具调用功能,让 AI 能够主动查询用户信息。 ## 具体需求 1. AI 应该能够通过工具调用实现以下功能: - 根据 user_id 查询 username - 根据 username 查询 user_id - 查询所有存在的 username 列表 2. 使用 LlamaIndex 框架的高级功能(FunctionTool + AgentWorkflow + ReActAgent) 3. 参考 NewsReport.py 的工具调用架构实现 # 项目概览 - **项目**:NewWPSBot - **相关文件**: - `Plugins/Others/ChatAI.py` - AI 对话插件(需要改造) - `Plugins/WPSConfigSystem.py` - 用户配置系统(需要添加查询所有用户名的方法) - `Plugins/Others/NewsReport.py` - 参考实现(已实现工具调用) # 分析 ## WPSConfigSystem.py 现状 - ✅ 已有方法:`get_user_name(user_id: int)` - 第201-206行 - ✅ 已有方法:`find_user_id_by_username(username: str)` - 第238-248行 - ❌ 缺失方法:查询所有用户名列表 - 数据表:`user_info` (user_id, username, userurl, userpoint) ## ChatAI.py 现状(第1-428行) - 当前使用简单的 `Ollama` LLM + `ChatMessage` 架构 - 通过 `llm.achat()` 进行对话 - **没有工具调用能力** - 维护全局历史 `global_history` - 单例模式:`ChatAIAgent.get_instance()` ## NewsReport.py 工具调用架构(参考) ```python # 1. 导入 from llama_index.core.tools import FunctionTool from llama_index.core.agent.workflow import AgentWorkflow from llama_index.core.agent.workflow.react_agent import ReActAgent # 2. 创建工具 tools = [ FunctionTool.from_defaults( fn=self._tool_function, name="tool_name", description="工具描述" ), ] # 3. 创建 Agent agent = ReActAgent( llm=self.llm, tools=tools, verbose=True, system_prompt=system_prompt, ) # 4. 创建 Workflow self.workflow = AgentWorkflow( agents=[agent], timeout=600.0, ) # 5. 执行 result = await self.workflow.run(user_msg=query) ``` ## 技术要点 1. **工具函数必须是同步函数**(从 NewsReport.py 看,工具函数如 `_get_current_date()` 都是同步的) 2. **WPSConfigAPI 需要通过 Architecture.Get() 获取** 3. **系统提示词需要明确指导 AI 何时使用工具** 4. **需要保留现有的历史消息管理功能** # 提议的解决方案 ## 方案探索(INNOVATE 阶段) ### 方案A:完全重构为 ReActAgent 架构 ⭐ 推荐 **架构设计**: - 移除 `llm.achat()` 调用方式 - 使用 `AgentWorkflow` + `ReActAgent` - 历史消息通过系统提示词传递 - 工具函数独立实现 **优势**: - 与 NewsReport.py 架构统一,易于维护 - ReActAgent 专门为工具调用优化 - 工具调用日志清晰(verbose=True) - 扩展性强,易于添加新工具 **劣势**: - 需要大幅度重构现有代码 - 历史消息管理方式需改变 - qwen3:0.6b 小模型的工具调用能力需验证 **关键改进**: - 保留历史消息数组结构,调用时转换为提示词 - 添加错误处理和降级机制 - 可根据消息内容智能决定是否启用工具 --- ### 方案B:混合架构 - 保留对话 + 添加工具层 **架构设计**: - 保留 `llm.achat()` 作为主要对话方式 - AI 在回复中使用特殊标记触发工具(如 `[TOOL:get_username:123]`) - 后处理解析工具调用并再次调用 LLM **优势**: - 改动最小,风险低 - 保留现有历史消息机制 - 对话连贯性不受影响 **劣势**: - 需要自定义工具调用协议 - 可能需要多轮 LLM 调用 - 工具调用智能程度较低 --- ### 方案C:双智能体架构 **架构设计**: - ToolAgent(ReActAgent)专门处理工具调用 - ChatAgent(现有架构)处理普通对话 - 路由逻辑判断使用哪个智能体 **优势**:职责分离,灵活性高 **劣势**:架构复杂,维护成本高,上下文共享困难 --- ### 方案D:轻量级工具注入 **架构设计**: - 预处理:分析消息,预先调用工具 - 将工具结果注入到提示词 - 正常调用 `llm.achat()` **优势**:改动极小,性能影响最小 **劣势**:AI 无法主动决定使用工具,智能程度低 --- ## 最终推荐方案:方案A(ReActAgent 架构) ### 实施要点 #### 1. 在 WPSConfigSystem.py 添加方法 ```python def get_all_usernames(self) -> List[Dict[str, Any]]: """获取所有用户名列表""" cursor = get_db().conn.cursor() cursor.execute( "SELECT user_id, username FROM user_info WHERE username != '' AND username IS NOT NULL" ) rows = cursor.fetchall() return [{"user_id": row["user_id"], "username": row["username"]} for row in rows] ``` #### 2. 改造 ChatAI.py **导入新增**: ```python from llama_index.core.tools import FunctionTool from llama_index.core.agent.workflow import AgentWorkflow from llama_index.core.agent.workflow.react_agent import ReActAgent from PWF.Convention.Runtime.Architecture import Architecture ``` **添加 `_initialize_agent()` 方法**: - 获取 WPSConfigAPI 实例 - 创建三个工具函数 - 初始化 ReActAgent - 创建 AgentWorkflow **工具函数**: 1. `get_username_by_id(user_id: int) -> str` 2. `get_userid_by_name(username: str) -> str` 3. `list_all_usernames() -> str` **修改 `chat()` 方法**: - 将历史消息格式化为提示词 - 使用 `await self.workflow.run(user_msg=...)` - 保留历史消息管理逻辑 - 添加错误处理 **更新系统提示词**: - 告知 AI 可用的三个工具 - 说明工具使用场景和时机 - 保持原有的 @用户 格式规则 ### 技术挑战与解决方案 1. **历史消息管理**:保留数组结构,调用时动态转换 2. **WPSConfigAPI 访问**:在 `_initialize_agent()` 中通过 Architecture.Get() 获取 3. **错误处理**:工具调用失败时返回友好提示,不中断对话 4. **模型兼容性**:测试 qwen3:0.6b 的工具调用能力,必要时提供降级方案 # 当前执行步骤:"4. 执行完成,等待测试" # 任务进度 ## [2025-11-20_15:25:43] - 状态:研究完成 - 已完成: - 分析 WPSConfigSystem.py 现有功能 - 分析 ChatAI.py 当前架构 - 研究 NewsReport.py 工具调用实现 - 创建任务文件 - 下一步:进入 INNOVATE 模式 ## [2025-11-20_15:30:00] - 状态:创新完成 - 已完成: - 探索了 4 种技术方案(ReActAgent、混合架构、双智能体、轻量级注入) - 评估各方案优劣势和技术风险 - 确定推荐方案:完全 ReActAgent 架构 - 更新任务文件,记录方案分析 - 下一步:进入 PLAN 模式 ## [2025-11-20_15:35:00] - 状态:规划完成 - 已完成: - 制定详细的代码修改规格 - 设计完整的系统提示词(包含工具使用说明、示例、错误处理) - 明确每个函数的签名和实现细节 - 创建8项实施清单 - 添加降级机制设计 - 下一步:进入 EXECUTE 模式 ## [2025-11-20_15:38:25] - 状态:执行完成 - 已修改文件: - Plugins/WPSConfigSystem.py(添加 get_all_usernames() 方法) - Plugins/Others/ChatAI.py(完全重构为 ReActAgent 架构) - 已完成修改: 1. ✅ WPSConfigSystem.py 添加 get_all_usernames() 方法 2. ✅ ChatAI.py 添加导入(FunctionTool, AgentWorkflow, ReActAgent) 3. ✅ ChatAIAgent.__init__() 添加 workflow 和 config_api 属性 4. ✅ ChatAIAgent.__init__() 添加 _initialize_agent() 调用 5. ✅ 实现 _initialize_agent() 方法(包含三个工具函数) 6. ✅ 实现 _build_system_prompt() 方法(详细提示词,约200行) 7. ✅ 重构 chat() 方法使用 workflow.run() 8. ✅ 添加 _fallback_chat() 降级方法 - Linter 检查:✅ 无错误 - 更改摘要: - 新增方法:get_all_usernames() (WPSConfigSystem) - 新增方法:_initialize_agent() (ChatAI) - 新增方法:_build_system_prompt() (ChatAI) - 新增方法:_fallback_chat() (ChatAI) - 重构方法:chat() (ChatAI) - 新增工具函数:get_username_by_id, get_userid_by_name, list_all_usernames - 新增导入:FunctionTool, AgentWorkflow, ReActAgent - 下一步:用户测试工具调用功能 # 详细实施规格(PLAN 阶段输出) ## 实施清单 1. 在 WPSConfigSystem.py 添加 get_all_usernames() 方法 2. 在 ChatAI.py 添加新的导入语句 3. 在 ChatAIAgent.__init__() 添加 workflow 和 config_api 属性 4. 在 ChatAIAgent.__init__() 添加 _initialize_agent() 调用 5. 添加 _initialize_agent() 方法(创建三个工具) 6. 添加 _build_system_prompt() 方法(详细提示词) 7. 重构 chat() 方法使用 workflow.run() 8. 添加 _fallback_chat() 降级方法 ## 关键设计 ### 系统提示词特点 - 详细说明三个工具的用途、参数、返回值 - 提供大量使用示例(5个场景) - 明确工具使用原则(何时用/何时不用) - 包含错误处理指导 - 强调 标签使用规则 ### 三个工具函数 1. get_username_by_id(user_id: int) -> str 2. get_userid_by_name(username: str) -> str 3. list_all_usernames() -> str ### 错误处理 - Workflow 初始化失败 → 使用 _fallback_chat() - 工具调用失败 → 返回友好错误信息 - 整体异常 → 降级到简单对话模式 # 最终审查 (待完成后填写)