text-to-cad落地指南:大模型+OpenSCAD实现一句话出图

发布时间:2026/9/12 3:54:18
text-to-cad落地指南:大模型+OpenSCAD实现一句话出图 前阵子结构工程师老王扔给我一句话能不能让AI把我刚才说的那个座子直接画出来他说的“座子”是一块带四个腰型孔、底面有沉台的安装板型号、尺寸全是口头交代的。我花了两个星期把 text-to-cad 这条路从选型到落地完整走了一遍。结论先说能做能出图但离“一句话出图”还差一个合格的工艺师。text-to-cad字面意思就是拿自然语言去生成CAD模型。很多人第一反应是“用AI画图”其实这里有个根本区别今天主流的大模型并不会原生输出CAD文件它们最擅长的是把自然语言翻译成一段程序再由程序去驱动几何内核生成模型。想通这一点后面所有技术选型就顺了。这篇文章适合两类人看一类是想用AI辅助日常出图的工程师另一类是准备把文本生成CAD做成内部工具的开发同学。我会尽量把选型逻辑、提示词设计、流水线搭建和实际踩坑都讲透。1. 一句话出图先搞清楚text-to-cad到底走的是哪条路1.1 短视频里的演示为什么总是“刚好成功”短视频里的 text-to-cad 演示十个里有八个是“生成一个M6内六角螺栓”或者“生成一个带圆角的法兰盘”。这类对象在模型训练数据里堆积如山模型几乎是在背标准答案所以看起来又准又快。真实场景根本不是这样。真实需求往往长这样“左下角固定座高度大概30底面要一个沉台上表面四个孔不要跟那个加强筋干涉。”这里面有模糊量词、有位置关系、有隐性的制造常识模型想凭空生成一个准确模型几乎不可能。我见过太多人拿一段模糊描述去跑结果得到一个漂亮但完全无法加工的形状然后开始怀疑AI是不是不行。所以做这个项目首先要放下一个执念text-to-cad 的目标不是让AI直接画出终稿而是让AI把模糊需求翻译成可执行的建模指令再由工程师在CAD里做“最后确认”。想清楚这点工具链的选择就简单了。1.2 目前能落地的三条技术路线我梳理下来真正能落地的路线只有三条其余大多是实验室玩具。第一条是CAD原生API二次开发。比如 AutoCAD 的 .NET 接口、SolidWorks 的 API让大模型生成控制这些API的代码程序自动在CAD里建模。优点是输出的是原生格式、保留特征树缺点是API太庞大、文档分散大模型生成的代码出错率非常高调试成本比手动画图还高。第二条是脚本化建模语言。典型代表是 OpenSCAD、CadQuery、FreeCAD 的 Python API。模型先生成脚本脚本再去驱动几何内核生成网格或实体。链路清晰、错误可控、轮子现成是当前最适合快速落地的路线。第三条是端到端的三维生成模型也就是直接用点云、SDF、NeRF等表示生成几何然后转成CAD网格。这条路对“创意造型”有优势对机械件是灾难——输出是网格而不是参数化特征孔位、公差、装配关系全丢了基本没法进工程流程。三条路放一起对比路线输出格式参数化能力调试难度落地速度CAD原生API原生CAD保留特征树最强最高慢脚本化建模语言STL/STEP等中间格式强中快端到端3D生成网格Mesh弱高慢我最后选了第二条。接下来解释为什么。2. 为什么我绕开了CAD二次开发选了大模型OpenSCAD2.1 CAD二次开发解决的是“模板”不是“从零生成”先说清楚CAD二次开发擅长什么。假设你公司有一款固定产品只是每次尺寸不同那你把参数模板写好程序按表格自动驱动模型这是最成熟的做法没有之一。但 text-to-cad 面对的是“一次性需求”老张口头说一个座子小王口头说一个支架每个需求都不一样。如果你用CAD二次开发意味着每来一个新需求你都要写一套新的API调用逻辑就算有大模型辅助生成代码只要有一个API用法错了整个进程直接崩溃。排查这种错误的时间足够手工建完模型。我并不是否定这条路线。如果目标是生成公司内部固定的标准件族二次开发依然是正确选择。但如果是“把任意文本变成任意模型”脚本化建模语言的泛化能力要好得多。2.2 大模型真正的强项是翻译而不是画图大模型不理解几何但它极其擅长“将弱约束文本翻译成强约束代码”。自然语言里可以有“差不多”“厚一点”“留点间隙”这种模糊表述但代码不行一个数字都得写死。让大模型一次性完成“模糊描述 - 明确参数 - 建模代码”的过程实际上是把需求分析这个最耗时的环节自动化了。这句话是我做完整个项目后最大的体会text-to-cad 表面上是画图问题本质上是需求参数化问题。谁把参数抽得准、约束得死谁生成的模型就能用谁指望模型“脑补”尺寸谁就会得到一个无法加工的装饰品。2.3 OpenSCAD 为什么比 CadQuery、FreeCAD 更适合做第一版我第一版用的是 OpenSCAD原因有三个。第一OpenSCAD 是纯代码建模所有几何都表达为基本几何体的加减运算代码短、逻辑直白。大模型生成一段 OpenSCAD 代码出错了我可以直接看到是哪一行、哪个括号出了问题调试成本极低。第二OpenSCAD 有一个命令行工具openscad可以无界面地把.scad文件渲染成 STL。这意味着我可以完全脱离GUI在服务端跑一个“文本 - 模型文件”的批量管道一次处理几十个需求也不怕。第三OpenSCAD 的建模能力刚好覆盖机械设计里最常见的零件比如带孔的法兰盘、支架、轴套、外壳。对于雕花、曲面、复杂自由造型它确实不擅长但那也不是当前主流需求。CadQuery 和 FreeCAD Python API 我也试过。CadQuery 的优势是能直接输出 STEP 文件、支持真正的参数化特征但它的 API 层级更深大模型经常把selector写错或者把链式调用顺序搞颠倒FreeCAD 的问题是启动慢、API 版本混乱做原型验证有点重。结论是第一版先用 OpenSCAD 跑通链路后面等核心逻辑稳定了再换 CadQuery 做真正的工程级输出。这个后面会展开说。3. 从自然语言到参数提示词和结构化输出的设计3.1 分两步走先让模型“说人话”再“写代码”很多人在提示词里直接写“请帮我生成一个法兰盘的OpenSCAD代码”这样做模型确实会生成代码但它会背一个标准模板尺寸、孔数、倒角通通按最常见的方式处理。一旦你的描述里带了“四个孔均布在直径48的圆上”这种具体要求它就容易出问题。我在系统提示词里强制要求模型分两步思考但思考结果不直接暴露而是全部放在结构化输出里第一步把用户描述转成参数清单包括部件类型、主尺寸、孔数量、孔距、厚度、倒角、公差等。能明确的参数必须写死不能明确的参数必须标注为“Default”并在analysis字段里说明我用了什么默认值。第二步根据参数清单生成 OpenSCAD 代码。这样做的核心原因是把“需求理解”和“代码生成”拆开错误就更容易定位。如果尺寸错了问题一定在第一步如果尺寸对但模型渲染不出来问题一定在第二步。两个环节混在一起的时候大模型自己都不知道自己错在哪。3.2 单位、基准面、可加工性这三个预设最容易翻车单位问题是重灾区。大模型在训练数据里见过 inch、mm、cm 混用的场景你只说“长10宽5高2”它可能默认是厘米结果生成一个比期望值大十倍的东西。我在所有提示词里加了一条硬规则所有长度一律视为毫米除非用户明确写了单位。基准面也必须约定。我要求模型默认把零件底面放在 Z0 平面上Z轴向上。这样生成的模型放到3D打印切片软件或加工软件里方向是确定的不需要人工再翻转。可加工性则是更深一层的问题。模型很容易为了“看起来合理”而自作主张比如把 M8 螺栓画成一根光滑圆柱或者给一个倒角编一个 0.5mm 的圆角结果特征直接消失。我的处理方式是凡是用户没有指定的尺寸模型必须使用我提供的默认值表而不是凭记忆脑补凡是涉及到标准件螺纹、头部形状这类有国标可查的要素模型只生成简化示意不许自己发明细节。3.3 返回结构化JSON而不是直接生成文件一开始我让模型直接输出.scad代码后来发现自动处理非常难受。代码里混着分析文字、解释性注释、无法解析的符号程序没法稳定解析。后来我把输出格式统一成JSON{ analysis: 用户描述的是安装板包含4个通孔默认厚度5mm单位按毫米处理。, params: { width: 80, depth: 60, thickness: 5, hole_diameter: 6, hole_count: 4, hole_circle_diameter: 48 }, code: difference() { ... } }调用大模型接口的时候我在请求参数里加了response_format: {type: json_object}并且明确告诉模型“只输出JSON不要输出其他内容”。如果后端不支持response_format就在提示词里追加一句“你的回复必须是一个合法的JSON对象不要用markdown代码块包裹”。这一步是整个项目里投入产出比最高的一项改造。结构化的params不仅能用来生成模型还能用来做后续的版本对比和参数回填。4. 把流程拆成六步从描述到STL的最小流水线4.1 六步流水线的整体设计完整的 text-to-cad 管道我设计成六个步骤每步职责单一方便单独调试意图识别与约束解析读取用户描述判断这是“新建一个零件”还是“修改已有零件”识别出刚性约束必须满足的尺寸和弹性约束大约、差不多。参数化输出让模型输出一份结构化的参数清单全部转成数字和枚举拒绝模棱两可。代码生成根据参数清单生成 OpenSCAD 代码。参数清单里的每个数字都必须直接出现在代码里禁止模型引入“根据比例计算”的逻辑。沙箱执行调用openscad -o output.stl input.scad渲染模型。这个过程在独立进程里跑限制超时时间30秒避免某些循环把CPU占满。几何校验加载生成的STL检查体积是否大于0、网格是否有洞、包围盒尺寸是否落在合理范围。失败重试如果渲染失败或几何校验不通过把错误信息、代码片段、期望的校验指标一起回传给模型让它修正代码最多重试3次。这六步里步骤1到3是“翻译”步骤4到6是“验证”。很多只做了前半段的人会撞上一堵墙模型生成的代码能跑但跑出来的东西根本不对。所以后半段才是真正决定工具能不能用的关键。4.2 几何校验是整条流水线最不能偷懒的环节“cad软件建模质量评价”这个热搜我印象很深它背后反映的就是大家越来越发现自动生成的模型质量没人把关。我用的校验手段不复杂但非常有效。加载STL用的是trimesh库。第一步看volume如果体积为0或者小于一个极小阈值说明模型是空壳直接判失败第二步看is_winding_consistent网格朝向不一致的模型后续没法切片也没法加工第三步看包围盒尺寸假如用户说的是一个80mm宽的安装板结果生成一个8mm宽的说明单位或者参数传递出了问题必须重试。一开始我也觉得这一步是多余的直到有一次模型生成了一段合法代码所有括号都闭合渲染也不报错但打开模型一看只有一张飘在空中的薄片。没有体积校验这个错误会一直流到生产环节。4.3 把OpenSCAD的报错原样回传给模型比多轮对话更有效大模型多轮对话有个通病它会在对话历史里“脑补”用户想表达的意思甚至为了讨好用户而反复修改原本正确的代码。我在重试机制里做了限制不搞自由对话只把三项信息打包回传——OpenSCAD 的 stderr 原始报错生成的代码全文几何校验失败的具体指标比如“体积为0”或“包围盒宽度8期望80”让模型在保持原参数不变的前提下最小化修复代码。三轮回合还没通过我就把这次生成标记为失败记录下来供后续分析。这样做的效果是重试的成功率明显高于自由对话而且每次失败都留下了结构化日志后面可以当训练数据用。5. 三次实测记录AI画的法兰盘能直接拿去加工吗5.1 测试一带倒角的轴套第一个测试我选了一个很简单的东西描述是“内孔20外径40高度25两端倒角1×45°”。模型生成的 OpenSCAD 代码如下这里我做了简化difference() { cylinder(d 40, h 25); translate([0, 0, -0.01]) cylinder(d 20, h 25.02); } // 两端倒角用圆台做45°切角 translate([0, 0, 23]) cylinder(d1 42, d2 38, h 2);逻辑是对的用大圆台套小圆孔再用一个锥形台模拟倒角。渲染结果一眼看上去也没问题。但仔细看就暴露了两个工程问题第一倒角部分没有跟内孔求差倒角面跨过了内孔边缘不是真正的45°倒角第二零件没有公差标注哪怕几何正确加工师傅也不知道该按什么精度做。结论是作为“设计方案预览”完全可用作为“生产图纸”还差得远。5.2 测试二M8×40螺栓这组测试最能暴露问题。描述是“M8×40螺栓六角头”。第一次生成的代码偷懒到了极点画面就是cylinder(d 8, h 40); cylinder(d 13, h 6, $fn 6);一根光杆加一个六棱柱螺纹完全没表达。我要求它“必须表达螺纹轮廓”后第二次生成的代码用了一个绕着圆柱旋转的三角形截面去“扫”出螺旋体STL确实能看出牙型但牙距、牙型角都不是标准值而且头部的外接圆直径也不对。这个测试让我看清一件事标准件恰恰是 text-to-cad 最不擅长、但也最应该去做的方向。因为标准件参数有国标可查与其让模型背不如后面直接挂一个标准件数据库让模型只负责“取数组装”。5.3 测试三四孔法兰盘第三个测试我故意加了点陷阱。描述是“外径60mm内孔25mm厚度8mm四个直径6mm的通孔均布在直径48的螺栓圆上”。模型第一版生成的孔全部偏了原因是它把“直径48的螺栓圆”理解成了“半径48的螺栓圆”四个孔直接跑到零件外面去了。这个错误非常有代表性说明大模型对“直径/半径”这类一对反义词单纯靠语义理解还是会翻车。我把几何校验的包围盒检查范围收紧后这个问题被自动拦住了期望模型外径60结果四个孔的中心到圆心距离达到48比外径还大逻辑上不可能成立。校验模块把这个条件反馈给模型第二次它就老老实实把圆心距离改成了24。5.4 三次测试的结果汇总测试项是否渲染成功尺寸准确度能否直接加工主要问题带倒角轴套是基本准确否倒角未与内孔正确求差无公差M8×40螺栓是螺纹参数错误否螺纹牙型不标准、头部尺寸不标准四孔法兰盘是第一次错误二次修正否直径/半径理解错误靠校验拦截三轮测试跑下来我的判断是text-to-cad 目前能做“结构概念模型”不能做“生产级零件”。它的价值是把 80% 的重复性工作干掉剩下 20% 的工艺细节留给工程师。6. 正式用之前必须处理的四个细节6.1 单位与坐标系必须统一OpenSCAD 默认长度单位是毫米但大模型可能会写出cylinder(d0.5, h2)这种明显不符合用户口述尺寸的代码。我加了一个出厂设定所有长度必须符合用户描述未经用户允许不得自动缩放。还有一个隐藏很深的坑是坐标方向。模型生成的“法兰盘”可能默认 Z 轴是轴向也可能默认 Y 轴是轴向。如果后续要导入装配体光这个方向差异就够你折腾半天。我的办法是让 AI 生成一个orientation字段固定返回flat_on_z0表示底面在 Z0 平面解析代码时自动做一次rotate归一化。6.2 输出格式决定你能用到哪一步OpenSCAD 能导出 STL、3MF、OFF 等格式但导不出 STEP导不出原生CAD特征。这意味着你得到的是一块“实心网格”而不是一个可以编辑特征树、可以修改尺寸的参数化模型。如果你的目标只是3D打印一个手板STL完全够用。但如果你要把模型丢给供应商开模、加工、做装配干涉检查最后还得用 CadQuery 或 FreeCAD 重新建一遍带特征的模型。我目前的处理方式是分流内部验证用 STL需要交付到生产环境的需求先让 AI 生成 CadQuery 代码再用 OpenCASCADE 内核导出 STEP。这一步改造并不难关键是多一层后端转换。6.3 小心代码里的“幽灵参数”OpenSCAD 有一个非常坑人的特性未定义变量不会报错而是默认当成 0 处理。大模型有时会生成一个引用PI的地方写成PI3或者pi_valueOpenSCAD 不报错直接当成 0 带入计算结果圆角没了、孔径变成0了整个模型变成一个诡异的形状。我用两条防线来防这个问题。第一是渲染前先跑一遍openscad --check-parameters -c该选项会检查代码里的参数是否在 OpenSCAD 内置变量范围内第二是在几何校验阶段增加包围盒和体积的上下限任何超出预期十倍的特征直接拦截。6.4 防“幻觉几何”最有效的办法是给模型一个数据库而不是一句劝告我在提示词里写过无数遍“不要编造螺纹尺寸”“不要自行推断标准件参数”效果都一般。模型不是不听话而是它的训练数据里根本没有可靠的国标参数表它只能编。真正有效的兜底是RAG 标准件库。比如用户提到“M8螺栓”系统先向量检索标准件数据库把真实的头径、对边、长度范围、螺距全部查出来填入提示词让模型只负责把真实参数写成几何代码不负责记忆任何数字。这之后“幻觉几何”的问题基本消失。7. 最小可复现代码与下一步想做的事7.1 一个能跑起来的最小例子下面这个脚本是我项目的最小子集。它做三件事调用大模型拿到结构化JSON写临时.scad文件并用 OpenSCAD 渲染成 STL再用trimesh做基础几何校验。# text_to_cad_min_demo.py import json import os import subprocess import tempfile import requests import trimesh SYSTEM_PROMPT 你是机械制图助手。用户会给出零件描述你需要输出JSON对象格式如下 { analysis: 简要分析, params: {关键参数名: 数值}, code: 完整的OpenSCAD代码 } 规则 1. 所有长度单位一律视为毫米。 2. 如果用户没有指定尺寸使用合理的机械默认值并在analysis中说明。 3. 禁止编造标准件参数无法确定时使用简化外形并在analysis中注明。 4. 只输出JSON不要输出其他内容。 def generate_model(user_desc: str): resp requests.post( f{os.environ[LLM_BASE_URL]}/chat/completions, headers{Authorization: fBearer {os.environ[LLM_API_KEY]}}, json{ model: os.environ.get(LLM_MODEL, default-model), messages: [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_desc}, ], temperature: 0.2, response_format: {type: json_object}, }, timeout90, ) resp.raise_for_status() content resp.json()[choices][0][message][content] data json.loads(content) with tempfile.NamedTemporaryFile(suffix.scad, deleteFalse) as f: f.write(data[code].encode(utf-8)) scad_path f.name stl_path scad_path.replace(.scad, .stl) proc subprocess.run( [openscad, -o, stl_path, scad_path], capture_outputTrue, textTrue, timeout60, ) if proc.returncode ! 0: return {ok: False, error: proc.stderr, code: data[code]} mesh trimesh.load(stl_path) if mesh.volume 0 or not mesh.is_winding_consistent: return {ok: False, error: 几何校验失败, code: data[code]} return { ok: True, stl_path: stl_path, volume: mesh.volume, bounds: mesh.bounds.tolist(), code: data[code], } if __name__ __main__: result generate_model(外径60mm内孔25mm厚度8mm四个直径6mm通孔均布在直径48的螺纹圆上) print(json.dumps(result, ensure_asciiFalse, indent2))使用前需要安装依赖pip install requests trimesh另外要确保 OpenSCAD 的openscad命令在PATH里。Windows 用户装完 OpenSCAD 后把安装目录加进环境变量即可。如果你调的模型接口不支持response_format把这一行注释掉同时在SYSTEM_PROMPT里加一句“输出必须是合法JSON不要用markdown代码块包裹”。实测下来大部分兼容接口都能解析这种强约束输出。7.2 下一步用RAG把标准件库接进来现在系统还有一个明显的短板没有标准件记忆。我下一步会把常用的标准件参数螺栓、螺母、垫圈、轴承座、型材截面等整理成结构化文档用向量库做检索。用户在描述里提到“M8螺栓”系统自动检索标准参数并注入提示词。这个改造对 text-to-cad 的意义不在“让模型知道M8是8毫米”而在于“让模型不再自己编造牙距和对边距离”。标准件是机械设计里出错率最高的地方把这块稳住整个工具的工程可用度会上一个台阶。7.3 再往后从OpenSCAD换到CadQuery/OpenCASCADEOpenSCAD 作为第一版完全合格但它输出不了STEP撑不起参数化特征。等流程稳定后我会把后端建模语言换成 CadQuery同时保留 OpenSCAD 作为“快速预览”通道。CadQuery 的典型代码长这样下面是一个法兰盘的简化示例import cadquery as cq result ( cq.Workplane(XY) .circle(60 / 2) .extrude(8) .faces(Z) .hole(25) .faces(Z) .workplane() .rect(48, 48, forConstructionTrue) .vertices() .hole(6) ) cq.exporters.export(result, flange.step)这套接口生成的是带特征的参数化模型导出STEP后可以直接进主流CAD软件。唯一的问题是 CadQuery 的学习曲线比 OpenSCAD 陡大模型生成代码的准确率目前不如 OpenSCAD。我的想法是做一个“翻译层”先用 OpenSCAD 把几何验证跑通再把同一套参数翻译成 CadQuery 代码两步都成功才输出最终文件。7.4 几点个人体会这个项目做下来我最深的感受是text-to-cad 最值钱的部分不是“自动建模”而是“倒逼你把需求说清楚”。以前工程师口头描述一个零件CAD操作员听漏一个尺寸要返工半天现在模型会明确告诉你哪些参数缺失、哪些参数用了默认值需求里的模糊地带被摊在桌面上。如果你也打算做类似的东西我建议不要一上来追求全自动。先搞一个“AI出初稿、工程师在OpenSCAD里改参数”的半自动流程把流水线和校验跑稳再逐步增加标准件库、STEP导出、装配体支持。这个顺序能让你少走很多弯路。