Text-to-CAD实战:从自然语言到可编辑三维模型的生成链路
发布时间:2026/10/8 8:12:26 作者:尧图编辑部 阅读量:1,286

我最早接触 text-to-cad 这个方向是在一次给客户做自动化设计流程评估的时候。对方产品团队提了个需求希望业务人员用一句话描述“我要一个内径25、外径60、四个均布螺丝孔的法兰盘”系统就能直接给出可编辑的三维模型而不是让设计员重新画一遍草图、拉特征、打孔。当时市面上还没有特别成熟的方案但 text-to-cad 这个概念已经足够清晰了——它不是AI生成一张好看的效果图而是让大语言模型直接生成CAD软件能识别、编辑、再加工的实体模型。这篇文章我就把自己这段时间跑通项目、踩坑、复现推理和训练的经验整理出来给想做这块或者正在调研技术路线的朋友一个参考。text-to-cad 的核心价值在于它把传统CAD建模从“手动操作软件”变成了“自然语言描述几何意图”交给大模型去完成建模命令的组织和执行。适合的人也很明确机械设计、工业设计、建筑构件的自动化生成场景CAD二次开发的工程师以及做生成式几何算法研究的技术人员。它不能替代设计师但在标准件生成、概念方案发散、批量改型这些高重复度场景里确实能节省大量时间。下面我按从原理到实操的顺序把这个项目完整拆一遍。1. 内容整体设计与思路拆解1.1 从“画图”到“说图”建模范式的变化传统CAD建模流程本质上是“人手动告诉软件每一步怎么做”先建草图、加约束、拉伸、切除、打孔、倒角每一步都依赖鼠标点击和参数输入。这个流程的问题在于很多零件的结构是规则化的建模路径完全可以标准化却仍然要设计师逐条执行。text-to-cad 的思路则是把建模过程抽象成“意图到操作序列”的映射输入一句话输出一组CAD操作命令再由CAD内核解析执行。这个范式变化最大的意义不在于“省一次点击”而在于建模知识本身可以被数据化、被学习、被复用。一个经验丰富的结构工程师画法兰盘可能要两分钟但在好的数据集上训练出的模型可以在几百毫秒内生成同样可编辑的特征树。对前期概念设计特别友好——你只需要描述大致的几何关系模型先生成几个候选方案人再从里面选一个细化。这比从空白文件开始要高效得多。1.2 技术路线的关键分岔口生成什么“表示”做 text-to-cad 第一个要拍板的问题让模型以什么形式输出几何我见过三种主流路线各有适用场景路线输出形式优势短板隐式场/体素/点云直接生成三维几何数据视觉效果丰富适合自由曲面、艺术造型数据量大难以编辑工业软件不认程序化代码生成OpenSCAD、CadQuery、Python-CAD脚本可参数化逻辑清晰适合规则零件代码空间较大容易生成不可执行的脚本B-Rep命令序列生成带参数的建模命令序列如C-CODE贴近CAD内核可直接重建特征树对解析器和数据质量要求高我自己在实际项目里更倾向 B-Rep 命令序列这条路线。原因很直白工业界最终要的是能进CAD软件、能二次编辑、能出工程图的实体。网格和点云好看是好看但导入SolidWorks之后没法编辑特征树等于废了。程序化代码灵活度高但模型的代码生成能力再强也不能保证每一段都是可执行且无歧义的。B-Rep序列天然贴近CAD内核的数据结构模型只要把命令序列预测对几何引擎就能重建实体。2. 核心原理拆解模型怎么把文字变成CAD模型2.1 为什么用B-Rep序列作为中间表示B-Rep边界表示法是几乎所有主流CAD内核Parasolid、ACIS、OpenCASCADE内部存储实体的核心数据结构。它描述的不只是一个网格外壳而是面、边、顶点之间的拓扑关系以及每个面上的参数方程。CAD软件之所以能做到“拉伸一个面就能改整个实体”就是因为模型内部保存着这些拓扑和特征信息。text-to-cad 里采用B-Rep序列本质上就是把“建模操作”编码成一种接近程序语言的中间格式。比如一个简单的带孔长方体序列大致是add_box origin(0,0,0) dims(100,60,20) add_hole center(50,30,10) axis(0,0,1) radius5 depththrough模型要学的不是“像素级的体素分布”而是“一段有序的操作指令”。这看着简单实际是两个层面的对齐一是几何参数要对坐标、尺寸、方向不能错二是操作顺序要对你得先建主体再加孔不能先打孔再建主体。好在语言模型最擅长的恰恰就是“有序生成token序列”所以把三维几何问题转成序列问题是把LLM的能力嫁接到CAD上的关键一步。2.2 数据从哪来CAD数据集的选择与构建训练 text-to-cad 模型数据是最耗精力的一环。公开可用的CAD模型数据主要有几个来源Fusion 360 Gallery、ABC Dataset、OpenSCAD模型库以及各种机械零件库。Fusion 360 Gallery 的数据优点是带有完整的建模特征树能提取出真实操作序列ABC数据集体量大模型数量百万级覆盖几何形态极其多样但很多不带特征树需要额外做解析处理。OpenSCAD模型的优势是自带程序化描述天然就是“代码到几何”的映射。实际构建过程不是下载即用。要先把原始模型转成统一的命令序列格式再为每个序列生成对应的自然语言描述。常见做法是用规则脚本把模型特征树里的操作、参数、顺序提取出来整理成C-CODE这类格式然后用大模型比如GPT-4级别的模型根据B-Rep序列反推一句自然语言描述。这个“反推”阶段要加人工抽检不然生成出来的指令对描述可能语义偏了模型学会了也没用。数据规模上社区主流实现一般用几十万到上百万对“指令-模型序列”样本。但我的经验是质量远比数量重要。宁可要一万个拓扑正确、特征清晰、描述准确的样本也不要百万个包含自相交、破面、无意义碎特征的样本。数据清洗时至少要做几件事用几何引擎尝试重建每个样本检查能否生成合法实体过滤掉超出常规范围的异常参数剔除特征数过多或过少的两端极端样本保证分布均匀。2.3 微调基座模型为什么不从头训练做 text-to-cad 不需要从零训练一个模型而是在现成开源大模型基础上做监督微调。社区里常用的基座包括 Llama 3.1 8B、Mistral 7B 这类中等规模模型。选基座要看几个硬指标对指令跟随的理解能力、上下文窗口长度CAD命令序列可能上百token太短的窗口没法用、以及社区生态是否活跃。选择基座模型后训练方式一般是LoRA或者QLoRA低秩微调不是全参数微调。原因很现实全参数微调一个8B模型需要多卡A100跑很久LoRA只需要在注意力矩阵上加低秩适配器显存和训练时间都能降到可接受范围。我实测下来LoRA rank在16到32区间学习率1e-4到2e-4训练两到三个epoch效果就足够生成结构合理的简单零件了。基座模型自带的语言常识和代码理解能力是白嫖来的优势LoRA只需要把“自然语言”和“CAD操作序列”之间的映射关系学进去就行。3. 实操从零跑通一个 text-to-cad 推理环境3.1 环境准备与依赖安装先尽量把问题限定在可控范围Linux 环境、CUDA 12.1以上、一张显存不低于24GB的显卡。消费级卡其实也能跑我手头的4090就能运行8B模型只是batch size要压到1。如果你只有16GB显存可以考虑直接上量化版权重AWQ或GPTQ格式的4bit模型效果代价很小省下来的显存可以换更长的上下文。环境搭建我用condaPython版本3.10以上。核心依赖大概这样conda create -n text2cad python3.10 conda activate text2cad pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install transformers accelerate peft pip install vllm # 可选推理加速 pip install OCP # OpenCASCADE Python绑定用于解析B-Rep序列OCP 是OpenCASCADE的Python绑定包装它主要是为了验证模型输出的命令序列能不能真的构建出实体。这步别省因为你肉眼看到一段文本输出根本不知道几何上是不是合法的。只有让CAD内核自己去解析、去构建才能确认“这段命令真的有效”。3.2 模型权重下载与目录结构社区里已经有一些训练好的 text-to-cad 权重通常以LoRA适配器的形式分享在Hugging Face上。下载之前先把目录结构考虑清楚基座模型单独一个目录适配器单独一个目录tokenizer用基座自带的那一套千万不能混用。我见过有人把不同模型的tokenizer搞混加载后输出彻底乱码排查了半天发现是tokenizer不一致这个细节最容易踩。Hugging Face 下载大文件建议用 git-lfs或者直接用 huggingface_hub 的 snapshot_download 接口断点续传更稳。模型放哪个盘也有讲究8B模型float16权重差不多要16GBLoRA适配器一般几百MB但推理时的临时缓存、KV cache、最终导出的STEP文件都要考虑到建议至少预留50GB空间。如果下载一直失败先检查是否设置了镜像站点国内网络环境下的下载问题常规解决办法是配镜像和断点工具这里不展开。3.3 推理脚本与参数解读加载模型用 transformers 的标准流程就行。这里放一个最小可用的推理脚本import torch from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel base_model_id meta-llama/Llama-3.1-8B-Instruct adapter_path ./text2cad-lora-adapter tokenizer AutoTokenizer.from_pretrained(base_model_id) model AutoModelForCausalLM.from_pretrained( base_model_id, torch_dtypetorch.float16, device_mapauto ) model PeftModel.from_pretrained(model, adapter_path) model.eval() prompt 创建一个内径25mm、外径60mm、四个均匀分布的M6螺丝孔的法兰盘 messages [ {role: system, content: You are an expert CAD modeling assistant. Output CAD command sequences only.}, {role: user, content: prompt} ] inputs tokenizer.apply_chat_template(messages, return_tensorspt).to(cuda) with torch.no_grad(): outputs model.generate( inputs, max_new_tokens512, temperature0.2, top_p0.9, do_sampleTrue, repetition_penalty1.05 ) print(tokenizer.decode(outputs[0][inputs.shape[1]:], skip_special_tokensTrue))注意几个参数选择的原因。temperature 一定是低的我一般设0.1到0.3之间。CAD命令序列不像聊天不能有太大的随机性temperature 一旦超过0.5生成的参数很容易漂移明明想生成半径5的孔模型给你输出一个5.732这种莫名其妙的数。top_p 保持0.9基本够用。max_new_tokens 根据零件复杂度设置简单零件256复杂零件可以给到1024设少了模型会在生成中途被截断输出一段不完整的命令序列几何引擎根本没法解析。重复惩罚也要稍微加一点这个动作是为了防止模型在某个参数上死循环生成一串重复的坐标点。理论上C-CODE这种格式化输出不容易重复但一旦出现就是整段全部报废所以成本很低、收益不小。如果显存紧张可以换用vLLM做推理吞吐量更高代码改动也不大。3.4 从生成的B-Rep序列到可视化和导出拿到一段命令序列文本还远远不算完。下一步要解析它交给OpenCASCADE重建实体。我一般写一个简易解析器把每一行命令映射到OCP的建模API调用上from OCP.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder from OCP.BRepAlgoAPI import BRepAlgoAPI_Cut from OCP.BRepFeat import BRepFeat_MakeCylindricalHole from OCP.STEPControl import STEPControl_Writer, STEPControl_AsIs # 解析命令序列 # add_box origin(0,0,0) dims(100,60,20) box BRepPrimAPI_MakeBox(gp_Pnt(0,0,0), 100, 60, 20).Shape() # add_hole center(50,30,10) axis(0,0,1) radius5 depththrough hole_axis gp_Ax2(gp_Pnt(50,30,10), gp_Dir(0,0,1)) hole BRepFeat_MakeCylindricalHole(box, 5, 100, hole_axis).Shape() # 导出STEP writer STEPControl_Writer() writer.Transfer(box, STEPControl_AsIs) writer.Write(output.step)这段代码里最关键的是“解析后的命令序列能不能被内核接受”。如果模型输出的坐标轴是斜的、方向向量没有归一化、或者孔深度比实体厚度还大OpenCASCADE照样会报错或者生成一个破玩意儿。所以我会在解析器里加一层“合法性校验”检查每个参数的范围替换掉非法值再把几何引擎的构建结果保存成STEP和STL各一份方便快速查看。实际验收标准我建议就定成一条生成的STEP文件能被主流CAD软件SolidWorks / Fusion 360 / FreeCAD任一即可直接打开并且特征树是可编辑的。只要这个标准通过了说明这条生成链路是真正可用的。打开失败就说明某个环节有问题要么命令序列本身错要么你的解析器漏了参数。4. 如果想更进一步训练自己的 text-to-cad 模型4.1 数据预处理流水线自己训练模型第一步还是做数据。完整的流水线大概是收集原始模型 → 提取特征树 → 转成命令序列 → 给每个序列生成自然语言描述 → 清洗过滤 → 构建训练集。这个流程里最容易忽视的是“描述多样性”。如果一万个样本的指令都是“创建圆柱体”这种固定句式模型学到的只是句式匹配不是真正的语义理解。要主动给描述加噪声换说法、换单位、加修饰语、用不同风格的表达方式让模型见过足够多的语言变化。描述生成这一步可以用规则模板生成一部分简单可靠再用大模型生成一部分覆盖复杂场景最后人工抽检合并。我的经验比例是三七开三分模板、七分LLM生成再人工抽查其中10%确认质量。数据量上起步两三万对就能见到效果要做得比较稳十万对起步比较合适。每一对样本还要做去重防止同一个零件在数据集里重复出现太多次导致模型过拟合到某几个特定形状上。4.2 微调时的关键超参与数据格式训练脚本用 transformers 的 Trainer 或者 peft 的封装都可以。数据格式上我建议直接用对话式结构保持和基座模型一致的指令模板。每条样本包括一个system提示、一个user请求、一个assistant回答。system提示固定为“你是一个CAD建模专家只输出CAD命令序列”user部分是自然语言描述assistant部分是命令序列。这样的好处是训练和推理时格式完全一致不会出现GAP。LoRA 配置可以直接参考下面的参数from peft import LoraConfig lora_config LoraConfig( r32, lora_alpha64, target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], lora_dropout0.05, biasnone, task_typeCAUSAL_LM )训练超参里最重要的是学习率和batch size的搭配。学习率2e-4左右warmup比例3%总batch size梯度累积后32到64。batch size大收敛更稳但要注意显存。训练过程中不要只盯着loss曲线我强烈建议每隔几百步就采样几个验证集样本把生成的命令序列解析成STEP文件肉眼看一下几何是否正确。loss下降不代表生成的命令合法语言模型可以loss很低但仍然在坐标、参数上犯低级错误。4.3 评估指标三层验证体系评估一个 text-to-cad 模型的好坏我不会只看一个指标而是分三层做验证第一层是执行成功率。把生成结果丢给解析器和几何引擎看能不能成功构建实体、导出STEP。这一层是硬门槛过不了基本没有下一步。第二层是语义对齐度可以用传统文本指标BLEU、ROUGE做一个粗筛但我实际觉得这些指标对CAD场景很不可靠——命令序列换个参数表达方式BLEU分就掉得厉害但几何结果可能完全一样。更可靠的是把生成的STEP文件和一个参考模型做几何相似度比对或者用更强的LLM做裁判判断“这两个建模方式是否实现了同一个几何意图”。第三层是工程设计维度的人工抽检随机挑100个生成样本看特征树是否合理、是否有多余的布尔操作、能不能在CAD里顺利编辑。评估维度主要方法是否推荐执行成功率几何引擎解析实体构建必看硬门槛语义对齐几何相似度比对 / LLM-as-judge推荐比BLEU靠谱文本相似BLEU / ROUGE仅参考工程设计人工抽检特征树必看决定最终可用性我踩过的坑是过分追求BLEU分调了一堆超参让文本指标上去了结果生成STEP文件打开率高了一点但没本质变化。后来改成几何验证之后才意识到前面全都白调了。建议从一开始就把几何引擎校验接入评估管线别走弯路。5. 踩坑实录常见问题与排查技巧5.1 显存溢出和加载慢8B模型 float16 权重占约16GB实际上推理时还有KV cache24GB卡勉强跑batch 1稍微拉长输入输出就爆显存。我踩过一次给了一张24GB卡max_new_tokens 开到2048跑了十几个样本后OOM。解决办法是降级到4bit量化AWQ/GPTQ显存占用直接减半或者改用vLLM做推理它会把显存调度做得很激进同样的卡能撑更长的序列。加载慢的问题除了换硬件没有太多办法一个正向经验是把模型用 safetensors 格式保存加载速度比pickle格式快一个量级。5.2 生成结果只是一堆乱码或空模型这个问题在刚开始跑通流程时特别常见。排查路径我总结成三步先看tokenizer对不对再看采样参数是不是太高最后看是否有上下文截断导致命令序列不完整。有一次我生成出来的文本前半段正常后半段突然变成了重复的坐标对排查到最后发现是某个版本的repetition_penalty在量化模型上表现异常。换成默认1.0再调temperature之后就好了。如果当前权重的基座模型和代码里指定的基座模型版本不一致也很容易出现奇怪的输出记得先核对权重的来源说明。5.3 数据集下载失败和硬盘空间问题训练数据集动辄几百GB我用一个公开CAD数据集时连续两天卡在4%进度最后换了下载方式加断点续传才跑完。硬盘空间也别侥幸建议至少预留1TB我实际数据预处理时就发现临时文件、解析缓存、中间格式加起来比原始数据还大。另一个重要的经验是预处理完后直接生成 tokenize 后的二进制的缓存文件arrow/parquet格式后续训练加载快很多还能避免反复解析原始STEP文件的那种慢到崩溃的体验。5.4 生成的模型CAD软件打不开这是最隐蔽也最头疼的问题。命令序列看起来完全正常OpenCASCADE也成功构建了实体但STEP导入SolidWorks就是报错。这种情况往往是几何内核之间的数据兼容差异造成的比如某个面退化成一条边、某个曲面参数域异常、或者布尔操作产生了非常薄的退化几何。OpenCASCADE里有个 ShapeFix 工具可以自动修复这类问题我在导出前会强制跑一遍修复流程。还有一个治本方向的思路是在生成阶段就限制参数范围比如圆柱半径最小值、孔深度上限把离群参数直接交给解码器约束从源头减少退化几何。很坦白地说这个领域目前的模型很难做到100%生成全部合法后处理修复几乎是必然要保留的一环。还有一个容易被忽略的小问题很多CAD软件不识别重复面或重复边。同一个长方体和另一个长方体完全重合地做了一次布尔并集OpenCASCADE可能不报错但下游软件的面编号会乱掉。我一开始没注意后来导出的一批STL在打印切片软件里全是破面排查了很久才定位到这个原因。后来在解析器里加了“空操作检测”遇到完全重复的面就跳过问题就消失了。6. 后续还可以怎么扩展跑通基础流程后值得往几个方向再深挖一层。第一个方向是支持更复杂的装配体现在的方案基本都是单零件级别如果能把“由一个底座、两根轴和四个螺栓组成的装配体”这种描述直接转成装配树和配合关系价值会大很多但需要的数据和建模复杂度也上一个台阶。第二个方向是交互式修正一次生成不满意可以通过追加对话的方式让模型局部修改某个尺寸或特征而不是重新生成整个零件。第三个方向是结合设计规范比如把GB标准、ISO标准里对标准件的要求编码进数据让模型生成的零件自动符合设计标准这对工业落地很关键。我自己在尝试的方向是让模型输出时带上推理过程先说为什么选择这个建模顺序再输出命令序列。实测下来带推理过程生成的零件比直接输出命令序列的成功率高一些可能是因为中间推理token给了模型额外的计算空间。考虑到这不是主流论文里的结论只能算个人经验你也可以在项目里试试看成本很低只看会不会影响输出格式的稳定性。最后分享一个小技巧不管你是下载现成权重还是自己训练先在FreeCAD里把生成结果打开看特征树再决定要不要把它当作正式交付物。FreeCAD免费、轻量、内核对STEP解析的容错度比商业软件低如果它都能干净打开并显示合理的特征树基本可以放心地把STEP转发给工业软件做后续处理。反过来如果FreeCAD都打不开就别指望SolidWorks能救你。这个习惯帮我筛掉了大量“看起来能用、实际不能编辑”的废模型省了很多下游返工的时间。