ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Text-to-CAD技术解析:从自然语言到可编辑CAD模型的工程化路径

Text-to-CAD技术解析:从自然语言到可编辑CAD模型的工程化路径

text-to-cad 这个方向,这两年是实打实火起来了,我身边不少做机械设计、三维建模的朋友都跑来问:现在是不是写一句话就能出模型了?严格讲,你现在能看到的大部分“AI 生成 3D”工具,跟 text-to-cad 压根是两码事——那些大多是“文生图”路线生成的网格模型,好看归好看,落到工程软件里基本没法用。而 text-to-cad 的目标,是用自然语言直接生成能被 CAD 软件正常打开、能编辑、能量尺寸、能改参数的真实模型文件。这篇文章不准备铺太高深的理论,就按我实际调研和动手跑过的方案,把这条链路上的关键技术点拆开讲一遍。适合搞算法、做 CAD 二次开发、或者在自研工具链里接“语言到 CAD”能力的团队阅读,读完至少能少踩四五个坑。

1. text-to-cad 在解决什么:先分清“假 3D”和“真 CAD”

1.1 从一句话到能编辑的实体

你给系统输入“生成一个直径 60mm、厚度 20mm、中心带 15mm 通孔的法兰盘”,它返回给你的,理想情况下应该是一个标准的 STEP 文件或原生 CAD 文件。打开之后,你能看到完整的特征树:草图、拉伸、切除、倒角,每一步都有参数可以改。改一下直径,整个模型自动更新约束和配合关系。这才是 text-to-cad 真正想做的东西。

这个目标和“AI 生成一张看起来像法兰盘的图片”完全不同。图片只能看,网格模型也只能拿来渲染或 3D 打印个外形,但工程上要的是可以进入装配、仿真、加工流程的精确几何体。说得更直白一点:设计一个零件,不是在画形状,而是在定义形状背后的拓扑关系、尺寸约束和制造语义。这也是 text-to-cad 比普通文生 3D 难一个量级的根本原因。

1.2 为什么不能直接用“AI 生成网格”那套

很多刚接触这个方向的人第一反应是:现在生成 3D 模型的技术已经很成熟了,把扩散模型换成 text-to-cad 不就行了?但实际一跑就发现完全不是一回事。主流文生 3D 模型输出的是三角网格(mesh)或者神经隐式场,这类结果本质上是“形状的近似素描”。它由成千上万个三角面片组成,没有连续几何曲面,没有边、面、顶点之间的拓扑关系,也没有参数化历史。

网格模型拿来渲染一个游戏道具可以,拿来开模具就非常尴尬了。你没法在 SolidWorks 或 Fusion 360 里选中一个圆柱面去定义配合公差,没法把一条边倒成圆角,更没法回到草图里改一个直径尺寸。用网格做逆向设计当然有现成工具,比如 Geomagic,但那是一条独立的逆向管线,需要大量人工修补,跟 text-to-cad 追求的生产力提升完全不是一回事。

我常用一个类比跟人解释这件事:网格模型相当于一张像素图,CAD 模型相当于矢量图。像素图放大就糊,改一个局部的颜色得手动抠;矢量图任意缩放都清晰,双击就能改锚点。B-Rep(边界表示)就是 CAD 世界的矢量图,它保存的不是密密麻麻的三角片,而是用精确数学曲面和拓扑连接关系描述的实体。所以 text-to-cad 这条赛道的核心难点,本质上是“怎么让 AI 直接生成矢量图,而不是画一张高清像素图”。

2. 三条技术路线:我为什么押注“序列生成”

2.1 路线一:LLM 生成 CAD 操作序列

这条路线是目前最主流、也是我觉得最接近真实工程工作流的方案。核心思路很直接:既然一个 CAD 模型本质上是一串建模操作的产物,那就把“画草图轮廓”+“拉伸”+“切除”+“倒角”这些动作编码成结构化指令序列,然后用大模型根据自然语言输出这一串指令。拿到指令之后,再通过 CadQuery、FreeCAD 脚本这样的执行引擎重放操作,最终生成实体。

