CAD这块儿最近有个方向让我挺兴奋的,就是text-to-cad。简单说,就是输入一句人话,比如“一个直径50的圆盘,中心开一个直径20的孔,周围均布六个直径6的安装孔”,系统直接给你生成对应的三维模型。这听起来像科幻,但实际上已经有不少模型和工具能跑通了。我自己试过几个,也折腾过一些小实验,今天这篇就把这个方向的核心技术、实现思路、常见的坑,以及怎么把它真正用进工作流里,仔仔细细聊一遍。
如果你平时要做机械结构、非标件,或者经常被业务部门用一句“就那种带孔的板子”搞得头大,text-to-cad就是你值得关注的方向。这篇文章适合想了解技术原理的人,也适合打算自己动手训一个最小验证模型的工程师。
1. text-to-cad本质上是给三维建模装上一个“自然语言编译器”
1.1 传统建模方式和自然语言的差距在哪里
传统CAD建模是什么?是操作序列。你画一个草图,拉伸,再选一个面打孔,再阵列,每一步都是在告诉软件“怎么做”。而text-to-cad想解决的是“做什么”这个层面——它直接把设计意图翻译成操作序列。这中间的差距,就是自然语言和几何操作之间的鸿沟。
举个例子。一句话“底板上开四个对称的圆孔”,人很容易理解。但要变成CAD命令,你需要知道:底板是多厚?圆孔直径多少?四个孔的中心分布半径是多少?“对称”是左右对称还是圆周均布?这些信息源文本里可能都没有。所以text-to-cad系统面临的第一问题不是生成几何,而是“补全缺失的决策”。它得像一个经验丰富的设计师,把没说出口的部分也猜出来。
这和文本生成图像的原理很像,但有一个根本性差异:图像是像素矩阵,生成偏差一点点肉眼看不出来;CAD模型是参数化实体,一个孔位偏了0.5毫米,整个零件就废了。这意味着text-to-cad的容错率极低。我在实际测试中看到过很多模型输出的模型,看渲染图很像那么回事,一测量尺寸全不对。这就是典型的“看起来能用,实际上不能用”。
1.2 解决的核心问题和实际价值
text-to-cad的核心价值在于压缩“从想法到模型”的时间。传统流程里,一个熟练工程师画一个中等复杂度的零件,可能需要20分钟到1小时;用text-to-cad辅助,可能几秒钟出一个初版,剩下的时间全部用在修改和确认上。对于非标设计频繁的场景,这个提升非常可观。
另一个价值点是“设计意图的沉淀”。自然语言描述可以被记录、复用、检索。比如“带法兰的圆柱壳体,四螺栓孔均布”,这句话既是一个历史需求记录,又可以作为下次生成类似零件的输入条件。存量设计文档、需求规格书、甚至聊天记录里的需求描述,都能变成模型生成的输入源。
我实际试过的场景之一是标准件库的扩充。标准件比如螺钉、垫圈、法兰,特性很规律,非常适合用文本来描述。“M8平垫圈,内径8.4,外径16,厚度1.6”,这种描述几乎就是结构化参数,模型特别好学,生成也稳定。这类场景是最容易落地见效的,值得优先切入。
2. 从文本到模型,中间要跨越的三道门槛
2.1 语义理解:把一句话拆成完整的参数表
这一步和常规NLP任务比较接近,但也有自己的特点。CAD描述中的核心信息是“实体特征”和“空间关系”,不是情感或主题。我们需要从文本中抽取出类似这样的结构化内容:
- 基础实体类型(圆柱体、长方体、球体、圆台)
- 关键尺寸(直径、长度、高度、厚度)
- 特征操作(切割、打孔、倒角、阵列)
- 位置关系(中心、同轴、偏移、均布、对称)
- 隐含约束(对称隐含了镜像关系,均布隐含了圆周阵列)
我自己在处理文本标注时,习惯先把一句话拆解成“实体—操作—尺寸—关系”四元组。比如“中心开孔的法兰盘,直径120,四孔均布在直径90的圆上”,拆出来就是:
- 实体:法兰盘
- 操作:开孔
- 尺寸:主体直径120,孔分布圆直径90
- 关系:中心、均布、四个
这一步如果拆错了,后面模型再强也白搭。所以很多团队在做数据集时都花巨大精力在文本标注上,这是整个流程的地基。
2.2 几何映射:从参数到实体模型的翻译规则
有了参数,下一步就是把这些参数变成几何体。这里有个关键问题——输出形式怎么选。
一种思路是直接输出网格(mesh),像文本生成3D模型领域的常见做法,比如用神经网络生成体素场或者SDF。这种方式视觉效果好,但导出的模型没有参数化特征,不能编辑,不能改尺寸,工程上基本没法用。
另一种思路是输出参数化特征树,或者直接生成CAD命令序列。比如:
CreateSketch(base_plane) AddRectangle(center=(0,0), width=100, height=60) Extrude(distance=10) AddCircle(center=(50,30), diameter=10) CutThroughAll()这段伪代码式的命令序列可以通过脚本回放,直接在软件里重建出实体,而且每个特征都是独立可编辑的参数。这是text-to-cad区别于普通文本生成3D的关键——可编辑、可参数化、可追溯。
还有少数方案直接生成BREP(边界表示)数据,精度高,也不依赖具体软件,但实现难度更大,目前应用还不算广。我的建议是,自己动手做实验优先考虑命令序列方案,落地最容易。
2.3 约束处理:模型生成中最容易翻车的地方
参数化设计里有大量约束关系,这是文本描述里最容易丢信息的部分。比如“孔心到两条边的距离相等”意味着一个定位约束;如果生成时只生成坐标,一旦上游尺寸变化,这个约束就丢失了,模型就废了。
目前不少模型倾向于直接生成绝对坐标和尺寸,好处是训练简单,缺点是无法应对参数驱动。如果想让text-to-cad真正融入现有设计流程,模型输出的最好是一套带约束关系的命令流,比如“孔心到edge1的距离等于到edge2的距离”这样的约束表达式,而不是固定的坐标值。
我在自己做小实验时踩过这个坑:刚开始让模型直接输出坐标,生成的模型在静态测试中完美,但一改底板长度或宽度再重新生成,孔的位置不会跟着边自动调整。后来换成了相对定位描述——比如“沿底边居中,水平偏移30”,效果一下子好了很多。这类经验说明,生成策略的设计比模型架构本身更影响落地效果。
3. 拆解一个可落地的text-to-cad流程
3.1 数据准备是真正的护城河
text-to-cad项目最稀缺的不是模型结构,而是数据。文本描述和CAD模型配对的公开数据集非常少,而且大多只覆盖很窄的类别,比如简单的机械零件、建筑构件。如果你的目标是特定行业或特定产品形态,基本得自己造数据。
我的做法是:自己录制CAD操作宏,把操作序列存成JSON,然后根据这个JSON写自然语言描述,最后用CAD内核重新执行JSON生成实体。这样形成“指令集—文本—实体”的三元组。别小看这个方案,它比人工逐条标注的效率高很多,而且可以批量生成数据增强样本,比如把尺寸随机变化、把位置关系随机表达。
文本生成方面,我写过一个模板引擎,把指令集里的参数和关系转成自然语言,比如“RoundHole(diameter=6, position=(50,30))”转成“直径6的圆孔,圆心坐标在(50,30)”。然后还做了同义扩充,用“孔”“钻孔”“圆孔”互相替换,这样避免模型过拟合到单一表达上。
数据量方面,我个人的经验是最少几千条才有说服力,一万条以上训练出的效果会比较稳。纯粹为Demo的话,几百条也能看出模型能不能学到基本语法,但要实际用,数据量必须起得来。
3.2 模型选型:代码生成模型是当前的性价比之王
text-to-cad模型的选型,很多人第一反应是要不要搞个专门的几何神经网络。我觉得现阶段没必要。因为如果你把CAD生成定义为“命令序列生成”,那这个问题本质上就是一个序列到序列任务,跟代码生成、SQL生成非常像。用现成的代码生成模型,比如CodeGen、StarCoder、CodeLlama这些开源系列,再在自建的CAD指令数据集上微调,是性价比最高的路线。
有一个点值得说一下——这里的“代码”不要理解成传统意义的程序代码,而是CAD软件自己的API脚本。我们微调的目标是让模型学会输出一段能在软件里回放生成实体的脚本。所以数据格式设计非常重要,早期我做实验时用了FreeCAD的Python API格式,后来也测试过OpenSCAD的描述语言,两者都能用,但通用性差别不小。如果想让生成结果在不同软件间共用,中间加一层“中性指令集”会更合理。
模型参数规模上,从几亿到几百亿参数的模型我都试过。对于一个专注特定领域的text-to-cad任务,小模型微调的效果完全够用,几亿参数对几百种零件类别可以应对;真正影响效果的是数据质量,不是模型大小。
3.3 一个最小可跑的流程示例
我这里给一个最小可跑的参考流程,基于我自己的实验配置,帮你理解整体链路:
输入:“一个40x30的长方形底板,厚度5,中心一个直径8的圆孔,四个角落各一个直径4的圆孔”先做语义抽取,用正则和规则引擎就能处理这类固定句式:
import re def parse_simple(text): plate_match = re.search(r"(\d+)x(\d+)", text) thickness_match = re.search(r"厚度(\d+)", text) center_hole = re.search(r"中心一个直径(\d+)", text) corner_holes = re.search(r"四个角落各一个直径(\d+)", text) return { "width": int(plate_match.group(1)), "height": int(plate_match.group(2)), "thickness": int(thickness_match.group(1)), "center_d": int(center_hole.group(1)), "corner_d": int(corner_holes.group(1)) }然后把这个参数传给生成脚本的模板:
def gen_cad_script(params): w, h, t = params["width"], params["height"], params["thickness"] cd, kd = params["center_d"], params["corner_d"] # 角孔位置,留边距5 margin = 5 script = f""" import cadquery as cq result = cq.Workplane("XY").box({w}, {h}, {t}) result = result.faces(">Z").workplane().center(0, 0).hole({cd}) c = {w}/2 - {margin} d = {h}/2 - {margin} result = result.faces(">Z").workplane().pushPoints([({c}, {d}), ({-c}, {d}), ({c}, {-d}), ({-c}, {-d})]).hole({kd}) """ return script最后用cadquery回放,输出STEP文件。整套流程跑通只需要几百行代码,这是理解text-to-cad的最小骨架。真实场景的模型只是把这个骨架中的规则引擎换成神经网络,其他的部分几乎不变。
4. 训练与推理中最容易翻车的三个环节
4.1 坐标一致性问题
训练模型直接生成CAD脚本时,最大的坑是绝对坐标。模型在训练数据里看到的坐标是一个值域范围,如果训练数据里坐标普遍集中在某个区域,模型学到的分布就是偏的。推理时一旦输入文本描述的尺寸超过训练分布,模型输出的坐标很可能离谱,比如跑到负值区,造成特征反转。
我自己的解决方法是:把所有坐标从绝对坐标改成相对坐标,比如“孔心相对于底座中心偏移(20, 15)”,让模型学的是相对关系而不是绝对位置。相对位置模式下的泛化能力会显著提升,实测效果稳定很多。
4.2 命令序列未闭合问题
文本生成代码有个经典问题——代码不完整,比如截面没有完全闭合、轮廓线没有首尾相接,直接导致实体生成失败。这在text-to-cad里的表现是:模型生成的脚本语法看起来都对,但实际执行时CAD内核直接报错,或者生成一个破碎的几何体。
排查思路很简单,设计两个规则做约束:
- 每个草图必须有闭合的轮廓线,不允许自由端点
- 每个拉伸、切割操作必须有对应的布尔运算结果检查
这类结构化约束不靠模型自己领悟,靠脚本后处理规则就能兜底。我在推理阶段接了一段自动修复逻辑,发现脚本生成失败时,自动把开放线端点连接起来再重试,成功率能提升不少。
4.3 评估指标的选择陷阱
很多text-to-cad项目都陷入一个评估误区——只看生成模型的视觉相似度。用SDF或者点云距离衡量两个三维模型的距离,看起来科学,但实际工程上没用。因为视觉相似不代表尺寸正确、也不代表特征可编辑。
我的建议是分三层评估:
- 语法正确率:脚本能否被CAD内核回放并生成有效实体
- 几何准确率:关键尺寸、孔心位置是否存在误差,误差是否在容许范围内
- 约束保持率:修改上游参数后,下游约束是否仍然维持
这三个指标能比较好地反映“能不能真正投入使用”。我自己的模型迭代过程中,也主要盯着这三个指标做优化。很多论文里展示的漂亮图片,拿到这三个指标下测立刻就见真章。
5. 从玩具到工具:text-to-cad真正融入工作流的三个方向
5.1 作为“设计意图捕获器”而不是“全自动建模工具”
以我目前的使用经验,不要指望text-to-cad完全替代CAD建模——现阶段它的定位更像是“设计意图的捕获器和草稿生成器”。它能在你脑子还没想清楚细节时,先把大概的几何形状生成出来,你再在CAD里调整参数、加约束、做优化。这个模式比全自动生成靠谱得多。
实际项目中,我习惯把text-to-cad作为一个插件集成在软件里,使用者输入一句话,系统生成一个带参数的预置模型,接下来所有修改都在参数面板里完成。这样既保留了CAD的优势,又把前期的繁琐操作去掉了。
5.2 从单零件到装配体的挑战和应对
目前的text-to-cad基本都局限在单零件,也就是“一个实体”的范畴。但真实设计里,装配体才是常态,比如“底板上面放一个电机支座,用四颗螺钉固定”。这个目标对模型的理解能力要求高了很多——不但要描述每个零件的几何,还要表达零件之间的贴合面、定位关系、安装顺序。
我实验中尝试过将装配体分解成多个零件描述,再额外输出装配关系,比如“face1贴合到face2,中心对齐”。这个思路可行,但数据获取的难度又上一个台阶。目前距离直接成品化还有距离,但值得关注。
5.3 未来会走向“设计意图对话式生成”的模式
text-to-cad未来发展大概率不是“一句话生成最终模型”这样一锤子买卖,而是“对话式逐轮细化”:先给定一个粗略需求,生成初版,用户说“孔太小了,孔距再大一点”,系统在参数空间上做局部修改。这比一次生成更符合真实设计习惯,因为它允许渐进式探索。
从技术角度看,这需要模型具备多轮对话能力和修改记忆能力——记住上一轮生成的模型参数,理解本轮修改意图,更新相应参数而不是重新生成全部内容。目前这个方向的实验还不多,但我觉得这是text-to-cad产品化的必经之路。
我自己在实际使用中发现,最管用的做法是把text-to-cad的输出当成“设计的第一个版本”,后面的决策完全交由人来控制。模型负责把模糊的表达变成可讨论的几何,人负责判断“这是不是我要的感觉”。踩过几次坑之后,我更加坚信一点——真正能落地的AI工具,不是替你做决定,而是让你更高效地做决定。text-to-cad是这个思路的绝佳实践,而且它才刚刚开始。如果你也想试试这个方向,建议从最小流程跑通开始,别一上来就追最复杂的模型,先把数据链路和评估体系搭好,你的每一步优化都会踩在实处。