☰
text-to-cad 实战:从自然语言到参数化三维模型的生成流程
2026/10/10 4:01:04 网站建设 项目流程

1. 从一句话到三维模型:text-to-cad 到底在解决什么问题

第一次听到 text-to-cad 这个词,我脑子里蹦出来的画面是:对着电脑说一句“给我画一个带四个安装孔的方形法兰盘”,屏幕上就自动生成一个可以导出加工的 3D 模型。这个场景放在几年前还像是科幻,但这两年随着大模型能力的提升,它已经变成了一个真实可落地的工程方向。text-to-cad,顾名思义,就是把自然语言文本转换成 CAD(计算机辅助设计)模型的技术方案。它的核心价值在于:让不懂 CAD 软件操作的人,也能通过描述需求直接得到可用的三维几何体。

我之所以对这个方向特别感兴趣,是因为在实际工作中见过太多这样的场景:一个机械工程师想快速验证某个结构想法,却要花半小时在软件里画草图、拉伸、打孔;一个产品经理拿到客户的口头需求,想先出个粗略的三维示意,却因为不会用专业工具而卡住。text-to-cad 要解决的,正是这种“想法到模型”之间的效率断层。它适合的人群很明确:有一定工程背景但想提升建模效率的从业者、做快速原型验证的开发者、以及想探索 AI 辅助设计边界的技术爱好者。

需要先说明的是,text-to-cad 目前并不是要替代专业 CAD 软件,而是作为一种“前置快速生成”的手段存在。它生成的模型通常需要后续在专业软件里做细节修正和工程标注。理解这一点很关键,否则容易对它产生不切实际的期待。接下来我会从整体设计思路、核心技术细节、实操流程和常见问题几个维度,把这个方向拆开讲透。

2. 整体设计思路:为什么这样搭架构

2.1 三种主流技术路线的取舍逻辑

做 text-to-cad,摆在面前的第一道选择题就是技术路线。我梳理下来,目前主流方案大致分三类,每类都有自己的适用边界。

第一类是基于代码生成的方式。核心思路是让大模型输出一段参数化建模脚本,比如 OpenSCAD 或 CadQuery 的代码,然后由这些脚本引擎执行生成三维模型。这条路线的优势非常明显:模型是参数化的,尺寸精确可控,生成结果可复现,而且代码本身就是一种“设计意图的文档”。缺点是模型的表现力受限于脚本引擎的能力,复杂曲面造型会比较吃力。

第二类是基于序列化建模操作的方式。把 CAD 操作抽象成一系列指令序列,比如“创建草图-绘制矩形-拉伸-打孔”,让模型预测这个操作序列,再在 CAD 内核里回放执行。这种方式更贴近真实建模流程,但对操作序列的表示和预测精度要求很高,训练数据也更难获取。

第三类是基于隐式表示或网格生成的方式。直接输出点云、体素或网格模型,绕开参数化建模的复杂性。这种方式生成速度快、造型自由度高,但缺点是模型不可参数化编辑,精度也往往达不到工程要求。

我在实际选型时的判断标准是这样的:如果你的目标是做功能性零件,比如支架、法兰、连接件这类以尺寸精度为核心的模型,优先选代码生成路线;如果目标是做概念造型,比如外观曲面、艺术化结构,网格生成路线更合适;序列化操作路线则适合那些需要完整保留建模历史、后续要频繁修改参数的场景。对大多数入门者来说,我建议从代码生成路线切入,因为它的技术栈最清晰,调试也最直观。

2.2 为什么参数化是绕不开的核心

很多人一开始会想:直接生成一个网格模型不就行了吗,为什么要费劲搞参数化?这个问题我在项目初期也纠结过。后来想明白了:CAD 的本质不是“画出一个形状”,而是“定义一组约束关系”。一个孔的位置不是固定的坐标,而是相对于某个基准面的偏移量;一个圆角的大小不是绝对值,而是和板厚关联的参数。这种参数化能力,才是 CAD 区别于普通三维建模的地方。

text-to-cad 如果只生成一个静态网格,那它本质上只是个“三维画图工具”,价值有限。只有当它生成的模型带有参数化结构,用户后续能改尺寸、调位置、加特征,它才真正融入了设计工作流。这也是我坚持选择代码生成路线的根本原因——OpenSCAD 和 CadQuery 这类工具天生就是参数化的,模型里的每个尺寸都可以是变量,改一个数字整个模型自动更新。

