1. 为什么“text-to-cad”突然成了硬需求
先别急着把它当成又一个昙花一现的AI噱头。我在制造业和设计软件领域泡了十来年,最近半年被同行问得最多的问题就是:用一句话描述一个零件,真的能直接生成可编辑的三维模型吗?
先说结论:能,而且不是玩具级的“样子货”。所谓 text-to-cad,就是通过自然语言输入,让程序直接产出参数化CAD模型(比如带特征树、可改尺寸的STEP/原生工程文件),而不是传统意义上用文本生成一张图片,或者用文本生成一个粗糙的网格体。它解决的核心痛点是:设计师和工程师大量重复性建模工作——或者更准确地说,是“明明脑子里有清晰结构,但手跟不上”的那部分效率损耗。
一套完整可落地的 text-to-cad 流程,现在主要覆盖三类人。第一类是我这样的机械设计/结构工程师,做非标件、夹具、钣金支架时,与其在软件里拉伸、切除、倒角来回切工具,不如直接描述;第二类是仿真和工艺工程师,需要快速验证某个结构是否可制造、可装配,不需要为一个简单零件花费半小时建参数模型;第三类是搞制造业自动化的开发者,想把“设计意图”直接导入到参数化建模环境和自动排产流程里。
这技术目前更多是辅助角色,但趋势已经很明显:它正在把“设计意图表达”从手势操作中解放出来。下面我想从核心原理、工具链选择、完整实操流程、踩坑经验这四个维度,把这件事讲透。
2. 这玩意儿背后的原理,其实没有那么玄
2.1 从“语义到几何”:本质是约束求解
很多人以为 text-to-cad 是类似文生图的“扩散模型输出一堆点云”,这个理解偏差很大。工业界能用的技术路线,核心是“把自然语言转换成参数化特征指令”,再交给约束求解器去生成模型。
打个比方:你告诉建模师傅“给我做一个直径30mm、厚度5mm的法兰盘,中心打一个直径10mm的通孔”,师傅脑子里会拆解成“圆柱拉伸=直径30×高5”、“打孔=拉伸切除直径10”——text-to-cad 系统干的就是这个拆解。它内部有两个关键模型协同:
- 语言理解模型(通常是大语言模型微调版):负责把自然语言拆解成结构化的建模指令序列,比如“创建草图平面→绘制圆→拉伸凸台→切除”。
- 几何约束求解器:负责把指令执行成带尺寸、带特征树、参数可改的CAD实体模型。
这个链路和文生图完全不同。它不追求“看起来像”,而是追求“尺寸对、特征全、能修改”。所以工业验证过的方案里,输出的原生CAD模型往往比渲染图更重要。
2.2 为什么不能直接用通用LLM生成STEP文件
有个坑很多新手会踩:直接让通用大模型“写一份STEP文件”或者“给我生成一段CAD代码”。且不说STEP文件本质是EXPRESS语言描述的交换格式,手写极易产生拓扑错误——就算模型背下了格式,输出的模型也难以参数化修改。通用LLM生成的往往是一次性的“死模型”,改一处尺寸就得重新生成。
核心原因在于:CAD建模的灵魂是“特征历史”。你看一个正规的.prt或.sldprt文件,里面有拉伸、切除、圆角、阵列的特征树,每一步都记录着基准面、草图、尺寸约束。没有这个特征树,一个圆柱体就只是一坨B-rep表面几何,工程上几乎不可用。
因此目前主流方案都是“代码生成中间表示”路线,比如生成对应开源CAD内核的Python脚本(CadQuery / build123d / OpenCascade),或生成某个商用CAD软件的宏命令(比如SolidWorks的宏API),然后脚本执行动态重建模型。这样生成的模型自带参数化逻辑,改一个变量,整条特征链随之更新。
2.3 模型选型:通用大模型 vs 专用微调模型
做这个方向的开发者常纠结:到底用什么模型做语义解析?我的实测结论是:通用大模型(具备较强代码能力的那种)在高层次理解上强,专用微调模型在“稳定输出合法建模命令”上强。
通用大模型的好处是能理解复杂描述,比如“一个带四个安装孔的方形底座,孔距50mm,底部有加强筋”,它能综合语义和常识推理出大致拆解;缺点是有时会“自由发挥”,生成长度不定的代码,要么漏掉某个特征,要么使用了内核不支持的API,出错率不低。
专用微调模型(用大量CAD脚本语料微调过)的好处是输出格式极稳定,可能90%以上的一次生成都能直接通过语法检查;缺点是理解复杂语境的能力稍弱,需要你把需求描述得更加结构化。
我的建议是:直接用通用大模型,但加上强约束提示词、输出Schema、以及后置的代码校验修复循环。千万别一上来就去微调专用模型——数据准备和训练成本高,投入产出比未必划算。
3. 实操准备:先搞清楚你要走哪条技术路线
3.1 一条最推荐的轻量级技术栈
工具选型直接决定你后续的踩坑数量。我这两年反复换方案,最后留存下一套相对稳定的组合:
- 语言模型通道:调用国内可用、具备较强代码生成能力的通用模型API,或者用开源的代码大模型本地部署,看你是否介意数据出内网。
- 中间表示层:CadQuery 或 build123d,这两个是Python原生的参数化CAD库,运行在OpenCascade内核之上,生成的模型可以导出STEP/STL,也能桥接到FreeCAD做进一步操作。
- 执行校验层:本地执行生成的Python脚本,捕获异常并自动把错误信息回灌给模型,让模型自我修正。这一步非常关键,是提升成功率的胜负手。
- 后端处理层:将成功生成的STEP模型做可视化预览(可以用 trimesh + pyvista,也可以用FreeCAD的图形界面),确认无误后归档。
这套组合最大优势是把“模型生成”和“几何内核运行”彻底分离。语言模型只负责写代码,实际建模由OpenCascade完成,出现几何错误跑不起来,模型会收到报错信息再修正,而不是生成时凭空想象。
3.2 环境搭建与依赖细节
环境搭建看着简单,实际有不少坑。给个可复现的步骤,按顺序操作:
# 建议用虚拟环境,避免Python包相互污染 python -m venv cad_env source cad_env/bin/activate # Windows下是 cad_env\Scripts\activate # 核心依赖 pip install cadquery build123d # 可视化与格式处理 pip install trimesh pyvista numpy # 如果你要本地跑开源模型,再加 # pip install transformers torch安装完成后建议先跑一个最小用例验证内核是否可用:
import cadquery as cq result = ( cq.Workplane("XY") .box(50, 30, 10) .faces(">Z") .hole(8) ) # 导出STEP cq.exporters.export(result, "test.step")这里要注意:CadQuery 的依赖 OpenCASCADE 是较大的二进制包,国内源有时拉取失败,建议直接使用阿里云或清华的 pip 镜像源。首次导入cadquery会比较慢(需要加载内核库),这是正常现象。另外 Windows 环境下最好用 Python 3.10 或 3.11,某些版本在 Python 3.12 上存在二进制兼容问题,我踩过这个坑,白白折腾了一个下午。
3.3 提示词结构设计:直接抄作业的模板
既然核心是让语言模型生成 CadQuery 脚本,你在提示词里给出的约束越明确,产出越稳定。我长期使用的一套提示词模板(亲测有效):
你是一个专业的CadQuery参数化建模专家。请根据以下产品描述,生成一段CadQuery Python代码。 要求: 1. 使用 cadquery 库,导入方式为 `import cadquery as cq` 2. 所有关键尺寸必须变量化,定义在代码顶部,变量名要有意义 3. 优先使用 fromPoint/center 定位,避免使用绝对坐标魔法数字 4. 建模逻辑必须清晰,分步骤操作(先主体,后特征) 5. 不得使用 cq.importers 或 cq.exporters 6. 最后一行将结果赋值给 `result` 产品描述: {用户输入内容}这个模板解决了我曾面临的三大痛点:变量不提取导致模型不可参数化、模型自作主张使用不支持的导入函数、代码结构混乱导致报错后难以定位。用模板后,一次成功率提升非常明显。
4. 完整实操:从自然语言到可编辑STEP模型
4.1 冲突描述:从“一句话需求”到“结构化指令”
很多教程止步于“一句话生成模型”,但真实项目哪有这么简单。实际需求往往是:
- “一个L型安装支架,长边100mm、短边60mm、宽40mm、厚度5mm,长边上有两个直径8.5mm的安装孔,孔距离边缘20mm,短边末端有一个直径12mm的半圆凸台。”
这算中等复杂度。完整操作流程如下,我以一个实际案例走一遍:
第一步,先将自然语言转成结构化参数表。这一步可以让语言模型先输出一个JSON参数清单,再据此生成代码,而不是描述完直接生成代码。这样做的好处是:人类可检查,参数错误能在早期发现。
第二步,用模板提示词,将参数表与描述传给模型生成脚本。
第三步,本地执行生成的脚本。如果抛异常,把完整traceback回灌给模型,让它自行修正,循环最多5次。
第四步,模型成功后导出STEP,再用可视化脚本快速渲染一张预览图,人工确认尺寸与拓扑。
我把上述流程整理成一个可复用的Python框架,核心执行循环如下——这样你后续换模型接口或换内核时,只改很少的代码:
import subprocess import re CLAUDE_CODE = "..." # 或者任意模型的接口封装 def generate_and_fix(prompt, max_attempts=5): for attempt in range(max_attempts): code = get_model_output(prompt + "\n请现在开始生成代码。") # 清理可能的markdown围栏 code = re.sub(r"^```(?:python)?\s*|\s*```$", "", code, flags=re.MULTILINE) with open("generated_model.py", "w") as f: f.write(code) try: subprocess.run( ["python", "generated_model.py"], check=True, capture_output=True, timeout=60, ) print(f"第{attempt+1}次尝试成功") return code except subprocess.CalledProcessError as e: error_msg = e.stderr.decode("utf-8", errors="ignore") print(f"第{attempt+1}次失败,错误:{error_msg[:300]}") prompt += f"\n\n你的上一次代码执行失败,错误信息如下:\n{error_msg}\n请修正后重新输出完整正确代码。" raise RuntimeError("超过最大尝试次数,生成失败")4.2 案例演示:电子设备外壳的生成
我们用一个真正产品级的案例验证:手持设备外壳。已知条件:主体尺寸120×60×20mm,壁厚2mm,内部分布4个直径3mm的定位柱,底面有USB接口开槽(长12mm、宽6mm,位置在短边正中偏右10mm),顶部四个角做R5的圆角。
建模思路拆解:
- 主体壳体用
box拉伸然后抽壳(shell),壁厚2mm。 - 定位柱用
workplane偏移到内底面,添加圆柱体。 - USB开槽用“布尔减运算”或拉伸切除。
- 圆角用
edges()选择顶部周边线执行fillet。
这些在CadQuery里实现并不算复杂,但让模型一次性全部写对并不容易,尤其是抽壳方向很容易写反。实际运行结果:模型第一次尝试就在“抽壳方向”上犯错了,生成了一个外壁壳体而不是带内腔的壳。我把报错和预期结果回灌后,第二次它就正确实现了——这也是“反馈修正循环”的核心价值所在。
可视化确认时我一般直接用 pyvista 渲染检查,关键看三点:壁厚是否均匀、特征是否完整、安装孔位置是否正确。这一步不要省,主要是过滤模型“语法正确但几何错误”的情况。
4.3 参数化能力:让模型可复用,而不是一次性的
做工程的人最看重“改参数重新生成”的能力。一个text-to-cad流程如果每次都从头生成一个新模型,那还不如不用。所以我在提示词里强制要求“所有关键尺寸变量化”,就是为了让生成脚本天然具备参数化属性。
比如外壳脚本的主要参数:
L = 120.0 # 外壳长度 W = 60.0 # 外壳宽度 H = 20.0 # 外壳高度 T = 2.0 # 壁厚 R = 5.0 # 四角圆角半径后续只要改这几个数字再执行一次脚本,新模型秒出,完全不用再和模型对话。这就从一个“生成器”变成了一个“参数化模板”,这对批量生成系列化零件(比如不同尺寸的仪表壳体)非常有价值。
注意:有些模型生成的代码会把变量写在中间某一行,或者直接在函数参数里填数值。你需要在反馈修正时强制要求变量集中在文件头部。这一步影响到项目后续可持续性,务必盯紧。
5. 常见问题与排查技巧实录
5.1 语法正确但几何错误的三大典型症状
症状一:抽壳方向反了。CadQuery的shell()方法默认向内部抽壳,但当你先做了圆角或倒角后再抽壳,可能出现几何退化。排查方法:将抽壳操作尽量提前,在圆角/倒角之前完成。
症状二:面选择歧义。faces(">Z")这类面选择器是基于边界框最值定位的,当模型有多个凸台、圆顶结构时,模型可能选错面。排查方法:改用明确的workplane偏移,或者用faces(tag=...)预先打标签。
症状三:布尔运算重叠阈值问题。两个实体恰好贴合时,OpenCascade有时会因容差问题产生破面。排查方法:给配合面留0.001mm的间隙或重叠量,这是工程建模中很实用的习惯。
5.2 让语言模型稳定输出的四个技巧
技巧一:把“少样本示例”直接放进系统提示词。给模型看一个完整的输入-输出示例对,比说一百遍“你要生成CadQuery代码”都管用。我一般放两个示例,一个是简单主体,一个是带孔和圆角的组合特征。
技巧二:限制输出格式。要求模型必须输出```python代码块,并且代码块内不得包含注释中的“示例”字样。这些细节能把HTTP传输时的转义问题降到最低。
技巧三:关键术语中英对照。对某些模型,中文“圆角”可能被理解为“圆形倒角”,但英文“fillet”则更准确。提示词中同时给出中文描述和英文对应关键词,能明显减少怪异生成结果。
技巧四:明确禁止模型调用外部文件。有些模型会自作聪明地尝试读写本地文件,这在自动化执行流程中非常危险,必须在系统提示里禁掉。
5.3 模型对复杂装配体描述的局限性
单零件场景下,text-to-cad 的成功率已经可以做到比较理想。但涉及装配体,比如“一个底座加4个螺栓加2个垫片”,模型往往会犯两个错误:一种是把所有零件合并成一个实体,另一种是零件之间完全没有装配约束关系。
目前比较务实的做法是:装配体按“单零件逐个生成,再用外部装配工具组合”来处理。生成单个零件时,保留统一的坐标系基准约定(比如都把底面原点放在 (0,0,0)),后续在FreeCAD或商业软件里施加配合约束即可。夸大text-to-cad目前能承担的水平没好处,你如果一开始就幻想一句话生成一套减速器装配体,大概率会失望。
6. 从个人效率工具到业务落地的几条经验
6.1 真实场景下的预期管理
务实地说,text-to-cad目前最适合的场景还是:单一几何体为主、特征数量适中、描述清晰的结构件。那些高度依赖曲面造型、自由曲面、复杂分型线的外观件,纯靠文字描述很难表达到位,这类任务建议老老实实用传统建模。
这就像文字生成图片一样,如果你用文字描述一个抽象概念会有很多种解读,但描述“一个红色圆圈”则几乎不会出错。CAD任务同理,特征越规则、参数边界越清晰,成功概率越高。
6.2 数据安全和内网部署考量
如果你的项目涉及产品预研或非公开结构,把图纸描述发给外部大模型API有泄露风险。建议优先考虑私有化部署代码大模型,显存需求大约在16GB以上(7B量级)或48GB以上(更大参数)。实际体验中,7B级别的模型在通用语义理解上略逊,但加上完善的反馈修正循环后,最终成功率差距并不算悬殊。
另一个思路是采用“本地模板库+小型改写模型”的混合架构:维护一份常见特征(安装孔、法兰、卡扣、加强筋)的CadQuery代码库,模型只需将自然语言映射到已有模板和参数。这种方式数据不出内网,生成稳定性反而更高。
6.3 往前一步:从文本生成到逆向优化
最近我在试验的方向是让text-to-cad不只是“文本到模型”,而是“文本到满足约束的模型”。即除了输入描述,系统还能从仿真结果中读取应力分布,然后自动调整壁厚或增加加强筋,再重新生成模型。
虽然目前这个链路还比较粗糙,但思路是通的:既然模型的输出是参数化脚本,那么脚本中的变量就能成为优化变量。这让text-to-cad有机会成为设计优化闭环中的一个执行器,而不是一个孤立的生成工具。
7. 最后再分享一条实操感受
text-to-cad真正让人上头的瞬间,不是模型第一次跑通,而是两个月后你拿到一张变更通知单、上面写着“主板厚度从1.6mm改成2.0mm,整机外壳所有卡扣位置随动偏移”时,你发现自己只需要在参数化脚本里改一个数字,重新执行一遍,几秒钟就输出了新版3D模型和STEP文件。这种效率提升就是这项技术最实在的价值。
我个人的建议是:不要等工具成熟了再学,现在就开始把日常工作中重复度最高的那几个零件类型,尝试用text-to-cad流程重构一遍参数化模板。这条流程可能一开始不如你用鼠标点得快,但一旦跑通,它后续的复用价值会远远超过你最初的那点学习成本。工具会不停迭代,但“用自然语言描述设计意图、再由参数化脚本驱动模型”这个思路,会是长期不变的趋势。早点动手,你积累的模板库和踩坑笔记会变成别人追不上的存量优势。