探索记录
August 30, 2026 · View on GitHub
[简体中文] | English
探索记录
本文件记录为实现 DeepSeek-OCR1 记忆插件过程中进行的联网搜索、技术选型和验证结论。
1. DeepSeek-OCR 论文
- 论文:DeepSeek-OCR: Contexts Optical Compression
- arXiv:https://arxiv.org/abs/2510.18234
- 核心:用 DeepEncoder 把文档图像压缩成少量 visual tokens,再用 DeepSeek-3B-MoE-A570M 解码。
- 官方分辨率模式:
- Tiny:512×512 → 64 tokens
- Small:640×640 → 100 tokens
- Base:1024×1024 → 256 tokens
- Large:1280×1280 → 400 tokens
- Gundam:动态拼接
2. 记忆系统相关论文/实现
- OCR-Memory(ACL 2026):明确以 DeepSeek-OCR 3B 为 backbone,SoM + Locate-and-Transcribe + age-aware multi-resolution + active recall。
- https://arxiv.org/abs/2604.26622
- 未找到官方开源代码。
- AgentOCR(ACL 2026 Oral):光学自压缩 + segment optical caching,有开源代码,但 backbone 是 Qwen2.5-VL。
- MemOCR(美团):视觉记忆 agent,backbone 是 Qwen2.5-VL,属于思路相近而非 OCR1 直系实现。
- VTC-R1:光学 memory 用于长上下文推理,backbone 是 Glyph/Qwen3-VL,非 DeepSeek-OCR。
3. DeepSeek-OCR 本地部署
- vLLM 官方支持 DeepSeek-OCR,但本机为 AMD RX 7800 XT,无 NVIDIA CUDA,vLLM 官方路线不推荐。
- 社区 GGUF 来源:
- Ollama:
ollama run deepseek-ocr(需 v0.13.0+) - Hugging Face:
ggml-org/DeepSeek-OCR-GGUF(Q8_0,官方 llama.cpp 博客推荐)sabafallah/DeepSeek-OCR-GGUF(Q4_K_M / Q8_0 / BF16)NexaAI/DeepSeek-OCR-GGUF(Q4_K / Q5_K / Q6_K / Q8_0 等)
- Ollama:
- 实测:
ollama pull deepseek-ocr卡在 84%,速度降至 100KB/s,放弃。- 使用 aria2c 多线程从
hf-mirror.com下载成功,速度可达数 MB/s。 sabafallah的 Q4_K_M 在 llama.cpp CLI 中触发崩溃,可能属于 PR 分支转换;但llama-server下可稳定运行。- 当前使用
sabafallah的deepseek-ocr-Q4_K_M.gguf+mmproj-deepseek-ocr-q8_0.gguf通过llama-server稳定运行。
4. llama.cpp / AMD 路线
- 下载:
llama-b10453-bin-win-vulkan-x64.zip与llama-b10453-bin-win-cpu-x64.zip - 路径:
<models>\llama.cpp\、<models>\llama.cpp-cpu\ - 运行:
llama-server监听127.0.0.1:18080- 使用
deepseek-ocr-Q4_K_M.gguf+mmproj-deepseek-ocr-q8_0.gguf(更省显存)
- 关键参数:
- 必须使用
\nFree OCR.风格 prompt - 必须加
repeat_penalty和no_repeat_ngram_size防止重复输出
- 必须使用
- 注意:
llama-mtmd-cli在 Vulkan 和 CPU 模式下均崩溃(0xC0000409),但llama-server可正常工作。- 这是本机实测现象,可能与 Windows/驱动/构建有关。
5. 本机环境
- GPU:AMD Radeon RX 7800 XT(16GB)+ Radeon 780M
- 无 NVIDIA CUDA
- Python 3.12 / Node 24 / bun 1.3
- Pillow 已安装,torch 未安装
- 模型文件:
<models>\deepseek-ocr-gguf\
6. llama-server 运行注意事项
- 独立 OCR 服务使用
-c 8192更适合容纳 1280×1280 图像产生的视觉 token;OCR 与 embedding 共用 endpoint 时,插件默认使用ocrEmbeddingContextSize=2048,并将ocrEmbeddingUbatchSize=2048传给服务。 - 插件已内置自动拉起:
lib/ocr-server.js+autoStartOcrServer配置。 - 自动拉起实现细节:直接 detached spawn
llama-server.exe,不走 PowerShell wrapper;同一 endpoint 的并发启动合并为一个任务,取消/失败/卸载只清理插件自己启动的进程。 - 当前 combined CPU 服务的等价启动参数:
llama-server.exe --host 127.0.0.1 --port 18080 \ -m deepseek-ocr-Q4_K_M.gguf \ --mmproj mmproj-deepseek-ocr-q8_0.gguf \ --alias deepseek-ocr -c 2048 -np 1 -n 1024 --embeddings --pooling mean -b 2048 -ub 2048
7. llama.cpp 多模态 embedding(真实视觉 embedding)
- 结论:llama.cpp
llama-server的/v1/embeddings支持图片输入,但请求格式不是 OpenAI 标准input字符串,而是:{ "input": [ { "prompt_string": "<media_marker>", "multimodal_data": ["<raw base64>"] } ] } <media_marker>必须从GET /props的media_marker字段动态获取(每次启动随机)。multimodal_data必须是裸 base64,不能是data:image/png;base64,...(后者会报Failed to load image or audio file)。- 某些 llama.cpp 构建默认
-ub$(\text{physical} \text{batch} \text{size})为 512,1024 \times 200 的 \text{SoM} 记忆图约 784 视觉 \text{token},会报 $input too large;插件的 embedding/combined 自动启动默认传-ub 2048。 - 实测:
- 当前 llama.cpp 构建在
--embeddings --pooling mean下同时支持/v1/chat/completions和/v1/embeddings,因此 OCR 与视觉 embedding 可共用同一个 18080 服务; - marker-only 请求
prompt_tokens=785; - 空文本
input:""的prompt_tokens=1; - 直接视觉 token = 784,embedding 维度 = 1280;
- 服务端已按欧氏范数归一化(
--embd-normalize 2默认)。
- 当前 llama.cpp 构建在
- 插件已集成:
measureImageEmbedding/createEmbeddingHttpClient,并在visualMemory中持久化embedding、embeddingDim、visualTokensDirect。
8. 关键结论
- 插件核心已能真实调用 DeepSeek-OCR 读图。
- 隔离临时环境测试通过;当前
npm test为 88/88(真实后端在线时 0 skip;后端不可用时 8 个 live-backend 用例跳过)。 - 新增
ocr1_mem_metrics工具:按官方分辨率模式估算文本 token / 视觉 token 压缩比,并记录真实 OCR 请求的usage.prompt_tokens和近似视觉 token 数。 - 新增
ocr1_mem_update工具:支持显式更新记忆,用于冲突消解/最新值覆盖。 - 新增
scripts/start-ocr-server.ps1、scripts/ensure-ocr-server.mjs、lib/ocr-server.js。 - 插件新增
autoStartOcrServer配置:启用后插件加载时自动确保 llama-server 在线;ocrBaseUrl的显式端口决定健康检查/启动端口,外部已运行服务不会被插件停止。 - 对比基准(
BENCHMARK.md、scripts/compare-memory.mjs):R1–R6 已用修正后脚本完整重跑;dsh-ocr1-memory 全部通过;dsh-memory 本次也全部通过,但 R5 此前手动验证曾 FAIL(归档后仍可读到),行为不稳定;R4 现在有显式 update 能力。 - DSH 级 R1–R6 已在隔离 headless 环境完成完整对比(不 kill 进程,后台运行):dsh-ocr1-memory 全部 PASS。
- 已实现 robustness 增强:多 Agent 共享 store(
sharedStore)、图像缺失/缓存损坏自动恢复、超长输入边界测试、纯查询 list、bounded tier refresh 与 renderer 取消传播。 - 维护路径现为有界、可取消、按 namespace single-flight;
maintenanceBatchSize默认 8,插件卸载会取消并等待自动维护。 - 现已通过 llama.cpp
/v1/embeddings的 marker-only 请求存储真实 1280 维 DeepSeek-OCR 视觉 embedding,并测量直接视觉 token 数(marker-onlyprompt_tokens− 空文本基线);当前 probe 为785−1=784。 - 已实现视觉 embedding 相似度检索:
measureTextEmbedding嵌入查询,retrieveSegmentsWithEmbeddings按余弦相似度参与排序;由于跨模态区分度验证不足,插件默认关闭embeddingRetrieval,不把它作为无条件的主检索信号。 - 已调研通用 agent 记忆测试规范(MemoryAgentBench / LongMemEval / LoCoMo / AMB),并整理成
TEST_SPEC.md;R1–R6 与这些规范一一映射。 - 尝试“无微调让 DeepSeek-OCR 直接输出 SoM 编号”的实验:当前 llama.cpp 后端在自定义 locate prompt 下输出不可靠(返回无关文本而非编号),因此在不做 LoRA 的前提下,论文原版 Locate(模型输出编号)不可推进。当前插件的
opticalLocatorStrict路径仍要求兼容的已训练定位模型,并在 malformed 输出时拒绝文本回退。
9. LoRA 光学定位器:本机实跑推进(2026-08)
9.1 环境与工具链(WSL2 / RX 7800 XT / ROCm)
- 独立训练 venv
/root/ocr1-train-env:torch 2.11.0+rocm7.2 + torchvision 0.26.0+rocm7.2 + transformers 4.57.2 + trl 0.24 + unsloth 2026.8.22 + bitsandbytes 0.50 + datasets 5.0.1。 - 关键坑(详见记忆 SOP):
- WSL 必须删除 PyTorch wheel 自带
torch/lib/libhsa-runtime64.so*才见 GPU(否则get_device_capability为 None); - transformers ≥5 与 DeepSeek-OCR 旧 remote code 不兼容(strict dataclass
kv_lora_rank=None、DeepseekV2Moe/MoE命名差),须用 4.57.x + MoE 别名补丁; - Unsloth
UnslothVisionDataCollator只支持带image_processor的模型,DeepSeek-OCR 没有 → 自写 collator。
- WSL 必须删除 PyTorch wheel 自带
9.2 训练输入(官方格式,来自 HF remote code 与 vLLM processor)
images=[(patches, global_view)],global_view=(1,3,1024,1024)归一化,patches空时为(0,3,640,640);配images_seq_mask(<image>id 128815 处 True)、images_spatial_crop=[[1,1]]。- tokenizer 单 token 监督:
0→18、1→19;只监督 target 区间(prompt/image/space/EOS 均为 -100)。HotpotQA 每样本约 2 正/8 负,代码默认w+=4,w-=1做频率平衡(论文仅披露w+>w-,未给具体值)。 - 生成必须遵循训练语法
digit space digit ... digit EOS;若强制只允许 0/1 而禁空格,autoregressive 上下文会立即漂移。
9.3 实证结果(2026-08-28)
训练集 300 条(seed=7)与评估集 30 条(seed=42)ID 零重叠。评估严格使用同一语法约束;下表为前 12 条独立评估样本:
| 阶段 | 配置 | 结果 |
|---|---|---|
| base(无 LoRA) | 相同二元语法约束 | exact 0/12,mean F1 0.139 |
| LoRA 中间里程碑 | 300 条×3 epochs,lr 1e-4,旧 w+=2 | exact 1/12,mean F1 0.375 |
| 单样本过拟合 | 100 steps,lr 1e-3,w+=4 | exact 1/1,F1 1.000;15 步后 loss≈0 |
结论:完整训练/视觉/监督/自回归解码闭环成立;300 条 LoRA 相比 base 的 mean F1 约 2.7×。当前默认代码已进一步修正:target 对齐自测、EOS 不监督、空格语法约束、w+=4 类别平衡、正确梯度累积。尚未宣称复现论文主表,因论文使用更大 HotpotQA 训练规模及 Mind2Web/AppWorld/RULER 等评测。
9.4 运行时与训练分离
- 训练:WSL ROCm,允许占用独显(本次验证耗时数分钟至 1 小时级)。
- 运行时(检索):llama-server 默认用 CPU-only 构建(
<models>\llama.cpp-cpu\),不占独显;已实测 CPU 版 OCR/embedding 端到端可用,DSH 隔离 headless 用官方 V4 Flash 验证通过。 - 距离论文主表级完整复现仍缺:
- DeepEncoder 内部逐层输出的纯 visual token 数量(当前 llama.cpp 运行时仅有接口统计);
- 按论文真实训练规模跑满 HotpotQA,并复现 Mind2Web/AppWorld/RULER/Mind2Web retrieval subset 指标;
- 将 LoRA 合并/量化为 CPU 可运行的 GGUF,并接入
opticalLocatorEnabled做 DSH 端到端 Locate 工具验证。