
1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词我脑子里蹦出来的画面是对着电脑敲一行字比如“一个外径 80mm、内孔 30mm、厚度 12mm 的法兰盘带四个均布螺栓孔”然后软件啪一下吐出一个能直接拿去加工或者 3D 打印的模型文件。这个画面放在五年前基本属于科幻但放到现在它已经是一条能跑通的技术链路了。text-to-cad 本质上就是用自然语言描述几何意图由程序自动生成 CAD 模型并导出成 STEP、GLB、STL 这类通用格式的一套方法或工具链。它解决的问题很具体。传统建模流程里哪怕只是画一个垫片你也要打开 CAD 软件、选基准面、画草图、标尺寸、拉伸、倒角一套操作下来十分钟起步。如果是批量做几十个规格相近的零件重复劳动能把人逼疯。text-to-cad 的价值就在于把这套“人肉翻译”的过程交给程序你把参数和形状逻辑用文字或结构化描述讲清楚剩下的草图约束、实体生成、格式转换全部自动化。适合谁来参考三类人最该关注一是经常要做参数化零件的机械设计从业者二是需要批量生成模型做仿真或渲染的工程师三是想把 AI 能力和传统 CAD 打通的开发者。哪怕你只是刚接触 CAD 制图初学入门阶段理解这套思路也能帮你少走很多弯路。我先把话说在前面text-to-cad 不是要取代 CAD 软件它更像是给 CAD 装了一个“自动写草图的助手”。真正复杂的曲面、装配关系、工程图标注目前还是得靠人。但凡是能用参数和规则描述清楚的零件它都能帮你省下大量时间。下面我就把这套东西从思路到落地一层层拆开讲。2. 整体设计思路为什么是“文本驱动 参数化 多格式导出”2.1 核心链路拆解文本如何变成实体要理解 text-to-cad先得理解它的数据流。整条链路大致是这样的自然语言输入 → 意图解析 → 参数提取 → 几何构造 → 实体建模 → 格式导出。每一步都有讲究。自然语言输入这一环用户说的可能是“直径 50 的圆盘中间挖个 20 的孔”也可能是更结构化的“cylinder(d50, h10) - cylinder(d20, h10)”。前者需要语义理解后者更接近代码。实际项目里我建议把输入设计成“半结构化”的形式——既保留自然语言的灵活又降低解析难度。比如用固定的句式模板“形状 关键尺寸 特征操作”这样解析器不用去猜。意图解析和参数提取是整条链路里最容易翻车的地方。人说话是有歧义的“大一点的孔”到底是多大“倒个角”是倒多少所以成熟的做法是能要数字就不要形容词。我在实际项目里会把所有尺寸都要求带单位和数值解析器只做数值提取和单位换算不做模糊推断。这样虽然牺牲了一点“智能感”但换来了极高的稳定性工程上这笔账划得来。几何构造和实体建模是核心。这里绕不开一个关键选型用哪种建模内核。常见的有 OpenCASCADE、CGAL、Manifold 这几类。OpenCASCADE 功能最全STEP 支持最好但体积大、学习曲线陡Manifold 轻量、布尔运算快适合做网格类操作但精确 B-rep 能力弱。如果你的目标是导出 STEP 这种精确边界表示格式OpenCASCADE 基本是绕不过去的选择。2.2 为什么导出格式要同时支持 STEP、GLB、STL这是很多人一开始会忽略的点。三种格式对应三种完全不同的用途缺一不可。格式本质典型用途是否精确文件特点STEPB-rep 边界表示机械加工、CAD 交换、工程图精确体积小含拓扑信息STL三角网格3D 打印、快速预览近似体积大只有面片GLB二进制 glTFWeb 展示、渲染、AR近似体积小带材质STEP 是给“要拿去造”的场景用的它保留了圆柱面、平面这些精确几何信息CNC 编程和工程图都依赖它。STL 是给 3D 打印和网格处理用的它把模型全部三角化精度取决于弦高参数。GLB 是给展示用的浏览器里直接能加载配合 three.js 或者 model-viewer 就能做交互预览。我踩过的一个坑是一开始只导出 STL结果客户要拿去线切割STL 的三角面片根本没法用只能返工重做 STEP 导出。所以从项目第一天起三种格式的导出通道就要全部打通不要等到交付才发现格式不对。2.3 方案选型自研内核还是调用现成库这是每个做 text-to-cad 的人都要面对的选择。自研几何内核除非你有十年以上的计算几何团队否则不要碰。主流做法是站在成熟库的肩膀上。Python 生态里cadquery和build123d是两个绕不开的库它们底层都是 OpenCASCADE但提供了更友好的 Python API。CadQuery 的链式调用写起来很顺手比如cq.Workplane(XY).circle(25).extrude(10)就能生成一个圆柱。Build123d 则更接近传统 CAD 的建模思维支持上下文管理器语法。如果你要做 Web 服务OpenCASCADE.js可以把内核编译到浏览器里跑配合 WASM 实现纯前端建模。我的建议是原型阶段用 CadQuery 快速验证生产环境根据部署形态决定。如果是桌面工具Python CadQuery 足够如果是 Web 服务考虑 OpenCASCADE.js 或者后端 Python 服务 前端预览的组合。不要一上来就追求全自研那是给自己挖坑。3. 核心细节解析文本解析、参数建模与格式导出的实操要点3.1 文本解析层把“人话”翻译成参数字典文本解析是 text-to-cad 的第一道关卡也是最容易被低估的一环。很多人以为接个大模型就完事了实际上大模型输出的稳定性远不如规则解析。我的做法是规则优先模型兜底。具体来说先定义一套领域内的语法模板。比如针对回转体零件模板可以是[形状] [主尺寸], [特征1], [特征2]...对应的解析规则用正则或者简单的语法分析器就能搞定。举个例子输入“圆柱 直径60 高20 中心通孔直径15”解析出来的参数字典是{ shape: cylinder, diameter: 60.0, height: 20.0, features: [ {type: hole, diameter: 15.0, through: True} ] }这个字典就是后续建模的唯一输入。为什么要这么设计因为参数字典是人和程序之间的契约。只要字典结构稳定建模层就永远不用改解析层哪怕从规则换成大模型输出格式不变整个系统就是解耦的。单位处理是这里的一个隐藏坑。用户可能说“直径 6 厘米”也可能说“直径 60”你得约定默认单位。我的经验是内部统一用毫米输入层做单位归一化。厘米乘 10米乘 1000英寸乘 25.4全部转成毫米再进建模层。这样能避免 90% 以上的尺寸错误。注意不要相信用户会规范输入。我见过有人把“直径”写成“直经”“直徑”“D”“φ”解析层必须把这些变体全部覆盖否则用户第一次用就会报错体验直接崩掉。3.2 参数化建模层用代码描述几何逻辑拿到参数字典之后就进入建模层。这一层的核心思想是把几何逻辑写成可复用的函数。以最常见的法兰盘为例它的几何逻辑是一个大圆柱减去一个中心通孔再减去一圈均布的小孔。用 CadQuery 写出来大概是这样import cadquery as cq def make_flange(outer_d, inner_d, thickness, bolt_count, bolt_d, bolt_circle_d): # 主体圆盘 result cq.Workplane(XY).circle(outer_d / 2).extrude(thickness) # 中心通孔 result result.faces(Z).workplane().hole(inner_d) # 均布螺栓孔 result ( result.faces(Z).workplane() .polarArray(bolt_circle_d / 2, 0, 360, bolt_count) .hole(bolt_d) ) return result这段代码有几个关键点值得说。第一polarArray做均布孔比手写循环优雅得多它自动处理角度分布最后一个孔不会和第一个重叠。第二faces(Z)是选择顶面作为工作平面这个选择器语法是 CadQuery 的精髓用熟了效率极高。第三所有尺寸都是参数改一个数字整个模型就变这就是参数化的威力。对于更复杂的零件比如带拔模斜度的壳体就需要用到loft放样或者sweep扫掠。这时候文本描述也要相应升级不能只说“一个壳”而要说清楚截面形状、路径、拔模角。我的经验是文本描述的精细度直接决定建模的可行性。描述越结构化程序能做的事就越多。3.3 格式导出层STEP、STL、GLB 的参数调优模型建好之后导出环节的参数设置直接决定文件能不能用。三种格式各有各的坑。STEP 导出相对简单CadQuery 里一行cq.exporters.export(result, part.step)就搞定。但要注意版本STEP AP214 和 AP203 在颜色和装配信息上有差异。如果只是单零件AP203 够用如果要保留颜色用 AP214。STL 导出的核心参数是弦高linear deflection和角度公差angular deflection。弦高决定三角面片逼近曲面的精度值越小越精细文件也越大。默认值通常是 0.001对于小零件够用但对于直径几百毫米的大零件这个值会导致面片数量爆炸。我的经验公式是弦高取零件最大尺寸的 0.1% 到 0.5%。比如直径 200mm 的零件弦高取 0.2mm 到 1mm 之间视精度要求调整。cq.exporters.export( result, part.stl, tolerance0.1, # 弦高单位 mm angularTolerance0.1 # 角度公差单位弧度 )GLB 导出稍微麻烦一点因为 CadQuery 不直接支持。常见做法是先把模型转成网格再用trimesh或者pygltflib导出。这里要注意坐标系转换CAD 常用 Z 轴向上而 glTF 规范是 Y 轴向上不做转换的话模型在浏览器里会躺着。导出格式关键参数推荐取值常见问题STEP协议版本AP214带颜色版本不兼容导致丢面STL弦高最大尺寸的 0.1%~0.5%值太小文件巨大值太大表面粗糙STL角度公差0.1~0.5 弧度太小导致曲面面片过多GLB坐标系Y 轴向上不转换导致模型方向错误提示导出 STL 之后强烈建议用网格检查工具过一遍确认没有非流形边和翻转法线。我遇到过 STL 导出后 3D 打印失败排查半天发现是法线朝内切片软件直接懵了。4. 完整实操流程从零搭一个 text-to-cad 最小可用系统4.1 环境准备与依赖安装先把环境搭起来。我推荐用 Python 3.10 以上版本CadQuery 对 3.9 以下的支持越来越差。用 conda 装最省事因为 OpenCASCADE 的依赖在 pip 里经常编译失败。conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install trimesh pygltflib装完之后验证一下import cadquery as cq box cq.Workplane(XY).box(10, 10, 10) cq.exporters.export(box, test.step) print(OK)能打印 OK 就说明内核正常。如果报错找不到 OCC 库八成是 conda 环境没激活对或者和系统里的其他 OCC 版本冲突了。这种依赖冲突在 Windows 上尤其常见我的建议是一个项目一个独立环境绝不混用。4.2 解析器实现从文本到参数字典解析器我分成两层写。第一层是预处理把全角字符转半角、统一单位词、去掉多余空格。第二层是模式匹配用正则提取关键信息。import re UNIT_MAP {毫米: 1, mm: 1, 厘米: 10, cm: 10, 米: 1000, m: 1000} def normalize(text): text text.replace(φ, 直径).replace(Φ, 直径) text text.replace(直经, 直径).replace(直徑, 直径) return text.strip() def parse_cylinder(text): text normalize(text) d_match re.search(r直径\s*([\d.])\s*(毫米|mm|厘米|cm|米|m)?, text) h_match re.search(r高\s*([\d.])\s*(毫米|mm|厘米|cm|米|m)?, text) if not d_match or not h_match: return None d float(d_match.group(1)) * UNIT_MAP.get(d_match.group(2) or mm, 1) h float(h_match.group(1)) * UNIT_MAP.get(h_match.group(2) or mm, 1) return {shape: cylinder, diameter: d, height: h}这段代码看起来简单但覆盖了实际使用中 80% 的输入变体。关键设计是单位映射表和同义词替换这两招能挡掉大量脏输入。至于更复杂的形状可以按同样的模式扩展每个形状一个解析函数最后用一个分发器根据关键词路由。4.3 建模与导出一次完整的端到端跑通把解析和建模串起来就是一个最小可用系统def build_from_text(text): params parse_cylinder(text) if not params: raise ValueError(无法解析输入) result ( cq.Workplane(XY) .circle(params[diameter] / 2) .extrude(params[height]) ) return result def export_all(model, name): cq.exporters.export(model, f{name}.step) cq.exporters.export(model, f{name}.stl, tolerance0.1) # GLB 需要先转网格 import trimesh mesh trimesh.load(f{name}.stl) mesh.export(f{name}.glb) model build_from_text(圆柱 直径60 高20) export_all(model, output/cylinder)跑完这段output 目录下就会有 cylinder.step、cylinder.stl、cylinder.glb 三个文件。STEP 可以拖进任意 CAD 软件STL 可以拖进切片软件GLB 可以拖进浏览器预览。这就是 text-to-cad 的最小闭环。实测下来从输入文本到三个文件生成整个过程不到两秒。如果是批量生成一百个规格写个循环遍历参数表就行效率比手动建模高两个数量级。4.4 批量生成与参数表驱动单个零件生成只是玩具真正的生产力在于批量。我通常会把参数整理成 CSV然后批量跑import csv with open(parts.csv) as f: reader csv.DictReader(f) for row in reader: text f圆柱 直径{row[d]} 高{row[h]} model build_from_text(text) export_all(model, foutput/part_{row[id]})这个模式特别适合做标准件库。比如螺栓、垫片、法兰这些形状固定、只有尺寸变化的零件一次性生成几百个规格打包成库以后随用随取。我之前帮一个做非标设备的朋友做过类似的事他把常用的一百多个零件规格整理成表跑一遍全生成好后面设计时直接调用省了大量重复建模时间。注意批量生成时一定要加异常捕获和日志。某个规格参数不合法导致整个批次中断是最让人抓狂的事。我的做法是每个零件单独 try-except失败的记录到日志里成功的正常导出最后统一看日志补漏。5. 常见问题与排查技巧实录5.1 解析层高频问题速查文本解析是问题最集中的地方我把踩过的坑整理成表问题现象根本原因解决方法尺寸解析成 0单位词缺失且默认值没设强制默认毫米解析失败给明确报错中文全角数字识别失败正则只匹配半角预处理阶段统一转半角“直径”写成“D”识别不了同义词表不全持续收集用户输入变体补充映射多个尺寸混淆正则贪婪匹配用非贪婪匹配加边界锚定小数点和千分位混淆输入格式不统一约定不用千分位小数点用英文句点这里最想强调的是报错信息要具体。不要只说“解析失败”而要告诉用户“没有找到直径参数请按‘直径XX’的格式输入”。用户看到明确提示自己就能改对省去大量沟通成本。5.2 建模层典型故障与修复建模层的问题往往更隐蔽因为几何运算失败不一定报错可能只是结果不对。布尔运算失败是最常见的。两个实体做差集如果面重合或者相切OpenCASCADE 有时会算出空结果或者报错。解决办法是给布尔运算留微小间隙比如挖孔时孔径比目标大 0.001mm避免面完全重合。这个技巧在精密建模里很常用代价可以忽略不计。倒角失败也很常见。倒角半径大于相邻面尺寸时运算会失败。这时候要么减小倒角半径要么先检查几何是否合法。我的习惯是倒角放在最后做前面所有布尔运算完成后再统一倒角这样失败时容易定位。模型非流形是导出 STL 后才会暴露的问题。表现为切片软件报错或者打印出来有破面。根源通常是布尔运算产生了零厚度面或者悬挂边。修复方法是导出前用model.val().isValid()检查不合法就重新调整参数。5.3 导出层避坑指南导出层的坑主要集中在 STL 和 GLB。STL 最常见的问题是文件体积失控。一个直径 500mm 的圆盘如果弦高设成 0.001mm三角面片数量能到几百万文件几百兆。这种文件切片软件打开都费劲。解决办法就是前面说的弦高按零件尺寸比例设置不要用固定值。GLB 的问题是材质丢失和坐标系错乱。CadQuery 导出的模型没有材质信息转 GLB 后是纯灰的。如果需要颜色得在转网格后手动赋材质。坐标系问题前面提过Z 轴转 Y 轴一行代码的事但不知道就会卡很久。还有一个容易被忽略的点文件名和路径不要带中文和空格。OpenCASCADE 在某些系统上对非 ASCII 路径支持不好导出会静默失败。我统一用英文加下划线命名从来没出过问题。提示导出 STEP 后建议用免费查看器打开确认一下。我遇到过 STEP 导出成功但打开是空的情况原因是模型被放在了远离原点的位置查看器默认视野看不到。养成导出后立即验证的习惯能省掉大量返工。6. 工具选型与扩展方向让 text-to-cad 真正融入工作流6.1 建模内核与库的对比选择前面提过 CadQuery 和 build123d这里再补充几个选项方便你根据场景选。工具语言优势劣势适用场景CadQueryPython链式 API 简洁社区活跃复杂曲面支持一般参数化零件、批量生成build123dPython建模思维接近传统 CAD相对较新资料少复杂建模逻辑OpenCASCADE.jsJavaScript可跑在浏览器体积大加载慢Web 端纯前端建模ManifoldC/JS布尔运算极快无精确 B-rep网格处理、快速预览我的实际组合是后端 Python CadQuery 做精确建模和 STEP 导出前端用 three.js 加载 GLB 做预览。这样既保证了精度又有良好的交互体验。如果要做纯 Web 方案OpenCASCADE.js 是唯一选择但要做好加载优化的心理准备WASM 包动辄几十兆。6.2 与现有 CAD 工作流的衔接text-to-cad 生成的文件最终要能融入现有流程才有价值。STEP 文件可以直接导入 SolidWorks、中望 CAD、Fusion 360 这些主流软件导入后还能继续编辑这是它最大的优势。STL 主要用于 3D 打印导入切片软件直接就能用。GLB 用于展示和协作发给客户看方案特别方便不用装任何软件浏览器打开就行。如果你团队里有人习惯用传统 CAD 手动建模可以把 text-to-cad 定位成“初稿生成器”。先用文本快速生成基础形状导出 STEP再导入 CAD 软件做细节调整。这样既享受了自动化的速度又保留了人工精修的质量。我试过这个流程一个中等复杂度的零件从描述到出图时间能压缩到原来的三分之一。6.3 后续可扩展的方向这套系统跑通之后有几个自然的扩展方向。一是接入大模型做语义解析把规则解析换成模型解析支持更自由的描述。但要注意模型输出必须经过校验层不能直接进建模否则一个幻觉尺寸就可能生成完全错误的零件。二是增加装配支持现在只能生成单零件如果能描述装配关系和配合约束就能生成完整装配体。三是对接工程图生成模型建好后自动投影三视图、标注尺寸直接出图。我个人最看好的方向是和参数表结合做企业标准件库。每个公司都有一批常用零件形状固定、尺寸系列化。用 text-to-cad 把这些零件全部脚本化新项目直接调用这才是最能落地的价值点。至于更远的事情比如完全靠一句话生成复杂装配体那是下一步的事现在把单零件的链路做扎实比什么都强。最后分享一个我在实操中总结的小技巧把常用的建模逻辑封装成函数库文本解析只负责填参数。这样解析层和建模层彻底解耦解析层可以随便换实现建模层永远稳定。我现在的做法是维护一个shapes.py里面全是make_flange、make_shaft、make_bracket这样的函数文本解析只输出函数名和参数字典然后动态调用。这套架构跑了一年多扩展新形状只需要加一个函数和几条解析规则维护成本极低。