☰
Text-to-CAD实战:自然语言生成CAD模型的原理与工程化
2026/10/27 13:25:49 网站建设 项目流程

text-to-cad这个词,这两年但凡关注AI辅助设计的人都绕不开。简单说,它就是让用户用一句自然语言,比如"一个带圆角的矩形底座,中间挖一个直径10毫米的孔",直接生成对应的CAD模型。在我这种每天跟三维建模打交道的人看来,这东西最直接的价值不是取代设计师,而是把那些重复到让人烦躁的草图、拉伸、切槽操作,压缩成一句话的事。不管是做机械零件、产品外观快速验证,还是搭标准件库,它都能把"从想法到模型"的时间从小时级压到分钟级。这篇文章我会从原理、工具选型、实操流程到避坑经验,完整拆一遍这条技术路线。

1. text-to-cad的核心思路拆解:它到底在生成什么

1.1 先搞清楚它生成的不是模型,而是命令序列

很多人第一次听说text-to-cad,以为它是像文生图那样直接吐出一个网格文件,比如STL或者OBJ。实际不是这样。目前主流方案生成的是CAD建模软件的"操作指令",比如一段CadQuery或OpenSCAD代码,或者一组带参数的建模命令序列。这些指令被CAD内核执行后,才得到真正的实体模型。

这个区别非常重要。直接生成网格文件,听起来简单,但网格模型在工程里很难用:没有参数化、没法改尺寸、不能进入装配树、做不了应力分析。而命令序列不一样,它保留了建模逻辑,生成之后你可以改参数、重放、和现有图纸集成。我举个例子,用户说"生成一个直径50毫米、高30毫米的圆柱体",系统输出的不是圆柱体的面片,而是类似"cylinder(r=25, h=30)"这样的指令。CAD内核执行时,得到的圆柱是带完整拓扑信息的实体,可以继续打孔、倒角、布尔运算。

这个设计取舍背后是有道理的。CAD模型的本质是什么?不是几何面的集合,而是"参数 + 特征 + 约束"的层级结构。用命令序列生成,等于把自然语言映射到特征树上的操作,跟设计师平时手工操作的逻辑是一致的。这也是为什么当前text-to-cad的学术研究普遍选择了CSG(构造实体几何)或者草图-拉伸这类中间表达,而不是简单的体素或者点云。体素和点云只能告诉你"这个模型大概长什么样",命令序列告诉你"怎么一步步把它造出来"。

1.2 两条主流技术路线的逻辑差异

目前我实际用下来,text-to-cad大体分两条路线。一条是端到端的大模型生成路线,典型代表是2024年出现的Text2CAD工作。它用大量的"文本描述-CAD命令序列"配对数据,直接微调一个大语言模型,比如Llama-2-7B。模型输入一句英文描述,输出一串约束好的草图参数和挤出操作。这套路线的优势是"端到端",你不需要维护规则库,模型见过足够多数据后,能处理一些复杂的组合描述,比如"带四个安装孔的方形法兰"。

另一条是程序化生成路线,代表是CAD-CLI这类工具。它不是一个针对CAD微调过的专用模型,而是把通用LLM(比如GPT系列、Claude)接到CadQuery或OpenSCAD等程序化建模库上。用户用自然语言描述需求,LLM负责把这句描述翻译成Python代码,代码再调用CadQuery生成实体模型。这条路线的好处是灵活,通用LLM的代码能力越来越强,换成OpenSCAD、SolidWorks API也都能接;缺点是LLM生成的代码不稳定,偶尔会出现语法错误或者逻辑错误,需要额外的校验和修复环节。

选哪条路线,取决于你手里的资源和要解决的问题。如果你是研究者,想探索CAD生成的极限,可以走端到端微调路线,但你需要准备足够的算力和清洗过的配对数据集,门槛不低。如果你是在工程场景里想快速用起来,我更推荐程序化生成路线,因为它见效快,而且出问题了好排查——大不了改改代码,不至于推倒重来。我自己的实践是两条都试过,结论是:程序化路线更抗造,端到端路线更省事。

2. 工具选型与平台盘点:开源、商业怎么选

2.1 从Text2CAD数据集开始的研究路线

如果你对学术路线感兴趣,Text2CAD是我建议的起点。它是一个文本到CAD配对数据集,收集了来自ABC数据集的大量CAD模型,每个模型都有对应的自然语言描述和建模命令序列。描述不只是一句话,而是分层次的,从"一个长方体"到"一个带有四个等间距圆孔的扁平长方体",覆盖了从简单到复杂的多种组合。这个数据集最大的价值在于配对质量:文本和命令是严格对应的,不像网上随手抓的数据那样脏。

基于这个数据集,论文里用的是两阶段框架。第一阶段输入自然语言,输出一个草图和对应的约束条件;第二阶段再把这个草图转换成完整的CAD建模命令。为什么要分两步?因为直接生成最终模型,信息跨度太大,模型容易在中间步骤迷失。先画草图再挤出成体,是CAD建模里最基础的套路,把问题拆开之后,每一步的生成难度都降低了,整体成功率反而提升。

我自己拿这个框架跑过实验,有一个直观感受:模型在简单几何体上的生成成功率非常高,超过九成,但一旦描述里出现"对称""等距""切线"这类涉及空间关系的词,成功率就会往下掉。这不是模型不够大,而是训练数据里这类空间关系描述的比例不够高。所以在自己准备数据时,我建议刻意增加这类复杂关系描述的样本数量,效果比单纯加模型参数量更明显。

2.2 程序化生成路线:LLM加CadQuery的组合

对工程实操来说,我更常用的是LLM加CadQuery的组合。CadQuery是一个Python库,它用链式调用的方式构建CAD模型,代码直观,支持的建模操作也够全:拉伸、旋转、布尔、倒角、圆角、阵列都有。配合现代LLM的代码生成能力,这套组合的实用性非常高。

CAD-CLI这个项目就是套组合的典型实现。它会调用一个LLM后端(支持OpenAI API,也支持Ollama本地模型),把你的自然语言描述转成CadQuery代码,然后执行代码生成模型文件。我用下来,这套东西最舒服的地方在于可以"对话式建模":第一次生成结果不满意,你不需要从头描述,只要说"把孔改成6毫米""再加两个圆角",它就能输出修改后的模型。这个交互方式非常贴近设计师和客户之间的沟通习惯。

选型上有几个细节值得注意。CAD-CLI默认支持OpenAI API,但在国内网络环境下,API调用经常不稳定。我改用Ollama跑本地模型,实测下来也能跑通,只不过生成代码的质量比GPT-4要差一些,后处理时得多花点功夫修错。如果你对精度要求高,可以用API版本;如果你有数据隐私顾虑,或者网络不稳定,那本地模型是更合理的选择。在CadQuery和OpenSCAD之间,我倾向CadQuery,因为它的Python API更现代,出错信息也更容易理解。

2.3 商业软件里的AI辅助

除了开源路线,商用CAD软件这两年也在押注AI辅助。SolidWorks、Fusion 360、AutoCAD都有各自的AI助手或AI增强功能,用户可以用自然语言描述意图,软件自动生成对应的特征或修改建议。这些功能在工业界落地的逻辑和开源路线不太一样,它们更强调"辅助"而不是"生成":AI不会直接给你一个全新零件,而是在你建模的过程中,帮助你完成某个特征,或者在中途给你合理的下一步建议。

个人看法是,商业软件的AI辅助更适合已有建模基础、只是希望提效的工程师;text-to-cad这类工具更适合前期概念设计或者需要快速产出大量变体零件的人。两者不冲突,实际工作中可以结合使用:概念阶段用text-to-cad快速试验不同形状,确定方向后再进商业软件做详细设计。我自己就是这么干的,前期探索省下的时间非常可观。

3. 实操:跑通一个本地可用的text-to-cad流程

3.1 准备环境:先把CadQuery和LLM后端装好

下面进入实操部分。这一节的目标是搭建一个最小可用的text-to-cad系统:你输入一句中文或英文描述,它输出一个STEP格式的CAD模型文件。先说环境准备,我的建议是用Anaconda建一个独立环境,避免依赖冲突。

conda create -n cadgen python=3.10 -y conda activate cadgen pip install cadquery pip install ollama

如果你更习惯用mamba或者普通venv,也没问题。CadQuery安装之后,建议立刻跑一个最简单的冒烟测试,确认安装正确:

import cadquery as cq result = cq.Workplane("XY").box(10, 10, 5) cq.exporters.export(result, "test.step")

能生成test.step文件,环境就算准备好了。不要跳过这一步,卡在环境上比卡在算法上更浪费时间。

LLM后端方面,如果你有OpenAI API Key,直接用API最省事。没有的话,用Ollama拉一个代码能力较强的本地模型,比如qwen2.5-coder:7b或codeqwen。代码生成任务对模型的代码能力要求高,我从实际测试看,7B参数级别的开源模型,在简单几何体描述上生成CadQuery代码的成功率大约在六七成,配合错误修复还能再往上提一点。如果只有3B或更小的模型,建议放弃CadQuery,改用更简单的SVG或2D轮廓生成,否则调试成本太高。

3.2 构造文本到CAD命令的对话能力

环境准备好之后,核心问题就是怎么把自然语言转成CadQuery代码。最简单可靠的方式是直接调用LLM的聊天补全接口,设计一个针对CAD的system prompt。下面这段是我反复调过之后的效果比较稳定的提示词模板:

You are a CAD modeling assistant. You only write CadQuery Python code. - Output code only, wrapped in ```python``` blocks. - Use millimeters as the default unit. - The workplane is always "XY" unless specified. - Use variable name "result" for the final solid. - If the user request is ambiguous, state your assumption briefly, then write the code. - Do not include placeholder comments. - Handle holes using cq.Workplane("XY").pushPoints([...]).hole(diameter)

这个模板里有一个关键点:指定result作为最终变量名。这个约定非常重要,因为后面我们要在脚本里统一用result变量来做导出操作,如果模型给变量起了别名,自动执行逻辑就得去解析代码,麻烦很多。类似的约定越明确,LLM生成的代码越稳定。

写一个Python脚本,把用户输入拼到system prompt后面,请求LLM输出代码。我用Ollama的HTTP API为例,一个极简封装可以长这样:

import requests import json def generate_cad_code(prompt: str) -> str: response = requests.post( "http://localhost:11434/api/chat", json={ "model": "qwen2.5-coder:7b", "messages": [ {"role": "system", "content": "You are a CAD modeling assistant. ..."}, {"role": "user", "content": prompt}, ], "stream": False, "options": { "temperature": 0.2, "top_p": 0.9, }, }, ) data = response.json() return data["message"]["content"]

注意temperature这个参数。代码生成和文本创作不一样,我建议把温度压到0.2左右。温度太高,模型容易在代码里加一些"发挥"出来的逻辑,比如多创建一个多余的立方体,或者把尺寸改了。低温能显著降低这类随机性,代价是输出会有点机械,但对代码来说机械是好事。

3.3 从自然语言到STEP文件的完整闭环

拿到模型生成的CadQuery代码之后,最后一步是执行代码并导出STEP文件。因为我要求模型固定使用result变量名,导出逻辑就很干净:

