Text-to-CAD实战:用自然语言生成可编辑的STEP模型
Text-to-CAD字面意思是用自然语言直接生成CAD模型。我第一次把“一块长80、宽60、厚6的矩形铝板四角各带一个直径5的通孔”这样一句描述丢进工作流几分钟后拿到可编辑的STEP文件时第一反应不是“AI真厉害”而是“我以前为什么在类似的活上耗了那么多时间”。传统CAD里画这种零件开新文件、建草图、约束、拉伸、打孔、倒角一套命令走下来少说十几分钟改一版尺寸又得从头点一遍。Text-to-CAD这个方向本质是把“设计意图 → 参数特征 → 几何实体”这条链路压缩到一句话的距离。这篇文章不聊概念我从实际工程视角拆一拆它下面雷打不动的几条技术路径是什么哪些能真正落到加工和生产以及怎么在本地搭一条最快跑通、还能反复用的可复现流程。无论你是机械工程师想提效还是3D打印玩家想快速出模型这篇文章都值得看完后照抄一遍。1. text-to-cad 是在解决哪段“费力不讨好”的路先把问题摆正很多人以为3D建模的痛点是“不会用软件”但实际工作里更痛的是“想法已经很清楚却还要一笔一笔画出来”。做过机械设计的朋友都有体会最耗时间的往往不是结构方案本身而是把结构方案翻译成软件能认的特征序列这一步该选哪个基准面这个凸台该从哪个草绘拉伸孔到底是通孔还是盲孔。1.1 设计意图到可制造模型之间的三个断层第一个断层是语言到参数人对几何的描述是语义化的——“这里有个加强筋和底板对齐厚度3毫米”CAD软件不接受语义它要的是草图、尺寸、约束、特征树。语义到参数的转译过去只能靠熟练工程师手搓。第二个断层是参数到几何即使有了尺寸参数建模顺序错了、父特征选错了轻则模型报错重则整个装配体干涉。这个环节考验的是“建模经验”不是每个有想法的人都有。第三个断层是几何到工程交付图纸要标注、格式要STEP或IGES、零件要检查流形性和干涉这层工艺经验又是另一道门槛。Text-to-CAD瞄准的恰恰是第一个断层的自动化让模型替你完成从自然语言到参数特征的转译。这也是为什么它比单纯的“AI生成图片”更让工程界兴奋——因为它直接缩短了从概念到加工的距离。1.2 为什么入口偏偏是“文字”而不是鼠标这里有个反直觉的点图形建模软件已经有三四十年历史操作方式从命令行进化到图标再到现在的参数化和直接建模为什么绕了一圈入口又回到了“打字”因为文本是当前最稳定的指令接口。现阶段的生成模型本质上都是“下一个词预测”最擅长处理的就是离散符号序列。代码是符号序列文字是符号序列几何操作如果被写成代码也可以看成符号序列。反过来鼠标点选、拖拽、草绘这一串连续动作生成模型反而很难驱动。另一个原因是文本信息密度高。完整描述一个中等复杂零件几百字足够“教”一个新手画出来可能要半小时。文字能把约束、尺寸、材料、加工方式压缩在一个提示词里这对LLM来说是天然的输入形态。2. 分清技术路线text-to-CAD 与 text-to-3D 的差别比想象中大现在网上一搜“text to cad”会冒出两类完全不同的东西。一类是从自然语言直接生成三维网格或神经场视觉效果花哨常用于游戏、影视、概念展示另一类是生成参数化实体模型也就是真正进入CAD生态的数据。这两类差别极大如果没分清就选错方向项目大概率胎死腹中。2.1 CAD模型的三条硬指标流形实体、特征树、标准交换格式工业界愿意支付的CAD模型必须同时满足三条硬指标几何合法性模型必须是流形实体简单说就是“内部是实心、表面是封闭”的结构。不能有自相交面不能有零厚度薄片不能有悬空的孤立面。这样的模型才做得了布尔运算、切得出手印、算得出体积。参数化特征树下游工程师要改尺寸、改位置、改特征靠的是建模历史里的约束和特征。一个“实心死数据”的三角网格在工程链条里基本不可用。可交换格式CAD软件之间互通靠STEP、IGES这类B-rep标准。STL虽然常见但它只是三角面片没有法线连续性、没有单位语义、没有特征信息只能拿去打印和预览。如果你生成的模型满足不了这三条那它再有“美感”也过不了工程验收。所以真正意义上的Text-to-CAD落点通常是参数化实体模型而不只是“一个好看的三维形状”。2.2 四条主流转译路线的取舍把自然语言变成满足上述硬指标的模型目前主要有四条路子路线A大模型直接生成参数化脚本最成熟。让LLM写出CadQuery、OpenSCAD这类脚本CAD库代码再本地执行脚本生成实体。脚本天然带特征树导出STEP就是B-rep工程属性完全保留。路线B专用端到端模型直接输出B-rep参数。学术界已经有直接用Transformer生成几何拓扑序列的工作不经过代码直接吐出点、边、面的连接关系和方程系数。精度上限高但公开可用的成熟产品还不多工程复现成本高。路线C文本生成网格/点云再用软件逆向拟合。优点是出图快、造型自由缺点是网格转实体往往要重新拓补误差大且结果通常不再参数化。路线D从已有零件库检索再改参数。给大模型挂一个零件库检索器先找相似件再通过脚本改尺寸。胜在稳定败在依赖库的覆盖范围。四条路线里我实际项目里选最多的是A可解释、可迭代、可拿到工程用的STEP文件。接下来就沿着路线A把全套流程走一遍。3. 从零跑通一条“描述→脚本→STEP”的最小工作流如果你也想快速验证Text-to-CAD不必等什么IDE插件或商业产品自己搭一条最小可用链路核心组件就三个一个脚本化CAD内核、一个大模型API或本地部署模型、一个跑迭代的Python胶水脚本。3.1 环境准备装好验证极快的脚本CAD库我选CadQuery而不是OpenSCAD原因很直接OpenSCAD是CSG构型描述复杂倒角、抽壳、圆角这类工程特征非常别扭CadQuery用“工作平面特征链”的方式建模思路和SolidWorks相似生成的特征树也更容易让人理解。建议新建独立环境安装conda create -n cadq python3.11 -y conda activate cadq conda install -c conda-forge cadquery -y如果坚持用pip环境直接pip install cadquery也不是不行但CadQuery底层依赖OCCT的Python绑定pip在某些平台容易拉源码现场编译时间久且容易失败。Conda-forge有预编译包省心得多。装好先跑一个冒烟测试确认能导出一个STEP文件import cadquery as cq result ( cq.Workplane(XY) .box(40, 30, 10, centeredFalse) .faces(Z) .workplane() .hole(5) ) val result.val() print(体积:, val.Volume()) print(包围盒:, val.BoundingBox().xlen, val.BoundingBox().ylen, val.BoundingBox().zlen) print(合法:, val.isValid()) cq.exporters.export(result, smoke_test.step)这段代码的意思是在XY平面生成一个40×30×10的方块再在顶面打一个直径5的孔。如果“体积”“包围盒”“合法”三行都正常输出库就算跑通了后面所有内容都建立在这个验证链路上。3.2 系统提示词这是生成质量的“第一道闸门”很多人的Text-to-CAD失败不是模型能力不够而是提示词太“聊天”。给大模型一套工程约束明确的系统提示词生成质量会有质的提升。我长期使用下面这版模板你是参数化CAD脚本工程师。请根据用户描述输出CadQuery脚本。 规则 1. 单位一律是毫米。 2. 坐标系约定Z轴向上默认建基准面在XY。 3. 凡是规则排列的孔、凸台优先用线性阵列或极坐标阵列不要逐个写。 4. 所有尺寸必须是具体数值禁止用占位变量禁止让用户后续填写。 5. 每写一个特征必须在代码上方用中文注释说明这个特征对应描述里的哪句话。 6. 只生成单个实体零件不要生成装配体。 7. 脚本最后必须包含 cq.exporters.export(result, output.step)。 8. 如果描述里有相互矛盾的尺寸优先按较小者执行。第3条和第5条看起来不起眼其实是最关键的。第5条让模型的推理路径和用户描述对齐减少“听成了另一个零件”的幻觉第3条则逼着模型用参数化阵列模型的可修改性一下子上去因为你改一个数所有阵列孔都跟着变。3.3 一个能跑的生成结果长什么样假设输入是“做一个安装支架底板长120、宽80、厚8底板四角开直径6的安装孔在顶面居中升起一个高30的圆柱凸台直径40凸台中心打通孔直径20”。模型按上面模板输出的合理脚本大致长这样import cadquery as cq # 底板长120、宽80、厚8 result ( cq.Workplane(XY) .box(120, 80, 8, centeredFalse) ) # 底板四角开直径6的安装孔距边10 result ( result.faces(Z) .workplane() .rect(100, 60, forConstructionTrue) .vertices() .hole(6) ) # 顶面居中凸台高30直径40 result ( result.faces(Z) .workplane() .circle(40 / 2) .extrude(30) ) # 凸台中心打通孔直径20 result ( result.faces(Z) .workplane() .circle(20 / 2) .cutBlind(-30) ) cq.exporters.export(result, output.step) cq.exporters.export(result, output.stl)这个脚本涉及了“用构造矩形定位孔位”“先拉伸再切孔”两个常见套路。如果模型一次生成不完美你也不用手工改直接把报错信息丢回去让它重写后面会讲闭环迭代。3.4 生成后校验体积、包围盒、流形性脚本跑通不等于模型能交付。我建议每次生成后自动跑一段校验v result.val() bbox v.BoundingBox() assert v.isValid(), 模型不是合法流形实体 assert v.Volume() 0, 体积为零请检查特征是否被完全切穿 assert bbox.xlen 0 and bbox.ylen 0 and bbox.zlen 0, 包围盒非法 print(f体积: {v.Volume():.2f} mm^3) print(f包围盒: {bbox.xlen:.1f} x {bbox.ylen:.1f} x {bbox.zlen:.1f} mm)这一层是流水线的安全网。体积可以验证“是不是被切穿了”包围盒可以验证“大模型是不是把120听成了12”。后面我会专门讲一圈调试时最容易遇到的实际问题。4. 把生成质量从“能看”拉到“能用”的六个工程技巧跑通一条最小链路不难难的是让生成结果稳定地进入“可加工”状态。以下六个技巧是我在实际使用中反复踩坑总结出来的直接照搬能省很多调试时间。4.1 让模型先写建模计划再写脚本不要一上来就要求“直接给代码”。让模型先花一小段输出“建模计划”比如建模计划 1. 用box创建底板长120宽80高8。 2. 在顶面建直径6的安装孔四角均匀分布。 3. 在顶面中心拉伸圆柱凸台。先写计划的好处有两个一是模型在推理中途“复述”需求一旦理解偏了你在计划阶段就能发现而不必等代码跑完二是计划会自动约束后面的代码结构让代码顺序和人类建模习惯一致出Bug概率明显下降。4.2 编译反馈循环:把报错变成下一轮的上下文这是整个流程里最有价值的一个机制。脚本执行报错不可怕可怕的是你手动去改。正确的做法是写一个自动迭代器import traceback prompt USER_DESCRIPTION SYSTEM_TEMPLATE for turn in range(4): script llm_generate(prompt) # 调大模型生成脚本 try: exec(script, ns) break except Exception as e: err_msg f{type(e).__name__}: {e}\n err_msg traceback.format_exc() prompt f\n\n上次脚本执行报错如下\n{err_msg}\n请分析原因重写完整脚本不要省略无关代码。实测下来大部分语法错误、API拼写错误、特征引用错误三轮之内就能清完。这个闭环之所以有效是因为LLM能把“报错信息——错误原因——修正代码”串成一条推理链。它等于让你的工作流拥有了一个会自动Debug的虚拟助手。4.3 强制单位与坐标系规范工程领域的单位错误是灾难级的。一个“直径5”的孔如果模型按英寸解释孔径直接变127毫米。所以系统提示词里要反复强调毫米校验脚本里也建议比对包围盒与预期尺寸偏差超过5%直接拒绝下一轮。坐标系同理。CadQuery默认Z轴向上但生成模型有时会为了所谓“直观”把零件炸到别的方向。规定基准面统一为XY、主视图方向为Z正方向后续不管是出工程图还是接CAM都不用来回转坐标系。4.4 超过8步特征务必拆分大模型生成单个脚本的准确率随特征步数增加急剧下降。一个零件如果包含底板、翻边、凸台、四类孔、倒角脚本很容易“做到后面忘记前面”。我的经验是单体脚本控制在8个特征以内零件一旦复杂就拆成子件分别生成再导出装配。语言再好、模型再强上下文长度也是有限的别让一个脚本承载太多逻辑。4.5 加一个几何与语义双层校验器编译通过只是第一步几何还要过关。我在前面提到的校验基础上再加一层语义校验把用户描述里的关键参数提取成“约束字典”比如长120、宽80、孔6生成后用包围盒、孔数量、孔距去比对。expected {xlen: 120, ylen: 80, zlen: 8} bbox val.BoundingBox() for k, v in expected.items(): actual getattr(bbox, k) if abs(actual - v) 1: print(f警告: 期望{k}{v}, 实际{k}{actual:.1f})这一步能拦住绝大多数“听错尺寸”的幻觉成本却极低。4.6 把高频约束做成固定提示词片段“同心”“平行”“居中”“等间距”这类工程约束每次让模型现场理解很容易出错。更稳的做法是把它做成模板片段常见工程约束定义 - 同心两个圆形特征共享同一圆心建模时应先点选圆心参考再操作。 - 居中特征平面中心对齐父特征平面中心。 - 阵列孔四角均布孔先做构造矩形再取顶点打孔。把这段固定塞进系统提示词模型输出就会稳定很多。这一步属于“提示词工程里的封装”把工程师的经验固化成可复用的词表。5. 调试自动生成的CAD代码踩坑实录与排查链路即便有了上面这套流程生成模型仍然会犯一些让你哭笑不得的错。下面几个坑我全踩过列出来帮你省时间。5.1 尺寸幻觉直径写成半径最典型的用户描述“直径10的孔”模型在CadQuery里生成circle(10)。CadQuery的circle参数是半径不是直径。最后模型直径20安装螺柱直接穿不进去。排查链路并不复杂看到孔位相关的体积/包围盒对不上先不要怀疑整个模型优先检查涉及circle、radius、diameter的地方。建议在系统提示词里加一条“CadQuery的circle()和hole()都使用直径值不要使用半径”或者反过来统一用circle(直径/2)。我实测加这一条后孔径类错误下降非常明显。5.2 零厚度与自相交几何合法性失效第二条高频异常是isValid()返回False。常见诱因是抽壳操作配合圆角顺序不对先抽壳后圆角或者对过薄壁抽壳再倒角容易产生退化面。另一个诱因是叠加特征时选了错误的参考面导致几何体出现自相交。碰到这类问题我的排查链路是先用val.isValid()定位是在生成后立即失效还是导出前失效如果立即失效就把脚本里的特征序列逐一注释掉二分定位到坏特征再让LLM只重写那一段。不要试图让LLM“看着整个坏模型自己修”——信息越多它越容易改坏。5.3 交付格式的坑STL与STEP的用途界定很多初学者只导出STL就发给供应商结果加工端一脸茫然。STL是三角网格预览格式没有单位语义、没有特征树、没有精度信息。真要进CAM、做模流、搞装配干涉检查必须交付STEP。实操中我两步都导STL用来快速进切片软件看长什么样STEP用来进专业CAD做尺寸标注和加工评估。校验阶段也建议优先跑STEP的导入导出验证而不是只盯着STL看渲染好看。5.4 一条建议的排错路径当自动生成的模型不合格时不要从头重跑按下面的路径排查效率最高先看编译日志语法错误还是接口错误让LLM根据报错重写脚本。再看合法性isValid()是否为True不是则二分定位坏特征。再看尺寸一致性包围盒和体积是否和描述吻合不吻合检查单位与直径/半径。最后看装配环境把STEP放进总装配里检查干涉这一步往往能发现“单独看很完美装上去打架”的问题。6. 按场景选路线而不是按热度选路线最后聊一个方向性问题。现在一提Text-to-CAD好像什么都能生成但实际工程里没有银弹。不同场景对“稳定性、可编辑性、美观度”的权重不同选型组合也应该不同。6.1 四条路线横向对比路线工程可用性可编辑性生成速度适合场景LLM参数化脚本高高中机械零件、外壳、支架、模具初稿专用模型直接输出B-rep高中中学术界探索、特定领域深度优化文本生成网格再逆向拟合低低快概念展示、3D打印摆件、视觉原型零件库检索参数修改高高很快标准件变体、既有产品系列衍生6.2 我实际会采用的选型组合如果是做消费级3D打印摆件、手办原型我会直接选“文本转网格”路线图个出图快反正打印前也要修边修面如果是做五金件、外壳、装配件的结构设计我只会用“LLM参数化脚本”路线并且坚持生成后做合法性校验如果是企业里的标准件库管理我会优先检索和参数修改因为零件的家族体系往往比凭空生成更重要。我没有把“专用B-rep生成模型”放进日常工作流主要是这类模型的公开可用性和接口生态还不够成熟偶尔试验可以依赖它还太早。这个判断可能过半年会变但就目前而言脚本生成路线是投入产出比最高的。我在实际项目里已经形成了一套固定的半自动流程产品经理给出口头需求后先转成一页“结构化需求单”写明功能、安装关系、关键尺寸、加工方式然后交给模型生成第一版CAD脚本跑编译反馈循环再导STEP切片看截面。常规钣金件、塑料外壳类的设计初稿基本控制在半小时内就能拿到一个能评审的模型。最后再分享一个小技巧把“同心”“平行”“阵列孔距”这类高频约束写成固定提示词片段比每次让模型临场理解要稳定得多。整体说一句Text-to-CAD真正的价值不是让你彻底不建模而是把“建模体力活”交给机器把设计师的时间还给真正需要经验的判断。模型输出变稳了你才有余力去处理装配、工艺和成本——那部分才是工程师不可替代的地方。