在 Claude Code / Codex / Pi 里用 DeepSeek,怎么让它看见图?

在 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 再决定怎么改代码、怎么回你。

整条链路可以画成:

flowchart TD A[&#34;你 @ 了一张图&#34;] --> B[&#34;SKILL.md 约束 agent<br/>先跑 see.py,禁止脑补像素&#34;] B --> C[see.py] C --> C1[&#34;读取 ~/.config/glm-vision/env&#34;] C1 --> C2[&#34;同一模型重试<br/>429 / 1305 / 5xx&#34;] C2 --> C3[&#34;再换队列里的下一个模型&#34;] C3 --> D[GLM 输出文字描述] D --> E[&#34;DeepSeek 继续写代码 / 解释报错&#34;]

有两个角色,不要混:

flowchart LR subgraph eye[眼睛] G[智谱 GLM-4.6V-Flash 等] end subgraph brain[大脑] D[DeepSeek] end G -->|文字描述| D D -->|改代码 / 解释报错| U[你]
角色 谁来当 干什么
眼睛 智谱 GLM-4.6V-Flash 等 读图、OCR、说界面上有什么
大脑 DeepSeek 根据文字描述推理、改代码、给方案

这不是原生多模态。DeepSeek 拿到的是「别人看过之后的笔记」,不是视觉 token。好处是主模型不用换;代价是描述漏了的细节,后面补不回来。所以 -q 要把当前任务写进去,而不是笼统的「描述这张图」。

架构上就三块

仓库很小,刻意保持三块分离。

flowchart TB subgraph skill[给 agent] S[SKILL.md] end subgraph cli[真正发请求] P[scripts/see.py] end subgraph cfg[不进 git] E[&#34;~/.config/glm-vision/env&#34;] end S -->|约束:先跑脚本,禁止脑补| P E -->|API Key / 模型队列 / 重试| P P -->|image_url + 描述| G[智谱 /chat/completions]

一次完整调用的时序:

sequenceDiagram actor User as 你 participant Agent as DeepSeek Agent participant Skill as SKILL.md participant See as see.py participant GLM as 智谱 GLM User->>Agent: @error.png 这是什么报错? Agent->>Skill: 匹配识图场景 Skill-->>Agent: 必须先跑 see.py Agent->>See: see.py error.png -q 用户原话 See->>See: 读 env,转 data URL loop 同一模型重试 See->>GLM: chat/completions + image_url alt 429 / 1305 / 5xx 且还有次数 GLM-->>See: 限流 else 成功 GLM-->>See: 文字描述 end end alt 仍失败且队列未空 See->>GLM: 换下一个模型再试 GLM-->>See: 文字描述 end See-->>Agent: stdout 描述 Agent-->>User: 基于描述解释并改代码

1. SKILL.md:给 agent 看的说明书

它不负责发 HTTP。它只规定:

  • 什么时候必须调用脚本(@ 图、路径是 png/jpg、用户说识图/看截图)
  • 命令怎么写,-q 怎么带上用户原话
  • 脚本已经会重试和降级,禁止 再包一层 sleep && retry
  • stdout 当事实,stderr 里的 info: / warn: 只说明用了哪个模型
  • 没有文件路径就请用户先保存,不要假装看见了剪贴板

人看的安装说明放在 README.md,不塞进 skill 包,避免每次识图都把装机步骤灌进上下文。

2. scripts/see.py:真正干活的 CLI

只有 Python 标准库:urllibbase64argparse。不需要 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 把配置冲掉
  • 同一模型先重试,再换下一个

默认队列:

flowchart LR A[glm-4.6v-flash] --> B[glm-4.1v-thinking-flash] --> C[glm-4v-flash]

glm-4.6v-flash 官方标免费,也支持本地 base64,所以放队首。老的 glm-4v-flash 有过「不支持 base64」的记录,只能吃公网 URL,所以放队尾;一旦遇到的是格式错误而不是限流,脚本不会继续降级,避免把同一个坏请求打遍所有模型。

重试策略也很直白:

flowchart TD S[&#34;对当前模型发起请求&#34;] --> R{成功?} R -->|是| OK[输出描述] R -->|否| T{可重试?<br/>429 / 1305 / 5xx} T -->|是且未达次数| W[&#34;等待 2s / 4s / 8s&#34;] --> S T -->|是但次数用尽| N{还有下一个模型?} T -->|否 格式/鉴权等| X[停止降级并报错] N -->|是| M[换下一个模型] --> S N -->|否| X

每个模型最多 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

查找顺序:

flowchart TD A{&#34;$VISION_ENV_FILE 有值且文件存在?&#34;} -->|是| U[用该文件] A -->|否| B{&#34;~/.config/glm-vision/env 存在?&#34;} B -->|是| U2[用这份 env] B -->|否| C{&#34;~/.config/agent-vision-toolkit/env 存在?&#34;} C -->|是| U3[兼容 toolkit 的 env] C -->|否| E[缺少 VISION_API_KEY]

进程里的环境变量优先于文件。

怎么用

最佳推荐: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 至少能认真对待一张截图。

仓库:github.com/voidman2017...

MIT,欢迎star,提 issue 和 PR。

相关推荐
打呵欠的猫1 小时前
我用 AI 重写了项目的请求层,从 800 行"面条代码"变成 3 层洋葱模型
前端·ai编程
东姬AI2 小时前
Anthropic模型36小时突破46年数学进展,同日三家前沿模型上新:当AI抽象智能逼近极限,“表现力“为什么仍是结构性空白
ai·agent·grok·deepseek·anthropic·黎曼猜想·qwen3.8
tedcloud1232 小时前
book-to-skill 怎么部署?把技术书和文档转换成可复用的 AI Skill
运维·服务器·人工智能·开源·ai编程
政采云技术4 小时前
工单处理的智能革命:钉钉AI助理辅助系统探索
人工智能·后端·ai编程
神奇霸王龙4 小时前
Agentic RAG 双硬门屠夫:5 旗舰实测
数据库·人工智能·ai·agent·ai编程·ai写作·rag
labixiong4 小时前
DeepSeek V4 Pro 首日实测:用前端项目跑了一遍,Agent 能力暴涨8倍是真的吗?
agent·ai编程·deepseek
云卷云舒___________5 小时前
【加急快讯】DeepSeek Harness 深夜开源!主打「一切皆插件」,由 Cordis 驱动
开源·aiagent·deepseek·ai日报·智能体框架·deepseekharness·cordis
DS随心转小程序5 小时前
借助 AI 导出鸭简化各类办公场景下文心输出 word 文档全流程操作
人工智能·aigc·word·豆包·deepseek·ai导出鸭
lifallen5 小时前
Orca 与 Emdash:同样管理多个 Agent,差别在谁来调度
人工智能·学习·ai·软件构建·开源软件·ai编程