chore: sync current WechatHookBot workspace

This commit is contained in:
2026-03-09 15:48:45 +08:00
parent 4016c1e6eb
commit 9119e2307d
195 changed files with 24438 additions and 17498 deletions

View File

@@ -0,0 +1,234 @@
# AIChat 函数调用框架与开发指南
> 适用范围:`WechatHookBot/plugins/AIChat/main.py` 及所有通过 `ToolRegistry` 注册的插件工具。
> 更新时间2026-02-09
## 1. 目标与设计原则
当前 AIChat 的函数调用框架,核心目标是:
1. **少误触发**:只在用户明确有工具意图时暴露工具。
2. **少泄露中间态**:不向用户输出半截 `function_call/tool_calls` 或 JSON。
3. **可扩展**:插件只需实现 `get_llm_tools()` + `execute_llm_tool()`
4. **可控输出**:工具执行后,默认由 AI 再生成一条自然语言总结Eridanus 风格)。
---
## 2. 总体架构
### 2.1 核心模块
- AI 编排入口:`WechatHookBot/plugins/AIChat/main.py`
- 工具注册中心:`WechatHookBot/utils/tool_registry.py`
- 工具执行器:`WechatHookBot/utils/tool_executor.py`
- 工具结果标准化:`WechatHookBot/utils/llm_tooling.py`
### 2.2 数据流(简化)
1. 接收消息(文本/图片)
2. AIChat 按规则筛选本轮可用工具
3. 预处理工具 schema补全描述、约束参数
4. 注入函数调用规则到 system prompt
5. 请求模型(流式或非流式)
6. 提取 `tool_calls`(兼容旧 `function_call`
7. 通过 `ToolExecutor` 并发/串行执行工具
8. 工具结果回填上下文,二次请求 AI 输出最终自然语言
---
## 3. 关键流程(按代码路径)
### 3.1 主入口
- 文本入口:`_call_ai_api(...)`
- 图片入口:`_call_ai_api_with_image(...)`
两条链路逻辑保持一致:都支持工具选择、工具执行、二次总结回复。
### 3.2 工具选择Smart Select
函数:`_select_tools_for_message(...)`
特点:
-`tools.smart_select=true` 时,按意图正则筛选工具。
- 无明显工具意图时,返回空工具列表(严格模式)。
- 对“自拍/生图”口语增加专门识别:`_looks_like_image_generation_request(...)`
### 3.3 工具声明标准化
函数:
- `_normalize_tool_schema_for_llm(...)`
- `_prepare_tools_for_llm(...)`
标准化动作:
- 补函数描述(缺失时自动补)
- 补参数类型与描述(缺失时自动补)
- 统一 `parameters.additionalProperties = false`
### 3.4 规则注入System Prompt
函数:`_build_tool_rules_prompt(...)`
注入规则包括:
- 仅基于【当前消息】决定是否调用工具
- 参数不全先追问
- 禁止输出工具调用 JSON 片段
- 工具后输出自然语言总结
开关:`tools.rule_prompt_enabled`
### 3.5 工具调用提取
函数:`_extract_tool_calls_data(...)`
支持:
- 标准 `tool_calls`
- 旧格式 `function_call` 兼容转换
并且在流式链路中组装增量 `tool_calls`,避免丢参数。
### 3.6 工具执行与回传
函数:
- `_execute_tools_async(...)`
- `_execute_tools_async_with_image(...)`
- `_continue_with_tool_results(...)`
行为:
- 通过 `ToolExecutor.execute_batch(...)` 统一执行。
- 根据返回标志决定是否直接发送、是否二次 AI 总结。
- 默认启用二次 AI 总结(`tools.followup_ai_reply=true`)。
---
## 4. 关键配置项(`plugins/AIChat/config.toml`
`[tools]` 相关:
- `smart_select`: 是否启用意图筛选
- `loose_image_tool`: 文本形态绘图调用的宽松映射
- `async_execute`: 工具是否后台执行
- `followup_ai_reply`: 工具后是否二次 AI 总结
- `rule_prompt_enabled`: 是否注入函数调用规则提示
建议线上默认:
- `smart_select = true`
- `followup_ai_reply = true`
- `rule_prompt_enabled = true`
---
## 5. 插件开发规范
## 5.1 工具定义接口
插件实现:
- `get_llm_tools() -> List[dict]`
- `execute_llm_tool(tool_name, arguments, bot, from_wxid) -> dict`
`get_llm_tools()` 建议:
1. `description` 里明确:**何时调用**、**何时不要调用**。
2. 参数写清语义、可选值、默认行为。
3. `required` 只保留真正必需参数。
4.`additionalProperties: false`,减少幻觉参数。
### 5.2 工具返回结构约定
基础字段:
- `success: bool`
- `message: str`
可选控制字段(由 `ToolResult/ToolCallResult` 消费):
- `need_ai_reply`: 强制进入二次 AI 总结
- `already_sent`: 工具内部已发送过消息
- `send_result_text`: 是否直接发送 `message`
- `no_reply`: 本轮不需要任何回复
- `save_to_memory`: 是否保存到上下文记忆
---
## 6. 推荐模板
### 6.1 工具声明模板
```python
{
"type": "function",
"function": {
"name": "search_xxx",
"description": "仅当用户明确要求检索XXX时调用普通闲聊不要调用。",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "检索关键词,尽量简洁明确。"
}
},
"required": ["query"],
"additionalProperties": False
}
}
}
```
### 6.2 工具执行返回模板
```python
return {
"success": True,
"message": "已完成检索",
"need_ai_reply": True
}
```
---
## 7. 常见问题排查
### 7.1 用户说“看看自拍”却不触发生图
先检查:
1. `tools.smart_select` 是否开启
2. 生图插件工具是否在白名单中
3. 日志里“本次启用工具”是否包含生图工具名
当前已加入自拍口语识别(`_looks_like_image_generation_request`),如仍异常优先看意图文本是否被预处理掉关键字。
### 7.2 出现半截 JSON / function_call 泄露
检查:
1. `rule_prompt_enabled` 是否开启
2. 流式链路是否提前发送 preview应禁用
3. 是否落入旧模型 `function_call` 兼容分支但未成功转工具
### 7.3 工具执行后无最终文本
检查:
1. `followup_ai_reply` 是否开启
2. 工具返回是否误设 `no_reply=true`
3. `_continue_with_tool_results` 是否收到有效 `tool_results`
---
## 8. 后续建议
1. 继续统一所有插件工具描述风格(触发边界 + 禁用条件)。
2. 在日志中增加“本轮 allow 工具集合”调试行,提升定位速度。
3. 为高频工具加回归用例(最少做 py_compile + simulate 场景脚本)。