dsh-vision-ocr
September 12, 2026 · View on GitHub
给纯文本模型的"视觉替身"插件:通过调用本机 CLI 工具(默认 tesseract,可选 YOLO 风格检测器),让模型从本地图片里读文字、检出物体。所有子进程调用都走一条可注入的 runCommand 缝(seam),因此单元测试完全确定性、永不真正启动二进制进程;无网络、无模型调用、无常驻进程(每次调用是一次超时会杀掉的短命 spawn)。
三个工具
| 工具 | 参数 | 说明 |
|---|---|---|
ocr_image | imagePath,可选 languages | 执行 [ocrCommand, imagePath, 'stdout', '-l', langs],返回 { ok, text, exitCode, stderrTail, error }。OCR 可执行文件缺失(ENOENT)时优雅返回 error: 'ocr executable not found',不抛异常。 |
detect_objects | imagePath,可选 threshold | 未配置 detectCommand 时直接返回 { ok:false, skipped:true, reason:'no detector configured', objects:[] }(不 spawn)。否则执行稳定契约 [detectCommand, '--source', imagePath, '--json'],把 JSON stdout 解析为 objects:[{label, confidence, box:[x,y,w,h]}];输出不可解析时返回 error: 'detector output not JSON'。 |
describe_scene | imagePath,可选 languages | 组合调用:先走 OCR 路径,若配置了检测器再走检测路径,产出纯文本摘要 summary,形如 OCR found 123 chars; 2 objects detected: cat, remote。 |
三个工具均 isConcurrencySafe() === true,可并行调度。
配置(YAML)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ocrCommand | string | tesseract | OCR 可执行文件 |
detectCommand | string | '' | 可选目标检测器可执行文件;空串 = 禁用检测 |
ocrLanguages | string | eng | 传给 -l 的语言列表(如 eng+chi_sim) |
timeoutMs | number | 15000 | 每次 spawn 的硬超时(毫秒) |
maxOutputChars | number | 20000 | 返回给模型的 OCR 文本上限(字符) |
依赖与可用性
- 要真正可用,需要在主机 PATH 上安装
tesseract(推荐同时装对应语言包,如tesseract-ocr-chi-sim)。 - 目标检测为可选项:需要自备一个符合契约的 YOLO 风格 CLI——入参
--source <图片> --json,stdout 输出 JSON(顶层数组或{ objects: [...] }信封均可),每条含label、confidence、box:[x,y,w,h]。 - 二进制缺失不会让插件报错:相关工具会以
ok:false+ 说明性error优雅降级。
安装
npx -y @deepseek-ai/dsh plugin --profile web add @qingshanjiluo/dsh-vision-ocr
测试注入缝(对宿主/测试可见)
apply(ctx, config) 接受可选的 config.runCommand(不属于 YAML 配置,由宿主或测试注入):
type RunCommand = (argv: readonly string[], timeoutMs: number) =>
{ code: number | null; stdout: string; stderr: string; error?: string }
缺省实现 defaultRunCommand 使用 node:child_process 的 spawnSync(无 shell、带超时、绝不抛出,ENOENT 映射为 error: 'ENOENT')。单元测试注入假 runner,因此从不真正调用 tesseract 或任何真实二进制。
开发
npm install --no-audit --no-fund
npm run build # tsc + tsdown → lib/
npx vitest run # 行为测试(全假进程)
node scripts/load-smoke.mjs