58 lines
7.1 KiB
Markdown
58 lines
7.1 KiB
Markdown
# AI 问答上下文审计(2026-09-16)
|
||
|
||
范围:`C:/kefu/wechat_rpa`、`C:/wechat_rpa` 的桌面文本/视觉问答、共享模型协议及多模型/MCP 路由。此报告不代替主报告中的真实线上模型、知识检索服务端、视觉识别、原生协议测试结果。
|
||
|
||
## 已确认并修复
|
||
|
||
1. **网关 Dify 请求丢弃历史和知识**:`model_protocol.chat_payload()` 原来只取最后一条 user,system 中的已发布知识、客服规则以及此前问答全部丢失。新增 `dify_query()`,按角色和顺序保留规则、知识、客户历史、客服历史、本轮问题和工具结果。单条 user 仍保持原请求格式;不复用跨客户 conversation_id。
|
||
2. **Dify 通用/裁判分支同样丢上下文**:`ai_chat._chat_completion()` 的 Dify 兜底也只取最后 user,导致桌面 Dify 裁判可能缺少 system 中的评分和 JSON 格式要求。现复用同一协议转换。
|
||
3. **MCP 模型选择失效**:显式选定模型进入 MCP 循环时没有传 provider,实际请求重新使用全局默认模型。现无工具、工具轮和最终回复均传递本轮选定 provider。
|
||
4. **视觉请求污染检索文本**:网关 customer_text 原来直接字符串化多模态 content,包含图片 base64。新增 `message_text(content)`,仅抽取文本块;图片完整保留在 messages。可避免图片串进入知识查询/裁判文本。
|
||
5. **历史轮数和损坏档案边界**:本地轮数为字符串/非法值时抛 TypeError,0/负数会让裁剪失效;None 等损坏历史行抛 AttributeError。现轮数转为 1–50 整数,非法值回退 5,跳过非字典历史行。
|
||
6. **两目录留痕差异**:源目录缺少网关返回的 knowledge 留痕,目标目录已有。源目录现已同步保留该字段,便于验证知识使用情况。
|
||
|
||
上述代码修改仅涉及两个目录各自的 `ai_chat.py`、`model_protocol.py`;`model_router.py` 无需改动。原文件备份到各目录 `backups/recognition-audit-20260916/ai-context/`,修改前后 SHA-256 见 `ai-context-manifest.json`。
|
||
|
||
## 验证
|
||
|
||
新增 `test_ai_context_audit.py` 共 **17 项**。覆盖文本和视觉的 OpenAI/Claude/gateway 路由、Dify 直连文本和图片分支、Dify 共享协议和裁判协议、角色顺序、上下文关闭、最近轮数、非法配置、损坏历史、调用间隔离、不修改输入历史、图片不进入 customer_text、knowledge trace、MCP 指定模型及工具结果续传。
|
||
|
||
修复前先运行新增测试,16 项方法中的失败断言共 8 个、异常子场景共 4 个,证实上述问题不是仅凭代码推测。随后补上通用 Dify 裁判回归,总计 17 项。
|
||
|
||
最终用临时应用数据目录运行,阻止外网、真实鼠标键盘/截图和发送,仅允许测试自行创建的回环端口;运行结果:
|
||
|
||
| 目录 | 测试模块 | 通过 | 失败/异常/跳过 | 外部操作尝试 |
|
||
|---|---|---:|---:|---:|
|
||
| C:/kefu/wechat_rpa | test_ai_context_audit、test_ai、test_model_router、test_agent_rules | 137 | 0/0/0 | 0 |
|
||
| C:/wechat_rpa | 同上 | 137 | 0/0/0 | 0 |
|
||
|
||
可复核文件:`ai-context-source.json/.log`、`ai-context-target.json/.log`。运行器为同目录 `run_visual_audit.py`。最初使用完全禁网运行器时,现有端口发现测试被错误拦截;改用允许测试回环连接的隔离器后通过,没有修改生产代码来绕过测试。
|
||
|
||
主任务另已得到真实线上印证:相同的合成多轮问题,Dify 上游未记住此前提供的信息,OpenAI 兼容出口能记住;这与修复前 Dify 只传最后 user 的实现一致。该真实调用由主任务执行,详情和修复后线上验证以主报告为准。
|
||
|
||
## 实际覆盖及限制
|
||
|
||
- 本报告证明上下文、知识文本和图片**进入正确请求字段**,不声称所有模型一定按要求作答。真实模型响应质量和线上部署状态另列。
|
||
- 历史按轮数裁剪,默认最近 5 轮、最多 50 轮;尚无针对不同模型 token 窗口的动态估算/摘要压缩,不能承诺任意长的单条历史都兼容。
|
||
- Dify/Claude 的原生工具调用转换不在现有实现范围。此次 MCP 回归验证 OpenAI/网关工具轮的选定模型、历史和工具结果续传,没有声称新增原生 Claude/Dify 工具支持。
|
||
- 账户/会话身份绑定发生在协议引擎和会话档案层,此处仅验证已传入某会话 history 的顺序、裁剪和调用间不泄漏;底层跨账户隔离由并行协议测试负责。
|
||
- 未连接真实微信、未向客户发送消息、未修改用户实际配置或业务数据库;已修改的生产文件仅为上列授权代码。
|
||
|
||
## 追加:网关 Dify 上传失败隔离复核
|
||
|
||
在主任务修复图片上传后,补充 test_gateway_failure_audit.py **10 项**:纯文本不上传、exact 自定义路径、两图顺序/MIME/原始字节、上传与聊天 user 一致、旧轮图片不重传、内联/旧版重复图片去重、远程图片引用、上传 HTTP/网络/非 JSON/非对象错误不影响另一 OpenAI 出口。
|
||
|
||
修复前重现:上传响应为数组、字符串、数字时,.get() 引发 AttributeError,导致 asyncio.gather() 整体中断。只修改 model_gateway._dify_upload() 的响应结构校验,将不合法 JSON、非对象和无效 ID 转为出口级 GatewayError。原文件追加备份于 backups/recognition-audit-20260916/ai-context/model_gateway-before-upload-validation.py,哈希清单 gateway-upload-validation-manifest.json。
|
||
|
||
最终两目录各 **10/10 通过**,0 失败/异常/跳过;记录为 gateway-failure-source.json/.log 与 gateway-failure-target.json/.log。这部分是新增独立测试,不重复前面的 137 项。所有上传均由 httpx.MockTransport 接管。
|
||
|
||
## 追加:视觉守卫专用模型路由
|
||
|
||
新增 test_gateway_guard_audit.py **11 项**,修复前端到端确认:purpose=guard 且配置 vision_id 时,网关仍调用答题 A、B 和客服裁判 J,完全没有调用专用视觉出口 V。这会使后台设置的视觉模型不生效,并额外增加调用和延迟。
|
||
|
||
已修复 Catalog.plan(purpose=...) 与 /v1/answer:guard 仅选可用 vision_id、明确不调用客服裁判;没有可用视觉角色的旧配置仅使用主答题出口兼容;专用视觉出口失败按该出口错误返回,不静默改用其他文本模型。普通聊天及普通图片问答保留原 answer_ids 并发/裁判行为。测试还覆盖 Dify 专用视觉模型接收上传截图、禁用/缺失/ComfyUI 视觉配置回退和仅有视觉角色的计划。
|
||
|
||
最后将 guard 11 项、上传失败 10 项与既有 test_model_gateway 32 项合并,两目录各 **53/53 通过**,0 失败/异常/跳过。记录 gateway-guard-source.json/.log、gateway-guard-target.json/.log;新增测试已同步两个项目。最终两个 model_gateway.py 字节一致,SHA-256:62f8367b3e4489feb829957cf46d95ff61fdfbbe3517c2511423c929349b68b2。
|
||
|
||
这一部分仍为隔离应用、临时数据库、模拟上游,线上是否使用修复版需由主任务实际部署/验证结果确认。最后变更清单为 gateway-guard-manifest.json;其前版本备份 model_gateway-before-guard-routing.py 保留此前已修的图片和上传校验逻辑。
|