Skip to content

ds4 的多模态视觉输入:PNG/JPEG 解码(vendored iris 头文件库)→ 按模型预处理(smart resize / 384-token 硬预算)→ GPU-only ViT 编码器(--vision 侧车 GGUF)→ 投影到 4096 维、以浮点嵌入覆盖 LLM 上下文里的占位 token。图像身份用 SHA-256 指纹表示,是多模态 KV 复用的安全基础。

图像 → token 的四段管线 ​

  1. 解码(ds4_image.c):PNG/JPEG 魔数嗅探 → third_party/iris/png.h / jpeg.h(头文件-only,零 libpng/libjpeg);EXIF 方向(ds4_jpeg_orientation);上限 64 MiB / 16384 边长 / 64M 像素。输出携带 SHA-256 指纹(vendored 实现)——这张图的唯一身份
  2. 预处理:两族策略完全不同(见下表)
  3. 编码(GPU-only):ds4_engine_vision_encode_image 按 e->vision_kind 分发到 ds4_gpu_glm53_vision_encode / ds4_gpu_deepseek4_vision_encode。侧车权重先注册映射:Apple ds4_gpu_set_model_map_range,CUDA/ROCm ds4_gpu_set_aux_model_map_range(DGX Spark 统一内存上直接映射零拷贝,767e517)
  4. 合并进上下文(ds4_prompt_append_vision):
GLM 5.3DeepSeek V4 Flash Vision-Exp
缩放Qwen-VL smart resize(因子 28、1568 像素/token、二分塞 16..8000 token),双三次 + CLIP 归一化最小 147456 像素、8:1 钳制、硬 384 token 预算(压缩比 3),灰 127 画布
ViT24 层 / 1024 / 16 头,QK-RMSNorm,合并后网格 RoPE32 层 / 1024 / 16 头,无 QK norm,中间结果舍入 BF16,原始网格 RoPE
进上下文vision_start + N × 占位 token + vision_end,prefill 时浮点嵌入覆盖占位行(glm_vision_overlay_prepare)合成哨兵 token(DS4_N_VOCAB + type),行对交织 + pos%4 对齐;语言模型侧 visual_router_bias[43] 让视觉 token 走不同的 MoE 专家分布

DeepSeek 的 visual_router_bias 值得单独记:多模态不只是"嵌入拼接进上下文",路由器也为图像 token 换了偏置——视觉信息走专门遴选的专家组合。

多模态 KV cache:指纹是安全边界 ​

图像 token 的 KV 行依赖具体图像内容,所以"上下文前缀相同"不再蕴含"KV 可复用"。ds4 的答案(98b9135 + b0982a1,81a7658 细化为前缀复用):

  • 会话记账:checkpoint_images[](每项 = SHA-256 指纹 + token 跨度),ds4_session_sync_multimodal 校验跨度不重叠、DeepSeek 侧每跨度恰好覆盖完整图像块
  • 精确匹配才复用:ds4_session_vision_state_matches 要求图像数量、每个跨度与指纹全部一致,才允许任何 live-KV 复用路径(Responses / Anthropic 续接、GLM rewind、thinking 前缀……)——图变了就从零重建,绝不错用
  • 追加新图可前缀复用(81a7658):ds4_session_vision_prefix_matches 只要求历史图像跨度+指纹一致、新图起点在 live 前沿之后;live 续接经独立凭证(工具调用 ID)认证后,ds4_session_rebase_vision_state 从检查点恢复各图像 token 起点,build_live_prompt_suffix 把新图像 token 块拼进 live 续接——四条续接路径统一走它
  • 恢复起点推进到 live 前沿:server_multimodal_resume_pos/frontier 让同步从"恰好可复用的确切位置"开始,而不是从 0(旧实现会截断本可复用的长检查点)
  • 磁盘 KV 拒收视觉状态:kv_cache_store_live_prefix_text 检测 ds4_session_has_vision_state 即拒写——磁盘 payload 不带图像身份,占位 token 的 KV 绝不能在另一张图上命中;kv_cache_try_load_text 恢复纯文本检查点前先清除残留视觉状态
  • 有界嵌入缓存:server_image_cache(32 项 / 128 MiB LRU)按编码后字节的精确匹配复用 ViT 嵌入,同一张图重复出现不重跑编码器;请求局部 marker 归一化(visible_prompt_key)让跨请求的可见历史比对不被 nonce 干扰

这组设计把 Day 14 的洞察推广到了多模态:"采样的 KV 状态是最高保真度的状态",而图像的指纹就是它的合格证——前缀复用放松的是数量,不是身份。

使用面 ​

  • CLI:./ds4 --vision gguf/…-Vision-Encoder.gguf,REPL /read image.png
  • 服务器:OpenAI image_url(仅 data:image/png|jpeg;base64, URI)、Anthropic image 块、Responses input_image;每请求 ≤ 16 张、body ≤ 64 MiB;本地路径与远程 URL 拒绝
  • agent:--vision 启用 view_image 工具
  • 下载:ds4f-vision-*(含专用 DSpark 检查点——不能混用 0731 的)、glm53-vision(1.1 GB)、ds41f-vision(V4.1,0.9 GB,只此一个)

V4.1 Flash 视觉(2026-09,第三族) ​

V4.1 的视觉与 V4 Flash 共享 patch 几何与 ViT 骨架(32 层 / hidden 1024 / patch 14 / 3×3 合并),但走自己的侧车 GGUF(266 个 BF16 张量逐字节直拷,投影 5120 维、图像 token id 129264)。差异集中在预算与布局:token 上限 1024(V4 Flash 是 384)、最小像素 295936、无 8:1 长宽比钳制;token 流是朴素行主序(START、每行 width×IMAGE + NEWLINE、END、恒等置换),不再有 V4 Flash 的行对交织与 compress_pad。图像位置同时抑制 engram(n-gram 记忆的键在图像 token 上无意义)。编码器只随 Metal 后端提供;V4 与 V4.1 的视觉编码器互不通用。

Qwen3.8 Flash Next 视觉(2026-09,第四族) ​

第四条视觉管线换了供货方式:直接消费 llama.cpp 生态的标准工件——qwen38-vision 下载 llama.cpp 的 Q8_0 mmproj(Qwen3-VL 塔,clip 架构 + qwen3vl_merger 投影,qwen4_vision_weights_bind 校验 1152 维 / 16 头 / patch 16 / 2×2 空间合并)。ds4 此前三条管线都是自制片;这次是第一次"别人家的转换器输出直接喂进来"。图像缩放到 32 像素倍数、token 预算 64..1024(DS4_QWEN4_IMAGE_MAX_TOKENS 提上限),GPU 编码,视觉 token 取模型的 3D rope 位置(t/h/w 三轴)。live KV 复用键 = 图像指纹;服务器复用阶梯对图像会话的校验(指纹前缀 vs 精确位置)见 Part 5 §7。Metal 与 CUDA 都支持。

相关概念 ​

  • kv-cache — 文本前缀复用的基础机制,视觉状态在其上加了指纹校验层
  • moe — visual_router_bias:图像 token 的路由偏置
  • engram — V4.1 的外部记忆表在图像 token 上被抑制
  • Part 3 §7 — 两族编码器架构细节
  • Part 3 §9 — Qwen3.8 架构(视觉与其他组件)
  • Part 5 §7 — 服务器图像 API 与多模态 KV 复用