1. 从一段文字到三维实体text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人会下意识地把它理解成用嘴画图——说一句话软件自动帮你把零件建出来。这个理解方向没错但真正落地的时候它解决的其实是一个更具体、更痛的问题从自然语言描述到可编辑、可制造的三维几何模型之间的自动化转换。传统流程是这样的客户或者产品经理给你一段文字需求比如一个外径 80mm、内径 40mm、厚度 12mm 的圆环垫片边缘倒角 1mm你得打开 CAD 软件手动画草图、拉伸、倒角、导出。一个简单零件三五分钟复杂一点的装配体就是几小时甚至几天。text-to-cad 想做的事情就是把这段文字直接喂给程序让它输出 STEP、STL、GLB 这类标准格式的文件你拿到之后可以直接进 CAM 加工、进 3D 打印切片、或者进渲染管线。这里有几个关键词必须先厘清因为它们决定了整个技术路线的走向CAD计算机辅助设计核心是参数化、可编辑的几何表达。STEP 是它的典型载体。STEP一种基于边界表示BRep的精确几何交换格式保留曲面、实体、拓扑关系是工业界通用的精确模型标准。STL三角网格格式只有面片没有拓扑精度靠网格密度堆3D 打印和快速预览常用。GLBglTF 的二进制版本主打轻量渲染和 Web 展示适合做可视化预览。所以 text-to-cad 的输出目标不是单一的。你要加工就得给 STEP你要打印STL 更直接你要在网页上给客户看GLB 最省事。理解这一点后面的技术选型才不会跑偏。这篇文章适合谁看如果你是会写 Python、懂一点三维几何、想把手里的重复建模工作自动化的人那这篇就是给你写的。如果你是完全不懂 CAD 的纯程序员也没关系我会把几何概念用生活化的方式讲清楚。如果你是从业多年的结构工程师想看看 AI 到底能不能替代手工建模那也能从里面找到判断依据。我自己的背景是做过几年参数化建模和几何内核相关的开发踩过不少坑。下面这些内容一部分来自实际项目一部分来自对常见方案的合理推演我会明确标注哪些是实测、哪些是基于行业惯例的补充。2. 拆解 text-to-cad 的技术链路文字是怎么变成几何的2.1 自然语言到结构化参数的映射文字进、几何出中间不可能一步到位。真正靠谱的链路一定是分阶段的第一段就是把自然语言解析成结构化的几何参数。比如输入一个长 100、宽 50、高 20 的长方体中心开一个直径 10 的通孔。人一看就懂但程序需要把它拆成基体类型长方体box尺寸参数length100, width50, height20特征操作通孔through hole孔参数diameter10, 位置几何中心布尔运算基体减去圆柱这一步现在主流有两种做法。一种是基于规则的正则/模板匹配适合参数固定、句式有限的场景比如企业内部的标准件库你只要覆盖几十种句式就能跑得很稳。另一种是基于大语言模型的结构化抽取让它输出 JSON 或者类似 DSL 的中间表示。后者泛化能力强但会幻觉——它可能给你编一个不存在的参数或者把直径和半径搞混。我实测下来比较稳的组合是LLM 负责抽取规则层负责校验。LLM 输出 JSON 之后用一套 JSON Schema 去验证字段类型和取值范围超出范围或者缺字段的直接打回重问。这样既保留了泛化能力又不会让错误参数流到几何内核里。2.2 中间表示为什么不能直接生成 STEP很多人会想既然要 STEP那让模型直接吐 STEP 文本不就行了这个思路基本走不通原因有两个。第一STEP 文件是高度结构化的里面有实体定义、曲面定义、拓扑关系、坐标系变换一个稍微复杂点的零件就是几千行。让语言模型逐字符生成这种文件出错概率极高而且一旦某个引用 ID 对不上整个文件就废了。第二STEP 表达的是精确几何而语言模型擅长的是序列预测它没有真正的三维空间推理能力。你让它算一个倒角后的曲面方程它大概率是编的。所以正确的做法是引入中间表示层。常见的选择有CSG 树用布尔运算把简单体素组合成复杂形状比如difference(box, cylinder)。结构清晰容易生成也容易转成网格。参数化特征序列类似 CAD 软件里的建模历史树草图→拉伸→倒角→阵列。更贴近真实 CAD 逻辑但生成难度更高。DSL 脚本比如用 CadQuery 或者 OpenSCAD 的语法让模型生成脚本代码再由脚本引擎执行出几何。我个人最推荐的是CSG 树 脚本生成的组合。让模型输出一段 CadQuery 或者 build123d 的 Python 代码代码里用布尔运算描述形状。这样做的好处是代码可读、可调试、可版本管理而且 CadQuery 底层用的是 OpenCASCADE 这个成熟的几何内核输出的 STEP 质量有保障。2.3 几何内核OpenCASCADE 为什么是绕不开的选择说到几何内核就不得不提OpenCASCADE简称 OCCT。它是一个开源的 BRep 几何内核支持实体建模、布尔运算、倒角、抽壳、曲面求交这些核心操作而且能导出 STEP、IGES、STL 等多种格式。为什么它绕不开因为从 CSG 描述到精确 BRep 实体中间必须有一个可靠的几何内核来做布尔运算和拓扑重建。你自己写一个布尔运算引擎那基本是一个团队几年的工作量而且稳定性很难保证。OCCT 虽然 API 有点难用、文档有点劝退但它是目前开源方案里最成熟的选择。实际用的时候CadQuery 和 build123d 都是对 OCCT 的 Python 封装帮你把底层复杂度藏起来了。你写cq.Workplane(XY).box(100, 50, 20).faces(Z).workplane().hole(10)它内部就是调 OCCT 去建实体、做布尔减。所以选 CadQuery 这类库本质上是站在 OCCT 的肩膀上。2.4 格式导出STEP、STL、GLB 各自的取舍几何建好之后导出格式的选择直接决定了下游能不能用。格式几何类型是否可编辑典型用途导出要点STEPBRep 精确几何是工业加工、CAD 交换保留拓扑文件较大STL三角网格否3D 打印、快速预览需设置网格精度精度越高文件越大GLB三角网格 材质否Web 展示、渲染需做网格简化和法线处理这里有个坑我必须提醒STL 和 GLB 都是从 BRep 网格化出来的网格精度参数设不好要么文件巨大要么形状失真。比如一个直径 10mm 的孔如果网格弦高公差设成 0.5mm出来的孔可能是多边形而不是圆。一般建议弦高公差控制在 0.01~0.05mm角度公差控制在 0.1~0.5 弧度具体看零件尺寸。另外GLB 导出前最好做一次网格简化decimation把不必要的三角面去掉否则一个简单零件可能导出几十 MB网页加载直接卡死。3. 动手搭一个最小可用的 text-to-cad 流水线3.1 环境准备与依赖选择先说环境。我建议用 Python 3.10 或 3.11太新的版本有些几何库还没跟上。核心依赖就三个pip install cadquery openai pydanticcadquery几何建模和导出底层是 OCCT。openai调用大语言模型做参数抽取和代码生成你也可以换成任何兼容接口的模型。pydantic做结构化校验防止模型输出的参数越界。CadQuery 的安装在某些平台上需要编译 OCCT如果直接 pip 装失败可以用 condaconda install -c conda-forge cadquery我实测 conda 渠道的预编译包最省心尤其是 Windows 上省去了一堆 C 编译环境的折腾。3.2 用 Pydantic 定义几何参数模型这一步是整个流水线的防呆设计。不要让模型自由发挥而是先定义好它能输出的结构。from pydantic import BaseModel, Field from typing import Literal, List, Optional class Hole(BaseModel): diameter: float Field(gt0, le1000) position: Literal[center, corner] center class PartSpec(BaseModel): shape: Literal[box, cylinder, ring] length: Optional[float] Field(defaultNone, gt0) width: Optional[float] Field(defaultNone, gt0) height: Optional[float] Field(defaultNone, gt0) outer_diameter: Optional[float] Field(defaultNone, gt0) inner_diameter: Optional[float] Field(defaultNone, gt0) holes: List[Hole] []这样模型输出的 JSON 必须先过PartSpec校验字段类型不对、数值超范围、形状类型不认识都会直接抛异常。比起让错误参数流到几何内核里报一个看不懂的 OCCT 错误这种方式排查起来轻松太多。3.3 让模型生成 CadQuery 脚本而不是直接生成几何参数抽取只是第一步真正生成几何我推荐让模型输出CadQuery 脚本。原因前面说过可读、可调试、可复用。给模型的提示词大概长这样你是一个 CAD 脚本生成助手。根据用户描述生成一段 CadQuery Python 代码。 要求 1. 只输出代码不要解释。 2. 使用 cq.Workplane 构建几何。 3. 所有尺寸单位是毫米。 4. 最后把结果赋值给变量 result。比如用户输入长 100 宽 50 高 20 的长方体中心开直径 10 的通孔模型应该输出import cadquery as cq result ( cq.Workplane(XY) .box(100, 50, 20) .faces(Z) .workplane() .hole(10) )拿到这段代码之后不要直接exec而是先做一次静态检查确认只 import 了 cadquery没有调用文件读写、网络请求、系统命令。这一步是安全底线因为模型生成的代码本质上是不可信输入。3.4 执行脚本并导出三种格式检查通过之后在受限环境里执行脚本拿到result对象然后导出import cadquery as cq # result 来自上一步执行的脚本 cq.exporters.export(result, part.step) cq.exporters.export(result, part.stl, tolerance0.02, angularTolerance0.2) cq.exporters.export(result, part.glb)这里tolerance就是弦高公差angularTolerance是角度公差。我一般先用 0.02 和 0.2 跑一遍看看 STL 文件大小和形状精度是否平衡再根据实际零件调整。导出 GLB 的时候要注意CadQuery 的 GLB 导出对材质支持比较基础如果你需要带颜色或者贴图可能得用 trimesh 或者 pygltflib 再做一层后处理。3.5 一个完整的调用示例把上面的环节串起来主流程大概是这样def text_to_cad(user_input: str): # 1. 抽取参数 spec_json llm_extract(user_input) spec PartSpec.model_validate_json(spec_json) # 2. 生成脚本 script llm_generate_script(spec) # 3. 安全检查 if not is_safe_script(script): raise ValueError(生成的脚本未通过安全检查) # 4. 执行 local_vars {} exec(script, {cq: cq}, local_vars) result local_vars[result] # 5. 导出 cq.exporters.export(result, output.step) cq.exporters.export(result, output.stl, tolerance0.02) cq.exporters.export(result, output.glb) return result这套流程跑通之后你会发现简单零件的生成已经相当可用了。但真正上生产还有一堆坑等着。4. 实测中暴露的问题与对应的处理办法4.1 模型幻觉出不存在的几何特征这是最常见的问题。你让它画一个带键槽的轴它可能给你生成一个带螺纹的孔因为训练数据里轴和螺纹经常一起出现。或者你给了一个直径 10 的孔它生成代码的时候写成hole(20)把直径当半径用了。处理办法有两层。第一层是参数校验前面 Pydantic 那套能拦住数值越界但拦不住语义错误。第二层是几何后验检查生成实体之后用 OCCT 的 API 去测量实际几何包围盒尺寸对不对、孔的数量和直径对不对、体积是否在合理范围。如果对不上就把实际测量值反馈给模型让它重新生成。我实测这种生成-测量-反馈的循环两轮之内基本能收敛。4.2 布尔运算失败与拓扑修复OCCT 的布尔运算不是万能的。当两个实体表面几乎相切、或者有微小重叠的时候布尔运算可能失败报一个BRepAlgoAPI相关的错误。这种问题在手工建模时也会遇到但在自动生成场景下更频繁因为模型不知道留一点间隙这种工程直觉。我的处理经验是在布尔运算之前先做一次实体有效性检查Shape.isValid()。对参与布尔运算的实体做微小偏移比如把相切改成 0.001mm 的过盈很多时候能绕开数值退化。如果还是失败用ShapeFix_Shape做一次拓扑修复再重试。这些操作在 CadQuery 里可以通过底层 OCCT API 调用虽然麻烦但比直接报错强。4.3 STL 网格精度与文件体积的平衡前面提过网格公差这里展开说。STL 文件大小大致和(1/tolerance)^2成正比。你把公差从 0.1 降到 0.01文件可能大 100 倍。一个原本 2MB 的零件变成 200MB3D 打印切片软件直接卡死。我的做法是分级导出预览用粗网格tolerance0.1打印用中等网格tolerance0.02精密分析才用细网格tolerance0.005。而且导出前先算一下预估三角面数超过阈值就自动放宽公差。4.4 GLB 在 Web 端的加载优化GLB 虽然轻量但如果不做处理一个带复杂曲面的零件也可能几十 MB。Web 端加载优化主要靠三件事网格简化用trimesh或者pymeshlab做二次误差简化把三角面数降到原来的 20%~30%视觉上几乎看不出差别。Draco 压缩glTF 支持 Draco 扩展能把几何数据压缩到原来的十分之一。LOD 分级根据相机距离切换不同精度的模型远处用低模近处用高模。这些在纯 CadQuery 里做不了需要引入额外的网格处理库。如果你的场景只是内部预览不做也行但如果要给客户在网页上看这几步省不了。5. 从能跑到好用几个提升成功率的实战技巧5.1 提示词里要写工程约束而不只是形状描述很多人写提示词只描述形状比如一个法兰盘。但工程上法兰盘有标准外径、内径、螺栓孔数量、孔分布圆直径、厚度、倒角。你不写清楚模型只能猜猜错概率很高。我的经验是提示词里要显式包含这几类约束尺寸约束所有关键尺寸给数值和单位。位置约束孔在中心还是边缘阵列是圆周还是线性。工艺约束最小壁厚、倒角要求、拔模角度。格式约束输出什么格式精度要求多少。把这些写进系统提示词让模型每次生成前都对照检查成功率能提升一大截。5.2 建立常用零件的模板库不是所有零件都需要模型从零生成。像垫片、法兰、支架、齿轮这些标准件完全可以预先写好参数化模板模型只需要抽取参数填进去就行。这样既快又稳还省 token。我的做法是维护一个模板目录每个模板是一个 CadQuery 函数接受一组参数。模型的任务从生成代码降级为选择模板 填参数出错概率大幅下降。只有模板覆盖不到的形状才走自由生成路径。5.3 用单元测试守住几何正确性自动生成的几何必须有一套自动化测试来守。我一般会针对每个模板写测试用例def test_box_with_hole(): result build_box_with_hole(100, 50, 20, 10) bb result.val().BoundingBox() assert abs(bb.xlen - 100) 0.01 assert abs(bb.ylen - 50) 0.01 assert abs(bb.zlen - 20) 0.01 assert result.val().Volume() 100 * 50 * 20包围盒尺寸、体积、面数这些都可以作为断言条件。每次改提示词或者换模型跑一遍测试就知道有没有退化。5.4 版本管理把提示词和脚本一起管起来text-to-cad 项目里提示词、参数模型、脚本模板、测试用例都是核心资产必须进版本管理。我见过有人把提示词写在代码里改一次就覆盖一次出了问题根本不知道是哪版提示词导致的。我的建议是提示词单独放一个目录用 YAML 或者 Markdown 管理每次修改都提交。生成的脚本也存下来和输入参数、输出文件一起归档。这样出问题的时候可以完整复现。6. 这套方案适合什么场景不适合什么场景6.1 适合的场景标准化、参数化、批量化的零件text-to-cad 最擅长的是那些形状规则、参数明确、批量重复的零件。比如标准件库的自动生成螺栓、垫片、轴承座。客户定制化产品的快速出图给定尺寸范围自动生成系列化模型。教学演示学生输入描述立刻看到三维结果理解参数和形状的关系。快速原型产品经理口述一个想法几分钟内拿到可打印的 STL。这些场景的共同点是几何复杂度可控参数空间有限错误代价低。6.2 不适合的场景自由曲面、复杂装配、高精度配合反过来下面这些场景目前不要指望 text-to-cad自由曲面造型汽车外形、消费电子外壳这种 A 级曲面靠文字描述根本说不清楚模型也生成不出来。复杂装配体几十个零件的装配关系、运动约束、干涉检查不是一段文字能表达的。高精度配合公差配合、形位公差这些需要工程判断模型给不了。非标结构依赖工程师经验和行业惯例的设计文字描述本身就模糊。认清边界很重要。text-to-cad 是提效工具不是替代工程师的魔法。6.3 和传统参数化建模的关系有人担心这东西会取代参数化建模。我的判断是它取代的是重复劳动不是设计能力。传统参数化建模的核心价值在于工程师对几何关系的理解和设计意图的表达。text-to-cad 做的是把已经想清楚的设计快速转成模型。它不负责想只负责画。所以未来的工作流更可能是工程师用文字或者草图描述设计意图工具自动生成初版模型工程师再在 CAD 软件里精修。人机分工各干各擅长的。7. 我踩过的几个具体坑你可以直接避开第一个坑是单位混乱。模型有时候按毫米生成有时候按米生成因为它训练数据里两种都有。解决办法是在提示词里强制声明所有尺寸单位为毫米并且在参数校验层加一个范围检查比如长度超过 10000 的直接拒绝。第二个坑是坐标系约定不一致。CadQuery 默认 Z 轴向上但有些模型生成的代码假设 Y 轴向上结果零件躺倒了。解决办法是在提示词里明确坐标系约定并且在导出前做一次朝向检查。第三个坑是中文描述里的歧义。直径 10 的孔和半径 10 的孔模型有时候会搞混。我的做法是在参数抽取阶段就把直径半径归一化成统一的字段名比如统一用diameter半径描述自动乘 2。第四个坑是导出路径的权限问题。自动生成的脚本如果包含文件写入可能写到不该写的地方。所以执行环境一定要做沙箱限制可写目录禁止网络访问。第五个坑是大模型接口的超时和重试。生成复杂脚本的时候模型响应可能超过 30 秒。如果不做超时和重试整个流水线会卡住。我的做法是设置 60 秒超时失败自动重试两次两次都失败就降级到模板匹配。这些坑看起来都是小事但每一个都能让流水线在关键时刻掉链子。提前处理好后面省心很多。8. 后续可以继续深挖的方向如果你已经把基础流水线跑通了下面几个方向值得继续投入。多模态输入不只是文字还可以接受手绘草图、照片、甚至语音。手绘草图转 CAD 已经有研究在做核心是草图识别加几何推理。照片转 CAD 更难因为要处理透视和遮挡。装配体生成从单零件扩展到多零件装配需要处理配合关系、约束求解、干涉检查。这一步的复杂度比单零件高一个数量级。制造约束嵌入让生成的模型天然满足加工约束比如最小刀具半径、拔模角度、壁厚均匀性。这需要在几何生成阶段就引入工艺知识而不是事后检查。和 CAM 打通生成 STEP 之后直接生成刀路跳过人工编程环节。这对批量小零件加工很有价值。反馈学习把用户对生成结果的修改记录下来反哺提示词和模板库让系统越用越准。这些方向我有的试过原型有的还在调研。整体判断是单零件生成已经可用装配和制造约束还在早期多模态是下一个爆发点。最后分享一个我自己的体会text-to-cad 这个方向工程化能力比模型能力更重要。模型再强如果参数校验、几何检查、错误恢复这些工程环节没做好流水线就是不可用的。反过来即使用一个中等能力的模型只要工程环节扎实也能跑出稳定可用的结果。所以如果你要投入这个方向别只盯着换更强的模型先把工程骨架搭稳。