提示:如果你只是想快速看个形状,网格生成路线确实更快。但只要涉及后续修改和工程出图,参数化路线是唯一选择,前期多花的时间会在后期成倍省回来。

2.3 大模型在其中的角色定位

搞清楚大模型在 text-to-cad 里到底干什么,能避免很多方向性错误。它不是“理解三维空间”的,它做的是自然语言到结构化代码的翻译。也就是说,模型需要把“一个长宽各 50 毫米、厚 5 毫米的方板,四角各有一个直径 4 毫米的孔”这样的描述,翻译成一段带有正确变量和函数调用的建模代码。

这个定位决定了几个关键设计点。首先,提示词工程极其重要,因为模型需要足够的上下文才能生成正确的代码结构。其次,需要给模型提供清晰的代码模板和示例,让它知道目标代码长什么样。最后,必须有一套验证机制,因为模型生成的代码不一定能跑通,也不一定符合几何逻辑。我在实践中发现,把大模型当成一个“懂建模语法的翻译官”而不是“懂设计的工程师”,心态会稳很多,对它的输出预期也更合理。

3. 核心细节解析:从文本到模型的关键环节

3.1 提示词设计:怎么把话说清楚

提示词的质量直接决定生成结果的质量。我踩过的最大坑就是:以为随便说一句“画个盒子”就能得到想要的东西。实际上,模型需要的是结构化、带尺寸、带约束关系的描述。经过反复试验,我总结出一个比较稳的提示词模板,包含以下几个要素。

  • 几何类型:明确是立方体、圆柱、法兰、支架还是其他基本体或组合体。
  • 关键尺寸:长宽高、直径、厚度,单位统一用毫米。
  • 特征描述:孔、槽、圆角、倒角的位置和尺寸。
  • 约束关系:哪些特征是对称的,哪些是相对于某个面定位的。
  • 输出格式:明确要求输出 OpenSCAD 或 CadQuery 代码。

举个例子,与其说“做一个安装板”,不如说“创建一个长 80 毫米、宽 60 毫米、厚 6 毫米的矩形板,四个角各有一个直径 5 毫米的安装孔,孔中心距离板边缘各 10 毫米,输出 OpenSCAD 代码”。后者的生成成功率比前者高出好几倍。这个道理其实很朴素:你给的信息越精确,模型需要“猜”的东西就越少,出错概率自然就低。

3.2 代码模板与约束注入

光靠提示词还不够,我习惯在系统提示里注入一套代码模板和硬性约束。这套模板定义了变量命名规范、单位约定、以及常用的建模函数封装。比如我会预先定义好plate_width、plate_length、hole_diameter这类变量名,让模型生成的代码风格统一,后续维护起来也方便。

约束注入则是把一些工程常识写进提示里。比如“所有尺寸单位为毫米”“孔必须完全贯穿实体”“圆角半径不得超过最小板厚的一半”。这些约束看起来琐碎,但能挡掉大量低级错误。我印象很深的一次,模型生成了一个圆角半径 10 毫米、板厚只有 6 毫米的模型,结果圆角直接把板“吃穿”了。自从加了圆角约束,这类问题再没出现过。

3.3 几何有效性校验

模型生成的代码能跑通,不代表生成的几何体是有效的。我遇到过好几次代码执行成功,但导出的模型是空心的、自相交的、或者根本就是个空文件。所以必须加一层几何校验。我的做法是:代码执行后,检查生成实体的包围盒尺寸是否和预期一致,检查体积是否大于零,检查是否存在非流形边。

这套校验逻辑用 Python 写起来不复杂,核心就是调用建模引擎的 API 读取模型属性,然后和预期值做比对。如果校验不通过,就把错误信息反馈给大模型,让它重新生成。这个“生成-校验-反馈-重生成”的循环,是整个系统稳定性的关键。我一般设置最多重试三次,三次还不行就报错让用户介入,避免无限循环浪费资源。

校验项检查方法不通过的常见原因
包围盒尺寸读取模型 bounding box 与预期比对尺寸单位理解错误
实体体积计算体积是否大于零布尔运算失败导致空实体
流形性检查是否存在非流形边特征重叠或自相交
孔特征统计圆柱面数量孔被误删或位置错误

3.4 参数提取与变量化处理

这一步是让模型真正“可用”的关键。模型生成的代码里,尺寸往往是硬编码的数字。我会在生成后做一次参数提取,把关键尺寸抽成变量,放在代码顶部集中管理。这样用户拿到代码后,改一个变量就能调整整个模型,不用去代码里到处找数字。

