摘要:DeepSeek Harness rc.8打通图片通道,但默认模型不支持视觉。框架自动退化到OCR+像素扫描+颜色统计的土法方案,让纯文本模型也能"猜"图。本文拆解七步流水线并实测五类图的识别边界。

前几天我在Harness里用DeepSeek-V4-Flash跑一个任务,顺手截了张代码报错的图丢进对话框。我本来没指望它能看懂——Flash是纯文本模型,又没有视觉能力,丢图跟丢空气差不多。

结果它回了我一句:“这个错误是TypeError,看起来是undefined没有map方法,你检查下第17行那个数组是不是没初始化。”

我盯着屏幕愣了两秒。它连第17行都报出来了。一个纯文本模型,怎么知道我截图里有什么?

rc.8确实支持图片了,但别高兴太早

先泼盆冷水。rc.8确实加了原生图片请求能力,/goal/plan这些命令支持图文混合输入,输入框的@菜单也能引用文件了。但Harness做的事情是打通了图片传输的管道,管道通了不代表水龙头那边有水。

模型能不能看图,取决于它的元数据里有没有声明inputModalities: [text, image]。默认的Flash、Pro,以及所有没声明这个字段的模型,Harness一律按纯文本处理。你把图拖进去,管道照传,模型收到的是——什么都没有,因为它根本不接受图片输入。

实验性的视觉模型目前也没进默认模型目录,你得自己配支持图片输入的端点。图片本身还有限制:单张默认3.5MiB,单条消息最多20张,原始图片合计不超过100MiB;进了DeepSeek适配器之后单次请求累计上限20MiB。长会话里图片超预算了,从最旧的开始用占位文字顶替。

所以现实是:大部分人用默认配置,模型就是看不见图。可我开头那个场景又确实发生了。

模型说"我看不了",框架没报错,而是偷偷换了套方案

我翻了会话日志才搞明白。模型声明不支持图像输入之后,read_image调用直接失败了。换成别的框架,这时候大概率给你弹个错误:"当前模型不支持图片输入。"完事。

Harness没报错。它启动了一套退化方案——用工具链把图片"翻译"成纯文本,再喂给模型。整个过程你在界面上可能只看到模型在"思考",底下其实已经跑了一连串工具。

用户发送图片

模型是否声明
inputModalities含image?

原生视觉路径
模型直接处理图片像素

`read_image`调用失败

OCR文字识别

颜色统计

像素扫描

元信息读取

结构化证据汇总JSON

纯文本模型推理

输出图片内容推断

两条路径,一条走模型自己的眼睛,一条走工具当"翻译官"。互补,不替代。

七步流水线,每一步都在干什么

退化方案拆开是七步,但别被这个数字唬住——真正出力的只有两步,剩下的要么是触发信号,要么是给推理凑证据。

第一步:read_image失败

这不是真正的步骤,更像一个触发信号。框架尝试按原生视觉路径走,模型元数据里没有image能力,调用直接被拒。框架捕获这个失败,不抛给用户,转而启动工具链。

第二步:OCR文字识别

这是信息量最大的一步。OCR引擎扫描整张图,把所有能识别的文字抠出来,连同每个文字块的坐标位置一起返回。

代码截图、PPT、文档照片这类图,OCR基本能把核心内容拿出来。我那张报错截图能被"看懂",主要功劳就在这——OCR把错误信息和行号全提取了。

OCR返回的东西大致长这样:

{
  "ocr": {
    "blocks": [
      { "text": "TypeError: Cannot read properties of undefined", "x": 120, "y": 45, "width": 420, "height": 24 },
      { "text": "at processData (app.js:17:15)", "x": 120, "y": 80, "width": 280, "height": 20 },
      { "text": "17  return data.map(item => item.value)", "x": 80, "y": 160, "width": 360, "height": 20 }
    ]
  }
}

坐标很重要。光有文字,模型知道"图里有这些字";有了坐标,模型能推断文字之间的空间关系——哪行在上面、哪两块在同一水平线上、哪个是标题哪个是正文。

第三步:颜色统计

OCR只管文字,颜色信息它不管。颜色统计模块扫一遍图片像素,统计主色分布和各色占比。

这步看着最不起眼,但能告诉模型一些OCR给不了的信息:这张图整体是暗的还是亮的?主色调是什么?有没有大块纯色区域?比如一张PPT截图如果70%是白色、15%是蓝色、剩下是黑色文字,模型大概能推断"这是个白底蓝标题的幻灯片"。

说实话,最开始我没把这步当回事,觉得不就是算个主色调嘛。直到测到那张一个字符都没有的风景照,我才发现它是全场唯一还在给模型递信息的步骤。

输出类似:

{
  "colors": {
    "dominant": "#FFFFFF",
    "palette": [
      { "hex": "#FFFFFF", "ratio": 0.68 },
      { "hex": "#2563EB", "ratio": 0.14 },
      { "hex": "#1F2937", "ratio": 0.11 },
      { "hex": "#E5E7EB", "ratio": 0.07 }
    ]
  }
}

第四、五步:像素扫描 + 元信息读取

这两步单独看都挺寒酸。像素扫描不是做什么高级图像理解,就是沿着特定像素行(或列)扫,检测颜色在什么位置发生突变。突变意味着边界——文字和背景的交界、区块的分割线、表格的横竖线。对表格和界面截图来说,这些线条能帮模型判断"这是一个几行几列的表格"或者"左边是导航栏右边是内容区"。

元信息更简单,就是读尺寸、色彩模式(RGB/RGBA/灰度)、格式(PNG/JPEG/WebP)、DPI这些基础数据。平时没啥用,但一张1920×1080的图跟一张200×200的图,模型对内容复杂度的预期会不一样。

{
  "meta": {
    "width": 1920,
    "height": 1080,
    "format": "PNG",
    "colorSpace": "srgb",
    "hasAlpha": false
  }
}

第六步:结构化证据汇总

前五步各自产出一坨数据,这一步把它们组装成一份结构化的JSON"证据包"。不是简单拼接,而是按统一schema整理,让模型能一眼看出各维度的信息。

整份证据包大致长这样:

{
  "image_evidence": {
    "metadata": { "width": 800, "height": 600, "format": "PNG" },
    "ocr": {
      "full_text": "TypeError: Cannot read properties of undefined\nat processData (app.js:17:15)",
      "blocks": [/* 带坐标的文字块 */]
    },
    "colors": { "dominant": "#1E1E1E", "palette": [/* 颜色占比 */] },
    "layout": {
      "horizontal_lines": 3,
      "vertical_lines": 0,
      "regions": [/* 检测到的区域边界 */]
    }
  }
}

第七步:文本模型推理

最后一步,把这份JSON证据包塞进模型的上下文,附一句指令——大致意思是"根据以下结构化证据推断图片内容"。模型拿到的不是图片,是一份关于图片的"勘验笔录",然后它基于这份笔录做推理。

注意,是推理,不是感知。模型没有看到图,它看到的是"图里有这些文字、这些颜色、这些线条、这个尺寸",然后靠语言模型的常识去拼:深色背景+代码文字+等宽字体+行号,八成是代码截图;白底+蓝色大标题+几个圆点符号,可能是PPT;大面积渐变色+没有任何文字,可能是照片或插画。

实测:五种图,结果天差地别

光说原理太虚,我拿五类图分别跑了一遍,用的是默认的DeepSeek-V4-Flash(纯文本模型,没有任何视觉能力),所有识别全靠上面这套退化方案。跑之前我的预期是文字多的能看、没字的瞎猜,结果落差比我想的大得多。

测试一:代码截图

截了一张VS Code里的JavaScript代码,大约20行,有语法高亮。

在这里插入图片描述

结果:基本准确。 OCR把代码全文提取了,变量名、函数名全对,行号也识别出来了。颜色统计检测到深色背景(#1E1E1E,VS Code默认主题色),模型据此推断"这是一张深色主题的代码编辑器截图"。像素扫描检测到行号区域和代码区域之间有一条竖线分隔,跟实际情况吻合。

模型不仅说出了"这是一段JavaScript代码",还根据代码内容给了重构建议。不过它把一处语法高亮颜色搞混了——绿色的字符串和浅蓝色的变量名在颜色统计里色差不够大,模型误判了几个关键字的角色。不影响理解,但细节有损失。

测试二:PPT页面

一张智能客服系统项目汇报的PPT封面,深蓝和浅蓝双色背景,白色大标题,中间一条竖向金色分隔线,左下角有两个橙色小方块装饰。

在这里插入图片描述

OCR把标题全提取了,文字一字不差——“智能客服系统项目汇报”,连标题下方的"2026年4月-7月"时间范围都认出来了;颜色统计识别出整体是蓝色系,辅以金、橙点缀。最让我意外的是像素扫描——它沿着颜色突变的位置描,真把那条竖向金色分隔线和左下角两个橙色块描出来了。但轮到判断橙色块是什么,它就没辙了,只能报告"检测到两个橙色矩形区域,内部颜色均匀"。

于是模型推断这是"一张商务汇报PPT,标题是智能客服系统项目汇报,下方有两个装饰性图形"。"装饰性图形"这五个字是纯猜——橙色块里面是图标还是纯色块,它不知道,因为OCR在方块区域里找不到文字,颜色统计显示块内是纯色。要是方块里画了个小图标,它照样看不出来。

测试三:网页截图

截了一篇新浪新闻的文章页,讲的是西藏吉隆泥石流救援,有标题、正文,右侧一列"阅读排行榜"推荐,还有一个"生成电子签名"的广告模块。

在这里插入图片描述

这轮OCR就露怯了。标题"运-20起飞!赶赴西藏救援"和正文段落都提出来了,右侧那排"阅读排行榜"的小字推荐只识别出一部分——字号小、字体细、对比度低,直接漏掉了大半。更坑的是那个"生成电子签名"广告模块,上面的字倒是认出来了,但模型不知道那是广告,把它跟正文混在一起理解。

布局这块倒是像素扫描救回来的。它检测到页面中间有一条纵向分隔线,判断"左侧是主内容区,右侧是侧边栏",跟实际吻合。模型最终给出的描述是"一篇新闻文章,左侧正文,右侧有推荐链接",大方向对,但右侧排行榜具体推荐了什么,它说不出。

测试四:风景照片

一张我周末在盘山拍的风景照,阴天,山顶被云雾罩着,山体上段是裸露的红褐色岩壁、下段是绿色植被,山脚是居民区。没有任何文字。跑之前我就猜它会翻车,只是没想到翻得这么彻底。

在这里插入图片描述

OCR返回空——图里确实一个字符都没有。颜色统计倒是给出了信息:上半部分偏灰白(云雾和天空),下半部分偏绿(植被),中段还有一片红褐色(岩壁)。元信息显示尺寸685×378。

模型的推断是:"这可能是一张山景照片,上半部分灰白色可能是云雾或天空,下半部分绿色可能是植被。“听着好像还行,但你仔细想,它除了"上灰下绿"之外什么都不知道。山是陡是缓?云雾是厚是薄?山脚下那排路灯和屋顶它完全没提——它不知道那是居民区,只当成了"山的一部分”。天气是晴是阴?全凭"上灰下绿"这个线索套常识。我换一张上半面灰墙、下半面绿草坪的室内照片,它大概率也会猜成山景。

测试五:表情包

一张很火的"猫懵逼"表情包,猫的大脸占满画面,上面叠了一行白色描边大字:“我看不懂但我大受震撼”。

在这里插入图片描述

这轮是全篇最有节目效果的一次。OCR把那行字完整提取,一字不差;颜色统计显示大面积暖色调(橘猫的毛色);像素扫描一个直线、一条规则几何边界都没检测到。

模型的推断:"图片中有一只橘色的猫(根据颜色推测),配有文字’我看不懂但我大受震撼’,这应该是一张网络表情包或meme图片。"猫的种类和表情它完全看不出来——"橘色的猫"纯粹是从颜色占比推的。它不知道那是猫,是"橘色+没有文字+没有直线+大尺寸"这些线索凑在一起,让模型猜了个最常见的可能性。万一这图是一张橙色的抽象画配字,它也会猜成橘猫。

所以边界在哪

跑完这五个测试,结论很清楚。

土法视觉擅长的: 结构明确、文字为主的图片。代码截图、PPT、文档扫描件、表格、界面截图、带文字的示意图——这些图的核心信息在文字和布局结构上,OCR加像素扫描能恢复七八成,模型靠推理补剩下的两三成,日常用够了。

土法视觉搞不定的: 需要理解视觉语义的图片。照片里的人脸表情、物体之间的空间关系、图表的趋势走向(不是表格那种带数字的,是折线图柱状图这种纯视觉表达)、图标和插画的具体含义——这些东西OCR给不了,颜色统计给不了,像素扫描也给不了。模型拿到的证据包里没有这些信息,它只能瞎猜,猜得听起来合理但不靠谱。

说白了,这套方案不是"看",是"猜"。猜得准不准,取决于图片里有多少信息可以被工具提取成文字和数值。文字越多、结构越规整,猜得越准;纯视觉信息越多,猜得越离谱。

不行

擅长

OCR+布局可恢复

OCR+布局可恢复

OCR+布局可恢复

OCR+布局可恢复

纯视觉语义丢失

纯视觉语义丢失

纯视觉语义丢失

纯视觉语义丢失

代码截图

PPT页面

表格截图

界面截图

风景照片

人脸表情

抽象插画

空间关系

猜得准

基本靠蒙

为什么要这么设计

你可能会问,既然模型不支持视觉,直接告诉用户"看不了"不就行了,搞这么复杂干嘛?

Harness的思路不一样。它的架构哲学从Day01就在说——模型能力不足的时候,用工具编排来补。模型没有眼睛,但工具可以当眼睛;模型看不懂像素,但OCR能读文字、像素扫描能检测线条、颜色统计能给出分布。把这些工具的输出组装起来,虽然比不上真正的多模态模型,但在多模态模型还没完全普及的过渡期,这已经够用了。

而且这套方案跟原生视觉不是互斥的。模型声明了视觉能力,就走原生路径直接看图;模型没有,自动退化到工具链方案。两条路在同一套框架里共存,用户不用管底下走了哪条,体验是连续的。你哪天配了个支持视觉的模型端点,同样的操作自动升级成真视觉,不用改任何使用习惯。

社区里还有一批插件把这套土法视觉做得更狠。ModLens(3431 star)直接粘图就能识别,输出结构化JSON证据,还能自动发现纯文本模型路由并生成vision变体,内置6个视觉引擎组成容错链——一个挂了换下一个。dsh-vision-router(911 star)自带免费视觉链和像素级工具,能做定位、裁剪、像素差异对比。dsh-vision桥接任意OpenAI兼容的VLM,默认走智谱免费档。还有个picturereader更极端,纯本地像素到文本,不调任何外部API。rc.8原生视觉上线之后这些插件非但没被取代,反而跟原生路径互补了——原生视觉走模型直连,插件走工具链,各管各的场景。社区视觉生态这块水挺深,后面专门写一篇聊。

最后

土法视觉这个东西,你说它厉害吧,给它一张照片它连猫和狗都分不清;你说它没用吧,我截一张报错图丢过去,它能直接告诉我哪行出了什么问题。它的价值不在于"替代多模态模型",而在于在你手头只有纯文本模型的时候,多给你一条路。能走多远看图片类型,但总比"不支持图片输入"这六个字强。

这套"模型不够、工具来凑"的思路,在Harness里不止视觉这一处。rc.8还做了一件更野的事——把Claude Code和Codex收编成了子代理,你在Harness里可以调度它们当打工仔干活,一个写代码一个做审查,主任务负责拆分和编排。Day06就来拆这个子代理系统,看看Harness是怎么让别的Agent给自己打工的。

本文由「梅雅达编程笔记」原创,首发CSDN。 AI Agent实战系列共18篇,从Function
Calling到多Agent协作,全程用免费模型GLM-4.7-Flash,点个关注不迷路✨
CSDN博客:https://blog.csdn.net/2601_96428997/

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