拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

解决 Codex 接入 Deepseek 后不能识别图片:用开源 Skill 让截图直接可读

解决 Codex 接入 Deepseek 后不能识别图片:用开源 Skill 让截图直接可读

1. Codex 接入 Deepseek 后图片识别失效的真实场景

Codex 本身是个偏代码理解与生成的 CLI 工具,它的强项是读文件、跑命令、改代码。但很多人把它接上 Deepseek 之后,会默认以为"既然模型能聊天,那应该也能看图"。结果把一张报错截图粘进去,Codex 要么回你一句"我看不到图片内容",要么干脆把图片路径当成普通文本处理,返回一堆无关的代码建议。这个现象在本地开发和自动化截图分析场景里特别常见:你跑完测试生成了一张失败截图,想让 Codex 直接读图定位问题,它却像个"文盲"一样干瞪眼。

问题的根子不在 Codex,也不在 Deepseek 的文本能力,而在于多模态输入这条链路根本没打通。Deepseek 的对话接口默认走的是纯文本 chat/completions,你传图片进去,它要么忽略,要么报参数错误。Codex 作为客户端,也没有内置"把图片转成视觉模型能吃的格式"这一步。所以整条链路缺了一个中间层:把图片编码、发给一个真正支持视觉的模型、再把识别结果带回 Codex 的对话上下文。

我试过直接改 Codex 的配置去指向某个视觉模型,折腾半天发现行不通,因为 Codex 的请求体结构是固定的,它不会自动帮你做 base64 编码和 multimodal content 组装。正确的做法是引入一个 Skill——也就是一份告诉 Codex"遇到图片时该调用什么脚本"的声明文件,加上一个几十行的 Python 脚本,由脚本负责把图片转成 base64、调用视觉模型的 chat/completions 接口、把返回的文字塞回对话。

这个方案适合谁?三类人最需要:一是本地开发时经常要看报错截图、UI 截图的工程师;二是做自动化测试、需要批量分析截图内容的团队;三是想把 Codex 当成"能看图的编程助手"来用的个人开发者。你不需要懂多模态模型的底层原理,只要会复制文件夹、配一个 Key、跑一条命令,就能让 Codex 从"文盲"变成"能读图的助手"。

这里有个关键认知:Codex 负责调度,视觉模型负责看图,Skill 负责搭桥。三者分工明确,缺一不可。Deepseek 继续做它擅长的文本推理和代码生成,图片识别交给专门的视觉模型,比如 Qwen-VL、GPT-4o、GLM-4V 这些。你甚至可以让它们走同一个 API 通道,用统一的 Key 管理,省得在多个平台之间来回切换。

接下来我会把整条链路拆开:先讲清楚为什么原生接法会失败,再给出可复制的 Skill 配置和 read-image 调用示例,然后写一个 Python 验证脚本让你端到端跑通,最后把常见的报错一个个对照排查。全程命令和配置都能直接抄,路径和参数保持和实际一致。

2. TaoToken 前置准备:统一 Key 与 API 通道配置

在动手写 Skill 之前,先把"通道"这件事理清楚。很多人卡在第一步不是因为脚本写错,而是因为 Key 和 Base URL 配得乱七八糟:一会儿用这家平台的 Key,一会儿又换成那家的 endpoint,最后脚本里硬编码了一堆地址,换模型时全得改。我的建议是走一个统一的 API 通道,把 Key 和 Base URL 收敛到一处,后面换视觉模型只改一个 Model ID 就行。

TaoToken 在这里扮演的就是这个统一通道的角色。它的 API 地址是https://taotoken.net/api,兼容 OpenAI 的 chat/completions 协议,也就是说你原来写给 OpenAI 的请求体,改一下 Base URL 和 Key 就能直接用。对于 read-image 这个 Skill 来说,这意味着脚本里只需要维护一份配置:Base URL 指向 TaoToken,Key 用 TaoToken 生成的,Model ID 填你要用的视觉模型名。想从 Qwen-VL 换成 GPT-4o,只改 Model ID 那一行,其他不动。

先拿 Key。打开https://taotoken.net/api-keys,登录后创建一个新的 API Key,复制下来。这个 Key 就是后面脚本里要用的凭证,注意别提交到 Git 仓库里,用环境变量或者本地密钥文件存。创建完之后,你可以在控制台https://taotoken.net/console里看到用量和调用记录,方便排查问题。

配置的时候有三个东西必须成对出现,我把它叫做"三件套":Base URL + Key + Model ID。缺任何一个,请求都会失败。Base URL 是https://taotoken.net/api,Key 是你刚创建的那串,Model ID 是视觉模型的名字,比如qwen-vl-plus、gpt-4o、glm-4v这些。这三个值在脚本里要么走环境变量,要么走配置文件,别写死在代码里。