我实际调研过的几个开源工作流基本都是这个套路。有的把草图坐标、拉伸距离、操作类型 token 化,训练一个类似 transformer 的自回归模型,专门输出 CAD 操作序列;也有直接用现成 LLM API,配合精心设计的 prompt 和 few-shot 示例,让模型输出 JSON 格式的操作树。后者落地更快,前者的上限更高——一旦掌握了“语言描述→建模操作序列”的映射规律,理论上可以做到不依赖通用 LLM 的推理能力,速度和可控性都会好很多。

2.2 路线二:从点云或深度图重建后拟合成 B-Rep

另一条路线是让模型先生成中间表示,比如点云、深度图或者多视角图片,再由后处理模块拟合出 B-Rep 曲面。这个思路的优点是可以复用大量视觉领域的成熟模型,比如把单张图片转成多视角深度图,再走曲面重建。

但实际跑下来的感受是:拟合这一步极其痛苦。B-Rep 曲面拟合需要处理面的分割、邻接关系、退化情况,一个自由曲面怎么切成若干张数学曲面,哪些边该缝在一起,这些问题的复杂度比生成点云高得多。即便用上最成熟的逆向软件,也很难全自动处理任意机械零件。这条路更适合扫描件的逆向建模,不太适合从零开始的 text-to-cad 场景。

2.3 路线三:扩散模型直接预测隐式实体场

学术界有不少人在探索用扩散模型直接生成带符号距离场(SDF)或者 occupancy field,再通过 marching cubes 提取等值面。这条路本质上还是生成网格,离真正的 B-Rep 更远,而且提取出来的网格依然面临 1.2 节说的所有问题。

诚实地讲,我一开始也尝试过把这类模型拿来做 text-to-cad 的前置形状生成器,结果发现就算形状已经很像了,后续的“网格转 CAD”依然是绕不过去的大山。当你想批量处理几百个零件的时候,任何一个需要人工干预的环节都会变成灾难。所以私下判断,这条路线更适合生成卡通形象、角色模型这类对精度和拓扑要求低的场景,短期内很难直接服务工程制造。

2.4 选型判断:序列生成为什么更适合工程化

三条路线我做了个简单对比:

维度LLM 序列生成点云/B-Rep 拟合扩散模型+隐式场
输出类型参数化操作序列B-Rep 曲面网格/隐式场
可编辑性强,带完整特征历史中,取决于拟合质量弱,几乎是死模型
对数据的依赖需要文本+操作序列对需要点云/B-Rep 配对数据需要大量网格或隐式场样本
工程落地难度中低高中
适合场景机械零件、标准件、快速原型逆向工程、扫描件游戏资产、渲染、概念草图

这个表格基本说明了我把主要精力放在序列生成上的原因。它跟工程师的思维模式天然一致——建模本来就是一步一个操作做出来的,AI 只是把这个过程自动化了。而且它输出的东西,用户可以接着改,不会变成一个黑盒死模型。

3. 关键细节与实操要点:数据、建模与“三保险”

3.1 数据从哪来:文本描述与 CAD 序列对的构造

想训练一个真正理解自然语言的 CAD 生成模型,最缺的其实是高质量配对数据。业界有一套深度学习常用的 CAD 操作序列数据集,大约包含十几万个来自 Fusion 360 的实体建模流程,已经将每步操作参数化并 token 化。模型可以从里面学会“这个操作序列对应什么形状”,但光有序列没有文本描述,没法解决 text-to-cad 的关键——对齐自然语言与建模动作。

实操中,我见过最有效的补充办法是“合成描述 + 反转改写”:先把每个 CAD 序列翻译成伪自然语言,例如“在 XY 平面画一个半径为 30 的圆,向上拉伸 20,在顶面中心切一个半径 7.5 的通孔”;再拿这些模板句去喂给通用大模型,让它改写成更自然、更多样的描述,比如“帮我做一个外径 60 的法兰,中间钻一个 15 毫米的孔”。把这两部分数据合起来做训练或评估,能明显提升对用户口语化输入的泛化能力。

