text-to-cad 实战:从自然语言到 STEP/STL/GLB 参数化建模全流程

发布时间:2026/10/8 18:48:50
text-to-cad 实战:从自然语言到 STEP/STL/GLB 参数化建模全流程 1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个说法我脑子里蹦出来的画面是对着电脑敲一句“给我画一个 80×60×20 的法兰盘中心开直径 30 的通孔四角各一个 M6 沉头孔”然后软件自己把模型建好、导出 STEP 文件。这个画面放在五年前还属于科幻但放到今天它已经是一条能跑通的技术链路了。所谓 text-to-cad本质上是把自然语言描述翻译成参数化 CAD 模型最终产出 STEP、GLB、STL 这类通用三维格式让不会建模的人也能拿到可用的三维数据。这件事的价值在哪儿我接触过不少做机械设计、钣金加工、3D 打印的朋友他们最头疼的不是建模本身而是“重复建模”。比如一批支架只是孔位和尺寸不同却要一个个手动拉伸、打孔、倒角一天下来眼睛都花了。text-to-cad 想干的就是把这部分重复劳动吃掉——你用文字描述需求程序解析成几何参数再调用建模内核生成实体最后导出成下游能直接用的格式。它适合三类人一是需要快速出原型的设计师二是想批量生成零件模型的工程师三是做 AI 制造交叉方向、想自己搭一套流程的开发者。但这里有个关键认知必须先摆正text-to-cad 不是“AI 帮你画图”这么简单它的核心难点在于“语言到几何的映射”。自然语言是模糊的、有歧义的而 CAD 几何是精确的、有拓扑约束的。你说“一个圆角”到底是 2mm 还是 R2你说“中间打个孔”孔是通孔还是盲孔这些歧义如果不在流程里解决生成的模型就是废的。所以真正能落地的 text-to-cad 方案一定是“语言解析 参数校验 几何生成 格式导出”四段式结构缺一不可。我下面要拆的这套思路是基于常见工程实践补全的一套可复现方案。它不依赖某个特定商业软件而是用 Python 生态里成熟的几何内核和格式转换库来搭。你跟着走一遍能理解 text-to-cad 的完整链路也能自己改出一个适合自己场景的版本。关键词里提到的 CAD、STEP、GLB、STL 这几个格式我会在导出环节逐个讲清楚它们的区别和适用场景避免你导错格式导致下游打不开。2. 整体架构设计为什么这样搭而不是那样搭2.1 四层架构的选型逻辑我把整个 text-to-cad 流程拆成四层输入解析层、参数建模层、几何生成层、格式导出层。这个分层不是拍脑袋定的而是根据“每一层出错后能不能独立排查”来划分的。语言解析错了你只需要改解析规则几何生成错了你只需要换内核参数。如果全揉在一起一个模型生成失败你根本不知道是那句话理解错了还是布尔运算失败了。输入解析层我选的是规则模板 关键词抽取的方案而不是直接上大语言模型。原因很实际CAD 建模对尺寸精度要求极高大语言模型输出的数值经常“看起来对但实际飘”比如你说 50mm它可能给你 50.0 也可能给你 49.8。规则模板虽然笨但胜在稳定可控。具体做法是预定义一批“句式模板”比如“长为 A 宽为 B 高为 C 的立方体”“直径 D 深度 H 的圆柱”“在 X 面上开 N 个直径 D 的孔”然后用正则和关键词匹配把数值抽出来。这套方案对固定品类的零件描述命中率很高而且调试成本低。参数建模层我选的是CadQuery。这是一个基于 Python 的参数化建模库底层用的是 OpenCASCADE 几何内核。选它而不是直接调 FreeCAD 的 GUI 脚本是因为 CadQuery 的 API 更干净链式调用写起来像在描述几何关系而且它原生支持导出 STEP 和 STL。另一个候选是 pythonocc功能更底层更强大但学习曲线陡写一个倒角可能要十几行。对于 text-to-cad 这种“快速生成”场景CadQuery 的性价比更高。几何生成层其实和参数建模层是耦合的但我单独拎出来说是因为这里要做布尔运算和拓扑校验。比如你描述“在立方体上开一个通孔”程序要先建立方体再建圆柱然后做差集运算。差集之后还要检查结果是不是有效实体——有时候圆柱和立方体只是相切布尔运算会生成非流形边这种模型导出 STL 后切片会出问题。所以这一层必须加校验不能生成完就直接导出。格式导出层要处理 STEP、GLB、STL 三种格式的转换。STEP 是精确边界表示适合后续在 CAD 软件里继续编辑STL 是三角网格适合 3D 打印和切片GLB 是 glTF 的二进制版本适合网页展示和渲染。这三种格式的导出逻辑完全不同STEP 直接由内核写出STL 需要做网格化GLB 需要把网格转成 glTF 结构。我下面会逐个给代码。2.2 为什么不用“端到端大模型直接出模型”有人会问现在不是有那种“输入文字直接输出三维模型”的 AI 吗为什么还要自己搭这套我实测过几个端到端方案问题集中在三点。第一尺寸不可控。你让它生成一个“100mm 长的支架”它生成的模型在网格空间里可能是任意尺度你得手动缩放而缩放后孔位全偏了。第二拓扑不稳定。同一个描述跑两次一次生成实体一次生成壳体下游根本没法用。第三无法参数化修改。端到端模型输出的是死网格你想把孔从 6mm 改成 8mm只能重新生成不能像参数化模型那样改一个数就更新。所以我的判断是text-to-cad 在工业场景落地必须走“参数化”路线而不是“生成式”路线。参数化路线的好处是每一步都可追溯、可修改、可校验。你描述里的每个数值都对应模型里的一个参数改参数就改模型这才是 CAD 该有的工作方式。生成式路线适合做概念草图、游戏资产但不适合做需要加工制造的零件。2.3 数据流与关键接口整个流程的数据流是这样的用户输入一段文字解析层输出一个结构化的参数字典比如{type: box_with_holes, length: 80, width: 60, height: 20, hole_dia: 6, hole_count: 4}。建模层拿到这个字典调用对应的建模函数生成 CadQuery 的 Workplane 对象。几何层对这个对象做布尔运算和校验确认是有效实体。导出层根据目标格式分别调用 STEP、STL、GLB 的导出接口。这里的关键接口是参数字典的结构设计。我建议用“类型 尺寸参数 特征参数”的三段式结构。类型决定调用哪个建模函数尺寸参数决定毛坯形状特征参数决定在毛坯上做什么操作。这样设计的好处是扩展性强——你新增一种零件类型只需要加一个建模函数和一套解析模板不用动其他层。我下面给的代码就是按这个结构写的。3. 核心细节解析语言怎么变成几何参数3.1 句式模板的设计与匹配策略语言解析这块我的做法是“模板优先关键词兜底”。先定义一批高频句式模板用正则去匹配。比如下面这几条是我在实际项目里用得最多的import re TEMPLATES [ { name: box, pattern: r长[为是]?\s*(\d(?:\.\d)?)\s*(?:mm)?[,]?\s*宽[为是]?\s*(\d(?:\.\d)?)\s*(?:mm)?[,]?\s*高[为是]?\s*(\d(?:\.\d)?), fields: [length, width, height] }, { name: cylinder, pattern: r直径\s*(\d(?:\.\d)?)\s*(?:mm)?[,]?\s*(?:高|深度|长度)\s*(\d(?:\.\d)?), fields: [diameter, height] }, { name: hole, pattern: r(\d)\s*个\s*直径\s*(\d(?:\.\d)?)\s*(?:mm)?\s*(?:的)?\s*(?:通孔|孔), fields: [count, diameter] } ]匹配的时候按顺序跑一遍把命中的字段合并到一个字典里。这里有个细节要注意数值后面的单位要允许省略。用户写“长 80 宽 60”和“长 80mm 宽 60mm”都应该能匹配。我在正则里用(?:mm)?来处理但实际项目中还要考虑“厘米”“米”的换算这个可以在解析后统一做单位归一化全部转成毫米。关键词兜底是给那些不按模板说话的用户准备的。比如用户说“帮我搞一个方块大概巴掌大中间戳个洞”这种就没法用模板匹配。我的做法是维护一个同义词表把“方块”映射到 box“圆柱”映射到 cylinder“戳个洞”映射到 hole 特征。尺寸方面“巴掌大”这种模糊描述我建议直接拒绝返回提示让用户给具体数值。在 CAD 场景里模糊尺寸是灾难宁可让用户多打几个字也不要猜。3.2 参数校验那些必须拦住的非法输入解析出参数之后不能直接拿去建模必须先过一遍校验。我踩过的坑里最常见的是尺寸为负或为零。用户可能手滑打成“长 -80”或者“直径 0”这种如果直接传给建模内核轻则报错重则生成一个无效实体导出的时候才崩排查起来很费劲。所以校验层要拦住这些def validate_params(params): errors [] for key in [length, width, height, diameter]: if key in params and params[key] 0: errors.append(f{key} 必须大于 0当前值 {params[key]}) if hole_dia in params and width in params: if params[hole_dia] params[width]: errors.append(孔径不能大于等于零件宽度) if hole_count in params and params[hole_count] 0: errors.append(孔数量不能为负) return errors除了数值合法性还要做几何可行性校验。比如你要在一个 60mm 宽的面上开 4 个直径 20mm 的孔按 2×2 排布那每个孔占 20mm两列就是 40mm加上边距60mm 可能放不下。这种校验要在建模前做算一下孔的总占位面积和零件面积的比例超过阈值就提示用户调整。我一般设的阈值是孔总面积不超过零件面的 60%留出足够的边距和壁厚。提示校验层返回的错误信息要具体不要只说“参数错误”要说“孔径 20mm 大于零件宽度 15mm请调整”。用户看到具体原因才知道怎么改。3.3 特征组合的顺序问题一个零件往往有多个特征比如“立方体 四角孔 中心沉头孔 边缘倒角”。这些特征的执行顺序会影响最终结果。我的经验是先做毛坯再做减材特征孔、槽最后做倒角和圆角。原因是倒角和圆角如果先做后续打孔可能会切到圆角面导致布尔运算失败或者生成奇怪的几何。举个例子你先给立方体做了 R5 的倒角然后在靠近边缘的位置打一个孔孔壁可能和倒角面相交生成一个非平面的孔口这种几何在导出 STL 后切片会出问题。正确的顺序是先打孔再倒角这样倒角会沿着孔口和边缘一起处理结果更干净。这个顺序在 CadQuery 里体现为链式调用的先后我下面给代码的时候会标注清楚。4. 实操过程从文字到 STEP/STL/GLB 的完整实现4.1 环境准备与依赖安装先把环境搭起来。我用的 Python 版本是 3.10CadQuery 用 pip 装就行pip install cadquery pip install trimesh pip install pygltflibCadQuery 装的时候会连带装 OpenCASCADE 的 Python 绑定这个包比较大下载慢是正常的。trimesh 用来做 STL 的网格处理和 GLB 的转换pygltflib 用来写 glTF 结构。如果你只要 STEP 和 STL其实 CadQuery 自己就能导出GLB 需要额外处理。装完之后跑一句import cadquery as cq确认没报错。如果报 OCC 相关的错大概率是 OpenCASCADE 的库没链接上这种情况在 Windows 上比较常见解决办法是装 CadQuery 的 conda 版本conda 会自动处理二进制依赖。4.2 建模函数以“带孔法兰盘”为例我拿一个典型零件来演示长 80、宽 60、高 20 的方块四角各一个直径 6 的通孔中心一个直径 30 的通孔。这个描述对应的参数字典是params { type: plate_with_holes, length: 80, width: 60, height: 20, corner_hole_dia: 6, corner_hole_count: 4, center_hole_dia: 30 }建模函数这样写import cadquery as cq def build_plate_with_holes(p): # 第一步建毛坯 plate cq.Workplane(XY).box(p[length], p[width], p[height]) # 第二步打中心通孔 plate plate.faces(Z).workplane().hole(p[center_hole_dia]) # 第三步打四角通孔 l p[length] w p[width] margin 10 # 孔中心距边缘的距离 points [ (-l/2 margin, -w/2 margin), (l/2 - margin, -w/2 margin), (-l/2 margin, w/2 - margin), (l/2 - margin, w/2 - margin) ] plate plate.faces(Z).workplane().pushPoints(points).hole(p[corner_hole_dia]) # 第四步边缘倒角 plate plate.edges(|Z).fillet(2) return plate这里有几个细节值得说。faces(Z)是选 Z 方向最高的那个面作为工作平面hole()默认是通孔如果要盲孔需要加深度参数。pushPoints()接受一个坐标列表在多个位置同时打孔比循环调用效率高。edges(|Z)是选所有平行于 Z 轴的边也就是四条竖边对它们做 R2 的圆角。注意fillet和chamfer一定要放在最后。我试过先倒角再打孔结果孔口和倒角面相交生成的实体在导出 STL 时出现了破面。后来改成先打孔后倒角问题消失。4.3 导出 STEP保留精确几何STEP 是 CAD 领域的通用交换格式它保留的是精确的边界表示BRep不是网格。这意味着你导出的 STEP 文件在 SolidWorks、UG、中望 CAD 里打开后还能继续做参数化编辑孔还是孔面还是面不会变成一堆三角片。cq.exporters.export(plate, output.step)就这一行。CadQuery 的 export 函数会根据文件扩展名自动选择导出器。STEP 导出很快因为不需要网格化。但要注意STEP 文件里不包含颜色和材质信息如果你需要带颜色的模型得用 GLB。4.4 导出 STL3D 打印和切片的标配STL 是三角网格格式它把模型表面离散成一个个三角形。3D 打印切片软件、有限元分析前处理、渲染引擎都认这个格式。导出的关键是控制网格精度cq.exporters.export( plate, output.stl, tolerance0.01, angularTolerance0.1 )tolerance是线性偏差单位是毫米值越小网格越密。angularTolerance是角度偏差单位是弧度。这两个参数决定了 STL 的文件大小和精度。我一般用 0.01mm 的线性偏差对于 80mm 的零件来说这个精度足够 3D 打印用了。如果你要导出很大的零件比如 1 米长的0.01mm 会导致文件巨大这时候可以放宽到 0.1mm。提示STL 导出后一定要用切片软件预览一下确认没有破面和法线翻转。我遇到过布尔运算生成的实体在某个面上法线反了切片软件里看起来是正常的但打印出来那个面是空的。用 trimesh 可以检查import trimesh mesh trimesh.load(output.stl) print(是否水密:, mesh.is_watertight) print(法线是否一致:, mesh.is_winding_consistent)4.5 导出 GLB网页展示和渲染用GLB 是 glTF 的二进制版本适合在网页里用 three.js 加载也适合做产品展示。CadQuery 不直接支持 GLB 导出需要先转成网格再用 trimesh 导出import trimesh # 先把 CadQuery 实体转成 trimesh 网格 mesh plate.val().tessellate(0.01) vertices, faces mesh tm trimesh.Trimesh(verticesvertices, facesfaces) # 导出 GLB tm.export(output.glb)这里tessellate的参数和 STL 的 tolerance 含义一样。trimesh 导出 GLB 的时候会自动处理法线和材质如果你需要给模型上色可以在 trimesh 里设置visual属性。三种格式的对比我整理成表格方便你选格式类型可编辑性适用场景文件大小STEP精确 BRep高可参数化编辑CAD 软件交换、后续加工中等STL三角网格低只能整体缩放3D 打印、切片、FEA较大GLB三角网格 材质低适合展示网页渲染、产品展示中等4.6 完整流程串起来把上面的步骤串成一个完整脚本import cadquery as cq import trimesh def text_to_cad(text): # 1. 解析 params parse_text(text) # 2. 校验 errors validate_params(params) if errors: return {error: errors} # 3. 建模 model build_plate_with_holes(params) # 4. 导出 cq.exporters.export(model, output.step) cq.exporters.export(model, output.stl, tolerance0.01) mesh model.val().tessellate(0.01) tm trimesh.Trimesh(verticesmesh[0], facesmesh[1]) tm.export(output.glb) return {status: ok, files: [output.step, output.stl, output.glb]}跑一遍你就能在目录下看到三个文件。STEP 拖进中望 CAD 或者 SolidWorks 能直接打开STL 拖进切片软件能直接切片GLB 拖进网页查看器能直接渲染。5. 常见问题与排查技巧实录5.1 布尔运算失败最常见也最头疼布尔运算失败是 text-to-cad 里出现频率最高的问题。表现是建模函数不报错但导出的模型是空的或者只有毛坯没有孔。原因通常是两个实体只是相切而没有真正相交。比如你打孔的时候孔的圆柱面和立方体的面刚好切在同一个位置OpenCASCADE 的布尔运算就会失败。解决办法有两个。一是让特征稍微“过切”一点比如通孔的长度比零件高度多 1mm确保圆柱完全穿透立方体。CadQuery 的hole()默认就是过切的但如果你手动建圆柱做差集就要注意这个。二是检查坐标是否对齐有时候孔的中心坐标算出来是 39.999999和面的边界 40 差了一点点这种浮点误差也会导致布尔失败。我的做法是在坐标计算后做一次 round保留 3 位小数。5.2 导出 STL 后文件巨大有人导出的 STL 动辄几百 MB切片软件打开卡死。这通常是 tolerance 设得太小。0.001mm 的精度对于 3D 打印来说完全没必要因为打印机的喷嘴直径一般是 0.4mm你网格再密也打印不出那个精度。我建议根据零件尺寸来设小于 100mm 的零件用 0.01mm100-500mm 的用 0.05mm大于 500mm 的用 0.1mm。这样文件大小能控制在几 MB 到几十 MB切片软件也能流畅打开。5.3 GLB 在网页里显示全黑GLB 导出后法线方向不对在 three.js 里渲染出来就是全黑或者只有背面可见。这是因为 tessellate 出来的网格法线可能不一致。解决办法是在 trimesh 里做一次法线修复tm.fix_normals() tm.export(output.glb)fix_normals()会统一所有面的法线方向确保朝外。如果修复后还是有问题检查一下模型是不是非水密非水密的模型法线修复可能不彻底。5.4 中文描述解析不出来正则模板对中文的标点和空格很敏感。用户可能写“长80宽60高20”也可能写“长 80 宽 60 高 20”还可能写“长为80mm宽为60mm”。我的做法是在解析前先做一次文本归一化把全角标点转半角把多个空格合并成一个把“为”“是”这类虚词统一处理。这样正则只需要处理一种格式维护成本低很多。5.5 常见问题速查表问题现象可能原因排查方法解决办法模型为空布尔运算失败检查特征是否相交让特征过切 1mmSTL 文件过大tolerance 太小查看文件大小放宽到 0.05-0.1mmGLB 全黑法线不一致用 trimesh 检查调用 fix_normals()解析失败标点或空格不统一打印归一化后的文本加文本预处理导出报错实体无效检查 is_valid()重新做布尔运算提示每次建模后都调一下model.val().isValid()确认生成的是有效实体再导出。这个检查只要几毫秒但能省掉后面大量的排查时间。6. 扩展方向这套流程还能怎么用这套 text-to-cad 流程跑通之后扩展空间比想象中大。最直接的一个方向是批量生成。你把一批零件的描述写成 CSV每行一句话程序循环解析、建模、导出一晚上能生成几百个模型。我试过用这个方式给一批钣金件生成 STEP原本手动建模要两天脚本跑了二十分钟。另一个方向是接入 Web 界面。用 FastAPI 包一层 HTTP 接口前端传文字后端返回模型文件用户下载即可。GLB 可以直接在网页里用 three.js 预览用户看到效果满意了再下载 STEP。这个链路适合做在线报价或者自助设计工具。再往深了走可以结合参数优化。比如你描述“一个尽量轻的支架”程序可以自动调整壁厚和孔位用有限元做几次迭代找到一个满足强度要求的最轻方案。这部分就涉及到优化算法和仿真接口复杂度高一个量级但原理上是在现有流程上加一层循环。我个人在实际操作中的体会是text-to-cad 的瓶颈不在建模而在语言解析的鲁棒性。你把解析层做扎实了后面都是水到渠成的事。解析层的关键是“宁可拒绝不要猜”遇到模糊描述直接返回错误让用户补充比生成一个错误的模型再让用户去改要高效得多。这个原则我在多个项目里验证过确实能省掉大量返工。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询