ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Text-to-CAD技术解析:从自然语言到参数化可制造模型

Text-to-CAD技术解析:从自然语言到参数化可制造模型

1. Text-to-CAD到底要解决什么问题

1.1 从“生成一张图”到“生成一个能用的零件”

这两年AI生图、生视频都快被玩烂了,但真正让机械、硬件圈的人眼前一亮的,还得是Text-to-CAD。这名字很直白:把自然语言描述直接变成CAD模型。但别被“生成”两个字骗了,它和Stable Diffusion画出来的那张“扳手渲染图”完全是两码事。图像生成追求的是“看起来像”,而Text-to-CAD追求的是“能进加工、能装配、能改参数”。一个从图片生成出来的扳手模型,你没法给它标注M8螺纹、没法导出STEP进数控机床、更没法在装配体里约束它和螺母的配合关系。而Text-to-CAD的目标,就是从“我要一个六角头螺栓,公称直径8毫米,螺距1.25,杆长40毫米”这句话,直接落地成一个水密、尺寸可查、可编辑、可制造的三维实体模型。

我最早接触这个方向是在GitHub上看到几个开源项目,当时第一反应是“这不就是把自然语言翻译成OpenSCAD脚本嘛”,后来深入用了一圈才发现,这个领域水挺深。它表面上是自然语言处理问题,本质上是一个“几何约束求解 + 参数化建模 + 工程语义理解”的复合问题。大模型要把一句口语化的需求,拆解成一系列建模指令:先画哪个草图、往哪个方向拉伸、倒多大的圆角、特征之间怎么布尔运算。中间任何一步漏了,出来的东西可能就是废件。

1.2 和传统参数化建模、AI生图的本质区别

CAD软件本身早就有了参数化建模能力,你在SolidWorks里画一个拉伸特征,改改直径值,模型自动更新。但传统工作流里,所有参数都得人手动定义,建模过程还是得一步一步点鼠标。Text-to-CAD想干掉的是这个“从脑子里的想法到参数化模型”之间的翻译成本,它直接替你把这个翻译过程做了。换句话说,传统CAD是“你告诉软件怎么画”,Text-to-CAD追求的是“你告诉软件要什么”。

它和AI生图的区别就更好理解了。生图模型输出的是像素矩阵,精度只有分辨率那么高;而Text-to-CAD输出的要么是带拓扑信息的网格Mesh,要么是程序化建模脚本(OpenSCAD/CadQuery/FreeCAD宏)甚至STEP这类边界表示(B-rep)实体。其中只有后两类能真正进入工程流水线。所以我现在判断一个Text-to-CAD工具靠不靠谱,就看它导出的是什么格式、模型能不能被参数化再编辑。如果导出来只有STL网格,那它顶多算个“3D打印草稿器”,还算不上CAD工具。

1.3 谁最需要它,哪些场景已经能用起来

我观察下来,目前最典型的用户有这么几类。第一类是非标机械设计工程师,天天在画螺丝、支架、法兰这一类重复度高的零件,有了Text-to-CAD之后,写一段话就能把基础体拉出来,剩下的时间全花在关键配合面精修上。第二类是创客和硬件产品原型开发,大部分时候只需要一个能验证装配关系的粗模型,不需要每根圆角都完美,这时候Text-to-CAD的快速出稿能力非常香。第三类是教学场景,让学生用自然语言描述一个零件,然后对比模型生成结果和理想几何的差异,反而能帮他们建立更好的空间几何直觉。

我记得有个焊接车间的老师傅和我说过,他手底下实习生画图慢,但他口头能把一个支架的形状、板厚、加强筋位置说得清清楚楚。这种“口语化需求”恰好是Text-to-CAD最擅长接住的输入形态。当然,现阶段它还没到“全自动替代工程师”的程度,更准确的说法是:它是建模初稿阶段的加速器,是概念设计和详细设计之间的一个脚手架。

2. 核心实现路线:到底有哪些流派在卷

2.1 生成式几何路线:端到端吐Mesh

这一派把Text-to-CAD当成一个三维生成问题,本质上是把图像生成的扩散模型或自回归模型搬到3D空间。代表性的工作有OpenAI的Point-E、Shape-E,后来的MeshAnything、TRELLIS也属于这一类。输入一段文本,输出体素、点云、隐式神经场或者直接生成Mesh网格。优点是自由形状表现力强,特别适合做雕塑、玩具、有机曲面这些“长得随意”的东西,不需要严格的工程约束。

但缺点对工程师来说几乎是致命的。网格模型通常不是水密的,可能有孔洞、退化面、自相交,壁厚也不均匀,而且完全不带参数化信息。你拿一个这样的STL进SolidWorks,首先得做曲面逆向,把网格拟合成B-rep实体,这个活本身就够折腾半天了。再加上生成精度通常在毫米级就不错了,而机加工零件的公差要到微米级,所以这个流派目前更多用在概念展示和3D打印粗模上,离真正CAD工作流还有距离。

