资讯动态

Text-to-CAD技术拆解:从自然语言到可编辑CAD模型的实现路径

发布时间:2026/10/27 3:53:33 来源:尧图企业网站定制
做CAD这行十几年我第一次在终端敲完一段描述直接生成完整零件图的时候后背是发麻的。text-to-cad——也就是把自然语言描述直接转成CAD模型——听起来像概念Demo但它已经能进真实工作流了。更关键的是它的技术路线选得很有意思不是让AI生成网格而是让AI生成CAD代码。这篇文章我打算把text-to-cad从原理到落地讲透包括LLM怎么把一句话拆成参数化特征、为什么代码是当前最优的中间表示、怎么搭一个能用的最小系统再把我实操中踩过的坑全部列出来。适合正在研究AI辅助设计的工程师也适合想做自动化建模、刚入坑的独立开发者参考。1. Text-to-CAD 是什么解决什么问题1.1 传统CAD建模的痛点传统参数化建模的学习成本有多高经历过的人都知道。拿SolidWorks或者NX来说新手光是理解草图-约束-特征这套逻辑就需要几个星期而真正的高手能快速建出复杂曲面靠的是大量肌肉记忆和快捷键操作。但这里有一个长期被忽略的效率黑洞工程师花在告诉软件怎么画上的时间其实远多于想清楚要什么的时间。比如要建一个带六个均匀分布圆孔的法兰盘手工操作至少需要十几步新建草图、画圆、标注直径、退出草图、拉伸、再草图画孔、圆周阵列、切除。每一步软件都在等一个明确指令而这些指令本质上是机械的、可预测的。更麻烦的是重复劳动。一个标准件库里的法兰、支架、轴承座每种型号可能就差几个关键尺寸但每次都要重新建一遍模型。传统做法是做成参数化模板由工程师手动关联尺寸表。可一旦模型复杂度上来模板本身的维护成本也跟着暴涨。改一个上游参数下游一堆特征报错是家常便饭。这种场景下真正稀缺的不是CAD操作技巧而是把设计意图快速转成可编辑模型的能力。text-to-cad瞄准的恰恰是这个转译过程。1.2 Text-to-CAD 的破局思路text-to-cad字面意思就是文本到CAD。用户输入一句自然语言描述比如外径100、内径50、厚度10毫米的法兰盘均布六个直径8的圆孔系统自动生成对应CAD模型。输出的不是一个不可编辑的网格文件而是一套完整的参数化建模脚本用户还能继续改参数、调尺寸跟传统CAD里的特征树完全兼容。这里要说清楚一个容易混淆的点text-to-cad和AI生成图片不是一回事。生成图片是把文字变成像素生成CAD是把文字变成精确的几何约束和布尔运算关系。两者的数学基础完全不同——像素没有精度问题而CAD从第一个毫米开始就要求可制造、可装配、可仿真。我搭建的这套工作流其实很简单四层链路文本输入、大模型理解、生成程序化CAD代码、执行代码得到模型。用户如果对结果不满意可以直接说孔的直径改成9系统只修改参数不需要整体重新生成。这种交互方式把CAD建模从逐特征手绘推进到了对话式迭代。2. 核心技术原理拆解从自然语言到可编辑几何2.1 LLM 的真正角色文本到代码的翻译官在text-to-cad系统里大语言模型不直接画模型它的角色是翻译官把模糊的自然语言转换成精确的结构化代码。这个定位极其关键。文本描述天然是模糊的。大一点的孔是多大圆润的把手曲率多少这些语义需要被翻译成确定的数值和操作序列。LLM擅长做这种映射——它见过海量的CAD教程、技术文档和建模示例知道法兰盘意味着圆柱体加环形阵列孔圆角对应fillet操作布尔差集可以用什么API实现。我自己的实践验证了一个道理LLM生成CAD代码的成功率很大程度上取决于你是否把它限制在一个足够小、足够规范的语言子集里。让模型直接生成CadQuery代码它经常自由发挥但如果告诉它只允许使用这十个函数并给一段标准示例它就能稳定输出。这里有三个基本的架构选择逻辑描述 - 参数化代码LLM把六个孔、圆周分布翻译成循环加旋转副本这是人类可读、可验证的。描述 - 直接网格跳过代码一步到位生成三角网格。听起来直接但结果不可编辑精度无法保证没法进入后续装配或数控加工流程。描述 - 点云/体素适合三维重建任务但生成的曲面质量通常不够工程标准。所以当前text-to-cad的主流路线是LLM 程序化CAD内核的组合而不是LLM 三维生成对抗网络。2.2 为什么选择程序化代码作为中间表示如果只看表面文本直接生成网格似乎更酷。但实际工程里CAD模型和渲染模型的地位完全不同。CAD模型要进装配、进工程图、进有限元分析每一步都要求模型有清晰的拓扑结构、可复用的特征树和精确的边界表示。网格模型在这些环节几乎寸步难行。程序化代码的优势我用一个OpenSCAD的例子来解释。下面这段代码生成一个带六个孔的法兰盘module flange(outer100, inner50, thickness10, hole_d8, hole_count6) { difference() { cylinder(hthickness, router/2, $fn120); translate([0, 0, -1]) cylinder(hthickness2, rinner/2, $fn120); for (i [0 : 360/hole_count : 359]) { rotate([0, 0, i]) translate([outer/2 - 10, 0, -1]) cylinder(hthickness2, dhole_d, $fn60); } } } flange();这段代码的每一行都对应一个CAD特征圆柱体、平移、差集、阵列。修改任何参数——把hole_count改成8或者把outer改成120——模型自动重建所有特征保持一致。这正是CAD参数化设计的核心思想而代码天然支持参数化。相比之下如果LLM直接生成三角网格且不说顶点数可能高达几十万个单单是把直径从8改成9就意味着整个网格要重新生成而且没法保持圆孔和法兰之间的布尔关系。所以说代码是最适合做可复现设计意图的中间表示。还有一个工程层面的理由代码可以做静态检查。语法错误、变量未定义、函数签名不匹配这些在编译阶段就能暴露出来反馈给模型去修正。网格生成则是一个黑箱错了你几乎不知道错在哪一步。2.3 主流程序化CAD后端对比与选型逻辑选后端工具就是给LLM一个受限操作空间。空间越小模型越容易学好。我对比过三个主流方案工具语言风格布尔/CSG支持参数化能力主要导出格式适合场景OpenSCAD声明式、函数式强CSG是核心变量、模块、循环STL、OFF、AMF部分STEPMVP原型、快速验证、3D打印模型CadQueryPython强基于OCCT内核Python变量、参数化对象STEP、STL、DXF、SVG需要进入装配/制造流程的工程零件FreeCAD脚本Python强参数对象、表达式全格式与FreeCAD文档深度协同我的建议非常直白如果你只是做技术验证首选OpenSCAD。它语法非常封闭只有基本形状、变换和布尔运算模型非常容易学会。我在测试中让LLM生成OpenSCAD代码的成功率比生成CadQuery代码高出大约20个百分点主要原因就是CadQuery的API太庞杂模型经常记错某个链式调用的方法名。但OpenSCAD有个硬伤对STEP格式支持不好而STEP才是工业装配和CAM的标准格式。所以一旦系统要往真实制造方向走CadQuery是更稳妥的选择。它可以导出完整STEP文件直接进加工流程。代价是提示词和校验逻辑要复杂不少。3. 手把手搭建一个text-to-cad最小可用系统3.1 四模块架构与整体数据流一个能跑起来的text-to-cad最小系统只需要四个模块。我把它当作后端服务来设计这样方便接API复用。# text_to_cad_service.py from fastapi import FastAPI from pydantic import BaseModel import cadquery as cq app FastAPI() class CadRequest(BaseModel): description: str def llm_generate_code(description: str) - str: # 调用LLM返回CAD代码字符串 pass def execute_cad_code(code: str) - cq.Workplane: # 沙箱执行返回cadquery对象 pass app.post(/generate) def generate(request: CadRequest): code llm_generate_code(request.description) model execute_cad_code(code) return {code: code, model_id: id(model)}四个模块分别是提示词构建器把用户描述包装成结构化提示词。模型调用层接入任意LLM统一返回代码文本。代码执行层独立沙箱内执行代码得到模型对象。结果校验层检查模型合法性生成预览图和导出文件。数据流是用户描述 - 提示词构建 - LLM生成代码 - 沙箱执行 - 校验 - 返回结果。上一环节的输出就是下一环节的输入逻辑非常清晰。我在生产环境里还把每个环节的日志都保留下来用于后续分析模型失败的原因。3.2 提示词模板设计成功率从30%到70%的关键提示词是text-to-cad系统里最值得花时间的部分。同样的模型提示词写得好不好生成代码可执行率可能相差一倍。我调试出来的一个稳定模板如下你是参数化CAD编程专家。请把用户的自然语言描述转换成{backend}代码。 约束条件 1. 单位统一为毫米默认Z轴朝上模型放在原点附近。 2. 所有关键尺寸使用有意义的变量名定义禁止魔法数字。 3. 代码末尾必须把最终模型赋值给变量result。 4. 只允许使用{backend}内置函数和标准库禁止导入其他模块。 5. 不要生成网格数据不要调用渲染命令。 标准示例 用户描述直径30、高10的圆柱体顶部倒角2 {example_code} 用户描述{user_prompt}这个模板有四个设计要点缺一不可限定后端。如果不限定LLM经常把CadQuery、OpenSCAD、Blender、Three.js的API混在一起写。我见过一次代码开头是CadQuery语法中间突然出现Three.js的BoxGeometry最后以OpenSCAD的union()收尾执行完全不可能成功。明确变量约定。要求用变量而不是魔法数直接决定了后续参数化修改能不能做。模型生成r25和直接写25代表的是可编辑参数和写死的数两种完全不同的设计意图。约定输出变量名。系统能准确提取模型对象的关键是最后一行必须有一个统一的result变量。给出标准示例。few-shot比任何抽象描述都有效。模型看到一段规范的CadQuery代码模仿出来的风格就不会跑偏。我做过统计用这套模板之前LLM生成CadQuery代码的首次可执行率只有30%左右带上约束和示例后能到70%。剩余30%要用校验回填来救这个在下面展开。3.3 代码生成、校验与错误回填闭环校验是text-to-cad系统中决定成败的一环。我采用三层校验逐级上报错误第一层是静态语法检查。CadQuery代码本质是Python所以可以直接用Python的ast模块做解析语法错误立刻能被发现。OpenSCAD更简单自带命令行解析器openscad -o /dev/null file.scad就能检查语法而不输出文件。第二层是执行期错误捕获。把编译或执行过程中的报错信息直接反馈给LLM。关键是错误信息要整理成建议修正的语气而不是直接抛原文。比如执行时遇到TypeError: NoneType object is not callable我会把它包装成第17行调用了None类型请检查是否有前置操作未完成比如未选择面就调用extrude。第三层是几何合理性校验。模型生成了不代表正确。我每次都检查三件事有没有实体result.val().isValid()返回False说明几何可能破损。体积是否合理和尺寸量级匹配不出现负数或异常巨大。包围盒是否符合预期比如描述说直径100包围盒却是300说明模型可能多生成了一个超大特征。这一步我是这么实现的import cadquery as cq def validate_model(result: cq.Workplane, description: str) - list[str]: issues [] solid result.val() if not solid.isValid(): issues.append(模型无效几何体错误) volume solid.Volume() if volume 0: issues.append(模型无效体积非正数) bbox solid.BoundingBox() # 粗略检查最大边长不能超过1000mm max_dim max(bbox.xlen, bbox.ylen, bbox.zlen) if max_dim 1000: issues.append(f尺寸异常最大边长{max_dim}mm远超常见零件尺寸) return issues错误回填闭环的实际操作是校验发现错误就把错误信息和修正建议拼接成新消息追加到对话上下文里要求模型重新生成。这个编译错误回填技巧我实测能让累计成功率从70%提升到接近90%。整个流程循环最多五轮如果五轮仍然失败就直接返回失败状态不再浪费算力。3.4 渲染、导出与沙箱执行细节模型通过校验之后就要做两件事生成预览图导出标准格式文件。这里有不少细节坑。CadQuery导出STEP格式的标准做法cq.exporters.export(result, output.step)导出STLcq.exporters.export(result, output.stl)但预览图就不一样了。CadQuery的SVG导出默认只输出线框三视图的观感还行但用户想看三维效果就有困难。我推荐的方案是用cq.exporters.export配合projectionDir参数导出带阴影的PNG图cq.exporters.export( result, preview.png, opt{ projectionDir: (1, 1, 1), width: 800, height: 600, showAxes: False, }, )注意CadQuery的PNG导出依赖matplotlib和numpy-stl等库环境里没装会直接报错。我经常踩这个坑所以环境准备阶段就会统一安装。沙箱执行是另一个不能省的部分。LLM生成的代码不可控它可能生成import shutil; shutil.rmtree(/)也可能生成无限循环占用CPU。我的生产方案是Docker容器化基础镜像选python:3.11-slim安装CadQuery指定版本。每次请求创建全新容器执行期间限制内存1~2GBCPU配额0.5个核心。禁止容器访问宿主网络文件写入限定在/workspace卷。这样即便模型生成了恶意代码也只在容器内部生效。OpenSCAD虽然不太可能执行系统命令但它如果生成一个巨大规模的循环内存也会爆掉同样需要容器保护。4. 实操中的高频问题与排查实录4.1 三大类常见错误与对应解法我把实操中遇到的问题归纳为三大类每一类都有比较清晰的排查思路。第一类语法混合类。模型生成了非目标语言的语法。CadQuery代码里混入MATLAB风格的括号、OpenSCAD的rotate块、甚至JavaScript的const声明。解决办法是强化提示词在模板里加入一行请仔细检查语法确保代码可以直接在Python 3.9环境中运行。如果还不行就在后处理阶段做一个简单过滤把明显不符合Python语法特征的行剔除。第二类坐标系混乱类。模型把Z轴朝下建模或者把模型放在离原点很远的位置导致后续装配对不上。这类问题通常在几何校验阶段发现特征是包围盒中心严重偏离原点。我的处理是二次校正检测到包围盒中心点不在原点附近时自动加一个平移变换把模型拉回原点。这个这在工程上是一个很实用的后处理。第三类布尔运算失败类。这大概是我遇到最多的失败类型。典型报错是Failed to compute boolean operation或BRep_API: command not done。最常见的原因是布尔操作的两个实体存在共面或极薄间隙。OCCT内核解决这类问题很挑剔。处理方法是在参与差集或并集的对象之间加入微小偏移比如0.001mm人为打破共面状态。还有一个比较隐蔽的原因布尔操作的顺序。并集再差集和差集再并集结果可能完全不同LLM经常搞错优先级需要检查代码里difference()内嵌套的实体列表顺序。4.2 几何合理性校验别让AI生成不可能零件执行成功、模型有效不代表是一个能用的零件。text-to-cad系统最常见的翻车是生成几何上存在但在物理上不可能的模型。举一个例子描述壁厚1毫米直径200毫米的圆盘。LLM生成一个薄壁圆盘几何有效但实际3D打印或CNC加工时1mm的壁厚对应200mm直径刚度和精度根本达不到。这类问题LLM自己是不知道的需要系统层面的领域知识介入。我在校验层加入了几个制造约束规则最小壁厚检查所有薄壁特征不能小于预设值针对3D打印我通常设0.8~1.2mm。悬垂角度检查模型中的悬垂角度过大时提示增加支撑。装配间隙检查如果描述中有配合关系比如轴和孔配合系统要检查直径差是否符合工程公差。这些规则在执行代码后通过分析模型的BRep结构来实现。CadQuery底层是OpenCCCT可以用model.val().Faces()遍历所有面计算面法向和最小距离。实现上有点复杂但加上之后系统输出的结果实用性提升非常明显。4.3 基于参数变更的增量迭代设计text-to-cad真正好用的地方不在于一次生成完美模型而在于能跟用户对话式迭代。这个迭代机制如果设计成整段重新生成体验会非常差因为每次生成都可能跑偏。我的做法是让系统维护一个参数状态表。用户第一次说外径100的法兰系统生成代码时会把outer100记录下来。用户接着要求改成120系统不会重新生成整段代码而是定位到参数变量那一行直接做字符串替换然后重新执行代码。def update_parameter(code: str, param: str, new_value: float) - str: pattern rf{param}\s*\s*[0-9.] return re.sub(pattern, f{param} {new_value}, code, count1)这个简单方案在参数值变更场景下能覆盖80%的需求。复杂一点的比如孔的排列从圆周改为矩形阵列就涉及结构变更不能简单替换参数需要重新生成。此时我会把上一次成功的代码作为上下文传给LLM让模型在已有代码基础上修改而不是从零生成。实测下来带着旧代码做增量修改成功率比重新生成高出30%以上而且能保持整体风格一致。5. 模型、工具与Benchmark选型参考5.1 LLM选型通用大模型 vs 专用模型做text-to-cad项目第一个要选的就是LLM。市面上可选的方向大概分两类。通用强模型比如GPT-4o、Claude 3.5/4系列。它们对复杂指令的理解能力强生成的代码质量高但调用成本高。我的建议是开发阶段用这类模型做基准测试验证提示词模板的设计思路是否正确。开源模型比如Qwen2.5-Coder、DeepSeek-Coder系列。它们可以私有化部署单次调用成本几乎为零适合批量标注和微调。缺点是代码生成稳定性弱一些需要更完善的校验回填机制。实测在CadQuery任务上表现最好的开源模型大约能达到商用模型90%的水平差距主要集中在复杂布尔运算和嵌套特征的处理上。还有一类是针对text-to-cad任务微调的专用模型比如Text2CAD数据集上训练出来的模型。它们在小范围测试集上表现惊艳但泛化能力明显不足换个不常见的零件描述就容易失败。我的看法是现阶段做产品原型不用纠结专用模型通用模型加提示词约束已经完全够用。5.2 后端工具选型OpenSCAD与CadQuery对比这个选择题本质是要开发效率还是要工业标准。OpenSCAD适合做MVP。它的语言极其简单LLM学习成本低语法错误少渲染快。还有现成命令行工具可以批量渲染STL预览图。但它的STEP导出支持不完整而STEP文件是工业界真正的硬通货。你的系统如果只在3D打印场景里用OpenSCAD完全够了如果要对接SolidWorks、NX、CATIA这些CAD软件必须选择CadQuery或FreeCAD。CadQuery的优势是基于OCCTOpenCascade Technology内核这是工业级几何内核。它导出的STEP文件能被主流CAD系统无缝读取布尔运算稳定支持复杂曲面。代价是API层级深链式调用多LLM经常调用错误方法名。缓解方法是在提示词里给一个完整的最小示例不要只给函数签名要给完整的代码体。5.3 数据集与评测方法做text-to-cad系统没有评测不叫工程。目前我主要用的两个公开数据集Text2CAD包含大量文本描述和对应CAD模型的配对数据。DeepCAD包含从在线CAD社区抓取的、带参数化特征的模型序列数据。评测的时候我建议分三个难度级别简单描述中包含明确尺寸和基本形状比如半径10的球体。中等描述涉及特征组合比如带六个孔的环形支架。困难描述是功能性的、没有精确尺寸比如手机支架能让手机横放并有充电线出口。我自己用下来简单级别一次性成功率已经能做到90%以上中等在70%~80%之间困难描述能做到50%就已经非常不错了。功能性描述才是text-to-cad的未来方向但现在的模型对功能性的理解还很浅。6. 扩展方向与个人体会6.1 从单零件迈向装配体级生成现阶段的text-to-cad基本只能生成单个零件这是技术上相对容易实现的层级。而工程实际里装配体才是更常见的需求。一个装配体模型需要定义零件之间的配合关系、坐标系对齐、命名规范甚至包括运动自由度。描述起来复杂生成起来更是几何约束的噩梦。如果能把装配体的文本生成做好比如夹具底座带四个M8沉头孔与夹爪滑轨配合这类需求会非常实用但难度比单零件高一个数量级。6.2 从模型生成走向制造链路闭环生成CAD模型只是第一步。真正让text-to-cad发挥价值的是把生成结果直接接入下游制造链路。最常见的是3D打印text-to-cad生成STL后自动送入切片软件生成G-code。更进一步的是CAM数控加工生成STEP后自动规划刀具路径。这两个方向的门槛不在几何建模而在工艺参数的匹配——同样的模型用FDM打印和用CNC加工需要的结构调整完全不同。如果系统能提前感知制造工艺并在生成模型时就融入制造约束那才是text-to-cad真正走向产品化的时刻。6.3 我踩过坑之后的理解最后分享一点实操体会。text-to-cad最值得投入的方向不是让AI独立完成复杂设计而是让AI承担重复、机械的特征定义工作把工程师从告诉软件怎么画的琐碎操作里解放出来。我现在把text-to-cad接入了内部标准件库需求描述进初版模型出再手工调整公差配合整体设计效率大概提升了3倍。踩过几次坑之后我的结论是不要追求100%自动生成把目标设定在从一句话到第一版草稿的加速器后面精细调整仍然需要工程师的判断。text-to-cad不是要替代设计师而是要替代那些枯燥的鼠标点击——沿着这个思路做项目就不会跑偏。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