资讯动态

Text-to-CAD从原理到实战:LLM驱动CadQuery建模的八个坑

发布时间:2026/10/27 3:52:07 来源:尧图企业网站定制
看到text-to-cad这个方向又冒出来了我其实挺感慨的。作为从传统结构设计转到数字孪生和自动化建模的从业者我很清楚大家期待的是“我说一句话CAD模型自动出来”的魔法时刻。但真正碰过这条线的人都知道地上全是碎玻璃——自然语言天生模糊CAD天生精确这两者之间的鸿沟比很多人想象得要深得多。先说清楚这篇文章想聊什么我会从原理层面拆解text-to-cad为什么难对比目前主流的三条技术路线然后给你一个我亲测能跑的LLM驱动CadQuery小流程最后把我在真实项目里踩过的八个坑原原本本摆出来。适合想入门这个方向、或者正准备在公司内部做设计自动化预研的工程师和技术负责人看。如果你是第一次听说这个概念也不用担心我会把底层原理和实操代码都拆开讲。1. text-to-cad的本质矛盾一句大白话半本设计手册很多人第一次接触text-to-cad以为它就是“AI版的Midjourney”输入一句话输出一张模型图。这是最大的误解。CAD在工程语境下从来不是“一张图”而是一整套精确、可编辑、可制造、可追溯的几何定义。1.1 一句“帮我画个带孔的板”到底藏着多少隐含信息我先举一个极简单的例子。你说“生成一个直径50的圆盘中心开直径20的孔厚度8边缘倒角1”。听起来信息量挺足吧但落到CAD内核里问题立刻就来了直径50的单位是什么毫米、英寸、还是别的LLM如果默认毫米而下游装配体是英寸这个件直接报废。倒角是圆角还是45度斜角在CAD术语里“倒角”和“圆角”是两个完全不同的特征特征树结构完全不同。孔是通孔还是盲孔要求沉头吗孔和圆盘是同轴心吗这个模型的坐标系原点在哪基准面朝向哪边将来装配时以哪个面定位厚度8是从圆盘顶面向下拉伸8还是从底面向上拉伸8这决定了草图的基准平面选择。这些还只是“一个盘”的维度。真实工况里一句“做个法兰要能跟DN100的管道对接”涉及的是标准件参数、密封面形式、螺栓孔数量和分布圆直径——这些东西不在Prompt里写清楚模型就只能靠猜。而靠猜的CAD工程师是绝对不敢用的。这里我要点出一个核心道理自然语言是高度上下文依赖的而CAD是绝对坐标化的。一个词在不同行业、不同场景下含义完全不同但CAD模型只有一个确定答案。所以text-to-cad的第一性问题不是模型不够聪明而是“意图到约束”的翻译在本质上就是信息不完备的。1.2 为什么“看着像”没用必须“特征可编辑”再往深挖一层。即便是扩散模型能生成非常像样的渲染图也不能直接当CAD用。因为工程上需要的是可参数化驱动的实体模型。我见过不少入门者把“生成个像模像样的STL网格”和“完成一个CAD建模”混为一谈。渲染图/网格模型只有三角面片没有几何拓扑没有特征历史无法改参数重新生成。参数化CAD模型由草图、拉伸、切除、倒角、阵列这些“特征”组成每个特征都带参数改一个数字整个模型能联动更新。用生活类比讲网格模型就像一张拍好的照片姿势、光线都定死了想换个角度重拍做不到。参数化CAD模型则像一套乐高积木的搭建说明书换一块积木整体结构跟着调整。text-to-cad的真正价值恰恰在于后者——让AI帮你写“搭建说明书”而不是帮你按一下快门。所以我判断一个text-to-cad系统好不好用第一眼会看它的输出是不是参数化特征序列。如果最终给不出特征树那它充其量只是“文本转图片”离“文本转CAD”还有十万八千里。2. 三条技术路线怎么选代码生成、端到端生成、还是混合方案我复盘过市面上大部分自称text-to-cad的项目本质上没有跳出三条路线。搞清楚这三条路线的边界你再看别人的Demo就不会被花哨的展示带偏。2.1 路线ALLM直接写程序化建模代码这是目前最“务实”的路线。思路很简单用大语言模型把自然语言翻译成一段程序化建模脚本比如OpenSCAD脚本、CadQuery代码、FreeCAD的Python API调用然后由脚本执行生成模型。这条路线的好处是输出本身可编辑、可参数化因为脚本里的尺寸和特征都是显式的。有语法检查、有报错机制模型“胡说八道”时至少能被编译器拦住一部分。不需要大规模成对训练数据靠LLM已有的代码能力就能起步。缺点是LLM生成的代码经常“优雅地出错”——语法对了几何不对比如拉伸方向反了、布尔运算选错了体。复杂装配体和多零件联动代码长度一上来错误率急剧上升。但我要说句公道话**它是三条路里唯一现在就能在真实项目里跑起来的。**我后面第3章要演示的CadQuery方案就是这条路线。2.2 路线B端到端生成网络文本→隐式场/网格/点云这是学术界最爱的方向也是各种论文Demo的常客。思路是训练一个条件生成模型输入文本编码输出体素、点云或者隐式场函数再通过Marching Cubes之类的算法提取网格。这条路线的优势是“生成自然”几何不用通过代码描述模型能直接变出形状。去年我有段时间在调研这类方法确实有一些结果让人觉得惊艳特别是某种语义约束下的小物件生成。但问题也非常明确输出网格几乎无法参数化编辑工程师拿到一个三角形网格改不了圆角半径等于废物。泛化能力差。训练集里如果有一万个“轴套”样本模型对轴套就能生成得不错换一个“异形支架”立刻崩塌。对工业件的“尖锐特征”和“精确配合面”处理很差。神经网络擅长糊形状不擅长保证“这个面和那个面严格平行、间距正好5mm”这类硬约束。我的结论是端到端路线更适合做概念设计阶段的“灵感生成器”离工程落地还很远。你在评估它的时候不要看Demo渲染图直接问一句“输出能进CAD内核二次编辑吗”大多数就露馅了。2.3 路线C混合方案检索编辑生成第三条路是工程上更讨巧的做法不从零生成而是从已有的标准件库或模型库里检索最接近的模型然后用LLM或者目标驱动算法去改参数、改特征。比如用户说“需要一个比BW-102这个法兰直径大10mm的版本”系统先去零件库里搜到BW-102再定位到其直径参数执行加10mm的操作附带检查螺栓孔是否要跟着等比放大。这条路的逻辑很朴素却很管用尤其适合企业内部的标准化零件库场景。缺点是需要先有高质量模型库和参数化模板前期整理成本高。但一旦跑通了稳定性远远优于前两条路。我把三条路线的核心对比放在一起方便你按自己的场景挑路线输出形式可编辑性训练数据需求泛化能力落地难度LLM写代码参数化脚本强中依赖LLM基座能力中低端到端生成网格/点云/体素弱大需成对文本-模型数据低高检索编辑已有模型改参数强小依赖模型库质量中低中如果你现在正打算在公司内部立项我的建议非常直接短期走C中长期走AB用于预研和概念验证就好。3. 直接撸一个能跑的Demo用LLM驱动CadQuery生成参数化模型理论讲再多不如跑通一个最小闭环。下面是我在本地验证过的流程整体链路是自然语言 → LLM → CadQuery代码 → STEP/STL模型。所有代码基于Python环境依赖很简单。3.1 为什么我选CadQuery而不是OpenSCAD我知道很多人一上来就选OpenSCAD因为它语法最简单。但我个人更偏好在实际项目里用CadQuery理由有三CadQuery基于Python可以嵌入现有自动化流程而不像OpenSCAD是个独立DSL。CadQuery背后是OpenCascade内核生成的实体模型能直接导出STEP下游CAM、仿真软件通吃。它的语法更贴近“特征建模”思维比如workplane、hole()、extrude()LLM理解起来比纯CSG运算更自然。你可以理解为OpenSCAD像是给3D打印爱好者准备的拼积木CadQuery则是给工程师准备的、能在生产链路里干活的那套工具。安装环境非常快pip install cadquery如果你要用后面的LLM调用再补一个OpenAI SDK或者你常用的国产模型SDKpip install openai我下面示例默认你用的是可兼容的API接口实际Key和Endpoint改成你自己的就行。3.2 Prompt工程设计把话说死别给模型自由发挥的空间我踩过的最大的坑就是让LLM“自由地”写CadQuery代码。它会在代码里加注释、加print调试、甚至写一些CadQuery根本不存在的函数。所以我把系统提示词设计得非常“死”你是一个CadQuery代码生成器。 用户会输入自然语言描述的机械零件需求。 你需要输出纯Python代码使用cadquery库构建模型。 要求 1. 只输出代码不要输出任何解释、注释或Markdown标记。 2. 代码必须可以被直接exec执行。 3. 默认单位是毫米。 4. 所有关键尺寸都要定义为变量放到代码最顶部。 5. 模型最终赋值给名为result的CadQuery.Workplane对象。 6. 如果需求中有不确定的参数使用符合工程常识的默认值。 7. 禁止使用未导入的库。这几条每一条都是有原因的。第4条是我特别强调的因为一旦尺寸写成魔法数字后面参数化驱动就无从谈起。第5条确保我拿到代码后能统一执行逻辑。第6条解决的是自然语言信息不完备的问题与其让模型卡死不如让它按工程默认习惯补全。3.3 核心执行代码子进程隔离别污染主环境然后是我调用LLM并执行代码的Python脚本。我特别强调一点**执行LLM生成的代码绝对不要直接跑在主进程里。**因为你不知道它会给出什么鬼东西——可能死循环可能创建一堆临时文件万一它调用了os.remove你哭都来不及。子进程隔离是底线。import os import subprocess import tempfile from openai import OpenAI client OpenAI(api_keyyour-key, base_urlyour-endpoint) system_prompt ...以上那段Prompt... def generate_cad(user_desc: str) - str: resp client.chat.completions.create( modeldeepseek-chat, # 换成你实际可用的模型ID messages[ {role: system, content: system_prompt}, {role: user, content: user_desc}, ], temperature0.1, # 尽量低几何代码容不得随机性 ) return resp.choices[0].message.content def execute_cad_code(code: str) - str: # 在临时目录里用子进程执行输出STEP文件路径 with tempfile.TemporaryDirectory() as tmpdir: script_path os.path.join(tmpdir, gen.py) with open(script_path, w, encodingutf-8) as f: f.write(code) result subprocess.run( [python, script_path], cwdtmpdir, capture_outputTrue, textTrue, timeout120, ) return result.stdout, result.stderr, tmpdir这里有个容易被忽略的细节timeout120必须写。LLM有概率生成一个带有巨大循环的代码或者执行了一个非常复杂的布尔运算导致内核长时间无响应。一个超时保护能省掉你大量重启Jupyter Kernel的时间。3.4 跑一个真实例子矩形法兰带四个通孔接下来我们试试真实的链路。输入描述“生成一个矩形法兰外形100mm乘80mm厚度10mm四角各有一个直径8mm的通孔孔中心距边缘10mm中心有一个直径30mm的圆孔。”我让LLM生成的CadQuery代码大致是这个样子这是正常输出的形态不是唯一解import cadquery as cq # 参数定义 width 100 height 80 thickness 10 bolt_hole_d 8 bolt_center_offset 10 center_hole_d 30 # 建立矩形板 result ( cq.Workplane(XY) .rect(width, height) .extrude(thickness) .faces(Z) .workplane() .rect(width - 2 * bolt_center_offset, height - 2 * bolt_center_offset) .vertices() .hole(bolt_hole_d) .faces(Z) .workplane() .center(0, 0) .hole(center_hole_d) )这段代码我解释一下执行逻辑先画矩形、拉伸得到板体然后在上表面建立一个内缩的矩形取其四个顶点钻孔这样四个螺栓孔的位置就严格对齐了最后在中心打大孔。整个过程全部是参数驱动的改任何一个变量模型自动更新。你把结果导出为STEPcq.exporters.export(result, flange.step)再用CadQuery自带的cq.exporters的SVG预览或者直接丢进FreeCAD看一眼就能验证几何无误。我第一次跑通这个链路的时候说实话挺兴奋的。但随后连续一周的测试让我从兴奋迅速变回冷静因为**Demo能跑和管线能用的距离比你想象的远得多。**下面这两章就是我从“能跑”走向“能用”时撞上的墙。4. 过了Demo之后数据和评估才是真正的分水岭如果你只满足于“LLM偶尔能生成一个对的法兰”那第3章已经够用了。但如果你想衡量一个text-to-cad系统到底行不行或者为了发论文、做产品化评估就绕不开数据和评估指标。这两件事是区分真研究和刷Demo的分水岭。4.1 训练与评估数据先搞清楚这些数据集是干嘛的先说学术界最常见的几个数据集避免你在开会时张冠李戴Text2CAD数据集这是相对较新的一个专门提供自然语言指令到CAD建模序列的配对数据基于AutoCAD的Dynamo或CadQuery序列标注。它研究的正是“自然语言到程序化建模代码”的翻译。Fusion 360 Gallery包含了大量带设计历史树的真实机械零件模型树结构可以导出重建序列是训练“从数据到特征序列”的优质来源但原始数据里文本描述较少。ABC DatasetCAD模型几何数据的大型集合主要用于几何深度学习比如点云补全和隐式场学习但它不做语言配对。ShapeNet这个做CV的人太熟了语义类别多但几乎都是网格模型没有参数化特征用它做text-to-cad只能输出网格工程价值有限。搞不清这些数据集的边界你就会犯一个经典错误拿ShapeNet训练端到端网络然后宣称自己做了个text-to-cad最后被工艺工程师一句话问死“输出能转成STEP吗”4.2 评估指标BLUE-4、NCScore以及“能不能用”文本生成模型常用的评估指标是BLEU看生成序列和参考序列的n-gram重合度。但在text-to-cad里BLEU只是一个很弱的参考。你代码写对了但函数名不一样BLEU可能给低分你代码逻辑完全跑不通但关键词碰上了BLEU反而给高分。更贴近任务的是Paik等人当年在Text2CAD论文里提的NCScore说白了就是看重建出来的CAD模型在几何上与真实模型的相似程度。它比BLEU有意义但依然有局限因为“几何相似”不等于“建模方法正确”。同一个圆柱可以用拉伸做出来也可以用旋转特征做出来几何相同特征历史完全不同。我的建议是落到工程评估时直接看三个硬指标比任何学术指标都管用语法通过率生成的代码有多少能无错执行。几何规则通过率关键尺寸是否在允许公差内特征数量是否匹配。下游可用率生成的模型能否被下游工程师直接修改参数而不返工。这三项一拉你立刻就知道一个系统的真实段位。4.3 警惕数据泄漏和“背诵式回答”我在测试一些开源模型时发现一个有意思的现象那些在Text2CAD数据集上BLEU分数很高的模型换一个没见过的话术描述同样的零件输出质量直线下降。说明模型并没有理解“语言到几何”的映射而是在背训练集里的相似句子。这就是数据泄漏的变体——模型背题不是做题。怎么避免被这种假象骗我的土办法是构造“跨域描述测试集”比如把同一个法兰用“管道的连接盘”“带四个螺丝孔的矩形板”“DN100配套端板”三种完全不同的说法分别描述看模型是否都能给出几何上一致的答案。能才说明它真的理解了不能那再高的评测分也是空中楼阁。5. 我在真实管线里踩过的八个坑每个都赔过时间最后这部分我按时间顺序复盘我从“第一个Demo跑通”到“内部工具初步可用”期间踩过的坑。每条都很具体基本都能直接对应到你做同类项目时会碰到的场景。5.1 坑一直接在主进程里执行LLM生成的代码环境被搞崩这是我犯的第一个错。有一次模型生成了import shutil; shutil.rmtree(/tmp/xxx)虽然因为目录不存在没造成实质损失但把我吓出一身冷汗。后来我养成了铁律**凡是外部生成的代码必须在子进程里跑并且临时目录要用tempfile.TemporaryDirectory()自动清理。**这不仅防恶意代码也防手滑——我自己手写的代码还误删过文件呢何况一个会胡说的模型。5.2 坑二温度参数没调低同一个描述每次生成的结果都不一样几何建模不要创意要确定性。我一开始使用默认的temperature1.0结果同一个Prompt每次生成代码的关键尺寸命名和特征顺序都不同后续的验证流水线根本没法做。后来我把温度压到0.1基本稳定了。如果你的模型还支持top_p也建议一起压低。text-to-cad跟写诗不一样输出方差越小越好。5.3 坑三模型的默认单位永远在“毫米”和“英寸”之间横跳CadQuery默认单位不是严格定义的它跟内核精度相关你用一个单位写完导出STEP下游软件可能按另一个单位解析。模型如果没被我第3章那条“默认单位是毫米”的Prompt约束就会时不时生成尺寸虽然对、但实际模型只有指甲盖大小的零件。这个坑的排查最耗时因为它表面上看不出报错直到下游装配时尺寸对不上。你要做的就是把单位声明写死在Prompt里同时在导出命名里带上单位标识比如flange_mm.step。5.4 坑四中文Prompt效果明显差于英文我试过直接用中文描述“一个直径30的轴套内孔16”生成的代码经常把CFD计算流体力学里那个“轴套”和机械加工里的“轴套”搞混或者把“直径30”理解成半径。把描述先通过LLM翻译成结构化的英文工程描述再生成代码效果好很多。于是我在链路里加了一步“中文→英文工程意图转写”这让生成质量上了一个台阶。这不是模型歧视中文而是工程语料里英文占比太高模型的学习经验更偏向英文表达。5.5 坑五代码能跑通但模型是空白的有一次模型生成代码后子进程退出码是0没有任何报错但导出的STEP文件体积只有几百字节打开一看是个空物体。排查了半天发现模型生成的代码在最后执行了result None——它想表达“没有执行成功”的语义但程序不报错。从此我加了一步结果校验执行完成后检查result变量是否为合法的Workplane对象并且检查result.val().Volume()是否大于0。一句话的事能拦截掉不少无效生成。5.6 坑六模型把尺寸写成魔法数字参数化名存实亡生成的代码格式上是参数化的——变量放在顶部了但模型偶尔会把“直径8mm的孔”硬编码成hole(8)而“孔距边缘10mm”却定义了变量。这种“半参数化”最让人头疼你改一个尺寸另一个地方死活不动。解决的办法是事后扫描对生成的AST做规则检查要求所有数值都被变量引用发现魔法数字就直接判定生成失败并重试。这比事后人工改代码效率高得多。5.7 坑七生成了正确的模型但特征历史是“一笔糊图”CadQuery生成的模型最终是带特征树的但LLM生成的特征顺序偶尔非常糟糕。比如先用一个草图把所有孔都挖了再去做倒角导致倒角把孔口边缘也破坏了。几何虽然从数值上是对的但特征树没法用。这对工程师来说是不可接受的。我现在会让LLM在生成代码前先输出一个“特征规划清单”再输出对应代码相当于强制它先想步骤再动手。这能显著减少特征顺序混乱的问题。5.8 坑八子进程内存没回收批量生成时机器越来越卡批量测试的时候我连续跑了300次生成结果机器越来越慢。检查发现是CadQuery的子进程虽然结束了但某些OpenCascade的临时文件没有清干净再加上TemporaryDirectory在某些异常退出路径下没有触发清理。后来的方案是整个批量任务跑完后用multiprocessing强制回收并定期手动清理系统临时目录同时给子进程加resource限制防止个别极端代码吃掉整个内存。工程化的本质就是把这些角落里的脏活全部收拾干净。最后说点我的真实感受做到这一步我对text-to-cad的态度是不要指望它一步到位取代机械工程师但它会像当年从手绘板图切换到参数化三维软件那样把“从语言到模型”的重复性劳动砍掉一大半。最务实的落地姿势是先圈定一个很小的零件域——法兰、支架、轴承座、钣金件——把这个域里的参数化模板和校验规则做扎实再让LLM在边界内生成这比让AI一次性理解整个世界要靠谱得多。我自己接下来的小目标是给这套管线加上“几何规则校验器”让每个生成的模型都要过一遍装配干涉检查和尺寸公差检查。你如果也想动手试我建议先不要碰复杂的端到端网络先照着第3章的CadQuery链路搭一个最小闭环你会比看一百篇论文都更快地理解这个领域的真正难点在哪。

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

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

免费获取报价 →
↑