
1. 从一段文字到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个词很多人脑子里蹦出来的画面可能是对着电脑敲一句话屏幕上就自动长出一个三维零件。这个理解方向没错但真正落地到工程场景里它要解决的问题比“炫技”实在得多——把自然语言描述快速转化为可编辑、可制造的 CAD 模型并输出 STEP、GLB、STL 这类通用格式。我接触这个方向最初是因为一个很具体的痛点手头有一批非标零件的建模需求每次都要在 CAD 软件里从草图开始画拉伸、倒角、打孔一套流程下来简单件也要十几分钟。如果需求方只给一句“一个 80×60×10 的底板四角开 M6 沉头孔”我完全可以用脚本或者生成式工具先把毛坯建出来再手动微调。text-to-cad 的价值就在这里它不是要取代工程师而是把“从零画第一版”这个最耗时的环节压缩掉。它适合谁我梳理了一下大概三类人最用得上。第一类是机械设计工程师日常有大量重复性结构件建模需求想用参数化或生成式方式提速。第二类是产品经理和工业设计从业者脑子里有概念但不会用专业 CAD想快速把想法变成可视化的三维模型去沟通。第三类是做 3D 打印和手办模型的玩家需要把文字描述转成 STL 直接切片打印。这三类人的共同点是要的是结果模型而不是建模过程本身。从技术链路看text-to-cad 通常包含几个关键环节自然语言解析、几何参数提取、实体建模内核调用、格式导出。热搜词里出现的 STEP、GLB、STL正好对应了三种典型输出场景——STEP 用于工程制造和跨软件交换GLB 用于网页和 AR 展示STL 用于 3D 打印。理解这三者的差异是玩转 text-to-cad 的基本功。提示text-to-cad 目前更适合生成“规则几何体”和“参数化结构”比如板件、支架、法兰、齿轮毛坯。对于自由曲面、复杂有机形态生成结果往往需要大量后期修整不要抱不切实际的期待。2. 核心思路拆解为什么是“文本→参数→实体”这条链路2.1 直接生成网格 vs 生成参数化实体差别在哪市面上不少“文字生成 3D”的工具底层走的是网格生成路线用大模型直接输出顶点和面片数据得到 OBJ 或 GLB。这条路线的优点是视觉效果好适合做展示缺点是模型没有特征历史没法参数化修改。你拿到一个 GLB想改个孔径只能重新生成或者手动编辑网格工程上基本不可用。text-to-cad 走的是另一条路先把文本解析成结构化参数再调用几何内核生成 B-rep 实体。B-rep 是边界表示法的缩写简单说就是用数学曲面精确描述实体的边界。这样生成的模型每个面、每条边都是精确的可以导出 STEP可以在 SolidWorks、中望 CAD 这类软件里继续编辑特征。打个比方网格模型像一张雕塑照片好看但改不动参数化实体像一份带尺寸的施工图随时能改。我实测下来的感受是如果你的目标是制造、装配、出工程图必须选参数化实体路线如果只是做视觉展示或 3D 打印摆件网格路线更省事。text-to-cad 这个标题下的工具主流方向是前者所以 STEP 导出能力是核心指标。2.2 自然语言到几何参数的映射逻辑文本解析这一步核心是把“人话”翻译成“机器能懂的尺寸和特征”。比如“一个长 100 宽 50 高 20 的方块中间挖一个直径 30 的通孔”解析后应该得到这样的结构{ base: {type: box, length: 100, width: 50, height: 20}, features: [ {type: hole, diameter: 30, through: true, position: center} ] }这里有几个容易踩坑的地方。第一单位问题。文本里说“长 100”到底是毫米还是厘米工程场景默认毫米但用户不一定说。我的做法是在提示词里强制约定单位或者在解析层做默认值兜底默认毫米。第二位置描述模糊。“中间”“四角”“边缘”这些词需要映射成具体的坐标或约束。四角开孔就要根据底板长宽算出四个孔心的坐标。第三特征顺序。先拉伸再打孔和先打孔再拉伸结果可能完全不同。解析层要保证特征树的顺序符合几何逻辑。2.3 为什么输出格式要同时支持 STEP、GLB、STL这三种格式对应三种完全不同的使用场景我在项目里是全部保留的格式本质典型用途是否可参数化编辑STEPB-rep 实体工程制造、跨 CAD 软件交换是GLB网格材质网页展示、AR/VR、渲染否STL三角网格3D 打印切片否STEP 是工程界的“通用语言”中望 CAD、SolidWorks、Fusion 360 都能直接打开并识别特征。GLB 适合放到网页里用 three.js 加载做产品配置器。STL 则是 3D 打印的标配切片软件 Cura、PrusaSlicer 都认。如果你的 text-to-cad 流程只输出一种格式那它的适用范围会大打折扣。我在实际项目里是让生成管线同时吐出这三种用户按需取用。注意STL 导出前一定要做水密性检查。网格如果有破面或非流形边切片软件会报错。参数化实体转 STL 时控制好网格精度弦高和角度公差精度太高文件巨大太低表面有棱角。3. 实操环境搭建从零跑通一条生成管线3.1 工具选型与依赖安装要自己搭一套 text-to-cad 流程核心需要三块语言解析层、几何建模内核、格式导出模块。我用的组合是 Python CadQuery OCP这套方案开源、跨平台社区资料也够用。CadQuery 是一个基于 OpenCASCADE 的 Python 参数化建模库写起来像搭积木。安装命令如下pip install cadquery pip install ocp如果你要用大模型做文本解析还需要装对应的 SDK。我一般用本地部署的小模型做意图识别或者调用通用大模型的 API 做参数抽取。这里不展开具体品牌思路是把用户输入的自然语言通过提示词工程转成上面那种 JSON 结构。另外导出 GLB 需要额外的网格转换库pip install trimesh pip install pygltflibtrimesh 负责把实体转成网格并导出 GLBpygltflib 处理 glTF 的二进制封装。这套组合我用了大半年稳定性可以。3.2 一个最小可运行示例文字生成带孔底板先看一个完整的最小例子把“长 80 宽 60 厚 10 的底板四角开直径 6 的通孔”这句话变成模型import cadquery as cq # 参数定义 length 80.0 width 60.0 thickness 10.0 hole_dia 6.0 edge_offset 10.0 # 孔心距边缘距离 # 创建底板 plate cq.Workplane(XY).box(length, width, thickness) # 计算四角孔心坐标 holes [ (length/2 - edge_offset, width/2 - edge_offset), (-length/2 edge_offset, width/2 - edge_offset), (-length/2 edge_offset, -width/2 edge_offset), (length/2 - edge_offset, -width/2 edge_offset), ] # 打孔 plate plate.faces(Z).workplane().pushPoints(holes).hole(hole_dia) # 导出 cq.exporters.export(plate, plate.step) cq.exporters.export(plate, plate.stl)这段代码跑完你会得到两个文件plate.step 和 plate.stl。STEP 用中望 CAD 打开能看到完整的实体和孔特征STL 直接拖进切片软件就能打印。关键点在于孔心坐标的计算我用的是“距边缘 10mm”这个约束而不是直接写死坐标这样改底板尺寸时孔位会自动跟着调整。3.3 把自然语言接进来的解析层设计上面是硬编码参数真正要做的 text-to-cad得让参数从文本里来。我的做法是设计一个中间 JSON Schema规定好支持的几何特征和参数格式然后让语言模型按这个 Schema 输出。Schema 大概长这样{ units: mm, base: { type: box, length: 80, width: 60, height: 10 }, features: [ { type: hole, diameter: 6, through: true, pattern: corner, offset: 10 } ] }解析层拿到这个 JSON 后用一个分发器把每种 feature 映射到对应的 CadQuery 操作。这样做的好处是可扩展以后要加圆角、倒角、阵列只需要在 Schema 里加类型在分发器里加处理函数不用动主流程。实操心得提示词里一定要给模型几个 few-shot 示例尤其是“四角”“中间”“均匀分布”这类空间描述的映射方式。我试过不给示例模型经常把“四角”理解成绝对坐标结果孔跑到板子外面去了。4. 核心环节实现细节参数计算、特征顺序与格式导出4.1 尺寸参数的计算与校验逻辑文本里的尺寸往往不是直接可用的需要做一轮计算和校验。举几个我实际遇到的场景。场景一相对尺寸转绝对尺寸。用户说“孔距边缘一个板厚”板厚是 10那孔心偏移就是 10。这种相对描述要先解析成数值再代入计算。场景二阵列参数推导。用户说“沿长度方向均匀开 5 个孔”那孔间距就是(length - 2*edge_offset) / (5 - 1)。这里 edge_offset 如果没给我默认取孔径的 1.5 倍保证孔壁不破。场景三干涉检查。如果用户说“开一个直径 50 的孔”但底板宽度只有 40那这个孔会切穿侧壁。我的做法是在生成前做一次几何可行性校验孔直径必须小于最小边长减去两倍壁厚。不满足就报错提示用户调整参数而不是生成一个破模型。这些校验逻辑看起来琐碎但没有它们生成结果十有八九是废的。我踩过的坑就是早期不做校验生成了一堆孔打到板子外面的模型后期排查花了大量时间。4.2 特征树的顺序为什么不能乱CadQuery 是基于特征历史的建模方式操作的先后顺序直接影响结果。举个典型例子先倒角再打孔和先打孔再倒角孔口的边缘状态完全不同。我的经验法则是先做主体形状再做减材特征孔、槽最后做修饰特征倒角、圆角。原因是减材特征如果在修饰之后做可能会把倒角切掉一部分导致边缘不连续。而修饰特征放最后可以统一处理所有边。在代码层面这意味着解析层输出的 feature 列表要按类型排序而不是按用户说话的顺序。用户可能说“先倒角再打孔”但实际执行时要反过来。这个排序逻辑我写在分发器里用优先级字段控制。4.3 STEP、GLB、STL 三种格式的导出要点三种格式的导出各有各的坑。STEP 导出相对简单CadQuery 直接支持。但要注意单位STEP 文件内部默认是毫米如果你的模型是按厘米建的导出后尺寸会差 10 倍。我的做法是全程用毫米导出前再确认一次。GLB 导出需要先转网格。这里的关键参数是网格精度import trimesh # 从 STL 加载网格 mesh trimesh.load(plate.stl) # 导出 GLB mesh.export(plate.glb)如果直接从 CadQuery 的实体转网格可以用tessellate方法控制弦高。弦高越小网格越密文件越大。我一般设弦高 0.1mm角度公差 0.5 弧度这个精度下 100mm 见方的零件GLB 文件大概几百 KB网页加载无压力。STL 导出最需要注意的是水密性。参数化实体转 STL 通常是水密的但如果模型有自相交或零厚度面就会出问题。导出后我习惯用 trimesh 检查一下mesh trimesh.load(plate.stl) print(水密:, mesh.is_watertight) print(体积:, mesh.volume)is_watertight返回 True 才能放心切片。体积可以用来反推尺寸是否正确比如 80×60×10 的板减去四个孔体积应该在 46000 立方毫米左右。提示GLB 用于网页展示时建议做一次减面处理。工程模型的面数往往几十万网页加载会卡。用 trimesh 的simplify_quadric_decimation可以减到几万面视觉上几乎看不出差别。5. 常见问题与排查技巧实录5.1 生成模型打不开或报错怎么定位这是最高频的问题。我整理了一个排查顺序基本能覆盖九成情况。现象可能原因排查方法STEP 打开后是空文件实体未闭合或布尔运算失败检查 CadQuery 是否返回了有效 WorkplaneSTL 切片报错网格非水密用 trimesh 检查 is_watertightGLB 网页加载空白法线或材质缺失检查导出时是否包含法线数据尺寸差 10 倍单位不一致确认建模和导出都用毫米孔位置偏移坐标系理解错误检查 workplane 的朝向和原点我遇到最多的是布尔运算失败。CadQuery 在做差集时如果两个实体刚好相切或共面内核可能算不出结果。解决办法是留一点余量打孔时让孔的深度比板厚多 0.1mm保证完全切穿而不是刚好切到面。5.2 文本解析不准参数提取错误的应对语言模型解析文本时最常见的错误是数字提取错位。比如“长 100 宽 50”模型可能把 100 赋给宽度。我的应对策略是在提示词里强制字段名和顺序并且要求模型输出 JSON 后用 Pydantic 做一次类型和范围校验。另一个高频问题是隐含单位。用户说“5 厘米”模型可能直接输出 5。我在解析层加了一个单位识别模块遇到“厘米”“米”“英寸”就做换算统一转毫米。英寸转毫米是 25.4 倍这个系数我写死在配置里。如果解析结果明显不合理比如孔直径大于板宽我会触发一次重试把错误信息反馈给模型让它重新解析。实测下来重试一次能解决大部分问题。5.3 性能优化批量生成时怎么提速单次生成一个模型耗时主要在几何内核运算通常几百毫秒到几秒。但如果要批量生成几百个变体就得考虑优化。我的做法是复用基础实体。比如同一款底板只是孔位不同那就先建好底板实体然后复制多份分别打孔。CadQuery 的copy方法可以深拷贝 Workplane避免重复建模。另一个优化点是并行导出。STEP 和 STL 的导出可以放到不同线程里跑因为它们是独立的 IO 操作。我用concurrent.futures做了个简单的线程池导出耗时大概能降一半。实操心得几何内核的运算对内存比较敏感批量生成时建议分批处理每批 50 个左右处理完及时释放。我试过一次性生成 500 个内存直接飙到 8G后来改成批处理就稳了。6. 从生成到落地格式转换与下游衔接6.1 STL 转 STEP 的现实需求与限制热搜词里有个“sw 中 stl 转 stp”这其实反映了一个真实痛点很多人手里只有 STL但下游流程需要 STEP。STL 是网格STEP 是实体从网格反推实体本质上是逆向工程不是简单格式转换。SolidWorks 里可以用 ScanTo3D 功能做曲面重建但效果取决于网格质量。我的经验是规则几何体的 STL重建成功率较高自由曲面的 STL重建后基本没法参数化编辑。如果只是想要一个能打开的 STEP 文件用于查看可以用 FreeCAD 的“从网格创建形状”功能但得到的是一堆碎面不是干净的实体。所以我的建议是如果源头能生成 STEP就不要走 STL 转 STEP 这条路。text-to-cad 的价值恰恰在于它从一开始就生成参数化实体避免了后期的逆向麻烦。6.2 导入 CAD 软件后的二次编辑要点生成的 STEP 导入中望 CAD 或 SolidWorks 后通常还需要手动调整。几个要点第一特征识别。STEP 导入后软件会尝试识别拉伸、孔、圆角等特征。识别成功的可以参数化编辑识别失败的会变成“导入实体”。我在 CadQuery 里生成时会尽量用标准特征操作提高识别率。第二坐标系对齐。生成的模型默认以原点为中心导入后可能需要移动到底面或角点。这个可以在导出前用translate调整省得导入后再动。第三图层和颜色。批量生成时给不同零件设置不同颜色导入后便于区分。CadQuery 支持给实体赋颜色属性导出 STEP 时会保留。6.3 批量修改与脚本化维护热搜词里“python 批量对 cad 修改”也是我常做的事。text-to-cad 生成的模型如果参数存在数据库或 JSON 文件里批量修改就是改参数重新生成比在 CAD 软件里一个个改快得多。我的做法是维护一个参数表每行是一个零件的参数然后用脚本遍历参数表批量生成模型并导出。这样改设计就是改表格重新跑一遍脚本所有模型自动更新。这套流程在非标件批量出图场景下效率提升非常明显。提示批量生成时文件命名要有规律建议用“零件名_版本_日期”的格式避免覆盖。我早期没注意生成了一批同名文件结果互相覆盖白跑了一晚上。7. 我在这条路上踩过的坑和攒下的经验做 text-to-cad 这段时间最大的体会是生成模型只是第一步让模型可用才是真正的挑战。我见过太多演示很炫、实际没法用的工具问题都出在细节上。第一个坑是过度信任语言模型。早期我直接把模型输出的参数拿去建模结果经常出现负数尺寸、孔位越界。后来加了校验层所有参数先过一遍合理性检查不通过就拒绝生成。这个校验层看起来是额外工作但省下的排查时间远超投入。第二个坑是忽略单位一致性。有一次客户给的描述是厘米我默认毫米生成的模型小了 10 倍打印出来像个钥匙扣。从那以后我在提示词里强制要求模型输出单位字段并且在代码里做二次确认。第三个坑是网格精度设置不当。GLB 导出时弦高设太小文件几十兆网页加载转圈设太大圆柱面变成多边形看着很粗糙。后来我固定用 0.1mm 弦高兼顾质量和体积基本没再出问题。最后一个经验是保留中间产物。每次生成我都把解析出的 JSON、生成的 STEP、STL、GLB 全部存下来按时间戳归档。这样出问题时可以回溯是哪一步错了也方便对比不同版本的差异。这个习惯帮我定位过好几次解析层的 bug。如果你也在做类似的事情我的建议是先从规则几何体入手把一条链路跑通再逐步扩展特征类型。不要一上来就追求生成复杂曲面那会让调试难度指数级上升。把底板、支架、法兰这些规则件做好已经能覆盖很大一部分实际需求了。