agent-vision-toolkit 排障:TaoToken 下 OCR 工具没输出
2026/9/19 1:18:13 网站建设 项目流程

1. 先复现:agent-vision-toolkit OCR 在 Codex 里“静默无输出”的现场

这次排障的起点是 TaoToken(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=ocr-debug-intro)。场景很具体:你用 Codex 或 DeepSeek agent 做文本推理,agent-vision-toolkit 负责把长截图 OCR 成文字;文本模型本身看不了图,所以它必须先让 shell 调用 OCR 工具,再把 OCR 结果当成文本读进去。结果你让 agent “识别这张报错截图”,它回复了一句“已处理”,但聊天里没有 OCR 文本,shell 日志里也没有 stdout,echo $?却是 0。更迷惑的是,TaoToken 侧的文本推理请求正常计费,说明 agent 并没有完全挂掉,只是视觉工具那一段像被吞掉了。

先把 Key 和 Base URL 对齐:去 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=ocr-debug-key 拿到YOUR_API_KEY,然后把文本推理的 Base URL 填为https://taotoken.net/api。注意,OCR 本身通常不消耗模型 Token,消耗 Token 的是 Codex/DeepSeek agent 的文本推理:它要判断“现在该不该调用 OCR”,要读 OCR 返回的文字,还要继续推理报错原因。所以 OCR 没输出,不一定是模型坏了,很可能是 harness 没有真正把图片路由到 OCR 工具。

先做最小复现,不要一上来就重装 agent-vision-toolkit。准备一张长截图:

mkdir -p fixtures # 把你的报错长截图放到 fixtures/error-long.png ls -lh fixtures/error-long.png

下文用$AVT_OCR指代你在 agent-vision-toolkit 仓库里实际使用的 OCR 入口。它可能是python -m ...uv run ...,也可能是打包后的命令。先把它解析成绝对路径,避免 agent 工作目录漂移:

export AVT_OCR="$(command -v your-ocr-entry || true)" if [ -z "$AVT_OCR" ]; then echo "OCR 入口不在 PATH,先把 agent-vision-toolkit 的 OCR CLI 路径填进来" export AVT_OCR="/absolute/path/to/agent-vision-toolkit/ocr-entry" fi "$AVT_OCR" --help | head -40

错误复现通常长这样:

$ export TAOTOKEN_API_KEY="YOUR_API_KEY" $ export OPENAI_BASE_URL="https://taotoken.net/api" $ "$AVT_OCR" --image fixtures/error-long.png $ echo $? 0

没有任何文本输出,退出码还是 0。这并不代表 OCR 成功,只代表脚本没有抛异常。你需要把 stderr 和 debug 日志一起抓出来:

"$AVT_OCR" --image fixtures/error-long.png --debug 2>&1 | tee ocr-debug.log wc -c ocr-debug.log

如果ocr-debug.log也是空的,问题大概率在更上层:agent 根本没调用 OCR,或者 shell 调用被沙箱拦了。接下来看 agent 侧日志:

codex --config ~/.codex/config.toml --log-level debug 2>&1 | tee codex-ocr.log grep -n -E "tool_call|shell|ocr|stderr|exit_code" codex-ocr.log | tail -80

如果日志里没有tool_call,说明文本模型只是“口头答应”,并没有发起工具调用。如果日志里有tool_call,但stdout_bytes=0stderr_bytes=0,说明命令执行了但没有产出。如果exit_code=127,那就是 PATH 或命令名不对。排障要分层,不要把所有问题都归因于模型。

2. 把文本推理切到 TaoToken:Codex config.toml 与 CC Switch 三件套

OCR 工具是本地 shell 能力,但 agent 的“判断、读结果、继续推理”走的是文本模型。为了让 Codex 稳定调用工具,先把文本推理接好。进入 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=ocr-debug-models 确认可用模型名,然后编辑~/.codex/config.toml

model = "gpt-5-codex" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "responses"

环境变量这样加:

export TAOTOKEN_API_KEY="YOUR_API_KEY" # 有些工具会读 OPENAI_BASE_URL,Codex 以 config.toml 的 base_url 为准 export OPENAI_BASE_URL="https://taotoken.net/api"

验证文本推理是否通:

codex exec "只输出两个字符:OK"

如果这里返回 401、404、模型不存在,或者一直空回复,先修模型配置。因为 agent 连“要不要调用 OCR”这一步都完不成,后面的 OCR 工具自然没有输出。