2.2 程序化建模路线:让大模型写建模代码

这是我现在最看好的方向,也是社区里玩得最疯的路线。核心思想很直接:CAD模型本质上是参数和操作的组合,而参数和操作恰好可以用代码来描述。所以不让大模型直接生成几何体,而是让它生成OpenSCAD脚本、CadQuery Python代码或者FreeCAD的宏命令,然后由CAD内核去执行这些脚本,得到真正的参数化实体模型。

这条路最大的优势是“生成结果可解释、可编辑”。大模型写的脚本里每一个变量、每一个特征操作都是看得见的,你不需要重新建模,改个数字就能更新整个零件。比如生成一个齿轮,脚本里通常会有模数、齿数、压力角这些参数,你只要把齿数从20改成30,重新执行一次脚本,齿轮就自动变大了。这比生成一个Mesh再手动重建要高效得多。

另一个隐性的好处是,CAD内核帮你兜底了部分几何合法性。OpenSCAD和CadQuery底层用的是CSG布尔运算和参数化特征,只要最终几何能成功输出,至少说明没有大的拓扑错误。不像Mesh生成,看着漂亮但可能根本没法切片。

2.3 混合路线:文本+草图/模板参数匹配

还有一类方法并不完全依赖大模型自由发挥,而是让大模型做“参数抽取”,把用户的自然语言映射到预先定义好的参数化模板上。比如系统里预置了一个法兰盘模板,里面有外径、内径、螺栓孔数量、孔分布圆直径这些参数,大模型只需要从文本里提取数值和选项即可。这种方法生成结果的稳定性极高,因为模板本身经过了工艺验证,不会出现奇怪的几何。

缺点是覆盖面窄,只能处理模板库里的那几类零件,遇到稍微不规则的形状就无能为力了。我自己的经验是,这类工具适合企业内部做标准化零件库的快速选用,比如常用钣金支架、管道法兰、电机安装板。把历史图纸的参数做成模板,再用一个小的语言模型做入口,老工程师报一组参数就能出三维模型,效率提升非常明显。

2.4 三条路线怎么选:一张对比表说明白

对比维度Mesh生成路线程序化脚本路线模板参数匹配路线
代表工具Point-E、MeshAnything、TRELLISCodeLlama/ChatGPT + OpenSCAD企业内部定制、BricksCAD
输出格式OBJ/STL/GLTF(网格).scad/.py/.FCStd(代码+实体)STEP/原生CAD格式
可编辑性差,需逆向翻模强,改参数重跑即可中等,只能改模板内参数
几何精度毫米级由脚本数值决定,可达微米级模板决定,最稳定
自由形状能力强中等偏弱只支持模板形状
工程可制造性弱,需大量修复强,可直接进CAM/3D打印强,工艺验证过
适合场景概念展示、雕塑、手办机械零件、非标件、快速原型标准化零件选型

如果你做的是手办或者文创产品,Mesh生成路线足够用了;如果你要画的是一个要上机床的零件,直接把脚本路线焊死,别犹豫。

3. 实操笔记:从零跑通一个最小可用的Text-to-CAD流程

3.1 环境准备和工具选型

我自己搭的一套最小可用环境很简单:一台装了Ubuntu的机器(Windows也行,命令稍微不同)、Python 3.10、OpenSCAD命令行版、CadQuery库,再加上一个大模型入口。大模型我建议两条腿走路,一条是商用API,比如GPT-4或Claude,生成复杂代码的能力强,适合搞不定的疑难零件;另一条是本地开源模型,比如CodeLlama 70B或者Llama 3 8B的量化版,跑常见零件足够,而且免费、没有隐私问题。实测下来,8B模型在简单零件上的成功率在六成左右,70B能到八成以上,但显存要求高,家里小主机跑不起来,只能靠量化压缩。

这里有个容易被忽略的坑:模型参数大小不是唯一决定因素。上下文长度同样关键。生成OpenSCAD代码时,一个中等复杂度零件可能需要几百行代码,模型要把前面的变量声明和特征操作都记住,如果上下文窗口太小,写到后面就会自己“发明”变量,导致语法错误。所以我优先选上下文长度至少8K的模型,能到16K更好。

3.2 提示词怎么写:决定生成质量的最重要因素

Text-to-CAD的提示词和写作文提示词完全是两码事。我不能只给模型一句“给我一个法兰盘”,那它十有八九会生成一个没有任何螺栓孔的圆盘。我踩了无数坑之后总结出一个结构化的配方,按顺序包含五个要素。