还有一个细节是描述里必须带上“空间关系”。用户说“在板的左上角开一个孔”,这背后是坐标系理解、参考平面选择、边与边的距离等一连串隐含知识。数据增强阶段就要刻意加入方位词、相对尺寸词(“一半高”“两倍厚”)的变体,否则模型很容易学会表面话术,遇到真实需求就露馅。

3.2 模型结构与输出层怎么设计

如果是专用模型,常见做法是把 CAD 操作序列转换成离散 token,用自回归 transformer 训练。输入是文本描述 token 或者文本的 encoder 输出,输出是按顺序预测的 CAD 指令 token。推理结束再解码成参数化操作。这个方案的优点是推理快、可离线部署,缺点是训练成本高,而且要自己维护词表和序列化规则。

如果走通用 LLM 路线,我的建议不是让它直接输出可执行代码,而是输出一种自定义的中间 JSON 结构。比如这样:

{ "operations": [ { "type": "sketch_circle", "plane": "XY", "center": [0, 0], "radius": 30 }, { "type": "extrude", "distance": 20 }, { "type": "sketch_circle", "plane": "top", "center": [0, 0], "radius": 7.5 }, { "type": "cut", "through": true } ], "units": "mm" }

这种结构化输出比直接生成 CadQuery 代码稳得多。代码可以编译错,JSON 只要满足 schema 就能被解释器稳定消费;而且 JSON 方便做合法性校验、参数范围检查、分步回滚,后面接什么执行引擎都不冲突。

3.3 拓扑正确性的三道保险

第一道保险是 schema 校验。每个 JSON 操作节点都严格限制字段类型和取值范围,比如radius必须在 0.1 到 500 之间、operation type必须在白名单里。模型生成的数据一旦不满足 schema,直接触发重新生成或走修正循环,根本不会进入几何内核。

第二道保险是编译期的几何校验。CadQuery 和 FreeCAD 底层都是 OpenCASCADE,执行完操作后可以调用shape.Volume()检查实体体积是否为正数,也可以跑BRepCheck_Analyzer检查拓扑有效性。有相当一部分模型生成结果是“看起来合理但实际上有开放面”的死体,这一步能很高效地筛掉它们。

第三道保险是工程语义检查。几何有效不等于能加工,比如内孔直径是 3.17mm,看似正常,但放在公制环境里就是个诡异尺寸。我会在编译层加一组业务规则,比如尺寸取整数或常见小数、至少保留一个固定约束、禁止悬空特征。这类规则不需要模型理解,纯粹是硬编码约束,能很大程度上提升输出质量的稳定度。

4. 实操过程与核心环节实现:搭一个最小可用 Demo

4.1 技术栈选型

我实际搭过的最小可用系统,选型非常简单:一个本地部署的开源 LLM(量化到 7B 参数级别就够跑通流程),用它的结构化输出能力解析 JSON;后端用 CadQuery 作为几何执行引擎,导出 STEP 和 STL;调试阶段用 trimesh 简单加载 STL 看一看形状。整套链路不需要 GPU 集群,消费级显卡也能跑得动,因为大头开销在 LLM 推理,几何部分非常轻量。

如果对数据隐私比较敏感,建议本地部署 LLM,而不是把描述文本直接发到在线 API。设计图纸在制造业里往往是核心资产,很多团队对这一步的顾虑比对模型效果还大。实测来看,7B 级别的开源模型配合清晰的 few-shot 示例,处理中等复杂度的简单零件是够用的。

4.2 从自然语言到 JSON 中间表示

系统提示词我一般这样写:明确要求模型只输出 JSON,不输出任何解释;给出 schema 示例;强调单位是毫米;如果描述有歧义,通过一个questions字段向用户追问,而不是猜。下面是一个真实用过的示例片段:

你是机械 CAD 助手。根据用户需求生成模型操作序列。 你必须只输出 JSON,格式如下: ... 如果用户描述不够明确,比如缺少某个关键尺寸, 你必须在 "questions" 里列出你需要确认的问题, 不要假设默认值。

