Skip to content

feat: VLM 配置测试入口(选图即测 + 排障报文) - #2030

Merged
BigPizzaV3 merged 12 commits into
BigPizzaV3:mainfrom
jarvislee90s-dot:vlm-test-entry
Sep 2, 2026
Merged

feat: VLM 配置测试入口(选图即测 + 排障报文)#2030
BigPizzaV3 merged 12 commits into
BigPizzaV3:mainfrom
jarvislee90s-dot:vlm-test-entry

Conversation

@jarvislee90s-dot

@jarvislee90s-dot jarvislee90s-dot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

feat: VLM 配置测试入口(选图即测 + 排障报文)


PR 正文

背景

为纯文本模型配置 VLM 视觉辅助分析后,目前没有任何验证手段——只能等真实对话里发图,靠结果反推配置是否生效。常见遭遇:模型先说"不接受图片输入",追问后却开始幻觉式描述图片,用户无法判断是 Key 错、Base URL 错、模型名错,还是 VLM 服务本身异常(#1599)。

本 PR 在 VLM 配置区(Vision Analysis Provider)增加「测试 VLM」入口:选一张图立刻验证配置,失败时给人话诊断与完整排障信息。

测试截图-成功

设计要点:与真实链路同源

测试请求与真实识图链路共享同一提示词常量、请求体构造与端点构造call_vlm_batch 等价重构为共用原语,行为零变化,现有测试兜底),并共用全局并发信号量。测试通过即代表真实对话识图可用;一个形状钉子测试锁定提示词与请求体逐字一致。

交互

  • 「测试 VLM」→ 就地内联展开面板;选图即自动发起,无二次点击
  • 失败诊断按类型人话化:认证失败(API Key 或模型名)、接口不存在、限流、超时、网络、解析失败、无描述文本
  • 一键复制完整排障信息(诊断 + 原始请求/响应报文);报文永不包含 API Key,图片 base64 截断展示
  • 图片 >10MB / 非图片文件拒绝;表单当前值即可测(无需先保存);中英双语

测试

自动化(全绿):

  • codex-plus-core vision 68 例:11 例 wiremock 逐类失败口径(成功 / 401 / 404 / 429 / 502 HTML 错误页 / 超时 / 连接拒绝 / 非 JSON / 无描述文本)+ 请求体形状钉子 + 无 Key 泄漏钉子
  • protocol_proxy 74 例;cargo build --workspace 干净
  • 前端翻译纯函数 16 例(含逐字锁定)+ tsc --noEmit 零错误
  • i18n:本 PR 新增 29 键零缺失零冗余(校验工具余下的缺失/冗余为上游既有词典漂移,与本 PR 无关)

手工验收(15 项全过):

# 测试项 结果
1 勾选「视觉辅助分析」后 VLM 区出现「测试 VLM」
2 面板就地内联展开 / 收起
3 选图即测:自动发起 → ✅ 识别成功(耗时 11.8s)+ 描述原文
4 错 API Key → ❌ 认证失败(HTTP 401)
5 错 Base URL → ❌ 接口不存在(HTTP 404)
6 未保存表单直接测 → 用当前输入值
7 >10MB 图片 → 拒绝并提示
8 非图片文件 → 拒绝并提示
9 复制错误 → 诊断 + model + HTTP 码 + error + 原始报文两段,无 API Key
10 原始报文折叠:base64 显示前 64 字符 +「已省略」
11 重测:原图重跑,进行中防重复触发
12 换图并测试:选完自动开跑
13 收起 / 收起测试面板
14 英文界面全翻译
15 真实识图链路回归不变(同源重构零影响)

验收反馈驱动的一处修正:部分网关对未知模型名也返回 401,认证失败文案归因已从单一"API Key"改为"API Key 或模型名可能不正确"。

说明

  • i18n 校验工具(tools/i18n-verify.mjs)本 PR 扩展为识别注入式 tr 回调;存量词典漂移建议后续单独清理