参数提取的实现方式有两种。一种是让大模型在生成时就使用变量,另一种是生成后做静态分析自动提取。我倾向于前者,因为在提示词里明确要求“所有关键尺寸必须定义为顶部变量”,模型基本都能遵守。后一种方式作为兜底,用正则匹配数字然后人工确认。两种方式结合,参数化覆盖率能到九成以上。

4. 实操过程:手把手搭建一个可用的生成流程

4.1 环境准备与依赖安装

先把基础环境搭起来。我用的技术栈是 Python 加 OpenSCAD,原因是 OpenSCAD 的脚本语法简单,大模型生成起来准确率高,而且它自带命令行执行能力,方便自动化。CadQuery 功能更强但语法复杂,适合进阶后再切换。

# 创建虚拟环境 python -m venv text2cad_env source text2cad_env/bin/activate # 安装核心依赖 pip install openai trimesh numpy

OpenSCAD 需要单独安装,装完后确认命令行可用。trimesh用来做几何校验,numpy处理数值计算。大模型接口这里用通用的调用方式,具体用哪家根据自己情况定,关键是保证能稳定返回代码文本。

注意:OpenSCAD 的命令行参数在不同版本间有差异,装完后先用一个简单脚本测试openscad -o output.stl input.scad能否正常执行,确认无误再往下走。

4.2 完整生成流程的代码实现

整个流程分五步:接收文本、调用模型生成代码、执行代码、校验几何、返回结果。我把核心逻辑写成一个函数,方便复用。

import subprocess import trimesh import os def generate_cad_from_text(user_input, max_retries=3): system_prompt = """你是一个 OpenSCAD 代码生成助手。 要求: 1. 所有尺寸单位为毫米 2. 关键尺寸必须定义为顶部变量 3. 只输出代码,不要解释 4. 圆角半径不超过最小板厚的一半 """ for attempt in range(max_retries): code = call_llm(system_prompt, user_input) scad_path = "temp_model.scad" stl_path = "temp_model.stl" with open(scad_path, "w") as f: f.write(code) result = subprocess.run( ["openscad", "-o", stl_path, scad_path], capture_output=True, text=True ) if result.returncode != 0: user_input = f"上次代码执行报错:{result.stderr},请修正" continue mesh = trimesh.load(stl_path) if mesh.volume <= 0: user_input = "生成的模型体积为零,请检查布尔运算" continue return code, stl_path raise RuntimeError("多次生成均失败,请检查输入描述")

这段代码的核心在于那个重试循环。每次失败都把错误信息拼回输入,让模型带着“上次错在哪”的上下文重新生成。实测下来,第一次成功率大概六成,加上重试能到九成以上。call_llm是调用大模型的封装函数,根据自己用的接口实现即可。

4.3 参数计算的实际案例

拿一个具体例子走一遍。用户输入:“做一个 100x80x8 毫米的底板,四角各有一个 M6 的沉头孔,孔中心距边缘 12 毫米。”

模型生成的代码大致是这样:

// 参数定义 plate_length = 100; plate_width = 80; plate_thickness = 8; hole_dia = 6.5; // M6 通孔标准间隙 counterbore_dia = 11; // 沉头直径 counterbore_depth = 4; edge_offset = 12; difference() { cube([plate_length, plate_width, plate_thickness], center=true); for (x = [-1, 1], y = [-1, 1]) { translate([ x * (plate_length/2 - edge_offset), y * (plate_width/2 - edge_offset), 0 ]) { cylinder(h=plate_thickness+2, d=hole_dia, center=true); translate([0, 0, plate_thickness/2 - counterbore_depth/2]) cylinder(h=counterbore_depth+1, d=counterbore_dia, center=true); } } }

这里有几个细节值得说。M6 螺栓的通孔直径取 6.5 毫米而不是 6 毫米,这是机械设计的常规做法,留出装配间隙。沉头直径 11 毫米对应 M6 沉头螺钉的标准头部尺寸。孔的位置用for循环加正负号生成四个对称位置,比写四遍translate简洁得多。这些细节模型不一定每次都能处理对,所以我在提示词里会补充“M6 通孔按 6.5 毫米生成”这类工程约定。

4.4 结果导出与后续处理

生成 STL 后,如果只是看形状,直接扔进任意三维查看器就行。但如果要进入正式设计流程,我建议把 OpenSCAD 源码也一并保留,因为 STL 是网格格式,丢失了参数信息。后续要改尺寸,改源码重新导出即可。