实测下来,“允许模型反问”这个设计特别重要。通用 LLM 面对缺参数的描述时,最喜欢自作主张填一个默认值,这在工程场景里很危险。一旦养成反问的习惯,生成结果的可用率会显著提升,因为第一次就没把方向带偏。

4.3 把 IR 编译成 CadQuery 并导出

拿到模型输出的 JSON 后,就是一个纯粹的遍历编译过程。我用 CadQuery 写过类似这样的骨架。注意这里只是示意风格,具体实现需要根据 schema 扩展:

import cadquery as cq import json def run_ops(ops): w = cq.Workplane("XY") for op in ops["operations"]: t = op["type"] if t == "sketch_circle": w = w.circle(op["radius"]) elif t == "extrude": w = w.extrude(op["distance"]) elif t == "sketch_circle_from_face": w = w.faces(">Z").workplane().circle(op["radius"]) elif t == "cut": w = w.cutBlind(op["distance"]) return w with open("result.json") as f: ops = json.load(f) result = run_ops(ops) print("volume:", result.val().Volume()) result.export("part.step") result.export("part.stl")

这段代码虽然简单,但已经覆盖了整个闭环:解析 IR、执行建模、输出可编辑的 STEP 文件和用于快速预览的 STL。跑一次从用户输入到文件落地的完整流程,在我机器上大约在十秒量级,大头是 LLM 生成时间,几何执行只需要零点几秒。

4.4 跑通后的实测结果与多轮修改

用这个链路实测了几个基础零件,最稳的是法兰盘、轴承座、带阵列孔的底板。用户说“给底板阵列 4×3 个直径 5 的孔”,系统输出 JSON 里包含循环信息,在编译层展开成 12 个洞口。整个流程非常顺。

更让我意外的是多轮修改的潜力。用户第一轮生成完以后说“孔太小了,改成 8 毫米”,系统只需要把历史操作 JSON 原样传回给 LLM,让它输出一个增量补丁,编译层重新执行一次完整历史即可。这个模式比重新生成一个模型省 token,也更符合设计师实际改图的习惯。后来我甚至把整个操作历史当成对话上下文来维护,效果比想象中好,因为模型能看到完整建模过程,不容易出现“新尺寸破坏了老特征”的荒谬错误。

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

5.1 快速排查速查表

现象可能原因排查思路解决手段
输出 JSON 解析失败模型产生了多余文字或 JSON 不完整查看原始输出,确认是否有包围层提示词里强调“只输出合法 JSON”,或者做二次修复查询
STEP 能打开但体积为 0草图未形成闭合轮廓或拉伸距离异常用BRepCheck_Analyzer检查拓扑降低操作复杂度,将草图约束到参考平面
布尔切除失败工具实体与被切除体不相交或共面打印每一步几何的包围盒在编译层自动修正切削深度为“穿透”
尺寸严重偏离预期LLM 误解了单位或描述里的数量关系人工检查 JSON 数值在 schema 中限定范围并追加单位强制声明
模型生成结果始终和描述无关few-shot 示例太少或格式混乱检查 prompt 中示例的覆盖范围增加各操作类型的正例,尤其是带空间关系的例

这张表里的每一条我几乎都真实遇到过,尤其是第二条和第四条,占比能到一半以上。很多所谓“失败案例”都不是模型听不懂人话,而是中间表示和执行引擎之间缺少一道校验导致的。

5.2 一次“看起来成功”的失败案例复盘

有一回我让系统生成一个“L 型支架,长边 100mm,短边 60mm,厚度 5mm,带三个直径 6 的安装孔”。系统输出的 JSON 非常漂亮,CadQuery 也执行成功,STEP 文件能打开,体积检查是正数,一切看起来都很完美。直到我把模型导入环境以后才发现问题:三个安装孔全部落在了同一块板上,且间距只有 12mm——意思是说其中两个孔钻在同一个安装面上,根本没有分布在短边方向和长边方向。

