Text-to-CAD实战:从自然语言到STEP/GLB/STL的完整链路 1. 从一句话到一个实体模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个词很多人脑子里浮现的画面大概是对着电脑敲一行字比如“一个边长 50mm 的立方体中心开一个直径 20mm 的通孔”然后软件自动吐出一个可以旋转、可以导出、可以拿去打印的三维模型。这个画面听起来像是科幻片里的桥段但它背后其实是一条已经跑得通的技术链路只是目前还没有被大多数人用顺手。我最早接触这个方向是因为手头有一批结构相似、尺寸不同的零件要建模。传统做法是在 CAD 软件里一个个画草图、拉伸、打孔、倒角重复劳动多到让人怀疑人生。后来我尝试用脚本批量生成再后来接触到用自然语言驱动建模的思路也就是 text-to-cad。它的核心价值很直接把“人对着图形界面点鼠标”这件事换成“人用语言描述需求程序去执行建模”。对于需要批量出图、快速验证结构、或者本身不熟悉 CAD 操作的人来说这是一条值得投入时间研究的路径。需要先厘清一个概念text-to-cad 不是一个具体的软件而是一类工作流的统称。它的输入端是自然语言或者结构化文本输出端通常是STEP、GLB、STL这几种格式之一。STEP 偏向精确的工程交换格式保留实体边界表示适合后续在专业 CAD 里继续编辑GLB 是面向渲染和展示的格式带材质和层级适合放进网页或者三维场景STL 则是三角面片网格几乎是 3D 打印的通用语言。理解这三者的差异是理解整个 text-to-cad 链路的第一步因为不同的输出目标决定了中间该走哪条技术路线。这篇文章适合几类人看一是经常需要重复建模、想用脚本提效的工程师二是做三维可视化、需要快速产出展示模型的开发者三是刚入门 CAD、想找一个低门槛方式理解建模逻辑的新手。我会把整条链路拆开讲包括文本怎么变成几何、几何怎么变成文件、中间有哪些坑以及我自己踩过的那些教训。2. 整体设计思路文本如何一步步变成三维实体2.1 为什么不能指望“一句话直接生成完美模型”很多人对 text-to-cad 的期待是“输入一句话输出一个能直接用的模型”。实测下来这种期待在简单几何体上勉强成立一旦涉及复杂结构就会崩。原因在于自然语言本身是模糊的而 CAD 建模要求的是精确的尺寸、约束和拓扑关系。你说“一个带圆角的盒子”圆角半径是多少盒子壁厚是多少这些信息缺失程序只能猜猜出来的结果大概率不是你想要的。所以一个靠谱的 text-to-cad 工作流通常不是“文本直接到模型”而是“文本到中间表示再到模型”。中间表示可以是一段参数化的脚本也可以是一份结构化的 JSON 描述还可以是一段代码。这个中间层的作用是把模糊的自然语言翻译成精确的、可执行的指令。我个人的习惯是让文本先转成参数表再由参数表驱动建模函数这样每一步都可控、可调试、可复现。2.2 三种主流技术路线的取舍目前实现 text-to-cad 大致有三条路线各有各的适用场景。第一条是代码驱动路线代表工具是 OpenSCAD 和 CadQuery。你用类似编程的方式描述几何比如cube([50,50,50])就是一个 50 毫米的立方体。文本到 CAD 的过程就是让语言模型把自然语言翻译成这类代码。这条路线的优点是精确、可参数化、版本可控缺点是学习曲线陡复杂曲面表达起来吃力。第二条是参数化特征路线依托 FreeCAD 这类支持脚本的 CAD 内核。它更接近传统 CAD 的建模逻辑用草图、拉伸、布尔运算这些特征来构建模型。文本转成特征序列再依次执行。优点是符合工程师的思维习惯导出的 STEP 质量高缺点是执行链路长中间任何一步失败都会导致整体失败。第三条是网格生成路线直接生成三角网格输出 STL 或 GLB。这条路线的优点是快、对复杂形状容忍度高缺点是精度低、不保留工程语义不适合后续精确编辑。选择哪条路线取决于你的最终目标。要拿去 3D 打印网格路线够用要拿去工厂加工必须走精确实体路线要放进网页展示GLB 加网格路线最省事。2.3 输出格式的选择逻辑输出格式不是随便选的它直接决定了你前面该走哪条路。我整理了一张对照表方便快速判断。输出格式本质适用场景是否保留精确尺寸后续可编辑性STEP实体边界表示工程交换、CNC 加工是高可在专业 CAD 中继续编辑GLB网格加材质网页展示、三维场景否低主要是渲染用途STL三角面片网格3D 打印、快速原型否低只能做网格修复这张表的核心结论是只要涉及精确制造就必须走 STEP 路线也就意味着必须用实体建模内核而不是网格生成。很多人一开始图省事用网格路线结果发现尺寸对不上、孔位偏移返工成本很高。3. 核心细节解析文本解析、几何构建与格式导出3.1 文本解析把“人话”拆成机器能懂的参数文本解析是整个链路的第一道关也是最容易出问题的地方。自然语言里充满了省略和歧义比如“一个高一点的盒子”这个“高一点”到底是多高我的做法是尽量在输入阶段就约束表达方式用“尺寸加特征”的结构来描述比如“长方体长 80宽 60高 40顶面中心有一个直径 15 的通孔”。解析时程序需要提取几类信息几何类型长方体、圆柱、球体等、尺寸参数长宽高、半径等、位置关系中心、偏移、对齐、特征操作打孔、倒角、抽壳。这四类信息缺一不可。我见过很多失败案例都是因为位置关系没描述清楚导致特征跑到了错误的位置。提示在文本里显式写出单位比如“50 毫米”能避免大量因单位不一致导致的尺寸错误。程序默认单位和你预期单位不一致是新手最常踩的坑之一。3.2 几何构建布尔运算的顺序决定成败拿到参数之后就进入几何构建阶段。这一步的核心是布尔运算先建基础实体再用加、减、交的方式组合出最终形状。顺序非常关键。比如你要在一个盒子上打孔必须先有盒子再做减法。如果顺序反了程序会报错或者得到空结果。我一般遵循“先主体、后特征、再修饰”的顺序先构建最大的基础形体再依次添加或减去次要特征最后处理倒角、圆角这类修饰性操作。倒角放在最后是因为它依赖已有的边如果提前做后续的布尔运算可能会破坏这些边导致倒角失败。另一个细节是容差设置。实体建模内核在做布尔运算时需要判断两个面是否重合、两条边是否相交。容差设得太小运算容易失败设得太大又会出现几何错误。我的经验是对于毫米级零件容差设在 0.001 到 0.01 毫米之间比较稳妥具体要看模型尺度。3.3 格式导出STEP、GLB、STL 的导出要点导出这一步看似简单其实有不少讲究。导出 STEP 时要注意单位一致性和实体完整性。有些内核导出的 STEP 会把实体拆成多个面片导致后续软件识别为曲面而非实体。检查方法是重新导入后看能否做布尔运算如果不行说明实体已经碎了。导出 GLB 时重点是网格密度和材质。网格太粗模型看起来有棱角网格太细文件体积暴涨。我通常根据展示距离来定近距离展示用较细网格远景展示用粗网格即可。材质方面GLB 支持 PBR 材质可以带上颜色和粗糙度让展示效果更真实。导出 STL 时核心参数是弦高和角度容差。弦高决定曲面被离散成三角面片的精细程度值越小越精细文件越大。对于 3D 打印弦高设在 0.05 到 0.1 毫米通常够用。角度容差控制相邻面片之间的夹角一般设在 15 到 30 度之间。# 以 CadQuery 为例导出 STL 的关键参数 exporters.export( result, part.stl, tolerance0.05, # 弦高控制曲面精度 angularTolerance0.2 # 角度容差单位弧度 )4. 实操过程从零搭建一条可复现的 text-to-cad 链路4.1 环境准备与工具选型我用的组合是 Python 加 CadQuery再加一个语言模型做文本到代码的转换。CadQuery 基于 OpenCASCADE 内核导出的 STEP 质量稳定社区也活跃。安装方式很直接pip install cadquery如果你更习惯 OpenSCAD 的语法也可以用它但 OpenSCAD 导出的 STEP 需要额外转换链路更长。FreeCAD 的 Python 接口也是一个选择功能全但配置稍重。语言模型这块我用的是本地部署的小模型做文本解析把自然语言转成结构化的参数字典。如果你不想折腾模型也可以自己写一套正则规则来解析固定格式的文本稳定性反而更高。4.2 一个完整案例从文本到 STEP 文件假设输入文本是“一个长方体底座长 100 毫米宽 80 毫米高 20 毫米四角各有一个直径 8 毫米的安装孔孔深贯穿。”第一步解析出参数类型是长方体尺寸 100x80x20特征是在四个角打四个直径 8 的通孔。四角的位置需要计算通常取距离边缘一定距离比如各留 10 毫米边距那么孔心坐标就是 (10,10)、(90,10)、(10,70)、(90,70)。第二步用 CadQuery 构建import cadquery as cq # 基础长方体 base cq.Workplane(XY).box(100, 80, 20) # 四个角的孔位 hole_positions [(10, 10), (90, 10), (10, 70), (90, 70)] # 打贯穿孔 result ( base.faces(Z).workplane() .pushPoints(hole_positions) .hole(8) # 直径 8 的通孔 ) # 导出 STEP cq.exporters.export(result, base_plate.step)这段代码跑完你会得到一个标准的 STEP 文件可以直接拖进任何主流 CAD 软件里继续编辑。实测下来尺寸精度完全对得上孔位误差在容差范围内。4.3 参数计算孔位边距怎么定才合理上面例子里的 10 毫米边距不是随便定的。边距太小孔壁离边缘太近零件强度不够容易开裂边距太大安装空间又不够。一般经验是边距至少等于孔径的 1.5 倍。直径 8 毫米的孔边距至少 12 毫米才比较稳妥。我上面用 10 毫米是为了演示实际做承力件时我会加到 15 毫米。这个计算逻辑同样适用于其他特征。比如倒角半径通常取壁厚的三分之一到二分之一抽壳厚度取整体尺寸的百分之五左右。这些比例不是死规定但作为起点能帮你快速定出合理参数避免反复试错。4.4 批量生成一次文本输入多个模型输出text-to-cad 真正体现效率的地方是批量生成。比如你有一组尺寸不同的支架只需要把参数做成表格循环调用建模函数即可。import csv import cadquery as cq with open(brackets.csv) as f: reader csv.DictReader(f) for row in reader: length float(row[length]) width float(row[width]) height float(row[height]) hole_d float(row[hole_d]) part cq.Workplane(XY).box(length, width, height) part part.faces(Z).workplane().hole(hole_d) cq.exporters.export(part, fbracket_{row[id]}.step)这套流程跑下来几十个零件几分钟就能全部生成比手动建模快了一个数量级。而且参数存在表格里改一个数字就能重新生成版本管理也清晰。5. 常见问题与排查技巧实录5.1 布尔运算失败最常见的三类原因布尔运算失败是 text-to-cad 里出现频率最高的问题。我总结下来主要是三类原因。第一类是面重合。两个实体有完全重合的面内核无法判断该保留哪个直接报错。解决办法是让两个实体稍微错开一点或者先做微小偏移再运算。第二类是容差过小。前面提过容差太小会导致相交判断失败。适当放大容差通常能解决。第三类是非流形几何。比如一个边被三个面共享这种几何在数学上不合法内核处理不了。解决办法是回到建模步骤检查是否有重复的面或边清理掉再运算。5.2 导出文件打不开或显示异常STEP 文件导出后打不开常见原因是单位不一致。有些内核默认用米有些用毫米导出时不转换就会导致模型尺寸差一千倍。检查方法是在导出前显式设置单位。GLB 显示异常多半是法线方向反了。网格的法线朝内渲染时就会看到黑面或者穿模。修复方法是重新计算法线或者在导出时勾选“统一法线方向”。STL 打印出来尺寸不对通常是缩放问题。STL 本身不带单位信息切片软件默认按毫米处理。如果你的模型是按厘米建的导出后就会小十倍。导出前确认单位导入切片软件后再核对一次尺寸。5.3 问题速查表现象可能原因排查方向解决手段布尔运算报错面重合、容差过小、非流形检查相交区域错开实体、放大容差、清理几何STEP 打不开单位不一致、实体破碎检查导出设置显式设单位、重新导出实体GLB 显示黑面法线反向查看法线方向统一法线、重新计算STL 尺寸偏差缩放错误核对单位导出前确认单位、切片软件核对孔位偏移坐标计算错误复核孔心坐标重新计算边距和坐标5.4 我踩过的几个坑第一个坑是过度依赖模型解析文本。早期我让语言模型直接输出建模代码结果模型经常写出语法正确但逻辑错误的代码比如把孔打在了错误的位置。后来改成让模型只输出参数代码由固定模板生成稳定性大幅提升。第二个坑是忽略中间验证。一开始我追求一步到位文本进去、文件出来中间不检查。结果一旦出错根本不知道是哪一步的问题。后来我在每个环节都加了验证比如解析完参数先打印出来核对建模完先看包围盒尺寸对不对导出后再重新导入检查。多花这几分钟省下的返工时间远超想象。第三个坑是容差设置一刀切。不同尺度的模型需要不同的容差。小零件用大容差会丢细节大零件用小容差会运算失败。现在我会根据模型的最大尺寸动态设置容差一般是最大尺寸的万分之一到十万分之一之间。6. 进阶方向让 text-to-cad 更贴近真实工程需求6.1 引入约束与参数联动基础版的 text-to-cad 只能生成固定尺寸的模型但真实工程里尺寸之间往往有关联。比如孔位随板长变化壁厚随承重变化。要实现这种联动需要在参数层引入表达式而不是固定数值。CadQuery 支持在建模时使用变量和表达式你可以把“孔位边距等于孔径的 1.5 倍”这种规则写进代码这样改孔径时边距自动跟着变。这一步做完模型就从“死”的变成了“活”的复用价值高很多。6.2 结合版本管理做参数追溯参数化建模的一个隐藏好处是模型可以用代码管理。把建模脚本放进 Git每次改参数都留一条记录出了问题可以随时回滚。这比在 CAD 软件里手动改尺寸、另存为多个版本要清晰得多。我现在的习惯是每个零件一个脚本文件参数放在文件顶部的配置区改参数只动配置区建模逻辑不动。6.3 从单件到装配单个零件跑通之后下一步是装配。text-to-cad 同样可以用于装配体生成思路是先分别生成各个零件再按位置关系组合。位置关系可以用文本描述比如“零件 A 的底面与零件 B 的顶面贴合中心对齐”。解析出这些约束后程序自动计算变换矩阵把零件摆到正确位置。装配的难点在于干涉检查。两个零件如果重叠导出的装配体在后续使用中会出问题。我的做法是在装配完成后用包围盒做一次快速干涉检测发现重叠就报警人工确认后再调整。6.4 精度与性能的平衡当模型复杂度上升生成时间会明显变长。我做过一个测试一个包含两百个特征的零件生成 STEP 花了将近一分钟。如果批量生成上百个这样的零件时间就不可接受了。优化的方向有几个一是减少不必要的布尔运算能合并的特征尽量合并二是降低中间过程的精度只在最终导出时提高精度三是并行生成多个零件同时跑。这几点结合起来能把批量生成的时间压到可接受的范围内。7. 一些实操心得与建议如果你打算认真用 text-to-cad 做点东西我的建议是从小处着手。先拿一个你熟悉的简单零件用文本描述出来跑通整条链路确认每一步都符合预期。然后再逐步增加复杂度加入孔、槽、倒角这些特征。不要一上来就挑战复杂曲面那会让你在调试上耗掉大量时间。另外文本描述的规范要尽早定下来。我用的格式是“几何类型 尺寸 特征 位置”这个顺序固定下来之后解析逻辑写起来简单出错也容易定位。你可以根据自己的需求调整但一定要固定不要每次换一种说法。最后别忘了验证环节。每生成一个模型至少检查三项包围盒尺寸对不对、特征数量对不对、导出文件能不能重新导入。这三项检查花不了多少时间但能拦住绝大多数低级错误。我在实际项目里就是靠这套检查流程把返工率压到了很低的水平。