如果你用的是 Claude Code 或者类似的 CLI 工具做润色、接入,配置逻辑是一样的:在 settings 里填 Base URL、Key、Model ID 三件套。比如 Claude Code 的配置可以写成这样:

{ "apiBaseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥", "model": "qwen-vl-plus" }

注意这里的apiBaseUrl不要带末尾斜杠,有些客户端会自动拼接/v1/chat/completions,带斜杠会变成双斜杠导致 404。Key 用sk-开头的那串,Model ID 按你实际要用的视觉模型填。这个 JSON 片段可以直接放进 Claude Code 的 settings 文件,路径按你系统的实际位置来,Windows 一般在用户目录下的.claude文件夹,macOS 和 Linux 在~/.claude/。

对于 Codex 的 Skill 方案,配置方式稍微不同,因为 Skill 是通过环境变量或者本地密钥文件读取的。我推荐用环境变量,跨平台兼容性好,也不容易误提交。在 Windows 上用set或者系统环境变量面板设置,macOS 和 Linux 上用export。具体命令后面第三节会给。

这里要提醒一句:TaoToken 是统一通道,不是让你绕过什么限制,它只是把多个模型的调用收敛到一个入口,方便管理和切换。你用的还是正规的视觉模型服务,Key 也只存在你本地。别把 Key 贴到公开仓库或者聊天记录里,这是基本的安全习惯。

配好三件套之后,先别急着写 Skill,用一条 curl 命令验证通道是否通。如果这条命令能返回正常的 JSON,说明 Base URL、Key、Model ID 都没问题,后面脚本里出错的概率就小很多。验证命令我放在第四节,你可以先跳到那里跑一遍再回来。

3. 可复制配置:Skill 目录结构与 read-image 脚本

这一节是核心,我把整个 Skill 的目录结构、SKILL.md 声明文件、Python 脚本全部给出来,你照着复制就行。先说目录结构,Codex 的技能目录在 Windows 上是C:\Users\<你的用户名>\.codex\skills\,macOS 和 Linux 上是~/.codex/skills/。在这个目录下新建一个read-image文件夹,里面放两个文件:SKILL.md和read_image.py。

目录长这样:

.codex/ └── skills/ └── read-image/ ├── SKILL.md └── read_image.py

SKILL.md是给 Codex 看的声明文件,告诉它"什么时候该用这个技能"。内容不用复杂,关键是描述清楚触发条件和调用方式。我用的版本是这样的:

--- name: read-image description: 当用户粘贴图片或提到截图、识图、看图、识别图片文字时,调用此技能读取图片内容 --- # read-image 读取本地图片文件,调用视觉模型识别其中的文字和内容,返回识别结果。 ## 使用方式 当用户提供图片路径或粘贴图片时,运行: python read_image.py <图片路径> 脚本会输出识别到的文字内容。

这个声明文件的作用是让 Codex 在遇到图片相关请求时,知道去调用read_image.py。description里列的关键词越贴近你的实际说法,触发越准。比如你习惯说"帮我看看这张截图",那就把"截图"写进去。

接下来是read_image.py,纯 Python 标准库实现,零第三方依赖,Windows、macOS、Linux 都能跑。核心逻辑就三步:读图片转 base64、组装请求体、调 chat/completions 接口。完整代码如下:

import base64 import json import os import sys import urllib.request import urllib.error # 三件套配置:Base URL + Key + Model ID BASE_URL = os.environ.get("TAOTOKEN_BASE_URL", "https://taotoken.net/api") API_KEY = os.environ.get("TAOTOKEN_API_KEY", "") MODEL_ID = os.environ.get("TAOTOKEN_MODEL", "qwen-vl-plus") def encode_image(image_path): with open(image_path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") def read_image(image_path): if not API_KEY: print("错误:未设置 TAOTOKEN_API_KEY 环境变量") sys.exit(1) if not os.path.exists(image_path): print(f"错误:图片文件不存在 {image_path}") sys.exit(1) b64 = encode_image(image_path) ext = os.path.splitext(image_path)[1].lower().lstrip(".") mime = "image/png" if ext == "png" else "image/jpeg" payload = { "model": MODEL_ID, "messages": [ { "role": "user", "content": [ {"type": "text", "text": "识别这张图片里的所有文字和关键内容,按原样输出。"}, {"type": "image_url", "image_url": {"url": f"data:{mime};base64,{b64}"}} ] } ], "max_tokens": 2000 } req = urllib.request.Request( f"{BASE_URL}/v1/chat/completions", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}" }, method="POST" ) try: with urllib.request.urlopen(req, timeout=60) as resp: result = json.loads(resp.read().decode("utf-8")) content = result["choices"][0]["message"]["content"] print(content) except urllib.error.HTTPError as e: print(f"HTTP 错误 {e.code}: {e.read().decode('utf-8')}") sys.exit(1) except Exception as e: print(f"请求失败: {e}") sys.exit(1) if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python read_image.py <图片路径>") sys.exit(1) read_image(sys.argv[1])

