ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

一文读懂text-to-CAD:从自然语言到可编辑三维模型的技术路径与实操指南

一文读懂text-to-CAD:从自然语言到可编辑三维模型的技术路径与实操指南

1. text-to-CAD 是什么,以及它为什么值得关注

text-to-CAD,字面意思就是“用文字描述直接生成CAD模型”。不管你是机械工程师、产品设计师,还是刚开始学建模的学生,只要你曾经对着空白的草图界面发呆,或是为一个简单零件反复调整拉伸、倒角、阵列这些参数,就一定理解这个工具的价值:把脑子里那个“大概长什么样”的模糊想法,直接变成可编辑的三维模型。

这个方向之所以在近两年爆发,核心原因是多模态大模型和参数化建模技术终于走到了一个交汇点。以前我们聊AI辅助设计,更多是自动出图、拓扑优化这类偏仿真和分析的工作;现在不一样了,语言模型可以直接输出OpenSCAD脚本、CadQuery代码、STEP文件生成指令,甚至是FreeCAD的宏命令。也就是说,AI不再只是“帮你算”,而是真的“帮你建”。

适合关注这个方向的人,我认为主要有三类。第一类是经常需要快速验证结构方案的工程师,脑子里有想法,但不想花半小时建一个临时模型;第二类是做非标自动化或工装治具设计的朋友,很多零件其实就是“一个板子上面开几个孔、折几道弯”这种模式化结构,用自然语言描述绰绰有余;第三类是教育领域的老师和学生,text-to-CAD 能极大降低学习CAD的门槛,让学生先学会用工程语言描述需求,再反过来理解建模逻辑。

我自己测试了大半年这个方向,包括各类开源模型、商业API、本地部署方案,还尝试在工作流里加入自动校验环节。这篇文章不是一篇综述,而是把我实际跑通过、踩过坑的经验整理出来,尤其会讲清楚几条技术路径的差异、提示词该怎么写、生成的模型如何检查修正,以及哪些常见问题会被很多人忽略。

2. 技术路线拆解:四种实现路径与选型逻辑

2.1 文生代码:最务实、最可落地的路线

所谓文生代码路线,简单说就是让大语言模型输出一段CAD相关的脚本,然后用对应的解析器或CAD内核去执行这段脚本,生成几何实体。

目前在工业级和创客圈子里,最主流的几个目标语言是OpenSCAD、CadQuery、build123d,以及FreeCAD的Python API。为什么选它们而不是直接生成一个二进制的STEP文件?因为脚本本身就是参数化描述,用户拿到脚本之后随时可以改尺寸、改数量、改位置关系,这才是CAD的核心价值。你让模型输出一个死板的网格文件,那只是“一次性造型”,对工程迭代没有意义。

以OpenSCAD为例,它的语法接近函数式编程,非常适合让语言模型生成。你描述“一个长100宽60高10的板子,中心位置挖一个直径30的圆孔”,模型大概率会输出类似这样的代码:

difference() { cube([100, 60, 10], center = true); cylinder(r = 15, h = 12, center = true); }

这段代码的逻辑其实很直白:先创建一个立方体,再用一个圆柱体做差集运算,得到孔洞。OpenSCAD的模型树就是一段可读的文本,这让大模型非常容易学习和推理。

CadQuery则是基于Python的另一个思路,它更接近传统CAD的“特征建模”逻辑。比如同样的零件,CadQuery写法是这样的:

import cadquery as cq result = ( cq.Workplane("XY") .box(100, 60, 10) .faces(">Z") .workplane() .hole(30) )

这个代码在语义上更贴合工程师的思维:创建一个长方体,选中顶面,打一个直径30的孔。我用下来感觉,CadQuery生成的模型边界质量更好,圆孔、倒角这类特征的几何精度更高,更适合要拿去加工或仿真的场景;OpenSCAD胜在简单直接、渲染快、生态成熟。