为纯文本模型的 VLM 视觉辅助配置提供即测即看的验证入口。
核心契约:测试请求与真实识图链路同源;交互为选图即测 +
排障增强(原始报文折叠、一键复制错误)。
- 提示词常量与请求体构造提取为共享原语,call_vlm_batch 等价重构,
  vlm_endpoint 共享端点构造——测试请求与真实识图请求构造同源
- VlCallOutcome 结构化结果:status 分类(ok/http_error/timeout/
  send_error/json_error/no_text)+ 耗时 + 原始请求/响应(展示副本:
  base64 截断、永不包含 API Key)
- 错误判定先读 body 再判 HTTP 码,HTML 错误页不再误判为 json_error
- 11 例 wiremock 测试逐类覆盖失败口径 + 请求体形状钉子
表单当前值(未保存可测)→ test_vlm_once 单图调用 → 结构化结果
返回前端。HTTP 客户端复用 vlm_http_client(与真实链路同款
连接/总超时)。
状态分类 -> 人话文案(认证失败 401/403、接口不存在、限流、超时、
网络、解析等),翻译回调注入,模块零依赖、16 例单测(含逐字锁定)。
认证失败归因 API Key 或模型名——手工验收发现部分网关对未知模型
也返回 401,单一归因 Key 会误导。
- VLM 配置区底部入口,就地内联展开;选完图片自动发起,无需二次点击
- 结果区:通俗诊断 + 描述原文 + 复制错误(诊断+原始报文,无 Key)
  + 可折叠原始请求/响应
- 图片超 10MB / 非图片拒绝;表单当前值即可测;a11y(role/aria)齐备
i18n-verify.mjs 增扫 vlm-test-translation.ts;tr(zh) 按 plain、
tr(zh, params) 按 template 归类。本 PR 新增 29 键零缺失零冗余
(工具余下的缺失/冗余均为上游既有词典漂移,与本 PR 无关)。
@jarvislee90s-dot
jarvislee90s-dot marked this pull request as ready for review August 27, 2026 17:11
@BigPizzaV3

Copy link
Copy Markdown
Owner

合并前请补两点:1. 后端 对 重新做类型和大小校验,不能只依赖前端;2. 和 展示前需要脱敏,避免上游回显 Authorization/API Key 时复制排障信息泄露凭据。请补充对应测试。

@BigPizzaV3

Copy link
Copy Markdown
Owner

更正:合并前请补两点:1. 后端 test_vlm 对 image_data_url 重新做类型和大小校验,不能只依赖前端;2. raw_response 和 error 展示前需要脱敏,避免上游回显 Authorization/API Key 时复制排障信息泄露凭据。请补充对应测试。

