1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个说法我脑子里蹦出来的画面是对着电脑敲一句“给我画一个 80×60×10mm、四角带 M4 沉头孔的安装板”然后 CAD 里就自动出现一个可以继续编辑的实体。这个场景放在五年前还像科幻但这两年随着大模型在代码生成和结构化输出上的成熟它已经变成了一个可以自己动手搭出来的工程链路。所谓 text-to-cad本质上是把自然语言描述翻译成参数化几何数据再输出成 CAD 能识别的格式比如 STEP、STL、GLB 这些。它解决的核心痛点很直接大量重复性的、结构相似的零件建模占用了工程师太多时间而这些零件的几何逻辑其实是可以被“描述”出来的。我之所以对这个方向感兴趣是因为在实际工作中接触过太多“改一个尺寸就要重新画一遍”的场景。比如做非标设备的朋友客户今天要 200mm 长的支架明天要 260mm 的结构完全一样只是拉伸长度变了。这种活儿用传统 CAD 手动改十分钟一个一天下来也改不了几个还容易出错。text-to-cad 的思路就是把这部分工作交给程序你用文字描述清楚几何约束和尺寸程序生成对应的模型文件你拿去直接装配或者打印。它适合的人群其实比想象中广——不只是程序员机械工程师、产品经理、甚至做创客项目的手工爱好者只要你能把需求说清楚就有机会用上这套流程。不过这里要先泼一盆冷水text-to-cad 目前不是“说一句话就给你一个完美复杂的装配体”。它能稳定处理的是参数化明确、几何逻辑清晰的零件比如板类、轴类、法兰、支架、简单的壳体。你要是让它生成一个涡轮叶片或者复杂的自由曲面那基本是自找麻烦。理解这个边界比盲目追求“全自动”重要得多。下面我会从整体设计思路开始把这套东西拆开讲清楚包括格式怎么选、代码怎么写、坑在哪里。2. 整体设计与技术选型为什么是 STEP、STL、GLB 三件套2.1 三种格式各自的定位与选择逻辑做 text-to-cad绕不开的第一个问题就是生成的模型用什么格式存我见过不少人一上来就纠结“哪个格式最好”其实这个问题问错了正确的问法是“这个模型接下来要拿去干什么”。STEP、STL、GLB 这三个格式分别对应三种完全不同的下游用途选错了不是不能用而是会多走很多弯路。STEP是参数化边界表示B-rep格式它保留的是精确的几何定义——面、边、圆柱面、平面这些数学描述都在。这意味着你拿到 STEP 文件后可以在 SolidWorks、中望 CAD、Fusion 360 这些软件里继续编辑改尺寸、加特征都没问题。它是工程交付的标准格式也是 text-to-cad 最应该优先输出的格式。缺点是文件结构复杂生成它需要真正的几何内核不能靠拼三角形糊弄。STL是三角网格格式说白了就是用一堆小三角形逼近模型表面。它没有参数、没有特征历史就是一个“壳”。但它的优势在于通用性极强——3D 打印切片软件、OpenGL 渲染、Qt 里的三维显示几乎都吃 STL。热搜词里出现的 “qopengl 加载 stl”“qt5.15.2 读取 stl 模拟六轴机械臂”说的就是这种用法把 STL 当成纯几何数据来渲染和仿真。STL 的坑在于它是“死”的你想改个孔径只能重新生成没法在 STL 上直接编辑。GLB是 glTF 的二进制版本主打轻量和 Web 友好。它带材质、带颜色适合在浏览器里做可视化展示比如给客户看一个产品的三维预览。GLB 同样基于网格精度不如 STEP但胜在加载快、体积小。我把三者的差异整理成一张表方便你对照格式几何类型可否参数化编辑典型用途生成难度STEPB-rep 精确几何可以工程交付、后续建模高需几何内核STL三角网格不可以3D 打印、渲染、仿真中需网格化GLB三角网格材质不可以Web 展示、可视化中需网格化材质我的建议是主输出 STEP按需派生 STL 和 GLB。因为 STEP 是信息最全的从 STEP 可以转出 STL 和 GLB反过来则不行。这就像拍照存 RAW 再导出 JPG而不是只存 JPG。2.2 生成链路的核心架构整套 text-to-cad 的链路我把它拆成四层语义解析层、参数建模层、几何生成层、格式导出层。这个分层不是为了好看而是为了每一层都能单独调试和替换。语义解析层负责把自然语言变成结构化参数。比如“一块 100×50×5 的板中心一个直径 10 的通孔”解析出来应该是{type: plate, length: 100, width: 50, thickness: 5, holes: [{x: 50, y: 25, d: 10}]}这样的 JSON。这一层现在用大模型做最合适因为它能处理各种口语化表达。但要注意不能让大模型直接生成几何代码那样出错率极高必须让它只输出结构化参数几何生成交给确定性的程序。参数建模层拿到 JSON 后做参数校验和补全。比如检查尺寸是否为正、孔是否超出边界、有没有缺省值需要填。这一层是纯逻辑用任何语言写都行Python 最顺手。几何生成层是真正的硬骨头它调用几何内核把参数变成实体。可选的内核有 OpenCASCADE开源、功能全、CadQuery基于 OCC 的 Python 封装写起来像搭积木、build123dCadQuery 的进化版API 更现代。我实测下来CadQuery 是上手最快的几行代码就能出一个带孔的板而且直接支持导出 STEP 和 STL。格式导出层负责把内核里的实体写成文件。CadQuery 的exporters模块直接支持 STEP、STLGLB 需要额外用 trimesh 之类的库转一道。提示不要试图用大模型直接“写 OpenCASCADE 的 C 代码”那条路我试过生成的代码十有八九编译不过调试成本远超收益。让模型输出参数、让程序生成几何才是稳的路子。2.3 为什么不用纯网格方案有人会问既然 STL 和 GLB 都是网格那我直接用代码拼三角形不就行了何必上几何内核这个问题我认真想过结论是简单零件可以稍微复杂一点就崩。拼三角形意味着你要自己算每个面的顶点坐标、法向量、三角形索引。一个带圆孔的板孔壁是圆柱面用三角形逼近需要几十上百个三角形你还得保证它们首尾相接、法向一致。一旦涉及倒角、圆角、布尔运算手工拼网格的工作量会指数级上升而且极易出现破面、法向翻转这些恶心问题。热搜里 “3dsmax2012 修复 stl 模型的 uv” 这种需求本质上就是在给网格模型的先天缺陷擦屁股。几何内核的价值在于它用数学方式描述曲面布尔运算、倒角这些操作由内核保证正确性你只需要关心“要什么形状”不用关心“三角形怎么摆”。所以只要你的目标是工程可用的模型几何内核是绕不过去的。3. 核心细节解析从自然语言到参数化几何的关键环节3.1 语义解析怎么让大模型稳定输出结构化参数这一层是整个链路里最“玄”的部分因为自然语言太灵活了。同样一个需求有人写“100 长 50 宽 5 厚的板”有人写“一块板长宽高分别是 100、50、5”还有人写“板子 100×50×5”。如果直接让模型生成代码它会给你四种不同的写法其中两种可能跑不通。我的做法是定义一套严格的 JSON Schema然后通过提示词约束模型只能输出符合这个 Schema 的 JSON。Schema 里把常用零件类型板、圆柱、法兰、支架和它们的参数都定义好模型的任务就变成了“填空”而不是“自由发挥”。这样稳定性会高很多。举个实际的例子我用的板类零件 Schema 大致是这样{ type: plate, length: 100, width: 50, thickness: 5, holes: [ {x: 50, y: 25, diameter: 10, depth: through} ], fillets: [ {edge: vertical, radius: 3} ] }模型解析“一块 100×50×5 的板中心一个直径 10 的通孔四个角倒 R3 圆角”时就应该输出上面这个结构。注意depth: through表示通孔如果是盲孔就写具体深度数值。这种约定要提前在提示词里说清楚。注意一定要在提示词里明确“尺寸单位统一为毫米”“坐标原点默认在板的左下角底面”“孔位坐标以原点为基准”。这些默认约定不写清楚模型每次的理解都不一样生成出来的模型位置会飘。3.2 参数校验别让错误参数流到几何层模型输出的 JSON 不能直接信必须过一遍校验。我踩过的坑包括模型给出负数的厚度、孔的直径比板还宽、圆角半径大于板厚的一半。这些参数如果直接喂给几何内核轻则报错重则生成一个自相交的畸形实体你还得花时间排查。校验逻辑其实不复杂就是一堆 if-else但必须写全。我通常检查这几类数值合法性所有尺寸必须大于 0圆角半径必须小于相邻边长的最小值。几何可行性孔必须完全落在板面内孔与孔之间不能重叠孔壁不能和板边相交。逻辑一致性如果声明了倒角必须指定是哪条边如果声明了阵列孔必须给出阵列方向和间距。校验不通过时不要直接抛异常给用户而是把错误信息回传给大模型让它重新解析。这个“解析—校验—反馈—重解析”的循环能把成功率从六七成拉到九成以上。3.3 几何生成CadQuery 实操要点几何生成层我用 CadQuery 最多这里展开讲讲它的几个关键用法。CadQuery 的核心思想是“链式调用”你从一个基础形状出发不断叠加操作最后得到一个实体。生成一块带孔和圆角的板代码大概长这样import cadquery as cq length, width, thickness 100, 50, 5 hole_d 10 fillet_r 3 # 创建基础板 plate cq.Workplane(XY).box(length, width, thickness) # 打中心通孔 plate plate.faces(Z).workplane().hole(hole_d) # 四角倒圆角 plate plate.edges(|Z).fillet(fillet_r) # 导出 cq.exporters.export(plate, plate.step) cq.exporters.export(plate, plate.stl)这段代码里几个点值得说。cq.Workplane(XY)是在 XY 平面上建立工作平面box直接生成一个长方体。faces(Z)是选择朝上的那个面workplane()把工作平面移到这个面上hole就在这个面上打孔。edges(|Z)是选择所有平行于 Z 轴的边也就是四条竖边fillet给它们倒圆角。实操心得faces和edges的选择器语法是 CadQuery 的精髓也是最容易出错的地方。Z表示法向朝 Z 正方向的面|Z表示平行于 Z 轴的边。选择器写错操作就会作用在错误的几何元素上结果往往莫名其妙。建议每做一步操作就导出看一眼别一口气写完再调。3.4 格式导出的细节差异STEP 导出基本无脑cq.exporters.export(shape, xxx.step)就行。STL 导出要注意网格精度默认精度有时候太粗圆柱面看起来像多边形。可以在导出时指定公差cq.exporters.export(plate, plate.stl, tolerance0.01, angularTolerance0.1)tolerance是线性公差越小网格越密angularTolerance是角度公差控制曲面细分程度。这两个值调小文件会变大但曲面更光滑。做 3D 打印的话0.01mm 的线性公差足够了。GLB 导出 CadQuery 不直接支持我的做法是先把实体导出成 STL再用 trimesh 读进来转成 GLBimport trimesh mesh trimesh.load(plate.stl) mesh.export(plate.glb)trimesh 会自动处理材质和场景结构导出的 GLB 可以直接丢进 Three.js 或者 model-viewer 里展示。4. 完整实操流程从零搭一个 text-to-cad 小工具4.1 环境准备与依赖安装先把环境搭起来。我用的组合是 Python 3.10 CadQuery trimesh 一个大模型 API。CadQuery 的安装稍微有点讲究推荐用 conda 装pip 装有时候会因为 OCC 的二进制依赖出问题。conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install trimesh openai装完之后跑一句import cadquery验证一下不报错就说明几何内核就位了。这一步如果卡住多半是 OCC 的库没链接上conda 渠道的包一般不会有这个问题。4.2 提示词设计与参数模板提示词我分成两部分系统提示词定义角色和输出格式用户输入就是那句自然语言描述。系统提示词里我会把 Schema、单位约定、默认值都写进去。下面是我实际用的一版精简提示词你是一个 CAD 参数解析器。用户会用自然语言描述一个零件 你需要输出符合以下 JSON Schema 的结构化参数。 支持的零件类型plate板、cylinder圆柱、flange法兰。 plate 参数 - length, width, thickness数值单位毫米必填 - holes数组每个元素含 x, y, diameter, depththrough 或数值 - fillets数组每个元素含 edgevertical 或 horizontalradius 坐标约定原点在板左下角底面X 向右Y 向后Z 向上。 所有尺寸为正数。无法解析的字段留空不要编造。这套提示词的关键在于把自由度压到最低。模型不需要理解几何只需要做“文本到 JSON”的映射任务简单了准确率自然上去。4.3 主流程代码实现主流程就是一个循环拿用户输入、调模型解析、校验参数、生成几何、导出文件。核心代码结构如下import json import cadquery as cq def parse_text(user_input): # 调用大模型返回 JSON 字符串 response call_llm(SYSTEM_PROMPT, user_input) return json.loads(response) def validate(params): if params[type] ! plate: raise ValueError(暂不支持该类型) if params[length] 0 or params[width] 0 or params[thickness] 0: raise ValueError(尺寸必须为正) for h in params.get(holes, []): if h[x] 0 or h[x] params[length]: raise ValueError(孔位超出板面) return True def build_plate(params): plate cq.Workplane(XY).box( params[length], params[width], params[thickness] ) for h in params.get(holes, []): plate (plate.faces(Z).workplane() .center(-params[length]/2 h[x], -params[width]/2 h[y]) .hole(h[diameter])) for f in params.get(fillets, []): if f[edge] vertical: plate plate.edges(|Z).fillet(f[radius]) return plate def run(user_input): params parse_text(user_input) validate(params) shape build_plate(params) cq.exporters.export(shape, output.step) cq.exporters.export(shape, output.stl, tolerance0.01) print(生成完成)注意build_plate里打孔时的坐标换算。CadQuery 的workplane()默认把原点放在面的中心而我们的参数约定原点在左下角所以要减去长宽的一半做偏移。这个细节不注意孔位会整体偏半个板。4.4 参数计算实例一个带阵列孔的支架光说代码不够直观拿一个实际需求走一遍。假设用户输入“一块 120×80×6 的板四角各一个 M4 沉头孔孔中心距边 10mm板中间开一个 40×20 的方孔。”解析出来的参数应该是{ type: plate, length: 120, width: 80, thickness: 6, holes: [ {x: 10, y: 10, diameter: 4.5, depth: through}, {x: 110, y: 10, diameter: 4.5, depth: through}, {x: 10, y: 70, diameter: 4.5, depth: through}, {x: 110, y: 70, diameter: 4.5, depth: through} ], slots: [ {x: 60, y: 40, width: 40, height: 20} ] }这里 M4 沉头孔的通孔直径取 4.5mm是标准沉头螺钉的过孔尺寸。孔位坐标按“距边 10mm”算左下角那个就是 (10, 10)右上角是 (120-10, 80-10) (110, 70)。方孔中心在板中心 (60, 40)尺寸 40×20。生成时方孔用rect加cutThruAll实现plate (plate.faces(Z).workplane() .center(0, 0) .rect(40, 20) .cutThruAll())注意cutThruAll是穿透切割适合通孔。如果是盲槽要用cutBlind(depth)。另外方孔的四角默认是尖角实际加工中会有刀具半径如果需要圆角要额外加fillet。4.5 批量生成与参数化变体text-to-cad 真正体现价值的地方是批量生成。比如你要做一系列长度递增的支架长度从 100 到 200步进 10其他参数不变。用传统 CAD 你得改十次用这套流程就是一个循环for length in range(100, 210, 10): params base_params.copy() params[length] length shape build_plate(params) cq.exporters.export(shape, fbracket_{length}.step)十秒钟生成十一个模型每个都是可编辑的 STEP。这种效率提升在非标设计里是实打实的。热搜里 “python 批量对 cad 修改” 说的就是这类需求只不过传统做法是操作 CAD 软件的 API而 text-to-cad 是从参数层面直接生成更干净。5. 常见问题与排查技巧实录5.1 几何生成阶段的典型报错这一阶段的问题最集中我整理了一张速查表报错现象可能原因解决办法布尔运算失败实体自相交或面重合检查孔位是否在板边圆角是否过大圆角报错半径大于相邻边一半减小半径或改倒角导出 STEP 为空实体未闭合检查是否所有操作都作用在实体上STL 曲面粗糙网格公差太大调小 tolerance 和 angularTolerance孔位偏移坐标系约定不一致确认 workplane 原点位置布尔运算失败是最常见的。有一次我生成一个带多个孔的板孔与孔之间距离太近孔壁相交内核直接报错。排查了半天才发现是两个孔的中心距小于孔径之和。这种问题在参数校验阶段就该拦住所以校验逻辑一定要包含“孔间距检查”。5.2 大模型解析不稳定的应对模型解析偶尔会抽风比如把“厚度 5”理解成“厚度 50”或者漏掉某个孔。我的应对策略有三条第一在提示词里给示例。给一两个输入输出的例子模型的表现会稳定很多。这叫 few-shot实测比纯描述有效。第二加后处理校验。比如检查解析出的尺寸是否在合理范围内如果长度是 10000mm那多半是解析错了直接打回重解析。第三保留人工确认环节。对于关键零件生成前把解析出的参数展示给用户确认确认无误再生成几何。这一步多花几秒能省掉大量返工。5.3 格式转换中的坑STEP 转 STL 时如果模型有薄壁特征网格化可能会失败或者产生破面。这时候要适当放大公差或者检查薄壁厚度是否小于公差。STL 转 GLB 时trimesh 默认会合并顶点有时候会导致法向错误可以在导出时加processFalse保留原始数据。热搜里 “sw 中 stl 转 stp” 是反向操作从网格转回精确几何。这个难度比正向大得多因为网格丢失了曲面信息转出来的 STEP 是一堆碎面基本没法参数化编辑。所以我的建议始终是能保留 STEP 就保留 STEP别等到只剩 STL 了再想转回去。5.4 性能与规模化的注意事项生成单个零件很快一两秒的事。但如果你要批量生成几百个就要注意内存管理。CadQuery 的实体对象占内存不小循环里要及时释放。我的做法是每生成一批就清一次或者用多进程并行每个进程独立处理一批。另外大模型 API 调用有延迟和成本批量场景下建议先把所有自然语言描述批量解析成 JSON缓存起来再统一生成几何。这样 API 调用可以并发几何生成可以本地跑整体效率高很多。6. 应用场景延展与个人实践体会text-to-cad 这套东西我现在主要用在三个场景。第一个是非标零件的快速打样客户给个尺寸我几分钟出 STEP直接发去加工。第二个是参数化零件库的搭建把常用零件写成模板需要时改参数生成比翻标准件库还快。第三个是教学演示给学生展示“文字到模型”的完整链路比单纯讲 CAD 操作直观得多。它和传统 CAD 不是替代关系而是互补。传统 CAD 适合从零设计复杂产品需要人的空间想象和工程判断text-to-cad 适合处理那些“结构已知、只是尺寸变”的重复劳动。把这两者分清楚你就知道什么时候该用它什么时候不该用。最后分享一个我踩过的坑别指望一次提示词就完美。我最初写的提示词很简陋模型解析出来的参数十有八九要改。后来我把 Schema 写细、把约定写死、把示例加上成功率才上来。这个过程没有捷径就是不断试、不断补规则。等你把常用零件类型的解析规则都磨顺了这套工具才真正开始省时间。
阅读完成 · 觉得有帮助?