EasyOCR 图片文字提取,能不能交给走 TaoToken 的 Codex 按 Agent Loop 一步步试?
2026/9/18 20:38:03 网站建设 项目流程

用 EasyOCR 从图片里提文字,langchain 把 python 脚本包成 tool,本来就不长;麻烦在出错之后要一轮轮改。TaoToken(https://taotoken.net/?utm_source=taotoken_aicg_blog_end)在这里的作用,是把这轮循环里的模型调用收成一条通道,再让 Codex CLI 按 Agent Loop 自己试:先 ls 看目录,再跑脚本撞报错,再补依赖,每一步 tool_call 的真实输出都要回填进下一轮 prompt。

整个过程最容易被忽略的一点是:Agent Loop 的轮数并不写死在代码里。图片路径不对是一轮,easyocr 没装是一轮,检测模型权重下载失败又是一轮,每一轮都要重新问一次模型。如果这几轮的请求分别打到不同的 key、不同的地址上,事后连“这轮为什么改了这行”都对不上账。所以先把通道收拢,再谈让 Codex 自己收敛。

1. EasyOCR 提字脚本不长,难的是它出错以后那几轮

1.1 一份能跑的 langchain + EasyOCR 最小脚本

先从最小可运行单元开始。下面这段代码把 EasyOCR 的 Reader 封成一个 langchain 工具,任何支持 tool calling 的 Agent 都能调用它。注意 Reader 在初始化阶段就会去下载检测模型和识别模型,这一步在离线环境或者网络抖动时最容易失败,后面排障会专门讲。

import easyocr from langchain_core.tools import tool # 首次初始化会下载检测/识别模型到 ~/.EasyOCR/model reader = easyocr.Reader(["ch_sim", "en"], gpu=False) @tool def ocr_image(image_path: str) -> str: """提取本地图片中的文字,按段落返回纯文本。""" blocks = reader.readtext(image_path, detail=0, paragraph=True) return "\n".join(blocks)

把工具挂进 Agent 之后,模型只负责决定“下一步要不要调 ocr_image、传入哪个路径”,真正的识别结果由 EasyOCR 返回。这个分工和 Codex 的循环是一致的:模型永远只输出动作,工具负责产出事实。

1.2 图片文字提取天然是个要跑好几轮才收敛的任务

图片文字提取不像写个排序函数,一次就能写对。它依赖的东西太多:图片本身是不是清晰、路径里有没有中文和空格、opencv-pythonnumpy的版本搭不搭、torch 装的是 CPU 版还是 CUDA 版、Reader 的语言参数写没写对。任何一项不对,脚本就在某一行为你停住,然后你只能看报错、改一行、再跑。

人手动改一次大概五分钟,但如果是让 Agent 来做,这个“看报错—改—再跑”就是好几轮模型调用。轮数越多,越能体现统一通道的价值:不然你排查到第三轮,已经说不清这条请求是谁花的额度。

2. Codex CLI 的 Agent Loop 拆开看,卡点只在一行 self.llm(prompt)

2.1 五步循环:goal、build_prompt、self.llm、execute_tool、回填

把 Codex CLI 的循环拆开,其实就是五步:

  1. 接收用户目标 goal,比如“让 ocr_demo.py 能跑出图片里的文字”;
  2. build_prompt把 goal 和self.history打包成一条 prompt;
  3. self.llm(prompt)只决定“下一步干什么”,输出要么是自然语言回答,要么是一个 tool_call;
  4. 命中 tool_call 就execute_tool,真正去ls、去跑npm startpython ocr_demo.py
  5. 把工具的真实输出塞回上下文,开始新一轮。

这五步里,前两步和最后一步是本地整理数据,第四步是真执行命令,只有第三步在花钱——self.llm(prompt)才是那次真实的模型调用。痛点也就落在这:while True什么时候结束不写死,模型觉得搞定了才停,中间可能三轮,也可能八轮。

2.2 为什么第二步的 history 决定后面几轮能不能省下来

self.history里塞的是每一轮工具的真实输出。如果第一轮ls的结果没进去,第二轮模型可能又去ls一遍;如果第二轮 python 的报错没进去,第三轮它就只能靠猜。所以“跑通”这件事,一半靠通道稳,一半靠 history 完整。

很多人的 Loop 跑着跑着就绕圈,原因不是模型笨,而是工具输出被截断成了“命令执行失败”这种没有信息量的字符串。把 stderr 原文带上,模型往往下一轮就能改对。

3. 把 Codex 的 base_url 指到 TaoToken,再让循环跑起来

3.1 先去控制台拿 Key,顺手把模型 ID 抄下来

打开 TaoToken 注册登录,在控制台里创建一个 API Key,然后进模型广场看你打算用哪个模型,把模型 ID 原样复制下来——别凭印象自己拼后缀,模型列表随时会更新,以模型广场当时显示为准。

拿 Key 的入口在 控制台 API Keys,创建完只显示一次,先存到本地环境变量里,不要直接提交进仓库。

export TAOTOKEN_API_KEY=YOUR_API_KEY

3.2 ~/.codex/config.toml 里只改三处

Codex 用的是 TOML 配置,不是 JSON,也不是环境变量一套。把~/.codex/config.toml打开,改成下面这样:

model = "你在模型广场选好的模型 ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

三个点要盯住:model用的是模型 ID,不是显示名;base_url末尾不要加/v1,多一段就会 404;env_key写的是变量名,不是 Key 本身,Key 交给环境变量读。

注意:Codex 的环境变量是TAOTOKEN_API_KEY,不要往里套ANTHROPIC_*那套,两套配置属于不同工具,混用只会互相干扰。

3.3 怎么确认这一步真的接到了统一通道

改完先别急着跑大任务。在终端里跑一次最简单的对话,看它有没有正常回话;再回到 TaoToken 模型对话 用同一把 Key 发一条消息,确认模型 ID 也是通的。两边都通,说明 Key、base_url、模型 ID 这三样都对上了,接下来 Loop 里的每一轮调用都会记到同一个账号下。

4. 让 Codex 按 Agent Loop 修 EasyOCR:三轮的真实形状

4.1 第一轮:先 ls,不动手

把 goal 说清楚,比如“当前目录下有个 ocr_demo.py,用的是 langchain + EasyOCR,现在跑不起来,想办法让它能提取 sample.png 里的文字”。第一轮模型通常不会直接改代码,而是先ls看目录结构,确认脚本名、有没有 requirements.txt、有没有 sample.png。

这一轮的意义是给 history 塞入事实基线。目录里有什么,后面几轮就不会出现“我以为你有 requirements.txt”这种错误假设。

4.2 第二轮:跑脚本,撞上 ModuleNotFoundError

有了目录信息,第二轮的 tool_call 多半是执行python ocr_demo.py。真实输出会是这样:

Traceback (most recent call last): File "ocr_demo.py", line 1, in <module> import easyocr ModuleNotFoundError: No module named 'easyocr'

这条 stderr 原样回填进 history 之后,第三轮模型就不需要猜了——它会给出pip install easyocr或者pip install -r requirements.txt。关键在于:命令由 Codex 给出,执行要落在你自己的终端环境里,跑完把输出贴回对话,而不是让工具去连接任何外部业务系统。

4.3 第三轮:补依赖、处理权重下载、再跑一次

装完依赖重跑,第二个坑往往紧跟而来:Downloading detection model, please wait卡住,或者直接抛出下载失败。这时候可以让 Codex 读你的报错,把 Reader 改成指定本地模型目录的写法,先把权重放到固定位置再复用。

reader = easyocr.Reader( ["ch_sim", "en"], gpu=False, model_storage_directory="./.EasyOCR/model", download_enabled=True, )

路径里带中文或空格也常导致识别阶段异常,把图片路径换成Path("sample.png").resolve().as_posix()再传进去,能避开不少莫名其妙的报错。

4.4 收敛的判据:history 里有没有上一轮的真实输出

判断 Loop 是不是真在往前走,看两个信号:一是每一轮 tool_call 返回的内容比上一轮更有信息量,从“命令执行失败”变成具体的报错行;二是模型不再重复同一个动作。如果它连续两轮都在ls,说明第一轮的结果没进上下文,优先查这一层,而不是急着换模型。

真正的收敛状态很朴素:脚本跑完,终端里打印出 sample.png 里的几行文字,模型说“已经可以提取了”,循环结束。这时候整条 Agent Loop 的每一次模型调用,都走的是同一把 Key、同一个 base_url。

5. EasyOCR + langchain 报错对照:哪类改代码,哪类改通道

5.1 依赖与版本类报错

ModuleNotFoundError: No module named 'easyocr'是最直白的一类,装就行。麻烦的是装了还报错:numpy升到 2.x 之后,某些 torchvision 版本会直接崩;opencv-pythonopencv-python-headless同时存在,也会互相打架。遇到这类,先pip list | grep -E "torch|numpy|opencv"看清实际版本,再决定是降级还是换成 headless 版本。

5.2 权重下载与图片读取类报错

Downloading detection model failed基本都出在网络或磁盘权限上,指定model_storage_directory后重试通常能过。cv2.error多半是图片路径或格式的问题,先把图片转成标准 PNG 再试。中文路径建议统一用pathlib处理,避免拼接字符串时踩到编码问题。

5.3 通道类报错,别去改业务代码

这一类错误和 EasyOCR 没关系,改脚本也修不好:

现象大概率原因处理
401Key 没设进环境变量,或写错变量名确认TAOTOKEN_API_KEY已 export,值用YOUR_API_KEY占位处替换
404base_url多写了/v1,或漏了/api写回https://taotoken.net/api
模型不存在模型 ID 凭印象拼的以模型广场当时列表为准重新复制

排障的顺序建议是:先看报错里有没有 URL 和状态码,有就先查通道;只有报错落在 python 堆栈里,才回去看 EasyOCR 那一层。

6. 循环跑通之后,去对一下这次的账

6.1 用同一把 Key 再复测一次

Agent Loop 跑通不代表配置百分百稳。换一张图、换一段文字,让 Codex 再走一轮,观察它是不是第一轮就去调 ocr_image,而不是重新试依赖。同时打开具体页面看这次调用有没有记上账,确认模型 ID 和你填的一致。

如果打算长期把改脚本这类活交给 Agent,可以先看一眼 Coding Plan 的额度是否够用;要多建几把 Key 分环境,再回 控制台 API Keys 创建。

6.2 下一步:把这套接法复制到别的脚本任务上

EasyOCR 只是一个例子。任何“跑一次就报错、改一行再跑”的任务——批量转格式、清洗 CSV、跑一次测试——都可以用同样的方式交给 Codex,前提是~/.codex/config.toml里的 base_url 一直指着https://taotoken.net/api,Key 一直从 TaoToken 控制台取。想让 Agent 试着修更多脚本,先去 模型对话 里把模型 ID 和通道各测一次,再回 Codex 里放开轮数,这样每一轮的账都落在你能看到的地方。

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

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

立即咨询