- redact_secrets:已配置 Key 精确替换 + Authorization/Bearer 头形态掩码(空 Key 跳过精确替换、下划线算词内、空引号值不掩)
- 接线全部构造路径:http_error/json_error/timeout/send_error + 命令层 client_error;脱敏先于截断(防跨界 Key 截半失配)
- description(OCR 结果)从原始响应解析、逐字可见、不脱敏(功能本体,仅本地展示无复制通道)
- wiremock 回显测试断言 error/raw_response 双字段;原 raw_request 泄漏钉子扩展为同时钉 raw_response
- validate_image_data_url:data:image/* + base64 段 + 解码后字节 ≤ 10MB(与前端口径对齐),非法输入不发起网络请求
- 命令层先校验后建客户端/发起调用;client_error 路径同步过脱敏,全仓库一条规则
- 前端 invalid_image 分支文案 + 中英 i18n 词条 + 翻译测试
@jarvislee90s-dot

jarvislee90s-dot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

两条已补(对应 更正版意见),涉及提交:b43149b(脱敏)、4cf4baf(输入校验)、f98b4dd(英文漏翻修复)。

1. 后端输入校验(4cf4baf)

test_vlm 命令层新增第二道门 validate_image_data_urldata:image/* 类型 + base64 编码段 + 解码后字节 ≤ 10MB(与前端口径对齐;量解码后字节而非字符串长度,避免 base64 膨胀把前端合法放行的图误拒)。非法输入不发起网络请求,新增失败分类 invalid_image(中英文案 + 翻译测试)。正常 UI 路径零感知(前端第一道门不变),此门仅拦绕过前端的 IPC 直调。

2. 排障输出脱敏(b43149b)

raw_responseerror全部构造路径(http_error / json_error / timeout / send_error / 命令层 client_error)统一经 redact_secrets 脱敏:已配置 Key 精确替换 + Authorization: / Bearer 头形态掩码(不区分大小写、兼容 JSON 形态;Key 为空时跳过精确替换)。脱敏在截断之前完成——先截断会把跨界 Key 截成半截,精确替换就失配了。

范围说明:脱敏针对的是「上游回显的凭据」;description(OCR 识别结果)不在脱敏范围——它是功能本体、仅本地展示,且「复制错误」拼装的内容不含该字段,无外贴通道;用户拿印着 Key 的图测试,OCR 仍逐字可见。

测试

  • 校验:纯函数单测逐类覆盖——非图片、非 data URL、非 base64、超限、恰好 10MB 边界放行、合法放行;
  • 脱敏:wiremock 构造上游回显 Authorization 头与 Key → 断言 errorraw_response*** 且不含 Key 原文;原只钉 raw_request 的泄漏钉子已扩展为同时钉 raw_response;description 逐字可见有专项测试双向钉住(desc 含 Key 原文、raw_response 反之);
  • codex-plus-core vision 80 例全绿;前端 135 例全绿 + tsc 零错误;i18n 新增键零缺失零冗余。

手工验收

正常流程回归、前端第一道门(>10MB / 非图片文案)、devtools 直调 IPC 验证后端拒绝(返回 invalid_image 且无网络请求发出)、真实网关 401 复制排障信息无 Key、印 Key 图片测试 description 逐字可见、英文界面回归。期间发现 VLM 区「图片处理方式」下拉两个标签英文漏翻(上游存量词典漂移),已顺手修复(f98b4dd)。

一个已知现象(非 bug)

无论界面语言,测试返回的图片描述均为中文——识别提示词是与真实识图链路共享的中文常量(同源契约),真实对话中的识图描述本来就是中文,测试面板如实反映真实链路行为。若需按界面语言输出描述,需要将共享提示词本地化并让真实链路同步调整(否则破坏「测试通过即代表真实识图可用」的同源主张),属独立需求,不在本 PR 范围。

@jarvislee90s-dot

Copy link
Copy Markdown
Contributor Author

补充两张截图(对应上文「英文漏翻修复 f98b4dd」与「一个已知现象」两节):

英文界面下「Image handling」两个选项仍为中文(已在 f98b4dd 修复) 英文界面下测试返回的描述仍为中文(非 bug,见「已知现象」节)
英文界面漏翻 英文界面中文回复

@BigPizzaV3

Copy link
Copy Markdown
Owner

当前 macOS x64 workflow 在 hdiutil eject 阶段因 Resource busy 失败,编译本身已完成。请重新运行干净的三平台 workflow,确认 DMG 打包/卸载失败不再出现,并保留后端图片类型、大小校验和排障报文脱敏测试。

@jarvislee90s-dot

Copy link
Copy Markdown
Contributor Author

三平台 workflow 已全绿(run 33620522493,head 22d109b):Windows artifacts / macOS DMG x64 / macOS DMG arm64 均 success。

DMG 打包/卸载失败的根因是打包脚本对 macOS 延迟弹出的等待不足:Finder 释放卷后,卷目录先消失、磁盘镜像随后才完成弹出,原脚本在 detach 与 convert 两处的退避都不够长。已在 1335f5d + 22d109b 就地加固(detach 退避重试并把「卷已消失」视为成功;convert 重试加长到 5 次/30s 退避),两处均只改 scripts/installer/macos/package-dmg.sh,不涉及功能代码。

后端图片类型/大小校验与排障报文脱敏测试均保留在 b43149b / 4cf4baf(校验逐类单测 + wiremock 回显脱敏断言 + 泄漏钉子扩展)。

@BigPizzaV3
BigPizzaV3 merged commit f329312 into BigPizzaV3:main Sep 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants