
1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人脑子里浮现的画面大概是对着电脑说一句给我画个法兰盘屏幕上就自动蹦出一个可以加工的三维模型。这个想象方向没错但真正落地的时候它解决的问题比省几下鼠标要深刻得多。传统 CAD 工作流的本质是人肉翻译。设计需求先以自然语言的形式存在于工程师、客户、产品经理的脑子里或者聊天记录里然后由人把它翻译成草图约束、拉伸参数、倒角半径、装配关系。这个翻译过程有三个天然痛点一是慢一个中等复杂度的零件从需求到可编辑模型熟练工程师也要几十分钟到几小时二是不可复现同一个需求交给两个人画出来的拓扑结构可能完全不同三是难以批量当你有几百个规格相近、只有尺寸不同的零件时手工建模就是纯粹的体力活。text-to-cad 要做的就是把自然语言描述和参数化几何模型之间的这层翻译自动化。它的输入是一段人话比如一个外径 80mm、内径 40mm、厚度 12mm 的圆环边缘倒 2mm 圆角输出则是一份机器可读、可继续编辑、可被下游工具消费的几何文件——可能是 STEP、可能是 URDF、也可能是直接给加工用的 G-code。这里必须先把一个概念掰清楚text-to-cad 不是一个软件而是一类技术方案的统称。它背后可能是一个调用大语言模型生成 OpenSCAD 脚本的管道也可能是一个把自然语言映射到参数化特征树的规则引擎还可能是基于扩散模型直接生成 B-rep 表示的研究型系统。理解这一点很重要因为不同技术路线的能力边界、精度上限、适用场景差别巨大选错了方向后面全是坑。从关键词和热搜词能看出来关注这个方向的人大致分几类有做机械设计想提效的工程师有搞机器人仿真需要批量生成 URDF 的开发者有做钣金、盘扣这类标准化构件的从业者也有单纯被AI 画图吸引进来的初学者。这几类人的需求其实并不一样——工程师要的是精度和可编辑性仿真开发者要的是格式兼容和批量能力标准化构件从业者要的是参数模板复用。所以下面我会分场景讲而不是给一个万能方案。2. 拆解 text-to-cad 的技术链路从文本到几何中间发生了什么2.1 文本理解层为什么外径 80比大一点的圆环值钱整条链路的第一环是把自然语言解析成结构化的设计意图。这一步看起来简单实际上决定了整个系统的天花板。大语言模型在这里的角色是意图抽取器不是几何生成器。它要做的事情是从一个外径 80mm、内径 40mm、厚度 12mm 的圆环边缘倒 2mm 圆角里抽出{shape: ring, outer_diameter: 80, inner_diameter: 40, thickness: 12, fillet: 2, unit: mm}这样一个结构化对象。注意模型本身并不知道圆环长什么样它只是把语言映射成了参数。这就引出一个非常关键的实操经验文本描述的确定性直接决定输出质量。我做过一组对比测试同样一个零件用模糊描述和精确描述分别喂给同一套管道结果差异大到离谱。输入描述解析结果输出可用性做个大一点的圆环参数缺失模型只能猜默认值基本不可用尺寸随机一个圆环只有形状无尺寸需要人工补全所有参数外径 80、内径 40、厚 12 的圆环参数完整但缺单位可用需确认单位制外径 80mm、内径 40mm、厚度 12mm 的圆环边缘倒 2mm 圆角参数完整且明确直接可用所以如果你打算自己搭一套 text-to-cad 流程第一件要做的事不是选模型而是定义一套描述规范。哪怕只是内部用也要约定好尺寸必须带单位、特征必须按顺序描述、基准面必须指明。这套规范就是你和系统之间的接口协议没有它后面所有环节都在赌运气。2.2 参数化建模层OpenSCAD 为什么成了事实标准文本被解析成参数之后下一步是把它变成几何。目前最主流的做法是生成代码而不是直接生成几何而 OpenSCAD 几乎是这个环节的默认选择。原因很实在OpenSCAD 是纯文本的、声明式的、参数驱动的。一个圆环在 OpenSCAD 里就是几行代码// 圆环参数化模型 outer_d 80; inner_d 40; thickness 12; fillet_r 2; difference() { cylinder(douter_d, hthickness, centertrue, $fn128); cylinder(dinner_d, hthickness2, centertrue, $fn128); }大语言模型生成这样一段代码的可靠性远高于让它直接输出 STEP 文件里的 B-rep 数据。因为代码是离散的、有明确语法的、可以被解释器验证的而 B-rep 是连续的、拓扑关系复杂的、一个控制点错了整个面就废了。这里有个很多人忽略的细节$fn参数决定了圆的光滑度。默认值下 OpenSCAD 画出来的圆其实是多边形$fn128意味着用 128 条边逼近一个圆。这个值设太小导出的 STEP 在别的软件里打开会看到明显的棱角设太大文件体积和计算时间都会飙升。我的经验是一般零件用 64 到 128 之间需要高精度配合的面用 256纯粹做视觉展示用 32 就够了。2.3 格式转换层STEP、URDF、G-code 各管一段几何生成出来之后要流向不同的下游就得转成不同的格式。这三个格式经常被混为一谈其实它们服务的目标完全不同。STEP是通用三维数据交换格式特点是精确表示 B-rep 几何几乎所有 CAD 软件都能读写。它是设计态的格式适合继续编辑、出工程图、做装配。text-to-cad 生成的模型如果要交给机械工程师继续改就必须导出 STEP。URDF是机器人领域的统一描述格式它描述的不只是几何还有关节、连杆、运动学关系。一个 URDF 文件里几何只是visual和collision标签里的内容真正重要的是joint定义的运动约束。所以从 text-to-cad 到 URDF中间多了一层装配语义的映射——你得告诉系统哪个零件连哪个零件、怎么连、能怎么动。G-code是加工指令是制造态的格式。它不描述几何本身而是描述刀具怎么走。从模型到 G-code 中间还隔着切片或 CAM 工序text-to-cad 一般只负责把模型准备好G-code 由下游的切片软件或 CAM 系统生成。格式服务阶段核心内容典型下游STEP设计B-rep 精确几何CAD 软件、工程图URDF仿真几何 关节运动学机器人仿真平台G-code制造刀具路径指令数控机床、3D 打印机理解这三者的分工能帮你避免一个常见错误拿 STEP 直接去喂仿真或者拿 URDF 去出工程图。前者会丢失运动学信息后者会丢失精确几何。格式选错后面全是返工。3. 自己搭一套 text-to-cad 管道选型、代码与踩坑实录3.1 技术选型为什么我最终选了LLM OpenSCAD 转换器这条路线在动手之前我调研过几条路线这里把对比摊开讲方便你按自己的情况选。第一条是端到端神经网络生成也就是训练一个模型直接从文本输出几何表示。这条路学术上很热但工程上目前不实用训练数据难搞、生成结果不可控、精度没保证、出了问题没法调试。除非你是做研究的否则不建议碰。第二条是规则模板匹配预先写好一堆参数化模板文本进来做关键词匹配填参数。这条路稳定、可控、快但泛化能力差遇到模板没覆盖的形状就歇菜。适合产品线固定、构件标准化的场景比如盘扣、法兰、标准件这类。第三条是LLM 生成参数化脚本也就是让大语言模型把自然语言翻译成 OpenSCAD 或 CadQuery 代码再执行代码得到几何。这条路泛化能力好、可调试、可编辑是目前工程落地最现实的选择。缺点是对模型的代码能力有要求复杂形状容易生成错误代码。我最终选的是第三条具体组合是大语言模型负责文本到 OpenSCAD 代码的翻译OpenSCAD 命令行负责代码到 STL/STEP 的转换再用 FreeCAD 的 Python API 做 STEP 导出。这套组合的好处是每一环都可以单独替换和调试出问题能定位到具体是哪一步。3.2 核心代码一个能跑通的最小管道下面是我实际在用的最小可用管道Python 写的依赖openai或任何兼容接口、subprocess调用 OpenSCAD、FreeCAD做格式转换。import subprocess import os from pathlib import Path def text_to_openscad(description: str, llm_client) - str: 把自然语言描述翻译成 OpenSCAD 代码 system_prompt 你是一个 OpenSCAD 代码生成器。 规则 1. 所有尺寸必须使用 mm 单位 2. 参数必须提取为顶部变量方便修改 3. 圆孔和圆柱使用 $fn128 4. 只输出代码不要任何解释文字 5. 代码必须能直接运行不能有语法错误 response llm_client.chat.completions.create( modelgpt-4, messages[ {role: system, content: system_prompt}, {role: user, content: description} ], temperature0.1 # 低温度保证输出稳定 ) return response.choices[0].message.content def openscad_to_stl(scad_code: str, output_path: str) - bool: 调用 OpenSCAD 命令行把代码渲染成 STL scad_file output_path.replace(.stl, .scad) with open(scad_file, w) as f: f.write(scad_code) result subprocess.run( [openscad, -o, output_path, scad_file], capture_outputTrue, textTrue, timeout120 ) if result.returncode ! 0: print(fOpenSCAD 报错: {result.stderr}) return False return True def stl_to_step(stl_path: str, step_path: str): 用 FreeCAD 把 STL 转成 STEP import FreeCAD import Mesh import Part mesh Mesh.Mesh(stl_path) shape Part.Shape() shape.makeShapeFromMesh(mesh.Topology, 0.1) shape.exportStep(step_path)这段代码里有两个地方值得展开说。第一个是temperature0.1。生成代码这种任务需要的是确定性而不是创造性。温度调高模型会开始发挥给你加一些你没要求的特征或者把参数名改得五花八门。0.1 到 0.2 之间是比较稳的区间。第二个是 STL 转 STEP 这一步。这里有个精度陷阱makeShapeFromMesh的第二个参数是网格到曲面的拟合容差我设的是 0.1mm。这个值越小转换后的曲面越接近原始网格但计算越慢而且如果网格本身精度不够强行拟合反而会产生畸形面。实测下来对于$fn128生成的网格0.1mm 是个平衡点。注意STL 是网格格式STEP 是精确曲面格式从 STL 转 STEP 本质上是用曲面去拟合网格一定会损失精度。如果对精度要求高应该让 OpenSCAD 直接导出其他精确格式或者用 CadQuery 这类原生支持 B-rep 的库。3.3 实测踩坑那些文档里不会写的教训坑一单位制混乱。OpenSCAD 默认单位是单位没有物理含义但所有下游软件都默认它是 mm。如果你的描述里混了英寸模型尺寸会差 25.4 倍。我的做法是在 system prompt 里强制要求所有输出都是 mm并且在解析层做一次单位归一化。坑二布尔运算的共面问题。做差集运算时如果两个几何体有完全共面的面OpenSCAD 有时会产生渲染错误或非流形几何。解决办法是让切割体稍微超出一点比如上面代码里内孔圆柱的高度设成thickness2而不是thickness就是为了避免共面。坑三复杂模型的渲染超时。$fn设得高、布尔运算层数多的时候OpenSCAD 渲染一个模型可能要几分钟。我在subprocess.run里加了timeout120超时就报错而不是无限等待。生产环境里这个超时值要根据模型复杂度动态调整。坑四LLM 生成的代码不一定能跑。即使 temperature 很低模型偶尔还是会生成语法错误或者用了不存在的函数。所以必须有一个代码校验环节最简单的做法就是直接跑一遍 OpenSCAD跑不通就带着错误信息让模型重试。我一般设置最多重试 3 次超过就人工介入。4. 不同场景下的落地打法从机械零件到机器人仿真4.1 机械标准件批量生成把重复劳动彻底干掉这是 text-to-cad 最容易见效的场景。假设你要生成一批不同规格的法兰盘传统做法是一个个画用这套管道就是循环喂描述。specs [ 外径 100mm、内径 50mm、厚度 15mm、6 个直径 8mm 均布螺栓孔的法兰, 外径 120mm、内径 60mm、厚度 18mm、8 个直径 10mm 均布螺栓孔的法兰, 外径 150mm、内径 80mm、厚度 20mm、8 个直径 12mm 均布螺栓孔的法兰, ] for i, spec in enumerate(specs): code text_to_openscad(spec, client) openscad_to_stl(code, fflange_{i}.stl)这里的关键经验是描述模板化。上面三条描述的结构完全一致只是数字不同。这种一致性让 LLM 的解析准确率大幅提升因为模式固定。如果你把描述写得五花八门模型每次都要重新理解出错率就上去了。对于盘扣、钣金这类有行业标准的构件我建议更进一步把标准参数表直接做成输入而不是让 LLM 从自然语言里猜。比如盘扣的立杆、横杆规格是固定的你只需要一个 CSV 表格程序读表生成描述再走管道。这样 LLM 只负责表格行到代码的翻译任务更简单可靠性更高。4.2 机器人 URDF 生成几何只是第一步关节才是重点做机器人仿真的朋友经常遇到一个问题从 CAD 导出的模型几何是对的但导入仿真平台后关节全乱了。这是因为 URDF 的核心不是几何而是运动学树。从 text-to-cad 生成 URDF正确的做法是分两步先用管道生成各个连杆的几何STEP 或 STL再单独定义关节关系。关节定义这部分自然语言描述反而不好用因为关节的坐标系、旋转轴、限位这些参数太精确了用结构化配置更靠谱。!-- URDF 关节定义示例 -- joint nameshoulder_joint typerevolute parent linkbase_link/ child linkupper_arm/ origin xyz0 0 0.15 rpy0 0 0/ axis xyz0 1 0/ limit lower-1.57 upper1.57 effort100 velocity1.0/ /joint我的做法是几何用 text-to-cad 批量生成关节用手写配置或者从参数表生成。两者在最后组装成完整 URDF。这样既享受了批量生成几何的便利又保证了运动学定义的准确性。导入仿真平台时还有个常见坑网格坐标系原点。OpenSCAD 生成的模型原点在几何中心还是底面直接影响 URDF 里origin的偏移量。我的习惯是统一让模型底面中心对齐原点这样在 URDF 里只需要处理高度方向的偏移逻辑简单不容易错。4.3 从模型到 G-code别跳过 CAM 直接生成加工指令有些朋友想一步到位让 text-to-cad 直接输出 G-code。这个想法可以理解但实操上要谨慎。G-code 是工艺相关的它不只取决于几何还取决于刀具直径、材料、进给速度、切削深度、机床类型。同一个零件用 6mm 铣刀和用 10mm 铣刀G-code 完全不同。让 LLM 直接从文本生成 G-code等于让它同时猜几何和工艺出错概率极高而且错了可能撞刀。正确的分工是text-to-cad 负责把模型做对导出 STEP 或 STL然后交给专业的 CAM 软件或切片软件生成 G-code。这些软件有刀具库、有碰撞检测、有工艺参数库是专门干这个的。text-to-cad 的价值在于把建模这一步自动化而不是把整条制造链都包了。如果你确实需要批量生成 G-code可行的做法是用 text-to-cad 生成模型再用 CAM 软件的脚本接口比如 FreeCAD 的 Path 工作台批量处理。这样工艺参数还是由 CAM 系统管理只是把重复的建模和导入导出自动化了。5. 精度、可靠性与边界text-to-cad 现在还做不到什么5.1 精度天花板在哪里必须诚实地讲当前 text-to-cad 生成的模型精度上限受制于几个因素。第一是文本本身的精度。你说直径 80mm系统就给你 80mm但工程上 80mm 可能是 80±0.05这个公差信息自然语言里往往不写系统也无从得知。所以 text-to-cad 适合生成名义尺寸模型不适合直接生成带公差的加工模型。第二是代码生成的精度。OpenSCAD 用浮点数计算本身精度足够但$fn参数决定了曲面逼近的精度。一个$fn32的圆实际是多边形最大径向误差可能到零点几毫米。对配合面来说这是不可接受的。第三是格式转换的精度损失。前面说过STL 转 STEP 是拟合会损失精度。如果整个链路是文本→OpenSCAD→STL→STEP那精度损失是累积的。我的建议是对精度敏感的零件text-to-cad 只用来生成初稿最终精度由人工在 CAD 软件里确认和修正。把它当成一个快速起稿工具而不是最终交付工具心态就对了。5.2 复杂拓扑的生成失败模式简单零件圆柱、方块、孔、倒角的生成成功率很高我实测在 90% 以上。但复杂拓扑就开始出问题自由曲面OpenSCAD 不擅长自由曲面生成的结果往往是多面体逼近质量差。复杂相交多个几何体做复杂布尔运算时容易产生非流形边或自相交面。薄壁结构壁厚接近$fn逼近误差时布尔运算可能把薄壁吃掉。大量特征一个零件上有几十个特征时LLM 生成的代码容易漏特征或顺序错误。遇到这些情况我的处理策略是降级到人工让 text-to-cad 生成一个简化版本然后人工在 CAD 里补复杂特征。不要指望它一次到位。5.3 什么场景现在还不适合用基于我的实践以下几类场景目前不建议用 text-to-cad一是外观设计。工业设计里的曲面造型讲究的是美学和手感这不是参数能描述的也不是当前技术能生成的。二是高精度配合件。需要严格控制公差、表面粗糙度的零件还是老老实实手工建模。三是安全关键件。承力结构、压力容器这类模型错了后果严重不适合用自动化工具生成后直接使用。四是一次性简单零件。如果一个零件你手工画只要 5 分钟搭管道、调试、验证的时间可能超过手工。text-to-cad 的价值在批量和重复不在单件。6. 把 text-to-cad 用顺手的几个实战心得6.1 描述规范比模型选择更重要我见过太多人纠结用哪个大模型却忽略了描述规范。实际上一套好的描述规范能让普通模型的表现超过没有规范的顶级模型。我的描述规范核心就几条尺寸必须带单位、特征按建模顺序描述、基准明确、避免歧义词汇大小差不多一律不用。这套规范写下来不到一页纸但它把生成成功率从大概六成提到了九成以上。6.2 建立自己的模板库不要每次都从零生成。把常用的零件类型做成 OpenSCAD 模板text-to-cad 只负责填参数。比如法兰、支架、外壳这些模板里把结构固定好LLM 只需要输出参数值。这样既快又稳还避免了每次生成结果不一致的问题。// 法兰模板 - 只需修改参数 outer_d 100; // 外径 inner_d 50; // 内径 thickness 15; // 厚度 bolt_count 6; // 螺栓孔数量 bolt_d 8; // 螺栓孔直径 bolt_circle 75; // 螺栓孔分布圆直径6.3 一定要做输出验证自动化管道最危险的地方在于静默失败——程序跑完了文件生成了但模型是错的。所以每个环节都要有验证OpenSCAD 执行有没有报错、生成的 STL 体积是否合理太小可能是空模型太大可能是$fn失控、STEP 能否被正常打开。我一般会在管道最后加一个检查读取 STL 的包围盒尺寸和预期尺寸对比偏差超过阈值就报警。这一步能拦住大部分低级错误。6.4 版本管理别偷懒生成的代码、模型文件、参数表全部纳入版本管理。因为 text-to-cad 的输出有随机性即使 temperature 很低也不是完全确定同一个描述两次生成可能有细微差异。有了版本管理你才能追溯这个模型是哪次生成的、用的什么参数、什么版本的模板。我在实际项目里踩过最深的坑就是没有做版本管理结果客户要改一个三个月前的零件我完全想不起来当时是怎么生成的只能从头再来一遍。从那以后所有生成产物都进 Git参数表和模板也一起管。6.5 关于卸载和安装的那些热搜问题热搜词里有一堆关于 CAD 安装、卸载、激活报错的问题这里顺带说一句。text-to-cad 管道本身不依赖某个特定 CAD 软件的安装它依赖的是 OpenSCAD 命令行和 FreeCAD 的 Python 库。这两个都是开源免费的安装干净不会出现那些激活、C 运行库报错的问题。如果你被商业 CAD 的安装问题折磨过用开源工具链搭 text-to-cad 反而省心。OpenSCAD 装完直接有命令行工具FreeCAD 装完import FreeCAD就能用。唯一需要注意的是 FreeCAD 的 Python 版本要和你的主环境匹配版本不匹配时import会失败这时候用 FreeCAD 自带的 Python 解释器跑脚本就行。这套东西我陆陆续续用了大半年从最开始的手忙脚乱到现在能稳定批量出图最大的体会是text-to-cad 不是一个输入一句话就完事的黑盒而是一条需要你精心设计的流水线。描述规范、模板库、验证环节、版本管理这些看起来是额外工作的东西恰恰是让它真正好用的关键。把它当成一个需要调教的工具而不是一个魔法按钮你的预期和实际体验就能对上。