在 Claude Code / Codex / Pi 里用 DeepSeek,怎么让它看见图?
DeepSeek 写代码很香,接进 Claude Code、Codex、Pi 也越来越常见。但有一件事会反复踩坑:官方 API 是纯文本的。你把报错截图、UI 稿、接口文档拍照丢进去,模型要么直接说看不见,要么根据文件名瞎编。
我后来做了个很小的 skill:glm-vision。思路不复杂------看图的事交给智谱 GLM,推理和写代码还是 DeepSeek 。仓库在这里:voidman2017/glm-vision
这篇文章把问题和做法讲清楚:为什么官方看不了图、skill 的架构怎么拆、怎么装、边界在哪。
问题不在 agent,在模型接口
Claude、GPT、Gemini 本身就能吃 image 块。DeepSeek V4 Flash / Pro 的托管 API 文档里,输入类型是 text。coding agent 不管多聪明,发出去的请求里只要带上图片,上游就会拒,或者在进模型之前把图丢掉。
所以会出现一种很割裂的体验:
- 用 Claude 时,
@screenshot.png就能对界面评头论足 - 切到 DeepSeek 后,同一张图变成「我无法查看图片」
社区里另一条路是视觉代理:本地拦请求,把图转成文字再转发给 DeepSeek。那条路能做到「粘贴即看」,但要改 base_url、常驻端口,还可能和你已经在跑的 Claude 反代叠在一起。我想先要一个更轻的东西:
- 不改 DeepSeek 的鉴权和线路
- 不装额外 Python 依赖
- Claude Code、Codex、Pi、OpenCode 都能用
- 智谱 Flash 视觉模型免费,先把日常截图跑通
于是就只剩 skill + 一条命令。
它到底做了什么
agent 看见图片路径时,不要自己「看」,而是跑:
bash
python3 scripts/see.py shot.png -q "这是什么界面?读出报错和关键按钮。"
see.py 把本地图编成 data:image/...;base64,...,打到智谱的 OpenAI 兼容接口 /chat/completions,把 stdout 里的描述交回 DeepSeek。DeepSeek 再决定怎么改代码、怎么回你。
整条链路可以画成:
有两个角色,不要混:
| 角色 | 谁来当 | 干什么 |
|---|---|---|
| 眼睛 | 智谱 GLM-4.6V-Flash 等 | 读图、OCR、说界面上有什么 |
| 大脑 | DeepSeek | 根据文字描述推理、改代码、给方案 |
这不是原生多模态。DeepSeek 拿到的是「别人看过之后的笔记」,不是视觉 token。好处是主模型不用换;代价是描述漏了的细节,后面补不回来。所以 -q 要把当前任务写进去,而不是笼统的「描述这张图」。
架构上就三块
仓库很小,刻意保持三块分离。
一次完整调用的时序:
1. SKILL.md:给 agent 看的说明书
它不负责发 HTTP。它只规定:
- 什么时候必须调用脚本(
@图、路径是 png/jpg、用户说识图/看截图) - 命令怎么写,
-q怎么带上用户原话 - 脚本已经会重试和降级,禁止 再包一层
sleep && retry - stdout 当事实,stderr 里的
info:/warn:只说明用了哪个模型 - 没有文件路径就请用户先保存,不要假装看见了剪贴板
人看的安装说明放在 README.md,不塞进 skill 包,避免每次识图都把装机步骤灌进上下文。
2. scripts/see.py:真正干活的 CLI
只有 Python 标准库:urllib、base64、argparse。不需要 pip install openai。
它做几件具体的事:
- 把本地 PNG / JPEG / GIF / WebP 转成 data URL(上限 5MB)
- 按 OpenAI 的
image_url格式发给VISION_BASE_URL/chat/completions - 用
VISION_LANG给视觉模型加一句「请用中文/英文回答」,和系统环境变量LANG分开,免得 macOS 的en_US.UTF-8把配置冲掉 - 同一模型先重试,再换下一个
默认队列:
glm-4.6v-flash 官方标免费,也支持本地 base64,所以放队首。老的 glm-4v-flash 有过「不支持 base64」的记录,只能吃公网 URL,所以放队尾;一旦遇到的是格式错误而不是限流,脚本不会继续降级,避免把同一个坏请求打遍所有模型。
重试策略也很直白:
每个模型最多 1 + VISION_RETRIES 次;等待按 VISION_RETRY_DELAY 翻倍。可重试:HTTP 429 / 500 / 502 / 503 / 504,以及智谱 1302、1305。
免费 Flash 高峰期很容易 429。如果失败一次就换模型,主模型几乎用不上;如果只死磕一个模型,又会卡死整轮对话。所以是「先礼貌地再问两遍,再换人」。
3. ~/.config/glm-vision/env:密钥单独放
Key 不进 git。agent 和脚本读同一份配置:
bash
VISION_API_KEY=你的智谱key
VISION_BASE_URL=https://open.bigmodel.cn/api/paas/v4
VISION_MODELS=glm-4.6v-flash,glm-4.1v-thinking-flash,glm-4v-flash
VISION_RETRIES=2
VISION_RETRY_DELAY=2
VISION_LANG=zh
查找顺序:
进程里的环境变量优先于文件。
怎么用
最佳推荐:AI时代自然是魔法打败魔法。直接提供仓库地址给AI,让它帮忙执行安装。当然也可以执行手动安装
安装
先克隆,再链到你正在用的 agent(不必四个都装):
bash
git clone https://github.com/voidman2017/glm-vision.git
cd glm-vision
ln -sfn "$(pwd)" ~/.claude/skills/glm-vision
ln -sfn "$(pwd)" ~/.codex/skills/glm-vision
ln -sfn "$(pwd)" ~/.pi/agent/skills/glm-vision
对应目录:
| Agent | Skills 目录 |
|---|---|
| Claude Code | ~/.claude/skills/glm-vision |
| Codex | ~/.codex/skills/glm-vision |
| Pi | ~/.pi/agent/skills/glm-vision |
| OpenCode | ~/.config/opencode/skills/glm-vision |
Windows 可以用目录 Junction。不想软链就 cp -R。装完重启 agent,很多 CLI 只在启动时扫 skill。
然后配 Key:
bash
mkdir -p ~/.config/glm-vision
cp assets/env.example ~/.config/glm-vision/env
chmod 600 ~/.config/glm-vision/env
# 填上 VISION_API_KEY,国内使用建议 VISION_LANG=zh
智谱开放平台实名后就能调 Flash 视觉模型,不必先充值。
先在终端验一下
bash
python3 scripts/see.py --help
python3 scripts/see.py ~/Desktop/error.png -q "读出报错全文和底部按钮"
成功时 stderr 类似 info: using model glm-4.6v-flash,stdout 才是给 DeepSeek 看的描述。
常用参数:
bash
# OCR,按阅读顺序抄文字
python3 scripts/see.py dialog.png --ocr
# 对比两张图
python3 scripts/see.py before.png after.png -q "布局和文案有什么差异?"
# 这次指定队列,或加大重试
python3 scripts/see.py shot.png --model glm-4.1v-thinking-flash
python3 scripts/see.py shot.png --retries 3 --retry-delay 2
在 agent 里怎么用
切到 DeepSeek,然后:
text
@error.png 这个报错是什么意思?相关代码在哪?
skill 生效时,模型会先跑 see.py,再基于描述回答。如果你只是把图粘进输入框、没有任何路径,skill 帮不上 ------像素根本没落到磁盘。先保存,再 @。
和「视觉代理」怎么选
| glm-vision | 本地视觉代理(如 agent-vision-toolkit) | |
|---|---|---|
| 粘贴即看 | 否,要有路径 | 能做 |
| 要不要改 DeepSeek 的 base_url | 不用 | 通常要改,还可能叠一层本地端口 |
| 安装量 | skill + 一份 env | 代理进程、开机自启、和现有反代协调 |
| 适合 | 日常 @ 截图、OCR、对比 UI |
三端无缝粘图、内置 view_image |
我自己日常用 skill 就够了。已经有 Codex / Claude 反代、又特别依赖粘贴的人,再上代理更合适。两套可以共用同一份 VISION_* 配置。
几个踩过的坑
免费模型会限流。 智谱 1305「当前访问量过大」很常见。所以脚本默认同一模型试 3 次,再换 glm-4.1v-thinking-flash。三个 Flash 一起挤的时候,把付费 glm-4.6v 加到 VISION_MODELS 队尾当保底即可。
老 Flash 不一定吃 base64。 coding agent 里的图几乎都是本地文件,没有公网 URL。队首一定要用支持 data URL 的模型。
这是有损压缩。 GLM 漏读的一行小字,DeepSeek 无法「再看一眼」,除非你让脚本带着更具体的 -q 再跑一次。把用户原话传进去,比「请详细描述」有用得多。
skill 不是魔法。 它改变的是 agent 的行为约束,不是模型的输入模态。没有路径,就没有图。
小结
DeepSeek 官方暂时不提供识图 API。与其等接口,不如把「看」和「想」拆开:GLM 看图,DeepSeek 写代码。glm-vision 把这件事收成一个可安装的 skill,一条不依赖第三方包的命令,加上重试和降级,让 Claude Code / Codex / Pi 里的 DeepSeek 至少能认真对待一张截图。
MIT,欢迎star,提 issue 和 PR。