PlanSightRAG 这个项目,名字里已经说出了它的核心:用“视觉优先”的多模态 RAG,去处理土木工程标准图纸的自动问答和合规检查。它和普通文档问答最大的不同,是用户的问题经常要落到图纸的某个区域、某道标注、某个节点上,而不是落到一整段规范文字上。这也是我把它单独拿出来写的原因:图纸场景里真正难的不是让模型能回答问题,而是让模型在“读图”和“查规范”之间建立一条稳定、可追溯的链路。下面按落地顺序拆开讲。
1. 图纸问答不是“文档问答换皮”,难在跨模态对齐
1.1 PlanSightRAG 解决的不是“找文档”,而是“看图回答”
PlanSightRAG 的定位很明确:面向土木工程标准图纸,做自动问答和合规检查。所谓“标准图纸”,通常指包含平面图、立面图、节点详图、尺寸标注、图例、标题栏和材料说明的工程图纸。用户可能这样提问:
- 这张图里某个区域的标注值是多少?
- 某个梁柱节点的做法符合哪一条规范?
- 当前图纸的防火分隔要求有没有违反相关标准?
- 两版图纸之间,某个关键部位是否一致?
这些问题不能靠“把 PDF 全文切块后做向量检索”直接解决。因为图纸的主要信息在视觉结构里:线型、图块、符号、尺寸标注、位置关系。如果先把图变成纯文本,再走文本 RAG,很多关键信息会丢失。
所以 PlanSightRAG 强调 Visual-First,也就是视觉优先。它先把图纸当图像处理,保留页面、区域、坐标、图元关系,再和规范文本的语义做对齐。对这套系统来说,最核心的能力不是“能回答”,而是“能定位到图上的哪个区域,并给出规范依据”。
1.2 “视觉优先”和“文本优先”的差异
普通文本 RAG 的流程一般是:解析文档、切块、向量化、检索、拼接上下文、生成回答。这个流程放在政策文件、技术手册、日常办公文档上没问题,但放在工程图纸上会出现三类问题。
第一,图纸里的文字本身不完整。很多标注只有数字、代号、符号,比如“C30”“φ8@200”“详见图 03”,没有上下文时很难理解。第二,位置关系很重要。同一句话出现在标题栏、图例、节点详图里,含义完全不同。第三,规范条款和图纸不是一一对应。一条规范可能涉及一个图形区域、一组标注、多个构件类型,单纯用文字匹配会漏掉大量证据。
视觉优先的做法是:把图纸页面按视觉对象切成区域,每个区域同时保存图像、文字、坐标和类型。检索时,用户的问题可以同时检索“文字含义”和“图像区域”。生成时,模型看到的不只是文字片段,还可以看到对应区域的图像或结构化描述。这个“跨模态对齐”的过程,才是这类项目真正需要花时间设计的地方。
1.3 自动化是辅助,不是替代人工判断
图纸合规检查听起来很诱人,但不能把“自动化”理解成“全自动裁决”。合规检查本质上是一个专业判断过程,涉及规范理解、图纸意图、工程上下文和多种解释空间。PlanSightRAG 这类系统真正能做到的,是把人工需要翻图册、查条款、比对区域的工作,变成“先由系统召回相关证据,再生成倾向性结论,最后由工程师确认”的流程。
我建议所有做类似项目的人,一上来就明确这个边界:系统输出应该是“证据 + 结论 + 需要确认的地方”,而不是一个没有任何依据的“符合”或“不符合”。这样既降低模型幻觉的影响,也更容易让工程师接受。
2. 动手前先盘点:数据、规范、标注和运行条件
2.1 需要准备哪几类数据
如果想把 PlanSightRAG 跑起来,不能只准备一张图纸和一份规范 PDF。至少要准备四类数据。
第一类是图纸数据。最好是有原始 PDF 或高分辨率图片。PDF 又分两种:矢量 PDF 和扫描件。矢量 PDF 可以直接提取文字和坐标,但很多工程图是导出图,文字可能被打散;扫描件则必须走 OCR。无论是哪种,都要保留页面编号和原始坐标。
第二类是规范文本。规范本身有明确层级,比如分册、章节、条款、条文说明。不要把整本规范当普通文档切块,最好按条款级别结构化,保留条款编号、标题、正文和附录关系。
第三类是问答标注。哪怕是 20 到 50 条也好,每条包含:问题、答案、涉及的图纸区域、涉及的规范条款、结论类型。没有标注就没法做效果评估,也很难判断系统到底有没有变好。
第四类是验证集。验证集和训练标注不同,它是用来做回归测试的。每次改分块策略、检索参数、模型提示词之后,都要跑一遍验证集,看关键指标有没有下降。
2.2 标注“可检查点”,比盲目增加数量更重要
一上来就标几千条问答,通常不是最优选择。图纸问答有个特点:并不是所有区域都能自动检查。有些图纸信息缺失、图层混乱、规范条文交叉,机器只能做到召回,不能做到严格判定。
我建议先标注“可检查点”,也就是答案确定、位置明确、条款直接的样例。比如:某个防火门宽度标注是否符合某条关于疏散宽度的规范。这类样例能让系统快速验证核心链路。等链路稳定了,再逐步加入复杂问题,比如多区域比对、规范冲突判断、多轮追问。
还要注意标注中的“反例”。也就是那些系统容易误判的情况,比如图纸区域不完整、多个规范解释不同、条款含义模糊。这些反例可以帮助你设计“需人工确认”的兜底分支。
2.3 运行条件:显存、分辨率、依赖和流程隔离
工程图中没有明确给出目标硬件的推荐配置,但从落地经验看,运行条件主要取决于视觉编码的输入分辨率和模型规模。
如果你的机器显存在 16GB 以下,可以先降低图纸渲染分辨率,或者限制推理 batch 大小。低显存环境能跑通流程,不代表适合批量跑。如果要做正式项目,我更建议把几个环节分开:
- 文档解析和 OCR:纯 CPU 也能跑,但速度慢;建议给足内存和磁盘空间。
- 视觉 embedding:一般需要 GPU,显存占用和输入分辨率直接相关。
- 检索:看用的向量数据库规模,单机内存通常够用。
- 生成:纯文本模型和多模态模型的资源占用差别很大。
一个常见问题是一台机器同时跑解析、索引、生成和外部服务,结果一放大批量就内存溢出。更稳妥的做法是先小样本跑通,再按环节看资源占用。如果输入材料没有明确版本要求,落地时先确认依赖版本,尤其注意视觉解析库和向量数据库之间的兼容性。
3. 视觉优先 RAG 的完整链路,按落地顺序拆开
3.1 文档解析:保证“图没碎、位置没丢”
图纸类 RAG 的解析环节,比文本 RAG 多两个硬要求:一是保留图像块,二是保留坐标。
拿到一份 PDF 图纸后,我一般会分几步处理:
- 把每一页渲染成高分辨率图片,分辨率太低会丢掉细部标注。
- 用版面分析算法把页面按区域切开,比如标题栏、图例、平面图主体、节点详图。
- 对切开后的区域做 OCR,提取文字内容和识别框坐标。
- 把每个区域保存成一个结构化对象:页面 ID、区域 ID、图像裁切、识别文本、坐标矩形、元素类型。
这里最容易忽略的是坐标系。如果页面渲染成图片后,做 OCR 得到的是像素坐标;如果从矢量 PDF 直接提取,可能又是 PDF 物理坐标。两者没有统一之前,后续定位一定出错。我建议从一开始就统一使用“页面 ID + 归一化坐标”的格式,以页面左上角为原点,坐标范围归一化到 0 到 1。
如果解析时把一个大图切成很多小块,必须保证每块都保存原图坐标。否则后面检索到了“某个块”,却没办法在原始图纸上高亮出来,整个溯源链路就断了。
3.2 视觉分块与多模态索引
文本 RAG 按字符数或段落切块,图纸 RAG 最好按“视觉对象”切块。常见的做法是:
- 标题栏作为一个块。
- 图例作为一个块。
- 节点详图作为一个块。
- 平面图中的某个局部,按坐标窗口切出一个块。
- 相邻图块之间可以保留少量重叠,避免切分刚好把标注切断。
每个块里放什么信息,决定了检索效果。我建议至少保存三类内容:
- 图像信息:区域裁切、或区域对应的视觉特征描述。
- 文本信息:OCR 结果、标题栏文字、图例文字。
- 结构信息:所属页面、区域坐标、图元类型、附近文本。
索引阶段要做两件事。第一件事是把区域图像编码成视觉向量;第二件事是把规范条款、说明文本编码成文本向量。如果使用的是统一多模态 embedding,可以直接把图像和文本放进同一个向量空间;如果不是,就需要做一次向量映射或者用双编码器做混合检索。
有一类常见错误:只用文本 embedding 索引 OCR 文本,然后把视觉信息丢掉。这样做等于退化成文本 RAG。真正的视觉优先,是让“图像区域”本身成为可检索对象。用户输入问题后,系统不仅要召回“相关规范文字”,还要召回“相关的图纸区域”。
伪流程可以这样理解:
输入问题 -> 文本查询向量 -> 在规范库中检索相关条款 -> 在图纸区域库中检索相关视觉区域 -> 合并候选 -> 重排 -> 组装上下文 -> 多模态模型生成答案3.3 检索、重排与上下文组装
图纸场景里的检索,建议不要只做一次向量相似度排序。因为视觉区域和规范文本之间的语义差异很大,第一轮召回的排序不一定可靠。
比较稳妥的做法是:第一轮用向量检索各自召回 top-k,第二轮做融合重排。重排可以考虑这些信号:
- 向量相似度。
- 关键词覆盖,比如问题里有“防火门”,候选块里是否出现“防火门”或“耐火极限”。
- 规范条款编号是否匹配。
- 图纸区域类型是否匹配,比如问“节点详图”就优先给节点详图区域。
- 坐标邻近关系,如果多个候选区域在同一页面且相邻,可以合并成更大证据区域。
重排模型在近年 RAG 实践里很常用,对文本场景提升明显,但图纸场景要额外注意:重排的输入不能只给文本,还要给区域类型和坐标。如果你用的是通用重排模型,最好把“这个候选来自图纸区域还是规范文本”作为字段一起输入,或者干脆用规则融合。
上下文组装同样重要。不要把一个长图的所有 OCR 文本都塞给模型,而是把候选区域整理成结构化上下文,例如:
{ "query": "某节点处的钢筋搭接长度是否符合要求", "evidence": [ { "source_type": "drawing_region", "page_id": "page_03", "region_id": "region_07", "bbox": [0.2, 0.3, 0.5, 0.6], "ocr_text": "300 / φ8@200", "region_type": "node_detail" }, { "source_type": "norm_clause", "clause_id": "GB50010-xxx-xx", "clause_text": "关于搭接长度的规定", "clause_title": "钢筋连接" } ] }这种结构化上下文,能明显减少模型的“自由发挥”。因为它要回答的不再是“看图写话”,而是“基于给定证据做判断”。
3.4 问答生成与合规检查输出
生成阶段有三类做法,按效果和成本排列:
第一类:纯文本模型。只把 OCR 文本、规范条款、区域描述塞给模型。优点是部署简单,缺点是没有图像理解能力,遇到需要看图形位置的问题会受限。
第二类:多模态视觉语言模型。把图纸区域一并作为输入。适合做“图示定位”“区域比对”“图形理解”类任务,也是视觉优先 RAG 更推荐的做法。
第三类:检索后接结构化判断规则。对不涉及复杂视觉理解的问题,可以先由模型抽取关键参数,再用规则做合规判断。这样输出稳定,也更容易追溯。
无论用哪种,输出格式都要规范。合规检查的输出不能是随意一段话。我建议至少包含:结论、依据、定位、说明。具体字段在下文第 5 节展开。
4. 关键参数怎么定:从单条样例到批量任务
4.1 需要关注的核心参数
图纸 RAG 的可调参数比文本 RAG 多。下面这张表,是我做这类项目时会优先确认的参数:
| 参数 | 建议初始值 | 说明 |
|---|---|---|
| 图纸渲染分辨率 | 150 DPI 到 300 DPI | 太低丢标注,太高增加解析时间 |
| 视觉分块大小 | 按语义区域,不按字符数 | 标题栏、图例、节点各成一个块 |
| 分块重叠 | 10% 到 20% | 防止标注被切在边界上 |
| 检索候选数 top-k | 5 到 10 | 先取小值看准确率,再按需增大 |
| 检索相似度阈值 | 不设硬阈值,看重排分数 | 直接卡阈值容易漏掉有效证据 |
| 生成温度 | 0.1 到 0.3 | 合规判断需要稳定输出 |
| 批量并发数 | 从 1 开始 | 稳定后再逐步增加 |
| 输出格式 | JSON | 包含结论、依据、区域、置信度 |
这些参数没有统一最优值。比如图纸中如果小字号标注很多,分辨率就要高一些;如果显存紧张,分辨率就需要降下来。核心原则是:先在小规模数据上把流程跑通,再用验证集比较参数变化带来的影响。
4.2 单条样例验证:先跑通,再谈效果
第一次测试,不要一上来就做大批量。我建议拿一条结构最简单的问题,比如“某区域标注的是什么材料等级”,跑完整条链路。
这一步主要验证几个问题:
- 文档解析是否成功,OCR 文本是否正确。
- 视觉分块是否保留了原图坐标。
- 问题能不能在图纸块里召回对应区域。
- 规范条款能不能在规范库里召回相关条文。
- 生成模型能不能按指定 JSON 格式输出。
- 输出的 region_id 能不能反查到原图。
如果某个环节失败,先修通再继续。不要直接跳到调模型提示词。比如输出一直是空,可能只是解析阶段没有生成区域块,而不是模型能力问题。
我会在本地写一个极简验证脚本,输入一张图和一个问题,打印出每个阶段的中间结果。看到“哪个阶段丢了”之后,才针对性调参数。
4.3 批量任务:从 1 路并发开始
单条跑通之后,再考虑批量。批量最容易踩的坑是:所有文件在一个进程里跑,任务到一半内存溢出,或者输出文件名冲突。
比较稳的做法是:
- 把任务列表写成输入文件,包含图纸路径、页码、问题。
- 逐条跑,保留每一条的日志和中间状态。
- 单条稳定后,再把并发数调到 2、4,逐步观察显存、内存和输出速度。
- 遇到失败任务只记录错误,不打断整体队列。
- 输出文件命名带上问题 ID 和图页 ID,避免覆盖。
批量任务里,最需要盯的不是“能不能跑”,而是“跑出来的结果是否一致”。同样的问题换一种表述,答案不应该出现完全相反但都没有依据的情况。如果批量输出里大量出现“看着相关但无法判断”的结果,说明上下文组装或重排还需要调整,而不是并发不够。
注意:不要一上来就开最大并发。先用一条样例确认输入、输出和日志都正常,再一点点加量。
5. 合规检查不能只看答案,证据链和结论分级一起设计
5.1 输出结构:结论、依据、定位、说明
合规检查项目里,答案文本只是最后展示的一部分。工程师真正关注的是“你为什么这么判断”。因此输出必须结构化。
我建议每个回答都包含这些字段:
- conclusion:结论,例如“符合”“不符合”“需人工确认”。
- confidence:倾向性置信度。不是概率,而是可解释的相对置信度。
- evidence:证据列表,按重要程度排序。
- drawing_location:涉及的图纸页面、区域 ID、归一化坐标、OCR 文本。
- norm_clause:涉及的规范条款编号和原文。
- reasoning:模型给出的简要判断过程。
- uncertain_points:当前方案里哪些信息不足以支撑判断。
给出 JSON 输出时,模型更容易遵守。下面的字段结构可以作为模板:
{ "conclusion": "needs_review", "confidence": "medium", "evidence": [ { "type": "drawing_region", "page_id": "page_03", "region_id": "region_07", "bbox": [0.2, 0.3, 0.5, 0.6], "text": "300" }, { "type": "norm_clause", "clause_id": "GB00000-0000-00", "clause_text": "相关内容" } ], "reasoning": "问题区域存在文字标注,但图像清晰度不足以判断具体构件类型。", "uncertain_points": ["标注不完整", "图纸缩放比例未知"] }5.2 结论分级:符合、不符合、需人工确认
土木工程合规检查不是一个非黑即白的二分类问题。实际落地时,我会把结论分成三档:
| 结论 | 含义 | 适用场景 |
|---|---|---|
| 符合 | 有明确规范条款,且图纸证据充分一致 | 可以直接提示,但仍建议人工抽检 |
| 不符合 | 有明确规范冲突,且证据链完整 | 需要人工复核后确认 |
| 需人工确认 | 缺少规范条款、图纸区域不完整、OCR 不确定、存在多种解释 | 系统不强行下结论 |
这个分级很重要。因为模型在没有完整证据时强行说“符合”或“不符合”,风险很大。与其让系统给出看起来专业但置信度不足的结论,不如让它“承认不知道”。
对于“需人工确认”的情况,系统仍然要给出已召回的证据。这样工程师可以基于证据快速判断,而不是从零开始翻图纸。
5.3 评估指标:不能只看生成文本
合规检查系统的效果评估,不能只看“回答是否通顺”。要从多个维度打分:
- 结论正确率:人工复核后,结论是否和真实情况一致。
- 条款命中率:是否召回并引用了正确规范条款。
- 图纸定位准确率:是否定位到正确页面和区域。
- 误报率:把“符合”判成“不符合”的比例。
- 漏检率:应该发现问题但没有发现的比例。
- 格式合规率:输出 JSON 是否能被前端正常解析。
我建议准备一个小规模评估集,包含 20 到 50 条有确定答案的问题。每次改模型、改参数、改分块策略后,用同一套评估集重跑,记录分数变化。不要凭几个例子感觉效果变好了。
如果评估集还没建好,先不要着急调生成提示词。因为提示词调整对单个样例可能有效,但对整体质量不一定有帮助。有评估集之后,每一个改动都能看到量化影响。
6. 常见问题排查:先看数据对齐,再怀疑模型
6.1 检索不到对应规范
用户问“某根梁的底部钢筋根数是否满足要求”,系统却只召回一些无关文本。这时先别急着重做模型,按顺序排查:
- 问题本身是否包含足够实体。比如“梁”“底部钢筋”“根数”这些关键词是否明确。如果问题泛泛而谈,任何人都很难检索准。
- 规范文本是否按条款级切分。如果一整页规范被切成一个大文本块,语义会被稀释,检索容易偏。
- 查询向量是否被正确生成。可以单独打印查询向量,看它和规范条款向量的相似度分布。
- 索引是否包含最新数据。改了规范文件后有没有重建索引,是老问题里最容易忽略的。
很多时候,问题不在模型,而在“规范文本切块太粗”。把条款拆细,保留条款编号,检索效果会立刻提升。
6.2 坐标和区域信息丢失
输出结果里明明提到“某区域”,但前端无法高亮显示,或者高亮位置不对。这种情况通常出在解析和索引阶段。
检查顺序:
- 原图坐标和渲染坐标是否统一。
- 裁剪区域时,是否使用了原页面坐标而不是缩放后坐标。
- 分块保存时,bbox 字段有没有被遗漏。
- 生成模型依赖的结构化输入里,bbox 是否真的传进去了。
我遇到过很多次,特征向量里带了区域信息,但生成上下文时只传了 OCR 文本,把坐标丢在上一环。排查时可以先看“检索到的 chunk 数据里有没有 bbox 字段”。没有的话,问题一定出在索引构建环节。
6.3 模型给出“看着合理但无依据”的答案
这种问题最危险。模型可能基于训练阶段见过的工程常识,自动补了一个规范结论,但当前图纸和当前规范库里并没有这个依据。
应对策略有几个:
- 降低生成温度,让输出更稳定。
- 在提示词里明确要求“只依赖给定上下文,不要使用外部知识”。
- 使用 JSON 输出框架,要求每个结论必须有 evidence。
- 对没有召回到足够证据的回答,强制输出“需人工确认”。
如果模型仍然坚持给出无依据答案,可以考虑换一个指令跟随更强或更容易约束输出格式的模型。还有一个办法:在生成之前先判断证据数量,证据不足时直接走兜底分支,不经过生成模型。
合规场景里,“不回答”比“错误回答”安全得多。宁可让工程师多确认一次,也不要让模型生成一个看着专业但没有依据的结论。
6.4 批量处理卡住或输出不稳定
批量任务里最常见的现象是:前 10 条正常,第 11 条开始卡住,或者某些任务输出格式不一致。
排查顺序:
- 看资源占用。显存和内存是否被占满,有没有进程互相竞争。
- 看日志。解析、embedding、检索、生成四个阶段,分别记录耗时和错误。
- 看输入文件。某一张图纸是否文件损坏、分辨率过大、页面缺失。
- 看输出命名。是否存在并发写入同一个文件的问题。
- 看依赖版本。某些 PDF 库对加密 PDF 或特殊字体支持不稳定,会导致进程卡死。
批量任务不要静默跳过。每个失败任务都要保留原始输入和错误信息,不然很难定位是“个别图纸问题”还是“系统性问题”。
7. 从 Demo 到工程化:缓存、评估、反馈,Agent 放最后
7.1 基础链路稳定后再谈 Agentic RAG
现在提到 RAG 实战,很多文章都会讲 Agentic RAG,也就是让模型自主决定检索计划、调用工具、迭代追问。这个方向确实能解决多轮复杂问题,但对图纸合规检查来说,我不建议一开始就上。
原因很简单:Agent 的优势是灵活,代价是结果不可控。合规检查需要的是稳定、可追溯、可复核。如果模型可以自由决定查哪些工具、拼哪些结果,一旦链路复杂,问题定位会很困难。
更稳的路线是:先固定一个“检索 -> 重排 -> 生成”的确定性链路。等基础效果稳定后,再在局部增加 Agent 能力。比如让模型先判断“这个问题需要看图,还是查规范,还是两者都查”,然后走对应子流程。这比直接交给一个完全自主的 Agent 更安全。
7.2 缓存、日志和失败重试
工程化之后,有几个容易被忽略但非常影响体验的部分。
缓存很有必要。同一个问题如果只是图纸版本或规范版本没变,可以缓存结果,避免重复计算。缓存 key 需要考虑问题文本、图纸版本、规范版本、模型版本和参数版本。
日志要分阶段。解析耗时、embedding 耗时、检索耗时、生成耗时都要记录。这样哪天系统变慢了,能知道瓶颈在哪。日志里还要记录每个问题命中的 chunk ID,方便追溯“为什么这次检索结果变了”。
失败重试要设计。解析失败和生成失败应该区别对待。解析失败多半是文件或依赖问题,重试意义不大;生成失败可能是瞬时资源波动,可以重试一到两次。
7.3 评估集和反馈机制
从 Demo 到工程化,最大的变化是:不能再用“看起来不错”来验收。
我建议做一个持续更新的评估集。每次项目文档更新、模型版本升级、参数调整后,都跑一遍。评估集里既要有标准问题,也要有边界问题。边界问题特别重要,比如“图纸标注缺失”“规范条款覆盖不到”“同一问题有多种解释”。
反馈机制也要设计。工程师使用系统后,如果对结论提出异议,系统要能把“用户修正”记录下来。这些修正不是用来训练大模型的,而是用来做后续规则调整和评估集补充的。比如用户多次纠正“某个区域不应被判断为不符合”,说明规则或上下文可能缺少前置条件。
7.4 和通用 RAG 框架怎么配合
做本地 RAG 服务时,常见做法是用 llama.cpp 加载量化模型,再配合 FastAPI 提供接口。这类方案对纯文本问答很合适,但对多模态图纸任务,要注意一个问题:视觉输入不能被简单转成文字描述后交给纯文本模型,否则丢失的信息很难补回。
如果团队使用通用 RAG 平台,比如 Dify 这类框架,办公文档问答会非常顺手。但图纸场景通常需要自定义数据解析流程。我的建议是:用通用框架管理流程、日志、队列和前端展示,但图纸解析、视觉分块、坐标对齐和规范条款结构这些核心环节,要在外部先把数据处理好,再接入框架的检索流程。
通用框架也有一个好处:可以快速搭出交互界面,方便工程师上传图纸、提问、查看证据链。这和 PlanSightRAG 的“视觉优先”并不冲突,关键是别让通用框架把“图”简化成“文本”。
回到 PlanSightRAG 本身,它最值得借鉴的不是某个具体算法,而是“先把图里有什么、图在哪、规范和哪里对应”这些底层问题想清楚。很多图纸问答项目做不好,并不是模型不够强,而是从一开始就把检索对象做错了。如果只把图纸当作文本来切,再强的模型也回答不了看图和查规范两件事的组合问题。
如果在实际项目里也想做类似系统,我的建议很简单:先拿 20 到 50 张图纸,把解析、分块、检索、生成、评估整条链路跑通。跑通之后你会更清楚地看到,问题到底出在分辨率、坐标、条款切分,还是最终生成策略上。先把这条最笨但完整的链路做稳,再谈参数优化和 Agent 化。