text-to-cad实战:从自然语言到STEP模型的参数化生成

发布时间:2026/10/8 5:41:26
text-to-cad实战:从自然语言到STEP模型的参数化生成
1. 从一段文字到一张图纸text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个词是在一个做机械设计自动化的群里。有人丢了一张截图左边是一段自然语言描述——“一个 80x60x10 的底板四角各开一个 M4 沉头孔中心挖一个直径 30 的通孔”右边直接生成了一张带尺寸标注的零件图还能导出 STEP 文件。当时群里就炸了做非标设计的朋友说这玩意儿要是靠谱能省掉一半的重复建模时间。text-to-cad直译就是“文本转 CAD”。它的核心逻辑很直接你用人话描述一个零件或者一个装配体的几何特征、尺寸约束、材料属性系统把这套自然语言解析成结构化的几何参数再驱动 CAD 内核生成三维模型最后输出成通用的 CAD 格式文件。这里的关键词是CAD、STEP、URDF、G-code——它们分别代表了这条链路上不同的输出终点。为什么这件事值得单独拿出来讲因为传统 CAD 建模的流程是“人脑理解需求 → 人脑翻译成草图约束 → 手动拉伸切除 → 手动装配”。这个流程里最耗时的不是软件操作而是“翻译”和“重复”。一个标准件库里的法兰改个孔径和孔数就要重新画一遍一套非标设备的支架结构大同小异只是尺寸不同也要一个个建。text-to-cad 想干的事就是把这部分重复劳动交给程序让人只负责描述需求。它适合谁我梳理了一下大概三类人最用得上。第一类是非标自动化工程师每天面对大量“长得差不多、尺寸不一样”的零件用文本模板批量生成能省大量时间。第二类是机器人方向的开发者需要频繁生成 URDF 模型来做仿真手写 URDF 的 link 和 joint 几何参数极其痛苦用文本描述生成就顺很多。第三类是做参数化设计的产品经理或创客不懂 CAD 软件的操作但能说清楚自己想要什么形状text-to-cad 降低了他们表达设计意图的门槛。但这里要先泼一盆冷水text-to-cad 不是“说一句话就出一个能直接加工的零件”。它目前的能力边界在于规则明确、特征可参数化的几何体。你让它生成一个“好看的手机壳”它大概率给你一个方盒子但你让它生成“一个 100x50x5 的板上面均布 6 个直径 8 的通孔孔间距 15”它能做得又快又准。理解这个边界后面的实操才不会跑偏。2. 拆解 text-to-cad 的技术链路从一句话到 STEP 文件2.1 自然语言解析层把“人话”变成“参数”这一步是整个链路里最容易被低估的环节。很多人以为难点在三维建模其实真正的坑在“理解”。自然语言描述天然带有歧义和省略。比如“一个带孔的板”孔在哪多大几个什么类型的孔如果描述里没写系统就得猜猜错了模型就废了。目前主流的做法有两种。一种是基于规则模板的解析提前定义好一套语法结构比如“尺寸 特征 约束”的句式用户按模板填内容。这种方式准确率高但灵活性差用户必须学会“机器能听懂的话”。另一种是基于大语言模型的语义解析把自然语言直接映射成结构化的 JSON 参数再交给几何引擎。这种方式灵活但存在幻觉问题——模型可能编造一个不存在的尺寸或者误解约束关系。我在实际测试中的体会是纯 LLM 解析适合做原型验证生产环境一定要加一层规则校验。具体做法是让 LLM 输出一个中间格式的参数字典然后用一套校验规则去检查——尺寸是否为正数、孔是否在板的范围之内、约束是否矛盾。校验不通过的要么让 LLM 重新生成要么直接报错让用户补充描述。这个“LLM 规则校验”的组合比单纯依赖任何一方都稳。还有一个细节单位。自然语言里说“长 100”是毫米还是厘米如果系统不明确单位生成的模型尺寸可能差 10 倍。我的做法是在解析层强制要求单位或者在系统提示里写死“所有尺寸默认单位为毫米”并在输出时显式标注。这个坑我踩过生成的一个支架比预期大了十倍导入仿真软件后直接穿模。2.2 几何建模层参数如何驱动出三维形状解析出来的参数要变成真正的三维几何中间需要一个几何内核。常见的开源选择有OpenCASCADE简称 OCCT商业的有 Parasolid、ACIS。text-to-cad 项目里用 OCCT 的居多因为它开源、功能全能处理布尔运算、倒角、抽壳这些常见操作。这一层的核心工作是特征映射。什么意思就是把“沉头孔”这个语义映射成 OCCT 里的一系列操作先打一个通孔再在孔口做一个锥形切除。把“均布”映射成一个环形阵列或者线性阵列的操作。把“中心挖通孔”映射成在指定坐标位置做圆柱体布尔减运算。这里有个经验特征映射的粒度要适中。太粗了比如把“带孔板”直接映射成一个固定模板灵活性就没了太细了比如把每个顶点坐标都让 LLM 生成出错概率极高。我的建议是把常见零件拆成“基体 特征”的组合。基体就是拉伸、旋转这些基本操作特征是孔、槽、倒角、圆角这些修饰操作。LLM 只需要输出“基体类型 尺寸 特征列表 特征参数”几何层负责把特征按顺序应用到基体上。顺序很重要。先打孔再倒角和先倒角再打孔结果可能完全不同。所以解析层输出的特征列表必须是有序的几何层按顺序执行。这个顺序在自然语言里往往没有明确说需要根据工程常识来推断。比如“一个带倒角的板上面有孔”通常理解为先做板再倒角最后打孔。如果顺序反了倒角可能会被孔打断影响外观和功能。2.3 格式输出层STEP、URDF、G-code 各自的门道模型建好了输出成什么格式取决于你要拿它干什么。这三个格式代表了三条不同的下游路径。STEP是通用三维模型交换格式几乎所有的 CAD 软件都能打开。它的特点是保留完整的边界表示B-rep精度高适合后续在 SolidWorks、Fusion 360 里继续编辑或者导入 CAM 软件做加工路径规划。text-to-cad 输出 STEP 时要注意单位一致性和坐标系对齐。我遇到过导出的 STEP 在另一个软件里打开后方向不对原因是建模时的坐标系和导出时的坐标系没有统一。解决办法是在建模阶段就约定好Z 轴朝上原点在零件底面中心或者一个明确的基准点上。URDF是机器人领域描述模型的标准格式全称是 Unified Robot Description Format。它描述的不是一个静态零件而是一个带关节的装配体。每个 link 有视觉几何、碰撞几何、惯性矩阵每个 joint 有类型、轴线、限位。text-to-cad 生成 URDF 的难点在于惯性参数的计算。一个 link 的质量、质心、转动惯量如果只靠文本描述很难精确给出。常见的做法是根据几何形状和指定的材料密度用程序自动计算。比如一个长方体 link给定长宽高和密度转动惯量是有解析公式的直接算就行。复杂形状可以用网格近似或者体素化来估算。G-code是数控加工和 3D 打印的指令格式。从 text-to-cad 到 G-code中间其实还缺了一步工艺规划。你得决定用什么刀具、走刀路径怎么走、切削参数是多少。目前 text-to-cad 项目直接输出 G-code 的还比较少更多是输出 STEP 后再导入切片软件或者 CAM 软件生成。但如果要做闭环可以在几何层之后加一个简单的工艺规则引擎比如“通孔用钻孔循环外形用轮廓铣削”生成基础的 G-code 框架。这一步的复杂度很高建议初期先不做把 STEP 输出做稳。3. 动手实现一个最小可用的 text-to-cad 流程3.1 环境准备与工具选型要自己搭一个 text-to-cad 的原型不需要一上来就搞大而全。我的建议是先用 Python 把链路跑通核心依赖就三个CadQuery基于 OCCT 的 Python 建模库、OpenAI API 或本地 LLM做语义解析、FastAPI做接口服务。CadQuery 是我试过对开发者最友好的参数化 CAD 库。它的语法接近自然语言比如cq.Workplane(XY).box(80, 60, 10).faces(Z).workplane().hole(30)就能生成一个带中心孔的板。而且它直接支持导出 STEP、STL、DXF 等格式省去了自己调 OCCT 接口的麻烦。LLM 的选择看你的预算和网络条件。如果追求效果用 GPT-4 级别的模型做解析准确率明显高于小模型。如果考虑成本和数据隐私可以用本地部署的开源模型比如 CodeLlama 或者 Qwen 的代码版本但需要自己写更详细的提示词和校验规则。我实测下来对于结构清晰的零件描述7B 级别的模型加上好的提示词也能达到可用的程度。FastAPI 负责把整个流程包成一个 HTTP 接口接收文本描述返回 STEP 文件的下载链接或者 Base64 编码。这样前端或者其他系统就能方便地调用。3.2 提示词设计与参数校验提示词是 text-to-cad 的“灵魂”。写得好模型输出稳定写得烂天天给你编尺寸。我的提示词模板大概长这样你是一个 CAD 参数解析器。用户会用自然语言描述一个零件。 你需要输出一个 JSON 对象包含以下字段 - unit: 单位固定为 mm - base: 基体包含 typebox/cylinder、dimensions长宽高或半径高度 - features: 特征列表每个特征包含 typehole/slot/fillet/chamfer、position坐标、parameters尺寸参数 - material: 材料名称默认 steel 注意 1. 所有尺寸必须是正数。 2. 孔的位置用相对于基体中心的坐标表示。 3. 如果用户描述模糊选择最常见的工程默认值并在 notes 字段说明。 4. 只输出 JSON不要输出其他内容。这个模板的关键在于约束输出格式和处理模糊性。我试过不加“只输出 JSON”这句话模型会在 JSON 前后加一堆解释文字解析起来很麻烦。加上之后输出干净很多。拿到 JSON 之后必须做校验。我写了一个validate_params函数检查项包括尺寸是否为正、孔是否在基体范围内、特征之间是否冲突比如两个孔重叠、材料是否在支持列表里。校验不通过的要么返回错误让用户修改描述要么触发一次 LLM 重试把错误信息作为反馈传回去。这个重试机制很管用能把一部分模糊描述自动修正。3.3 从参数到模型的代码实现下面是一个简化的核心代码展示从 JSON 参数到 CadQuery 模型的过程import cadquery as cq def build_model(params): base params[base] if base[type] box: l, w, h base[dimensions] model cq.Workplane(XY).box(l, w, h) elif base[type] cylinder: r, h base[dimensions] model cq.Workplane(XY).circle(r).extrude(h) else: raise ValueError(Unsupported base type) for feat in params[features]: if feat[type] hole: x, y feat[position] d feat[parameters][diameter] model model.faces(Z).workplane().center(x, y).hole(d) elif feat[type] fillet: r feat[parameters][radius] model model.edges(|Z).fillet(r) # 其他特征类型类似处理 return model def export_step(model, filename): cq.exporters.export(model, filename, exportTypeSTEP)这段代码里faces(Z)表示选择 Z 方向最高的那个面作为工作平面center(x, y)把工作平面原点移到指定位置hole(d)打一个直径 d 的通孔。这些操作都是 CadQuery 的标准用法文档里有详细说明。实际项目中特征的处理要复杂得多。比如沉头孔需要先打一个通孔再在孔口做一个锥形切除。CadQuery 里可以用cboreHole或者cskHole直接实现但需要传入正确的参数。我的做法是在特征映射层把“沉头孔”翻译成 CadQuery 的cskHole(diameter, cskDiameter, cskAngle)参数从 JSON 里取。还有一个容易忽略的点坐标系。CadQuery 默认的 Z 轴是朝上的但有些 CAD 软件默认 Y 轴朝上。导出 STEP 时如果下游软件用的是不同的坐标系约定模型方向就会不对。解决办法是在导出前做一次旋转变换或者在文档里明确说明坐标系约定。我一般会在生成的 STEP 文件里附带一个 README写明“Z 轴朝上原点在底面中心”。3.4 批量生成与模板化单个零件生成跑通之后最有价值的是批量生成。非标设计里经常有一组零件结构相同只是尺寸不同。这时候可以用一个 CSV 或者 Excel 文件每行是一组参数循环调用生成函数批量输出 STEP 文件。我做过一个测试一个包含 50 个不同尺寸法兰的列表用 text-to-cad 批量生成从解析到导出 STEP总共花了不到 3 分钟。如果手动建模一个法兰大概 5 分钟50 个就是 4 个多小时。这个效率提升是实打实的。模板化的另一个好处是版本管理。每个零件的描述文本和生成的参数 JSON 都可以存进 Git改了什么一目了然。传统 CAD 文件是二进制的diff 起来很痛苦文本描述就友好多了。4. 实操中踩过的坑与排查技巧4.1 常见问题速查表问题现象可能原因排查方法解决方案生成的模型尺寸明显不对单位解析错误检查 JSON 里的 unit 字段和数值在提示词里强制单位校验时检查数值范围孔的位置偏了坐标系理解不一致对比 JSON 坐标和模型实际位置统一约定原点位置在提示词里说明导出 STEP 后打不开文件写入不完整或格式错误用文本编辑器看文件头是否为 ISO-10303检查导出函数的参数确保 exportType 正确LLM 输出不是合法 JSON提示词约束不够强打印原始输出看格式加“只输出 JSON”约束用 JSON 修复库兜底特征顺序导致模型错误特征列表顺序不对逐步执行特征看哪一步出错在解析层按工程常识排序或让用户显式指定复杂形状生成失败OCCT 布尔运算失败查看异常信息简化形状分步生成或换用网格建模4.2 几个让我印象深刻的坑第一个坑是“孔打穿了不该打穿的地方”。有一次描述里写“在板上打一个深 5 的孔”LLM 解析成了通孔结果把 10 厚的板打穿了。问题出在“深”这个词的歧义——是孔的总深度还是从表面往下的深度后来我在提示词里明确如果用户说“深 X”默认是从表面往下的深度如果 X 大于板厚则视为通孔。这个规则写进去之后类似问题就没再出现。第二个坑是“倒角把孔口削掉了”。一个零件先打了孔然后对整个外边缘倒角结果倒角操作把孔口附近的材料也削掉了一块。原因是倒角选择边的时候把孔口的边也选进去了。解决办法是在选择边时加过滤条件只选外轮廓的边不选内部特征的边。CadQuery 里可以用edges(|Z)选平行于 Z 轴的边或者用edges(%CIRCLE)排除圆形边。第三个坑是“URDF 的惯性矩阵不对”。生成 URDF 时我一开始随便填了一个单位矩阵作为惯性结果在仿真里机器人一动就飞出去了。后来老老实实根据几何形状和密度计算惯性矩阵才稳定下来。对于长方体惯性矩阵是对角阵对角线元素是m/12 * (h^2 d^2)这样的公式。这个计算不难但不能省。4.3 提升生成成功率的几个技巧技巧一给示例。在提示词里放一两个输入输出的例子LLM 的解析准确率会明显提升。比如给一个“80x60x10 的板中心打直径 30 的通孔”对应到完整 JSON 的例子模型就能学会这种映射关系。技巧二分步解析。不要指望一次调用就拿到完美的 JSON。可以拆成两步第一步让 LLM 提取所有尺寸和特征关键词第二步再让 LLM 把这些关键词组织成结构化参数。两步之间可以加人工确认或者规则校验降低出错概率。技巧三缓存常用零件。对于反复出现的标准件比如 M4 沉头孔、M6 螺纹孔可以把它们的参数和对应的 CadQuery 代码缓存起来下次直接调用不用再走 LLM 解析。这样既快又稳。技巧四可视化预览。生成 STEP 之前先导出一张 PNG 预览图让用户确认形状对不对。CadQuery 支持导出 SVG 或者用cq.exporters.export导出 STL 后用其他库渲染。多一步确认少很多返工。5. 从 text-to-cad 到实际生产还差什么5.1 公差与配合文本描述难以覆盖的领域text-to-cad 目前能处理的是理想几何但实际生产中公差和配合才是决定零件能不能用的关键。一个孔标注“直径 10”加工出来可能是 10.02也可能是 9.98。如果这个孔要和一个轴配合公差没定好要么装不进去要么太松。自然语言里描述公差很别扭。你可以说“直径 10 的孔公差 H7”但 LLM 不一定理解 H7 的含义也不一定能把它映射成具体的上下偏差。我的做法是在参数 JSON 里加一个tolerance字段用标准公差等级表示然后在几何层不处理公差只在输出的 STEP 文件里附带一个公差表。下游的 CAM 软件或者加工师傅根据公差表来决定加工精度。配合的描述更复杂。“轴和孔间隙配合”这种话需要查表才能确定具体的公差带。目前 text-to-cad 项目很少涉及这一块更多是生成理想模型公差由后续工艺保证。如果你要做的是直接驱动机床的项目公差处理是绕不过去的坎建议单独做一个公差引擎。5.2 装配体与运动约束单个零件生成只是第一步真正的挑战是装配体。一个机构由多个零件组成零件之间有装配关系有的固定有的可以转动或滑动。用自然语言描述装配关系比描述单个零件难得多。比如“一个齿轮箱输入轴和输出轴平行中心距 50齿轮模数 2齿数比 3:1”。这句话里包含了多个零件的几何参数和它们之间的位置约束。目前的 LLM 能提取出关键词但很难直接生成完整的装配体模型。一个可行的路径是先用 text-to-cad 生成各个零件再用一个单独的装配描述来定义零件之间的约束。装配描述可以用简化的语法比如“part A 的孔中心与 part B 的轴中心对齐距离 50”。然后几何层根据这些约束计算每个零件的变换矩阵组装成装配体。URDF 天然适合描述这种带关节的装配体所以机器人领域的 text-to-cad 项目往往直接输出 URDF。5.3 与现有 CAD 工作流的集成text-to-cad 生成的文件最终要融入现有的设计流程。常见的集成方式有三种。第一种是作为插件。在 SolidWorks、Fusion 360 里装一个插件输入文本描述直接在当前文档里生成特征。这种方式用户体验最好但开发成本高需要熟悉各个 CAD 软件的 API。第二种是作为独立服务。text-to-cad 跑在一个服务器上设计师通过网页或者命令行提交描述下载 STEP 文件再手动导入 CAD 软件。这种方式开发简单适合快速验证。第三种是作为批处理工具。把 text-to-cad 集成到 CI/CD 流程里每次设计参数变更自动生成新的模型文件推送到版本库。这种方式适合参数化程度高的产品线。我目前用的是第二种因为最灵活不依赖特定 CAD 软件。等流程稳定了再考虑做插件。5.4 一个实际案例批量生成非标支架最后分享一个我实际做过的案例。需求是为一套自动化设备生成 20 个不同尺寸的 L 型支架。每个支架的底板长宽、立板高度、安装孔位置都不同但结构完全一样。传统做法是一个个画大概需要半天。用 text-to-cad 的做法是先写一个支架的模板描述把可变尺寸用占位符表示。然后从 Excel 里读取 20 组参数循环替换占位符调用生成函数批量导出 STEP。整个过程写代码加调试花了两个小时但生成只用了两分钟。而且以后再有类似需求改改 Excel 就能复用。这个案例让我确信text-to-cad 的价值不在于替代设计师而在于把设计师从重复劳动里解放出来。它适合处理“结构固定、尺寸变化”的零件不适合处理“结构创新、形态复杂”的设计。认清这个边界用对地方效率提升是实实在在的。如果你也想试试我的建议是从一个最简单的零件开始——一块带孔的板。把从描述到 STEP 的链路跑通再逐步增加特征类型和复杂度。不要一上来就搞装配体那个坑太深。先把单零件的生成做稳再考虑扩展。