这个方向我从去年开始盯到现在,text-to-cad算是把“一句话变成三维模型”这件事真正推进到了可落地阶段。它跟之前那些文生图完全不同,不是给你一张看起来像那么回事的渲染图,而是直接输出可以编辑、可以加工的参数化CAD模型。简单说,你输入“带四个安装孔的方形底座,中心有一个直径20毫米的圆孔”,系统会给出一个包含草图、拉伸、打孔操作的完整建模过程,导出的STEP文件能直接拖进SolidWorks或者Fusion 360里改参数。
这玩意儿解决的痛点很直接:传统CAD建模的学习成本高,一个稍微复杂的零件,新手光是搞明白草图约束就要折腾几天;对非设计岗的工程师来说,想快速验证一个结构方案,又不想求人画图。text-to-cad能把这个过程从“几小时”压缩到“几秒”,哪怕生成结果只是粗胚,也能极大缩短前期沟通的循环。现在这个方向特别适合三类人关注:一是做AI应用开发、想找新场景的工程师,二是机械设计或产品设计领域想提效的从业者,三是做3D打印和创客项目的玩家——用文字描述就能拿到可切片打印的模型,这种体验一旦用上就回不去了。
1. 整体设计拆解:text-to-cad到底在做什么
1.1 核心思路:把三维建模变成“文本翻译”任务
要理解text-to-cad,先要放下一个思维定式:CAD模型不是一堆三角面片,而是“操作序列”。你在SolidWorks里画一个零件,本质上是在执行一串带参数的指令——画一个矩形、标注尺寸、拉伸20毫米、在某个面上再画圆、切除。这些指令带有明确的先后顺序和几何参数,就像一段程序。
所以text-to-cad的技术路线就变得清晰了:把自然语言描述映射成一段CAD操作序列。这个词法层面的转换,比传统的文生图更接近“编译”而非“绘画”。一段中文描述“这是一个长100、宽50、高20的平板,四角有直径8的通孔”,对应的CAD操作序列大约是:新建草图→画矩形(起点0,0,尺寸100×50)→拉伸20→选择上表面→画四个圆(位置分别靠近四个角)→切除贯穿。
这个思路我第一次看到的时候就觉得方向对了,因为它解决了一个关键问题:输出是可解释的。你用AI生成一个stl网格文件,出来的模型不能改、不能编辑,工艺上基本是死路;但生成操作序列,每一个步骤都是结构化的参数,用户拿到手可以随便改尺寸、删除特征、重排顺序。这也是text-to-cad区别于普通“文本生成三维网格”方案的核心价值。
1.2 两条技术路线的取舍:生成式与检索式
现在做text-to-cad,主要有两条路:一条是纯生成式,用大模型直接预测CAD操作序列;另一条是检索式,先根据文本找一个最相似的现有模型,再做局部修改。
纯生成式的优势在于能做“无中生有”,文本描述里包含的特征组合方式只要在训练数据里出现过,模型就能组合出新的结果。劣势也很明显:对罕见结构的泛化能力有限,而且训练需要高质量的“文本-CAD序列”配对数据,数据成本相当高。
检索式的思路更讨巧,先从库里找到语义最接近的模型,再把文本作为修改指令,让模型在已有模型上做局部编辑。这个方案在小规模场景下非常好用,尤其是企业内部积累了大量历史图纸的情况——大多数新设计往往是对旧设计的改版,做检索增强能稳定输出可用度很高的模型。我在实际项目中更倾向于混合路线:先检索候选,如果相似度不够高再走生成式兜底,既能保证大部分场景的精度,又不至于让用户等太久。
关于这个方向,之所以难做,核心在于CAD操作序列的“离散长尾分布”——常用的操作(拉伸、切除、打孔)就那么几十种,但参数组合空间是连续的,同一个圆柱体,可以用“画圆+拉伸”实现,也可以用“旋转体”实现,这就给模型学习带来了歧义。所以数据预处理时统一操作表示、尽量消除多义性,比单纯增加数据量更有效。
2. 关键技术拆解:数据、模型与训练细节
2.1 数据从哪来:MLCAD数据集与“文本-序列”配对
所有做text-to-cad的人,几乎绕不开MLCAD数据集。这套数据从Onshape公开模型库中整理而来,包含大约17万组“CAD模型+文本描述”的配对,每个模型的描述词通常是一段简要英文,比如“bracket with two holes”这种级别。它不像图片描述那么丰富,却保证了文本和模型之间的对应关系是可靠的。
拿到MLCAD之后,第一件事不是直接训练,而是做“序列化”,就是把CAD模型转成一串格式化的操作指令。常见工具链是:用CadQuery或Build123d这类程序化建模库,把b-rep几何信息反解为草图、拉伸、旋转、镜像等高层操作,然后输出成类似Python脚本的指令序列。这一步是整个流程里最容易出问题的地方,反解出的序列能不能被CAD软件重新执行、参数是否完整、特征是否可编辑,都取决于这一环的质量。
如果你没有MLCAD,也可以自建数据,思路是“逆向”:用CAD插件批量记录建模过程,把每一步操作连同参数导出成JSON,同时让设计师写一句功能描述。这个方法得到的数据对特定业务场景更友好,缺点是成本高、节奏慢。我的建议是前期先拿公共数据跑通流程,等验证出效果再投入资源做私有数据。
2.2 文本编码与CAD序列生成:转化全过程拆解
模型结构上,text-to-cad基本沿用“编码器-解码器”框架。文本侧用预训练语言模型(比如T5、BERT或者更新的LLM底座)提取语义向量,CAD序列侧用Transformer解码器做自回归生成。这和你熟悉的大语言模型在机制上没有本质区别,只是词典被换成了“CAD操作+参数”的离散集合。
参数怎么处理是个细节问题。CAD操作里的尺寸、坐标通常是浮点数,比如“拉伸20.5毫米”,如果直接转成离散token,精度会受限于词典大小。社区里目前有两种做法:一种是量化到固定精度(比如保留一位小数,有65536个候选值),把数值映射成token;另一种是延续文本生成的思路,把数值当作文本直接生成,依靠解码器预测连续数字序列。实测来看,“数值文本化”的方法更稳,尤其对整数尺寸,模型学得又快又准。
整个生成过程可以这么理解:输入“一个M6螺丝的垫圈”这样的描述,编码器把它理解成“尺寸不大、环形、厚度薄”的语义;解码器一步步吐出一串token,先画一个外径18的圆,再画一个内径6.5的圆,然后拉伸2毫米。每一步的token选择都受到前文约束,最后得到的指令序列就是可编辑的建模脚本。
3. 完整实操:从零跑通一个text-to-cad项目
3.1 环境准备:依赖、硬件与模型选择
实际动手之前,先说硬件底线。text-to-cad虽然不像训练大语言模型那样吃天价显存,但也不是CPU能轻松扛住的。我的经验是:推理阶段,一张24GB显存的消费级显卡(比如RTX 4090或A6000)足够跑主流的开源模型;训练阶段,全量微调至少需要4张80GB的A100/H100,但如果用LoRA这种参数高效微调方案,一张24GB卡也能训得动小规模底座模型。
环境依赖建议按下面的组合来装,这是一套经过验证的搭配:
- 操作系统:Ubuntu 20.04/22.04,记得把驱动装好,推荐535或更新的版本
- Python环境:3.10以上,不建议用系统自带Python,直接用conda建虚拟环境最省心
- 深度学习框架:PyTorch 2.1以上,配合CUDA 12.x
- 语言模型底座:Hugging Face Transformers库,选T5-base或者更大规模的Flan-T5作为编码器
- CAD内核:CadQuery或OpenCASCADE,用于执行生成的指令序列并导出STEP文件
安装完依赖后,先把开源项目拉下来跑一遍自带的示例,看是否可以正常生成。我见过不少同学卡在环境阶段,CUDA版本不匹配、Python包冲突、CadQuery的依赖没装全,这些问题排查起来其实挺费时间,但一次搞通后面就顺了。
3.2 训练与推理的关键参数
当你准备开始训练自己的模型时,下面的参数设置可以直接作为起点参考。需要先说明,这些数值来自社区常见的开源实践与我的实测经验,不同数据规模下可能需要微调。
先看训练侧的参数。序列长度建议设为512,覆盖大部分中等复杂度零件的指令长度;batch size看你显存余量,24GB卡上设8~16比较安全,再配合梯度累积达到有效batch size 32即可。学习率不宜太大,建议在5e-5到1e-4之间;如果用的是LoRA,学习率可以放宽到1e-4到3e-4。优化器选AdamW,权重衰减按0.01设置。训练时开启混合精度,能把显存占用直接砍掉40%以上。损失函数方面,基础的交叉熵损失就能跑通,但在后期可以加一点“几何约束”辅助损失——对序列中出现的坐标数值做约束,让生成结果在几何上更合理。
推理侧的参数同样重要。采样温度设到0.1~0.3可以保证输出稳定,因为CAD序列不像自然语言那样容许多样性,输出必须是精确的操作指令;用beam search比用随机采样更合适,beam width设为4到8之间比较均衡,太小容易出错,太大会拖慢速度。此外,做推理时建议给CAD操作序列加一点“语法约束”:在每一步解码时,只允许模型吐出合法的下一个操作类型,这个逻辑写起来不难,但能显著减少无效序列——我在早期版本里曾经一晚上生成200个模型,有一半因为语法错误无法导入CAD软件,加上约束之后错误率降到5%以下。
3.3 生成结果的后处理:从指令序列到可编辑模型
模型推理完成后,你拿到的是一段CAD操作序列(通常表现为JSON或Python风格的结构化输出)。这一步还没完,后续要把它输入CadQuery执行,生成真正的几何体,然后导出成STEP或STL格式。
我的建议是导成两个格式:STEP格式用于后续在专业CAD软件里继续编辑;STL格式用于快速查看和3D打印。要注意的是,CadQuery生成的STEP文件放到SolidWorks里打开时,通常默认是“智能特征”模式——也就是能识别并保留建模历史树。这一步能否成功直接决定了“可编辑性”是否成立,当你看到特征树里有草图、拉伸、切除这样的节点,说明整个流程闭环了。
后处理阶段我遇到过的最大的坑是单位不统一。CadQuery默认是毫米,一些生成模型在推理时把坐标当作英寸处理,导入CAD后发现尺寸差25.4倍。后来我在指令序列里显式加入了一个全局单位字段,所有尺寸后处理时统一转换为毫米,问题就消失了。另一个经验是:导出STEP文件前,先做一次“实体校验”,看是否能检测到完整闭合、无非流形边,这个校验能帮你过滤掉大部分无效生成结果。
4. 常见问题与排查心得:用的时候才懂得坑在哪
4.1 训练不收敛:先查数据,再查模型
训练text-to-cad时,遇到loss不降或者忽高忽低的情况,大概率不是模型的问题,而是数据预处理出了岔子。首先检查的是“文本-序列”对是否对齐——MLCAD数据集的原始格式可能和你的预处理代码期望的格式不一致,解码的时候错位一条记录,整个训练就乱了。
其次是操作序列的分词方式。CAD语言里的token如果用空格简单切分,会把“circle(10,20)”这样的整体当一个词,模型根本学不到结构。正确做法是让分词器能够识别操作名、参数分隔符和数值符号,把“circle”和“(10,20)”分开,让模型逐步学会“看到操作名→输出参数”的模式。我建议直接按字符级BPE处理CAD序列,实测比按词切分效果好很多。
最后考虑模型本身的因素。如果你用的是大规模底座模型但只在小数据集上微调,loss容易在一个平台期死活下不去。这时换成更小的底座模型或者加大dropout反而能改善。我在实践中发现,Flan-T5-base在十几万条数据上的表现,比直接用7B级模型更稳定,因为底座太大,数据量不够,模型根本没有充分学习的机会。
4.2 显存溢出:混合精度与序列切分是两条路
训练时显存溢出,几乎是每个人都会遇到的。最直接的解决办法有三个:开混合精度bf16/fp16、减小batch size配合梯度累积、把序列长度从1024降到512。如果这三板斧都用上了还OOM,那就要从模型侧下手了——比如给编码器加一层梯度检查点,牺牲一点训练速度换取显存空间。
推理时OOM也是常见现象,尤其是当beam search的beam width设置过大,同时batch里塞了几个长序列的时候。我建议推理时动态调整batch size:先算一下最长序列的显存开销,用它来反推合理的batch大小,而不是盲目填满显存。
还有一个容易忽略的问题是CUDA Memory Fragmentation,也就是显存碎片化。长时间训练后,虽然总显存看似足够,但无法分配出一整块连续空间。遇到这种情况不要重启训练,先把pytorch的cuda caching allocator释放一下,或者设置PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True来减少碎片,基本都能解决。
4.3 模型生成结果打不开:八成是序列语法问题
生成结果的“不可用”,几乎是text-to-cad项目里最高频的投诉,具体表现为:STEP文件无法在CAD软件里打开、打开后是空壳、或者模型出现严重几何错误。排查思路按顺序来,从高频原因到低频原因。
第一步检查生成的指令序列本身是否完整:有没有漏掉关键的草图基准面定义,拉伸方向是否明确,布尔操作的对象是否引用正确。
第二步检查参数数值的范围:如果坐标值出现几千上万,通常是推理解码时数值token拼接错了,比如少了一位小数点或者多位数字被截断。针对这个问题,我建议在解码时对数值token加上语法约束,只允许合法组合,同时控制数值在一个合理的范围(比如坐标不超过模型包围盒的两倍)。
第三步才考虑几何内核问题:CadQuery执行时对某些特殊拓扑结构(如自相交轮廓、零厚度特征)会直接报错,这类错误通常需要重新设计指令模板,在生成阶段避免出现这种拓扑。我的经验是,在训练语料里大量增加“简单草图+拉伸/切除”的样本,这类基本特征组合的生成成功率最高,复杂特征可以后续叠加。
4.4 语义理解偏差:模型到底有没有听懂你在说什么
训练正常、生成也正常,但出来的模型和用户设想的不一样,这类问题最让人头疼。比如描述里写“带凸台的底座”,生成结果却只有底座没有凸台。这个现象的根源在于训练数据的描述文本粒度不够细,模型没有学会“凸台”这个词对应“拉伸一个额外特征”的这个语义关联。
解决办法有几层。第一层,在推理前做一个“意图归一化”环节,把用户输入的自然语言先转换成一组结构化约束,比如提取出主体形状(底座)、附加特征(凸台)、尺寸要求(厚度、高度),再把结构化约束送入text-to-cad模型。这样能把用户的模糊表达,转化为模型在训练时见过的清晰表达。
第二层,做数据增强时,多收集一些同义词和口语化描述。我见过一个效果不错的方法是用大语言模型对原始描述做改写生成,比如把“bracket with two holes”改写成“a flat piece with two circular holes for mounting”,这种多样性增强能显著提升模型的语义理解能力。第三层,如果项目允许,可以给用户提供“局部编辑”的交互方式:先生成粗胚模型,用户点选一个面,再输入“在这个面上加一个直径5的孔”,这种渐进式迭代成功率比一次性生成高得多。
5. 部署环境的几个实用心得
5.1 选对Prompt模板,少踩一半的坑
text-to-cad的输入不是随便一句话就能得到好结果。我测试过上千组提示词后总结出一个经验:描述越结构化,生成效果越稳定。好的提示词格式长这样:“A rectangular plate, length 100mm, width 60mm, thickness 5mm, with four through holes of diameter 8mm located near the corners。”把尺寸、形状、位置约束尽量拆开说,比“一块板子上有几个孔”的模糊描述可靠得多。
如果你做的是面向普通用户的产品,强烈建议在界面层做一个“引导式输入”的模板,让用户按“主体形状-尺寸-附加特征-位置”四个字段填写描述。这样既能约束用户的输入不跑偏,又能保证text-to-cad模型的输入在训练分布的覆盖范围内,生成成功率会有一个质的飞跃。
5.2 输出精度提升:从采样到几何校验
推理时算法层面的策略对最终模型质量的影响非常大。在解码阶段,我推荐使用“带约束的beam search”:每生成一个token,就检查当前已生成的序列在语法和语义上的合法性,把非法分支直接剪掉。这个剪枝策略参考了编程语言语法分析的做法——让模型在解码时自己保持一个“期望的下一个token集合”,比如生成了“circle”之后,期望下一个token必须是左括号,再下一个必须是数值参数。
在生成完成后,加一步几何校验:把生成序列提交到CadQuery执行,执行成功后检查实体是否为流形,是否有自交面,是否满足用户给出的关键尺寸(比如“直径20毫米”)。如果不满足,可以自动做一轮“回退再生成”——把错误信息作为提示词的一部分拼接回去,让模型重新生成,通常尝试2到3次就能得到合格结果。这个方法相当于给生成过程加了一个外部循环,不需要额外训练,就能把最终交付成功率从70%拉到90%以上。
5.3 部署架构和延迟控制
把text-to-cad部署成在线服务时,要关注的不只是模型本身,还有构成“文本→指令→CAD软件”链路的工程性能。服务端的请求处理链路建议拆成三个模块:意图解析模块(把自然语言转成结构化约束)、序列生成模块(运行大模型推理)、几何执行模块(CadQuery+OpenCASCADE生成实体和导出文件)。三个模块可以分别部署、独立扩缩容。
延迟优化上,量化方案值得投入。底座的T5模型可以量化为8位或者4位,推理延迟能降一半,精度损失很小。CadQuery执行几何运算相对较快,一个中等复杂零件的实体化在几百毫秒内能完成,主要瓶颈还是在模型推理侧。如果对延迟特别敏感,可以考虑减少beam width、启用批处理队列、用vLLM这类推理框架做加速。我第一次上线的时候没做批处理,高峰期GPU利用率不到10%,请求排队严重;改成动态batching之后,单张卡在保证单请求时延不超3秒的前提下,吞吐量提升了将近10倍,这个优化非常划算。
5.4 从单一模型走向多模态
用多了你会发现,纯文本描述有时候真的说不清楚几何形状,比如“一个带复杂曲面的外壳”这种描述,文本能表达的信息极其有限。所以这个方向的下一个演进点在于多模态输入——把文本和草图、参考图片甚至点云数据结合起来,做一个多模态到CAD操作序列的生成模型。
我最近在尝试的方案是“描述文本+参考图像”的输入组合:图像分支提取几何轮廓特征,文本分支提取语义约束,两个特征向量拼接后共同输入解码器。这种多模态方案尤其适合做“仿制设计”的场景——用户拍一张实物照片,加上一句“按这个形状重新设计,但把安装孔改成腰形”,模型就能生成可编辑的CAD模型。这个方向涉及的跨模态对齐有不少工程量,但潜力很大,相当于把text-to-cad的适用范围从一个“创意草稿助手”扩展成了“实物逆向设计工具”。
另外,为了让text-to-cad模型结果更贴近实际加工需求,我还在探索结合制造约束做“可制造性生成”——就是在生成阶段就避开钣金折弯半径过小、型腔深宽比过大这类工艺问题。这些约束可以用规则编码在解码剪枝阶段,不用动模型结构,就能有效降低后期返工率。这个思路对制造企业用户来说,价值比纯粹的“能出模型”大得多。
其实做这个方向,最大的感触是:技术本身不难理解,难的是让生成结果真正进入专业流程。抛开炫酷的Demo,用户要的是能编辑、能加工、能复用的CAD实体,而不是一张图。围绕这个目标去优化数据、调整训练策略、完善后处理和交互,每一步都有大量细节值得磨。我现在还会经常把一段描述用不同的说法反复测试,观察模型哪些地方理解稳定、哪些地方会跑偏,然后反推去补数据。这条路走起来不轻松,但效果是一点点看得到的。