Text-to-CAD实战:从自然语言到参数化CAD模型的完整生成流程

发布时间:2026/10/8 11:08:34
Text-to-CAD实战:从自然语言到参数化CAD模型的完整生成流程 text-to-cad这个方向我最近上手折腾了一个多月说实话第一眼看觉得就是个炒作概念真做下来才发现里面藏着大量和“模型生成”不太一样的坑。所谓text-to-cad往简单说就是拿一句自然语言比如“生成一个M8六角头螺栓螺杆长度25毫米螺纹螺距1.25”让系统输出一个真正可编辑、可加工的三维CAD实体而不是一张效果图。这个能力往小处说是省掉建模师重复画零件的时间往大处说它能让机械设计、产品结构验证、自动化夹具出图这些流程彻底换个玩法。这篇内容我不打算写什么“趋势、理念”之类的空话就结合我自己的实测项目把思路拆解、选型原因、完整跑通步骤、还有踩过的坑从头到尾摆出来给正在琢磨这个方向的工程师和设计师做个参考。1. 项目概述与核心思路拆解1.1 text-to-cad 到底解决了什么先理解痛点。传统CAD建模无论是SolidWorks、Creo还是FreeCAD本质上都是靠人手动操作拉一个草图、拉伸、打孔、倒角、阵列。这个过程对熟练工程师来说并不算慢但换成非设计岗的产品经理、工艺工程师或者刚入行的新人每改一次尺寸都要从头查树、改草图和约束效率非常捉急。text-to-cad想做的事是把“几何构造过程”压缩成“描述意图”的过程让机器直接帮你把操作项排好。在我这个项目里我选了个特别典型的工程零件法兰盘。输入一句话“一个外径120毫米、内径50毫米、厚度15毫米的法兰周围均布6个直径8毫米的螺栓孔孔中心圆半径80毫米”。传统建模要先把法兰主体拉出来再画孔、阵列、切除起码一两分钟用text-to-cad的思路目标是模型直接在内存里“长”出来然后一键导出STEP或STL拿去加工和做仿真。这件事关键点不是“模型长得像”而是生成出来的结果必须能进CAM软件必须满足公差和加工语义也就是要有可编辑的参数特征而不是一堆三角网格。1.2 为什么这个方向值得自己动手做一版很多人觉得现在AI生成3D模型不是挺多了吗像文本生成点云、文本生成网格模型开源的一抓一大把。但真拿去车间问一句“能出加工图吗”基本都摇头。因为那些模型大多停留在“Mesh级别”或者“体素级别”看着像却没法倒角、改孔距、标注尺寸、关联工程图。而text-to-cad的实义在于“CAD”三个字母意味着输出必须是B-rep边界表示或者参数化特征树带有工程语义。所以我自己判断这条路目前靠谱的做法不是去训练一个端到端的大模型输出几何体而是用“LLM生成参数化脚本 脚本驱动几何内核”的组合拳。简单说让大语言模型理解自然语言描述把它翻译成CadQuery或者FreeCAD Python脚本代码再用CAD内核去执行脚本、生成真正的带特征的可编辑模型。这就像你雇了一个懂CAD操作的助手你说一句话他替你把建模操作做完最后把工程文件和参数树都交给你。2. 技术原理与方案选型解析2.1 两条主流路径端到端生成 还是 LLM参数化脚本我调研下来业界和开源社区做text-to-cad基本在做两类事情。第一类是端到端生成输入文本经过大模型直接预测三维表示比如点云、占用场、网格或隐式神经场再后处理成CAD模型。代表工具有OpenAI的Point-E、谷歌的DreamFusion、以及一些针对CAD优化的变体。这类方法优点是对任意描述都“敢”生成但缺点也明显输出网格很难转为干净的参数化实体经常出现面片破损、不可封闭、没有特征树离工程可用差得远。第二类就是我自己项目采纳的“LLM参数化脚本”路径。大模型不去直接猜几何体而是负责把文本描述转成一段CAD建模程序。我用CadQuery作为几何内核它本身就是用Python写参数化模型的底层的OCCT内核OpenCascade负责布尔运算和精确实体生成。LLM只做代码生成不直接和几何打交道所以生成的模型天然是参数化的可以随意改尺寸实体质量完全由CadQuery保证。这两条路怎么选核心看你要什么。如果目标是快速刨一个AI生成3D内容的演示选第一条如果目标是做可加工、可复用的结构件选第二条。我在项目里也试过把Point-E生成的网格导入Meshlab重新网格化再想转STEP结果边界表示一团糟修都修不动。白白浪费了两天。2.2 为什么选CadQuery而不是FreeCAD脚本或者OpenSCAD我对比过三种脚本化方案CadQuery、FreeCAD的Python API、OpenSCAD。OpenSCAD用函数式描述几何建模能力全面可它的代码风格是CSG树和工程特征比如倒角、阵列、法兰上的孔结合得不够直接。FreeCAD Python API功能最强但接口太宽大模型容易捏造方法名生成代码的编译成功率明显偏低。CadQuery属于高层封装常用写法是“workplane上画个圆、拉伸、打孔、复制”API语义接近操作习惯对大模型来说更容易猜对。比如前面提到的法兰盘CadQuery的典型写法是先画一个circle然后用workplane和cut打孔再通过polar pattern做阵列。这种写法结构化强错误率低而且最后导出的STEP文件里保留了特征信息。我在实测中把CadQuery的API文档片段喂给模型作为上下文代码能跑的占比比纯FreeCAD高出四成左右。就这一条就值得选它。2.3 模型选型本地小模型还是云端大模型既然让LLM写代码那就得选模型。我这里的硬约束是工程零件描述经常涉及内部细节出于保密考虑不能传到云上所以在公司环境里部署本地模型。最终我挑了Qwen2.5-Coder-7B-Instruct量化为AWQ 4bit用vLLM跑推理显存占用9GB左右一张RTX 3090就够。如果个人玩、不太在意数据隐私用qwen-max或GPT-turbo这类云API效果更好毕竟体量大、编码能力强但对中文工程术语的理解我实测下来还都行常见的“均布”“沉头孔”“螺纹公制”都能准确落到代码里。但这里有个关键认知模型越大不代表最终成功率越高。工程描述里经常有尺寸公差、材质标注、表面粗糙度等信息这些对几何生成没帮助反而干扰模型。我在提示词里就要求模型忽略非几何属性专注尺寸和位置关系这样小模型的输出干净很多。所以选模型的同时更要设计输入的“提示模板”。3. 实操过程与核心环节实现3.1 环境准备与最小依赖安装下面我把完整跑通的方案展开你在Linux或Windows都行我这边用的是Ubuntu 22.04。首先装基础依赖Python版本3.10以上CadQuery库直接pip安装就行pip install cadquery vllm langchainvLLM是给本地模型做推理加速的如果只是试验用transformers或者ollama也能顶上。CadQuery安装完要检查一下OCCT内核是否正常加载import cadquery as cq result cq.Workplane(XY).box(1, 2, 3)这一步能跑通就说明环境没问题。接着处理大模型加载我用Qwen2.5-Coder作为代码生成模型。加载时给vLLM指定gpu-memory-utilization0.85避免显存爆掉。要是你只拿API做验证直接跳到模型调用那步就行。3.2 设计提示模板自然语言到CadQuery脚本模型不是神仙不给定规矩就乱写。我设计的提示模板包括固定上下文、示例代码和用户需求三部分。固定上下文里写了CadQuery的常见用法包括如何设置单位、如何使用workplane。示例代码放一个法兰盘的生成片段告诉模型输出必须包含模型变量名和最后导出STEP。核心模板大概长这样你是一个CadQuery代码生成引擎。请根据用户的零件描述输出完整的CadQuery Python代码代码中必须定义变量final_result并调用exportStep导出STEP文件。只输出代码不要解释。 示例 用户法兰盘外径120毫米内径50毫米厚度15毫米6个直径8毫米的孔孔中心圆半径80毫米。 代码 [示例代码] 用户{用户描述} 代码在这个模板基础上我把用户描述里的尺寸统一规范为毫米把常见的“均布6个孔”这类话术转成“6个孔均匀分布”这样的中性表达模型对均匀分布这种几何语义的把握明显更准。提示词里我还会要求模型先写注释再写代码别小看这步模型写着写着注释就能自己把建模思路捋顺代码错误率会降下来。3.3 从文本到模型的完整调用链下面给出我项目里核心调用链的精简代码这一步是把自然语言丢给LLM拿到CadQuery脚本并执行import cadquery as cq from vllm import LLM, SamplingParams llm LLM(modelQwen/Qwen2.5-Coder-7B-Instruct, gpu_memory_utilization0.85) sampling_params SamplingParams(temperature0.2, max_tokens1500) prompt build_prompt(生成一个M10内六角螺钉螺杆长30毫米螺纹段25毫米头部直径16毫米头部高度10毫米) output llm.generate([prompt], sampling_params) code extract_cad_code(output[0].outputs[0].text) # 执行生成的CadQuery代码 exec_globals {} exec(code, {__builtins__: __builtins__, cq: cq}, exec_globals) final_result exec_globals[final_result] # 导出STEP cq.exporters.export(final_result, output.step)执行结束后可以把STEP文件在FreeCAD里打开检查特征树。有一说一第一次跑通时我挺兴奋的因为生成的M10螺钉头部、螺纹段尺寸完全正确还能在FreeCAD里编辑那根“螺杆拉伸长度”这就意味着AI生成的模型不是死尸体而是带参数的活模型。3.4 后处理与模型有效性检查生成模型不等于收工。工程上绝不能只看一眼“好像对”必须做几何验证。我用Python做三件事检查模型是否封闭、计算体积误差、检查零件是否满足最小壁厚。CadQuery本身就有api可以查询实体的volume但如果模型有非实体比如有多个solid交叉体积会算错。我用GCCGeometry Checker阶段用OCCT的ShapeFix直接修复from OCP.GProp import GProp_GProps from OCP.BRepGProp import BRepGProp_ShapeProperties props GProp_GProps() BRepGProp_ShapeProperties_s(shape).MassProperties(props) print(体积:, props.Mass())如果体积为零或者明显异常我就判断生成的脚本逻辑有问题直接返回大模型重新生成不浪费时间手动修。这个检查逻辑已经写进我的自动化流水线里每生成一个零件先自动验证一遍再进人工复查环节。4. 常见问题与排查技巧实录4.1 模型尺寸不对单位乱成一锅粥这个坑我第一周就踩了。因为我给的提示模板里没有明确单位模型一会儿用毫米一会儿用英寸甚至把直径和半径混淆。后来我在用户输入里做了一个固定要求“所有尺寸单位必须是毫米所有尺寸写清楚是直径还是半径”并在提示词里反复强调。这个方法立竿见影。另外我还在代码生成完成后加了一个shell命令把STEP文件里的单位属性读出来万一模型偷偷用英寸直接拦下来。查单位可以用python的steputils工具比手动看模型快得多。4.2 生成的CadQuery代码运行报错怎么让模型学会反悔这是所有LLM写代码都会遇到的问题。我最初的做法是直接把报错信息丢回给模型再生成一次但效果不稳定有时候模型会无限循环。后来我改成“带反馈的再生成”捕获Python异常名、异常行号、错误消息连同原始需求拼成一个新的prompt要求模型“根据报错修正代码只输出修正后的完整代码”。实测下来两轮内修好的概率超过了75%。比如常见的AttributeError原因往往是大模型把CadQuery方法名写错了反馈一轮就改对了。但有个技巧必须说报错里debug信息别全贴回去模型会被无关框架栈带偏。我只提取最后一行异常原因最多加上引起异常的源码行。上下文越短修正效果越好这叫“给模型留空间”也算是LLM应用的经验之谈。4.3 布尔运算失败模型不封闭在生成带孔法兰或者螺纹的时候经常遇到布尔运算失败的问题表现是代码不报错但导出的网格模型在孔的位置有洞或者体积是负值。排查下来很多时候是因为CadQuery的cut操作选错了面或者草图平面和实体延申方向对不上。这时候先不急着改模型把代码中的workplane变量打印出来看看孔的平面位置是否符合法兰盘上表面。还有一招用CadQuery的clean参数在cut前对实体做一次简单清理能消掉不少退化几何。螺纹这类复杂特征如果布尔运算失败可以直接改成在圆柱表面绘制螺纹线再用sweep切出沟槽需求和代码都要调整但别指望一句“生成螺纹”就能一次成功。4.4 常见问题速查表问题现象可能原因排查建议生成模型尺寸成倍偏大单位被识别成英寸强制提示词输入单位mm检查STEP单位属性模型缺孔或孔距不对模型把均布半径当成直径提示词强调孔中心圆半径并在生成后检查坐标代码运行报AttributeError大模型写错CadQuery API名反馈最后一行异常要求以正确API修正实体面积/体积为0草图未封闭或拉伸距离为0检查草图轮廓把拉伸距离改为正数生成模型内部交叉多个实体未执行布尔合并生成后自动运行fuse操作检查固体集合4.5 性能太慢生成一个复杂零件等半天复杂零件特别是带螺纹、带多阵列孔的模型CadQuery执行脚本可能耗时几十秒再加上LLM推理整体响应奔着分钟级去。我在项目里做了两件事优化一是把大模型量化级别从FP16降到AWQ 4bit推理速度提升一倍多精度损失没那么明显二是用CadQuery的cq.cq.exporters.export增量导出先生成一个粗模给预览后台再计算精细STEP。对交互体验来说给用户先看到粗轮廓比干等强太多。渲染预览我直接用的CadQuery自带的积木视图基本能满足快速校验需求。5. 我的实操体会与可扩展方向5.1 把文本描述模板化成功率提升一个台阶做过大量实验下来一个最强心得是别让用户自由输入满满一句自然语言尽量用“填空式模板”。比如“零件类型法兰外径120内径50厚度15孔数6孔中心圆半径80孔直径8”。这种模板化描述能大幅减少歧义也让大模型的输出更稳定。自由描述看起来会“智能”但实际效果会让模型无所适从。与其追求炫酷的自然对话不如把输入规范成机器友好的结构这才是工程落地的正路。5.2 从单个零件走向装配体的思路text-to-cad目前最有价值的延展是做装配体生成。比如“一个基座上面装两个支撑柱柱间距100毫米再用四个M5螺栓固定”。这个逻辑其实可以拆解成几步先让LLM把装配描述切成子零件然后对每个子零件单独生成CadQuery代码最后在FreeCAD里用装配约束把它们组装。我在测试里已经能实现简单的两件套装配关键在于约束描述要精确。每一步都要独立设置命名空间和导出文件名否则后处理时会乱套。这个方向做好了对非标自动化产线设计非常有用因为很多工装结构就是这类标准件堆叠。5.3 与工程图、BOM表的联动价值还有一个被大家忽略的收益因为text-to-cad生成的是参数化模型尺寸、孔位、特征名都是结构化数据这些数据可以直接反哺给工程图和BOM表。我后期写了个扩展把CadQuery模型的特征参数输出成JSON然后自动生成一张带关键尺寸标注的图纸草稿。对非标设备厂家来说前期方案阶段如果能从一句话直接拿到带参数的模型和BOM那个效率提升就不是一点半点了。我在实际测试中也有不顺手的地方比如对复杂曲面、自由曲面造型的东西纯脚本化生成仍然力不从心毕竟那些东西更适合端到端的生成模型。所以我的建议很直接做标准结构件、机加工件、法兰、支架、轴套text-to-cad的可靠度已经能进工作流做消费级产品外观设计还得再等等。下一步我琢磨的是把文本、参考图片、现有STEP模型三个输入融合到一起先理解参照物再做参数化变体让AI能真在现有产品系列上做改型设计。这个坑如果趟出来我再单独写一篇。