从选型角度,我建议遵循一个原则:如果你的核心需求是“快速看形状、做概念示意”,OpenSCAD足够;如果生成的模型后续要进CAM、有限元分析或者和别的外部零件装配,优先考虑CadQuery。因为CadQuery最终基于OCCT内核,导出的STEP文件在工程软件里兼容性更好。

2.2 文生参数:把特征模板和语言模型结合

第二种路线不是让模型直接写代码,而是让模型输出“参数表”。你事先在CAD软件里定义好一个参数化模板,模板里有若干关键尺寸和特征开关,模型只负责根据自然语言描述把这些参数填上。

举个例子,我做过一个法兰盘的模板,变量包括法兰外径、内孔直径、螺栓孔数量、螺栓孔分布圆直径、法兰厚度。当用户输入“设计一个DN50的法兰,4个螺栓孔”,模型就输出一套结构化参数,程序再把这些参数写进模板,生成最终模型。

这种路线的优势非常明显:可控性极强。模型不需要理解复杂的建模操作,只需要做好语义到数值的映射。哪怕模型生成的参数有偏差,也不至于出现几何拓扑错误。缺点是泛化能力受限,换一个新类型的零件就得多写一套模板。

实际项目中,文生参数路线往往是和文生代码路线搭配使用的。对于结构高度标准化的零件族,用模板;对于非标结构,让模型直接写代码。判断标准其实很简单:这个零件有没有规律可循?如果“结构是稳定的,只是尺寸变化”,模板化;如果“每次结构都不同”,代码生成。

2.3 文生几何:关注度最高的前沿方向

文生几何是最像“AI生成图片”的路线,也就是让扩散模型或生成对抗网络直接生成三维几何数据,比如点云、体素场、隐式曲面或者三角网格。

许多相关论文展示的结果确实令人惊艳,输入一句话,模型直接产出精细的网格模型。但你一旦把这类模型生成的几何数据往CAD软件里放,问题就来了:网格模型在CAD里只是一个“实体”,没有特征树,没有参数,不能改孔的位置,不能改圆角半径,最多只能转换成一个无法编辑的B-rep实体。这在快速原型和游戏资产制作里够用,但在工程制造领域基本是鸡肋。

我可以负责任地说,如果目标是“让AI在工程场景里辅助设计”,那文生几何不是当前的最优解。倒不是说它没有意义,而是生成精度和可编辑性这两道坎,短时间内跨不过去。至少在我测试的模型中,还没有哪个能在“倒角到底是C2还是C3、孔距公差要求”这种细节上给出准确反馈。

2.4 混合路线:代码生成 + 视觉校验 + 参数反馈

我在实际项目中走得比较多的是混合路线。第一步用大模型生成CAD脚本;第二步自动执行脚本,渲染出预览图;第三步把预览图喂回给多模态模型,让模型自己检查尺寸是否合理、比例是否协调、特征位置是否对,必要时自动修改提示词或脚本,再重新生成。

这个闭环里面最关键的是第二步到第三步的衔接。你需要在本地搭建一个自动渲染服务,OpenSCAD和CadQuery都支持命令行离线渲染。比如OpenSCAD可以这样:

openscad -o preview.png model.scad --camera=0,0,0,45,0,30,200

--camera参数向量里依次是视野中心和相机角度,这一行命令的作用就是无头模式下渲染一张固定视角的PNG图。CadQuery可以直接导出SVG或者通过cq-editor的离线模式导出PNG。有了图片,你就可以调用视觉语言模型接口,自动审视生成的几何是否符合预期,然后把修改意见再编译成新的提示词。

这套流程我用下来的感受是,虽然每次生成和校验的时间成本比“直接出代码”高,但整体的成功率提升非常多。单独让模型写代码,可能生成10次有6次能跑通,但只有3次尺寸合理;加上视觉校验闭环之后,10次里有7次都是直接可用的结果。这个差距在项目里的价值非常大。

