1. 从一段文字到三维实体text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人会下意识觉得它是个噱头——输入一句话电脑就吐出一个能直接加工的模型这听起来像是把设计师十几年的手艺压缩成一次回车键。但如果你真的在机械设计、工业建模或者 3D 打印这条线上待过就会明白它瞄准的痛点非常具体从想法到可编辑几何体之间那段最枯燥、最重复、最容易出错的建模劳动。传统流程是这样的客户或工程师用文字描述需求比如一个 80×60×40 的底座四角各有一个 M6 沉头孔中心开一个直径 30 的通孔。设计师拿到这段话打开 CAD 软件画草图、拉伸、打孔、倒角一步步把文字翻译成几何。这个过程里文字描述本身是精确的但翻译动作是手工的一个尺寸看错、一个约束漏加后面全盘返工。text-to-cad 想做的就是把这段翻译自动化——让文字描述直接生成参数化的 CAD 模型输出成 STEP、GLB、STL 这些通用格式再交给下游去做渲染、仿真或者打印。它适合谁我梳理了三类人。第一类是做参数化零件批量设计的工程师比如标准件库、法兰、支架这类结构高度重复、只是尺寸不同的零件用文字驱动生成比手动画快一个数量级。第二类是3D 打印玩家和创客脑子里有个简单结构不想学 SolidWorks 的完整操作只想快速拿到一个 STL 去切片。第三类是做 AI 辅助设计工具开发的程序员需要理解 text-to-cad 的技术链路把它集成到自己的产品里。关键词里出现的 STEP、GLB、STL 不是随便列的它们代表了三种截然不同的下游用途。STEP 是精确的边界表示B-rep格式保留完整的曲面和实体信息是 CAD 软件之间交换数据的标准能继续编辑GLB 是 glTF 的二进制版本主打轻量化和 Web 渲染适合做可视化展示STL 则是三角网格只描述表面形状丢了拓扑和参数信息但几乎所有 3D 打印机和切片软件都认它。理解这三者的区别是理解整个 text-to-cad 工作流的前提——你生成的不是一个模型而是根据用途选择的一种几何表达。这篇文章我会把 text-to-cad 从输入到输出的完整链路拆开讲文字怎么变成结构化参数参数怎么变成几何几何怎么导出成不同格式以及我在实际跑这类流程时踩过的那些坑。不管你是想自己搭一套还是想评估现成工具能不能用这些内容应该都能帮上忙。2. 文字描述如何被翻译成可计算的几何参数2.1 自然语言里的尺寸信息为什么难提取很多人以为 text-to-cad 最难的是建模其实真正的地狱在第一步把一段人话解析成机器能用的结构化数据。人说话是带省略、带歧义、带行业黑话的。打个 M6 的孔——M6 是公称直径 6mm 的螺纹孔但到底是通孔、盲孔还是螺纹底孔沉头还是平头这些信息在口语里经常被省略因为说话的人默认对方懂。我做过一个统计在真实的零件描述文本里大约 40% 的关键几何信息是隐含的需要靠领域知识补全。比如四角各一个孔隐含了孔关于中心对称分布底座隐含了有一个大平面作为安装基准。如果解析器只做字面匹配生成的模型十有八九不能用。所以一个靠谱的 text-to-cad 前端通常不是单纯的大语言模型直接输出坐标而是大语言模型负责语义理解规则引擎负责几何约束补全。模型先把80×60×40 的底座四角 M6 沉头孔中心直径 30 通孔解析成一个中间表示类似下面这种结构{ type: plate, dimensions: {length: 80, width: 60, height: 40}, features: [ {type: hole, pattern: corner, count: 4, diameter: 6.6, countersink: {diameter: 12, angle: 90}}, {type: hole, position: center, diameter: 30, through: true} ] }注意这里 M6 沉头孔我写的是直径 6.6 而不是 6。这是实操里的一个关键细节M6 螺栓的通过孔标准直径是 6.6mm中等级配合不是 6mm。如果你按 6mm 生成螺栓根本插不进去。这种文字到实际尺寸的映射就是规则引擎要干的活。类似的知识还有M3 通孔 3.4mm、M4 通孔 4.5mm、M5 通孔 5.5mm沉头角度默认 90 度这些都得内置成一张对照表。2.2 中间表示层为什么不能直接生成坐标有人会问既然大语言模型这么强为什么不直接让它输出顶点坐标或者三角面片我试过这条路结论是能跑通但不可用。直接生成坐标的问题在于大语言模型对数值的精确控制能力很差。你让它生成一个 80mm 的边它可能给你 79.8 或者 80.3因为它本质上是在做概率预测不是在算数。而且一旦模型有几十个特征坐标之间的约束关系比如孔必须在面上、面必须平行很容易被破坏生成出来的东西看着像那么回事一测量全是错的。中间表示层的作用就是把语义和数值分开。大语言模型只负责把文字变成有哪些特征、特征之间什么关系具体的数值计算交给确定性的几何内核。这样即使模型理解错了语义至少数值是精确的而语义错误可以通过规则校验和人工确认来兜底。这个思路其实和编译器很像源代码自然语言先编译成中间代码IR再由后端生成机器码几何。中间表示层就是那个 IR它屏蔽了自然语言的模糊性又保留了足够的语义信息供后续处理。2.3 参数校验那些必须拦下来的错误输入解析完之后不能直接建模中间必须有一道校验。我踩过最惨的一次坑是用户输入直径 200 的孔打在一个100×100 的板上——孔比板还大几何内核直接报错崩溃。后来我加了一套校验规则至少拦住这几类问题校验类型检查内容处理方式尺寸合理性孔径是否小于所在面尺寸报错并要求确认特征冲突两个特征是否空间重叠警告并标出冲突区域数值范围尺寸是否在工艺可行范围内提示超出常规加工能力单位一致性是否混用 mm 和 inch强制统一或报错拓扑完整性特征是否会导致非流形几何拒绝生成并说明原因提示单位问题是最隐蔽的坑。用户写2 寸管你按 2mm 处理出来的东西完全不能用。我的做法是在解析阶段就强制要求带单位没带单位的按默认 mm 处理并在结果里显式标注让用户能一眼看到。这套校验看起来繁琐但它把大量错误挡在了建模之前比生成完再让用户去 CAD 里发现要友好得多。而且校验规则本身是可以积累的每遇到一个新的错误类型就加一条系统会越来越稳。3. 几何内核选型B-rep 还是网格这是个路线问题3.1 两种几何表达的本质差异到了真正生成几何这一步你会面临一个根本性的路线选择用 B-rep边界表示内核还是用网格mesh生成。这两条路出来的结果用途完全不同。B-rep 用数学曲面平面、圆柱面、NURBS 曲面来精确描述实体边界一个圆柱面就是一个方程不是一堆三角形。它的优势是精确、可编辑、体积小。你生成一个直径 30 的孔它就是数学意义上的正圆放大一万倍还是正圆。STEP 格式就是典型的 B-rep。缺点是计算复杂布尔运算比如打孔就是减法布尔容易失败尤其是特征多、曲面复杂的时候。网格路线则是把实体表面离散成一堆三角形。STL 就是纯网格。它的优势是简单、稳定、下游兼容性好几乎所有渲染引擎和 3D 打印机都直接吃网格。缺点是精度受三角面片密度限制一个圆孔其实是多边形近似而且丢了参数信息想改尺寸只能重新生成。我的经验是如果你的下游是 CAD 编辑或 CNC 加工必须走 B-rep如果下游是 3D 打印或 Web 展示网格就够了而且更省事。GLB 虽然底层也是网格但它带了材质和层级信息适合做可视化。3.2 主流几何内核的实操对比真要做 B-rep绕不开几个成熟内核。我把用过的几个列一下都是工业界在用的OpenCASCADEOCCT开源里最完整的 B-rep 内核STEP 读写、布尔运算、倒角圆角都有。Python 绑定是 pythonocc-core上手快。缺点是布尔运算偶尔会失败需要调容差参数。CGAL计算几何库布尔运算和网格处理很强但 B-rep 建模能力不如 OCCT更适合做几何算法而不是完整建模。Manifold专门做网格布尔运算的库速度快、结果稳定适合网格路线的 text-to-cad。CadQuery基于 OCCT 的 Python 参数化建模库语法接近自然语言非常适合做 text-to-cad 的后端。你几乎可以把中间表示直接映射成 CadQuery 的链式调用。我目前最推荐的组合是大语言模型解析 CadQuery底层 OCCT生成 按需导出 STEP/STL/GLB。CadQuery 的代码写起来像这样import cadquery as cq result ( cq.Workplane(XY) .box(80, 60, 40) .faces(Z).workplane() .rect(80, 60, forConstructionTrue) .vertices().cboreHole(6.6, 12, 6) # M6 沉头孔 .faces(Z).workplane() .hole(30) # 中心通孔 ) cq.exporters.export(result, base.step) cq.exporters.export(result, base.stl)这段代码的可读性极高几乎就是文字描述的直接翻译。这也是为什么我倾向于让大语言模型输出 CadQuery 代码而不是坐标——代码本身就是一种中间表示而且天然可执行、可调试。3.3 布尔运算失败的常见原因和绕法B-rep 路线最大的坑就是布尔运算失败。我遇到过的情况包括两个面恰好共面导致内核无法判断内外、倒角半径大于相邻边长度、孔的位置正好落在面的边界上。这些在数学上都是退化情况内核处理起来很脆弱。绕法有几个。第一给特征之间留微小间隙或过盈比如孔的位置稍微内缩 0.01mm避免正好落在边界。第二调整运算顺序先做大的减法再做小的减少中间状态的复杂度。第三设置合理的容差OCCT 的 fuzzy boolean 能容忍一定误差但容差太大会导致几何失真一般设在 1e-5 到 1e-4 之间。第四失败时降级到网格路线先保证能出结果再提示用户 B-rep 生成失败。注意布尔运算失败不是 bug是 B-rep 这种表达方式的固有特性。任何用 B-rep 的系统都会遇到区别只在于有没有做好兜底。评估一个 text-to-cad 工具时别只看它成功案例多漂亮要看它失败时怎么处理。4. 导出格式的门道STEP、GLB、STL 各自适合什么场景4.1 STEP精确交换的代价STEPISO 10303是 CAD 界的普通话SolidWorks、Fusion 360、中望 CAD、FreeCAD 都能读写。它保留完整的 B-rep 信息导出的文件在另一个软件里打开还能继续编辑尺寸、加特征。但 STEP 有个容易被忽略的问题不同软件对 STEP 的实现有差异。同一个文件在 A 软件里打开是实体在 B 软件里可能变成一堆曲面片。原因是 STEP 标准很宽泛各家的导出器对曲面缝合、容差处理不一样。我的做法是导出时尽量用 AP214 或 AP242 协议这两个对实体的支持最完整兼容性最好。另外 STEP 文件体积会比 STL 大不少因为存的是精确曲面方程而不是三角面片。一个中等复杂度的零件STEP 可能几 MBSTL 只有几百 KB。但这是值得的因为信息密度完全不同。4.2 STL3D 打印的通用语但精度要自己控STL 只存三角面片结构极简所以兼容性无敌。但它的精度完全取决于三角化的密度这个参数叫弦高chord tolerance或者偏差deviation。弦高设得小曲面就细腻但文件大设得大文件小但圆孔变成明显的多边形。我一般这样设做 3D 打印预览用 0.1mm 弦高做最终打印用 0.02mm。一个直径 30 的孔0.1mm 弦高下大概 60 个三角面肉眼已经看不出多边形0.02mm 下接近 200 个面基本和理论圆无异。STL 还分 ASCII 和二进制两种。ASCII 可读但体积是二进制的 5 到 6 倍实际用一律选二进制。有些老软件只认 ASCII那是历史遗留问题现在没必要迁就。4.3 GLB给 Web 和展示用的轻量格式GLB 是 glTF 的二进制打包格式专为实时渲染设计。它和 STL 一样是网格但多了材质、颜色、层级、动画这些信息。如果你的 text-to-cad 结果要在网页上展示、要给客户看 3D 预览GLB 是最合适的。从 B-rep 转 GLB 需要先三角化再走 glTF 导出。CadQuery 和 OCCT 都能直接导出 GLB但要注意坐标系——glTF 默认 Y 轴向上而 CAD 通常 Z 轴向上导出时得做一次旋转否则模型在网页里是躺着的。这个坑我踩过调了半天才发现是坐标系问题。格式几何类型可编辑典型体积主要用途STEPB-rep是大CAD 交换、CNC 加工STL三角网格否中3D 打印、快速预览GLB三角网格材质否小Web 展示、AR/VR选格式的逻辑很简单要改就 STEP要打就 STL要秀就 GLB。三者不是替代关系而是同一个模型在不同阶段的三种形态。一个成熟的 text-to-cad 流程应该能一键导出全部三种让用户按需取用。5. 把整条链路跑起来一个可复现的最小实现5.1 环境准备里最容易翻车的地方要自己搭一套 text-to-cad环境配置是第一道坎。我推荐的技术栈是 Python CadQuery 一个大语言模型 API。CadQuery 的安装有个经典坑它依赖 OCCT而 OCCT 的预编译包在不同平台上的可用性不一样。在 Linux 上pip install cadquery基本能一把过。在 Windows 上建议用 conda 装conda install -c conda-forge cadquery因为 conda 的包把 OCCT 的依赖都打包好了pip 有时候会缺 DLL。macOS 上 pip 也能用但 Apple Silicon 和 Intel 的包不一样装错了会报架构不匹配。还有一个坑是 Python 版本。CadQuery 对 Python 版本比较挑3.9 到 3.11 最稳3.12 有时候会有依赖冲突。我一般直接用 3.10 建虚拟环境省心。5.2 从文字到 CadQuery 代码的提示词设计让大语言模型输出可执行的 CadQuery 代码提示词是关键。我试了很多版最后稳定下来的结构是这样的你是一个 CAD 建模助手。用户会用自然语言描述一个零件你需要输出一段可执行的 CadQuery Python 代码。 规则 1. 所有尺寸单位默认为毫米mm。 2. 螺纹孔按标准通过孔直径处理M33.4, M44.5, M55.5, M66.6, M89。 3. 沉头孔默认 90 度沉头直径按标准M612, M816。 4. 代码必须以 result 变量结尾result 是 cq.Workplane 对象。 5. 不要输出任何解释文字只输出代码。 6. 如果描述有歧义选择最常见的工程解释。 用户描述{user_input}这个提示词里规则 2 和 3 就是前面说的领域知识补全把它写进提示词比写在代码里更灵活改起来方便。规则 6 很重要它让模型在信息不全时有个默认行为而不是卡住或者瞎猜。实测下来这套提示词对简单零件板、轴、支架的首次生成成功率大概在 80% 左右剩下的 20% 主要是描述太模糊或者特征太复杂。失败的时候把错误信息反馈给模型让它重试通常两三次能收敛。5.3 生成结果的自动验证与人工确认代码生成出来不能直接信得跑一遍验证。我的验证分三层第一层是语法和运行验证直接 exec 代码看有没有异常。这一步能拦住大部分低级错误。第二层是几何验证检查生成的实体是不是有效的valid solid、体积是不是正数、包围盒尺寸是不是和描述一致。CadQuery 的result.val().isValid()能查有效性result.val().Volume()能查体积。第三层是尺寸抽检从模型里提取关键尺寸和描述比对。比如描述说80×60×40就查包围盒是不是这三个数。这一步能发现模型理解偏差。三层都过了再输出给用户确认。用户看到 3D 预览确认没问题再导出最终格式。这个生成-验证-确认的闭环是把 text-to-cad 从玩具变成工具的关键。6. 实战中那些文档不会写的坑6.1 中文描述的解析比英文难在哪如果你的用户用中文描述难度会上升一个台阶。中文的工程表达有几个特点量词和单位经常省略打个 6 的孔、方位词模糊边上到底是哪条边、专业术语和口语混用沉孔和沉头孔是一回事。我的处理办法是建一个同义词映射表把常见的口语表达映射到标准术语。打个孔→hole挖空→cut倒个角→fillet圆角→fillet倒角→chamfer。这个表是慢慢积累的每遇到一个新说法就加一条。另外中文数字和阿拉伯数字要统一处理六个孔和6 个孔得解析成一样。还有一个隐蔽的坑是全角和半角。用户输入直径用的是全角数字直接解析会失败。预处理阶段统一转半角能省很多事。6.2 复杂模型的性能瓶颈在哪简单零件几个特征生成很快几秒钟的事。但特征一多性能会断崖式下降。我测过一个有 50 个孔的板布尔运算花了将近 30 秒。瓶颈在 B-rep 的布尔运算每加一个孔就是一次减法50 次减法累积起来很慢。优化思路有两个。一是合并相同特征50 个孔如果直径一样可以用阵列pattern一次生成而不是循环 50 次布尔。CadQuery 的rarray或者polarArray就是干这个的。二是延迟布尔先把所有孔的位置算好最后一次性做布尔而不是边加边算。OCCT 对这种批量操作有优化。如果实在慢还有个降级方案先生成网格版本给用户看预览B-rep 版本后台慢慢算。用户看到预览确认了B-rep 也差不多算完了。这个体验比干等 30 秒好得多。6.3 生成结果的看起来对和真的对这是我最想强调的一点。text-to-cad 生成的东西视觉上正确和几何上正确是两回事。一个孔位置偏了 0.5mm在屏幕上根本看不出来但装配的时候就是装不上。一个面其实有 0.01mm 的缝隙渲染时看不出来但导出 STEP 后下游软件会报非实体。所以验证不能只靠眼睛看。我的做法是关键尺寸必须用程序提取出来和输入比对不能靠人眼。包围盒、孔径、孔位、壁厚这些能量化的都量化。人眼只负责看整体形状对不对精确性交给程序。提示如果你在做面向生产的 text-to-cad建议加一个尺寸报告功能把生成模型的所有关键尺寸列出来让用户逐项确认。这个功能看起来笨但能避免大量返工。7. 这套东西的边界在哪以及怎么继续往下走text-to-cad 现在的能力边界很清楚它擅长规则明确、结构重复、参数驱动的零件不擅长自由曲面、有机形状、需要审美判断的设计。你让它生成一个带复杂曲面的外壳它做不好你让它生成一百个尺寸不同的法兰它做得又快又准。所以定位很重要。别把它当成替代设计师的工具把它当成把设计师从重复劳动里解放出来的工具。设计师的价值在于判断该做什么形状text-to-cad 的价值在于把这个形状快速、精确地变成几何。我自己在实际项目里的体会是这套流程最舒服的用法是**文字生成初稿 人工微调**。让 text-to-cad 生成一个 80% 可用的模型设计师在 CAD 里花几分钟调整剩下的 20%比从零开始画快得多。纯自动化的全流程目前还只在很窄的场景里可行。后续可以扩展的方向我觉得有两个值得关注。一是和参数化设计结合生成的模型不是死的而是带参数的改一个尺寸整个模型跟着变。二是多模态输入除了文字还能接受草图、参考图甚至语音让输入方式更自然。这两个方向都在快速演进值得持续跟进。最后分享一个小技巧如果你只是想快速验证一个想法不需要精确的 B-rep直接用网格路线Manifold 或者 trimesh生成 STL几秒钟就能拿到结果去打印。等验证完了再回头用 B-rep 做精确版本。先跑通再跑准这个顺序能帮你省下大量时间。
阅读完成 · 觉得有帮助?