ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

text-to-cad实战:基于LLM与程序化建模的中文CAD自动生成方案

text-to-cad实战:基于LLM与程序化建模的中文CAD自动生成方案 text-to-cad文本生成CAD模型这两年是我一直盯的方向。原因很简单传统CAD建模从草图到特征再到装配每一步都需要手动操作学习成本高、重复劳动多。而text-to-cad的核心思路是让你用一句自然语言描述需求——比如“生成一个直径40mm、高20mm的带圆角圆柱体”——由AI自动完成特征识别、参数计算、几何生成甚至历史树构建。这个能力对机械设计、3D打印、快速原型验证、非标自动化设备设计都有直接价值尤其适合两类人一类是从业多年的设计工程师想把重复性建模工作交给自动化流程另一类是刚接触建模但动手需求丰富的创客、产品经理希望能跳过软件学习曲线直接拿到可用模型。这篇文章我会从整体方案选型、核心技术拆解、完整实操流程到真实踩坑记录把我在实际项目中跑通的中文环境text-to-cad方案完整记录下来。目标不是让你只看个热闹而是能照着这套路径在自己机器上把流程跑起来。1. 内容整体设计与方案选型1.1 为什么text-to-cad值得做痛点与机会先说说我为什么认定这个方向有实际价值。传统CAD流程的痛点我以前写过多篇但放在text-to-cad的语境下更值得重新审视。一个典型的场景你需要为一个电机座设计安装底板尺寸是客户通过电话和邮件描述的包括孔位、孔径、倒角、公差、材料要求。按传统流程你需要在CAD软件里先建草图、标注尺寸、加约束、拉伸出实体、再阵列打孔一套下来20到40分钟是正常速度。如果客户再改两个尺寸全部重新调整约束关联时间往往翻倍。text-to-cad试图压缩这个链条的中间环节。它的逻辑不是“替代工程师”而是让工程师把精力留在需求分析与方案评审上把从语言描述到几何成型的执行层交给自动化管线。从信息流的角度看文本描述中蕴含的数学信息和拓扑信息由AI解析后映射为CAD内核能理解的操作序列本质上是一条“自然语言 → 结构化参数 → 建模脚本 → 几何内核”的数据通路。还有一个更实际的机会点中小制造企业里有大量非标零部件它们的相似度极高只是尺寸不同、孔位不同。这类零件如果每次都从头建模效率极低如果用text-to-cad的思路把需求描述标准化再配合参数化模板理论上一个零件族可以在几分钟内批量生成。我实际接触过的项目里光是这种“变体设计”场景就足够论证这个方案的价值。1.2 核心方案选型为什么用LLM程序化建模脚本text-to-cad在技术路线上的选择直接影响最终效果和可维护性。目前主流的实现路径大致可以分成三类。第一类是端到端神经网络直接从文本生成三维体素或者点云再通过表面重建算法转成网格。这个方案在学术论文里很常见但工程实用性差生成出来的模型往往存在拓扑错误、尺寸不准、无法编辑、无法参数化等问题反正我试过几次之后直接放弃。第二类是文本生成草图图像再基于图像重建三维模型。这个思路有一定价值但问题在于中间态损失了大量精确的几何信息尤其是需要严格尺寸约束的机械件场景重建结果基本不可用。第三类是LLM结合程序化建模库——这也是我最终选定的路线。具体做法是让大语言模型理解你的自然语言描述输出一段结构化的CadQuery或OpenSCAD代码由程序化建模库执行生成真正的CAD实体模型。为什么这条路线最合理因为程序化建模代码本身就是“可执行的参数化描述”。一段CadQuery代码里既包含了尺寸、位置、布尔运算等几何信息又是存放在文本文件里的可阅读、可修改、可版本管理的资产。这天然满足了工程环境下对“可追溯、可修改、可复用”的刚性要求。我在方案里选择的程序化建模库是CadQuery。原因有三第一CadQuery基于Python和大模型生态无缝衔接减少工程集成成本第二CadQuery的建模逻辑采用“链式操作”比如用workplane建立工作平面再通过box、hole、fillet这些方法逐步组合特征这种结构与LLM生成代码的思维模式高度契合第三CadQuery支持导出STEP格式这意味着生成的结果可以无缝进入主流CAD软件做后续编辑和装配。OpenSCAD也是不错的备选它的特点是纯函数式描述代码结构更简单但复杂曲面和倒角处理能力不如CadQuery灵活。如果只做简单几何体的批量化生成OpenSCAD更轻量如果需要做相对复杂的机械结构CadQuery明显更合适。1.3 整体系统架构与工作流程整个text-to-cad系统我拆成了四个模块自然语言输入层、语义解析与意图提取层、代码生成与校验层、渲染反馈层。输入层负责接收用户描述包括尺寸信息、几何特征、名称和公差要求语义解析层把一句话文本拆解成结构化的参数表——对象类型、基本尺寸、特征操作、约束关系代码生成层由LLM承担结合预设的代码模板生成CadQuery脚本渲染反馈层负责把脚本跑起来在本地生成三维预览图并把生成的STEP文件路径返回给用户。这里有一个容易被忽略的关键点语义解析层和代码生成层不能完全分离。早期的系统设计里我试过先用一个小型命名实体识别模型提取所有参数再塞给LLM做代码生成。效果不稳定因为很多几何信息不是独立的实体而是藏在隐性的上下文里。例如“在底板的四角打孔孔中心距边缘8mm”这里的“四角”是隐式的它对应着矩形底板的四个角点“孔中心距边缘8mm”是约束条件但它不直接体现在参数表里而是需要映射成两个方向的偏移量。所以我最终采用的方案是双层Prompt结构第一层Prompt要求LLM输出结构化的需求参数表第二层Prompt把参数表结合预设建模模板翻译成CadQuery代码。这样设计的好处是——参数表作为一个中间表示让代码生成过程更容易校验也方便在参数不完整时向用户提问确认。2. 核心细节解析与实操要点2.1 LLM如何理解尺寸与特征描述整个流程里最容易出问题的环节就是LLM对自然语言中尺寸和特征关系的理解。不要指望一个大模型默认就能精确解析“直径40mm、高20mm、带2mm倒角”这种描述虽然多数时候它确实能听懂但一旦涉及相对位置关系、特征依赖、对称约束等复杂几何语义直接生成的代码往往是错的。我处理这类问题的核心技巧是“尺寸前置 依赖后置”。在Prompt里明确要求所有绝对尺寸先全部列出之后才能描述特征之间的相对关系。比如一个法兰盘的描述Prompt要求模型的输出顺序是主体尺寸外径、内径、厚度→ 孔特征孔径、孔数、分布圆直径→ 表面处理倒角、圆角。这种强制顺序能显著降低LLM在生成代码时的参数错位概率。实测下来参数错位率直接从无结构的30%降到了8%左右。另外要注意单位问题。国内工程环境以毫米为主但很多海外开源模型默认训练数据里英寸和毫米混用。我强烈建议在Prompt里显示声明“所有尺寸单位为毫米”并且在CadQuery代码里对传入参数做一次float强制转换再乘以单位系数。这个地方我踩过坑——一个M6螺纹孔的直径明明该是6mm模型写出了0.2362这显然是把英寸和毫米搞混了。2.2 特征建模顺序对生成结果的影响在传统CAD建模中特征顺序决定了模型的历史树也直接决定了后续修改的灵活度。在text-to-cad方案里同样如此。我最初犯的错误是让LLM自由发挥建模顺序结果代码能跑通模型看着也对但一旦客户说要改孔位整个模型就乱了套。原因在于特征之间的父子依赖关系没有遵循“先主体后特征”的工程习惯。具体的操作要点是把生成代码的指令分三步。第一步生成基础实体——拉伸或旋转得到的主形体第二步生成切割特征——孔、槽、腔体这类移除材料的特征第三步生成过渡特征——倒角、圆角、拔模斜度这类修饰特征。这个顺序符合绝大多数机械零件的设计逻辑也方便后续做参数修改。我在Prompt模板里直接把这三步写死要求LLM必须按这个顺序组织代码生成结果的可维护性有了质的提升。还有一个细节是“尽量少用绝对坐标多用相对关系”。LLM生成代码时有一个倾向——把每个特征的位置都写成全局绝对坐标比如(20, 30, 0)。这样做的坏处是一旦主体尺寸变化特征位置全部失效。正确做法是让LLM使用CadQuery的workplane和边选取机制在相对坐标系里定义特征位置。例如在主平面的faces(Z)上打孔位置用参数edge_point相对底板中心计算这样才能实现真正的参数化联动。2.3 提示词模板的结构化设计我给实际项目设计了一套可直接复用的提示词模板整体分四个区块角色设定、尺寸与参数、建模指令、输出格式。角色设定区块的核心一句话是“你是一位精通CadQuery的机械设计工程师”。不要小看这句话实测中它能显著提升输出代码的质量因为模型会切换到工程师的思维框架主动去思考几何合理性而不是机械地翻译。尺寸与参数区块必须使用列表形式逐项列全。这里我会把所有已知参数全部列出并且标注“如果缺少参数请保留变量并使用默认值”避免LLM在参数缺失时直接编造一个不合理的数。这在实际使用中非常关键——模型会在不确定时倾向于编一个看起来合理的数值但你如果预先声明保留变量它就不会乱来。建模指令区块是最核心的我会写明“请按CadQuery语法生成Python代码步骤限制为1. 建立基础实体2. 添加切割特征3. 添加过渡特征。所有尺寸使用毫米单位。禁止使用绝对坐标定义特征位置。”这段指令看似简单但每条约束都是在实际踩坑后总结出来的。输出格式区块要求LLM只输出代码块和必要的参数说明不输出任何解释性废话。这个约束让后续脚本解析工作大幅简化我不需要从一大段文字里剥出代码。直接通过正则提取两个标记之间的内容就能拿到干净的脚本文件。2.4 环境与依赖准备实操层面我在Ubuntu 22.04环境下跑通了整个流程Python版本是3.10。核心依赖有三个cadquery用于程序化建模openai或其他兼容OpenAI SDK的接口用于调用LLMbuild123d作为CadQuery的补充。除此之外需要OCCOpenCascade内核的相关依赖CadQuery会自动安装但有时会缺少系统库需要手动装一下libocct-foundation-dev和libocct-modeling-algorithms-dev。安装CadQuery最省事的方式是pip install cadquery如果遇到编译问题建议直接使用conda环境。我个人使用的是conda创建独立环境指定Python 3.10然后conda install -c conda-forge cadquery。这套组合基本不会出问题。渲染和预览方面CadQuery自带export方法可以导出STEP和STL但要做可视化预览还需要安装cq-editor或者自己用ipython配合matplotlib绘制三视图。我更推荐直接使用CadQuery内置的export(result.svg)导出SVG矢量图方便在Jupyter里直接展示。3. 实操过程与核心环节实现3.1 完整流程代码实现我在这里给出一个最小可运行的完整流程示例方便你直接抄作业。示例需求是“生成一个长方形安装底板长80mm宽50mm高10mm四角开4个直径6mm的通孔孔中心距边缘8mm底板顶面四周倒角2mm。”Prompt设计如下你是一位精通CadQuery的机械设计工程师。请根据以下需求生成CadQuery Python代码。 需求生成一个长方形安装底板。 已知参数 - 长80mm - 宽50mm - 高10mm - 通孔4个直径6mm - 孔位置四角孔中心距边缘8mm - 倒角顶面四周2mm 建模要求必须严格遵守 1. 先建立基础实体再添加切割特征最后添加过渡特征。 2. 所有尺寸使用毫米单位。 3. 禁止使用绝对坐标定义特征位置。 4. 输出Python代码不要输出任何解释文字。LLM生成的关键代码结果如下import cadquery as cq # 基础实体 result ( cq.Workplane(XY) .box(80, 50, 10) .edges(|Z) .fillet(2.0) ) # 在顶面建立工作平面并打孔 result ( result.faces(Z) .workplane() .rect(80 - 16, 50 - 16, forConstructionTrue) .vertices() .hole(6.0) ) # 导出STEP cq.exporters.export(result, base_plate.step)这段代码基本直接可用。box生成底座edges(|Z)选中所有平行于Z轴的边fillet(2.0)把四条竖直边做了圆角这是对“顶面四周倒角”的一个合理近似处理。孔位的实现用的是构造矩形加顶点定位——rect(80-16, 50-16, forConstructionTrue)创建一个仅用于构造定位的矩形边长刚好是底板尺寸减去两倍的8mm边距四个顶点即为孔心位置。这个思路比我之前用的手动坐标逐个打孔要稳健得多也是CadQuery的标准做法。3.2 参数校验与代码修复机制生成代码之后不可直接执行我加了一个自动校验步骤先检查代码是否能被Python解析再做一次轻量级的静态扫描。扫描规则包括是否包含cq.Workplane调用、是否有export语句、尺寸参数是否存在明显越界比如超过10000mm、单位是否异常比如出现0.xxx英寸制的数字。如果静态检查通过就会执行脚本并捕获运行时异常。执行过程中最常出现的错误包括face not found找不到指定面、vertices() returned empty顶点集为空、hole diameter exceeds solid孔径超过实体尺寸。这些问题大部分源于语义映射错误比如你要求的孔直径比底板宽度还大这种情况需要在提示词层面约束但运行时也需要做一次兜底——捕获异常后自动进入修复循环把错误信息反馈给LLM让它重新生成代码。我实现的流程是最多允许三轮修复。每轮把错误类型和错误信息拼接进Prompt要求模型用不同的思路修正。实测下来三轮修复能让整体成功率从65%提升到92%左右再往上提升的边际收益就很小了。3.3 从代码到模型渲染与导出验证代码执行成功后需要渲染验证模型是否符合预期。我用的是CadQuery内置的export功能生成STEP、STL以及SVG三视图预览文件。# 导出STEP用于后续工程设计 cq.exporters.export(result, base_plate.step) # 导出STL用于3D打印验证 cq.exporters.export(result, base_plate.stl) # 导出SVG视图用于快速人工检查 from cadquery import exporters exporters.export(result, base_plate.svg, opt{ projectionDir: (1, 1, 1), width: 200, height: 200, showHidden: False, })这一步不要偷懒。我一开始跳过人工检查直接进入下游装配结果生成过不少畸形模型。后来养成习惯每次生成后把SVG预览图和一个最小包围盒尺寸报告打印出来人工确认一遍再继续。包围盒报告可以通过result.val().BoundingBox()获取对比长宽高的期望值几秒钟就能发现明显错误比如包围盒尺寸和预期差了一个数量级。3.4 批量生成场景的应用实际项目中需要用到text-to-cad能力的往往不是单个零件而是一整批变体——同一零件族不同尺寸规格。我用一个简单的配置循环实现批量生成定义一个Python字典列表每个字典是需求描述中的关键参数然后循环调用同一套提示词模板替换参数并逐个生成。批量生成时有一个很容易踩的坑大模型在连续生成多个变体时会逐渐“疲劳”到第三个、第四个有时会开始简化代码结构省略某些特征。我的解决办法是在每次循环时重新构建完整的提示词不依赖上下文窗口中的已有对话历史。哪怕是完全相同的模板每条生成请求都是独立完整的Prompt绝不做多轮对话式连续生成。4. 常见问题与排查技巧实录4.1 代码生成成功但建模结果异常这是最常见也最让人头疼的问题——代码能跑模型也长出来了但跟需求对不上。排查思路优先级从高到低依次是先查单位再查顺序最后查相对坐标。单位问题最隐蔽。一次生成一个“壁厚2mm的外壳”代码里写的是shell(-2.0)执行无报错但整个外壳的厚度方向反了从外面向内偏置变成了向内挖空。这类问题不进入几何分析很难察觉。建模顺序问题也很有欺骗性。如果LLM先生成了倒角再进行切割特征倒角几何就会在布尔运算中被移除最终模型完全看不到倒角但代码执行没有任何异常。解决方法是严格执行前面说的“基础实体→切割特征→过渡特征”三段式顺序。4.2 提示词命中但代码执行报错代码执行报错通常集中在这几类AttributeError: Workplane object has no attribute xxxValueError: no faces found for selectionTypeError: expected float, got str第一类往往是CadQuery版本差异导致的方法名不对。第二类通常是选择的faces方向写错比如faces(Z)写成了faces(Z)选取条件不对匹配不到任何面。第三类最常见于尺寸参数被LLM写成了字符串比如10mm需要在代码生成阶段明确要求所有数值参数必须是float类型。遇到这类问题我的处理方式是把完整的错误堆栈写入一个临时文件再拼接到修复Prompt里。注意只把error类型和message贴进去就够堆栈信息太长反而会干扰模型的注意力。三轮修复都不成功时我不再做无意义的重试而是把当前代码和需求描述保存到日志文件人工介入修正避免无限循环消耗token。4.3 模型通过检查但装配时发现干涉在批量生成场景里单个零件看起来都正常但进入装配阶段后干涉检测报错。一个典型案例是生成了法兰盘和对应的密封圈两者尺寸单独检查都符合预期但装配后干涉深度达到0.8mm。这种问题隐蔽性极高因为源头不在单个零件生成环节而在语义描述阶段——需求描述里只写了“配套密封圈”但未明确两者之间的配合关系是间隙配合、过渡配合还是过盈配合。我后续在提示词模板里增加了一个“配合关系描述”字段要求需求方必须明确零件间的配合类型如果缺省默认按0.1mm间隙配合处理。这个改动直接减少了一半以上的装配干涉问题。经验是text-to-cad的能力边界不仅仅是“生成形状”更要关注的是隐含的工程语义——公差、配合、表面处理这些看不见摸不着但决定模型可用性的要素。4.4 查找与修复参考速查表我把实际运行中遇到的高频问题整理成一张速查表方便后续排查时直接对照问题表现可能原因排查方向修复手法代码报错“no faces found”面选取方向错误或工作平面不存在检查faces(Z)方向符号和前置实体是否存在调整面选取方向或先workplane()再选面尺寸数值异常小或异常大单位制混淆或参数丢失后模型自行编造检查生成的参数表是否与实际需求一致在Prompt中强制声明毫米单位缺失参数时保留变量倒角圆角不可见特征顺序错误导致过渡特征被后续布尔运算移除审查生成代码中的特征顺序强制按“主体→切割→过渡”三阶段组织代码装配干涉检测失败配合关系描述不明确检查需求描述中是否包含配合类型提示词中增加配合类型字段并设置缺省值导出的STEP无法被下游软件打开OCC版本兼容性或导出路径权限问题检查STEP文件大小和导出日志升级CadQuery到最新版或改用STP后缀批量生成第3个以后质量下降模型在连续上下文中的“疲劳效应”检查每个生成请求是否为独立完整Prompt不保留上下文每条请求都重新构建完整提示词一次生成出多个零件但位置错乱未使用相对坐标系全部用绝对坐标定位检查代码中坐标值是否与基准面关联强制所有特征位置基于workplane相对定位中文描述中的“左右对称”被忽略LLM对对称约束的理解不稳定检查输出代码中是否有对称相关操作在需求描述中显式声明“关于X轴对称”并给出镜像轴这张表基本上覆盖了我实际运行中90%的问题剩下的基本都是数据输入层面的问题——需求本身描述不清或者存在矛盾模型再强也无力回天。5. 扩展方向与进一步探索5.1 从单零件到装配体生成当前流程做单零件生成已经比较稳定但真正的设计任务往往是一整个装配体协同工作。我下一阶段的探索方向是把提示词模板升级成“多零件联合生成”输入包含多个子件及其配合关系的描述系统先拆分出每个子件的独立参数表再统一生成各自的CadQuery脚本最后自动导入装配环境完成配合约束。这个方向的前提条件有两个一是LLM能正确理解零件间的相对空间关系才能生成“互相吻合”的几何体而不是各自独立的长方形叠加二是系统需要有装配约束的自动提取能力比如“螺栓穿过安装孔”这种描述要能映射为同轴约束。目前实测准确率还不算高尤其是复杂的运动副生成经常出现自由度过约束或欠约束。但作为研究探索方向前景相对清晰。5.2 结合仿真的自动化验证单纯生成几何模型不等于最终可以制造机械零件还需要强度分析和可制造性验证。这个扩展方向目前在尝试把text-to-cad生成的STEP模型直接送入仿真流水线自动执行网格划分、应力分析和变形计算最后生成一份包含安全系数和材料用量的报告。如果这个流程能完全自动化工程师的角色会进一步从“建模员”转变为“需求审核者”只负责确认模型是否满足设计意图即可。这需要打通三个环节STEP文件解析、自动网格化、仿真参数映射。物理仿真需要大量的材料参数、边界条件和载荷数据这些信息在自然语言中往往不完全包含。我目前的做法是把这些参数作为环境变量在Prompt模板中声明默认值用户可以在前端界面二次修改后再提交仿真。这条路走下去text-to-cad的能力边界可以从“几何生成工具”扩展到“初步设计验证工具”应用价值会再上一个台阶。5.3 多模态输入融合有一类需求纯用文字很难精确描述比如“一种类似现有图纸上的某个异形支架结构但尺寸缩小三分之一”。这类需求如果只用文本输入LLM很难理解具体形态。所以我在实验把图片输入也接入流程用视觉模型对输入图片做初步特征识别输出结构化描述文本再把文本拼接进入现有的text-to-cad提示词模板。生成的结果虽然精度不算特别高但对于快速原型阶段的参考建模已经足够。比如一张手绘的支架草图视觉模型识别出大致轮廓和孔位数量输出“L型支架长边100mm短边60mm厚度5mm3个安装孔”这样的结构化描述后续的代码生成流程完全复用现有管线。这种混合输入的实用性很高因为很多现场的初始需求就是一张照片或者一张草稿纸数字化设计需要经历“从图和话到文本再到参数化代码”的转化链条。写在最后的实操心得text-to-cad虽然听起来很“前沿”但真正落地的时候你会发现最大的瓶颈不在模型能力而在工程约束的表达。模型能不能把一句话变成一段代码现在基本已经解决了但这段代码是否符合行业规范、是否便于后续修改、是否考虑了公差配合这些问题需要从提示词到代码校验的整套机制来保障。我个人实际跑下来的体会是先用小零件把链路跑通不要一上来就挑战复杂的异形件。从带孔底板、法兰盘、轴套这类基础零件开始逐步积累一套完善的提示词模板和校验规则再扩展到更复杂的零件族和装配体。text-to-cad的实用价值不是一次生成一个完美模型而是它能把大量重复性、变体式的建模消耗自动消化掉让真正有创造性的设计工作留给人来做。一个值得记住的小技巧所有生成的脚本都纳入版本管理形如part_name_v1.py、part_name_v2.py因为每一次生成都是对设计知识的一次编码沉淀积累下来就是你自己项目的文本到CAD资产库。
返回列表