如果你用 CC Switch 做多配置切换,要同步三件套:Base URL 填https://taotoken.net/api,API Key 填YOUR_API_KEY,模型名填你实际可用的模型。三件套任意一个不一致,都会出现“看起来切换了,实际还在旧端点”的假象。尤其注意:Codex 用config.tomlTAOTOKEN_API_KEY,不要把 Claude Code 的ANTHROPIC_*变量套到 Codex 上;两套配置混用,最常见的表现就是文本推理请求发错端点,agent 直接静默失败。

切换完成后,再跑一次最小文本调用,保存日志:

codex exec "请用一句话说明:当你看到 .png 文件时,应该先调用 OCR 工具,而不是直接读取二进制。" | tee text-route.log

这一步不是形式主义。它验证了模型能接收“图片要路由到 OCR”的指令。很多 OCR 没输出的根因,不在 OCR 引擎,而在文本模型没有把图片路径当成工具调用参数。

3. OCR 工具没输出的根因树:从 shell 调用、PATH、skill 判据到长图分片

排 OCR 没输出,建议按下面顺序查,不要跳步。

第一层,agent 是否真的发起了 shell 调用。看codex-ocr.log里有没有类似:

tool_call shell: $AVT_OCR --image /abs/path/fixtures/error-long.png --lang chi_sim+eng tool_result exit_code=0 stdout_bytes=0 stderr_bytes=0

如果只有 assistant 的自然语言,没有tool_call,说明 skill 判据没命中。纯文本模型看不到图片像素,如果你只是在对话里说“看这张图”,agent 可能把它当成普通附件,直接跳过。修复方式是把图片绝对路径作为文本传进去:

请对 /home/dev/project/fixtures/error-long.png 调用 OCR 工具,输出完整文字,不要总结。

第二层,shell 是否被沙箱拦截。典型日志:

command not found: your-ocr-entry permission denied: /absolute/path/to/ocr-entry

解决办法是给绝对路径、确认可执行权限,并把 OCR 入口所在目录加入 PATH:

chmod +x "$AVT_OCR" export PATH="$(dirname "$AVT_OCR"):$PATH" "$AVT_OCR" --version

第三层,OCR 依赖是否完整。长截图 OCR 常见依赖包括 tesseract 二进制、语言包、Python 图像库。验证命令:

which tesseract tesseract --list-langs python -c "import pytesseract, PIL; print('python deps ok')"

如果tesseract --list-langs没有chi_sim,中文截图 OCR 会输出空文本或乱码。安装语言包后重试:

sudo apt-get install -y tesseract-ocr tesseract-ocr-chi-sim tesseract-ocr-eng

第四层,长图是否超过默认限制。长截图高度可能上万像素,某些 OCR 实现会静默失败,或者只处理第一屏。加 debug 参数,观察图片尺寸和分片数量:

"$AVT_OCR" --image fixtures/error-long.png --debug --lang chi_sim+eng 2>&1 | tee ocr-long.log grep -E "size|chunk|height|timeout|memory" ocr-long.log

第五层,输出是否被 harness 吞掉。有些 OCR 脚本把结果写到文件,stdout 只打印“done”。agent 读到的是“done”,自然没有文字。修复方式是在 skill 或包装脚本里强制 stdout 输出 OCR 正文,同时保留文件路径:

"$AVT_OCR" --image "$IMG" --lang chi_sim+eng --format txt 2>&1

第六层,图片路径是否在工作目录之外。agent 的工作目录和你的终端不一定相同。统一用realpath

IMG="$(realpath fixtures/error-long.png)" "$AVT_OCR" --image "$IMG" --lang chi_sim+eng --format txt

第七层,skill 是否要求 agent“先判断再调用”。如果 skill 写得含糊,比如“需要时使用视觉工具”,模型可能认为“不需要”。把触发条件写死:遇到.png/.jpg/.jpeg/.webp路径、遇到“截图/报错图/设计图”关键词、遇到用户要求 OCR,都必须先调用 OCR,再把结果读回来。

4. 修复后配置:让 Codex/DeepSeek agent 稳定触发 OCR 的 shell 包装

最稳的做法是不要直接让 agent 拼 OCR 命令,而是给它一个固定包装脚本。创建scripts/agent_ocr.sh

