ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

text-to-cad 实战:从自然语言到 STEP 模型的三段式架构与工程落地

text-to-cad 实战:从自然语言到 STEP 模型的三段式架构与工程落地 1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词我脑子里蹦出来的画面是对着电脑敲一行字比如一个 80×60×40mm 的带圆角法兰底座中心开 M8 通孔然后软件直接吐出一个可以导出 STEP 的实体模型。这个画面在几年前还属于科幻范畴但现在已经有一批工具和开源方案在往这个方向走了。所谓 text-to-cad本质上是把自然语言描述转换成参数化 CAD 几何体最终输出成 STEP、GLB、STL 这类通用格式让下游的建模、渲染、3D 打印、仿真都能直接吃进去。它解决的问题很具体。传统 CAD 工作流里哪怕你只是想要一个简单的支架、垫块、转接头也得打开 SolidWorks、Fusion 360 或者中望 CAD一步步草图、拉伸、打孔、倒角。对于非专业设计人员——比如做机械臂仿真的、做 3D 打印的、做产品原型的——这个门槛不低。text-to-cad 想干的事就是把这套草图-特征-实体的操作压缩成一段文字描述让程序去生成几何。适合看这篇内容的人大概有三类一是想快速验证结构想法的工程师二是做机器人/仿真需要批量生成零件模型的人三是想搞清楚 LLM 和 CAD 内核怎么对接的技术爱好者。我先把结论摆前面目前 text-to-cad 还做不到随便说句话就出完美工程图它在简单规则几何体上表现不错在复杂曲面、装配约束、工程标注上还很吃力。但如果你把它当成一个快速出草模、批量生成标准件的工具它已经能省下大量重复劳动。下面我按整体设计思路、核心格式解析、实操流程、问题排查四个大块把这条链路拆开讲清楚。2. 整体设计思路为什么是文本→中间表示→CAD 内核三段式2.1 直接让大模型输出 STEP 行不行很多人第一反应是既然大模型能写代码那让它直接输出 STEP 文件的文本内容不就行了我实测过这条路结论是基本不可行。STEP 文件ISO 10303-21是一种非常严格的实体边界表示格式一个最简单的立方体导出的 STEP 里也有几十行CARTESIAN_POINT、DIRECTION、ADVANCED_FACE、EDGE_CURVE之类的拓扑定义而且这些实体之间有严格的引用编号和闭合关系。大模型生成的文本看起来像模像样但引用编号一错、面的法向一乱CAD 内核直接报错打不开。更关键的是STEP 描述的是最终几何的边界而不是建模过程。你没法从 STEP 里看出这里是个孔、那里是个倒角后续想改参数只能重新建模。所以直接生成 STEP 这条路既难保证正确性又丢掉了参数化能力。2.2 三段式架构文本解析、中间表示、几何生成比较靠谱的做法是拆成三层。第一层是文本理解用大模型把自然语言解析成结构化的参数比如{shape: box, length: 80, width: 60, height: 40, fillet: 5, holes: [{type: through, diameter: 8, position: [40, 30]}]}。第二层是中间表示IR把参数映射成 CAD 内核能理解的建模指令序列比如 CadQuery 的链式调用、OpenSCAD 的 CSG 树或者直接调用 FreeCAD 的 Python API。第三层是几何生成与导出由 CAD 内核真正做布尔运算、倒角、网格化最后导出 STEP、GLB、STL。这个架构的好处是每一层都可以单独替换和调试。文本理解错了改 prompt 或换模型中间表示不对检查参数映射几何出错那就是内核的事跟语言模型无关。我踩过的坑是一开始想一步到位让模型直接吐 CadQuery 代码结果模型经常把Workplane的坐标系搞混生成的代码能跑但几何是歪的。后来改成先出 JSON 参数再由固定模板生成代码稳定性提升了一大截。2.3 为什么选 CadQuery / OpenSCAD 作为后端后端选型上CadQuery 和 OpenSCAD 是两个主流选择各有取舍。OpenSCAD 是纯 CSG构造实体几何语法简单适合做规则几何的加减运算但它的圆角、倒角能力弱曲面基本靠hull和minkowski硬凑导出 STEP 需要额外转换。CadQuery 基于 OCCTOpen CASCADE Technology内核原生支持 B-rep 实体、真正的倒角和圆角、STEP 导出更适合工程用途。我个人的选择是CadQuery 为主OpenSCAD 为辅。简单方盒子、阵列孔位用 OpenSCAD 快速出结果需要真实倒角、螺纹、STEP 交付的用 CadQuery。下面这张表是我总结的选型对照供你参考维度OpenSCADCadQuery几何内核CSG网格体素OCCTB-rep倒角/圆角弱需手动构造原生支持STEP 导出需转换易丢精度原生支持学习曲线低中适合场景快速草模、3D 打印工程件、装配、仿真文本生成友好度高语法简单中API 较多2.4 输出格式的选择逻辑STEP、GLB、STL 各管一段热词里反复出现 STEP、GLB、STL这三个格式不是随便选的它们对应不同的下游用途。STEP是工程交换格式保留精确的 B-rep 几何和拓扑适合导入 SolidWorks、中望 CAD、Fusion 360 继续编辑也是 CNC 加工、工程交付的标准。STL是三角网格只有表面没有拓扑适合 3D 打印和快速预览但精度取决于网格密度圆孔会变成多边形。GLB是 glTF 的二进制版本带材质和场景信息适合网页预览、AR/VR、渲染展示。所以一个完整的 text-to-cad 流程通常是先生成精确实体再按需导出要工程编辑导 STEP要打印导 STL要展示导 GLB。我见过有人直接拿 STL 去转 STEP热词里sw中stl转stp就是这个需求结果得到一个由几万个三角面拼成的实体根本没法做参数化编辑这是典型的格式误用。3. 核心细节解析文本怎么变成可执行的建模指令3.1 文本解析把人话拆成结构化参数这一步是整个链路里最不确定的环节因为自然语言太灵活。同样是一个带孔的板有人会说100×50 的板中间打个 10mm 的孔有人会说长 100 宽 50中心通孔直径 10。我的做法是定义一套严格的 JSON Schema让大模型按 schema 输出而不是自由发挥。一个典型的参数结构长这样{ units: mm, base: { type: box, length: 100, width: 50, height: 10 }, features: [ { type: hole, subtype: through, diameter: 10, position: [50, 25], axis: z } ], fillets: [ {edge: vertical, radius: 3} ] }这里有几个关键设计。单位必须显式声明因为 CAD 里 mm 和 inch 差 25.4 倍模型直接错一个量级。位置用绝对坐标还是相对坐标要统一我倾向绝对坐标因为相对坐标在多个特征叠加时容易算错。特征用数组而不是嵌套方便后续按顺序执行布尔运算。提示让大模型输出 JSON 时务必在 prompt 里给出完整的字段说明和示例并要求只输出 JSON不要解释。我试过不加约束模型会在 JSON 前后加一堆好的这是您的模型之类的废话解析直接失败。3.2 中间表示JSON 到 CadQuery 代码的映射拿到 JSON 后需要一个确定性的转换器把它变成 CadQuery 代码。这一步不能用大模型必须用固定模板因为几何生成的正确性不能靠概率。下面是我用的核心映射逻辑import cadquery as cq def build_from_spec(spec): base spec[base] # 基础实体 if base[type] box: result cq.Workplane(XY).box( base[length], base[width], base[height] ) # 特征叠加 for feat in spec.get(features, []): if feat[type] hole: result result.faces(Z).workplane().pushPoints( [tuple(feat[position])] ).hole(feat[diameter]) # 倒角 for fil in spec.get(fillets, []): if fil[edge] vertical: result result.edges(|Z).fillet(fil[radius]) return result # 导出 model build_from_spec(spec) cq.exporters.export(model, output.step) cq.exporters.export(model, output.stl)这段代码里有个容易翻车的点faces(Z)选的是 Z 方向最高的面如果你的基础实体高度方向不是 Z或者前面已经做过布尔运算改变了拓扑这个选择器可能选错面。我的经验是在每个特征操作前先打印当前实体的面和边数量确认选择器命中的是你想要的面。CadQuery 的faces()、edges()选择器很强大但也很玄学多调试几次就有感觉了。3.3 几何内核布尔运算的顺序决定成败CAD 建模里特征的执行顺序直接影响结果。举个简单例子先打孔再倒角和先倒角再打孔结果可能完全不同。如果孔靠近边缘先倒角可能导致孔壁被削掉一部分先打孔再倒角则可能让倒角面穿过孔。我的原则是先做主体形状再做减材特征孔、槽最后做倒角圆角。这样倒角作用在最终轮廓上最符合直觉。另一个坑是薄壁件的布尔运算。当你从一个实体里减去另一个几乎贴合的实体时OCCT 内核可能因为面重合产生零厚度错误。解决办法是让减材实体稍微超出被减实体比如打孔时孔的深度比板厚多 1mm确保完全穿透而不是刚好相等。3.4 精度与网格密度STL 导出不能随便设导出 STL 时默认的线性偏差linear deflection和角度偏差angular deflection决定了网格密度。设太大圆孔变成六边形设太小文件几百 MB 打不开。我的经验值线性偏差取模型最小特征尺寸的 1/10 到 1/20。比如最小孔直径 5mm线性偏差取 0.25~0.5mm。角度偏差一般取 0.1~0.5 弧度。下面是对照表用途线性偏差角度偏差典型文件大小快速预览1.0mm0.5rad小3D 打印0.1mm0.2rad中精细展示0.02mm0.1rad大仿真网格0.05mm0.1rad大注意STL 是网格格式无论你怎么调精度圆孔永远是多边形近似。如果下游需要真正的圆柱面必须用 STEP别在 STL 上纠结精度。4. 实操过程从零搭一个可用的 text-to-cad 流水线4.1 环境准备与依赖安装先把环境搭起来。我用的组合是 Python 3.10 CadQuery 2.x 一个大模型 API。CadQuery 的安装推荐用 conda因为它的 OCCT 依赖在 pip 下经常编译失败conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install openai pydantic装完之后先跑个冒烟测试确认内核能用import cadquery as cq box cq.Workplane(XY).box(10, 10, 10) cq.exporters.export(box, smoke_test.step) print(OK)如果这一步报OCCT相关的错八成是 conda 环境没激活或者版本冲突重装一遍通常能解决。我踩过的坑是在系统 Python 里直接 pip install cadquery装了两小时最后导入失败白白浪费时间。4.2 文本解析模块的实现解析模块的核心是 prompt 设计。我的 prompt 模板大致是这样你是一个 CAD 参数解析器。用户会用自然语言描述一个零件 你需要输出符合以下 JSON Schema 的参数不要输出任何解释。 Schema: { units: mm | inch, base: {type: box|cylinder, length:..., width:..., height:...}, features: [{type:hole,diameter:...,position:[x,y],axis:z}], fillets: [{edge:vertical,radius:...}] } 用户描述{user_input}实测下来给 schema 比给自然语言说明有效得多。我一开始写请提取尺寸和孔位模型经常漏字段或者自己发明字段。改成 JSON Schema 后字段完整率明显提升。另外加一句如果用户没指定单位默认 mm能避免大量单位歧义。4.3 几何生成与多格式导出生成模块我封装成一个函数输入 JSON输出三个文件def generate(spec, namepart): model build_from_spec(spec) cq.exporters.export(model, f{name}.step) cq.exporters.export(model, f{name}.stl, tolerance0.1, angularTolerance0.2) # GLB 需要先转网格再导出 import trimesh mesh trimesh.load(f{name}.stl) mesh.export(f{name}.glb) return modelGLB 的导出这里绕了一下因为 CadQuery 不直接支持 GLB。我的做法是先导 STL再用 trimesh 转 GLB。如果你需要带材质的 GLB可以在 trimesh 里给 mesh 赋材质再导出。这个链路实测稳定STL 和 GLB 的几何一致。4.4 一个完整案例生成带法兰的机械臂连接件假设用户输入生成一个 60×60×8mm 的方形法兰板四角各一个 M6 通孔孔中心距边缘 8mm中心一个直径 30mm 的圆凸台高 15mm凸台中心开 20mm 通孔。解析后的 JSON{ units: mm, base: {type: box, length: 60, width: 60, height: 8}, features: [ {type: hole, diameter: 6.6, position: [8, 8], axis: z}, {type: hole, diameter: 6.6, position: [52, 8], axis: z}, {type: hole, diameter: 6.6, position: [8, 52], axis: z}, {type: hole, diameter: 6.6, position: [52, 52], axis: z}, {type: boss, diameter: 30, height: 15, position: [30, 30]}, {type: hole, diameter: 20, position: [30, 30], axis: z} ] }注意 M6 通孔我用了 6.6mm 而不是 6mm这是螺纹过孔的常规做法留 0.6mm 间隙方便装配。这个细节如果让大模型自己决定它可能直接给 6mm装不进去。所以我在 prompt 里加了一条规则M 系列螺纹过孔直径 公称直径 0.5~1mm。生成后的模型导出 STEP导入中望 CAD 或者 SolidWorks 检查尺寸和拓扑都正确。整个过程从输入文字到拿到 STEP大概 10 秒。如果手工建模这个件至少 5 分钟。4.5 批量生成用循环处理零件清单text-to-cad 真正体现价值的地方是批量。比如你要给一个六轴机械臂做仿真需要几十个连接件、垫块、转接板。这时候把描述写成列表循环调用生成函数parts [ {desc: 40x40x5 底板中心 M8 孔, name: base_plate}, {desc: 直径 25 高 30 的圆柱中心 10mm 通孔, name: spacer}, # ... ] for p in parts: spec parse_text(p[desc]) generate(spec, p[name])这里有个经验批量生成时一定要加异常捕获和日志。因为只要有一个零件的参数解析出错整个循环就断了。我的做法是每个零件单独 try-except失败的记录到日志里最后统一人工检查。实测下来简单规则件的成功率能到 90% 以上复杂的多特征叠加、非标准形状大概 60~70%。5. 常见问题与排查技巧实录5.1 模型打不开或导入报错这是最常见的问题表现是 STEP 文件生成了但导入 CAD 软件时报无效的实体或直接崩溃。原因通常有三类一是布尔运算产生了非流形几何比如零厚度面二是倒角半径大于相邻边长度导致自交三是导出时实体不是闭合的。排查思路先在 CadQuery 里检查实体的有效性print(model.val().isValid()) print(model.val().Volume())isValid()返回 False 就说明几何有问题。Volume()如果是 0 或者负数说明实体没闭合或者法向反了。我遇到最多的是倒角半径过大比如 10mm 厚的板倒 8mm 圆角相邻两个倒角面直接撞在一起。解决办法是倒角半径不超过最小边长的 1/3。5.2 孔位偏移或方向错误这个问题的根源通常是坐标系理解不一致。CadQuery 默认在 XY 平面建模Z 是高度方向。但用户描述从左下角量 20mm时左下角到底是原点还是某个角我的做法是在 prompt 里强制约定所有坐标以基础实体最小角为原点X 向右Y 向上Z 向外。这样解析出来的坐标就是确定的。另一个坑是workplane()的偏移。在某个面上打孔时如果不指定workplane(offset...)孔可能从面往里打也可能往外打。我习惯在打孔前显式指定方向比如.workplane(offset-1)确保从表面往里。5.3 STL 文件过大或过小STL 大小完全由网格精度决定。文件过大几百 MB通常是精度设太高解决方法是调大 linear deflection。文件过小几 KB导致圆孔变多边形就调小 deflection。我一般先用默认值导一次看看文件大小和目视效果再微调。对于 3D 打印0.1mm 的线性偏差基本够用对于网页展示0.5mm 都嫌细。5.4 大模型解析不稳定同一个描述模型这次解析对下次就漏字段。这是 LLM 的固有特性没法完全消除但可以缓解。我的几个手段降低 temperature 到 0减少随机性在 prompt 里给 2~3 个 few-shot 示例让模型模仿格式加输出校验解析完 JSON 后用 pydantic 验证字段完整性和数值范围不合格就重试一次。实测下来加了校验和重试后解析成功率从 70% 提到 90% 以上。5.5 常见问题速查表现象可能原因排查方法解决STEP 导入报错非流形/零厚度isValid()调整布尔运算减材实体超出孔位偏移坐标系不一致打印坐标统一原点约定倒角失败半径过大检查边长半径 ≤ 最小边 1/3STL 太大精度过高看文件大小调大 deflection圆孔变多边形精度过低目视调小 deflection解析漏字段LLM 不稳定看 JSON降 temperature 校验重试模型体积为 0实体未闭合Volume()检查布尔顺序提示每次生成后别急着导入 CAD先在 Python 里跑一遍isValid()和Volume()检查能挡掉 80% 的低级错误省下大量来回导入导出的时间。6. 我对 text-to-cad 的实际体会与扩展方向用下来这段时间我最大的感受是text-to-cad 不是要取代 CAD 工程师而是把重复性建模这件事自动化掉。标准件、垫块、转接板、阵列孔位这些活以前一个个画现在描述一下批量出省下的时间可以花在真正需要创造力的复杂结构上。它的边界也很清楚规则几何、参数明确、单件或少特征叠加的场景它很能打自由曲面、复杂装配约束、工程标注目前还得靠人。后续我觉得可以往几个方向扩展。一是接入尺寸链校验生成后自动检查孔间距、壁厚是否满足加工要求比如最小壁厚 1.5mm、孔边距不小于孔径。二是和仿真打通生成的 STEP 直接丢进有限元做静力分析形成描述-建模-仿真的闭环。三是支持装配体描述比如一个底座加四个 M6 螺栓加一个盖板自动生成带配合关系的装配文件。这些方向目前都有开源项目在尝试感兴趣的话可以顺着 CadQuery 和 OCCT 的文档往下挖。最后分享一个我踩过的小坑别在 prompt 里用大约差不多这类模糊词。我试过输入大概 50mm 的板模型给了 50但下游加工需要精确值这种模糊描述在工程场景里是灾难。text-to-cad 的输入越精确输出越可靠这一点和传统建模没有区别。
返回列表