如果需要更高精度的工程模型,可以把 OpenSCAD 代码转成 STEP 格式。这需要借助 FreeCAD 的命令行工具做格式转换。转换后的 STEP 文件可以导入主流 CAD 软件,继续做工程标注和装配设计。这一步我一般只在模型确认可用后才做,避免在中间产物上浪费时间。

5. 常见问题与排查技巧实录

5.1 生成代码报错怎么快速定位

代码报错是最常见的问题,我整理了一张速查表,覆盖八成以上的报错场景。

报错信息关键词根本原因解决方向
syntax error括号或分号缺失检查代码块配对
unknown variable变量未定义就使用确认变量声明顺序
child object required布尔运算参数为空检查 difference 内是否有实体
CGAL error几何运算失败简化特征或调整尺寸
empty geometry结果为空实体检查减运算是否减没了

排查时我的习惯是:先把生成的代码单独在 OpenSCAD 图形界面里跑一遍,看报错行号,比在命令行里盲猜快得多。图形界面会高亮出错位置,定位效率高很多。

5.2 模型尺寸不对的排查思路

尺寸偏差通常有三个来源。第一是单位理解错误,模型把毫米当成了厘米。第二是坐标系理解偏差,center=true和默认居中的区别会导致位置偏移。第三是特征叠加时的尺寸累积误差。

我的排查方法是:生成后先量包围盒,和预期尺寸比对。如果整体差 10 倍,基本是单位问题。如果位置偏了但尺寸对,检查translate的基准点。如果局部特征尺寸不对,单独把那个特征的代码拎出来测试。这个“先整体后局部”的排查顺序,能快速缩小问题范围。

5.3 复杂模型生成失败的应对策略

描述越复杂,生成成功率越低,这是必然的。我的应对策略是分而治之:把复杂模型拆成几个简单部件,分别生成,最后用布尔运算组合。比如一个带支架的盒子,先单独生成盒子,再单独生成支架,最后合并。

另一个技巧是逐步细化。先让模型生成一个粗略版本,确认整体结构对了,再在提示词里逐步加细节。一次加一个特征,每次生成后验证。这样虽然步骤多了,但每步都可控,总体成功率反而更高。我试过一次性描述一个带十几个特征的复杂零件,失败率极高;拆成五步后,每步都顺利通过。

提示:复杂模型不要指望一次生成到位。把大模型当成一个需要明确指令的助手,而不是能读心的大师,分步骤引导效果最好。

5.4 提升生成质量的几个实操心得

第一个心得是给示例。在系统提示里放一两个高质量的代码示例,模型生成的质量会明显提升。这相当于给它打了个样,它知道该往什么风格上靠。

第二个心得是固定变量命名。我要求所有生成的代码都用统一的变量命名规范,比如plate_length、hole_dia这种。命名统一后,后续做参数提取和批量修改都方便很多。

第三个心得是保留生成历史。每次生成的代码和对应的输入描述都存下来,积累一段时间后就是一份高质量的微调数据集。我攒了几百条后,用这些数据做了简单的提示词优化,生成成功率又上了一个台阶。

第四个心得是人工兜底。再好的自动化也有失败的时候,所以流程里一定要留人工介入的口子。我的做法是重试三次失败后,把最后一次的代码和错误信息展示给用户,让用户决定是修改描述重试,还是手动改代码。这个兜底机制让整个流程的可用性提升了很多。

6. 这个方向后续还能怎么玩

把基础流程跑通后,我陆续尝试了几个扩展方向,效果都还不错。一个是批量生成,把一份参数表读进来,批量生成一系列尺寸不同的零件,适合做标准件库。另一个是反向解析,给一个现有模型,让模型反推出生成它的代码,用于理解别人的设计。还有一个是多轮对话式修改,生成初版后,用户继续说“把孔改大一点”“加个圆角”,模型在上一版代码基础上增量修改,体验比每次重新描述好很多。

这些扩展方向的共同点是:都建立在基础流程稳定可靠的前提上。所以我的建议是,先把单次生成的准确率打磨到位,再考虑这些花活。基础不牢,扩展越多问题越多。我在实际项目里的体会是,text-to-cad 这个方向技术门槛不算特别高,但工程细节特别多,每一个环节的打磨都需要耐心。把提示词、校验、重试这三件事做扎实,基本就能得到一个可用的系统了。

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

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

立即咨询