
最近在GitHub上刷到一个很有意思的开源项目星星数已经涨到480多颗简单说就是给AI装一双会看图纸的眼睛——把Revit、IFC、DWG这类工程领域最常见的CAD/BIM文件一键转成结构化的JSON数据。最香的是整个过程不需要安装任何Autodesk的商业软件。也就是说不用Windows下那一套庞大的Revit环境不用正版授权甚至你手头只有一台Linux服务器也能把图纸中的墙体、门窗、楼层、构件信息、坐标关系全部提取出来喂给大模型做分析。这个思路我关注了很久因为AI在文本和图像领域已经卷出天际了但在建筑工程领域绝大多数大模型还处于“睁眼瞎”状态。聊天、写文案、生成代码都很强可你拿一张DWG总平面图给它它基本看不出什么门道。核心原因不在模型本身而是在于输入格式。Revit、IFC、DWG这些格式本质上不是给自然语言模型消费的它们是几何引擎、参数化建模软件和CAD平台之间交换数据的载体。想要让AI读懂图纸就必须先有一个“翻译层”把这些专业二进制格式转换成模型能理解的文本或结构化数据。今天就把这个项目的来龙去脉拆开聊一聊包括格式原理、技术选型、完整实操流程还有我踩过的几个坑希望能帮你少走弯路。不管你是BIM工程师、二次开发从业者还是正在做建筑行业AI应用的产品经理这篇文章应该都能给你一些参考。1. 为什么AI总是“看不懂”图纸先说一个很多人忽略的事实建筑设计行业里的图纸格式天然是给机器看的而不是给人类或大模型看的。1.1 三种格式的“性格差异”RVTRevit项目文件是Autodesk专有的二进制格式里面不仅包含三维几何体还包含了族参数、构件类型、材质信息、阶段化数据、视图设置等一整套BIM逻辑。只要离开了Revit环境想直接解析这个文件几乎是不可能的因为它的数据组织方式和Revit的API深度绑定。IFC则完全是另一个路子。它是buildingSMART组织维护的开放标准格式专门用来描述建筑构件的语义信息。一个IFC文件里墙就是IfcWall门是IfcDoor楼板是IfcSlab它们之间的关系用IfcRelAggregates、IfcRelContainedInSpatialStructure这些关系实体来表达。因为它是公开的、文本化的IFC-SPF格式本质上是ISO 10303-21标准的STEP物理文件所以解析起来比Revit友好得多。DWG则是AutoCAD的老牌格式从1982年发展到现在中间迭代了至少几十个版本。内部结构极其复杂有各种版本差异而且也是封闭的商业格式。和IFC不同DWG通常只有几何数据比如线、圆弧、多段线、填充、标注基本不带建筑语义所以后面做AI应用时需要额外做一层信息提取。1.2 关键痛点数据孤岛与格式壁垒这几种格式之间的壁垒说白了就是建筑行业的“数据孤岛”。设计院用Revit建模施工单位拿到图纸后往往又要重新建模或手工翻图运维阶段再面对一沓PDF和Excel更是头疼。整个行业花了大量人力在格式转换和数据整理上。而AI时代的到来让这个问题变得尤其尖锐。想要训练一个能自动审图的模型你得先有大量标注好的图档数据想做一个基于图纸的智能问答机器人你得让大模型能读到构件属性和空间关系。光是数据清洗这一步就能卡住90%的团队。这个开源项目走了一条很聪明的路线不去硬啃Revit的二进制格式而是先用开放标准IFC作为中间载体再用各种开源库去解析DWG最终统一输出成JSON或者文本让大模型可以直接消费。一句话总结它的思路不是“替代Autodesk”而是“绕开Autodesk”。你不需要装任何商业软件只需要一个转换管道把图纸变成AI能懂的语言。1.3 传统做法到底贵在哪很多人会问用Revit本身不是能直接导出数据吗确实Revit可以通过Dynamo、Revit API导出构件明细表也可以手动导出IFC。但这里有几个绕不过去的问题需要Windows环境加正版Revit授权License费用不低。批量处理时极其痛苦几十个模型文件跑起来Revit经常卡死或崩溃。API开发门槛高你得熟悉C#和Revit的对象模型。不适合作为服务端流水线的一部分你不能在Docker容器里跑Revit。所以如果要做自动化、批量化的AI数据管道传统的“先导CAD再转换”的方式根本不适合。这也是这个开源项目存在的核心价值它是一个轻量级的转换中间层可以嵌入到你的Python数据处理流程里跑在Linux服务器上轻松实现批量处理。2. 项目核心设计思路拆解这个项目的整体架构可以拆成三个层次格式归一化层、语义提取层、AI适配层。2.1 从Revit到JSON先做格式归一再做语义提取它的设计非常务实不尝试用一个解析器通吃所有格式而是分三步走。第一步是格式归一化。无论是Revit、IFC还是DWG最终都会转成一个统一的数据模型。Revit文件先导出成IFCDWG先转换成DXF然后由各自的解析器提取信息。这样做的好处是后续的AI处理面对的是统一结构不用为每种格式写不同的逻辑。第二步是语义提取。从IFC里提取构件类型、空间结构、几何位置、连接关系从DXF里提取图层、线型、文本标注和块引用。这个阶段产出的就是一套基本完整的建筑信息数据集。第三步是AI适配。把提取出来的结构化数据序列化成JSON、JSONL或者缩略成纯文本形式配合Prompt模板就可以直接用于大模型的问答、摘要、审查等任务。2.2 为什么选IfcOpenShell作为核心解析引擎在IFC解析这个环节项目使用了IfcOpenShell这是开源社区里公认的IFC处理工具。它支持Python绑定可以读取IFC实体属性、拆分构件、计算体积面积、甚至做几何拓扑分析。我对这个库的评价是它几乎把IFC的复杂度全部封装好了。你只需要写几行Python代码就能拿到一面墙的厚度、高度、材质名称和它在第几层。它内部处理了STEP文件的解析、实体继承关系的展开、单位换算和坐标系变换这些如果全部自己实现没有几个月搞不定。import ifcopenshell # 打开IFC文件 ifc_file ifcopenshell.open(sample.ifc) # 提取所有墙构件 walls ifc_file.by_type(IfcWall) for wall in walls: name wall.Name global_id wall.GlobalId # 获取属性集 pset ifcopenshell.util.element.get_psets(wall) print(name, global_id, pset)这一段代码基本上就是项目的底层核心调用方式。可以看到解析IFC的难度被降到了极低非专业程序员也能上手。2.3 DWG解析的关键用ODA File Converter做“前锋”用ezdxf做“后卫”DWG就比IFC麻烦多了。因为DWG不是开放格式纯开源的解析方案还不算成熟。项目里采用了一个很常见的组合拳先用ODA File Converter把高版本DWG批量转成DXF再用ezdxf这个Python库去读取DXF内容。ODA File Converter是Open Design Alliance出的免费工具支持DWG到DXF的双向转换覆盖AutoCAD 2018到旧版的大部分格式。它没有图形界面自动化能力但可以通过命令行调用这在批量处理时非常有用。ezdxf则是一个非常成熟的DXF处理库。它不只能读取还能创建和修改DXF文件。对于建筑图纸我们主要提取这几类内容图层信息每个图层名称通常对应着“墙”、“门窗”、“标注”、“轴线”等语义。TEXT/MTEXT实体这是图纸里的文字标注。INSERT实体即块引用通常代表门窗、家具、设备等。LINE/LWPOLYLINE/ARC实体即基础几何轮廓。import ezdxf # 打开DXF文件 doc ezdxf.readfile(drawing.dxf) msp doc.modelspace() # 遍历所有实体 for entity in msp: if entity.dxftype() TEXT: print(文本:, entity.dxf.text, 位置:, entity.dxf.insert) elif entity.dxftype() INSERT: print(块插入:, entity.dxf.name, 位置:, entity.dxf.insert) elif entity.dxftype() LWPOLYLINE: print(多段线顶点数:, len(entity.get_points()))这个组合方案在实际运行中非常稳定。唯一需要注意的是ODA File Converter不是完全开源的不过对于绝大多数个人项目和小团队来说免费授权足够用了。2.4 Revit文件解析的“曲线救国”路线至于Revit的RVT文件项目并没有直接去解析而是走“先导出IFC再解析”的路线。这个设计很聪明因为RVT是封闭的想直接读取geometrical data要么用Revit API要么逆向工程成本极高。而BIM软件本身支持的IFC导出已经能把绝大部分构件语义和几何信息带出来了。这里我补充一个实操经验用Revit导出IFC时一定要在导出设置里勾选“Split Walls and Columns by Level”、“Export 2D Elements”这些选项否则导出的IFC模型在楼层划分和二维图元上会丢失信息。另外Revit导出IFC有两种格式一种是IFC2x3 Coordination View另一种是IFC4 Reference View。如果是给AI做分析用建议优先用IFC4因为它的属性表达能力更强构件类型也更细。3. 实操从零跑通“图纸转AI可读数据”这部分我拿一个实际案例来演示完整流程。假设我们有一个三层办公楼的Revit模型已经用Revit导出了IFC文件同时还有一张地下室平面图的DWG现在要把它们全部转成JSON然后交给大模型回答问题。3.1 环境准备需要准备的环境很简单一台Linux或者Windows电脑就行不需要安装任何Autodesk产品。核心依赖是Python 3.9以上加上几个库。pip install ifcopenshell ezdxf shapely还要下载ODA File Converter安装后确认命令行可用。在Windows上它通常位于“C:\Program Files\ODA\ODAFileConverter\ODAFileConverter.exe”在Linux上则需要用wine运行或者下载Linux原生版。3.2 IFC文件的信息提取首先处理IFC文件。我的目标是提取出每一层楼的房间面积、墙体体积、门窗数量以及这些构件的属性信息。import ifcopenshell import ifcopenshell.util.element as element import json # 打开IFC文件 ifc_file ifcopenshell.open(office_building.ifc) # 获取所有楼层 storeys ifc_file.by_type(IfcBuildingStorey) result {storeys: []} for storey in storeys: storey_data { name: storey.Name, elevation: storey.Elevation if hasattr(storey, Elevation) else None, walls: [], doors: [], windows: [], spaces: [] } # 获取楼层中包含的构件 contains_elements ifcopenshell.util.element.get_contained_elements(storey) for element_type in contains_elements: # 墙 if element_type.is_a(IfcWall): wall_psets element.get_psets(element_type) storey_data[walls].append({ name: element_type.Name, height: wall_psets.get(Pset_WallCommon, {}).get(Height), area: wall_psets.get(Qto_WallBaseQuantities, {}).get(NetSideArea), volume: wall_psets.get(Qto_WallBaseQuantities, {}).get(NetVolume) }) # 门 elif element_type.is_a(IfcDoor): storey_data[doors].append({name: element_type.Name}) # 窗 elif element_type.is_a(IfcWindow): storey_data[windows].append({name: element_type.Name}) # 获取房间空间 spaces ifcopenshell.util.element.get_contained_elements(storey, ifc_typeIfcSpace) for space in spaces: space_psets element.get_psets(space) storey_data[spaces].append({ name: space.Name, area: space_psets.get(Qto_SpaceBaseQuantities, {}).get(NetFloorArea), volume: space_psets.get(Qto_SpaceBaseQuantities, {}).get(NetVolume) }) result[storeys].append(storey_data) # 导出JSON with open(ifc_output.json, w) as f: json.dump(result, f, ensure_asciiFalse, indent2) print(IFC解析完成共, len(result[storeys]), 个楼层)这一点我需要说一下如果你直接用官方API硬啃IFC文件可能得研究半天IfcRelContainedInSpatialStructure的关系链而用ifcopenshell.util.element.get_contained_elements()这个方法一下子就把楼层和构件的包含关系拿出来了。这就是站在前人的肩膀上。3.3 DWG文件的批量转码与提取接下来处理DWG格式的地下室平面图。我这里有两张DWG都是AutoCAD 2018格式直接用ezdxf读取会报“DWG is not supported, use DXF”之类的错误。所以先交给ODA File Converter转成DXF。命令行方式如下# 先把所有DWG转成DXF ODAFileConverter input_dir output_dir ACAD2018 DXF 0 1 *.dwg这个命令的含义是把input_dir下的所有DWG文件转成AutoCAD 2018版本的DXF文件输出到output_dir。参数0代表输出文件类型为DXF1覆盖同名文件。转换完成后再用ezdxf读取DXF。我写了一个提取图层、文字标注和块引用的脚本。import ezdxf import json doc ezdxf.readfile(basement_plan.dxf) msp doc.modelspace() layers set() texts [] blocks [] for entity in msp: layers.add(entity.dxf.layer) if entity.dxftype() TEXT: texts.append({ text: entity.dxf.text, position: list(entity.dxf.insert) }) elif entity.dxftype() MTEXT: texts.append({ text: entity.text(), position: list(entity.dxf.insert) }) elif entity.dxftype() INSERT: blocks.append({ name: entity.dxf.name, position: list(entity.dxf.insert) }) result { layers: list(layers), texts: texts, blocks: blocks } with open(dwg_output.json, w) as f: json.dump(result, f, ensure_asciiFalse, indent2) print(DWG解析完成共, len(layers), 个图层, len(texts), 条文字标注, len(blocks), 个块引用)这个脚本跑完后我拿到的JSON里能看到“轴网”、“墙体”、“门”、“窗”、“标高”这些图层名以及“C-1”、“M-1”、“FM甲-1”这类门窗编号还有“-4.200”、“±0.000”这样的标高标注。这些信息对于AI理解图纸内容非常有价值。3.4 合并数据并喂给大模型IFC和DWG都解析完之后下一步就是把两种数据合并成一个总JSON然后根据场景组装Prompt调用大模型API进行问答。我最常用的做法是把JSON转成一段格式化的纯文本然后用“角色设定任务指令文本数据问题”的结构构造Prompt。import json import openai # 读取解析后的IFC和DWG数据 with open(ifc_output.json) as f: ifc_data json.load(f) with open(dwg_output.json) as f: dwg_data json.load(f) # 组装文本描述 building_desc 这是一栋三层办公楼。\\n for storey in ifc_data[storeys]: building_desc f楼层{storey[name]}标高{storey[elevation]}米\\n building_desc f- 包含墙构件{len(storey[walls])}个门{len(storey[doors])}个窗{len(storey[windows])}个\\n for space in storey[spaces]: building_desc f- 房间{space[name]}面积{space[area]}平方米体积{space[volume]}立方米\\n building_desc 地下室平面图信息\\n building_desc f- 图层{, .join(dwg_data[layers])}\\n building_desc f- 门编号{, .join([b[name] for b in dwg_data[blocks] if 门 in b[name]])}\\n # 调用大模型 client openai.OpenAI(api_keyyour-api-key) response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是资深建筑设计师请根据图纸数据回答用户问题。}, {role: user, content: f图纸数据如下\\n{building_desc}\\n\\n问题这栋楼一共有多少扇门每层面积最大的房间是哪个} ] ) print(response.choices[0].message.content)这个流程跑通之后你就会发现大模型对图纸的理解能力立刻上了一个台阶。它能根据你提供的数据回答“总共有多少门”、“三层哪个房间面积最大”、“地下室有多少种门编号”这类问题。虽然数据源仍然是结构化的但对使用者来说体验已经是自然语言对话了。3.5 进阶用向量检索做超大图纸的问答遇到超大项目时一次把整个模型塞进Prompt会超出上下文窗口或者导致成本飙升。我用的方案是先把解析出的构件信息做向量化存入向量数据库再配合RAG检索增强生成回答。每个构件或房间作为一个文档例如“三层会议室的净面积是85平米”、“首层大门采用的是FM甲-1甲级防火门”。然后用Embedding模型转成向量存到Chroma或者Qdrant里。查询的时候先检索相关的构件信息再扔给大模型归纳。这个进阶方案我在几个真实项目里验证过效果比一次性全量注入好很多特别是在处理十万级以上构件量的模型时速度、成本、准确率都能兼顾。4. 拿到数据之后能干什么实在事把图纸转成AI可读数据只是第一步真正有想象力的地方在下游应用。4.1 AI辅助审图与合规检查审图是建筑设计流程里非常耗费人力的环节。传统审图需要设计师和审查人员一页一页翻图纸对照规范找错误。现在有了结构化数据完全可以做一个自动合规检查工具。比如你可以定义一系列规则“楼梯梯段净宽不小于1.2米”、“走廊净高不小于2.4米”、“防火门等级不低于乙级”然后用脚本批量检查IFC数据里的构件属性不符合的自动标红。你也可以把规范文本和图纸数据一起喂给大模型让它做自由文本的合规审查效率比纯人工高很多。我试过用这个思路处理一个中型项目的结构图把墙厚、混凝土标号、配筋信息提取出来然后跟结构规范做比对半小时内找出了三处疑似不满足规范的地方设计师复核后确认两处确实是设计疏忽。4.2 工程量自动统计与造价估算从IFC里能拿到墙的体积、梁的截面尺寸、门的数量、窗的面积这些都是工程量清单的基础数据。虽然目前传统的工程量计算软件已经很成熟但它的流程是封闭的生成的数据难以直接供AI分析。而有了一个可编程的“数据中台”你可以随时用Python脚本统计任意维度的工程量然后对接造价库做快速估价。比如三层总共需要多少立方米的C30混凝土有多少平方米的断桥铝合金窗这些数据可以直接汇总成表格供商务标编制和成本管理使用。4.3 基于图纸的智能搜索与问答很多设计院和施工企业都有大量的历史图纸这些图纸散落在各个工程师的电脑里查找起来极其痛苦。利用这个转换工具你可以把所有历史图纸解析成统一的文档库然后做一个企业内部的“图纸搜索引擎”或者“问答机器人”。建筑师只需要问“之前那个医院项目里门诊楼的抗震等级是多少”系统就会从对应图纸的数据中检索出答案。这个应用对老图纸特别有价值因为很多老项目的原始信息只存在于DWG文件里施工人员去现场之前想查点资料还得翻半天CAD才能打开看。5. 常见问题与排查技巧实录实操过程中绝对会遇到各种坑这里整理几个最常见的问题和我的排查方法。5.1 ODA File Converter转换失败这个工具对高版本DWG的支持有时候会出现问题特别是一些用天正CAD基于AutoCAD二次开发画的图纸。天正图元写入的是自定义对象ODA转换之后容易出现“代理实体”或者直接丢失信息。遇到这类图纸我一般是先用天正CAD自身导出T3格式再走ODA转换。或者直接在AutoCAD里用EXPORTTOAUTOCAD命令把天正对象分解成普通实体。转换后先用ezdxf快速扫一遍看看图层和文字是否完整再做后续解析。5.2 Revit导出IFC时构件丢失这个我遇到过好几次典型场景是Revit模型里的“自适应族”或者“基于面的族”导出IFC时会变成一堆没有语义的“IfcBuildingElementProxy”属性全丢。解决办法是在Revit中导出IFC之前把族类别改成对应的系统族类型比如把幕墙嵌板族改成IfcCurtainWall。另外导出设置里要勾选“Export Revit property sets”和“Export IFC common property sets”这两个选项非常关键不勾的话导出文件里几乎没有属性信息。5.3 JSON文件过大导致模型上下文溢出处理大体量项目时生成的JSON可能达到几十兆直接把文本塞进Prompt会超出上下文窗口。我的经验是根据问题类型做有针对性地裁剪。如果是问门窗数量那只需要提取构件类型和数量字段不需要几何坐标如果是问空间关系则保留空间结构树和连接关系。另一个方案是用RAG前面说过了这是最可扩展的路径。5.4 DWG坐标单位不统一很多DWG文件没有遵守“毫米和米”的规范有的用毫米有的用英寸还有CAD制图习惯直接用“1绘图单位1米”的。解析出来的坐标如果不做单位换算喂给AI就会产生严重误导。我的做法是在解析脚本里统一做分层处理根据图纸里的标高标注和尺寸标注推算单位比例然后统一换算成毫米存储。这个步骤没有通用解法只能针对具体图纸做一些规则化处理。5.5 格式解析问题速查表问题现象可能原因解决方案IFC解析出来没有属性信息Revit导出未勾选属性选项重新导出勾选属性集选项DWG转DXF后缺少文字天正自定义对象未分解先导出T3格式再转换DXF图层名乱码编码问题设置dxf.readfile参数encodinggbk模型单位混乱不同专业图纸混用单位统一转换为毫米按比例尺换算构件类型为Proxy族类别未正确映射修改信息使用Revit中导出设置调整族类型大模型回答不准数据裁剪过狠或格式不友好调整Prompt增加上下文语境说明最后再分享一个小技巧项目用了一段时间之后我觉得最有价值的一个“隐藏功能”是把转换出来的JSON当作微调数据集的生成器。你可以用大模型对同一批JSON数据生成不同角度的问题和答案人工验一遍之后就得到了一批高质量的行业问答数据拿来做模型微调或者评估集都很好用。我自己目前就在用一个更大的本地测试集解析了大概一百多个住宅楼的IFC模型生成了三千多道建筑规范相关的问题用它们评估不同大模型在建筑领域的表现。实测下来数据质量直接影响模型表现而这个项目等于帮我搞定了一整套数据管线。如果你也在做建筑AI相关的事情这个“图纸数据桥”的思路值得借鉴。别一上来就盯着Revit二次开发先把数据翻成一个通用格式后面很多事情都会顺畅很多。