import cadquery as cq import re def extract_python(raw: str) -> str: match = re.search(r"```python\n(.*?)```", raw, re.DOTALL) return match.group(1) if match else raw def execute_and_export(cad_code: str, output: str) -> bool: namespace = {"cq": cq} try: exec(cad_code, namespace) result = namespace.get("result") if result is None: print("没有找到result变量") return False cq.exporters.export(result, output) return True except Exception as e: print("执行出错:", e) return False

执行时注意namespace里传入了cq模块。CadQuery代码依赖cq这个简写,如果你不提前在命名空间里把它准备好,exec执行时会报NameError。这个细节是调试过程中最容易踩的坑之一,我一开始没用命名空间传参,结果代码死活跑不起来,一度以为是LLM生成的代码有问题,排查了半天。

最后把这些串起来,一个从自然语言到STEP文件的闭环就完成了:

if __name__ == "__main__": user_input = "一块长100毫米、宽60毫米、厚8毫米的平板,四角各有一个直径6毫米的圆孔" raw = generate_cad_code(user_input) code = extract_python(raw) success = execute_and_export(code, "plate.step") if success: print("STEP文件已生成")

跑通之后,建议立刻验证STEP文件。最直接的办法是用FreeCAD或者在线查看器打开,确认模型和描述一致。这里有一个容易忽略的点:CAD模型的尺寸单位。CadQuery默认是毫米,但STEP文件里其实包含单位信息。在部分查看器里,如果你导入时设置的单位是英寸,一个25毫米的孔会显示成25英寸,看着像是模型生成错了,其实只是查看器的单位设置问题。我建议导出前,优先用cq.exporters.export的默认配置,然后在查看器里显式选择毫米单位。

3.4 验证模型质量:不只是"能生成"就行

模型生成出来之后,怎么判断它质量好不好?工程上建议从三个维度检查。第一个是几何正确性,即模型的尺寸、位置、拓扑关系是否和描述一致。这个可以通过测量工具逐项核对,说白了就是拿"卡尺"量一下模型。第二个是参数化程度,也就是生成的命令序列是否保留了可调参数。比如把圆孔直径写成一个变量,后面改尺寸时就只需要改一个值,整块板的其余特征都会联动更新。第三个是文件大小和复杂度,这决定了后续做有限元分析或者CAM编程时,系统会不会卡顿。

在实测过程中,我见过一种情况:模型看起来和描述一致,但仔细检查后发现是一个"实体"里面嵌套了另一个"实体",或者两个面之间有一个肉眼看不出来的微缝。这在CAD里叫非流形几何或者拓扑异常。CadQuery生成的模型正常情况下不会出现这种问题,但如果LLM生成了额外的布尔运算,比如把一个体从另一个体里减去之后又加回来,就可能在公差范围内产生零碎的微小实体。遇到这种现象,在导出前可以用CheckWorkplane或者vtx()检查顶点数,如果数据异常,直接重新生成一次往往比手工修复更快。

4. 效果调优:让生成结果从"能跑"升级到"能用"

4.1 Prompt工程的三个关键点

text-to-cad成败的关键,有时候不在模型本身,而在你怎么描述需求。同样的"生成一个带孔的法兰",描述方式的差异会带来完全不同的输出质量。我总结了三个在工程场景里最影响效果的因素。

第一是明确关键尺寸。说"一个中等大小的支架",模型大概率会给出一个它猜的尺寸。很多情况下这不算错,但工程上没法用。尺寸必须具体:长、宽、高、孔径、孔距、倒角半径,所有你能想到的数值都明确写出来,效果会好很多。第二是指定建模特征顺序。CAD模型的参数化等级和特征顺序有强关系。你说"先拉伸一个底座,然后在底座的顶面画四个孔",和只说"一个带孔的底座",得到的模型内部结构天差地别。对于需要后续修改的零件,我建议描述时尽量包含建模顺序信息。第三是明确单位和后缀。这个问题上面已经提到过,值得再强调一次:CadQuery默认毫米,但LLM训练数据里可能有大量用英寸描述的代码。如果你不指定单位,它可能随机给一个它自认为合理的单位体系。所以prompt里要固定写上"unit: millimeters"。

