feat: VLM vision analysis - intercept images for text-only models#1405
feat: VLM vision analysis - intercept images for text-only models#1405kanchengw wants to merge 7 commits into
Conversation
684e24f to
e5f529f
Compare
|
感谢提交。静态审查和本地测试后,目前有几项阻塞合并的问题需要先处理:
本地验证结果:
以上问题修复并补充回归测试后再进行下一轮审查。 |
|
感谢审查。VLM 管线采用两阶段分析,逐点回复如下。 1. Responses 模式不经过代理UI 侧已处理: 运行时确认 Codex 请求统一走 2. HTTP 超时超时后未完成的 batch task 被 JoinSet drop 取消,已完成的结果保留。全部失败则返回 Err 走 fail-closed。 3. 历史图片处理(两阶段分析)
Phase 1(同步):
决策矩阵:
Phase 2(后台,仅 X > 10 时启动):
上下文溢出保护: 截断兜底: 所有注入合并 ≤ available × 2 字符上限,超出从远端(最旧轮)砍。 概括: 同步路径覆盖当前轮+黄金窗口(保障核心相关性),后台静默推进深层(零延迟),X 统管所有注入总量,上下文消耗完全可控。 4. fail-closed 策略
各场景处理:
不再可能把上游错误正文注入模型上下文。 5. UI 校验
如需保存时强制阻断(当前为被动警告),请确认。 6. 并发 / 图片上限 / 错误截断
测试测试覆盖类别:
|
Strip image_url/input_image blocks, call VLM to describe them, inject descriptions as text. Per-round analysis with LRU cache (500 entries, 24h TTL), depth limit (20 rounds), per-request image cap (10 historical), bounded concurrency (3 per-request, 5 global), HTTP timeouts (connect 5s, request 30s, total 120s). Fail-closed: preserve images when VLM unreachable. 42 tests including 8 wiremock integration tests.
63e0da7 to
15a0de5
Compare
Replace boolean VLM toggle with ImageHandling enum: send-as-is (default), strip images (no VLM), VLM analysis. Add UX guidance for multimodal vs text-only models with tooltips and inline hints. Rename text-only to send-as-is for clarity.
|
补充:三态图片处理模式 + UX 指引 将原来的 boolean VLM 开关改为三态下拉,让用户明确控制图片行为:
默认显示占位提示"纯文本模型请配置此项",下拉右侧固定说明"多模态模型(支持图片输入的模型)请保持 send-as-is",每个选项有 tooltip 说明语义。 ImageHandling enum 在 vision.rs ,三态分发在 protocol_proxy.rs ,TS 端 model-windows.ts 处理序列化。 移除旧 should_process 函数(已被 image_handling_mode 替代)和对应的 deprecated 测试。 |
Summary
Add VLM (Vision Language Model) analysis to the protocol proxy. When a text-only model (e.g. DeepSeek V4) receives an image, the proxy strips the image blocks, calls a VLM API (e.g. qwen-vl-plus) to describe the images in the latest user message, and injects the descriptions as text -- enabling text-only models to see images without upstream errors. Furthermore, with VLM analysis enabled for a text-only model in the manager, previously corrupt sessions are recovered automatically since the proxy strips images from all messages (including history) on every request, and only calls VLM when latest user message includes images.
Closes #574 - DeepSeek session permanently broken by images
Closes #1191 - Feature request: auto-intercept images for non-vision models
Closes #631 #790 #1158 #1221 #1365 #839 #703 #1194 - unknown variant image_url deserialization errors
How it works
Vision analysis covers:
Together these cover the user's primary intents when sending images in a chat:
The original
image_urlblock is removed entirely. Only the text description remains, ensuring the text-only model can process the message without issues.Why not route the entire conversation to a vision model?
The proxy applies VLM at the network layer without changing the user's model, session, or tool configuration. This preserves full conversation context, avoids dual-model latency/cost, and requires zero changes to Codex Desktop or upstream APIs. Per-model VLM toggles also allow fine-grained control (e.g. flash with VLM, pro without) within the same supplier.
In contrast, routing the entire conversation to a vision model introduces a context dilemma: sending the full history burns excessive tokens on the vision model, while sending only the latest message strips the vision model of the context needed to understand the user's intent.
Files Changed
12 files, +587 / -71。
vision.rs (new, ~304 lines)
Core VLM pipeline with 13 unit tests:
Key design: collect BEFORE strip. Only the latest user message images are VLM-analyzed.
protocol_proxy.rs - Two interception points (+59/-15)
5-condition guard: model non-empty, should_process true, api_key/model/base_url non-empty.
Config and UI
Testing
cargo test -p codex-plus-core vision:: --lib -> 13 passed
node --test src/model-windows.test.ts -> 10 passed
cargo clippy -p codex-plus-core -> clean