#!/usr/bin/env bash set -euo pipefail IMG="${1:?usage: agent_ocr.sh <image> [lang]}" LANG_OPT="${2:-chi_sim+eng}" AVT_OCR="${AVT_OCR:?请先 export AVT_OCR=/abs/path/to/ocr-entry}" if [ ! -f "$IMG" ]; then echo "[agent_ocr] file not found: $IMG" >&2 exit 2 fi ABS_IMG="$(realpath "$IMG")" echo "[agent_ocr] image=$ABS_IMG lang=$LANG_OPT" >&2 # 关键:stdout 只给正文,stderr 给诊断,方便 agent 读正文 "$AVT_OCR" --image "$ABS_IMG" --lang "$LANG_OPT" --format txt

赋予执行权限并验证:

chmod +x scripts/agent_ocr.sh export AVT_OCR="/absolute/path/to/agent-vision-toolkit/ocr-entry" ./scripts/agent_ocr.sh fixtures/error-long.png chi_sim+eng | tee ocr-fixed.txt wc -c ocr-fixed.txt

修复后的日志应该能看到正文长度:

[agent_ocr] image=/home/dev/project/fixtures/error-long.png lang=chi_sim+eng [avt-ocr] engine=tesseract 5.3.0 [avt-ocr] chunks=7 chars=7462 elapsed=18.4s Traceback (most recent call last): File "app.py", line 42, in <module> raise RuntimeError("missing DATABASE_URL") RuntimeError: missing DATABASE_URL

注意,上面Traceback是截图里的报错内容,不是你的脚本报错。区分这一点很重要,否则你会把 OCR 成功识别出的报错误判成 OCR 失败。

然后在 Codex 侧固定调用方式。可以在项目根目录放一个CLAUDE.md或 skill 说明,明确要求:

遇到图片路径时,必须执行: scripts/agent_ocr.sh <absolute-image-path> chi_sim+eng 再把 stdout 原文读入上下文,禁止只回复“已处理”。 如果 exit_code 非 0,先输出 stderr 前 80 行,再决定是否重试。

再跑一次 agent 任务:

codex exec "请读取 fixtures/error-long.png 里的报错,用三行总结原因。必须调用 scripts/agent_ocr.sh。"

如果模型配置正确、skill 判据明确、包装脚本 stdout 干净,agent 端日志会出现:

tool_call shell: scripts/agent_ocr.sh /home/dev/project/fixtures/error-long.png chi_sim+eng tool_result exit_code=0 stdout_bytes=7462 assistant: 截图中的关键报错是缺少 DATABASE_URL,应用启动时读取环境变量失败...

到这一步,OCR 没输出的问题才算真正闭环:不是“模型突然会看图了”,而是 harness 把图片转成文本,文本模型继续做推理。

5. 长截图 OCR 的稳定化:分片、超时、日志与最小回归

长截图是 OCR 没输出的高发区。很多脚本在处理小图时正常,一遇到高度 8000px 以上的截图就静默返回空。解决思路是分片 OCR,再按顺序合并。下面是一个不依赖特定 OCR 实现的 Python 分片脚本:

from pathlib import Path from PIL import Image import subprocess import os import sys IMAGE = Path(sys.argv[1]).resolve() OUT = Path("ocr-merged.txt").resolve() CHUNK_H = 1800 OVERLAP = 120 AVT_OCR = os.environ["AVT_OCR"] img = Image.open(IMAGE) w, h = img.size chunks = [] top = 0 idx = 0 while top < h: bottom = min(top + CHUNK_H, h) chunk_path = IMAGE.with_name(f"{IMAGE.stem}.chunk-{idx:03d}.png") img.crop((0, top, w, bottom)).save(chunk_path) chunks.append(chunk_path) if bottom == h: break top = bottom - OVERLAP idx += 1 with OUT.open("w", encoding="utf-8") as out: for chunk in chunks: out.write(f"\n===== {chunk.name} =====\n") proc = subprocess.run( [AVT_OCR, "--image", str(chunk), "--lang", "chi_sim+eng", "--format", "txt"], capture_output=True, text=True, timeout=120, ) out.write(proc.stdout) if proc.returncode != 0: out.write(f"\n[stderr]\n{proc.stderr}\n") chunk.unlink(missing_ok=True) print(f"merged -> {OUT} chars={OUT.stat().st_size}")

运行:

export AVT_OCR="/absolute/path/to/agent-vision-toolkit/ocr-entry" python scripts/ocr_long.py fixtures/error-long.png wc -c ocr-merged.txt