4.2 训练数据质量才是真正的上限

如果你尝试自己微调一个text-to-cad专用模型,最深刻的体会一定是:数据天花板远比模型架构天花板低。Text2CAD数据集的质量已经算不错,但还是有大量模型描述存在歧义。比如"a round plate"到底是圆盘还是圆板?"a bracket with a slot"这个槽是通槽还是盲槽?这些歧义如果不消除,模型学到的就是一个模糊的映射,生成结果自然就不稳定。

我建议在准备训练数据时做这几件事。第一,统一描述模板,把尺寸、位置、特征顺序都格式化,比如"长L毫米、宽W毫米、高H毫米的矩形块,在顶面中心挖一个直径D毫米的通孔"。模板化本身就在帮助模型消除歧义。第二,过滤掉含有多重含义的形容词,比如"big""small""nice"这类主观词,或者明确给它们配上具体数值范围。第三,用CAD脚本生成合成数据对,这个过程可以用CadQuery批量生成代码,再用代码自动生成描述文本。这么做的好处是可以精确控制数据分布,缺陷是描述文本会偏模板化,真实场景里用户说的话往往更随意。比较好的做法是先用合成数据做主体,再人工补充一部分真实风格的描述作为增量数据。

4.3 后处理:让通用CAD工具跟AI生成的模型兼容

AI生成模型与实际生产之间还隔着一条河,后处理就是把桥搭起来的过程。通用CAD软件对AI生成模型的兼容性,是个经常被忽略但非常现实的问题。我遇到过的情况是:CadQuery导出的STEP文件在SolidWorks里打开正常,但导入Fusion 360时,有些圆角特征变成了网格面。这不是模型错了,而是STEP导出精度和不同CAD内核的容差设置不一致。

解决思路是使用STEP的高精度导出参数。CadQuery里可以这样设置:

cq.exporters.export( result, "part.step", cq.exporters.ExportTypes.STEP, tolerance=0.01, )

tolerance参数控制的是曲面细分的精度,数值越小越好,但也会让文件变大。对于一般机械零件,0.01毫米就足够了;如果涉及高精度的配合面,可以放到0.001毫米。另一个容易踩的坑是:CAD软件导入STEP文件时默认单位。不同软件之间的STEP单位处理逻辑并不完全一致,导入导出后出现尺度差了25.4倍的情况,多半都是单位转换问题。处理办法是,在导出前置入一个显式的坐标变换或缩放操作,在导出后立刻用测量工具确认关键尺寸,不要等到整个流程走完再检查。

5. 踩坑记录与问题排查实录

5.1 LLM生成了代码但执行报错:先分"四种错"

生成代码后执行报错是常态,不用慌。我总结下来,CadQuery代码出错基本可以归为四类。

第一类是语法错误,比如括号不匹配、引号没闭合。这类错误最简单,通常一看就知道,可以让LLM自己看着报错信息再修一遍,基本就能解决。第二类是API使用错误,比如调用了不存在的方法,或者参数类型不对。CadQuery的API在不同版本里变动过,LLM可能学到的是旧版API。这个只能靠把报错信息回传给LLM让它改,或者查阅CadQuery当前版本的文档。第三类是几何逻辑错误,代码能跑通,但结果不对。比如用户要四个孔,模型生成了六个;或者孔的位置偏移了。这类错误最隐蔽,因为程序不报错但结果和预期不符,必须结合模型输出和用户描述逐条核对。第四类是环境错误,比如缺少依赖库、版本冲突。这类问题纯属工程问题,和AI没啥关系,解决办法就是按报错信息装依赖。

一个提高修复效率的做法是把报错信息直接拼到prompt里,让模型看错误二次修改。实测下来,对于前两类错误,模型二次修复的成功率能有七八成;对第三类错误,模型往往还会坚持自己的错误逻辑。你应该在脚本里加入一个循环:执行失败时,把错误信息反馈给模型并让它修正,最多试三次。三次还不行,就重置prompt重新描述需求。