这就是典型的“语法正确但语义错误”。模型学会了输出合法 JSON,但没有真正理解“L 型支架”这个描述里隐含的几何拓扑结构。要解决这个问题,光靠 prompt 不行。后来我在 schema 里加了一个references字段,要求每个操作必须显式声明它基于哪个基准面或者哪条已有边;编译层再检查引用的是不是真实存在的拓扑实体。这个约束一加,虽然模型偶尔会犯糊涂,但至少大部分不合理的布局能在几何层就被拦住。

5.3 序列生成的工程化坑:安全、成本与交互

工程化和跑通 demo 完全是两码事。首当其冲的是安全:如果让模型直接生成 CadQuery 代码并执行,等同于允许 AI 在你机器上随便跑 Python,这是绝对不能接受的。所以我在任何面向外部用户的环境里都坚持用 IR 而不是代码,从源头杜绝注入风险。

其次是成本。用通用 LLM 生成的 token 数量比你想象的多,一个中等复杂零件可能要输出几千个 token 的操作信息。多轮修改场景下,每次迭代都重复发送历史记录,token 消耗会线性增长。我的经验是给系统加一个“操作历史压缩”机制,超过一定长度就把已经稳定的特征序列缩成摘要,只保留最近几轮的完整细节。

交互设计也值得多说一句。终端用户不像工程师那样知道什么尺寸必须明确,他们可能只会说“做一个差不多大小的盖子”。这时候系统如果不懂追问,生成结果大概率是废品。我后来在产品里加了一个“先确认关键尺寸,再生成模型”的引导式交互,用户回答三到四个问题之后,生成成功率提升了将近一倍。多问一句话,比让模型多猜十次都划算。

6. 影响范围:谁在用、能用到哪

6.1 下游设计工具链的连锁变化

text-to-cad 一旦成熟,最先被改变的其实是设计的起步阶段——概念生成和方案比选。过去设计师拿到一个需求,要在脑子里把需求翻译成建模步骤,然后一步一步在软件里执行。这个过程对一个熟练工程师来说也至少需要十几分钟到半小时。有了 text-to-cad,设计师可以直接输入一段模糊描述,得到三五个不同形态的候选模型,在参数化特征树层面快速比较方案,然后手工微调选中的那个。节省的不是画图时间,而是“从需求到设计草稿”的思考链路。

对于 3D 打印用户群体的影响更直接。大量普通人需要的是外壳、支架、堵头、卡扣这类简单零件,他们不会画图,更不需要装配公差和有限元仿真。一个响应足够快的 text-to-cad 服务,比让他们从零学一个 CAD 软件高效一个量级。所以我不太担心这个方向的市场大小,只担心当前生成质量还撑不起热情。

6.2 对算法团队的启发与机会

从算法角度看,text-to-cad 提供了一个很独特的落点:它把大模型的语义理解能力和传统几何内核连接起来了。这也意味着算法工程师不能只在 transformer 里打转,还必须理解 B-Rep、特征历史、约束求解这些 CAD 领域的老知识。复合型技能在这个方向上的溢价非常高。

我看到的机会包括:面向特定行业的垂直模型(比如只做钣金件或标准件)、与现有 PDM/PLM 系统结合的描述到图纸生成、以及基于历史设计数据的私有化模型微调。每一个方向都不是简单套一个开源模型就能交付,里面有的是脏活累活,也有的是竞争壁垒。

踩过这一路坑,我个人最大的体会是:text-to-cad 真正的瓶颈不在模型大小,而在“模型输出和几何内核之间的那道翻译桥”。谁能把中间表示、校验机制、执行引擎这层做好,谁就能在这个方向上占到先机。最后再分享一个小技巧:如果你也想快速验证 text-to-cad 的可行性,不用一上来就训练模型,先拿现成 LLM + CadQuery 跑通一个单机 demo,把校验和错误修正循环搭好,再逐步替换模型组件。这条路径的试错成本最低,也最容易看到效果。

RELATED READING

延伸阅读

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