PSD 文件进知识库,为什么不能只做 OCR?

发布时间:2026/8/31 6:14:26
PSD 文件进知识库,为什么不能只做 OCR? 用 RAG 搜 PSD有一种情况很容易让人误判。设计师明明记得设计稿里写过「产品 A」上传知识库以后却怎么都搜不到。打开原文件一看这几个字确实就在 PSD 里。问题出在哪很可能不是检索也不是 Embedding而是在文件入库的第一步PSD 被当成普通图片处理了。如果系统只是把 PSD 合成一张图再跑 OCR那么 OCR 没识别出来的文字后面的 RAG 根本没有机会检索到。但 PSD 有一个很特殊的地方你眼睛看到的是一张图文件内部保存的却是一棵图层树。这也是我们在做企业级 AI 知识库「有谷大脑」时没有把 PSD 简单当图片处理的原因。一、PSD 不是一张图片而是一棵图层树一个 PSD 文件通常由很多图层组成。比如PSD ├─ Group │ ├─ Text Layer │ ├─ Shape Layer │ └─ Image Layer │ ├─ Group │ ├─ Text Layer │ └─ Smart Object │ └─ Background这里最值得利用的是文字图层Text Layer。如果设计师是通过 Photoshop 的文字工具输入内容PSD 内部保存的不只是最后渲染出来的像素还保存着对应的原始文字字符串。也就是说同一份 PSD其实可以从两个方向读取。第一条路看它最终“长什么样”。把所有图层合成为一张图再通过 OCR / VL 识别其中的文字。第二条路直接读它“存了什么”。遍历 PSD 图层树找到文字图层直接读取原始.text内容。所以在有谷大脑里PSD 的入库链路不是PSD ↓ 转图片 ↓ OCR ↓ 入库而是两条路径并行┌→ 合成图 → OCR / VL ──────┐ PSD → 解析图层结构 ─┤ ├→ 合并 → Chunk → Embedding / 索引 └→ 文字图层 → 原文抽取 ────┘所以 PSD 的关键不是 OCR 做得够不够强而是不要把文件本身已经存在的结构信息先丢掉。二、第一条路合成图解决“看得见”的内容PSD 里并不是所有文字都来自文字图层。比如设计师可能直接贴进来产品截图网页截图活动海报扫描素材栅格化后的文字图片里的说明这些内容在人眼看来有文字但在 PSD 图层结构里可能只是一张像素图。你去读.text什么都拿不到。所以第一条路径仍然必须保留把 PSD 合成为最终画面再做 OCR / VL。例如用psd-toolsfrompsd_toolsimportPSDImage psdPSDImage.open(design.psd)imagepsd.composite()image.save(composite.png)然后把合成图送入 OCR 或视觉语言模型。这条路径主要负责覆盖图层结构里没有直接文本但视觉上确实存在的文字。不过实际处理时composite()并不是调完就结束了。三、合成图里有几个比较容易踩的坑超大画布PSD 的画布尺寸经常远大于普通图片。活动长图、详情页、品牌规范稿都可能出现几千甚至上万像素的长边。如果直接把超大画布送给 OCR / VL推理时间会上升显存或内存占用增加可能超过下游模型的输入限制返回坐标后还要能映射回原设计稿所以有谷大脑在进入视觉识别前会先判断画布尺寸。超过当前处理预算时按比例缩放原始画布 ↓ 按比例缩放 ↓ OCR / VL ↓ 识别 bbox ↓ 映射回原始坐标这里最重要的不是“缩多大”而是缩放比例必须保留下来。否则后面想做这段文字在 PSD 哪个位置坐标就对不上了。全透明画布还有一种特殊情况。PSD 可以正常打开但当前可见状态下合成图可能几乎完全透明。如果 Alpha 通道没有有效可见内容再送 OCR 基本没有意义。所以视觉路径之前可以先检查透明度。确认整个合成结果没有有效像素时就直接跳过 OCR / VL保留图层结构解析结果。这可以避免一次没有意义的视觉调用。合成失败PSD 的渲染能力很复杂。混合模式、蒙版、效果、Smart Object 等都可能让第三方解析库无法 100% 还原 Photoshop 的最终效果。所以工程上不能假设PSDImage.composite()永远成功。更稳妥的链路是正常合成 → OCR / VL 合成异常 → 尝试降级渲染 仍然失败 → 放弃视觉路径 → 至少保留 Layer Text这也是双路解析的价值之一其中一路失败不代表整份 PSD 就完全无法进入知识库。四、第二条路文字图层直接读取原始文本这条路径是 PSD 相比普通 PNG、JPG 最有价值的地方。通过psd-tools可以直接遍历文字图层frompsd_toolsimportPSDImagedefextract_psd_text(psd_path:str)-str:psdPSDImage.open(psd_path)parts[]forlayerinpsd.descendants():ifgetattr(layer,kind,None)!type:continuetextgetattr(layer,text,None)ifnottextornottext.strip():continueparts.append(text.strip())return\n.join(parts)这里和 OCR 做的事情完全不一样。OCR 在问这些像素看起来像什么字图层解析是在问这个文字图层原本保存的字符串是什么比如同一句有谷大脑企业知识库视觉上可以被设计成特殊字体发光渐变阴影描边低透明度这些效果都可能影响 OCR。但只要它仍然是 Text Layer原始字符串就还在。所以OCR 是从像素恢复文字Layer Text 是直接读取原始文字。后者天然少了一层识别误差。五、为什么要遍历descendants()PSD 的图层不是平铺的。真实设计稿经常会有很多层 Group首页 └─ Header └─ Navigation └─ Product └─ Text Layer如果只检查最外层图层很容易漏掉嵌套 Group 深处的文字。所以这里需要遍历所有后代图层。descendants()可以把嵌套在 Group 里的后代图层一起拿出来避免“PSD 明明有字但解析器只看了第一层”的问题。这个点看起来很小但对召回覆盖率影响很直接。六、隐藏图层要不要进入知识库这是 PSD 解析里一个很值得讨论的问题。假设设计师把一个备用版本藏在隐藏图层里备用方案 产品名称改成 B当前设计稿里看不到它。用户问这份 PSD 里有没有出现过“产品 B”应该搜到吗在有谷大脑当前的思路里我们更倾向于保留但不要和可见图层完全等权。原因是知识库有时关心的是这个文件里到底存过什么但隐藏图层又可能包含废弃文案老版本方案备用设计尚未采用的命名如果全部和当前可见内容一样进入召回很容易产生知识污染。所以更合理的方式是保留文字同时记录可见性{source:psd_text_layer,text:备用方案产品名称改成 B,visible:false}这样后续检索可以根据场景处理。例如默认降低visiblefalse的召回权重用户明确问“历史方案”时再放开最终答案里标记“来自隐藏图层”这样既不丢信息也不会把隐藏废稿和当前方案完全混在一起。七、两路结果不能只是简单拼在一起双路解析解决了“漏掉内容”的问题但会带来另一个实际问题重复。比如 PSD 里有一个 Text Layer2026 夏季新品发布会它最终也会出现在合成图上。于是Layer Text 路径2026 夏季新品发布会OCR 路径2026 夏季新品发布会两边可能拿到几乎一模一样的结果。如果简单OCR Result Layer Text Result然后全部向量化就可能出现重复召回。所以两路合并时不能只做文本拼接。更合理的方式是同时保留source图层路径bboxvisiblepage/canvas信息文本相似度再判断两段文本是不是同一份内容。对于已经明确来自 Text Layer 的文本可以优先保留结构化读取结果。OCR 更主要负责补充截图文字栅格化文字图片中的说明结构层拿不到的视觉文字于是两条路径的关系更像Layer Text ↓ 结构化文本主来源 Composite OCR / VL ↓ 补结构覆盖不到的视觉内容双路不是为了把同一句话存两遍而是为了互相补盲。这一点比“我们同时跑 OCR 和图层解析”更重要。八、两路内容最后怎么进入 RAG合并之后一份 PSD 可以得到类似这样的结构document_id: design.psd ├─ source: composite_ocr │ ├─ 截图中的按钮文字 │ └─ 产品图片中的说明 │ └─ source: psd_text_layer ├─ 页面标题 ├─ 正文说明 └─ 隐藏备用方案之后再进入清洗 ↓ Chunking ↓ Embedding ↓ 索引检索时两路结果都会进入候选池但可以保留不同的来源权重和 metadata。这样不同内容就有不同的主要覆盖路径PSD 内容主要路径正常文字图层Layer Text特殊字体 / 描边文字Layer Text隐藏文字图层Layer Text截图中的文字OCR / VL栅格化文字OCR / VL图片说明OCR / VL这套结构的好处是不会把 OCR 当成万能方案也不会假设所有文字都一定是 Text Layer。九、为什么不能只做 OCR现在再回头看开头的问题会更清楚。假设一个 PSD 里有大量正常文字图层。如果把整个 PSD 先压成图片再让 OCR 从像素里重新识别一次相当于文件已经给了你原始答案你先把答案拍成照片再重新猜一遍。这会同时引入OCR 识别误差额外的视觉推理成本超大画布处理开销装饰元素造成的噪声而直接遍历文字图层通常要轻量得多也不依赖额外视觉识别调用。所以有谷大脑处理 PSD 时的原则并不是OCR 和 Layer Text 二选一。而是能从文件结构直接读取的内容优先利用结构结构覆盖不到的视觉信息再交给 OCR / VL 补。这其实和前面几篇文章讲的是同一个思路先尊重文件自身的结构再决定怎么解析和 Chunk。十、PSD 还有几个目前比较难处理的地方PSD 结构很丰富但也不是所有信息都能轻松读出来。Smart ObjectSmart Object 可能嵌套另一个文件。比如main.psd └─ Smart Object └─ child.psd └─ Text LayerSmart Object 自己未必有.text。真正的文字可能藏在嵌套文件内部。如果不继续递归解析 Smart Object这部分内容就会成为覆盖盲区。而一旦递归展开就会继续带来嵌套深度控制不同文件格式兼容资源消耗循环引用防护所以它不是简单“再遍历一次”就能彻底解决的问题。Warp Text有些文字图层会做路径文字弯曲Warp透视变形.text可以告诉我们原始文字是什么。但不一定能准确告诉我们用户视觉上看到的字符具体落在哪里。对纯语义搜索影响不大。但如果以后要支持在 PSD 原图上框出这段文字。就需要进一步处理渲染后的空间位置。重复文字设计稿里还可能大量复制模板、标题、按钮。相同字符串可能出现很多次。简单按文本去重也有风险因为文字一样不代表图层位置和语义角色一样。所以真正做去重时最好结合文本图层路径bbox可见性source而不是只比较字符串。十一、PSD 和 PDF 为什么不能走同一条解析路径前面我们拆过 PDF。PDF 和 PSD 都包含视觉内容但底层结构差异非常大。PDF 更接近Page 1 Page 2 Page 3 ...处理时重点是Page ↓ Layout ↓ Text / Table / Figure ↓ ChunkPSD 更接近Canvas └─ Layer Tree所以它更适合Composite Visual Layer Structure ↓ 双路解析这也是企业知识库里一个经常被低估的问题不同文件后缀不是“换个解析库”这么简单信息真正存在的位置可能完全不同。如果所有文件最终都统一走转文本 ↓ 固定 Chunk ↓ Embedding很多结构信息其实在第一步就已经没了。十二、PSD 支持得好不好可以直接这样测如果你的知识库支持 PSD比起问帮我总结这个 PSD。更建议测试下面几种情况。特殊字体在文字图层里放一段描边、阴影、特殊字体文字。看 OCR 失败后Layer Text 能不能召回。截图文字在 PSD 里贴一张带文字的产品截图。看视觉路径能不能覆盖。隐藏图层在隐藏图层里放一个正文完全没有出现过的关键词。看系统能不能搜到同时是否标明它来自隐藏内容。深层 Group把文字放进三四层嵌套 Group。看解析是不是只扫了顶层。重复文本同一句文字同时存在于 Text Layer 和合成图 OCR 结果中。看检索会不会连续返回两份一样的内容。Smart Object把关键词放进嵌套 PSD 的 Smart Object。这个测试最容易暴露当前解析边界。十三、最后PSD 进知识库不是把它拍成一张图做了几类企业文件以后我们越来越确定一件事企业知识库真正难的不是把文件转成文本而是先搞清楚信息在这种文件里到底是怎么组织的。Excel 的语义藏在单元格、表头、公式和区域关系里。合同的语义藏在条款层级、Definitions、交叉引用和附件里。PDF 的信息可能藏在正文、表格、图表和页面布局里。到了 PSD信息又同时存在于最终画面 图层结构。所以在有谷大脑里我们不会把 PSD 简单拍平成一张图以后全部交给 OCR。而是走双路解析合成图 → OCR / VL负责视觉内容加上Layer Tree → Text Layer负责原始结构化文字两路互相补盲再一起进入后续 Chunking 和检索链路。这也是我们一直在解决的问题不是让 AI“支持更多文件后缀”而是让不同类型的企业文件用更适合自身结构的方式进入知识库。前面这个系列已经拆过Excel 表格为什么不能按行硬切合同为什么不能只按 Token 切PDF 图表和截图怎么找出来PSD 为什么不能只做 OCR后面还会继续写PPT 里的文本框、图片、备注怎么关联Word 几百页制度文件怎么保留章节层级为什么 RAG 明明召回了正确内容模型还是会答错多版本文件同时存在怎么避免知识库引用旧版本如果你也在做企业知识库、RAG、文档解析或者企业 AI 落地可以继续关注这个系列。想进一步看看这些能力最后在产品里怎么用也可以体验有谷大脑https://brain.yogu.proPSD 进知识库不是把它变成一张图而是把“画面”和“图层”一起变成可检索的信息。