5.2 中文描述支持问题:能说中文,但要说"明白话"

很多读者关心text-to-cad支不支持中文。答案是支持,但效果比英文差一些,尤其是本地开源模型。原因不复杂:开源模型的中文指令遵循能力普遍弱于英文,而且CAD命令序列的训练数据大多是英文描述。中文描述里如果还有"偏""靠""约"这类模糊方位词,模型理解起来更吃力。

我的解决方案不是让模型理解中文,而是让"人的语言"尽可能接近"机器的语言"。具体来说,用中文描述时,尽量把方位词替换成明确坐标:不说"孔在板的右上角",说"孔的中心在(X=20, Y=15, Z=0)"。不说"稍微厚一点",说"厚度从5毫米改成8毫米"。这一步做得好,中文描述的成功率能接近英文水平。如果还是不行,可以先用LLM把中文翻译成英文再执行生成,但注意翻译本身会损耗信息,原始描述必须足够精确。

5.3 拓扑错误和布尔运算的坑

使用布尔运算(并集、差集、交集)时,最容易遇到的是求解失败或产生退化实体。我在实际使用中频繁踩的一个坑是:给一个圆柱体侧面开槽,描述是"在圆柱侧面开一个水平方槽",LLM可能会生成一个方柱体,然后跟圆柱做差集。问题在于方柱体的一个面和圆柱表面正好相切,这种"恰好接触"的位置在CAD内核做布尔运算时,经常因为浮点数精度导致失败或产生微小的残留体。

处理这类问题的办法有两个。一个是让槽体穿透圆柱,不要刚好贴合表面,用穿透量来绕开相切问题。在CadQuery里,如果槽体长度是20毫米,圆柱直径是50毫米,就让它长度到25毫米以上。另一个是加一个微小偏移,把本来相切的位置改成相交0.001毫米。这两招能解决绝大多数布尔失败。另外,在描述里刻意避免"刚好""正好"这类等于关系的表达,它们映射到几何上就是相切或共面,都是高风险的拓扑关系。

5.4 生成速度与资源的平衡

最后聊一下性能。用API方式调用大模型,单次生成的耗时基本在1到3秒,加上CadQuery执行和导出,整个流程在5秒以内,这是最理想的体验。但本地模型就没这么舒服了,7B模型在CPU上生成一段代码往往要30秒到2分钟。如果你有GPU,建议用量化版本的模型,比如Q4_K_M量化,速度和显存占用都比较均衡。

性能优化上有两个思路。一个是用更小更快的模型做"初稿生成",再用规则脚本做第一步校验,如果校验失败,才升级到大模型重生成。这个两阶段策略能把平均延迟降到10秒以内。另一个是缓存:相似的描述可以先用Embedding做语义相似度匹配,如果历史上有非常接近的生成结果,直接复用并让用户确认。这个优化对标准件这类高频场景特别有效,我实现过一版,缓存命中率能到30%以上。

写在最后的一点个人体会

text-to-cad这条路,从最早实验室里的概念,到现在已经能看到实际落地的影子。我个人的体会是,别把它当成一个"神奇生成器",它的真正定位是"把人类意图翻译成机器可执行的建模逻辑"。因此,输入质量的提升远比模型参数的堆砌重要。在实际项目里,与其整天换更大更强的模型,不如花时间把你的需求描述模板做好、把验证流程打通。最后再分享一个小技巧:给每个生成任务准备一个固定的"需求检查单"——尺寸、单位、特征顺序、特殊要求,逐项采集完整后再发给模型,你会惊讶地发现,80%的返工都因为这个简单的习惯消失了。这套流程多跑几遍,你会慢慢摸到它的脾气,用起来会越来越顺手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询