CAD 这行当有个特别拧巴的地方:设计师脑子里的三维结构,要变成机器能读的几何文件,中间隔着一整套繁琐的手工建模流程。画个法兰、支架、齿轮箱,熟练工也得在草图、约束、拉伸、倒角之间来回折腾几十分钟。而大语言模型现在能写代码、能画流程图、能生成 SQL,唯独碰到"给我生成一个 STEP 文件"这种需求就抓瞎——它输出的永远是文字,不是几何。
text-to-cad要解决的就是这个断层。它的核心思路很直接:把自然语言描述翻译成 CAD 脚本代码,再由脚本驱动几何内核生成真正的三维模型文件,最终导出 STEP、URDF、G-code 这些下游能直接消费的格式。适合谁看?如果你是从业多年的机械设计师,想搞清楚 AI 到底能不能替你干重复建模的活;如果你是搞机器人仿真的工程师,天天被 URDF 手写折磨;或者你是做增材制造的,想让 G-code 生成流程自动化——这篇内容都值得你花时间读完。下面我按实际落地的顺序,把这条链路从头到尾拆一遍。
1. 从一句话到三维实体:text-to-cad 到底在翻译什么
1.1 自然语言和几何内核之间隔着的三层鸿沟
很多人第一次听到"文字生成 CAD",脑子里想的是"我说个杯子,它就给我个杯子"。实际远没这么简单。自然语言描述的是意图,而 CAD 文件描述的是精确几何,中间至少隔着三层翻译。
第一层是语义到参数的映射。"一个直径 50mm、厚 10mm 的法兰盘,中心开 20mm 通孔,边缘均布 6 个 8mm 螺栓孔"——这句话里,直径、厚度、孔径、孔数、分布方式都是明确参数,但"均布"这个词机器需要理解成"沿圆周等角度分布","边缘"需要理解成"距离外圆某个合理距离"。这些隐含知识,模型必须从训练数据里学到。
第二层是参数到建模操作的映射。有了参数,还得决定用什么建模原语:法兰盘主体是拉伸一个圆环,还是旋转一个截面?螺栓孔是用布尔减运算挖出来,还是用阵列特征生成?不同的操作路径,生成的几何拓扑结构不一样,下游能不能顺利做有限元分析、能不能被 URDF 正确引用,差别很大。
第三层是建模操作到脚本代码的映射。这一步才是 text-to-cad 真正落地的关键。它不直接操作几何内核,而是生成一段可执行的脚本——通常是 CadQuery 或 OpenSCAD 这类基于代码的 CAD 库的 Python 脚本。脚本执行后,几何内核(OpenCASCADE 或 CGAL)才真正计算出 B-rep 实体,最后导出成 STEP 或 STL。
提示:理解这三层鸿沟很重要,因为它决定了你评估一个 text-to-cad 方案时该看什么——不是看它生成的模型"像不像",而是看它生成的脚本能不能改、参数能不能调、导出的 STEP 拓扑是不是干净的。
1.2 为什么选脚本代码作为中间表示,而不是直接生成几何
这里有个设计决策值得展开说。理论上,大模型可以直接输出顶点坐标和面片索引,拼出一个网格模型。但实际工程里没人这么干,原因有三个。
可编辑性。脚本是参数化的,你把diameter = 50改成diameter = 60,重新执行就得到新模型,所有特征自动更新。而一堆顶点坐标改起来就是灾难,牵一发动全身。
可验证性。脚本是文本,可以静态检查语法、可以单元测试、可以做版本控制。你甚至可以让模型自己检查生成的脚本有没有引用未定义的变量。网格数据没法这么玩。
与现有工具链的兼容性。CadQuery 生成的实体是真正的 B-rep,能导出 STEP,能被 FreeCAD、SolidWorks 等主流软件打开继续编辑。而网格模型导出 STEP 后往往是一堆碎面,下游根本没法用。
所以 text-to-cad 的技术路线基本定型为:LLM 生成参数化脚本 → 脚本执行 → 几何内核计算 → 导出标准格式。这条链路里,LLM 只负责最前面那段"翻译",后面的活交给成熟的几何工具,各司其职。
1.3 一个最小可跑通的例子长什么样
光说原理太虚,直接看代码。假设你输入"生成一个 40mm 见方、高 20mm、中心有 10mm 通孔的方块",一个合格的 text-to-cad 系统应该输出类似这样的 CadQuery 脚本:
import cadquery as cq # 参数定义 length = 40.0 width = 40.0 height = 20.0 hole_dia = 10.0 # 建模 result = ( cq.Workplane("XY") .box(length, width, height) .faces(">Z") .workplane() .hole(hole_dia) ) # 导出 cq.exporters.export(result, "block_with_hole.step")这段脚本里,参数和建模逻辑是分离的,改尺寸只动上面四行。faces(">Z")选中顶面,.workplane()在顶面建立工作平面,.hole()挖通孔——这套链式 API 是 CadQuery 的典型写法。模型要理解"中心有通孔"对应的是"在顶面工作平面上打一个贯穿的孔",而不是在侧面或者底面。
跑通这个例子,你就理解了整条链路。剩下的复杂度,都在于怎么让模型稳定地生成正确的脚本,以及怎么处理更复杂的几何关系。
2. 拆解 text-to-cad 的技术栈:LLM、几何内核与格式转换
2.1 大模型在这里扮演的角色和它的能力边界
LLM 在 text-to-cad 里干的是"翻译官"的活,但它不是万能的。实测下来,它的能力边界大致是这样的。
擅长的:识别常见机械零件的描述模式(法兰、支架、轴、齿轮毛坯),把尺寸参数正确映射到变量,选择合适的建模原语(拉伸、旋转、扫掠),生成语法正确的 CadQuery 或 OpenSCAD 代码。对于训练数据里出现过的零件类型,一次生成成功率相当高。
不擅长的:处理复杂的空间约束关系("这个孔必须和那个槽对齐"),理解行业特定的公差标注,生成需要多步布尔运算的复杂装配体。还有一类高频错误是单位混淆——模型有时候会把毫米当成米,或者把直径当成半径。
完全靠不住的:涉及具体工程标准的细节,比如螺纹规格、键槽尺寸、倒角标准。这些必须靠外部知识库或者人工校验补上。
所以实际部署时,通常会在 LLM 后面加一层校验和修正:检查生成的脚本能不能跑通、参数范围是否合理、导出的实体是不是有效的闭合体。跑不通就让模型重试,或者回退到模板。
2.2 CadQuery 与 OpenSCAD:两条主流脚本路线的取舍
目前 text-to-cad 领域,脚本层基本是 CadQuery 和 OpenSCAD 二选一。两者差别很大,选错了后面全是坑。
| 对比维度 | CadQuery | OpenSCAD |
|---|---|---|
| 底层内核 | OpenCASCADE(B-rep) | CGAL(CSG) |
| 导出 STEP | 原生支持,拓扑干净 | 不支持,只能导 STL |
| 参数化能力 | 强,支持选择器链式操作 | 中,靠变量和模块 |
| 学习曲线 | 较陡,API 丰富 | 平缓,语法简单 |
| 适合场景 | 机械零件、需要下游编辑 | 快速原型、3D 打印 |
| LLM 生成难度 | 较高,API 组合多 | 较低,语法规整 |
如果你的下游是机器人仿真(需要 URDF)、是数控加工(需要 STEP)、是要在 SolidWorks 里继续改,那必须选 CadQuery,因为只有它能导出拓扑干净的 STEP。如果只是 3D 打印个摆件,OpenSCAD 足够,而且 LLM 生成 OpenSCAD 的准确率明显更高,因为它的语法更接近传统编程语言。
我个人的经验是:做工程用途选 CadQuery,做创意用途选 OpenSCAD。别想着一个方案通吃,两者的几何表示根本不同,混用会出大问题。
2.3 STEP、URDF、G-code:三种输出格式各自服务谁
text-to-cad 生成模型只是第一步,真正体现价值的是它能导出什么格式。这三种格式对应三条完全不同的下游链路。
STEP是 CAD 领域的通用交换格式,存的是精确 B-rep 几何。它的价值在于跨软件兼容——CadQuery 生成的 STEP 能被 SolidWorks、UG、Creo、FreeCAD 打开,继续做装配、出工程图、做有限元前处理。如果你要把 AI 生成的模型接入现有设计流程,STEP 是唯一选择。
URDF是机器人描述格式,存的是连杆的几何、质量、惯性、关节关系。它本身不存几何,而是引用 STL 或 STEP 文件。text-to-cad 在这里的价值是批量生成机器人连杆——你描述一个六轴机械臂的各段尺寸,它生成对应的几何文件加 URDF 描述,直接导入 CoppeliaSim 或 Gazebo 就能仿真。手写 URDF 是出了名的痛苦,这一步自动化省的时间最多。
G-code是数控加工和 3D 打印的指令格式,存的是刀具路径。从几何到 G-code 需要切片或 CAM 处理,text-to-cad 通常不直接生成 G-code,而是生成几何后调用切片软件(如 Cura 的引擎)或 CAM 库(如 FreeCAD 的 Path 模块)来生成。它的价值在于打通从描述到加工的最后一公里。
注意:URDF 导入 CoppeliaSim 时,几何文件的路径和单位经常出问题。建议生成 URDF 时统一用米做单位,几何文件用 STL 而非 STEP,因为 CoppeliaSim 对 STL 的支持更稳定。
3. 动手搭一条最小链路:从描述到 STEP 文件
3.1 环境准备里最容易翻车的依赖问题
要跑通 text-to-cad,环境配置是第一个坎。CadQuery 依赖 OpenCASCADE,这个库在 Windows 上的安装历史包袱很重,很多人卡在 C++ 运行库报错上。
推荐用 conda 而不是 pip 装 CadQuery,因为 conda 会把 OpenCASCADE 的二进制依赖一起处理好:
conda create -n text2cad python=3.10 conda activate text2cad conda install -c conda-forge cadquery如果你非要用 pip,那得先确保系统装了对应版本的 Visual C++ 运行库。网上那些"安装 CAD 出现 C++2005 错误"的帖子,本质都是运行库版本不匹配,跟 CAD 软件本身没关系。装 CadQuery 遇到类似报错,思路一样:先补运行库,再装库。
LLM 那端,如果你用本地模型,需要装 transformers 和对应的推理框架;如果用 API,装个 requests 或 openai 的 SDK 就行。本地跑的话,7B 级别的代码模型(如 CodeLlama、DeepSeek-Coder)在 CadQuery 生成上勉强能用,但复杂零件还是得靠更大的模型。
3.2 提示词工程:怎么描述才能让模型生成对的脚本
这一步是 text-to-cad 实操里最影响成功率的环节。同样一个零件,描述方式不同,生成质量天差地别。我总结了几条实用规则。
规则一:先给整体形状,再给局部特征。别说"一个带孔的方块,孔在中心,方块 40mm",要说"一个 40mm 见方的方块,中心有一个通孔"。模型对"整体→局部"的描述顺序处理得更好。
规则二:尺寸必须带单位,且统一。全程用毫米,别一会儿毫米一会儿厘米。模型对单位的推理能力很弱,混用必出错。
规则三:明确建模基准。说清楚零件以哪个面为底面、以哪个轴为中心。比如"以 XY 平面为底面,沿 Z 轴拉伸",比"竖着放"精确得多。
规则四:复杂特征拆成多句。一个零件如果有五个特征,就写五句话,每句一个特征。模型对长句里嵌套多个几何关系的解析能力有限。
一个实际可用的提示词模板长这样:
用 CadQuery 生成以下零件: - 整体:直径 80mm、高 30mm 的圆柱 - 特征1:中心沿轴向开直径 30mm 的通孔 - 特征2:顶面均布 8 个直径 6mm 的孔,分布圆直径 60mm - 单位:毫米 - 导出为 STEP 文件3.3 脚本执行与几何校验:怎么判断生成的模型是"对的"
模型生成了脚本,跑通了,导出了 STEP,不代表模型就是对的。我见过太多次脚本没报错但几何完全不对的情况——比如孔打穿了整个零件、特征位置偏移、实体不闭合。
校验分三层。第一层是语法和运行校验,脚本能不能跑通,这个最简单,try-except 就能捕获。第二层是几何有效性校验,用 CadQuery 的isValid()方法检查实体是不是有效的闭合体:
solid = result.val() if not solid.isValid(): print("几何无效,需要重新生成")第三层是尺寸校验,把生成实体的包围盒尺寸和预期对比:
bb = result.val().BoundingBox() print(f"X: {bb.xlen}, Y: {bb.ylen}, Z: {bb.zlen}")如果包围盒尺寸和描述对不上,说明模型理解错了。这三层校验串起来,就能自动筛掉大部分错误结果,只把靠谱的交给人工确认。
3.4 导出 STEP 之后,怎么验证文件真的能用
STEP 文件导出后,别急着往下游送,先做两个验证。
一是用 FreeCAD 打开看看。FreeCAD 是免费开源的,对 STEP 的兼容性好,能直接看到几何形状、检查有没有破面。如果 FreeCAD 打开是空的或者报错,说明 STEP 文件本身有问题。
二是检查文件大小和实体数量。一个正常的简单零件 STEP 文件通常几十 KB 到几 MB。如果只有几 KB,可能是空文件;如果几十 MB,可能是生成了大量碎面。用文本编辑器打开 STEP 文件(它是 ASCII 格式),搜索MANIFOLD_SOLID_BREP关键字,正常应该只有一个或几个,如果出现几百个,说明几何拓扑很碎,下游用起来会出问题。
4. 踩过的坑:text-to-cad 实操中的典型故障与排查
4.1 模型生成的脚本"看起来对"但几何是错的
这是最高频的坑,也是最难排查的。脚本语法没问题,跑起来也不报错,但生成的几何和预期完全不是一回事。
我遇到过一个典型案例:描述"一个 L 形支架,两臂各长 50mm,宽 20mm,厚 5mm",模型生成的脚本用两个长方体做布尔并运算,但两个长方体的位置没对齐,结果是一个错位的十字形而不是 L 形。脚本里每个box()调用都是对的,错的是translate()的坐标。
排查这类问题,不能只看脚本,必须看几何。我的做法是:生成脚本后,先导出 STL,用网格查看器(如 MeshLab)快速看一眼形状。STL 加载快,能立刻发现形状错误。确认形状对了,再导 STEP 做精细校验。
根因通常是模型对空间坐标系的理解不稳定。它知道要"并"两个体,但对"并"的位置关系推理不可靠。解决办法是在提示词里显式给出坐标,比如"第一个长方体中心在原点,第二个长方体中心在 (25, 10, 0)",把空间关系变成明确的数字。
4.2 单位、坐标系和布尔运算的连锁错误
单位错误往往不是孤立的,它会引发一连串连锁反应。模型把毫米当米,生成的零件尺寸差 1000 倍,然后布尔运算时因为尺寸差异过大,几何内核可能直接算失败,或者算出一个退化的结果。
坐标系错误更隐蔽。CadQuery 默认工作平面是 XY,Z 轴向上。但有些模型会假设 Y 轴向上(这是很多图形学库的习惯)。如果提示词里没说清楚,模型可能按 Y 轴向上生成,结果零件"躺"在 XY 平面上,下游装配时方向全错。
布尔运算的错误通常出在共面上。两个体如果有一个面完全重合,布尔并运算可能产生退化边,导出的 STEP 在别的软件里打开会报错。规避方法是在设计时让特征之间有微小的重叠或间隙,别让面完全贴合。
提示:在提示词里固定写一句"使用 CadQuery 默认坐标系,Z 轴向上,单位为毫米",能规避掉一大半坐标系和单位问题。这句话我每次都加,几乎成了肌肉记忆。
4.3 复杂装配体生成失败时的降级策略
让模型一次生成一个包含十几个零件的装配体,成功率很低。这时候需要降级策略:拆成单个零件分别生成,再用代码组装。
具体做法是,先让模型生成每个零件的脚本,逐个验证通过后,再写一个装配脚本,用 CadQuery 的Assembly类把零件按位置关系组装起来。这样每一步都可控,出错也好定位。
from cadquery import Assembly, Location assy = Assembly() assy.add(part1, name="base", loc=Location((0, 0, 0))) assy.add(part2, name="arm", loc=Location((0, 0, 30))) assy.save("assembly.step")如果连单个零件都生成不好,那就再降一级:用模板。把常见零件(法兰、支架、轴套)做成参数化模板,模型只负责填参数,不负责生成建模逻辑。这样牺牲了灵活性,但换来了稳定性。实际生产环境里,模板+参数填充的方案反而比纯生成更常用,因为可控。
4.4 从 STEP 到 URDF 转换时的常见断链
STEP 转 URDF 是机器人仿真里的高频需求,但这条链路坑特别多。URDF 需要的是每个连杆的几何、质量、惯性矩阵、关节类型和位置,而 STEP 只提供几何。质量和惯性得另外算,通常用 CAD 软件的质量属性功能,或者用 Python 的 trimesh 库从网格估算。
几何格式上,URDF 引用的是 STL 或 DAE,不是 STEP。所以流程是 STEP → STL → URDF。转换时要注意单位:URDF 标准用米,而 CAD 通常用毫米,转换时要除以 1000。忘了这一步,导入 CoppeliaSim 后机器人会大 1000 倍,整个场景都废了。
还有一个坑是坐标系原点。URDF 里每个连杆的几何是相对于连杆坐标系定义的,而 STEP 里的零件是相对于全局坐标系。转换时需要重新计算每个连杆的局部原点,通常取关节位置或者质心。这一步手工做很繁琐,建议写脚本自动处理。
5. 把 text-to-cad 接进真实工作流的几种姿势
5.1 批量生成标准件:参数表驱动的自动化
text-to-cad 最实用的场景不是生成复杂零件,而是批量生成标准件。比如你要做一系列不同规格的法兰,与其一个个描述,不如做一张参数表,让脚本循环生成。
import csv import cadquery as cq with open("flange_specs.csv") as f: for row in csv.DictReader(f): result = ( cq.Workplane("XY") .circle(float(row["outer_dia"]) / 2) .extrude(float(row["thickness"])) .faces(">Z").workplane() .hole(float(row["bore_dia"])) ) cq.exporters.export(result, f"flange_{row['id']}.step")这种模式下,LLM 只用来生成一次模板脚本,后面全靠参数驱动。效率极高,而且结果完全可控。我见过有团队用这种方式,把几百个标准件的建模时间从几天压缩到几分钟。
5.2 与现有 CAD 软件的协作:生成后继续手工精修
别指望 text-to-cad 一步到位生成能直接投产的零件。它的定位应该是生成初稿,然后设计师在 CAD 软件里精修。
实际流程是:text-to-cad 生成 STEP → 导入 SolidWorks/FreeCAD → 设计师加倒角、圆角、公差、螺纹特征 → 出工程图。这样设计师省掉了从零建模的时间,只需要做精修,效率提升明显。
这里有个技巧:生成时把特征做"粗"一点,别让模型去处理倒角、圆角这些细节。这些特征在 CAD 软件里手工加更快更准,而且模型生成这些细节的失败率很高。让 AI 干它擅长的(主体形状、孔位布局),让设计师干他擅长的(工艺细节)。
5.3 面向增材制造:从描述直接到可打印文件
3D 打印场景下,text-to-cad 的链路可以更短:描述 → CadQuery 脚本 → STL → 切片软件 → G-code。中间不需要 STEP,因为 3D 打印只认网格。
这个场景下,OpenSCAD 反而更合适,因为它的 CSG 表示天然适合生成网格,而且 LLM 生成 OpenSCAD 的准确率更高。一个典型的提示词是"生成一个壁厚 2mm、内部中空的立方体容器,边长 50mm,顶部开口",OpenSCAD 几行就搞定。
要注意的是壁厚和悬垂角。模型生成的几何可能包含不适合打印的薄壁或大悬垂,切片时会出问题。建议生成后先在切片软件里预览,检查有没有需要加支撑的地方。这一步目前还得人工判断,AI 还替代不了。
5.4 机器人仿真链路:URDF 自动生成的落地要点
机器人仿真是我认为 text-to-cad 价值最高的场景。手写 URDF 又臭又长,一个六轴机械臂的 URDF 动辄几百行,还容易写错。用 text-to-cad 生成,效率提升是数量级的。
落地要点有三个。第一,连杆几何用简单形状。别生成复杂的曲面连杆,用长方体、圆柱体近似就行,仿真里看不出来,但生成成功率高得多。第二,关节位置要精确。关节的 origin 决定了运动学,这个必须准,建议在提示词里显式给出每个关节的坐标。第三,惯性参数用估算。质量按体积乘密度估,惯性矩阵用简化公式算,仿真精度要求不高的话够用。
生成完 URDF 后,导入 CoppeliaSim 或 Gazebo 测试。如果机器人动起来姿态不对,八成是关节坐标系或者旋转轴方向错了,回去检查 URDF 里的<axis>和<origin>标签。
6. 几个提高成功率的实战心得
6.1 提示词里必须显式声明的几件事
踩了足够多的坑之后,我总结出一份"必写清单",每次生成前都检查一遍:
- 单位(毫米还是米)
- 坐标系(Z 轴向上还是 Y 轴向上)
- 建模基准(以哪个面为底面)
- 输出格式(STEP 还是 STL)
- 是否需要参数化(变量定义还是硬编码)
这五条写清楚,成功率能提升一大截。尤其是单位和坐标系,不写的话模型就随机选,结果不可预测。
6.2 生成结果的自动化校验脚本
手工校验太慢,建议写个校验脚本,把生成、执行、校验串起来:
def generate_and_validate(prompt, expected_bbox): script = call_llm(prompt) try: exec(script) except Exception as e: return False, f"执行失败: {e}" solid = result.val() if not solid.isValid(): return False, "几何无效" bb = solid.BoundingBox() actual = (bb.xlen, bb.ylen, bb.zlen) if not all(abs(a - e) < 1.0 for a, e in zip(actual, expected_bbox)): return False, f"尺寸不符: 期望{expected_bbox}, 实际{actual}" return True, "通过"这个脚本能自动筛掉大部分错误结果,只把通过的交给人工。实际用下来,能省掉七八成的人工检查时间。
6.3 什么时候该放弃 AI 生成,回到手工建模
不是所有零件都适合 text-to-cad。遇到这几种情况,我建议直接手工建模,别跟 AI 较劲:
- 零件有复杂的自由曲面(如叶轮、流道)
- 需要精确的工程标准特征(如螺纹、花键、齿轮齿形)
- 装配关系复杂,涉及大量配合约束
- 对公差和表面粗糙度有严格要求
这些场景下,AI 生成的模型要么形状不对,要么精度不够,改起来比自己建还慢。text-to-cad 的甜区是规则几何、参数明确、精度要求不高的零件,认清这个边界,才能把它的价值最大化。
6.4 把生成脚本纳入版本管理的习惯
最后说个工程习惯:把 LLM 生成的脚本存进 Git。每次生成的脚本、对应的提示词、校验结果都记录下来。这样做有三个好处:一是出问题能回溯,知道哪个版本的脚本有问题;二是好的提示词能复用,慢慢积累成自己的提示词库;三是团队协作时,别人能看到你是怎么描述零件的,减少沟通成本。
我现在的做法是,每个零件一个文件夹,里面放prompt.txt、model.py、output.step和validation.log。时间长了,这就是一个可复用的零件生成知识库,比任何文档都实用。
这套东西我用了大半年,最大的体会是:text-to-cad 不是要取代设计师,而是把设计师从重复劳动里解放出来。它擅长的是"把明确的需求快速变成几何初稿",不擅长的是"处理模糊需求和工艺细节"。把这两件事分清楚,用起来就顺手了。