3. 完整实操:从自然语言到可用CAD模型的完整流程

3.1 环境准备和模型选型

如果你只是随便试玩,直接使用主流的商业对话模型就能跑通OpenSCAD生成。但要做成一条可靠的生产线,我强烈建议自建服务。原因很简单:你需要批量调用、需要固定版本保证输出风格稳定,还需要在脚本出问题时自己定位。

本地部署方面,我的推荐是先用7B级别的小模型跑通完整链路,比如Qwen2.5系列或Llama 3.1 8B的量化版本,然后在真实效果不满意时再切换到更大参数规模的模型。为什么先从小的开始?因为这个任务对模型的“代码能力”和“空间想象能力”要求其实没有那么高,OpenSCAD这种简单的脚本语法,7B模型经过简单的微调就能胜任。与此同时,小模型的推理速度更快,迭代调试的成本也更低。

在调用模型之前,最好先在系统提示词里明确几个约束。第一,要求模型只输出纯代码,不要解释、不要额外注释,这样方便程序自动解析;第二,告诉模型OpenSCAD的坐标约定和常用函数名;第三,禁止使用某些容易出错的语法,比如polyhedron的顶点顺序如果错误会导致形面撕裂。这些约定能极大降低后续的解析难度。

3.2 提示词设计:如何把想法翻译成模型能理解的语言

提示词是text-to-CAD成败的第一道分水岭。很多人觉得“我都说了要一个架子,为什么模型生成的尺寸不对”,问题几乎都出在描述方式上。

我总结了一个“四要素”提示词模板:

  • 物体类型:明确告诉模型要生成什么,例如“L型支架”。
  • 整体尺寸:给出长宽高或关键尺寸,例如“总高100毫米,宽度80毫米,厚度10毫米”。
  • 特征明细:逐一罗列孔、槽、倒角、阵列等特征,并给出位置关系,例如“在竖直面板中心开一个直径25的圆孔”。
  • 约束条件:特殊要求,例如“所有外露锐边倒C1角”“底部四个角开安装孔,直径6.5”。

一个实际例子,我经常用来测试模型的一个提示词是这样的:

生成一个L型支架,水平面板尺寸为80x60毫米,厚度8毫米。 竖直面板高度为120毫米,厚度8毫米。 两个面板交接处内侧加一个加强筋,加强筋为三角形,厚度6毫米,高15毫米。 水平面板上均匀分布四个直径6.5毫米的安装孔,孔中心距边缘10毫米。 竖直面板顶部中心开一个直径20毫米的通孔。 所有锐边倒C1角。

你可能会注意到,这里有大量的具体数值。这是关键中的关键。语言模型不像人一样有“差不多”的直觉,你说“大一点的孔”,它可能理解为直径30毫米,也可能理解为直径8毫米,完全取决于训练数据里的统计偏好。唯一可靠的做法是把所有尺寸数值化。

另一个技巧是“先整体后局部”。让模型先生成主体轮廓,再通过后续提示词或人工检查添加细节。一次提示词里塞太多要求,模型容易顾此失彼。如果生成结果不尽如人意,不要重写整段提示词,而是针对差异部分做增量修正,例如“把两个安装孔改为4个,沿长边均布”。

3.3 从描述到脚本:一次典型的生成过程

拿上面这个L型支架来演示一次从文字到脚本的完整过程。

我先用OpenSCAD做第一版生成。把上面那段提示词发给模型,经过一次对话之后,得到的脚本框架是:

$fn = 32; // 水平面板 translate([0, 0, 0]) cube([80, 60, 8]); // 竖直面板 translate([0, 0, 8]) rotate([0, 90, 0]) cube([120, 8, 8]); // 加强筋 linear_extrude(height = 6) polygon([[0, 0], [15, 0], [0, 15]]); // 安装孔(后续差集) ...

