第一次看到 text-to-cad 的演示视频时,我的第一反应是:这不就是给 CAD 加了张"嘴"吗?但真正上手之后我才发现,这件事比想象中麻烦得多。它不只是把一句话变成模型,而是要把自然语言里的模糊意图,转换成一套精确、可编辑、能拿去生产的几何定义。这个方向热度一直很高,可真正能落地的方案屈指可数,大部分 Demo 只是用文生图模型勉强输出了一个像模像样的 Mesh,稍微放大看全是破洞,根本没法加工。这篇文章,我想从实操角度聊聊 text-to-cad 的现状、原理、工作流和踩坑记录,给想在这个方向动手的读者一个真实参考。
1. 先搞清楚 text-to-cad 到底在解决什么问题
1.1 它和文生图最大的区别:输出的是"可编辑的几何"
很多人第一次听到 text-to-cad,会下意识觉得它跟文生图差不多——输入一句话,输出一个三维模型。这个理解对了一半,实际上两者有本质区别。
文生图生成的是像素矩阵,你拿到的是颜色值,就算分辨率再高,放大之后也只是一堆有颜色的格子。但 cad 模型需要的是边界表示(B-rep)、构造实体几何(CSG 树)、参数化特征树这一类东西。你可以把 CAD 模型想象成一份带着尺寸标注的"数学配方",而不是一张"照片"。它能被导入 CAM 软件生成刀路,能切片生成 G 代码,能在装配体里反复改参数。这些需求决定了 text-to-cad 不能走"生成一个长得像的网格"这条路。
我见过不少早期项目,打着 text-to-cad 的旗号,实际输出的是 OBJ 或者 GLTF 网格模型。这类模型在可视化场景里够用,但工程软件拿到之后基本没法编辑。你没法直接拖拽一个孔的参数,没法把某个圆角从 R1 改成 R2,更没法导出高质量 STEP 文件给供应商。换句话说,它缺少"可编辑性"这个核心属性。
1.2 三条硬指标:精确性、可编辑性、制造可行性
我给 text-to-cad 项目做验收的时候,从来不看"模型渲染好不好看",只看三条硬指标。
第一条是精确性。用户说"直径 20 的孔",模型里就得是 20 毫米,不能是 19.97,也不能是 20.1。对于一般概念设计,毫米级别的误差可以接受;但到了装配和制造阶段,一丝一毫的偏差都会变成实际成本。
第二条是可编辑性。生成的模型必须带参数,或者至少带特征树。用户应该能在不重跑整个模型的情况下修改孔的位置、板的厚度、螺纹的规格。如果生成的是"死模型",用户只能把它当装饰品,那它就没有进入工作流的意义。
第三条是制造可行性。模型必须流形、封闭、没有自相交,允许导出 STEP/IGES,能在常见 CAM 系统里正常打开。这个要求听起来基础,却是文生图思路最难跨越的坎——图模型根本不知道什么叫"流形",它只会模仿形状。
这三条标准把 text-to-cad 和普通的三维生成严格区分开来。讲白了,它要完成的任务不是"画一张很像的图",而是"写一段能运行的建模程序"。
2. 一套完整可跑的 text-to-cad 流水线是怎么搭起来的
2.1 两种主流实现路线
我在搭建自己的 text-to-cad 系统时,首先面对的是路线选择。目前市面上跑得通的做法基本分两类,一类是端到端生成 B-rep,另一类是先生成中间代码再交给几何内核执行。
端到端生成 B-rep 的思路很像扩散模型直接生成点云或体素,只不过把输出空间换成了带拓扑和几何信息的张量。这种方式理论上可以学习到复杂的曲面造型,但问题是训练数据难构造、输出稳定性差,而且一旦生成失败,你没有任何中间层可以做人工修正。它更像一个"黑盒",适合学术研究,不太适合生产环境。
我最终选择了第二条路线:让语言模型先生成一段结构化的程序化建模脚本,然后用开源几何内核执行这段脚本,得到真正的 CAD 模型。这个做法的好处是可解释性极强——模型生成的代码可以直接看,哪里不对就改哪里,还能做规则校验。它也继承了语言模型的优点:用户随便怎么说,模型都能尝试翻译成标准建模操作。
2.2 我采用的中间表示方案:从文本到代码再到模型
完整流水线可以拆成四步。
第一步是文本标准化。用户输入"给我做一个长 100 毫米、宽 50 毫米、厚度 5 毫米的板子,四个角打 M6 的孔",这段话里有尺寸、有零件类型、有孔的规格,但还有很多隐含信息——比如孔离边缘多远、要不要沉头、板子默认原点是哪个角。语言模型需要先把这个描述解析成结构化的意图槽位。
第二步是生成建模脚本。脚本不是固定的模板,而是模型根据意图槽位动态组合出来的。它由一串基础几何运算组成,比如新建草图、画矩形、添加约束、拉伸、布尔差集。每个运算都对应 CAD 设计中的一个真实动作。
第三步是几何内核重建。我用的开源内核能解析这串脚本,在内存里构建出真实的实体模型。这一步会把脚本里的尺寸单位、草图坐标系、布尔公差全部落实到数学计算中。
第四步是校验与导出。系统会检查模型是否封闭、体是否为流形、有没有退化曲面,通过之后才导出 STEP 和 STL 两个格式,分别给 CAM 用户和下游可视化使用。
关键的地方在于,脚本语言本身是有限集合。我限制了约五十个基础指令,包括矩形、圆、拉伸、旋转、倒角、圆角、线性阵列、环形阵列、布尔并集和布尔差集。为什么要限制?因为语言模型在无限空间里生成代码,出错率会指数级增加。把生成空间锁死到五十条指令里,等于给模型修了一条轨道,它想跑偏都难。
2.3 环境搭建时最容易忽略的细节
硬件上,我用的方案是量化之后的本地部署,不需要昂贵显卡。真正让我头疼的是几何内核的 Python 封装,它经常在布尔运算时因为容差设置不当,导致生成的实体自相交或者干脆算不出结果。我的解决方法是把脚本执行放在独立进程里,一旦内核崩溃,语言模型那边不受影响,整个系统只是多了一次重试机会。
另外,单位制必须统一。我第一次跑通流水线时,生成的板子厚了二十五倍,排查了半天才发现训练数据里混进了英寸和毫米两套单位。这件事我后面会用一节单独展开,因为它在所有踩坑记录里出现频率最高。
3. 核心原理:语言模型、几何内核和程序合成是怎么被串起来的
3.1 语言侧:把一句话拆成意图槽位
text-to-cad 里语言模型承担的角色,本质上是一个"翻译官",它要完成的是把非结构化的自然语言翻译成结构化的建模指令。但建模指令不是逐词对应,而是要先理解用户意图。
我常用一个例子来演示:用户说"这两个孔之间隔一个拇指宽的距离"。什么叫"拇指宽"?没有标准答案,模型只能根据上下文推断。如果旁边有"大约是 20 毫米"的表述,那它就能把拇指宽和 20 毫米联系起来;如果没有,就要生成一个合理的默认值,并在结果中标注"使用默认值 20mm"。
为了让模型学会这种能力,我引入了"意图槽位"机制,有点像把自然语言填进一个表格。这个表格包含零件类型、主体尺寸、特征类型、特征位置、特征数量、公差等级、材料方向等十几个字段。模型的任务就是把用户输入映射到字段,同时补全没有提到的字段。
这个机制的优点在于可以单独评估。某个字段映射得准不准,可以逐个打分,不像端到端只能看整个模型对不对。它还能让用户事后手动修正某个字段,然后再让模型重新生成脚本,形成人机协作闭环。
3.2 几何侧:用参数化脚本驱动建模运算
既然是程序合成,几何内核的作用就不只是"画图",它更像一个计算引擎。脚本里每个操作都会触发大量几何计算:拉伸是扫掠,布尔差集是求空间交集,孔阵列是旋转复制。
我最初犯过一个认知性错误,觉得语言模型只要生成了正确代码,内核就会乖乖执行。但实际上,代码"看起来正确"和"几何上可计算"是两回事。比如一个试图把两个没有重叠的圆柱做布尔差集,内核会返回一个空的实体;再比如拉伸轮廓有一条边自相交,内核会在这一步直接报错。问题可能出在内核的容差处理上,也可能出在建模顺序上。这些根本不是语言模型能预见的。
所以我给系统加了一层"几何预检器"。它会在脚本执行前用轻量级规则扫描代码,看看是否有明显的不合法结构,比如草图未闭合、布尔差集对象完全不相交、阵列数量为零。这层预检能把大约三成的失败提前拦截下来,省掉大量后面的调试时间。
3.3 误差从哪来:每一步都在损失信息
我一开始天真地以为,输出的模型不准,问题肯定出在语言模型上。后来统计了几百个失败案例,才发现信息损失分布在每个环节。
文本到意图槽位这一步,损失的是歧义。用户说"不错的板子",系统不知道"不错"是厚度偏好还是材质偏好,最终只能猜。意图槽位到脚本这一步,损失的是默认值。脚本必须给出每一个尺寸,哪怕用户没说,模型也要自行编造。脚本到几何执行这一步,损失的是精度。内核计算时会有浮点舍入和容差处理,微小误差在复杂布尔运算里会被放大。
理解这个链路很重要。如果你发现模型输出结果尺寸不准,先去查意图槽位是否正确,再查脚本有没有错误默认值,最后才怀疑内核计算。我花了很长时间才意识到,很多看起来像"模型抽风"的问题,其实是脚本里某个默认参数写死了。找到这个默认参数,问题就解决了一半。
4. 数据比模型更值钱:text-to-cad 的训练数据到底该怎么造
4.1 公开数据为什么不够用
Text-to-cad 最大的瓶颈从来不是模型结构,而是训练数据。我试过几套公开的零件数据集,问题都很类似:模型大多是网格格式,没有特征树;描述文本只是简单的类别标签;零件种类集中在机械标准件上,缺少复杂的钣金和外壳结构。
网格格式的数据对文生图有用,但对我这个流水线基本没用。原因很简单,我要训练的是"生成脚本"的能力,而不是"生成形状"的能力。脚本需要的是从一组操作序列到最终实体的逻辑关系,网格数据根本没有这层信息。
公开数据里还有大量损坏模型。比如存在孤立边、非流形顶点、零体积实体的模型,在可视化软件里看不出来,但一旦导入 CAD 内核,整个文件都会报错。如果拿这些数据训练模型,模型会学到"非流形实体是可以被接受的",这在工程应用中是致命的。
4.2 我用的合成数据生成方案
既然公开数据不理想,那就只能自己生产。我的思路跟很多人反向:先用程序化方式生成大量参数化 CAD 模型,再把模型反推成对应的自然语言描述,形成一对一的训练对。
具体操作是先写几百个零件生成模板。例如"L 型支架"模板,定义主体长、宽、高,两臂厚度,孔数量和孔直径,再把每个参数随机化。每个模板执行之后都会得到一个带特征树的 STEP 模型,同时我保存一份原始参数表。接下来用这些参数表反向构造描述文本。
描述文本的生成不能太机械。我用了两级增强:第一级是用模板拼接,生成"长 100 宽 50 厚 5 的 L 型支架,两臂各有两个直径 10 的孔"这种标准说法;第二级是让语言模型对标准说法做语义改写,变成"我要个转角板,一边宽一点,上面开几个眼儿"这种口语化表达。
这两级数据混合使用,能够让模型同时认识标准术语和日常口语,这是我从踩坑中总结出来的经验。一开始我全用的是口语化数据,模型反而不会处理"直径""厚度"这类工程术语。
4.3 数据清洗的四个关键动作
合成数据也不是生成出来就能直接用,我做了四步清洗。
第一步是几何校验。用几何内核重新加载每个生成实体,检查体积是否为正、面积是否大于零、边界是否封闭。不通过的样例直接删除,绝不手软。
第二步是拓扑去重。两个不同参数组合可能生成几乎相同的实体,比如正方形拉伸和正立方体在最终结果上就相同。我使用轻量级哈希对模型去重,避免模型见过太多重复形状。
第三步是脚本合法性检查。每个模板生成的脚本都要能完整运行,不能出现内核崩溃或者无限循环。这一步排除了很多参数组合,但保证训练集质量。
第四步是描述对齐。每类零件的描述文本数量要均衡,不能支架生成了一万条,法兰盘只有一百条。我强制按类别配额采样,让模型公平地见到每类零件。
这套数据管线看起来很简单,但把质量控制住之后,模型效果提升非常明显。我甚至觉得,有好的数据,一个中等规模的语言模型就能在特定零件类别上做到超过大模型的水平。
5. 实测记录:从 L 型支架到带孔法兰盘
5.1 案例一:一句话生成可展开的 L 型支架
我在验证系统时,用的第一个标准测试是 L 型支架。用户输入"长 100 毫米、宽 50 毫米、高 5 毫米的 L 型支架,两臂各开一个直径 10 毫米的通孔"。
第一次运行时,系统输出的模型看起来很像,但有一个隐蔽问题:两臂之间用的是两个长方体并集,而不是一个整体的 L 型轮廓拉伸。从外观上看没差别,但导出的 STEP 里多了一条内部重合面。这个重合面在后续 CAM 编程时,可能导致刀路误判,产生重复切削。
我调整了提示词策略,在输入里加上一句"优先使用单草图拉伸轮廓,减少布尔操作"。从那之后,模型更倾向于用二维草图绘制 L 型轮廓,再一次性拉伸,得到的实体没有内部缝。这个改动听起来像提示词工程,实际上是在告诉模型"我需要一个干净的特征树"。
5.2 案例二:带孔法兰盘为什么总在布尔运算上翻车
第二个典型案例是法兰盘,输入很标准:"外径 80、内径 30、厚度 10 的法兰盘,均布六个直径 8 的螺栓孔"。
这个需求本身不难,但模型第一次生成的脚本里面,六个螺栓孔是逐个跟主体求差集。问题在于,如果某两个螺栓孔的圆柱面与主体面刚好相切,或者位置出现微小重叠,布尔差集就会产生退化边。内核虽然能算出结果,但结果里会出现一个异常细小的薄面。导入到后续软件时,薄面直接导致加工死角。
我的解决方案有两层。第一层是在脚本生成阶段,明确要求模型用环形阵列代替重复差集;第二层是在几何执行阶段,把公差从默认值放宽到内核支持的最大值,让计算更鲁棒。
这样做之后,法兰盘的成功率从六成涨到了九成。剩下的失败案例,几乎都是因为输入描述里缺少孔中心圆直径,模型要凭空猜一个默认值。猜的默认值稍微不合理,六个孔就部分跑到法兰外圈去了。
5.3 评测的硬性标准:不只是"像不像"
如果只靠肉眼判断模型效果,你很容易被 Demo 骗过去。我做了一套自动化评测,每次跑完都记录以下指标。
几何合法性方面,我检查实体是否封闭、是否流形、体积是否为正。尺寸命中方面,我把用户输入的每个尺寸都作为测试项,输出与目标值的偏差如果超过 0.5 毫米,就算失败。特征完整性方面,我要数孔的数量,检查阵列角度,确认倒角和圆角是否存在。渲染相似度方面,我把输出模型从八个角度渲染成图像,与真实模型做感知相似度对比,但权重放到最低。
这套指标帮我挡住了很多表面漂亮的模型。说实话,很多模型渲染出来很像,但尺寸一量全是错的。工程领域最忌讳的,就是拿"看起来像"冒充"精确"。
6. 上线前必须躲开的五个坑
6.1 单位制混乱:毫米、英寸与英尺的隐形陷阱
单位制是 text-to-cad 上线前最容易踩的坑。我训练数据以毫米为主,但用户习惯千差万别。有人输入"一英寸厚的板子",有人在 CAD 里用的是公制却下意识输入了英制小数,还有人把 1 英尺打成 1 英尺后加了一段文字描述。
模型很难自己判断单位是否合理。如果不做强制约束,它会把"1"直接当作 1 毫米。我的处理方式是在解析阶段显式识别单位词,同时让模型生成"单位归一化"字段,比如检测到英寸就显示警告,要求用户确认。这个简单的强制确认机制,替我挡掉了大量下游麻烦。
6.2 布尔运算失败:实体退化与自相交
布尔运算是 text-to-cad 流水线里最脆弱的一环。模型生成两个体求差,如果两个体只是边角接触,或者一个体完全包含另一个但仍保留相切面,内核计算结果经常是退化实体。
我总结的规律是:尽量让脚本使用阵列、镜像等特征操作,而不是在语言模型输出里写大量重复布尔差集。目标实体应该尽量由草图面决定,而不是由实体组合决定。这跟经验丰富的建模工程师思路一致:先画对二维草图,再拉伸,要比先建两个体再拼装稳定得多。
6.3 幻觉参数:模型会编造不存在的孔径
语言模型最讨厌的一点,是它非常擅长编造看起来合理的数值。用户说"在板上开几个孔",没说直径,模型直接写了个"直径 10 的孔"。这个值看似正常,但用户拿到手发现孔装在铰链上根本穿不过去。
要解决幻觉,必须在脚本生成前强制模型区分"明确参数"和"默认参数"。明确参数来自用户输入,默认参数来自模型推断。系统界面上要清楚标出"该值为默认值,请确认"。我把这个机制称为"参数来源标记",虽然增加了一步人工交互,但大幅减少了返工。
6.4 坐标系漂移:装配场景下的对齐问题
单零件生成时,坐标原点往往放在模型左下角或者中心,用户自己能接受。但一旦进入装配体,零件需要精确定位到某个坐标。模型如果习惯把原点放在自己认为"方便"的位置,装配时就完全对不上。
我在生成阶段增加了一个"定位规则":默认让零件关于原点对称,或者对齐到底面中心。文档里写清楚这个规则,后续再做装配测试时效率提升非常明显。很多模块化设计公司尤其注意这个点,因为他们要对接上下游设计流程。
6.5 版本兼容性:换了内核版本,结果全变了
几何内核的版本升级会默默改变布尔运算和扫掠的内部算法。同一段脚本,在旧版本上生成完美实体,在新版本上可能生成自相交曲面。
这个坑我踩得很深。有一次我升级了内核版本,没有任何报错,只是生成结果里多了一堆细小裂痕。排查了两天,最后发现是内核版本差异。解决方案是把内核版本固定下来,并且把运行环境整体封装到容器里。训练、验证、推理全都用同一套二进制,不允许任何隐性升级。
7. 现在的 text-to-cad 能用在哪儿,哪儿还不行
7.1 能落地的场景:概念设计、标准件、教学演示
把上面的坑都处理掉之后,text-to-cad 在几个特定场景里确实能干活。
概念设计是最合适的场景。工程师在脑子里有一个模糊想法,用自然语言快速生成一个基础外形,再在 CAD 里手动细化。这时候 text-to-cad 的价值是"消歧"和"快速起稿",而不是直接交付最终模型。
标准件库生成也很适合。我拿它批量生成常见的法兰盘、支架、垫片、挡板,只需要改参数描述就能得到一系列变体。这类零件特征固定、规则明确,语言模型完全能胜任。
教学演示是另一个容易忽略的用途。新手还不知道怎么操作 CAD 软件,可以先让 text-to-cad 生成一个模型,再用特征树反向学建模顺序。这一步对培养空间思维很有帮助。
7.2 暂时不行的场景:复杂曲面、精密公差、多零件装配
text-to-cad 目前的短板也很明显。第一个是复杂曲面造型,比如汽车外壳、手机中框、人体工学手柄,这些需要自由曲面和连续曲率控制,用自然语言很难描述,语言模型更是难以生成高质量曲面。
第二个是精密公差。铸造件可能要求正负 0.01 毫米的配合公差,text-to-cad 很难保证。它生成的模型也许在数学上是正确的,但具体到加工艺、材料收缩率和表面处理,语言模型完全没法参与。
第三个是多零件装配体。系统目前能较好地生成单个零件,但要把十几个零件加上运动副、约束和装配关系,自然语言描述会迅速变得模棱两可。模型生成一个零件还可以,生成整个装配体基本不可能。
7.3 选型建议:自建还是用现成的 API
最后给一个选型建议。如果你的需求只是内部测试、验证概念、或者搭建个人作品集,直接使用商业 API 最省事。它们有现成的模型、数据和客服,你不用处理合成数据的脏活累活。
但如果你的项目涉及企业数据安全,或者需要针对特定零件类别深度定制,自建可能更合适。自建的代价是大量时间花在数据管线和规则校验上,模型结构反而是最简单的部分。我的建议是先买现成 API 跑通流程,再决定要不要自建,不要一上来就重复造轮子。
如果让我给后来者一句忠告,那就是:text-to-cad 本质上是一个"程序合成"问题,不是"图形生成"问题。你的核心竞争力,应该是把自然语言约束映射到几何规则的能力,而不是又一个华丽的深度学习模型。先用一个非常窄的领域做透,积累一批高质量数据,再慢慢扩大范围。这个过程很枯燥,但每一步踩坑都会换来真实的生产力提升。