第一是明确零件类别和标准。不是只写“法兰”,要写“DN50 PN16带颈平焊法兰,按GB/T 9112标准”。这样模型才知道该有哪些特征和大致尺寸比例。第二是给出关键尺寸的绝对数值,不要用“大一点”“厚一点”这种模糊词。要写成“外径165mm,内径61mm,厚度18mm,8个M16螺栓孔均布在直径125mm的圆上”。所有尺寸必须带单位,并且统一用毫米。第三是指出特征的操作顺序,先哪个后哪个。比如“先拉伸出法兰主体,再挖中心孔,最后打螺栓孔”。这能显著减少模型把特征遗漏的概率。第四是明确禁止项,比如“不要倒角”“不要圆角”“不允许出现悬空特征”。第五是规定输出格式,比如“只输出OpenSCAD代码,不要解释”。

一个我常用的模板长这样:

生成一个M8六角头螺栓的OpenSCAD脚本。 要求: - 所有尺寸单位统一为毫米 - 公称直径8mm,螺距1.25mm,螺纹长度30mm,总杆长40mm - 六角头对边尺寸13mm,头厚5mm,头部倒角0.5mm - 螺纹用简化锯齿圆柱近似即可,不需要精确牙型 - 实体必须水密,不得有悬空、自相交几何 - 只输出代码,用```scala代码块包裹,不要任何额外文字

这个配方在大多数模型上都能稳定复现。核心原因是,大模型没有三维空间想象能力,它只是在做模式匹配,你把需求拆得越结构化,它能匹配到的训练样本就越相关。

3.3 生成结果的几何合法性校验

跑通这个流程最关键的一步不是生成代码,而是校验生成出来的几何对不对。我基本每次都写一段Python脚本,用trimesh库做快速检查,截几个关键指标:模型是否水密(is_watertight)、体积是否大于零、是否存在重复顶点、三角形是否退化。水密性不过关的模型,后面不管进3D打印切片还是CAM仿真,都会在预处理阶段直接爆错。

还有一个我特别强调的习惯:在OpenSCAD代码里手动加一个“基线尺寸断言”。比如让模型在每个关键特征后面都加一行assert(d > 0);,用参数检查挡住异常值。大模型生成的代码经常会出现“直径算出来是负数”“拉伸高度趋近于零”这种离奇错误,加了断言之后,至少能在执行阶段快速暴露问题,而不是生成一个看起来正常实则体积为负的“幽灵体”。

import trimesh mesh = trimesh.load('output.stl') print('水密:', mesh.is_watertight) print('体积/mm^3:', mesh.volume) print('三角形数量:', len(mesh.faces)) print('包围盒:', mesh.bounds)

如果水密性为False,我一般先看是不是STL导出参数的问题,OpenSCAD默认网格化精度低的时候容易产生微小裂缝,把$fn值调大到64或者128再重新导出,八成问题能解决。如果仍然不水密,那就是生成脚本里的几何操作本身有缺陷,需要回炉改提示词。

3.4 导出与下游生产流程对接

校验通过只是第一步,真正落到生产还有导出这一步。目标不同,导出策略完全不同。如果是要3D打印,直接导出STL就够了,打印切片软件基本都认STL。如果是要进CAM做数控加工,最好让用户拿STEP文件,STEP里带精确的B-rep曲面数据,CAM软件才能生成正确的刀路。OpenSCAD本身不直接支持导出STEP,但可以通过CadQuery重新建模或者用FreeCAD命令行方式转换。这也是为什么我更倾向于直接用CadQuery作为生成目标,它底层基于OpenCascade内核,原生支持STEP导出。

CdQuery生成螺栓的示例非常简单:

import cadquery as cq bolt = (cq.Workplane("XY") .polygon(6, 13/2).extrude(5) # 六角头 .faces(">Z").workplane() .circle(8/2).extrude(40)) # 螺杆 cq.exporters.export(bolt, "bolt.step")

这个脚本生成的STEP文件放进SolidWorks、Fusion 360都能直接打开,而且所有特征都是参数化的,后续改直径、改长度都非常方便。整个流程走下来,从自然语言到STEP实体文件,耗时基本在一分钟以内,这个速度在传统建模方式下是不可想象的。

4. 高频问题与排查技巧实录

4.1 生成“纸片模型”或悬空几何

这是个发生率极高的翻车现场。模型看起来有轮廓,但实际是个零厚度纸片,或者由一堆互不相连的曲面拼成。原因通常是模型把拉伸操作写成了纯粹的平面轮廓生成,或者布尔并集操作里两个子体根本没相交。代码层面检查方法是看OpenSCAD控制台有没有输出“ERROR: The given mesh is not closed”之类的警告。更有效的做法是在提示词里固定一句“所有实体必须使用linear_extrude或extrude生成,完成后执行一次全体布尔并集”,这能大幅降低悬空几何的概率。

4.2 尺寸和单位混乱

大模型的训练语料里英美工程资料占大头,所以它特别爱生成英寸单位或者干脆不写单位。而OpenSCAD本身是没有单位的,全靠人约定俗成,CadQuery默认又是毫米,一旦混用,生成的零件尺寸能差25.4倍。我的排查经验是先生成一段简单的提示词“使用毫米作为唯一单位,所有尺寸必须是大于0的十进制数”,把尺寸单位先固化下来。然后检查生成脚本里的数值数量级,一个M8螺栓的杆径如果出现0.315,那基本就是英寸直径8mm换算过来的,直接改成8.0就行。

4.3 长文本描述下细节丢失

人类描述一个零件的时候习惯先说整体再说局部,但大模型在生成代码时,注意力机制会导致它更关注开头和结尾的token,中间那些细节经常被忽略。典型的情况是,用户说“法兰盘外径100,内径50,八个孔,螺栓分布圆直径80”,模型最终只画了一个没有孔的圆盘。解决办法是把描述拆成两轮对话:第一轮先让模型“列出这个零件应该包含的全部特征和对应尺寸”,输出一份特征清单;第二轮再让它基于清单去生成代码。特征清单本身就是一种强制注意力集中的机制,效果比单纯靠模型自觉好得多。

如果是特别复杂的装配体,我建议不要一次性生成所有零件,而是拆成单个零件分别生成,再通过装配约束组合起来。CadQuery的Assembly机制或者OpenSCAD的module嵌套都能干这个活。理论上一次生成也是可行的,但实践中踩坑的概率会随零件数量指数上升。

4.4 生成了“看着对,实际没法造”的零件

这是最隐蔽的坑。几何完全合法、水密、尺寸也对,但壁厚只有0.3毫米、内腔有无法排屑的凹角、悬空部分超过45度没有支撑。这类问题代码检查根本查不出来,因为几何逻辑没错,错在制造工艺性上。

我现在的做法是在提示词里预置一段“可制造性约束”:

- 所有壁厚不得小于1.5mm - 避免悬空角度大于45度的结构 - 所有内角必须留有>=1mm的圆角 - 螺栓孔和轴孔预留0.2~0.4mm配合间隙 - 不得出现刀具无法进入的封闭内腔

这些约束相当于强制模型把DFM(面向制造的设计)规则写进代码里。说实话,它做不到完美,但至少能挡掉七八成愚蠢设计。剩下那两成太复杂的工艺判断,只能通过人工审查和仿真软件兜底。

4.5 模型生成的代码有版权和许可证风险

这个容易被忽视。很多开源模型训练的时候用了大量GitHub代码库和CAD模型库,这些数据的许可证各不相同。如果只是个人DIY,用不用都无所谓;但如果是商业项目,直接把模型生成的代码塞进产品线,可能引来许可证合规问题。我的建议是商用之前,查一下所用模型的训练数据来源和输出条款。大厂API通常有明确的输出使用授权,自部署的开源模型则要看它对应的模型卡和数据卡。这块花半小时确认清楚,能省掉后面无数扯皮。

5. 我的实用技巧和一些个人体会

做了这么久Text-to-CAD的实践,我最深的体会是:别把它当成一个“全自动出图机器”,要把它当成一个“特别擅长聊需求的设计师助理”。它的强项是快速把口语需求转化成结构化特征和参数化模型,弱项是理解制造约束和复杂装配逻辑。所以我的工作流从来不是“一句话生成一个完美零件”,而是“第一句话生成一个初稿,然后逐轮细化”。每次只让模型改一个维度或者加一个特征,成功率高得惊人。

另外有一个小技巧非常值得分享:与其直接让大模型写完整代码,不如先让它生成一个“尺寸参数表”。比如描述一个带座轴承,让它先输出“轴承内径、外径、宽度、座孔距、螺栓孔直径”这些参数值对齐表。拿到参数表后你再手动或者让模型套一个标准的代码模板,这样做出来的模型几乎不会出现尺寸内部矛盾。原因也很好理解,直接写代码的时候,模型要同时协调几十个变量的数值和位置,很容易就陷入局部混乱;先出参数表相当于给变量们排了个队,后面的代码生成只是机械地填入,难度完全不在一个数量级。

最后一个体会关于行业影响。我始终觉得Text-to-CAD不会取代工程师,但会彻底改变工程师的时间分配。以前画图占了六成时间,思考只占四成;以后可能反过来,思考和决策占六成,画图交给机器。这不是天方夜谭,实际上在我最近接触的几个非标自动化项目里,已经有同事靠这套流程把前期方案阶段的出图时间从两天压缩到两个小时。模型负责把脑中的模糊概念快速实体化,工程师负责判断这个实体到底对不对、能不能造、怎么造最经济。这种分工模式,我觉得才是这个工具真正的价值。

RELATED READING

延伸阅读

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