这里第二轮细节生成出现了几个问题:第一个是加强筋没有摆放到交界处,第二个是竖直面板的方向不对。这非常典型——模型理解了整体结构,但在局部定位上会出偏差。

我的处理方法是直接手动修正坐标,而不是重新生成。在脚本里把加强筋移动到正确位置,加上旋转和偏移。OpenSCAD的好处是代码改起来很直接,甚至可以写一个Post-Processor自动识别常见错误模式。

修正完成之后,执行渲染命令生成预览图,确认四要素都满足,然后导出STL或STEP文件。整个流程大约5分钟,其中大部分时间花在渲染预览和检查上。

3.4 自动校验:尺寸不对等于白干

对生成结果做自动校验,是text-to-CAD工作流里最应该重视但大多数人忽略的环节。没有校验,你根本不知道模型生成的孔距到底是20毫米还是30毫米,也不知道壁厚是否均匀。

校验方案按照精细程度分为三级。第一级是脚本静态检查,用正则表达式和语法分析器抓取所有数字参数,和预期范围比对。第二级是几何分析,用CadQuery或trimesh读取生成的模型,测量关键尺寸。第三级是渲染图视觉校验,用多模态模型“看”图判断比例是否协调。三级校验逐层递进,可以拦截绝大多数问题。

以CadQuery为例,一个简单的尺寸检查脚本是这样的:

import cadquery as cq # 读取生成的结果 result = cq.importers.importStep("output.step") # 检查模型整体包围盒 bbox = result.val().BoundingBox() x_len = bbox.xlen y_len = bbox.ylen z_len = bbox.zlen print(f"尺寸检查: X={x_len}, Y={y_len}, Z={z_len}") # 如果尺寸超出预期范围,报警 if not (70 <= x_len <= 90): print("警告: X方向尺寸超出预期范围")

实际项目里,我会把这些校验规则整理成一张配置表,每个零件对应一组阈值,校验结果自动写入日志,再决定是否进入人工审核环节。

3.5 输出格式选择:STL、STEP还是原生脚本

到最终交付阶段,输出格式的选择取决于你的下游需求。只做3D打印验证,STL就够了;需要进一步编辑修改,必须保留脚本或STEP;需要进装配体做干涉检查、出工程图,STEP是稳妥选择;需要在FreeCAD或者SolidWorks里继续操作,CadQuery脚本可直接转换,OpenSCAD脚本则要导入后再重建特征树。

我在这一步踩过一个坑:STL导出之后发现网格质量太差,圆孔变成多边形,表面有明显的棱线。解决办法是在OpenSCAD里提高$fn精度变量,或者在CadQuery的导出API里设置线框偏转角度。对于需要展示和装配的模型,$fn=64通常能达到视觉和性能的平衡点。

另外一点,对于有经验要求的交付场景,比如CNC加工,不要直接拿STL切片编程,最佳实践是导出STEP文件,然后配合CAM软件重新拾取加工特征。这能极大减少加工中的意外,也让工艺人员在模型上做针对性的修改。

4. 常见问题与排查技巧实录

4.1 模型生成出来了,但结构不对怎么办

结构不对,是最常见的挫败点。模型理解了大概形状,但开口方向、孔的位置、加强筋的连接关系都有问题。

我的经验是:先区分“语义错误”和“几何错误”。语义错误是模型没听懂你在说什么,比如把“水平面板上开孔”理解成“竖直面板上开孔”;几何错误是模型理解对了,但计算出的坐标偏移错了。前者靠改进提示词解决,后者靠脚本局部修正解决。

改进提示词的时候,有一个非常实用的技巧:增加“位置锚点”。在描述每个特征时,都明确指出相对于哪个参考面、哪个边的位置。不要只说“在面板中心”,要说“在水平面板的上表面中心,以底面为基准向上偏移8毫米”。这种锚点描述法对模型定位的帮助是极大的,我实测下来能把位置类问题的发生率减少一半以上。