分片时注意三点:每片高度不要超过 OCR 引擎舒适区;片与片之间留重叠,避免行被切断;每片设置超时,避免某一片卡死导致整体无输出。最小回归用例也很重要:找一张包含固定错误码的长截图,比如E_CONN_REFUSED_104,每次修复后都要求输出必须包含这个字符串。这样你就能区分“OCR 完全没跑”和“OCR 跑了但识别质量差”。

如果你在 Codex 或 DeepSeek agent 里执行,建议把分片和合并也封装成一条 shell 命令,让模型只负责读合并后的文本:

python scripts/ocr_long.py fixtures/error-long.png && sed -n '1,120p' ocr-merged.txt

6. 把 OCR 工作流接到 Claude Code:settings.json 与 ANTHROPIC_* 不串到 Codex

如果你同时用 Claude Code 做 agent 排障,配置方式不同。Claude Code 走settings.jsonANTHROPIC_*,不要把这套变量复制到 Codex 的config.toml场景里。示例:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }

保存后验证:

claude -p "只输出 OK"

然后在 Claude Code 项目说明里加入 OCR 路由规则:

当用户提供 .png/.jpg/.jpeg/.webp 路径,或提到“截图/OCR/报错图”,必须先执行: scripts/agent_ocr.sh <absolute-path> chi_sim+eng 读取 stdout 后再回答。若 stdout 为空,执行: scripts/agent_ocr.sh <absolute-path> chi_sim+eng 2>&1 | tail -80 并把 stderr 原文贴出来。

Claude Code 侧的常见坑和 Codex 类似:只给相对路径、沙箱不允许执行脚本、AVT_OCR环境变量没继承、TESSDATA_PREFIX没设置。可以显式检查:

echo "$ANTHROPIC_BASE_URL" echo "$AVT_OCR" echo "$TESSDATA_PREFIX"

如果 Base URL 不是https://taotoken.net/api,或者 Key 还是旧值,先修配置。Claude Code 文档入口放在文末 CTA,需要时按官方文档对齐字段名。

7. 成本与边界:文本推理走 TaoToken,OCR 本地跑,不要把图片硬塞给文本模型

agent-vision-toolkit 这类工具的价值,不是让纯文本模型突然拥有像素级视觉,而是把“看图”拆成两步:本地 OCR/UI 工具先把图片转成结构化文本,文本模型再读文本。这样做有两个直接好处:第一,文本推理可以继续走 Codex/DeepSeek 这类成本更可控的模型;第二,图片不必上传到模型侧,OCR 在本地 shell 完成,适合私有化或敏感截图场景。

边界也要说清楚:OCR 对“报错文字、日志、聊天记录、设计图标注”这类结构化信息很有效;但“这个配色好不好看”“这个图标有没有设计感”这类审美判断,工具替代不了原生多模态模型。你的排障目标如果是“让 agent 读出截图里的报错并继续推理”,那 OCR 工具足够;如果是“让 agent 理解复杂视觉语义”,就要换模型或补多模态能力。

回到本次排障:OCR 没输出时,不要先怀疑模型能力。按顺序查 agent 是否发起 tool_call、shell 是否执行、OCR 依赖是否完整、长图是否分片、stdout 是否被吞、路径是否为绝对路径。修复后保留三样东西:错误复现的ocr-debug.log、修复后的ocr-fixed.txt、以及 Codex/Claude Code 的最终配置。下次再遇到“OCR 静默无输出”,直接拿最小回归用例跑一遍。

8. 文末 CTA:模型对话 → Coding Plan → 创建 Key → Claude Code 文档

如果你还没把文本推理接好,建议按下面路径走一遍:

  1. 先试模型对话,确认文本推理可用:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=ocr-cta-chat
  2. 需要长期跑 agent 排障,看 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=ocr-cta-plan
  3. 创建并管理 Key,把YOUR_API_KEY换成真实值:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=ocr-cta-key
  4. Claude Code 配置细节看官方文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=ocr-cta-claude

最后再强调一次配置要点:Codex 用config.toml+TAOTOKEN_API_KEY,Claude Code 用settings.json+ANTHROPIC_*,两者不要混用;Base URL 统一填https://taotoken.net/api,不要带 UTM;Key 占位符用YOUR_API_KEY。把 OCR 工具包装成固定脚本,强制 stdout 输出正文,长截图先分片,agent 端日志留档。这样再遇到 agent-vision-toolkit 的 OCR 工具没输出,你就能在十分钟内定位到是模型路由、shell 调用、依赖缺失还是长图分片问题,而不是反复重装工具。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询