text-to-cad 实战:用 CadQuery 将自然语言生成 STEP/GLB/STL 模型 1. 从一段文字到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个说法我脑子里蹦出来的画面是对着屏幕敲一句“给我画一个 80×60×10 的法兰盘中心开 30 的通孔四角打 M6 沉头孔”然后 CAD 软件自己把模型建好、把工程图出完。这个画面在几年前还属于科幻范畴但最近一两年随着大模型在代码生成和结构化数据生成上的能力外溢它已经变成了一个可以动手落地的工程方向。所谓 text-to-cad本质上是把自然语言描述转换成CAD 可识别的几何数据最终产出 STEP、GLB、STL 这类通用三维格式文件让下游的建模、渲染、3D 打印、仿真环节可以直接消费。这件事的价值在哪里我举个自己踩过的场景。做非标设备设计的时候经常要画大量“标准件变体”——不同孔径、不同长度、不同法兰规格的支架、连接板、垫块。这些东西结构高度相似只是参数不同但每改一次就要在 CAD 里重复一遍拉伸、打孔、倒角、阵列的操作。一个熟练工一天也就出十几个变体还容易改错尺寸。如果能把“描述”直接变成模型哪怕只覆盖 60% 的常规件效率提升也是数量级的。这就是 text-to-cad 最直接的需求来源参数化、批量化、低门槛的模型生成。它适合谁来用我梳理了一下大致三类人受益最明显。第一类是机械、钣金、建筑领域的工程师他们懂设计意图但不想把时间耗在重复建模上第二类是产品经理、创客、3D 打印爱好者他们有想法但不会用 SolidWorks、中望 CAD 这类工具希望能用说话的方式把东西“说”出来第三类是做 AI 应用开发的程序员他们想把 CAD 生成能力集成到自己的平台里比如做一个在线的零件定制页面。这三类人的诉求不一样但底层都指向同一件事把几何建模的门槛从“会软件”降到“会描述”。需要先泼一盆冷水text-to-cad 目前不是万能的。它擅长的是规则明确、参数清晰的零件比如板类、轴类、法兰、简单壳体对于复杂曲面、自由造型、装配体干涉这些现阶段还很难靠一句话搞定。所以我在后面的内容里会重点讲清楚它的能力边界在哪里以及怎么用工程化的方式把它用稳。你如果抱着“一句话生成一台发动机”的期待那大概率会失望但如果你把它当成一个“参数化建模的加速器”它会非常香。2. 整体技术路线拆解从一句话到 STEP/GLB/STL 的完整链路2.1 为什么不能直接让大模型“画图”很多人第一反应是既然大模型能生成图片那直接让它生成三维模型不就行了这个思路在工程上走不通原因很实在。图片是二维像素网格而 CAD 模型是带拓扑关系的边界表示B-rep它记录的不只是形状还有面、边、顶点之间的连接关系以及每个面的数学定义平面、圆柱面、NURBS 曲面等。大模型直接“猜”出来的顶点坐标往往面与面接不上、法线方向乱、实体不封闭导进 CAD 里要么报错要么变成一个没法编辑的“死网格”。所以工业界和开源社区的主流做法是把任务拆成两步先让大模型生成结构化的建模指令代码或参数再由几何内核去执行这些指令。这就像你不可能让一个翻译直接口述一篇论文的排版但你可以让他输出 LaTeX 源码再由编译器排版。大模型负责“理解意图 生成代码”几何内核负责“精确执行”。2.2 三条主流技术路线对比我把目前能跑通的方案归成三类各有各的适用场景下面这张表是我自己实测后的总结路线核心思路代表工具输出格式适合场景上手难度代码驱动型大模型生成 CadQuery/OpenSCAD 代码内核执行CadQuery、OpenSCAD、build123dSTEP、STL参数化零件、批量变体中参数映射型预定义模板 大模型填参数自研模板库 LLMSTEP、GLB标准件、系列化产品低网格生成型直接生成/检索三维网格文生3D模型、网格重建STL、GLB概念展示、3D 打印摆件低但精度差我个人的建议是如果你要做的是能用于生产、能继续编辑的模型优先选代码驱动型。因为 CadQuery 这类库生成的模型是真正的 B-rep 实体导出 STEP 后可以在 SolidWorks、中望 CAD 里继续改尺寸、加特征。而网格生成型出来的 STL虽然 3D 打印能用但想改一个孔的直径基本等于重做。2.3 为什么 STEP、GLB、STL 要分清楚这三个格式经常被混着用但它们的定位完全不同选错了会在下游环节吃大亏。STEP是工程领域的“通用语言”它保存的是精确的 B-rep 几何文件里记录的是数学曲面而不是三角面片。所以 STEP 文件可以无损地导入各种 CAD 软件继续编辑是 text-to-cad 面向工程应用时的首选输出。缺点是文件体积相对大且不同软件对 STEP 版本AP203、AP214、AP242的兼容性有差异。STL是 3D 打印和快速预览的“老黄牛”它只保存三角面片没有颜色、没有材质、没有拓扑。优点是几乎所有切片软件、渲染器都认它缺点是精度靠面片密度堆圆孔会变成多边形而且没法反向编辑。我见过太多人拿 STL 去 CAD 里想改尺寸结果发现全是碎面这就是没搞清格式定位。GLB是面向可视化、Web 展示和游戏引擎的格式它把几何、材质、贴图打包成一个二进制文件加载快、体积小。如果你要做的是一个在网页上让用户旋转查看的零件展示页GLB 是最优解。但它同样不是精确几何不适合回传 CAD 做工程修改。提示text-to-cad 的输出格式选择取决于下游是谁在用。给工程师改图用 STEP给 3D 打印机用 STL给网页展示用 GLB。不要指望一个格式通吃。3. 核心实操用 CadQuery 搭一套能跑的 text-to-cad 流程3.1 环境准备与依赖安装我选 CadQuery 作为主力工具原因是它基于 OpenCASCADE 几何内核生成的模型是真正的 B-rep 实体导出 STEP 质量稳定而且 Python 生态友好方便和大模型 API 对接。下面是我在 Windows 和 Linux 上都验证过的安装方式。# 建议用 conda 建独立环境避免和系统 Python 冲突 conda create -n text2cad python3.11 conda activate text2cad # 安装 CadQuery官方推荐用 conda-forge 渠道 conda install -c conda-forge cadquery # 如果要用大模型接口装 openai 或对应 SDK pip install openai装完之后先跑一个最小验证确认几何内核正常import cadquery as cq # 画一个 80x60x10 的板中心开 30 通孔 result ( cq.Workplane(XY) .box(80, 60, 10) .faces(Z).workplane().hole(30) ) cq.exporters.export(result, test_plate.step) print(导出成功)这段代码跑通说明你的环境没问题。如果报错找不到 OCCT 相关库八成是 conda 渠道没配对重新用conda install -c conda-forge cadquery装一遍基本能解决。3.2 让大模型生成建模代码的提示词设计这是整个流程里最关键的环节。大模型不是天生就会写 CadQuery 的你得把“规矩”讲清楚。我反复调试后总结出一个比较稳的提示词结构核心是给约束、给示例、给输出格式。你是一个 CAD 建模代码生成助手。请根据用户的自然语言描述生成 CadQuery Python 代码。 要求 1. 只输出可执行的 Python 代码不要解释。 2. 代码必须以 import cadquery as cq 开头。 3. 最终模型赋值给变量 result。 4. 所有尺寸单位为毫米。 5. 如果描述缺少关键尺寸按常见工程惯例取合理默认值并在代码注释中标注。 6. 孔、倒角、阵列等特征要明确写出。 示例 用户画一个 100x50x8 的板四角打 M5 通孔孔中心距边 10mm 代码 import cadquery as cq result ( cq.Workplane(XY) .box(100, 50, 8) .faces(Z).workplane() .rect(80, 30, forConstructionTrue) .vertices().hole(5) )这个提示词里“缺少尺寸取默认值并注释”这一条特别重要。实际使用中用户很少会把所有尺寸说全比如“画个法兰盘”你不给默认值模型就生成不出来给了默认值至少能出一个可用的初版用户再改。3.3 完整链路代码从文字到 STEP 文件把大模型调用和 CadQuery 执行串起来核心逻辑就是一个“生成-执行-导出”的循环。下面是我实际在用的简化版脚本import cadquery as cq from openai import OpenAI client OpenAI(api_key你的key) SYSTEM_PROMPT 你是一个 CAD 建模代码生成助手...上面那段提示词 def text_to_cad(user_input, output_nameoutput): response client.chat.completions.create( modelgpt-4o, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input} ], temperature0.2 ) code response.choices[0].message.content # 去掉可能的 markdown 代码块标记 code code.replace(python, ).replace(, ).strip() # 在受限命名空间中执行避免污染 local_ns {cq: cq} exec(code, local_ns) result local_ns[result] # 导出三种格式 cq.exporters.export(result, f{output_name}.step) cq.exporters.export(result, f{output_name}.stl) print(f已导出 {output_name}.step 和 {output_name}.stl) return result # 测试 text_to_cad(画一个外径 100、内径 40、厚度 15 的法兰盘沿圆周均匀分布 6 个直径 8 的螺栓孔分布圆直径 75)跑通之后你会得到一个 STEP 文件用中望 CAD 或 SolidWorks 打开就是一个可以继续编辑的实体。这里有个细节temperature我设成 0.2因为建模代码需要稳定复现不需要“创意”温度高了同样的描述每次生成的尺寸可能不一样这在工程上是大忌。3.4 参数化模板比纯生成更稳的方案纯靠大模型生成代码偶尔会翻车比如把hole()的参数顺序搞错或者忘记闭合工作平面。对于高频使用的零件类型我的做法是预置参数化模板让大模型只负责“填参数”不负责“写逻辑”。这样稳定性大幅提升。def make_flange(outer_d, inner_d, thickness, bolt_count, bolt_d, pcd): 法兰盘参数化模板 result ( cq.Workplane(XY) .circle(outer_d / 2) .circle(inner_d / 2) .extrude(thickness) .faces(Z).workplane() .polarArray(pcd / 2, 0, 360, bolt_count) .hole(bolt_d) ) return result然后让大模型从用户描述里抽取outer_d、inner_d这些参数输出 JSON再由程序调用模板。这条路线的容错率高得多因为几何逻辑是人工验证过的大模型只做它最擅长的“语义理解”。我实测下来模板法在批量生成系列化零件时成功率接近 100%而纯生成法大概在 70% 到 85% 之间波动。4. 实操中的坑与排查我踩过的那些雷4.1 模型导出后打不开或显示为空这是最常见的问题表现是 STEP 文件能生成但导入 CAD 软件后什么都没有或者提示“无效实体”。原因通常有三个一是模型不是封闭实体比如用shell或offset时参数不对导致面片之间有缝隙二是工作平面选错模型生成在了奇怪的位置三是布尔运算失败比如两个实体没有真正相交却做了cut。排查方法我总结成一套顺序先在 CadQuery 里打印result.val().isValid()如果是False说明实体本身有问题再用result.val().Volume()看体积是否为正体积为负或为零基本可以判定几何异常。定位到具体特征后把复杂操作拆成单步执行逐个确认。注意CadQuery 里.hole()默认是通孔如果你想要盲孔必须用.cboreHole()或先extrude再cut。我见过有人用.hole()做盲孔结果把整个板打穿了。4.2 大模型生成的代码语法对但几何错这种情况最隐蔽代码能跑模型也生成了但尺寸完全不是你要的。比如你说“孔中心距边 10mm”它给你理解成“孔半径 10mm”。根源在于自然语言本身有歧义而大模型倾向于“猜一个合理值”。我的应对策略是在提示词里强制要求输出参数表。让大模型在生成代码之前先把它理解的参数列出来格式如下参数确认 - 板长100mm - 板宽50mm - 板厚8mm - 孔径5mm - 孔中心距边10mm这样你一眼就能看出它有没有理解错。如果错了改提示词重新生成比改代码快得多。这个习惯我坚持了很久能省掉大量返工。4.3 STL 精度不够导致 3D 打印变形STL 是三角面片圆孔会被离散成多边形。如果面片密度不够打印出来的孔就是“多边形孔”装配时螺栓塞不进去。CadQuery 导出 STL 时可以控制精度cq.exporters.export( result, output.stl, tolerance0.01, # 线性偏差越小越精细 angularTolerance0.1 # 角度偏差弧度制 )tolerance0.01意味着曲面偏离理想形状不超过 0.01mm对于大多数 3D 打印场景够用了。但要注意精度调太高文件会急剧变大一个法兰盘可能从几百 KB 涨到几十 MB。我的经验值是普通零件用 0.05精密配合件用 0.01展示用 0.1 就够。4.4 常见问题速查表问题现象可能原因排查动作解决方案STEP 导入后为空实体不封闭检查 isValid()拆分特征修复布尔运算尺寸与描述不符语义歧义输出参数表确认改提示词明确单位与基准STL 圆孔变形面片精度低查看 tolerance 设置调小 tolerance 至 0.01代码执行报错API 用法错误看 traceback 定位行用模板法替代纯生成生成速度慢模型复杂度过高统计特征数量分步生成后布尔合并GLB 材质丢失未指定颜色检查导出参数用color参数显式指定5. 能力边界与扩展方向text-to-cad 现在能做什么、不能做什么5.1 当前能稳定覆盖的零件类型经过我这段时间的实测以下几类零件用 text-to-cad 生成的成功率和质量都比较理想板类零件带孔、槽、倒角、圆角、轴类零件阶梯轴、带键槽、带螺纹、法兰与盘类均布孔、沉头孔、中心孔、简单壳体矩形壳、圆形壳、带加强筋、型材截面拉伸件。这些零件的共同特点是特征规则、参数有限、几何逻辑清晰正好是大模型擅长处理的。反过来说自由曲面、有机造型、复杂装配体、带运动约束的机构目前还很难靠一句话生成。你如果要做的是一个仿生外形或者汽车覆盖件text-to-cad 现阶段帮不上大忙还是得靠传统建模或逆向工程。5.2 从单零件到装配体的扩展思路单零件跑通之后自然会想能不能生成装配体。我的做法是分零件生成 位置约束描述。比如“一个由底板、立柱和顶板组成的支架立柱在底板四角顶板盖在立柱上”可以拆成三次生成每次输出一个 STEP再用代码按坐标装配。base make_base_plate() column make_column() top make_top_plate() assembly ( cq.Assembly() .add(base, namebase, loccq.Location(cq.Vector(0, 0, 0))) .add(column, namecol1, loccq.Location(cq.Vector(20, 20, 10))) .add(top, nametop, loccq.Location(cq.Vector(0, 0, 60))) ) assembly.save(assembly.step)这条路目前还需要人工介入坐标计算但已经能把装配体的建模时间压缩不少。未来如果大模型能直接理解“四角”“居中”“贴合”这类空间关系词自动化程度会更高。5.3 和现有 CAD 工作流的衔接text-to-cad 生成的东西最终还是要回到工程师熟悉的工具里。我的衔接方式是STEP 作为中间格式导入中望 CAD 或 SolidWorks 后继续加工程特征。比如生成的初版法兰盘导入后可以再加倒角、加中心孔、改材料属性然后出工程图。这样 text-to-cad 负责“从 0 到 1”传统 CAD 负责“从 1 到 100”各司其职。有一点要提醒不同 CAD 软件对 STEP 的解析有差异。我遇到过 CadQuery 导出的 STEP 在某个软件里圆角丢失的情况换一个 STEP 版本比如从 AP214 换成 AP242就正常了。所以导出时最好留一个版本切换的选项遇到兼容问题可以快速试。6. 一些实操心得与后续可以玩的方向我个人在实际操作中的体会是text-to-cad 这件事七分靠工程约束三分靠模型能力。很多人一上来就追求“全自动”结果被各种边界情况搞得焦头烂额。更务实的做法是先把高频零件做成模板让大模型只做参数抽取把稳定性拉到 95% 以上再逐步放开自由度。这个思路和做任何自动化系统都一样先收敛场景再扩展能力。另外一个小技巧是建立自己的零件描述词典。比如“沉头孔”对应cboreHole“通孔”对应hole“圆角”对应fillet“倒角”对应chamfer。把这些术语和 CadQuery API 的映射固定下来写进提示词里大模型生成的代码准确率会明显提升。我维护了一份大概 40 个词条的映射表日常够用了。后续可以扩展的方向我觉得有两个比较有意思。一个是结合尺寸标注图让用户上传一张带尺寸的草图大模型识别尺寸后生成模型这比纯文字描述信息量大得多。另一个是批量变体生成给定一个基础模型和一组参数表自动生成几十个变体并导出这对做系列化产品的团队非常实用。这两个方向我都在试等跑顺了再单独整理出来分享。