1. 从一段文字到三维实体text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人会下意识觉得它是个噱头——用一句话就能生成 CAD 模型这听起来像是把设计师十几年的功夫一笔勾销。但真正在机械设计、工业建模或者 3D 打印这条线上摸爬滚打过的人看到这个词的第一反应往往不是怀疑而是终于有人来啃这块硬骨头了。我做了十多年结构设计和三维建模日常打交道最多的就是各种格式的模型文件STEP、STL、GLB、IGES、OBJ。每次接到一个新需求从脑子里有个模糊的形状到最终能拿去加工或者打印的文件中间要经历草图、拉伸、倒角、装配、导出这一长串流程。哪怕只是改一个孔径、挪一个安装位都得重新打开软件、找到特征树、一层层点进去。text-to-cad 想做的事情本质上是把描述和几何之间的那道墙给拆掉——你用自然语言说清楚你要什么系统直接给你吐出可用的三维模型文件。这件事的价值不在于取代设计师而在于把重复性、模板化的建模劳动压缩掉。举个很实际的例子做非标设备的朋友经常要画各种支架、法兰、连接件这些东西结构高度相似只是尺寸和孔位不同。以前的做法是建一个参数化模板每次改参数、重新生成、导出。现在如果 text-to-cad 能理解一个 80x80 的角铝支架两侧各两个 M6 沉头孔中心一个 30mm 通孔直接生成 STEP 文件那省下来的时间就是实打实的。关键词里出现的 STEP、GLB、STL 这三个格式恰好对应了 text-to-cad 输出环节最核心的三条路径。STEP 是工业界的通用交换格式精度高、带 B-rep 实体信息适合后续在 SolidWorks、中望 CAD、UG 这些软件里继续编辑STL 是 3D 打印的通用格式只有三角面片没有特征信息但胜在兼容性无敌GLB 则是 Web 和 AR/VR 场景的主力轻量、带材质、能直接在浏览器里渲染。一个成熟的 text-to-cad 工具必须能根据用户的下游用途把同一份几何数据导出成不同格式而不是只给一个看起来像的模型。这篇文章适合谁看如果你是做机械设计、产品结构、3D 打印服务、或者在做 AI 辅助设计工具开发的这里面的内容应该能帮你少走不少弯路。如果你只是好奇文字生成 CAD到底靠不靠谱我也会把它的能力边界、常见坑、以及实际能落地的操作流程讲清楚。我不会给你画大饼只讲我实际试过、踩过、验证过的东西。2. 文字如何变成几何text-to-cad 的底层链路拆解2.1 从自然语言到结构化参数语义解析这一步决定了上限text-to-cad 的第一道关卡是把人话翻译成机器能理解的参数。这一步听起来简单实际上是最容易翻车的地方。你说一个圆柱体直径 50高 100这没问题参数明确。但如果你说一个差不多拳头大小的圆柱系统就懵了——拳头大小到底是多大不同的人拳头尺寸差很多。所以真正能用的 text-to-cad 系统在语义解析层通常会做几件事。第一建立领域词表和同义词映射。比如沉头孔和埋头孔是一回事通孔和贯穿孔是一回事倒角和倒边在很多场景下指的是同一个操作。第二做单位推断和默认值填充。如果你没说单位系统要根据上下文猜是毫米还是英寸如果你没说壁厚系统要给一个合理的默认值而不是直接报错。第三做约束提取。你说两个孔对称分布系统要能理解这是关于中心面的对称约束而不是随便放两个孔。我实测过几个开源的 text-to-cad 方案发现一个规律凡是语义解析做得粗糙的后面几何生成再强也白搭。因为参数错了模型就是错的精度再高也没用。反过来如果语义解析能把用户的模糊描述补全成一套完整的参数集哪怕几何生成用的是比较基础的建模内核出来的东西至少是可用的。这里有个很实用的经验如果你在开发或者使用 text-to-cad 工具一定要在语义解析层加一个参数确认环节。系统解析完你的描述后先把提取到的参数列出来让你确认比如检测到以下参数长度 80mm、宽度 80mm、孔径 6mm、孔数 4、沉头角度 90 度是否正确这一步看似多余实际上能挡掉后面 80% 的返工。2.2 参数化建模内核为什么 OpenCASCADE 是绕不开的选择语义解析出参数之后下一步就是把这些参数变成真正的三维几何。这一步需要一个建模内核而在这个领域OpenCASCADE 几乎是开源方案里唯一能打的选择。OpenCASCADE 是一套开源的 B-rep 建模内核支持实体建模、布尔运算、倒角、抽壳、放样这些 CAD 核心操作。它的优势在于成熟、稳定、文档相对齐全而且能直接导出 STEP 格式。你在 FreeCAD、KiCad 的 3D 查看器、以及很多工业软件里看到的建模能力底层都是 OpenCASCADE 在撑着。但 OpenCASCADE 有个很现实的问题学习曲线陡峭。它的 API 设计是典型的 C 风格对象生命周期管理、异常处理、坐标系变换这些都需要花时间啃。如果你只是想快速验证 text-to-cad 的想法直接用 OpenCASCADE 可能会被它的复杂度劝退。我的建议是分两条路走。如果你要做的是工业级、需要精确 B-rep 实体的应用那 OpenCASCADE 是绕不开的老老实实啃文档、写测试用例。如果你只是想快速出原型、验证语义到几何的映射逻辑可以先用 Python 的 cadquery 或者 build123d 这类高层封装库。cadquery 底层也是 OpenCASCADE但 API 友好很多写起来像在写脚本import cadquery as cq result (cq.Workplane(XY) .box(80, 80, 10) .faces(Z).workplane() .hole(30) .faces(Z).workplane() .rect(60, 60, forConstructionTrue) .vertices().cboreHole(6, 12, 6) ) cq.exporters.export(result, bracket.step)这段代码做的事情就是创建一个 80x80x10 的方块中心打一个 30mm 通孔四角打四个 M6 沉头孔最后导出 STEP。如果 text-to-cad 系统能把自然语言解析成这样的参数化脚本那整个链路就通了。2.3 网格化与格式转换STL 和 GLB 的生成逻辑STEP 文件生成之后如果你要拿去 3D 打印或者放到网页上展示还需要转成 STL 或 GLB。这一步的核心操作是网格化——把 B-rep 实体表面离散成三角面片。网格化的质量直接决定了 STL 文件的可用性。这里有个关键参数叫线性偏差和角度偏差。线性偏差控制的是曲面被三角面片逼近时的最大误差角度偏差控制的是相邻面片之间的最大角度变化。这两个值设得越小网格越精细文件越大但形状越接近原始实体。设得太大圆柱会变成多边形球体会变成多面体打印出来就是一层层的棱角。我一般给 3D 打印用户的建议是线性偏差设 0.01mm 到 0.05mm角度偏差设 5 到 10 度。这个范围能在文件大小和精度之间取得比较好的平衡。如果是大尺寸模型比如 300mm 以上的零件线性偏差可以放宽到 0.1mm否则文件会大到切片软件都打不开。GLB 的生成逻辑稍微不同。GLB 是 glTF 的二进制版本它需要的不只是几何还有材质、法线、UV 坐标这些渲染相关的信息。从 STEP 转 GLB通常要经过 STL 或者 OBJ 作为中间格式然后再用 trimesh、assimp 这类库做转换。这里有个坑STEP 里的颜色和材质信息在转网格的过程中很容易丢失如果你需要保留外观得在转换前把材质信息单独提取出来转换后再重新绑定。3. 格式选型实战STEP、STL、GLB 到底该用哪个3.1 STEP 的不可替代性为什么工业场景必须用它在 text-to-cad 的输出环节STEP 是唯一能保留完整 B-rep 实体信息的格式。这意味着什么意味着你拿到 STEP 文件之后可以在 SolidWorks 里打开它看到完整的特征树能继续倒角、打孔、做装配。而 STL 和 GLB 做不到这一点它们只有三角面片没有特征信息你没法在 STL 上把孔径从 6mm 改成 8mm只能重新建模。我遇到过很多次这种情况客户发来一个 STL 文件说把这个孔改大一点我只能苦笑。STL 改孔本质上是在网格上重新挖洞、补面操作起来极其麻烦而且精度很难保证。如果当初给的是 STEP改孔就是几秒钟的事情。所以 text-to-cad 系统如果面向的是工业设计、机械制造、模具这些场景STEP 必须是默认输出格式。STL 和 GLB 只能作为辅助格式用于预览、打印或者展示。但 STEP 也有它的麻烦之处。STEP 文件体积通常比 STL 大传输和存储成本更高。而且不同软件对 STEP 的兼容性有差异有时候在 SolidWorks 里打开正常的 STEP到中望 CAD 里就报错。这通常是因为 STEP 的版本不同或者建模内核的容差设置不一致。我的经验是导出 STEP 时尽量用 AP214 或者 AP242 协议这两个版本的兼容性最好。3.2 STL 的精度陷阱为什么你的打印件总是有棱角STL 是 3D 打印领域的事实标准几乎所有的切片软件都支持。但 STL 的精度问题是新手最容易踩的坑。前面提到过STL 是三角面片网格曲面的精度取决于网格密度。如果你在 text-to-cad 系统里生成 STL 时没有正确设置网格参数出来的圆柱可能只有 12 个面打印出来就是一个十二边形而不是圆。这个问题在打印小尺寸零件时特别明显因为切片软件会进一步放大网格的缺陷。我自己的做法是在 text-to-cad 的导出环节给 STL 设置一个基于模型尺寸的自适应网格策略。具体来说线性偏差取模型包围盒对角线的 0.1% 到 0.5%角度偏差取 5 到 15 度。这样小模型自动获得高精度大模型不会因为网格过密而文件爆炸。还有一个容易被忽略的点STL 文件没有单位。STL 的坐标值就是纯数字切片软件默认按毫米处理。如果你的 text-to-cad 系统内部用的是米或者英寸导出 STL 时一定要做单位换算否则打印出来的尺寸会差 25.4 倍或者 1000 倍。这个坑我见过太多次了每次都是打印到一半才发现尺寸不对浪费材料和时间。3.3 GLB 的轻量化优势网页展示和 AR 预览的首选GLB 在 text-to-cad 的输出场景里主要承担的是展示和交互的角色。它的优势很明显文件小、加载快、支持材质和动画、浏览器原生支持。如果你要把生成的模型嵌入到网页里让客户旋转查看或者放到 AR 应用里做预览GLB 是最合适的选择。但 GLB 的几何精度通常不如 STEP 和 STL。因为 GLB 面向的是实时渲染面片数量需要控制太精细的网格会导致帧率下降。所以从 STEP 转 GLB 时通常会有意识地降低网格密度牺牲一点精度换取流畅的交互体验。这里有个实操建议如果你的 text-to-cad 系统要同时输出 STEP、STL、GLB 三种格式不要用同一条网格化流水线。STEP 直接导出STL 用高精度网格GLB 用低精度网格加材质。这样每种格式都能发挥它的优势而不是互相将就。格式核心用途精度文件大小可编辑性推荐场景STEP工业交换最高B-rep中等完整特征机械设计、模具、后续编辑STL3D 打印取决于网格较大无特征切片打印、快速原型GLB网页/AR 展示中等最小无特征在线预览、AR 交互、展示4. 把 text-to-cad 跑起来从环境搭建到第一个模型4.1 环境准备Python 生态是最快路径如果你要自己搭一套 text-to-cad 的验证环境Python 是目前最省事的选择。cadquery 和 build123d 这两个库把 OpenCASCADE 的复杂度封装掉了大半让你能用比较直观的方式描述几何。安装 cadquery 很简单pip install cadquery但这里有个坑cadquery 依赖 OpenCASCADE 的二进制库在 Windows 上通常没问题在 Linux 上可能需要额外装一些系统依赖比如 libgl1、libglu1-mesa 这些。如果你用 Docker建议基于 python:3.10-slim 镜像然后手动装依赖不要用 alpine 镜像因为 OpenCASCADE 在 musl libc 上编译很麻烦。装完之后跑一个最简单的测试import cadquery as cq # 创建一个 50x50x50 的立方体 box cq.Workplane(XY).box(50, 50, 50) # 导出 STEP cq.exporters.export(box, test.step) # 导出 STL设置网格精度 cq.exporters.export(box, test.stl, tolerance0.01, angularTolerance0.1)如果这两行导出都成功了说明环境没问题。接下来就可以把自然语言解析的结果映射到 cadquery 的 API 调用上。4.2 语义到代码的映射一个可落地的实现思路text-to-cad 的核心难点在于自然语言的表达方式太多了而 cadquery 的 API 是固定的。你需要一个中间层把在四个角打 M6 沉头孔这种描述翻译成.vertices().cboreHole(6, 12, 6)这样的调用。我的做法是定义一个 JSON schema 来描述几何特征然后写一个解释器把 JSON 转成 cadquery 代码。比如{ type: box, length: 80, width: 80, height: 10, features: [ { type: hole, position: center, diameter: 30, through: true }, { type: cbore_hole, position: corners, diameter: 6, cbore_diameter: 12, cbore_depth: 6 } ] }然后写一个函数把这个 JSON 转成 cadquery 的链式调用。这样做的好处是语义解析层只需要负责把自然语言转成这个 JSON几何生成层只需要负责把 JSON 转成 cadquery 代码两层解耦各自可以独立迭代。实际写的时候你会发现有些特征用 cadquery 表达很自然有些则很别扭。比如阵列操作cadquery 有.rarray()和.polarArray()但如果你要的是沿一条曲线阵列就得手动计算每个实例的位置。这时候就需要在 JSON schema 里设计更灵活的表达方式或者在解释器里做特殊处理。4.3 导出环节的实测参数STEP、STL、GLB 各怎么设导出这一步参数设置直接决定了输出文件能不能用。我把实测下来比较稳的参数列一下。STEP 导出基本不需要额外参数cadquery 的export函数默认就是 AP214 协议。如果你需要 AP242可以指定cq.exporters.export(box, test.step, opt{write_pcurves: False})STL 导出需要关注tolerance和angularTolerance两个参数。我的经验值小零件 50mmtolerance0.005angularTolerance0.1中等零件50-200mmtolerance0.02angularTolerance0.2大零件 200mmtolerance0.1angularTolerance0.3GLB 导出 cadquery 本身不支持需要先导出 STL 或 OBJ然后用 trimesh 转换import trimesh mesh trimesh.load(test.stl) mesh.export(test.glb)trimesh 会自动处理材质和法线但如果你需要更精细的控制比如设置材质颜色、添加环境光就得用 pygltflib 手动构建 glTF 结构。这一步比较繁琐建议只在必要时才做。注意STL 导出时如果 tolerance 设得太小文件会急剧膨胀。我见过一个 100mm 的零件tolerance 设成 0.001STL 文件超过 200MB切片软件直接卡死。所以精度和文件大小之间一定要做权衡。5. 踩坑记录text-to-cad 实际落地时最容易翻车的几个地方5.1 单位混乱一个让所有尺寸都错位的隐形杀手单位问题是 text-to-cad 里最隐蔽、也最致命的坑。自然语言里用户可能说直径 50但没说单位。系统默认按毫米处理但如果用户心里想的是厘米出来的模型就小了 10 倍。更麻烦的是不同格式对单位的处理方式不一样。STEP 文件内部有单位定义可以明确是毫米还是英寸。STL 没有单位切片软件默认按毫米。GLB 也没有单位但 glTF 规范建议用米。如果你在导出时不做换算同一个模型导出成三种格式尺寸会完全对不上。我的解决方案是在系统内部统一用毫米作为基准单位所有输入都先转成毫米所有输出也按毫米处理。如果用户明确说了英寸就在解析层做换算。导出 STL 和 GLB 时在文件名或者元数据里标注单位避免后续混淆。5.2 布尔运算失败为什么你的模型总是破面布尔运算是 CAD 建模里最常用的操作也是最容易出问题的操作。两个实体做差集如果它们的表面有共面、相切或者微小间隙布尔运算就可能失败或者产生破面。在 text-to-cad 场景里这个问题特别常见。因为用户描述的特征往往是理想化的比如在方块中心打一个通孔但实际建模时孔的位置可能刚好和方块的某个边对齐导致布尔运算时出现退化面。我的应对策略是在布尔运算之前先做一次几何清理。具体来说检查所有实体的容差确保没有微小边和微小面如果两个实体有共面稍微偏移一点避免完全重合布尔运算之后用isValid()检查结果是否有效如果无效就回退到上一步调整参数重试。result box.cut(hole) if not result.val().isValid(): # 稍微偏移孔的位置避免共面 hole hole.translate((0.001, 0, 0)) result box.cut(hole)这个 0.001mm 的偏移在视觉上完全看不出来但能解决大部分布尔运算失败的问题。5.3 网格化参数不当STL 文件打不开或者打印失败STL 文件打不开通常有两个原因一是文件太大切片软件内存不够二是网格有错误比如非流形边、法线方向不一致、孔洞。非流形边是指一条边被超过两个三角面片共享这在正常的实体网格里不应该出现。如果出现说明网格化过程中有 bug或者原始 B-rep 实体本身有问题。法线方向不一致会导致切片软件分不清内外打印出来的东西是空心的或者错位的。我的做法是STL 导出之后用 trimesh 做一次检查import trimesh mesh trimesh.load(test.stl) print(是否水密:, mesh.is_watertight) print(是否流形:, mesh.is_winding_consistent) print(体积:, mesh.volume)如果is_watertight是 False说明网格有孔洞需要修复。trimesh 提供了fill_holes()方法但修复效果取决于孔洞的大小和形状。如果孔洞太大最好回到 B-rep 层面重新检查实体是否有效。5.4 格式转换丢信息STEP 转 STL 之后特征全没了这是很多人第一次用 text-to-cad 时最困惑的地方明明 STEP 文件里有完整的特征树转成 STL 之后所有特征都消失了只剩下一个网格。这不是 bug这是 STL 格式的固有特性。STL 只存储三角面片不存储特征信息。所以如果你需要后续编辑一定要保留 STEP 文件STL 只作为打印或者展示的副本。同理STEP 转 GLB 也会丢失特征信息而且还会丢失 B-rep 的精确曲面变成三角面片逼近。如果你在网页上展示一个圆柱放大之后看到的是多边形这就是网格化的结果。要改善这个问题只能提高网格密度但会增加文件大小。我的建议是在 text-to-cad 系统里始终保留一份 STEP 作为母版STL 和 GLB 都是从母版派生出来的副本。任何修改都回到母版上做然后重新导出副本。这样能保证数据的一致性和可追溯性。6. 从能用到好用text-to-cad 的进阶优化方向6.1 参数化模板库让常用结构一键生成text-to-cad 如果每次都要从零解析自然语言效率其实不高。更实用的做法是把常用的结构做成参数化模板用户只需要填参数不需要重新描述。比如法兰、支架、齿轮、轴承座这些标准件结构是固定的变化的只是尺寸。你可以预定义一套模板每个模板对应一组参数。用户说生成一个 80mm 的法兰系统直接调用法兰模板填入 80mm生成模型。这样做的好处是生成速度快、结果稳定、不容易出错。而且模板可以不断积累覆盖的场景越来越多系统的实用性就越强。我在实际项目里会把模板分成几个层级基础几何体方块、圆柱、球、常用特征孔、槽、倒角、螺纹、标准件法兰、齿轮、轴承、行业专用件钣金件、注塑件、型材。每个层级都有对应的参数 schema 和生成逻辑上层可以组合下层形成更复杂的结构。6.2 自然语言的多轮交互一次说不清楚就分几次说单轮的自然语言输入信息量有限很难一次把复杂模型描述清楚。更好的方式是支持多轮交互用户可以先说一个大概系统生成一个初步模型然后用户再补充细节系统增量修改。比如用户生成一个 100x100 的底板系统生成 100x100x5 的方块用户四角加 M6 沉头孔系统在四角添加沉头孔用户中心加一个 40mm 的通孔系统在中心添加通孔这种交互方式更接近人类设计师的工作习惯也更容易处理复杂模型。实现上需要系统维护一个当前模型状态每次用户输入都基于当前状态做增量修改而不是重新生成。6.3 与现有 CAD 软件的集成不要重复造轮子text-to-cad 不需要取代 SolidWorks、中望 CAD 这些软件它更适合作为这些软件的前端或者插件。用户用自然语言快速生成一个初步模型导出 STEP然后在专业软件里做精细调整。这样既发挥了 text-to-cad 的速度优势又保留了专业软件的精度和功能。集成的技术路径通常有两种一是通过文件交换text-to-cad 生成 STEP用户在 CAD 软件里打开二是通过 API 直接调用 CAD 软件的建模内核实时同步。第一种方式简单可靠适合大多数场景第二种方式体验更好但需要 CAD 软件开放 API实现成本较高。我目前更推荐第一种方式。STEP 作为工业标准兼容性足够好而且用户已经习惯了文件交换的工作流。等 text-to-cad 的能力足够强、用户信任度足够高之后再考虑深度集成。6.4 精度与性能的平衡不是所有场景都需要最高精度text-to-cad 系统在设计时很容易陷入精度越高越好的误区。但实际上不同场景对精度的要求差别很大。网页展示用的 GLB精度差不多就行重要的是加载快、交互流畅。3D 打印用的 STL精度要够但也不能太高否则文件太大。工业交换用的 STEP精度必须最高因为后续还要做加工。所以系统应该根据输出格式和用途自动调整精度策略。用户不需要手动设置一堆参数只需要说这个模型是用来打印的或者这个模型要拿去加工系统自动选择合适的精度和格式。我在实际使用中会把精度策略分成三档预览级GLB低精度、打印级STL中精度、制造级STEP高精度。用户选择用途系统自动匹配。这样既降低了使用门槛又保证了输出质量。7. 一些实际使用中的体会text-to-cad 这个概念听起来很未来但实际用下来它更像是一个加速器而不是替代品。它能把从想法到初步模型的时间从几小时压缩到几分钟但后续的精细调整、装配验证、工艺检查还是得靠人来做。我自己的用法是先用 text-to-cad 快速生成一个概念模型导出 STEP然后在 SolidWorks 里打开基于这个模型做详细设计。这样比从空白草图开始快很多尤其是对于结构比较规整的零件。另外自然语言的描述能力其实很有限。你说一个好看的支架系统没法理解好看是什么。但你说一个 L 型支架竖板 80x60横板 60x40厚度 5mm竖板两个 M6 孔横板一个 20mm 通孔系统就能准确生成。所以用 text-to-cad 的关键是学会像工程师一样描述把模糊的需求翻译成明确的参数。最后分享一个小技巧如果你经常生成类似的结构把成功的描述保存下来做成模板或者快捷短语。下次直接调用比重新描述快得多。我自己的模板库里已经攒了几十个常用描述覆盖了大部分日常需求效率提升非常明显。