chore: sync current WechatHookBot workspace
This commit is contained in:
234
docs/AIChat函数调用框架与开发指南.md
Normal file
234
docs/AIChat函数调用框架与开发指南.md
Normal 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 场景脚本)。
|
||||
|
||||
Reference in New Issue
Block a user