
1. 从一段文字到三维模型text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人脑子里浮现的画面可能是对着电脑敲一句给我画一个法兰盘然后屏幕上就自动出现一个带螺栓孔的三维模型。这个想象不算离谱但真正落地的时候它解决的问题比自动画图要具体得多也有意思得多。text-to-cad 的核心链路是把自然语言描述转换成参数化的三维几何数据再导出成下游能直接用的格式比如 STEP、GLB、STL。它瞄准的不是替代资深结构工程师去做复杂装配体设计而是解决那些重复、琐碎、有规律、但手工建模很烦的场景。举个最典型的例子你需要一批不同尺寸的垫片、支架、盒子、齿轮毛坯每个都要改几个参数重新建模。传统做法是打开 CAD 软件改草图、改拉伸、重新导出一个下午就没了。而 text-to-cad 的思路是你用一句话描述尺寸和形状程序直接生成几何体并导出文件。这套东西适合谁我观察下来主要是三类人。第一类是做批量零件或标准件的工程师他们需要快速产出大量变体模型。第二类是做仿真、渲染、3D 打印的开发者他们需要程序化地拿到 STL 或 GLB 文件而不是手动建模。第三类是做 AI 应用的产品和技术人员想把文字生成三维这个能力接进自己的工具链里。这三类人的共同点是他们要的不是精美的曲面造型而是能用的、参数正确的、格式标准的几何数据。关键词里出现的 STEP、GLB、STL 三个格式其实就对应了三条不同的下游路线。STEP 是 CAD 领域的通用交换格式精度高、带 B-rep 实体信息适合回流到专业 CAD 软件里继续编辑。GLB 是 glTF 的二进制打包格式轻量、带材质和层级适合网页 3D 展示和游戏引擎。STL 是三角网格格式只有表面几何、没有拓扑但它是 3D 打印和很多仿真软件的事实标准。理解这三个格式的差异是理解 text-to-cad 整个价值链条的钥匙后面我会专门拆开讲。需要先说明一点text-to-cad 不是一个现成的、开箱即用的商业软件名字它更像是一类技术方案的统称。市面上有开源项目、有 API 服务、也有自己攒的工具链。所以这篇文章不会只讲某一个工具而是把这类方案的通用原理、选型逻辑、实操步骤和踩坑经验讲透你拿到任何一套具体实现都能对号入座。2. 拆解 text-to-cad 的技术链路文字是怎么变成几何体的2.1 自然语言到结构化参数的转换层整条链路的第一环是把人话变成机器能算的参数。这一步看起来简单实际上是最容易翻车的地方。用户说一个长 50 宽 30 高 20 的盒子壁厚 2 毫米人一听就懂但程序要从中抽出长度、宽度、高度、壁厚四个数值还要知道它们分别对应哪个几何维度。常见的做法有两种。一种是基于大语言模型做信息抽取让模型输出一段结构化的 JSON比如{type: box, length: 50, width: 30, height: 20, wall: 2}。另一种是基于规则模板匹配用正则或者语法解析去抓关键词和数字。两种方式各有取舍大模型灵活、能处理各种口语化表达但可能不稳定、偶尔抽错规则匹配稳定可控但用户稍微换个说法就识别不了。我自己的经验是生产环境里最好两者结合。先用大模型做一轮抽取再用规则做校验和兜底。比如模型抽出来的长度是负数或者大得离谱规则层就该拦下来报错而不是傻乎乎地拿去建模。这一步的稳定性直接决定了整个系统的可用性因为几何建模本身是确定性的输入错了后面全错。2.2 参数化几何的生成从 JSON 到实体拿到结构化参数之后就进入真正的几何生成环节。这里主流的工具有几个方向。一个是基于 OpenCASCADE 这类几何内核用代码直接构造 B-rep 实体这种方式生成的模型精度高、能导出 STEP。另一个是基于网格建模库比如用 trimesh、numpy-stl 这类库直接拼三角面片适合快速产出 STL。还有一种是调用 CAD 软件的脚本接口比如用 Python 驱动 FreeCAD 或者用脚本控制专业 CAD让它按参数建模再导出。选哪条路取决于你的下游要什么。如果最终要 STEP那基本绕不开几何内核因为 STEP 需要精确的边界表示网格数据转过去会丢精度。如果只要 STL 做打印那网格库就够了还更轻量。如果团队本来就在用某个 CAD 软件那用它的脚本接口最省事生成的模型天然兼容。这里有个很多人忽略的点几何内核的布尔运算比如挖孔、开槽、求交是有失败率的。参数稍微极端一点比如壁厚小于某个阈值、孔的位置刚好在边缘布尔运算就可能报错或者生成破面。所以生成环节必须做结果校验检查实体是否有效、体积是否合理、有没有自相交。这一步不做导出的文件到了下游软件里打开就是一堆烂面排查起来非常痛苦。2.3 格式导出STEP、GLB、STL 各自的门道导出这一步看着只是调个 API其实坑不少。STEP 导出要注意单位很多内核默认是毫米但有些场景要米单位错了模型尺寸就差一千倍。GLB 导出要注意坐标系glTF 用的是 Y 轴向上而很多 CAD 用 Z 轴向上不做转换的话模型在网页里就是躺着的。STL 导出要注意是二进制还是 ASCII二进制体积小、加载快ASCII 可读但文件巨大3D 打印一般用二进制。还有一个隐蔽的坑STL 没有单位信息。STL 文件里只有一堆三角面片的坐标它不知道自己是毫米还是英寸。所以导出 STL 的时候尺寸必须在下游软件里手动指定单位否则打印出来的东西可能大得离谱或者小得看不见。这个坑我踩过不止一次后面会详细讲。3. 格式选型实战STEP、GLB、STL 到底该用哪个3.1 三种格式的本质差异对照很多人选格式是凭感觉或者别人用啥我用啥。其实这三种格式的差异是结构性的选错了后面全是麻烦。我用一张表把关键差异列清楚。维度STEPGLBSTL几何表示B-rep 精确实体三角网格 材质三角网格是否带拓扑带能识别面/边/体部分带层级不带只有面片单位信息带带米不带文件体积中等小二进制小 / ASCII 大可否再编辑可以回流 CAD有限适合展示基本不能典型用途CAD 交换、加工网页/引擎展示3D 打印、仿真精度高中取决于网格密度看懂这张表选型就清楚了一大半。要回流到 CAD 继续设计选 STEP。要在网页或者游戏里展示选 GLB。要送去 3D 打印或者做有限元网格选 STL。3.2 什么时候必须用 STEPSTEP 的核心价值是精确和可编辑。它保存的是数学意义上的曲面和实体不是近似的三角面片。所以当你需要把模型交给加工中心、需要做精确的装配干涉检查、或者需要在下游 CAD 里继续改特征的时候STEP 是唯一选择。但 STEP 也有代价。它的生成依赖几何内核内核的布尔运算可能失败导出可能报错。而且 STEP 文件在不同 CAD 软件之间传递时偶尔会出现破面或者实体变曲面的情况这通常是因为内核版本或者精度设置不一致。我的建议是导出 STEP 之后一定要用目标 CAD 软件实际打开验证一遍别假设它能用。3.3 GLB 在展示场景里的优势与陷阱GLB 最大的优势是轻和通用。它是为实时渲染设计的文件小、加载快、浏览器原生支持。如果你要做的是一个输入文字、网页上立刻看到 3D 模型的产品GLB 几乎是默认答案。但 GLB 的陷阱在于坐标系和缩放。glTF 规范规定 Y 轴向上、单位是米而绝大多数 CAD 数据是 Z 轴向上、单位是毫米。直接导出的话模型要么躺着要么小一千倍。正确做法是在导出时做一次坐标变换和单位换算把 Z-up 转成 Y-up把毫米转成米。这个转换不难但忘了就会得到一个看起来啥都没有的网页。3.4 STL 用于 3D 打印时的单位与精度控制STL 是三个格式里最糙的但它在 3D 打印领域是绝对主流。用 STL 有两个关键参数要控制网格密度和单位。网格密度决定了模型的精细程度。太粗曲面变成多边形打印出来有明显的棱角太细文件巨大切片软件卡死。一般经验是对于直径 50 毫米左右的圆柱圆周方向 64 到 128 个分段比较合适。这个值可以通过弦高公差来控制公差越小网格越密。单位问题前面提过STL 不带单位所以导出时你心里要清楚这个模型是毫米数值到了切片软件里要选毫米。我见过有人导出的模型在切片软件里显示成 0.05 毫米高就是因为单位没对上。4. 手把手搭一条最小可用的 text-to-cad 流水线4.1 环境准备与依赖选择要自己搭一条流水线先得把工具选好。我推荐一套对新手比较友好的组合用 Python 做胶水语言用大模型 API 做文字解析用 CadQuery 或者 build123d 做参数化建模用 trimesh 做网格处理和 STL 导出。CadQuery 是基于 OpenCASCADE 的 Python 建模库语法接近自然描述适合做参数化零件。build123d 是它的新一代替代API 更现代。trimesh 则是网格处理的多面手读 STL、转格式、算体积都很方便。这套组合的好处是全部开源、文档齐全、社区活跃。安装上CadQuery 建议用 conda 装因为它的几何内核依赖比较重pip 装容易出问题。trimesh 用 pip 就行。大模型 API 看你用哪家按官方文档配好 key 即可。conda create -n text2cad python3.11 conda activate text2cad conda install -c conda-forge cadquery pip install trimesh openai4.2 用大模型把一句话解析成参数字典假设用户输入生成一个外径 40、内径 20、厚度 5 的圆环。我们要把它变成{type: ring, outer_d: 40, inner_d: 20, thickness: 5}。用大模型做这件事关键是把输出格式约束死让它只吐 JSON不要废话。import json from openai import OpenAI client OpenAI() PROMPT 你是一个参数抽取器。把用户的几何描述转成 JSON。 只输出 JSON不要任何解释。字段包括 type 和尺寸参数。 支持的 type: box, cylinder, ring, plate。 def parse_text(user_input): resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: PROMPT}, {role: user, content: user_input}, ], response_format{type: json_object}, ) return json.loads(resp.choices[0].message.content)这里用response_format强制 JSON 输出能大幅降低解析失败率。但即便如此仍然要做字段校验因为模型可能给出不存在的 type 或者缺失参数。校验层是保命的别省。4.3 用 CadQuery 生成实体并导出 STEP拿到参数字典后就可以建模了。以圆环为例CadQuery 的写法很直观。import cadquery as cq def build_ring(outer_d, inner_d, thickness): return ( cq.Workplane(XY) .circle(outer_d / 2) .circle(inner_d / 2) .extrude(thickness) ) def export_step(model, path): cq.exporters.export(model, path)生成之后务必做一次有效性检查。CadQuery 的实体有isValid()方法返回 False 就说明几何有问题这时候要么调整参数要么报错给用户千万别硬导出。4.4 转成 STL 和 GLB 的完整代码从同一个实体出发导出 STL 和 GLB 也不难。STL 可以直接用 CadQuery 导出GLB 则建议先转成网格再用 trimesh 处理。import trimesh def export_stl(model, path, tolerance0.01): cq.exporters.export(model, path, tolerancetolerance) def export_glb(model, path): # 先导出临时 STL再转 GLB cq.exporters.export(model, /tmp/tmp.stl) mesh trimesh.load(/tmp/tmp.stl) # Z-up 转 Y-up mesh.apply_transform(trimesh.transformations.rotation_matrix( -3.14159 / 2, [1, 0, 0])) mesh.export(path, file_typeglb)这段代码里那个旋转矩阵就是解决坐标系问题的关键。少了它GLB 在网页里就是躺着的。5. 那些文档里不会写的坑我在实操中踩过的雷5.1 布尔运算失败最常见的玄学报错布尔运算失败是几何建模里最让人抓狂的问题。你参数明明没问题代码也没错但内核就是告诉你运算失败。原因通常有几个面重合两个实体刚好贴在一起内核分不清内外、精度冲突不同来源的几何精度不一致、退化几何某个面小到接近零。解决办法我总结了几条。第一给布尔运算留余量比如挖孔的时候让孔的深度比板厚多一点点避免刚好穿透。第二统一精度所有几何用同一套公差设置。第三失败时重试有时候微调一下参数比如把 20.0 改成 20.001就能过。第四实在不行就换内核或者换建模顺序。5.2 STL 单位丢失导致的打印灾难这个坑我印象太深了。有一次导出一个 100 毫米的零件切片软件里显示成 0.1 毫米我以为是软件 bug折腾半天才发现是单位问题。STL 本身不带单位切片软件默认按毫米读但如果你的建模环境用的是米导出的数值就是 0.1切片软件读成 0.1 毫米。规避方法很简单建模阶段统一用毫米导出前确认数值范围合理。一个 100 毫米的零件STL 里的坐标应该在 -50 到 50 之间如果看到 -0.05 到 0.05那就是单位错了。5.3 GLB 坐标系翻转引发的模型躺平前面提过glTF 是 Y-upCAD 是 Z-up。忘了转换模型在网页里就是躺着的。更麻烦的是有些转换工具会自动帮你转有些不会导致你搞不清到底转没转。我的做法是在导出 GLB 的代码里显式写死转换不依赖任何工具的默认行为这样行为可预测。5.4 大模型解析不稳定时的兜底策略大模型偶尔会抽风把外径 40理解成半径 40或者漏掉一个参数。这时候如果直接拿去建模出来的就是错的东西。兜底策略有三层格式校验字段齐不齐、类型对不对、范围校验数值在不在合理区间、语义复核把解析结果回显给用户确认。第三层最有效让用户看一眼我理解的是外径 40、内径 20、厚 5对吗确认了再建模能挡掉绝大多数错误。6. 把 text-to-cad 接进真实工作流的几种姿势6.1 批量生成标准件变体这是 text-to-cad 最实用的场景。比如你要生成 50 个不同尺寸的法兰与其手工建模 50 次不如写个循环把尺寸列表喂进去批量生成 STEP 和 STL。这种场景下文字输入其实可以简化成参数表大模型那一层甚至可以省掉直接用模板加参数就行。text-to-cad 的价值在于把描述和几何解耦描述可以是自然语言也可以是结构化数据。6.2 和现有 CAD 工具链的衔接很多团队已经有自己的 CAD 工作流text-to-cad 不是要替代它而是补上快速产出初版模型这一环。生成的 STEP 可以直接导入现有 CAD 继续细化生成的 STL 可以直接进切片软件。关键是格式要标准、单位要统一、命名要规范否则接进去还得手工修就失去意义了。6.3 面向 3D 打印的自动化出图3D 打印用户最需要的是描述即打印。你说要一个手机支架程序生成 STL直接丢进切片软件。这条链路里text-to-cad 省掉的是建模这一步但打印前的检查不能省模型是否封闭、壁厚是否够、有没有悬空结构。这些检查可以程序化做比如用 trimesh 检查水密性用切片软件的 CLI 做预切片。7. 关于精度、性能与扩展性的几点个人体会做了一段时间 text-to-cad我最大的体会是这东西的难点不在生成而在保证生成的东西是对的。几何建模本身是确定性的代码写对了就一定能出结果但对的结果需要一整套校验和兜底机制来保障。参数校验、几何有效性检查、格式转换验证这三道关卡一个都不能少。性能上单次生成的耗时主要花在几何内核的布尔运算上简单零件几百毫秒复杂零件可能几秒。如果要批量生成建议做并行处理因为每个零件是独立的天然适合多进程。但要注意几何内核不一定线程安全用多进程比多线程稳妥。扩展性方面我建议把整个链路设计成插件式的解析层、建模层、导出层各自独立换大模型不影响建模换几何内核不影响导出。这样以后想支持新的输入方式比如语音、草图或者新的输出格式比如 3MF、OBJ只需要加一个插件不用动核心逻辑。最后分享一个小技巧给每个生成的模型算一个哈希基于输入参数和输出格式。这样同样的请求可以直接命中缓存省掉重复计算。批量场景下这个优化能省掉大量时间尤其是那些反复生成相同标准件的情况。