今年我在一台旧工作站上花了不少时间做text-to-cad相关的实验。起因很实在:团队里有个机加工师傅老要改同一类支架,每次改孔距、改板厚都得在CAD里从头折腾一遍。我寻思,能不能直接跟电脑说一句“把底板加宽10mm,孔距改成55mm”,模型自己就跟着变了?试了一圈下来,结论有点出乎意料:text-to-cad真正能打的地方,不是很多人吹的“一句话凭空生成复杂零件”,而是把空间描述转换成参数化建模指令的能力,这刚好踩中了制造业里高频、琐碎、需要快速迭代的那一类需求。
这项技术适合谁?我认为至少有三类人值得关注。第一类是结构工程师,做方案对比时不用反复画草图;第二类是机械制造里的非标设计人员,大量工作其实是“改尺寸”;第三类是那些想快速验证想法的硬件创客,脑子里有大概形状、但CAD操作不熟练。这篇文章不打算讲太多论文公式,我会按自己实际搭建和调试的过程,把路线选型、环境配置、提示词写法、常见翻车案例一次说清楚。
1. text-to-cad是什么:把一句话变成可制造模型
1.1 一句话到三维模型,这里发生了什么
很多人第一次接触text-to-cad,都会误以为它是“文字版本的3D生成器”,跟AI画图差不多。实际差别非常大。文字生成图片,像素可以稍微模糊,肉眼看着像就行;CAD模型不行,差0.1mm就可能装不上,拓扑结构一旦破洞,后端的CAM路径根本算不出来。
拆开来看,一条text-to-cad指令要经过三层转换。第一层是自然语言解析,把“带四个安装孔的法兰底座”拆成实体主体、孔特征、位置关系;第二层是几何语义对齐,要把文字中的相对描述“角落上”“中心处”映射成坐标系里的绝对坐标;第三层才是真正的建模执行,调用几何内核生成B-rep实体。前两层是语言模型擅长的,最后一层则完全依赖你选用的CAD脚本引擎。
关键问题在于大多数开箱即用的demo只做到了第一层和第二层的“看起来像”,到了第三层就露馅。比如你让它“在板的四角各打一个孔”,它可能在一条边的中心打了孔,因为语言模型对“角”的几何理解并不稳定。我自己刚入门时遇到的第一个翻车案例,就是生成一个方形底座,模型把中心孔开到了边线上,壁厚只剩0.3mm,纯纯的废品。这也是为什么说text-to-cad不是“输入文字出模型”这么简单,它本质上是人、语言模型、几何内核三方协作的过程。
1.2 它真正解决的问题是什么
搞清楚它不只是“替代画图”之后,要更仔细看它切中的痛点:参数化改型。制造业里有大量设计工作,不是从零做创新,而是把上一代产品的某个板加大、孔距调整、厚度变化。这种活传统CAD软件做起来很啰嗦,你得先找到草图、改约束、重新拉伸,一步做错还得回退。而text-to-cad的脚本式实现,天然就把尺寸变成了变量,改尺寸就是改一行参数。
另外,text-to-cad对非设计岗的工程师特别友好。我一个做工艺的朋友,不懂三维建模,但很清楚地知道自己要的零件长什么样,用文字描述能力很强。他只要说“外径60mm,内径32mm,厚度4mm,内孔带一圈台阶”,脚本就能把模型生成出来,他再拿去车间确认。这类需求在过去得专门找设计员排期,现在自己花五分钟就能出初步模型。
还有一个价值容易被忽视:可追溯性。CAD文件格式五花八门,但一段Python脚本或OpenSCAD源码是纯文本,放进Git里就能做版本管理。谁改过什么参数、什么时候改的,清清楚楚。这对需要走变更流程的团队非常关键。
1.3 我最初的三个误判
刚开始我觉得这东西无非是“prompt写得好就行”,后来发现大错特错。这里先说三个误判,后面展开解释。第一个误判是以为模型越复杂越能体现AI能力,实际恰好相反,越复杂的零件越需要拆成多个子任务独立生成再组合;第二个误判是以为提示词只需要描述形状,不用管单位、基准面和坐标系,结果输出常常对不上;第三个误判是以为生成出来就算完事,忽略了最关键的验证环节,导致好几个零件从模型层面看不出问题,实际加工时全废。这三个误判基本就是新手必经的坑,本文后面都会给对策。
2. 两条技术路线:生成式模型还是脚本式管线
2.1 端到端生成网络是怎么玩的
现在市面上的text-to-cad方案大致分两类。一类是端到端的生成网络,代表作是一些开源研究项目,思路是把文字描述输入到一个编码器里,然后通过扩散模型或者自回归模型直接生成体素、点云或者三角网格。这类方案的优势是自动化程度高,不需要中间代码,输入自然语言之后直接拿到网格文件,演示效果非常震撼。
但实际用起来问题不少。首先是几何精度难以保证,生成出来的网格在视觉上像模像样,导成STL后量一量尺寸,误差可能达到几个毫米,对配合件来说这就是报废。其次是拓扑结构经常出问题,网格有开口、自交面、非流形边,后处理你得用Meshmixer或者Blender去修复,工作量不亚于重新建模。再一个,这类模型往往只能输出网格格式,很难转成机械行业通用的STEP实体格式,也就意味着下游CAM、有限元分析基本接不上。
这类方案的典型使用场景其实不是精密制造业,而是早期概念设计、快速展示、游戏资产生成。如果你是拿来做外观评审,完全没问题;但要是准备拿去加工,我建议谨慎再谨慎。
2.2 LLM与CAD脚本引擎组合:务实派路线
第二类方案是我个人更推荐的:让大语言模型生成CAD代码,再用几何内核执行。具体来说,语言模型负责写OpenSCAD脚本、CadQuery的Python代码、或者FreeCAD的Python宏,然后由CadQuery内置的OpenCASCADE内核或OpenSCAD的CSG引擎完成真正的实体建模。
这条路线的核心逻辑是“让模型做它擅长的,让引擎做引擎擅长的事”。语言模型擅长的是理解自然语言并将其翻译成有逻辑的代码,而精确的布尔运算、倒角、拉伸、旋转这些几何操作,交给成熟的CAD内核即可。模型不需要“凭空想象”出一个合法实体,它只需要生成对API的正确调用序列。
这条路线最大的红利是可参数化、可复用。语言模型生成的不再是一个一次性模型文件,而是一段带变量和函数的代码。下次要改尺寸、改孔距,直接改代码里的数字就行,不需要再让模型重新生成一遍。这对工程落地来说太重要了。
2.3 我用什么标准来选型
我自己做了一个简单的评估表,整理如下,给正在选型的朋友参考。
| 评估维度 | 端到端生成网络 | LLM与CAD脚本引擎 |
|---|---|---|
| 几何精度 | 中等,常有毫米级偏差 | 高,由几何内核严格计算 |
| 模型可编辑性 | 低,改形状相当于重新生成 | 高,改参数即可 |
| 拓扑合法性 | 需要额外修复 | 天然合法 |
| 下游格式兼容 | 多输出STL/OBJ,STEP困难 | 可直接输出STEP/STL/SVG |
| 参数化复用 | 不擅长 | 天生适合 |
| 上手成本 | 接口简单但调参难 | 需要会读代码、调试API |
我目前的实际工作流是混合策略:方案阶段偶尔用端到端生成做灵感参考,正式出图坚决走“LLM生成CadQuery代码”的路线。这个选择不是因为它听起来更酷,而是踩过坑以后权衡下来的结果。如果你是学生做研究,关注端到端没问题;如果你要交付实际零件,脚本式管线是少走弯路的答案。
3. 实操:搭建一套text-to-cad工作流
3.1 环境准备与依赖安装
先交代我的实验环境:一台Ubuntu 22.04工作站,Python 3.10。之所以强调系统,是因为CadQuery在Windows下的安装体验相对痛苦,而Ubuntu上基本可以一条命令解决。如果你主力机是Windows,我建议优先用WSL2配Ubuntu,或者直接上一台Linux服务器,省去一堆动态库的坑。
核心依赖其实就两个,CadQuery本体和它的CLI工具。打开终端,依次执行:
python -m venv venv source venv/bin/activate pip install --upgrade pip pip install cadquery装完后验证一下:
python -c "import cadquery; print(cadquery.__version__)"能打印出版本号就说明环境OK。CadQuery自带一个名为cq-cli的命令行入口,它可以把一个Python脚本直接转换成STEP、STL、SVG等格式,非常适合嵌入自动化流程。如果你更习惯OpenSCAD,那就更简单了,一个二进制安装包搞定,不需要管Python环境。
这里有个细节要提醒:CadQuery的版本迭代不算快,有些API在新旧版本之间有差异。比如老版本的Workplane.hole()在钻孔深度参数上和新版行为不同,你让大模型生成的代码如果用了过时API,执行时可能会报TypeError。解决办法是给大模型提示词里带上你本地的CadQuery版本号,并且准备一份当前版本API摘要在上下文里,错误率会明显下降。
3.2 最小示例:用自然语言生成一个法兰底座
环境准备好之后,先跑一个最小可用的实验。我给大模型写了这样一句描述:
“生成一个CadQuery代码,创建法兰底座:底座是100mm乘80mm的长方体,高度10mm,顶面四周圆角R5;顶面中心有一个直径30mm的贯穿通孔;顶面中心沿长宽方向各偏移30mm和20mm的位置上,布置4个M6沉头安装孔,沉头孔径11mm,深度6mm,通孔直径6.6mm。所有单位使用毫米。输出文件名为base_plate.step。”
第一版模型返回的CadQuery代码大致长这样,我稍微整理缩进:
import cadquery as cq base = ( cq.Workplane("XY") .box(100, 80, 10) .edges("|Z") .fillet(5) ) base = base.faces(">Z").workplane().hole(30) mount = ( base.faces(">Z").workplane() .rect(60, 40, forConstruction=True) .vertices() .cboreHole(6.6, 11, 6) ) cq.exporters.export(mount, "base_plate.step")然后执行:
cq-cli -i gen_base_plate.py -o base_plate.step几秒钟后目录里就生成了STEP文件。导入到FreeCAD里查看,尺寸完全符合预期。这个过程第一次跑通时,我还是挺兴奋的,因为它意味着“设计改型”这个动作,真的可以压缩到“改一句自然语言”的级别。
但这只是最理想的情况。第二版我故意改了描述,说“四个孔分布在四个角上,不要太靠近边缘”,模型输出的代码把孔放到了角点坐标,结果有一侧孔边距只剩2mm,明显不合理。原因在于“不要靠近边缘”是模糊表达,语言模型只能猜。于是我把提示词改成“四角孔中心距相邻边均为15mm”,它立刻给出了精确坐标。这件事给我的教训很直观:text-to-cad的提示词里,模糊词汇是精度杀手。
3.3 参数化模板:让改型不再重画
跑通最小示例后,我马上想到下一步:只生成一次模型意义有限,最好让它生成一个参数化模板,以后每次改尺寸只需要调参数。
于是我换了种提示词写法:
“创建一个参数化函数flange_base(length, width, height, hole_d, mount_offset, cbore_d, cbore_depth),返回一个CadQuery Workplane对象。函数内部实现:底部长方体,顶面中心通孔,顶面四角沉头孔。坐标原点在长方体底面中心。”
模型给出的代码骨架如下:
import cadquery as cq def flange_base(length, width, height, hole_d, mount_offset, cbore_d, cbore_depth): base = cq.Workplane("XY").box(length, width, height) base = base.edges("|Z").fillet(5) base = base.faces(">Z").workplane().hole(hole_d) if mount_offset: points = [ (mount_offset, mount_offset), (mount_offset, -mount_offset), (-mount_offset, mount_offset), (-mount_offset, -mount_offset), ] base = ( base.faces(">Z").workplane() .pushPoints(points) .cboreHole(6.6, cbore_d, cbore_depth) ) return base model = flange_base(100, 80, 10, 30, 30, 11, 6) cq.exporters.export(model, "base_plate.step")这个模板化思路带来的收益远超预期。后来我又用它生成了十几种不同尺寸的支架,每改一次尺寸,只需要改一行函数参数,半分钟出图。对比之前手动用CAD软件去改基准面、重建约束、逐步拉伸的那套流程,效率提升是数量级的。
3.4 换个引擎:OpenSCAD写法也有独特优势
CadQuery虽然好用,但有时我也会切到OpenSCAD。两者差异很大,CadQuery更接近传统特征建模,适合结构件;OpenSCAD则是纯CSG布尔操作,逻辑更直观,适合用for循环批量生成阵列。
同一个法兰底座用OpenSCAD写出来是这样:
module flange_base(length, width, height, hole_d, mount_offset, shift=0) { difference() { // 底板主体 hull() { translate([shift, shift, 0]) cube([length - 2*shift, width - 2*shift, height]); } // 中心孔 translate([length/2, width/2, -1]) cylinder(d=hole_d, h=height+2, $fn=64); // 四角沉头孔 for (i = [-1, 1], j = [-1, 1]) { translate([length/2 + i*mount_offset, width/2 + j*mount_offset, -1]) { cylinder(d=6.6, h=height+2, $fn=64); translate([0, 0, height-6]) cylinder(d=11, h=7, $fn=64); } } } } flange_base(100, 80, 10, 30, 30);OpenSCAD的好处是语法足够简单,几乎所有大模型都能高质量生成,而且它的$fn参数直接控制曲面细分数,对3D打印场景特别友好。缺点是它做不了复杂的倒角、拔模斜度和真正意义上的变半径圆角,曲面造型能力明显弱于CadQuery背后的OpenCASCADE。
如果你做的零件以钣金支架、壳体、简单机械件为主,OpenSCAD就够了;一旦涉及配合曲面、复杂倒角、阵列孔、螺纹孔,老老实实用CadQuery。两条腿走路的方案可以适应更多场景。
4. 质量评估与调试:模型输出真的能用吗
4.1 怎么判断一个生成模型是否合格
很多新手上路后第一个疑问:模型生成出来了,怎么判断它“合格”?这问题比想象中重要。text-to-cad输出一个视觉上很像样的模型,和能真正用于生产,中间隔着一道巨大鸿沟。我的评估流程分四步。
第一步,看尺寸。在CAD软件里直接测量关键尺寸,对比需求。这一步看似简单,却是最高频的翻车点,因为有些模型看着比例对,实际尺寸差了一倍。最经典的坑是英寸与毫米混用,提示词没写单位,模型默认用了英寸,结果出来一个大了25.4倍的“巨物”。
第二步,检查拓扑有效性。CadQuery生成的实体一般合法,但如果你用的是端到端生成网格,这一步必须做。看网格是否封闭、有没有自交、有没有非流形边。简单的检查可以借助在线工具,复杂的建议用Blender的3D打印工具箱。
第三步,测试可编辑性。把生成的STEP文件导入到常用的CAD软件里,尝试改一个尺寸、加一个特征。如果导入后是“死模型”,无法直接编辑,那它对你的日常设计流程帮助有限。这一点脚本式管线天然占优,因为变量的源头在代码里。
第四步,输出到下游工具复核。把模型切出G代码或者做一次有限元分析,模型层面看不出问题,在下游工具里经常原形毕露。比如壁厚不够导致仿真时应力集中,或者刀具路径计算出干涉。这一步最花时间,但也是最有价值的保险。
4.2 提示词工程的关键写法
我踩过很多次坑后,总结了一套针对CAD生成的高质量提示词模板。核心五要素:单位、基准面、绝对尺寸、相对位置、特殊特征。缺一个,输出质量就降一档。
单位不用多说,“一律用毫米”这句话请写进每条提示词。基准面很关键,许多模型默认把坐标原点放在角点还是中心,差别巨大,你不说模型就自由发挥。绝对尺寸要精确,“中等大小”“比较厚”这种词直接扔掉。相对位置要用“中心距边缘15mm”“距顶面5mm”这类描述。特殊特征要明确深度、直径、角度,比如“沉头深度6mm而不是贯穿”。
下面放一组对比示例。
| 差的描述 | 好的描述 |
|---|---|
| 一个L形支架,上面有几个孔 | L形支架,两臂长80mm和60mm,宽40mm,厚5mm,每臂均布2个直径8mm通孔,两孔中心距30mm |
| 圆角稍微大一点 | 底面为基准,四角圆角半径8mm |
| 中心有孔,旁边加凸台 | 坐标原点在底面中心,圆柱凸台外径20mm高15mm,凸台中心距原点25mm |
| 一个盒子,薄壁 | 内腔尺寸100x60x40mm,壁厚3mm,无盖 |
这个表我贴在工位旁边,每次写提示词前扫一眼,输出靠谱率提升非常明显。总结成一句话:你在提示词里提供的信息越接近图纸标注方式,输出就越接近你要的东西。
4.3 实际调试案例:孔位偏置问题
空讲道理不如看一个真实调试案例。我做一个安装支架时,提示词让模型生成“底部有四个对称安装孔”。模型输出的模型视觉上看着很对称,但用测量工具一查,左边两个孔是准确的,右边两个孔整体偏移了0.2mm。
排查过程是这样的。我首先怀疑是布尔运算精度问题,但CadQuery基于OpenCASCADE,默认公差足够应对这种尺度,不太可能出现0.2mm的局部偏移。随后我怀疑是坐标参考发生了旋转,检查代码发现模型的边在倒角时创建了一个新的Workplane,但LLM在后续打孔时仍引用了旧平面,导致某些点落在了略微偏移的坐标系上。简单说,就是它生成多步骤代码时,坐标系变换没有“接住”。
解决办法不是手工改代码,而是改提示词,在描述里明确加上“所有安装孔基于底面中心为原点的同一个坐标系生成,不要在倒角后的平面上计算位置”。模型重新生成的代码,这次所有孔位都对齐了。这个案例让我深刻理解了一个原则:text-to-cad的调试,核心不是改代码,而是改输入描述。你描述得越有“坐标感”,模型输出的程序就越稳。反过来,如果描述里都是“上面”“旁边”“附近”这类词,模型只能靠猜,出错是必然的。
5. 常见问题与避坑指南
5.1 我遇到的典型故障速查
| 现象 | 可能原因 | 处理方法 |
|---|---|---|
| 生成的代码执行报错:module object has no attribute | 大模型用了旧版API或者拼错方法名 | 在提示词里附带当前CadQuery的API摘要,让模型按摘要写代码 |
| 布尔差集时报错,没有几何实体生成 | 两个体之间没有实际重叠,或完全共面未做偏移 | 检查坐标计算;共面时让其中一个体在目标方向偏移0.001mm |
| 模型尺寸整体偏大或偏小 | 单位混用,英寸误认为毫米 | 在提示词和系统配置里强调“全部使用毫米” |
| 模型生成的STEP导入CAD后是个空壳 | 只生成了面片没有实体,常见于端到端方案 | 换成脚本式管线,或对网格做实体化转换 |
| 同一个描述,多次生成结果差异巨大 | 随机采样参数过高,或者描述信息量太少 | 降低温度参数、固定随机种子,并丰富描述细节 |
| 孔位或特征有细微偏移 | 多步骤坐标参考没有对齐 | 强化“基于同一坐标系”的描述,并在代码里锁定参考面 |
这张表是我三个月实操的浓缩,几乎每一个我都遇到过。最让我意外的是第三行,单位混用问题出现的频率远超想象,就算在明确写了“毫米”的情况下,偶尔也会蹦出一个英寸相关的默认值。保险做法是生成后立即量一遍关键尺寸,别偷懒。
5.2 关于落地的一些非技术心得
技术之外还有几件事,我对每个打算把text-to-cad引入团队的人都要讲一遍。
先想清楚切入场景,不要一上来就想替代现有完整CAD流程。我见过不少团队买了个工具就开始让所有设计都走生成路线,结果复杂的装配体一塌糊涂,反向把工具否定了。正确姿势是选一个你手里最高频、最标准化的小零件类别,比如支架、垫片、法兰,先跑通一套从描述到加工的闭环,有成功案例再慢慢扩。
不要完全自动化,留一道人工审查关口。模型生成的模型,从几何上看可能完全正确,但它不理解加工工艺。比如薄壁结构容易变形、尖角处应力集中、螺栓孔离边缘太近导致破裂,这些都需要有经验的工程师把关。把text-to-cad当成一个“会写代码的实习生”是最好用的心智模型,它速度快,但你不能不review。
建立你自己的提示词示例库。每次跑通一个成功的零件,把它的提示词和输出代码保存下来,分类整理。积累几十个之后,你会发现大部分需求都能从库里找到接近的模板,只需要改几个参数。这个库就是团队资产,比任何工具选型都值钱。
5.3 关于大模型本身的一点看法
最后一件事,我要替大模型说句公道话。很多人把text-to-cad的效果不佳归咎于“模型太蠢”,但根据我的实测,现阶段的主流大模型对OPENSCAD和CadQuery语法的掌握,已经超越了相当一部分刚入行的设计师。真正的问题在于使用者没有给它足够清晰的约束条件。
我建议你做一个动作:每次写提示词前,先问自己“如果这句话给一个人类CAD工程师,他会不会反问我要更多信息”。如果他需要问,那说明你的描述不合格。把这种反问式的缺口在提示词里补上,模型的输出质量会立刻上一个台阶。这一点几乎不花时间,回报却非常可观。
我个人在这段时间里的体会是:text-to-cad还不会取代手工建模,但它正在悄悄改变我们对待设计迭代的方式。以前我改一版孔距,要做的事情是把整个图纸流程再走一遍;现在我只需要在一段代码里改一个数字,重新导一次模型。省下来的时间,我全部放在了工艺审查和多方案对比上。对一个做机械设计的人来说,这种工作重心的转移,比工具本身带来的效率提升更有长期价值。