1. 从一句话到三维模型text-to-cad 到底在解决什么问题“text-to-cad”这个词最近出现的频率越来越高但很多人第一次听到会误以为它只是“用嘴画图”的噱头。实际接触下来你会发现它真正要解决的是一个非常具体的痛点从自然语言描述到可编辑、可制造的三维 CAD 模型之间存在一条长期靠人工填平的鸿沟。传统流程里你得先理解需求、再在 CAD 软件里一步步拉伸、旋转、倒角最后导出 STEP 或 STL。而 text-to-cad 想做的是把“描述”直接映射成参数化几何让模型生成从手工劳动变成可编程、可批量、可复现的过程。我最初关注这个方向是因为手头有一批结构相似但尺寸各异的零件需要建模。如果每个都手动画一天下来眼睛都花了。后来尝试用脚本驱动 CAD再往后接触到用文本描述生成模型的做法才意识到这条链路的价值远不止省时间——它让“设计意图”可以被记录、被版本管理、被自动校验。关键词里出现的 CAD、STEP、URDF、G-code其实正好对应了这条链路的四个关键节点建模、交换、仿真、制造。这篇文章适合谁看如果你是会一点 Python、对 CAD 有基础认知、想把手动建模变成自动化流程的工程师那下面的内容基本可以照着复现。如果你是完全没碰过 CAD 的小白也能通过它理解 text-to-cad 的边界在哪里、哪些事它现在做不好、哪些事它已经能稳定输出。我不会只讲概念重点放在怎么把一句描述变成能用的 STEP 文件以及中间那些文档里不会写的坑。需要先说明一点text-to-cad 不是一个单一软件而是一类方法的统称。目前主流实现路径有三条——基于大模型直接生成 CAD 脚本代码、基于参数化模板做语义填充、基于几何内核做约束求解。三条路各有适用场景后面会逐一拆开讲。2. 三条技术路线的取舍为什么不能只用一种方法2.1 大模型直接生成 CAD 脚本的可行性边界最直观的做法是让大模型读一句描述直接吐出 CadQuery 或 OpenSCAD 的代码。我实测过不少次结论是简单几何体成功率很高复杂装配体基本靠运气。比如“一个长 80mm、宽 40mm、高 20mm 的方块四角倒 R5 圆角中心打一个直径 10mm 的通孔”这种描述大模型能稳定生成可运行代码。但一旦涉及“这个孔要和另一个零件的轴对齐”“壁厚要随高度渐变”模型就开始胡编参数。原因不难理解大模型擅长的是语言模式匹配不是空间约束推理。它生成的代码往往“看起来对”但尺寸链是断的。我的做法是把它当成代码草稿生成器而不是最终方案。生成后必须过一遍几何校验检查体积、包围盒、特征数量是否符合预期。下面这段是我常用的校验骨架import cadquery as cq result cq.Workplane(XY).box(80, 40, 20).edges(|Z).fillet(5).faces(Z).workplane().hole(10) # 关键校验包围盒和体积 bb result.val().BoundingBox() print(f包围盒: {bb.xlen:.2f} x {bb.ylen:.2f} x {bb.zlen:.2f}) print(f体积: {result.val().Volume():.2f} mm^3) # 预期体积 80*40*20 - 圆角损失 - 孔体积偏差超过 5% 就要人工复核 expected 80*40*20 - 4*(25 - 3.14159*25/4)*20 - 3.14159*25*20 assert abs(result.val().Volume() - expected) / expected 0.05, 体积偏差过大几何可能出错这段校验逻辑看着简单但帮我拦下过好几次“代码能跑、模型是错的”的情况。大模型生成的代码最危险的地方不是报错而是静默生成一个形状相似但尺寸错误的模型。2.2 参数化模板加语义填充的稳定打法如果你要生成的是同一类零件比如法兰、支架、齿轮毛坯那参数化模板的稳定性远超大模型直出。思路是先用 CadQuery 写好一个带参数的函数再用自然语言解析出参数值填进去。这样几何逻辑是确定的语言模型只负责“抽参数”这一件事出错概率大幅下降。我做过一个支架生成器模板里固定了底板、立板、加强筋的拓扑关系只把长宽高、孔径、孔位这些做成变量。用户输入“底板 120x80立板高 60四个 M8 孔”解析层提取出数值模板层负责建模。实测下来同类型零件的首次成功率从大模型直出的三成提升到九成以上。代价是模板要提前写灵活性受限但工程场景里“稳定”往往比“万能”更重要。2.3 几何内核约束求解的适用场景第三条路最重也最接近传统 CAD 的内核逻辑把描述转成约束方程组交给几何求解器算。这条路的优势是能处理真正的参数联动比如“孔始终位于板的几何中心”“壁厚随外径线性变化”。但实现成本高需要对接 OpenCASCADE 这类内核还要自己写约束解析。除非你要做的是交互式设计工具否则不建议一上来就走这条。我的建议是先用模板法跑通业务等遇到模板覆盖不了的约束关系再考虑引入求解器。三条路线的对比如下路线首次成功率开发成本适用场景主要风险大模型直出脚本低到中低简单零件、原型验证静默尺寸错误参数化模板语义填充高中同类型零件批量生成模板覆盖不足几何内核约束求解高高交互式设计、复杂约束开发周期长3. 把描述变成 STEP一条可复现的完整链路3.1 环境准备里最容易翻车的地方CadQuery 的安装是第一个坎。它依赖 OpenCASCADE 的 Python 绑定在 Windows 上直接用 pip 装经常遇到编译问题。我踩过的坑是系统里同时存在多个 Python 版本pip 装到了 A 版本运行时用的却是 B 版本报错信息还特别隐晦。稳妥做法是用 conda 建独立环境把版本锁死conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery2.4用 conda-forge 渠道装 CadQuery它会自动处理好 OpenCASCADE 的依赖比 pip 省心得多。装完先跑一句import cadquery as cq; print(cq.__version__)确认能导入再往下走。另外提醒一句如果你机器上之前装过其他 CAD 软件注意环境变量里有没有冲突的 DLL 路径这个在 Windows 上偶尔会导致导入失败。3.2 描述解析层的设计要点解析层要做的事是把“长 80 宽 40 高 20四角 R5中心通孔直径 10”这种描述转成结构化的参数字典。我的做法是用正则先抽数值和单位再用关键词映射到参数名。这里有个经验不要让模型直接输出最终代码让它输出 JSON 参数中间加一层校验出错时定位容易得多。import re import json def parse_description(text): # 抽取带单位的数值 pattern r([\u4e00-\u9fa5a-zA-Z])\s*(\d(?:\.\d)?)\s*(mm|cm|m)? matches re.findall(pattern, text) params {} for name, value, unit in matches: value float(value) if unit cm: value * 10 elif unit m: value * 1000 params[name] value return params # 实测中文描述里数值和名称的顺序不固定正则要能容忍 print(parse_description(长80mm 宽40 高20圆角R5孔径10))实测下来纯正则能覆盖七八成的常见描述剩下的靠关键词表兜底。比如“通孔”映射到 through_hole“盲孔”映射到 blind_hole深度参数单独抽。这一步的准确性直接决定后面建模的成败值得多花时间打磨。3.3 建模执行与 STEP 导出参数齐了之后建模就是调模板函数的事。导出 STEP 用 CadQuery 的 export 接口一行搞定。但这里有个细节STEP 的坐标系和单位要在导出前确认。CadQuery 默认单位是毫米导出时不用额外转换但如果你后续要导入其他软件最好在文件名或元数据里标注单位避免对方按英寸解读。def build_bracket(length, width, height, fillet_r, hole_d): result (cq.Workplane(XY) .box(length, width, height) .edges(|Z).fillet(fillet_r) .faces(Z).workplane().hole(hole_d)) return result part build_bracket(80, 40, 20, 5, 10) cq.exporters.export(part, bracket.step)导出后我习惯用 FreeCAD 或在线 STEP 查看器打开确认一遍重点看三个东西包围盒尺寸对不对、特征有没有丢失、坐标系原点在不在预期位置。这三项没问题这个 STEP 才算能用。4. 从 STEP 到 URDF 和 G-code模型的下游去向4.1 URDF 导入仿真环境的常见报错STEP 是通用交换格式但如果你要做机器人仿真需要的是 URDF。STEP 转 URDF 不是简单改后缀中间要处理几何简化、质量属性、关节定义三件事。我遇到最多的报错是导入仿真环境后模型位置全乱原因是 STEP 里的装配层级和 URDF 的 link-joint 树对不上。处理思路是先在 CAD 里把每个运动部件拆成独立 STEP再在 URDF 里用 joint 把它们连起来。质量属性如果 CAD 里没定义可以按体积乘密度估算惯性张量用简化公式算。这一步没有捷径几何越复杂手工调整越多。我一般会先用简单包围盒代替真实几何跑通运动学确认关节关系对了再换精细模型。4.2 G-code 生成前必须确认的工艺参数如果模型最终要加工那 STEP 之后还要过 CAM 生成 G-code。这里的关键不是 text-to-cad 本身而是工艺参数必须由人确认。刀具直径、进给速度、主轴转速、切削深度这些参数模型给不出来也不该由模型猜。我的做法是 text-to-cad 只负责输出几何CAM 环节单独配置工艺模板两者通过文件解耦。有个容易忽略的点text-to-cad 生成的模型如果包含微小特征比如小于刀具直径的圆角或窄槽CAM 阶段要么加工不出来要么直接报错。所以建模时就要考虑可制造性圆角半径不要小于预期刀具半径槽宽留够余量。这个约束最好写进模板的校验逻辑里生成时就拦掉。4.3 批量生成时的文件组织当你一次要生成几十上百个模型时文件命名和目录结构就很重要了。我的习惯是按“项目_零件名_版本”命名STEP、URDF、G-code 分目录存放再写一个 manifest 记录每个文件的参数来源。这样后期追溯“这个模型是哪句描述生成的”时不用翻聊天记录。import os, json def export_all(parts, out_dir): os.makedirs(out_dir, exist_okTrue) manifest [] for name, part, params in parts: path os.path.join(out_dir, f{name}.step) cq.exporters.export(part, path) manifest.append({name: name, file: path, params: params}) with open(os.path.join(out_dir, manifest.json), w) as f: json.dump(manifest, f, ensure_asciiFalse, indent2)这个 manifest 看着不起眼但在批量返工时能省下大量时间。参数和文件一一对应改哪个参数重新生成哪个文件清清楚楚。5. 实操中真正会卡住你的几个问题5.1 描述歧义导致的模型偏差自然语言最大的问题是歧义。“一个带孔的板”这句话孔在哪、多大、几个、通孔还是盲孔全没说。大模型会按训练数据里的常见模式补全但补出来的未必是你想要的。我的应对策略是在解析层做主动追问如果关键参数缺失不猜直接返回缺参列表让用户补。这比生成一个错误模型再返工要高效得多。实测中把“缺参追问”加进去之后首次生成可用率提升明显。因为很多偏差不是模型能力问题而是输入信息本身不完整。工程场景里宁可多问一句也不要生成一个看起来对但装不上的零件。5.2 单位与精度陷阱单位混乱是 CAD 自动化的经典坑。描述里写“长 8”是 8mm 还是 8cm模型默认按 mm 处理但用户可能想的是 cm。我的做法是强制要求描述里带单位解析时统一转成 mm并在输出时把单位写进元数据。精度方面浮点数运算会有微小误差导出 STEP 时保留三位小数通常够用但如果是配合公差要求高的场景要保留更多位。还有一个隐蔽的坑某些 CAD 内核在布尔运算后会产生极薄的面或极短的边这些在后续 CAM 或仿真里会引发报错。生成后跑一遍几何清理合并共面、移除微小边能避免很多下游问题。5.3 版本兼容与格式回读STEP 有多个版本AP203、AP214、AP242不同软件默认导出的版本不一样。我遇到过导出的 STEP 在自己这边能打开发给对方却报错的情况最后发现是版本差异。稳妥做法是导出时显式指定 AP214 或 AP242这两个兼容性最好。回读验证也很重要导出后重新导入一次对比包围盒和体积确认没有信息丢失。# 导出后回读校验 import cadquery as cq original build_bracket(80, 40, 20, 5, 10) cq.exporters.export(original, check.step) reimported cq.importers.importStep(check.step) print(f原始体积: {original.val().Volume():.2f}) print(f回读体积: {reimported.val().Volume():.2f})体积对不上就说明导出或回读过程有问题得查格式设置。这个校验我一般会写进自动化流程每次导出都跑一遍。6. 我对 text-to-cad 落地节奏的真实判断折腾这段时间下来我的体会是text-to-cad 现在最成熟的用法不是替代设计师而是把重复性建模变成可编程流程。同类型零件批量生成、参数化模板快速出图、设计意图的版本化管理这些场景它已经能稳定创造价值。但涉及复杂装配、精密配合、可制造性深度优化还是得靠人。如果你打算在自己的工作流里引入这套东西我的建议是从一个具体的小场景切入比如“每周要画十几个相似支架”先把模板和解析层搭起来跑通再扩展。别一上来就追求“说一句话生成整台机器”那个目标现在还太远。把边界摸清楚在边界内它很好用越界使用返工的时间可能比自己画还长。另外工具链的选择上CadQuery 适合代码驱动FreeCAD 适合需要图形界面辅助确认OpenSCAD 适合纯参数化简单几何。选哪个取决于你的团队更习惯哪种工作方式没有绝对优劣。我自己的组合是 CadQuery 做生成、FreeCAD 做校验、manifest 做追溯跑了大半年稳定性可以接受。