1. 从一句话到三维模型:text-to-cad 到底解决了什么问题
我在 CAD 建模这个圈子里摸爬滚打了十几年,从最早的鼠标逐点画线,到参数化建模,再到现在的 text-to-cad,工具链的变化可以说是天翻地覆。所谓 text-to-cad,简单说就是你把一句自然语言描述扔给模型,它直接给你吐出一个可以编辑、可以导入 SolidWorks 或 Fusion 360 的三维模型文件。比如你说"一个直径 40mm、高 60mm 的圆柱体,顶部有一个直径 10mm 的圆孔",它就能给你生成对应的 STEP 或 STL 文件。
很多刚接触这块的朋友会误以为它只是个高级的图块生成器,实际用下来你会发现完全不是这么回事。text-to-cad 背后的核心价值在于它将"设计意图"直接翻译成"几何约束关系",省掉了中间大量重复性的草图绘制和特征建模操作。对于非专业建模人员来说,这是极大的门槛降低;对于专业工程师来说,这相当于把一个能听懂人话的参数化建模助手放在手边。我最早接触这个方向是因为团队里经常接到一些非标零件的紧急需求,客户电话里描述一个形状,我要花半小时画出草图再拉伸打孔,有了 text-to-cad 之后,这个流程被压缩到了几分钟。
现在市面上的主流方案大致分为两派:一派是基于大语言模型做结构化命令生成,再调用传统内核建模,典型代表是 Zoo 的 Text2CAD 项目和复旦大学的相关研究工作;另一派是直接用神经网络隐式表达生成体素或隐函数场,再网格化成可编辑模型,比如 AutoDesk 的某些实验性项目。前者生成的是参数化特征树,可编辑性强;后者生成的是网格模型,有机形状表现力好但后期修改麻烦。这篇博文我打算把两派的核心逻辑都拆一拆,重点记录我在实际项目中跑通全流程的实操经验、踩过的坑,以及一些可以"抄作业"的参数配置。
先交代一下我自己的使用背景:我主要用它来生成机械加工零件和简单的结构件,偶尔也用来做产品外形的快速验证。我的工作流是 text-to-cad 输出 STEP 文件,然后导入 SolidWorks 做尺寸微调和装配。如果你跟我场景类似,那这篇文章的实操部分会非常对胃口。
2. 整体设计与技术选型:两条技术路线的深度对比
2.1 命令生成派 vs 几何生成派
在我实际测试过的方案里,两条路线的差异非常明显,先看一张对比表再展开说。
| 对比维度 | 命令生成派 | 几何生成派 |
|---|---|---|
| 底层原理 | LLM 输出建模命令序列,传统内核执行 | 神经网络直接预测体素/隐式场 |
| 输出格式 | STEP、BREP、参数化特征树 | STL、Mesh、隐式函数 |
| 可编辑性 | 强,特征可回溯修改 | 弱,网格模型修改困难 |
| 几何精度 | 高,符合 CAD 内核精度 | 低,受限于网格分辨率 |
| 擅长形状 | 规则机械件、拉伸旋转特征 | 自由曲面、有机形态 |
| 代表项目 | Zoo Text2CAD、复旦 Text2CAD | DreamFusion、AutoSDF |
命令生成派的核心思路是把自然语言先解析成"操作序列"。举个例子,用户说"创建一个宽度 100mm 的矩形底座,在四个角上各加一个直径 8mm 的通孔",模型会输出类似sketch_rectangle(0,0,100,50)、extrude(10)、hole(8, corner_positions)这样的指令序列,然后交给底层几何内核去执行布尔运算和拉伸。这种做法的最大优势是最终模型的参数化信息完整保留在特征树里,我可以在 CAD 软件里直接改尺寸,灵活性非常高。
几何生成派则不搞什么特征树,它直接把文本描述映射到三维空间中的占用概率场,然后通过 Marching Cubes 之类的算法提取等值面生成网格。这条路线的优势非常明显:几乎不受拓扑结构限制,什么古怪造型都能给你生成出来。但问题也同样致命——生成结果经常出现破面、孔洞、非流形边等问题,对于需要在数控机床上加工的实际零件,这种网格模型不能直接用,还得花大量时间做曲面修复。
我个人的建议是:如果做机械加工件或者有严格装配关系的结构件,优先选择命令生成派方案;如果做概念设计、外观评审、3D 打印的摆件,几何生成派也完全够用。两条路线不是对立关系,我现在的项目里就是混着用,根据任务性质随时切换。
2.2 命令生成派的核心架构拆解
命令生成派的技术栈其实可以拆成三层:文本理解层、命令映射层、几何执行层。
文本理解层目前基本都是拿预训练的大语言模型来做的,比如 Zoo 项目用的就是 LLaMA 系列微调模型。这一层要做的事情是把自然语言里的尺寸、形状、位置关系、特征类型抽出来,转成结构化的中间表示。以"一个直径 40mm 高 60mm 的圆柱体顶部有直径 10mm 的孔"为例,模型需要正确识别出"圆柱体"是基础体素、"40mm"和"60mm"是约束参数、"顶部"是参考面、"直径 10mm 的孔"是布尔减运算。
命令映射层负责把中间表示转成一套确定性的建模命令,这套命令的语法一般参考 OpenSCAD 或者 CadQuery 的 DSL。我用过的几个方案里,CadQuery 风格的命令序列最顺手,因为它天然支持参数化,一个零件的建模脚本可以复用和调整。命令序列必须是有序的、无歧义的,模型还要生成合理的默认值——比如用户没提到圆角半径,系统就得按照经验值补一个或者明确不处理。
几何执行层就是传统的 CAD 内核,OpenCASCADE 是绝大多数方案的选择。执行层把命令序列逐条跑完,最终生成 STEP 或 BREP 文件。这里有个关键点:文本理解层的错误可以通过命令序列的语法检查发现一部分,但语义层面的错误(比如把孔的位置从前端放到了后端)只有依赖几何内核的合理性校验才能兜底。我在实践中的做法是额外加了一层规则校验:零件是否封闭、是否有非流形边、体积是否合理、孔位是否在实体范围内等等。
3. 核心细节解析与实操要点:从提示词到输出文件的每一道关卡
3.1 提示词工程:怎么把话说清楚,让模型不跑偏
文本输入质量直接决定输出质量,这条铁律在 text-to-cad 里比任何其他 AI 生成场景都适用。我的经验是,一个"好"的建模提示词需要包含以下信息要素:主体形状、关键尺寸、特征位置、特征类型、默认单位、精度要求。
拿一个实际例子说明。我第一次用 Zoo Text2CAD 的时候,输入的是"做一个法兰盘,上面有四个螺丝孔",生成结果惨不忍睹——模型默认了 100mm 外径,孔直接排成了一排,完全没有按照圆周均布来理解。后来我调整了写法:"创建一个外径 120mm、内径 40mm、厚度 12mm 的法兰盘,在直径 80mm 的螺栓圆上均匀分布 4 个直径 10mm 的通孔"。这一次结果完全正确。
这里面的门道在于"螺栓圆"这个术语。模型训练语料里包含大量机械设计文档,"螺栓圆的直径"这个信息能让模型准确地定位孔的分布位置。如果你只说"四个孔均布",模型能理解均布的概念,但不知道均布在哪个圆周上,就会给你安排到外径边缘上去,孔壁都快跟外圆切在一起了。
另外要注意单位问题。绝大多数开源模型默认毫米,如果你说"做一个 12 英寸的支架",有的模型能正确换算,有的模型直接当成 12mm 处理。我的习惯是一律在提示词里显式声明单位,比如"所有尺寸单位均为毫米"。这个习惯养成了之后,返工率下降了一大半。
3.2 关键参数的调优策略
无论是用现成的开源模型还是自建部署,几个核心参数对生成质量的影响极大。我整理了一份自己的调参记录。
温度(temperature)直接控制模型输出的随机性。我发现建模任务跟文案生成完全两个路数:写文案需要一点随机性让表达更丰富,但建模命令序列是确定性任务,温度稍微高一点都会导致参数值乱跳。我的建议是将温度设置在 0.1 到 0.2 之间,超过 0.5 基本没法看,孔的位置、圆角半径这些数值都会出现明显偏差。
Top-p 采样阈值建议配合温度一起调低,0.8 左右比较安全。这个值控制候选集的大小,调低了能避免模型从一些低概率的"奇怪操作"里采样。我之前遇到过一次模型给长方体加了个球面凹陷,就是因为 top-p 调太高让低概率的造型操作混进来了。
还有一个常被忽略的参数是最大生成长度(max_length)。命令序列通常不长,但如果设置得太短,模型会在生成一半的时候被截断,输出一个不完整的建模脚本,几何内核执行到一半直接报错;设置太长又容易让模型"自由发挥",编出一些根本不在建模语言规范里的指令。我用下来 512 到 1024 是个合理区间,根据命令复杂程度动态调整。
3.3 坐标系与特征基准面的约定
生成模型时坐标系的选择是个隐藏的坑。大多数 text-to-cad 系统默认以全局坐标系原点为参考,生成的零件位置和方向都基于这个原点。问题在于:如果用户描述里提到了"底面""正面""左侧"这类方位词,模型需要正确映射到坐标轴方向。我踩过最惨的一次是一个左右手件搞反的案子——提示词里说"凸台在左侧",模型默认 +X 方向为左,但实际装配时 +X 对着右边,整个零件装不上,最后只好镜像重来。
我的解决方案是在提示词里直接定义方向:"以全局坐标系为参考,+X 方向为零件正面,+Z 方向为零件顶面,底面位于 Z=0 平面"。这样模型就有了明确的坐标系锚点,方位词的歧义大大减少。如果你用的是支持自定义基准面(datum plane)的系统,还可以进一步指定主基准面和参考基准面,让模型的定位逻辑更接近手工建模的思维。
4. 实操过程与核心环节实现:完整跑通一个法兰盘模型
4.1 环境搭建与工具链配置
我目前使用的方案是 Zoo 团队发布的 Text2CAD 推理框架,底层模型是微调过的 LLaMA-2-7B,几何内核用的是 OpenCASCADE,Python 3.10 环境下运行。模型的推理需要一张至少 8GB 显存的显卡,CPU 模式也能跑,但速度会慢到让人怀疑人生——我测试过用纯粹 CPU 推理一个中等复杂度的零件,耗时超过三分钟,GPU 加速后只要八秒左右。
部署过程有几个关键步骤:
git clone https://github.com/zoo/Text2CAD.git cd Text2CAD conda create -n text2cad python=3.10 conda activate text2cad pip install -r requirements.txt安装依赖的时候有个坑:OpenCASCADE 的 Python 绑定pythonocc-core版本兼容性极差,在 Python 3.11 上经常编译失败,所以我一直锁定 Python 3.10 版本。如果pip安装卡住,建议直接到 conda-forge 频道安装:
conda install -c conda-forge pythonocc-core=7.7.0我用的是 Nginx + Gunicorn 把推理服务封装成 HTTP 接口,这样团队其他成员可以通过 REST API 提交文本生成模型,不需要每个人都配一套 Python 环境。FastAPI 比 Flask 更合适,因为它的异步支持能同时处理多个推理请求,不会互相阻塞。接口层只暴露两个端口:一个接收文本返回 STEP 文件,一个接收 STEP 文件返回模型的参数化特征摘要,方便下游 CAD 软件使用。
4.2 从文本到 STEP 文件:分步拆解
下面我用一个法兰盘例子走一遍完整流程。假设用户输入的文本是:
"创建一个外径 120mm、内径 40mm、厚度 12mm 的法兰盘,在直径 80mm 的螺栓圆上均匀分布 4 个直径 10mm 的通孔,外沿倒角 1mm,材质为 304 不锈钢。"
第一步,文本进入 LLM 后,系统会先做意图识别和实体抽取。这个过程模型内部会先输出一段结构化 JSON,包含主实体(法兰盘)、参数列表(外径、内径、厚度)、特征列表(通孔阵列、倒角)、材质标注。我在调试日志里看到过这段中间输出,有时候模型会漏掉某个参数,比如忘记"厚度 12mm",这时候就需要在后续的代码里做默认值补齐。
第二步,JSON 转成 CadQuery 风格的建模命令序列。这一步的代码逻辑大致如下:
import cadquery as cq def flange_from_text(params): outer_d = params["outer_diameter"] inner_d = params["inner_diameter"] thickness = params["thickness"] bolt_circle_d = params.get("bolt_circle_diameter", outer_d * 0.67) hole_count = params.get("hole_count", 4) hole_d = params.get("hole_diameter", 10) # 创建基础法兰盘轮廓 result = ( cq.Workplane("XY") .circle(outer_d / 2) .extrude(thickness) .faces(">Z") .hole(inner_d) # 中心孔 ) # 在螺栓圆上打均布孔 for i in range(hole_count): angle = 360 / hole_count * i result = ( result.faces(">Z") .workplane() .polarArray(bolt_circle_d / 2, 0, 360, hole_count) .hole(hole_d) ) result = result.edges("|Z").chamfer(1) # 外沿倒角 return result执行这一步有几点要注意:faces(">Z")是要选中顶面作为下一步的草图平面,这是 CadQuery 的典型用法;polarArray能精确地在圆周上生成均布阵列;倒角要用chamfer,如果需要的是圆角则用fillet。
第三步,几何内核执行命令序列并验证结果。执行完成后系统会跑一遍网格检查:检查实体是否封闭、是否有自由边、体积是否为正值、螺孔是否真的穿透了实体(布尔减运算是否成功)。如果某个孔没有贯穿,通常是厚度方向的参数理解错误导致的,需要在输入端修正。
第四步,导出为 STEP 文件:
from cadquery import exporters exporters.export(result, "flange.step", exportType="STEP")这一套流程跑下来,我的实测时间大概是:热启动状态下 6 到 10 秒,冷启动(重新加载模型权重)需要 30 秒到 1 分钟。对于设计验证场景,这个速度完全可接受。
4.3 复杂场景实战:带空腔和加强筋的壳体
只做简单的法兰盘体现不了 text-to-cad 的威力,我挑一个复杂点的场景说说。有一次团队要快速验证一个控制器壳体,要求是:外形尺寸 150×100×50mm,壁厚 3mm,内部有一个隔板把空腔分成上下两层,侧面开一个 30×20mm 的矩形散热孔,四角有安装柱。
这个模型如果用传统方式画,我大概需要 20 分钟;text-to-cad 生成初始版本只要了 15 秒,但后续手工修正花了十分钟。生成的问题出在"隔板"的理解上——模型把隔板做成了贯穿整个壳体的完整平板,但实际上我要的是隔板距离顶部 20mm,只挡住下半部分,不封顶。这是典型的语义理解偏差,模型能理解"隔板"的概念,但精确的位置关系需要额外的位置描述。
修正思路是把"距离顶部 20mm"直接写进提示词,同时补充隔板的边界信息"隔板四边与壳体内壁贴合"。生成结果立刻就对了。这个案例给我的启发是:text-to-cad 能理解特征类型和大致位置,但精确尺寸关系和贴合关系必须显式声明,不能依赖模型的"常识推断"。
5. 常见问题与排查技巧实录:踩过的坑和梳理出的排查表
5.1 建模失败原因分类与快速定位
我用 text-to-cad 跑了大半年,遇到的建模失败问题基本可以归结为四类:语义理解错误、命令序列错误、几何内核执行错误、输出文件下游兼容问题。我整理了一份排查速查表。
| 问题现象 | 可能原因 | 快速排查方法 |
|---|---|---|
| 模型生成了但尺寸完全不对 | 单位被误解或遗漏 | 检查提示词是否显式声明单位 |
| 孔没有穿透实体 | 特征方向理解错误 | 确认特征是否附加在正确的面上 |
| 倒角导致实体异常 | 倒角半径过大或位置错误 | 查看几何内核报错信息 |
| STEP 文件导入后零件缺失特征 | 导出精度设置不足 | 显式设置导出容差和表面精度 |
| 生成速度极慢 | 模型在冷启动 | 使用模型预热机制或常驻进程 |
| 输出文件损坏无法打开 | 命令序列被截断 | 检查 max_length 是否过小 |
快速定位的第一原则是先看日志里的中间表示(JSON 和命令序列),而不是直接看最终模型。中间表示是"翻译结果",最终模型是"执行结果",八成的问题都出在翻译阶段,如果 JSON 里信息都对,那问题基本锁定在几何内核层面。
5.2 几何拓扑错误的修复方案
网格模型生成派经常出现非流形边和破面,这类问题虽然有自动修复工具,但修复参数非常讲究。我用 MeshLab 做修复的经验是:先小步长执行"删除重复面"和"合并相邻顶点",再检查是否有非流形边。顺序不能反,先合并顶点有可能把本来正确的面缝合出错误拓扑,先删重复面则可以避免这类问题。
如果是生成 BREP 实体时出现了面自相交或者缝合失败,OpenCASCADE 的ShapeFix_Shape工具可以救一部分场,但严重自相交的模型基本只能重做。与其和内核死磕,不如回到提示词层面改描述。举个例子,我遇到过提示词里说"圆角过渡"结果模型在两条不相交的边之间做了圆角,导致曲面自相交。把描述改成"仅在顶面外沿做半径 2mm 的圆角"之后,问题迎刃而解。
5.3 性能瓶颈与批量生成优化
如果你像我一样需要批量生成几十个零件模型,逐个推理的效率问题会很突出。我的优化经验有几点:
- 开启批处理推理,显存允许范围内batch size开到 4 到 8,吞吐量能提升 3 倍以上;
- 模型预热:启动后随机生成几个简单零件作为热身,避免每个请求都触发全量计算;
- 文件缓存:相同或相似的提示词直接复用之前生成的结果,用文本的哈希值做文件索引;
- 显存不够时用 FP16 半精度推理,精度损失对建模任务影响不大,但显存占用几乎减半。
还有个小技巧:生成的 STEP 文件可以在后处理阶段批量去除重复几何体(用同胚检测算法)和压缩坐标精度。CAD 软件虽然接收小数点后六位的坐标精度,但实际加工只需要三位,压缩后文件体积能缩小 40% 左右,传输和打开都更快。
5.4 团队协作与版本管理
最后说一个很多人忽视的点:text-to-cad 生成的不是"图",而是"参数化描述 + 几何结果"。所以版本管理也要跟代码一样严谨。我现在的做法是每一条提示词和它对应的生成结果都放进 Git 仓库,提示词写清楚版本变化的理由。比如:
v1: 法兰盘外径 150mm 螺栓孔为 4 个 v2: 外径改为 120mm,孔增加到 8 个,新增螺纹孔 M6这样管理的好处是:当某个改版需求来了,我可以直接 diff 两个版本之间提示词的差异,精确知道是哪个参数的变化影响了最终几何结果。迭代过程变得可追溯,这在传统 CAD 里很难做到。
还有一个协作上的经验:让非建模团队也能安全使用这个工具,需要在上层做一层"参数白名单"保护。比如只允许修改外径、高度、孔位这些参数,固定壁厚和材料属性不可改变,否则产品经理随便改一句描述,生成的模型可能完全不满足强度要求。我在 FastAPI 层做了参数的取值范围校验,超出阈值直接拒绝并返回错误信息,这样才敢把接口开放给更多同事使用。
6. 从发展脉络看 text-to-cad 的未来走向与个人实践感悟
扯点个人的判断。我接触过早期的 AI 辅助设计工具,也看着 text-to-cad 从一个需要手写一大段结构化指令的科研演示,变成了现在这种可以直接对话式生成的实用工具。一个明显的趋势是:大语言模型的能力提升直接带动了命令生成派的进步。以前模型理解不了"均匀分布""螺栓圆""沉头孔"这类专业术语,随着训练语料里工程文档占比增加,现在的模型在这些概念上的表现已经相当可靠。另一个趋势是几何生成派正在试图融合参数化思想,比如用超网络预测参数化模型的参数张量,而不是直接输出网格,这样既保留了自由曲面表达能力,又获得了参数化的可编辑性。
作为每天实际使用它的工程师,我最大的体会是:text-to-cad 不会替代建模工程师,它替代的是那些重复性的、确定性极高的草图绘制和特征创建劳动。设计师的创造性工作——理解需求、规划结构、权衡加工工艺——仍然是不可替代的。工具真正解放出来的是我从机械制图桌面里挣出来的时间,让我有精力去思考产品整体架构层面的问题。
最后再分享一个实用小技巧:把常用零件类型的"模板化描述"整理成一个提示词库。比如法兰盘模板、支架模板、壳体模板,每套模板写下描述格式和参数占位符,需要新零件的时候只需要替换关键参数,不需要每次都从头写提示词。我用这个方式把 80% 的重复性生成请求都变成了填表操作,团队里的非专业人员也能参与到前期的结构仿真验证中,效率提升非常可观。这套模板库我一直在维护,每次遇到模型理解偏差就顺手补充进模板的注释里,迭代了几轮之后,现在的成功率已经稳定在九成以上。