做了一年多的“用自然语言直接生成CAD模型”这件事我最大的感受是text-to-cad这玩意儿终于从论文里的demo变得能落地了。以前你跟CAD说“帮我画一个带四个安装孔的支架”它只会弹个语法错误现在你对着一条提示词能直接拿到一个可编辑、可制造、能导出STEP的实体模型。这个变化不是某个单点技术的突破而是大语言模型、几何内核、参数化建模几股力量凑到一起的结果。这篇文章不打算写那种“教你三分钟用AI取代工程师”的鸡汤我想从一个实际做过很多次生成、踩过无数坑的人的角度把text-to-cad的完整链路拆开给你看它背后是什么原理、有哪些实现方式、怎么搭一套能用的流程、以及那些真正要命的问题怎么避开。适合正在搞AI辅助设计、想接生成式建模的开发者也适合想用工具提升效率的产品和结构工程师。不管你是用开源方案自己撸还是调用现成工具这篇文章应该能帮你省掉不少试错成本。1. 先搞清楚text-to-cad到底在生成什么很多人一听“text-to-cad”第一反应是“这不就是用AI画图吗”。这是最大的误解。文生图生成的是像素矩阵而CAD模型需要的是精确的几何信息哪条边是圆弧、哪两个面平行、哪个孔是通孔还是盲孔、直径公差是多少。像素错了无所谓几何错了零件就装不上更没法加工。1.1 从描述到模型的两种技术路线我梳理了一下目前主流方案基本可以分成两条路线脚本生成路线和端到端生成路线。脚本生成路线的思路是让大语言模型理解自然语言然后把设计意图翻译成一段参数化建模脚本再交给CAD内核执行。常用载体包括CadQuery、OpenSCAD、FreeCAD的Python API。这条路线的最大优点是生成的模型完全可编辑、可参数化因为脚本本身就是特征历史的另一种表达形式。你后来想改某个孔的直径改脚本里的参数重新跑一遍就行。端到端生成路线则是训练一个深度学习模型输入文本直接输出点云、体素或者BREP边界表示。这条路线的优点是一步到位短平快。但问题是输出结果往往是“不可编辑的实体”像是一块捏好的泥巴没有特征树、没有参数、没有历史记录。在制造业的工作流里这种模型基本只能当参考没法直接进PDM系统做变更管理。我自己在实际项目里几乎只走脚本生成路线原因后面会展开说但核心就一句话CAD的核心价值在于“可复用”和“可修改”而不是“一次性画出来”。对比维度脚本生成路线端到端生成路线代表实现LLM CadQuery/OpenSCAD专用生成网络输出BREP/体素可编辑性高参数任意改低生成即固定可制造性高遵守建模规则一般可能产生破面对算力要求普通推理即可训练和推理成本高上手门槛需要懂一点代码需要炼丹门槛更高1.2 一个核心认知你要生成的是“特征”不是“网格”我刚入坑时犯过一个错误拿到一个text-to-cad生成的模型兴奋地点开一看发现它导出的是STL网格。网格对3D打印够用但对真正的机械设计是完全不够的。真正的CAD模型内核里记的是“先拉伸一个矩形再在顶面上打两个直径5mm的通孔再倒一个R2的圆角”这种特征历史而不是“一堆三角形拼成的形状”。所以在评估任何text-to-cad工具时我第一个问题永远是“你输出的是B-rep实体还是Mesh网格”如果答案是后者基本可以排除在工程场景之外。现代的CadQuery和OpenSCAD都属于前者它们底层的几何内核分别是OCCT和CGAL能生成真正带拓扑信息的实体模型。这个差别到了下游做有限元分析、开模具、做装配干涉检查的时候会被放大成一个天一个地。2. 我把text-to-cad拆成了四个关键环节如果你要自己搭一套text-to-cad流程或者要评估市面上某个工具靠不靠谱我建议把它拆成四个环节来看自然语言理解、设计意图到CAD指令、几何内核执行、可制造性校验。这四个环节每一环都会掉链子而且掉链子的方式完全不同。2.1 自然语言到设计意图缺的不是理解是约束提取大语言模型理解自然语言这件事现阶段已经不是瓶颈了。真正麻烦的是用户说的一句话里往往参数不全、几何关系不明确、术语混乱。比如你说“给我一个带孔的板子”模型得自己决定板子多厚、多大、孔开在哪、开多大、是通孔还是沉头孔。我试过几种处理方法最有效的是让模型输出结构化的JSON中间表示而不是直接输出代码。也就是说让LLM先把自然语言翻译成一套明确的“设计意图描述”然后再用一个确定性规则把它映射成CAD脚本。这样做的优势是出错了你能知道是理解错还是生成错不用对着堆栈瞎猜。举个我实际用的例子。对于“一个80毫米宽、60毫米高的L型支架厚度3毫米底部有两个直径6毫米的安装孔”我让模型先输出这样的JSON{ part_type: l_bracket, parameters: { width: 80, height: 60, thickness: 3, base_depth: 40, mounting_holes: [ {diameter: 6, x_offset: -15, y_offset: -20}, {diameter: 6, x_offset: 15, y_offset: -20} ] } }这一步非常关键它等于把模糊的中文描述格式化成CAD软件能接受的数据结构。2.2 设计意图到CAD指令模板和自由生成的博弈有了结构化JSON之后接下来就是把参数填进模板脚本里。这个环节我踩过的坑最多。一开始我让LLM直接从零生成CadQuery代码结果经常出现用了一个不存在的API、坐标系搞反、单位搞错、甚至逻辑上先布尔减再布尔加导致把特征削没了。后来我改成预置一套经过验证的建模模板LLM只需要负责从模板库里选择并填参数。这套做法稳定性提升非常明显。模板的作用相当于把LLM的搜索空间缩小到一个能保证正确的范围内剩下的只是一些简单的参数映射。只有当用户需求超出模板范围时才让LLM尝试扩展但扩展的代码必须经过自动校验。典型的校验手段包括语法检查、引用检查、用样本参数试运行看是否会抛异常、检查几何结果是否满足预设约束比如体积大于零、面数合理、最小壁厚大于某阈值。2.3 几何内核执行一步错步步错这个环节普通用户感觉不到它的存在但它恰恰是text-to-cad稳定性的命门。几何内核负责完成拉伸、旋转、布尔并集差集、倒角圆角这些操作。拿CadQuery来说它底层是Open CASCADE这是一个有几十年历史的C几何库功能强大但API设计也比较“古典”很多行为需要经验才能预测。举例两个实体做布尔差集用来减去的那个工具实体如果刚好和主体共面某些内核会判定为无法执行报错“No shape found”。这个情况在用户对壁厚没概念时很常见——他说“掏个槽”槽深刚好等于板厚工具体就跟主体底面完全重合了。我的经验是在生成脚本里加一层隐性约束——所有操作参数都要留安全余量或者在后处理里做“几何合理性检查”。比如布尔运算前先查一下两个实体是否只共享边界而不共享体积是的话就自动给偏移一个微小距离避免共面的数值问题。这类问题不踩几次真的不知道坑有多深。2.4 可制造性校验AI负责生成社会负责现实最后一个环节是制造相关很多人忽略我建议任何人都别省。要知道“能画出来”和“能加工出来”之间还隔着好几座大山。你让LLM生成一个带悬伸结构的零件在3D打印上可能还行但如果你要用数控铣削加工这个设计就是废铁。我的做法是在生成流程末尾接一个自动校验层检查项目包括最小壁厚是否满足材料和工艺要求注塑至少0.8mmCNC至少1.5mm具体看材料是否存在封闭内腔导致无法排屑或模具无法脱模锐角内角是否过小导致应力集中或刀具无法进入孔径是否小于推荐的最小加工孔径限制这套校验其实不需要写在CAD脚本里它可以是独立的一段Python脚本在模型导出前跑一遍不合格就直接拦截返工。这也避免了“生成100个拿到工厂80个不能用”的窘境。3. 实操从零搭一套能用的text-to-cad流程前面聊了不少原理这块我给你一套我能跑通的实现方案。没有依赖某个特定付费平台你只需要一个能调用大语言模型的环境以及Python库就够了。3.1 环境准备与工具选型我目前的推荐组合是大语言模型可以选用商业API或者本地开源模型。项目里如果涉及保密设计建议本地部署开源模型如果追求理解能力商业API效果更好。我只把脱敏的通用需求发给外部API涉密任务走本地。参数化CAD库CadQuery或者更现代的build123d结构化输出用Pydantic定义JSON格式强制模型输出符合Schema的数据。校验层自定义Python脚本跑完几何后检查体积、干涉、壁厚等指标。环境安装没什么特别的Python 3.10以上pip install cadquery即可。如果你要用build123d它是CadQuery的进化版API更友好但社区资源少一些二选一即可。3.2 提示词与输入规范化我一开始直接让用户把需求敲进去然后丢给LLM。结果惨不忍睹。用户描述里经常带语气词、默认值、口语化的模糊单位“差不多这么大的”“厚一点的”“孔别太大啊”。这些表述在工程师之间是靠默契理解的LLM瞎猜的准确率达不到工程要求。后来我加了一个需求澄清前置环节。系统先根据用户输入提取参数如果发现关键参数缺失会反问用户。比如“如果只告诉我‘带孔的板子’我会默认厚度2mm长度80mm宽度50mm孔径5mm请确认或者提供修正参数”。这一步交互看着简单但对于提升生成成功率是质的改变。如果场景不允许交互比如批量任务我就用默认值策略但必须在生成结果里明确标注哪些参数是采用默认值的。这样做的好处是工程师拿到的模型自带参数假设说明不用自己去猜AI干了什么。3.3 核心生成代码示例一个L型支架的实战下面这段代码是简化后的流程核心我用它跑了无数次。它做的是接收用户自然语言调用模型提取JSON然后填充CadQuery模板生成STEP文件。import cadquery as cq import json from pydantic import BaseModel # 定义结构化输出Schema class BracketParams(BaseModel): width: float 80.0 height: float 60.0 thickness: float 3.0 base_depth: float 40.0 hole_diameter: float 6.0 hole_x_spacing: float 30.0 # 假设这已经由LLM从用户输入提取出来 params BracketParams() # 生成L型支架 vertical cq.Workplane(XY).box( params.width, params.thickness, params.height, centered(True, True, False) ) base cq.Workplane(XY).box( params.width, params.base_depth, params.thickness, centered(True, True, False) ).translate((0, 0, params.thickness / 2)) result vertical.union(base) # 在底板上开安装孔 result ( result.faces(Z) .workplane() .pushPoints([ (-params.hole_x_spacing / 2, -15), (params.hole_x_spacing / 2, -15) ]) .hole(params.hole_diameter) ) # 导出STEP和STL cq.exporters.export(result, output/bracket.step) cq.exporters.export(result, output/bracket.stl)有几个细节值得展开说。第一box的centered参数我特意设成了(True, True, False)意思是让x、y方向居中z方向放在原点平面以上。这是为了后续用faces(Z)选择顶面时有个明确的坐标参考否则容易选到意想不到的面。第二pushPoints传的是打孔点的坐标列表这里用了相对位置的写法便于以后改成任意布局。第三translate((0, 0, params.thickness / 2))是为了把底板抬起来使它的顶面恰好和竖板的底面贴平。这段代码不是我拍脑袋写的它是迭代了很多次之后稳定下来的模板。之前我犯过一个低级错误把竖板和底板都用centered(True, True, True)然后靠坐标偏移拼到一起。结果是两块板在z方向的中心对齐L型的轮廓变得很别扭。这些几何细节LLM自己是很难一次生成的必须靠模板固化下来。3.4 让输出更可控规则注入与多轮修正用模板结构化输出的方式能把成功率拉高但依然会有用户不按套路出牌。比如他说“在竖板上加一个长圆孔”而我的模板里只有圆孔。这时候LLM如果硬填参数就会出错。我应对的办法是检测到用户需求超出模板能力时切换到自由代码生成模式同时把几何校验层调到最严。让LLM生成一段全新的CadQuery代码然后我在沙箱里运行看它的输出是否满足基本约束。如果失败把错误信息回到LLM让它自己修。这个“生成-运行-报错-修复”的循环通常跑两三轮就能得到可用的结果。这个过程有点像和一个有经验但偶尔粗心的实习生合作你得给他清晰的任务边界、规则清单并在他做完之后检查结果而不是甩一句“你去把它搞定”就完事了。4. 在实际业务里怎么用text-to-cad而不是玩票讲了这么多技术细节如果这玩意儿只能拿来生成几个玩具模型那没什么意思。我这里说几个我实际验证过有长期价值的使用场景。4.1 三个高价值场景概念造型、标准件库批量生成、非专业人员定制第一个场景是前期的概念造型阶段。产品经理或者工业设计师在头脑风暴时往往会提很多模糊的想法“能不能做一个底座能放两个电池仓和一个充电模块”过去工程师得手动搭个糙模型来验证空间布局现在可以直接用text-to-cad生成几个方案版快速比对尺寸和布局。虽然最终的详细设计工程师还得重做但早期沟通成本省了一大截。第二个场景是标准件库批量生成。很多公司的外购件、标准件库里同一类零件有不同的尺寸规格以前得靠人工建一堆类似模型。现在可以写一批参数化模板然后用一个简单的LLM脚本让用户输入自然语言“生成M6×20的内六角螺栓头部直径10mm”直接得到对应的STEP文件。批量生成几十个变体也就是几分钟的事。第三个场景更野是让非设计人员也能做定制。我认识的一个做非标设备的老板给终端客户提供了一套内部系统客户只需要输入自己的安装尺寸和负载要求系统内部调用text-to-cad流程自动生成定制支架模型和报价。这种玩法在过去至少需要一个CAD二次开发工程师现在一个人能做一条线。4.2 对接3D打印和加工的关键一步生成模型之后下一步往往是做原型。3D打印这条路最顺因为STL格式直接切片就行。但这里有个我踩过的坑CadQuery默认的STL导出三角化精度比较粗如果你的模型是小尺寸精细件会出现明显的棱边打印出来表面粗糙得像狗啃。解法是在导出前设置弦高公差。CadQuery里可以这样控制把cq.exporters.export时的tolerance参数调小或者先通过val().tessellate(tolerance)做高精度三角化再保存为STL。弦高公差我一般设置在0.01mm级别文件会变大但打印质量能接受。如果是CNC加工STEP才是标准交付格式。CNC编程人员拿到STEP可以直接在CAM软件里生成刀路不需要重新建模。4.3 和传统CAD工作流的协作方式很多人担心“AI生成的模型会不会打乱我们现有的设计流程”。我的经验是把它当成一个“设计前置工具”而不是“替代工具”。生成的STEP文件进入PDM系统时我会强制在流程里建立审核节点要求设计负责人确认关键尺寸和制造约束并附上生成时的提示词和参数假设。这样即使后面出了问题也可以回溯。这个思路跟人类工程师设计的图要经历校对、审核是一个道理只是把“快速出初稿”这个环节交了出去。说到底CAD从来不是“画图”这么简单它是工程决策的记录工具。text-to-cad的价值在于加速这个记录过程的“起步阶段”而审核和决策永远是人的工作。5. 常见问题与避坑指南最后这块我整理了几个高频问题都是我自己或者团队小伙伴实际遇到过的。5.1 生成的脚本经常编译报错怎么办我的回答是别让它绕开你的模板。如果你发现模型在自由代码生成模式下频繁报错最好的做法不是换更大的模型而是回到模板策略。把所有能预定义的特征都做成插槽让模型只在插槽里填数字。自由代码生成留到最后兜底并且一定配合自动试运行校验。还有一个容易被忽略的点CadQuery的版本差异会带来API兼容问题。你本地跑的版本跟模型训练时见过的代码版本很可能不同。所以一旦锁定CadQuery版本后提示词里最好带上版本信息降低模型生成不兼容API的概率。5.2 能生成形状但改不了尺寸不满足要求这种情况多半是走的端到端生成路线或者模型生成的是网格。解法只能是回到参数化脚本路线。如果你用的工具不提供参数暴露那这个工具在你的工作流里就是死路。购买或者选型的时候一定问清楚“生成的模型有没有特征树能不能改参数”5.3 结果“看起来像”但不可制造这是最迷惑人的坑。一个零件在屏幕上看着很完美壁厚0.2mm内腔封闭锐角一堆但它实际没法注塑、没法铣削。我的避坑方法前面讲过就是自动校验层。这里补充一个细节校验不能只看几何还要把工艺约束一起检查。比如对CNC来说铣刀半径决定了内圆角的最小半径如果你设计了一个R1的内角而加工刀具是R3的那这个角就清不到根。这类规则完全可以在校验脚本里写成硬约束。5.4 提示词模糊导致结果不稳定同一句话两次生成不一样LLM天然有随机性所以如果你的流程是“自然语言直接生成代码”每次结果不同是必然的。想要稳定只有一条路把随机性从关键路径上搬走。具体就是我前面说的三步先提取结构化JSON再查表选模板最后用确定性逻辑生成代码。这样LLM的随机性只影响JSON字段的取值不影响代码结构和几何操作顺序。同样一句话两次生成的模型在尺寸上有细微差异但整体结构、特征位置、可编辑性都是确定的。5.5 生成太慢或者API调用太贵如果你的场景要批量生成逐条调用大语言模型API的延迟和成本都很可观。我的优化办法是拆分任务对于参数完全相同、只是数值不同的批量需求不需要每次都调LLM一次提取参数、批量跑CAD模板即可。只有真正的新结构才需要走完整流程。另外对高频的“标准件变体”可以直接做成查表连LLM不用环境也不会抱怨。最后再分享两个我个人的习惯第一我始终把可追溯性放在第一位。每生成一个模型我会在同一目录下保存一份JSON参数文件里面完整记录了用户原始描述、解析出的结构化参数、哪些用了默认值、用的是什么版本的模型和模板。这个习惯在我后来追查一个问题时救过我很多次。第二别迷信“一键生成”。即使现阶段text-to-cad已经能跑通比较复杂的零件我仍然会在生成结果后手动旋转查看一遍有时候还要切成线框模式看内部结构。AI能干活但最后签字的是你。带着这个心态用text-to-cad它能成为你手里最顺手的工具而不是定时炸弹。