这段代码里,BASE_URL、API_KEY、MODEL_ID三个值都从环境变量读,默认 Base URL 是https://taotoken.net/api,Model ID 默认qwen-vl-plus。你只要设置好TAOTOKEN_API_KEY,其他两个不设也能跑。想换模型就改TAOTOKEN_MODEL,比如换成gpt-4o或glm-4v。

设置环境变量的命令,Windows 上用:

set TAOTOKEN_API_KEY=sk-你的密钥 set TAOTOKEN_MODEL=qwen-vl-plus

macOS 和 Linux 上用:

export TAOTOKEN_API_KEY=sk-你的密钥 export TAOTOKEN_MODEL=qwen-vl-plus

如果你不想每次开终端都设,可以把这两行写进~/.bashrc或~/.zshrc,Windows 上写进系统环境变量。注意 Key 别写进脚本文件本身,这是安全底线。

配置完之后,Codex 在遇到图片请求时会自动调用这个脚本。你也可以手动跑一遍验证:python read_image.py test.png,看能不能返回识别结果。如果返回了文字,说明 Skill 配置成功;如果报错,对照第五节排查。

4. 验证请求与成功结果:Python 脚本端到端跑通

配置写完,必须验证。我见过太多人配完就以为好了,结果实际用的时候才发现 Key 没生效或者 Base URL 写错。这一节给你两条验证路径:先用 curl 验证通道,再用 Python 脚本验证完整链路。

先验证通道。打开终端,把下面的命令里的 Key 换成你自己的,图片路径换成一张真实存在的截图:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的密钥" \ -d '{ "model": "qwen-vl-plus", "messages": [ { "role": "user", "content": [ {"type": "text", "text": "识别这张图片里的文字"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,你的base64"}} ] } ] }'

手动拼 base64 太麻烦,所以更实际的做法是直接用 Python 脚本验证。把第三节的read_image.py保存好,准备一张测试截图,比如你本地随便截一张网页或者报错信息,命名为test.png,然后跑:

python read_image.py test.png

如果一切正常,几秒钟后终端会输出图片里的文字内容。我实测下来,一张阿里云控制台的截图丢进去,返回的文字基本一个不漏,包括按钮上的小字和表格里的数字。返回的 JSON 结构里,choices[0].message.content就是识别结果,脚本已经帮你提取出来了。

成功的结果长这样:

登录 控制台 费用 资源 域名 备案 实例名称 运行中 公网IP 内网IP 创建时间 2024-01-15 到期时间 2025-01-15

如果返回的是这种纯文字,说明整条链路通了:Codex 触发 Skill → 脚本读图转 base64 → 请求发到 TaoToken → 转发给视觉模型 → 返回识别结果 → 脚本打印。每一步都正常。

再验证一下 Codex 里的实际效果。新开一个 Codex 对话,把图片路径贴进去,说一句"识别这张图片里的文字"。Codex 应该会调用read_image.py,然后把识别结果带回对话。如果它没调用,检查SKILL.md里的description关键词是否匹配你的说法,或者手动指定"用 read-image 技能读这张图"。

想换模型验证的话,改环境变量再跑:

export TAOTOKEN_MODEL=gpt-4o python read_image.py test.png

换成gpt-4o后,识别结果可能略有不同,但整体流程一样。这就是统一通道的好处:换模型只改一个变量,Base URL 和 Key 都不用动。

验证通过之后,你可以把这个脚本接到自动化流程里。比如跑完测试生成截图,自动调用read_image.py把识别结果写进日志,或者让 Codex 直接分析截图里的报错信息。这一步的想象空间很大,核心是链路已经通了,后面就是怎么用的问题。

5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth

配置和验证过程中,最容易撞上四类报错。我把它们和真实错误信息对照着列出来,你遇到时直接对号入座。