如果提示词已经写得很精确,结构还是不对,那就要怀疑是不是模型版本本身的问题。不同的模型在OpenSCAD的“空间坐标系变换命令”上的掌握程度差异很大。建议准备一组标准测试集,包括拉伸、旋转、差集、阵列、镜像五种基本操作,每次更换模型之前先跑一遍测试集,心里有底再上线。

4.2 生成速度慢和批量处理的优化方案

本地部署小模型跑单条指令通常需要几秒到十几秒,这在交互场景下勉强可接受,但批量生成几十个零件的时候就很难受。

我的优化思路有三个方向。第一,结合并行推理框架加载模型,比如用amll或者带有continuous batching的推理服务,让多个请求同时进入,吞吐量能提升3到5倍。第二,提示词里少用长文本,因为输入token和输出token都会影响推理延迟,把提示词模板压缩到精简格式。第三,引入缓存机制,同一组参数重复生成时直接复用历史结果,不做重复推理。

我也尝试过把全家桶部署在有GPU的服务器上,用API形式对外提供生成服务,配一个队列系统管理任务,效果很理想。对个人用户来说,没必要一步到位搞大规模集群,一台24G显存的机器足够支撑小团队的日常使用。

4.3 孔洞与装配关系频繁出错的深层原因

最后说一个我在实际测试中观察到的深层问题:语言模型对“孔”和“配合关系”的理解普遍偏弱,因为它本质上没有物理世界的直觉。

举个例子,你让模型在管道法兰上生成6个螺栓孔,分布圆直径100毫米。模型常常会输出均匀分布但缺少基准角定位的结果,也就是说它知道“均匀分布”,但不知道“第一个孔应该在哪个角度”。在真实装配中,基准角决定了法兰的对中,一旦错位,整个装配就废了。

解决这个问题,我的方案是引入“特征模板约束”——把常见的标准特征定义成结构化模板,建模时优先调用。比如螺栓孔分布,我预先定义了这样一个段模板:

for (i = [0 : 360 / n : 360 - 360 / n]) { rotate([0, 0, i]) translate([pcd / 2, 0, 0]) cylinder(r = hole_r, h = plate_h + 1, center = true); }

提示词里只需要告诉模型“使用标准螺栓孔模板,数量6,分布圆直径100毫米”,模型输出时直接引用这个模板名,细节由程序拼接完成。这个“模板优先”的思路,让我在涉及孔洞、螺柱、倒角等标准特征时,出现的几何错误数量大幅下降。

5. 我对这个方向的一些体会和扩展想法

整套text-to-CAD工作流跑下来的最大感受,是不能把大模型当作“全能的建模师”,而应该把它当作一个“理解能力很强的实习生”。它需要你给清晰的任务描述,需要通过代码这种媒介来交互,做完任务之后需要检查,错了需要纠正。这个类比帮助我调整了很多预期,也不再追求“一次完美生成”,而是把重心放在“快速迭代、高效修正”上。

对于想上手实践的朋友,我建议从OpenSCAD开始,因为它的语法最简单、生态最成熟,遇到问题容易搜到答案。先跑通“生成-渲染-检查”的闭环,再逐步引入CadQuery和更复杂的模板体系。不要一上来就追求本地大模型,先用API接口验证业务价值,再考虑成本和部署。

这个方向后续还有几个我很看好的扩展点。一个是“设计意图理解”——从工程图纸、手绘草图甚至口头描述中自动提取参数,生成CAD模型;另一个是“装配体生成”,从自然语言描述整个机构的运动关系,自动生成多个零件的装配模型;还有“设计规范嵌入”,把企业的标准件库、制造工艺约束写进提示词或检索增强数据库里,让生成结果天然符合规范。

这些扩展点目前都还在快速演进中,如果你也在这个方向探索,我建议多动手实测,少追热点词汇,真实项目和真实需求是最好的试金石。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进