401 Unauthorized。这是最常见的,错误信息一般是{"error":{"message":"Invalid API key","type":"invalid_request_error"}}。原因就三个:Key 没设、Key 设错、Key 前后有空格。先检查环境变量有没有生效,Windows 上用echo %TAOTOKEN_API_KEY%,macOS 和 Linux 上用echo $TAOTOKEN_API_KEY。如果输出为空,说明没设上,重新 export 一遍。如果输出有值但还报 401,检查 Key 是不是复制时带了换行或者空格,重新从https://taotoken.net/api-keys复制一次。还有一种情况是 Key 被删了或者过期了,去控制台确认一下状态。

local proxy failed。这个报错通常出现在你本地配了代理或者客户端自动读取了系统代理设置的时候。错误信息类似local proxy failed: connection refused。解决办法是检查环境变量里有没有HTTP_PROXY、HTTPS_PROXY这类设置,有的话临时清掉:

unset HTTP_PROXY unset HTTPS_PROXY

Windows 上用set HTTP_PROXY=清空。清完之后重跑脚本。如果你确实需要走代理才能访问外网,那要确保代理本身是通的,但注意别把代理配置和 API 调用混在一起排查,先确认直连能不能通。

reading choices 报错。完整信息一般是KeyError: 'choices'或者list index out of range,出现在脚本解析返回结果的时候。这说明请求发出去了,但返回的 JSON 结构里没有choices字段。原因通常是:Model ID 填错了,比如填了一个不存在的模型名,服务端返回的是错误信息而不是正常的对话结果;或者请求体格式不对,比如content数组结构写错。先打印完整的返回内容看看:

print(json.dumps(result, ensure_ascii=False, indent=2))

把read_image.py里提取choices那行前面加一句打印,看服务端到底返回了什么。如果是model not found,就去确认 Model ID 拼写;如果是invalid content format,检查image_url那层嵌套有没有写对。

OAuth 相关报错。如果你用的是 Claude Code 或者带 OAuth 登录的客户端,可能会遇到OAuth token expired或者authentication failed。这类报错和 API Key 是两套体系,OAuth 走的是登录态,API Key 走的是密钥。如果你在 Claude Code 里配了 Base URL 和 Key 三件套,就不要再走 OAuth 登录,两者会冲突。解决办法是在配置里明确指定用 API Key 模式,把 OAuth 相关的 token 清掉。具体到 Claude Code,检查 settings 里有没有残留的 OAuth 配置,删掉后只保留apiBaseUrl、apiKey、model三件套。

还有一个容易忽略的点:Base URL 末尾带斜杠。比如写成https://taotoken.net/api/,客户端拼接后变成https://taotoken.net/api//v1/chat/completions,双斜杠会导致 404 或者路由错误。检查一下你的配置,把末尾斜杠去掉。

排查的顺序建议是:先 curl 验证通道 → 再跑 Python 脚本 → 最后在 Codex 里触发。每一步都确认通过再往下走,别跳步。这样出问题时能快速定位是哪一层的问题。

6. 语义一致 CTA:把图片识别接进你的日常工作流

链路跑通之后,真正的价值在于把它接进日常工作流。我自己的用法是:跑完自动化测试,脚本自动截图,然后调用read_image.py把识别结果写进测试报告,Codex 再基于这些文字做失败原因分析。整个过程不需要人工介入,截图里的报错信息直接变成可检索的文本。

如果你想让 Codex 长期承担这类编码和 Agent 任务,可以考虑用 Coding Plan,把调用额度固定下来,避免每次临时配 Key。地址是https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite。对于需要频繁调用视觉模型的场景,这个方案比每次手动配更省心。

想快速验证模型对话效果,或者测试不同视觉模型的识别质量,可以用模型对话页面直接试:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite。把同一张截图分别丢给 Qwen-VL 和 GPT-4o,对比识别结果,选一个最适合你场景的。

Key 的管理和创建在https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite,接入文档在https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite。文档里有完整的接口说明和参数列表,遇到不确定的字段可以去查。

如果你用的是 Claude Code 做代码润色和接入,配置入口在https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite,里面有三件套的填写说明。控制台在https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite,可以看调用记录和用量。

最后说一个实用技巧:把read_image.py包装成一个命令行工具,加到 PATH 里,这样在任何目录下都能直接调用。比如在 macOS 和 Linux 上建一个软链接:

ln -s ~/.codex/skills/read-image/read_image.py /usr/local/bin/read-image chmod +x /usr/local/bin/read-image

之后直接read-image test.png就能识别。Windows 上可以写一个read-image.bat放到 PATH 目录里。这样你不仅能在 Codex 里用,还能在终端里随手调用,配合其他脚本做批量截图分析。

整条链路的核心就一句话:Codex 负责调度,Skill 负责搭桥,视觉模型负责看图,统一通道负责收敛配置。把这四件事理顺,图片识别就不再是障碍。

返回列表