最近和几个做机械设计的朋友聊天,发现大家不约而同在琢磨一件事:能不能直接跟电脑说“帮我画一个法兰盘”,它就把图纸给出来?这个场景听起来很科幻,但实际落地时卡点不在大模型能不能听懂人话,而在它听懂之后,怎么把话变成一份真正能打开、能编辑、能拿去加工的CAD文件。我花了两周时间,把 OpenClaw 这个开源 Agent 框架和 CAD 数据解析生成流程完整跑了一遍,今天把整个过程里的关键思路、实现细节和踩过的坑一次性说清楚。
先说结论:在对话中生成工业设计图这件事,真正的技术核心是“结构化数据的解析与生成”,大模型只负责把自然语言翻译成中间指令,真正决定图纸能不能用的,是 CAD 数据这一层的处理和转换。OpenClaw 这类 Agent 框架恰好把这两部分粘合在了一起。
1. 对话式工业设计:OpenClaw 在这个场景里到底扮演什么角色
1.1 从“聊天”到“图纸”:一条完整的技术链路
先拆一下用户和机器之间的完整交互链路。你输入一句话,比如“设计一个 DN50 的法兰,8 个螺栓孔,厚度 16mm”,这句话本身只是一段自然语言。要让 CAD 软件最终显示出一张法兰图纸,中间需要经历三个层级:语义理解层、参数提取层、图形生成层。
语义理解层把用户的话做意图识别和实体抽取,这一步现在的主流做法是交给大模型完成,OpenClaw 在这里承担的就是对话入口和意图路由的角色。参数提取层负责把识别出的“法兰”“DN50”“8孔”“16mm”转成结构化的数据字典,比如 {"类型": "法兰", "公称直径": 50, "螺栓孔数": 8, "厚度": 16}。图形生成层拿到这个数据字典后,调用 CAD 内核或绘图库生成实际的矢量图形文件。
很多人一上来就想着让大模型直接输出 DXF 文件内容,这是个大误区。大模型擅长的是文本生成,而 CAD 文件尤其是 DWG 这类二进制格式,根本不是自然语言能稳定生成的。正确做法是把生成任务拆开,让大模型只做参数提取和代码生成,实际的图形绘制交给专门的处理库来完成。这就好比炒菜,大模型是配菜师傅,负责把食材切好按菜单配齐,真正掌勺的还是 CAD 库。
1.2 为什么选 DXF 作为对话生成的中间格式
在接触 OpenClaw 之前,我最早试过让 Agent 直接生成 DWG 文件,结果惨不忍睹。DWG 是 Autodesk 的私有二进制格式,没有公开的完整规格说明,第三方库读写起来要么不稳定要么收费。后来我换成 DXF,问题一下子少了很多。
DXF 是 Autodesk 推出的开放交换格式,本质是带标签的文本文件。它的好处有三个:其一,纯 ASCII 文本,生成和解析都非常稳定,大模型就算不直接生成它,我们也能用几行代码轻松构造;其二,几乎所有主流 CAD 软件都支持 DXF 导入导出,兼容性覆盖极广;其三,DXF 的实体模型足够表达工业设计里绝大多数需求,比如直线、圆弧、多段线、圆、文字标注、尺寸标注、图层、块引用等等。
所以我的技术选型思路是:OpenClaw 负责对话和意图理解,Python 负责生成 DXF,然后由 CAD 软件负责打开和二次编辑。三者各司其职,把大模型不擅长的精确计算和格式生成交给了专用工具,整体稳定性大幅提升。
注意:如果你的下游流程必须使用 DWG 格式,也建议先生成 DXF,再用 CAD 软件的批处理功能批量转成 DWG,这条路比让 Agent 直接生成 DWG 要可靠得多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CAD 数据解析:让 Agent 读懂图纸的核心步骤
2.1 CAD 文件格式的地图:DWG、DXF、STEP 各自的位置
做对话式设计的时候,Agent 不仅要能“画图”,还要能“读图”。用户可能会丢过来一个现有的 CAD 文件,告诉你“按照这个改一下”,这时候 Agent 就得先解析文件内容。搞清楚常见格式的定位很重要。
| 格式 | 类型 | 适用场景 | 解析难度 |
|---|---|---|---|
| DWG | 二进制私有格式 | AutoCAD 原生编辑、工程交付 | 高,依赖闭源库或 ODA 转换 |
| DXF | 文本开放格式 | 数据交换、程序生成与解析 | 中,有成熟的 ezdxf 等库 |
| STEP | 文本标准格式(ISO 10303) | 三维模型数据交换、CAM 加工 | 中高,侧重三维实体和装配 |
| IGES | 文本标准格式 | 传统三维/曲面数据交换 | 中 |
| PDF/DWF | 文档格式 | 图纸审阅打印 | 低,但无法还原为参数化模型 |
我的建议是:在 Agent 的流程里,统一把输入文件先转换成 DXF 再做信息抽取。如果收到的是 DWG,可以用 ODATools 或者 AutoCAD 自身的命令行批量转成 DXF,再交给 Python 解析。这样你只需要维护一条解析管线,而不是针对每种格式各写一套。
2.2 DXF 解析的实操拆解:段、实体、属性
DXF 文件的结构其实非常有规律。它由多个 SECTION(段)组成,常见的有 HEADER(文件头)、TABLES(表)、BLOCKS(块)、ENTITIES(实体)和 EOF(文件结束标记)。每一行是一个组码(group code),下一行是对应的值。组码是有意义的,比如 0 表示实体类型、8 表示图层名、10/20/30 表示 X/Y/Z 坐标。
用 Python 的 ezdxf 库解析 DXF 非常简单,核心代码就几行:
python复制import ezdxf
doc = ezdxf.readfile("flange.dxf")
msp = doc.modelspace()
# 遍历所有实体
for entity in msp:
print(f"实体类型: {entity.dxftype()}")
if entity.dxftype() == "LINE":
print(f" 起点: {entity.dxf.start}, 终点: {entity.dxf.end}")
elif entity.dxftype() == "CIRCLE":
print(f" 圆心: {entity.dxf.center}, 半径: {entity.dxf.radius}")
elif entity.dxftype() == "LWPOLYLINE":
print(f" 顶点列表: {list(entity.get_points())}")
这里要注意一个细节:DWG 和 DXF 都有精度问题。解析回来的坐标经常是类似 (100.0000000001, 50.0000000002) 这样的数值,直接拿去跟用户输入比对会出现莫名其妙的误差。我习惯在解析后立刻做一次四舍五入,统一保留到小数点后精确度合适的位数,比如工程图上常用 0.01mm 精度,那就统一 round(x, 2)。
2.3 解析过程中最常见的三类“坑”
第一类坑是版本兼容性。不同 CAD 版本生成的 DXF 在结构上有细微差别,尤其是老版本 DXF 里很多表的字段定义不太一样。ezdxf 读取高版本 DXF 一般没问题,但偶尔会遇到无法识别的实体类型,比如某些第三方插件生成的自定义实体。遇到这种情况不要强行解析,直接跳过并在日志里记录,至少保证主流程能跑通。
第二类坑是炸开的块。DXF 里的块(BLOCK)是一种复用机制,实际图纸里同一个螺栓可能只定义一次,然后多次引用。解析时如果不去炸开(explode)块,你只看到引用插入点,不知道里面具体图形长什么样。用 ezdxf 时可以调用 entity.explode() 方法把块引用展开成基本实体。
第三类坑是中文字符编码。很多国内 CAD 图纸的文本实体用的是 GBK 编码,直接按 UTF-8 读会乱码。ezdxf 库对编码处理得还凑合,但保险起见,我解析完所有 TEXT/MTEXT 实体后,会用正则做一次常见乱码模式校验,比如出现 锟斤拷 这类经典乱码字符就标记为编码异常,让 Agent 知道需要二次确认。
3. CAD 数据生成:从自然语言到可编辑图纸
3.1 三条生成路径对比:文本直出、脚本驱动、API 调用
把对话内容变成 CAD 图形,目前实践下来有三条可行的技术路径,各有适用场景。
第一条是文本直出。严格来说就是让大模型直接输出 DXF 格式的文本内容。这么做的好处是链路最短、不需要额外代码,坏处是大模型对坐标和格式的精确控制能力很差,生成的文件经常直接打不开。我试过让 GPT 级别的模型输出 DXF,10 次里能正常打开的大概只有 2-3 次,而且几何关系经常是错的。这条路径基本只能应付教学演示,生产环境不推荐。
第二条是脚本驱动。让大模型输出 Python 代码,由脚本调用 ezdxf 这类库来画图。这是我在生产环境里用得最多的一条路径。大模型负责生成绘图脚本,本地环境负责执行脚本并把结果保存为 DXF。因为绘图逻辑完全掌控在代码里,所以几何精度高、文件结构稳定。
第三条是 API 调用。如果公司已经部署了 CAD 服务器的 API(比如基于 CAD 内核的云渲染服务),可以让 Agent 直接调用这些接口。这条路对企业来说是最终形态,因为它能直接对接产品数据管理、工艺规划等系统,但搭建成本高,适合已经有信息化基础的企业。
3.2 用 Python 生成一张法兰盘 DXF 的完整示例
我把最常用的脚本驱动路径展开讲讲。假设用户说“画一个 DN50 法兰,外径 165mm,内径 61mm,8 个螺栓孔,螺栓孔中心圆直径 125mm,厚度 16mm”,OpenClaw 提取出参数后,交给 Python 生成脚本。
下面是一段可直接运行的生成代码:
python复制import ezdxf
from ezdxf.enums import TextEntityAlignment
import math
def generate_flange(out_path, outer_d, inner_d, bolt_d, bolt_count, thickness):
doc = ezdxf.new("R2010", setup=True)
msp = doc.modelspace()
# 图层设置
doc.layers.add("轮廓线", color=7)
doc.layers.add("中心线", color=1, linetype="CENTER")
doc.layers.add("标注层", color=3)
outer_r = outer_d / 2
inner_r = inner_d / 2
bolt_r = bolt_d / 2
# 外圆和内圆
msp.add_circle((0, 0), outer_r, dxfattribs={"layer": "轮廓线"})
msp.add_circle((0, 0), inner_r, dxfattribs={"layer": "轮廓线"})
# 中心十字线
msp.add_line((-outer_r - 10, 0), (outer_r + 10, 0), dxfattribs={"layer": "中心线"})
msp.add_line((0, -outer_r - 10), (0, outer_r + 10), dxfattribs={"layer": "中心线"})
# 螺栓孔
for i in range(bolt_count):
angle = 2 * math.pi * i / bolt_count
x = bolt_r * math.cos(angle)
y = bolt_r * math.sin(angle)
msp.add_circle((x, y), 6.5, dxfattribs={"layer": "轮廓线"}) # M12 螺栓孔径
doc.saveas(out_path)
print(f"已生成: {out_path}")
generate_flange("flange_dn50.dxf", 165, 61, 125, 8, 16)
这段代码有几个要点值得展开说。doc = ezdxf.new("R2010", setup=True) 里的 setup=True 会预设一些基础的标注样式和线型,如果不加这一句,后续引用 CENTER 线型时会报错。图层我单独建了轮廓线、中心线和标注层,目的很直接,后续在 CAD 里做分层管理和打印设置会方便很多。
中心十字线的长度我故意比外径多出 10mm,这是机械制图的规范,中心线要超出轮廓线一段距离,实际工作中这个超出量通常取 3-5mm,长一点也无妨,关键是不能短。
3.3 尺寸标注与图层的处理细节
如果只是生成几何轮廓,图纸离“能用”还差一步,那就是尺寸标注。没有标注的图纸只能算示意图,下发给加工车间肯定会被打回来。自动标注这块,ezdxf 其实内置了很完整的尺寸标注能力。
python复制# 添加线性标注(外径)
dim = msp.add_linear_dim(base=(0, -30), p1=(-82.5, 0), p2=(82.5, 0), dxfattribs={"layer": "标注层"})
dim.render()
这里 base 是标注线的位置,p1 和 p2 是标注的两个测量点,render() 是生成具体标注图形的关键调用,漏掉这一步标注不会显示。说起来简单,但自动标注的排版是个老大难,实际项目里我很少依赖纯自动标注,更常用的是让 Agent 生成标注代码,然后由绘图员在 CAD 里手动微调位置。
另一个关键点是图层规范。国内制造业的图层命名习惯跟国外模板不太一样,比如“轮廓线”“中心线”“标注层”“剖面线”这些命名,我在代码里直接用中文图层名是为了一打开 CAD 就能无缝对接现有模板。虽然 DXF 标准允许任意字符串做图层名,但要注意有些老版本 CAD 对中文图层名支持不友好,如果目标环境是国外版本建议用英文图层名加注释。
注意:生成 DXF 时,请务必设置正确的线性比例(LTSCALE)。很多图纸打开后中心线显示成实线,就是因为没有设置全局线型比例。可以加一句
doc.header["$LTSCALE"] = 10,具体值根据图纸比例调整。
4. 在 OpenClaw 里落地:Skill 配置与完整对话流程
4.1 OpenClaw 的基本结构与 Skill 机制
OpenClaw 是社区里口碑不错的开源 Agent 框架,可以把它理解成一个带“手脚”的对话机器人。它本身不直接提供 CAD 能力,但通过 Skill(技能)机制和工具调用来扩展。这也是我选择它的原因:框架的定位更像一个调度中枢,具体干活的能力都通过注册函数的方式放进去。
一个 Skill 本质上是一个可以被大模型调用的函数,包含三部分:函数名、参数描述、执行代码。OpenClaw 的 Agent 在理解用户需求后,会自动判断该调用哪个 Skill,并按照参数描述把对话中提取的信息填进去。这就是“对话生成图纸”的中间桥梁。
实际配置一个 CAD 生成 Skill 时,参数描述写得越清楚,大模型调用的准确率越高。比如"外径"这个参数,你要写清楚“法兰外径,单位毫米,浮点数”,大模型才知道要把“165”填到这里;如果你只写“outer_d”,它可能猜不出对应关系。
4.2 让 OpenClaw 调用 CAD 生成工具的最小配置
我在本地跑通的最小配置包含四个文件:Agent 主配置、法兰生成脚本、Skill 定义和对话调用的模型配置。核心的 Skill 定义大概是这样的结构:
python复制# skills/cad_generator.py
from openclaw import skill
@skill.register(
name="generate_flange",
description="根据参数生成法兰盘DXF图纸",
parameters={
"outer_d": {"type": "number", "description": "法兰外径,单位mm"},
"inner_d": {"type": "number", "description": "法兰内径,单位mm"},
"bolt_d": {"type": "number", "description": "螺栓孔中心圆直径,单位mm"},
"bolt_count": {"type": "integer", "description": "螺栓孔数量"},
"thickness": {"type": "number", "description": "法兰厚度,单位mm"},
}
)
def generate_flange_skill(outer_d, inner_d, bolt_d, bolt_count, thickness):
# 调用上文的 ezdxf 生成逻辑
# 返回文件路径给 Agent
return file_path
配置好之后,OpenClaw 会在对话中自动识别意图并填充参数。实际运行中我建议把返回给用户的路径用绝对路径,避免 Agent 拼接相对路径时出错。另外,建议把生成的文件名加上时间戳,比如 flange_20250607_1530.dxf,避免不同用户同时生成时互相覆盖。
4.3 一段完整的对话演示与结果验证
我实际跑通的一段对话记录是这样的:
用户:帮我画一个 DN50 的法兰盘,外径 165,内径 61,8 个螺栓孔,孔分布圆直径 125。
OpenClaw:好的,我将为您生成该法兰盘的 DXF 图纸。已生成文件
/workspace/flange_20250607_1530.dxf,包含外圆、内圆、8 个螺栓孔及中心线。您可以用 CAD 软件打开查看。
这个流程看起来简单,但为了让它稳定跑通,我在脚本里加了三个额外校验步骤。第一是参数范围校验,比如外径必须大于内径、螺栓孔数必须能被 360 整除,否则脚本直接抛异常返回给 Agent 去和用户沟通,而不是生成一张畸形图纸。第二是生成后的文件存在性和大小校验,确保文件真的写出来了再回复用户。第三是在对话里明确告知文件位置和包含的图形元素,这样用户能快速判断是否满足需求。
生成的 DXF 我每次都会用 ezdxf 重新读取一遍做“自检”,打印出所有实体数量和各图层分布,这个习惯帮我挡住了很多低级错误。如果读到实体数为 0,基本可以确定生成过程的某个环节出了问题,这时候再让 Agent 去查看脚本日志定位原因。
5. 常见问题与排查技巧实录
5.1 生成文件打不开或显示异常
这是新手遇到最多的情况。生成的文件在 CAD 里打不开,大概率是 DXF 版本设置过高。很多人用 ezdxf.new() 不指定版本,默认可能生成 R2018 格式的 DXF,碰到用低版本 CAD 的单位就尴尬了。我统一用 ezdxf.new("R2010"),这个版本兼容性最好,从 AutoCAD 2008 到最新版都能正常打开。
还有一种情况是文件能打开,但显示空白或者图形跑到很远的地方。这多半是坐标系问题,有一版脚本我把螺栓孔坐标计算成了极坐标的弧度制还是角度制搞混了,导致所有孔都重叠在同一个位置。排查方法很简单,用 ezdxf 读回文件,打印所有实体的坐标范围,如果 min 和 max 的跨度异常大或者所有圆心都重合,那就是坐标计算有问题。
5.2 单位与比例错乱
CAD 世界里最坑的事情就是单位。用户在对话里说“厚度 16”,可能是 16mm、可能是 16cm,也可能想的是 16 英寸。我在 Skill 的参数描述里强制标注“默认单位为 mm”,但用户不一定会按这个来。现在的处理办法是:在对话里主动向用户确认单位,尤其是当数值看起来不符合常理时。比如法兰外径“16”,我会反问“你说的单位是 mm 吗?16mm 外径的法兰比较少见”。
还有一类比例问题出在 DXF 尺寸标注上。生成的图形是 1:1 的实际尺寸,但是 CAD 布局空间的视口比例经常没有设置,导致打印出来要么超大要么超小。这个问题我没有在脚本层面完全解决,目前是靠模板文件和一个 after-open 的脚本来自动设置视口比例。
5.3 中文字体与 SHX 字体问题
生成的 DXF 里如果带中文文字,比如标注文本写的“法兰 DN50”,在 CAD 里打开经常会变成一排问号。这是因为 DXF 里引用的字体找不到。我用 ezdxf 的标注样式时,会显式指定一个 TTF 字体,比如:
python复制doc.styles.new("工程字", dxfattribs={"font": "simfang.ttf"})
但要注意,就算 DXF 里指定了字体,如果打开图纸的 CAD 机器上没有安装这个字体,照样显示乱码。最稳妥的做法不是因为追求效率用默认字体,而是在交付时附带一个字体说明文件,或者直接把文字炸开成线条。有些单位的图纸规范要求把所有文字转成曲线,这样文件在任何机器上都不会乱码。
5.4 Agent 交互中的上下文过长与参数幻觉
还有一个很隐蔽的坑:当 Agent 对话轮次超过十几轮之后,大模型可能会在调用 Skill 时“遗忘”之前的参数,甚至凭空捏造数值。比如用户前面说“内径 61”,到后面几轮改口说“内径改成 55”,但 Agent 执行生成时却传了 61,或者干脆传一个完全没出现过的数值。
我试了两套方案应对。第一套是在 Skill 调用之前强制让 Agent 向用户复述一遍完整参数列表,确认无误再执行。第二套是给每个对话会话创建一个独立的参数缓存文件,Agent 每次提取参数时先读取缓存文件里的值,再结合当前轮次做修改。用了第二套方案后参数幻觉的情况明显减少。
另外千万不要让 Agent 在生成时做复杂的运算,比如“螺栓孔直径 6.5,改成 8 个位置均布”这种计算尽量放到底层脚本里做,大模型对数字计算的稳定性比专门计算函数差很远。
6. 从“能画”到“能用”:高级方向的三个扩展建议
把对话生成 DXF 跑通只是第一步,实际工业场景里还有很多可以升级的方向。我这里只是梳理几个我自己觉得最有价值也最可行的扩展点,供大家参考。
第一个方向是模板化参数化设计。把企业里常用的零部件做成参数化模板,比如法兰、轴承座、支架、盖板这些,每个模板定义好关键参数和几何约束,Agent 只负责把用户对话里的自然语言参数映射到模板字段上。这样做的好处是生成的图纸大概率符合企业制图规范,因为有模板兜底。我实际已经在做的几个模板,生成的图纸基本不需要人工调整就能直接进工艺环节。
第二个方向是生成结果自动走一次规则校验。在脚本层接一个简单的几何规则引擎,比如检查零件是否满足最小壁厚、孔间距是否小于标准要求的极限、有没有自相交的轮廓线。这些规则不复杂,但能拦住很多“生成成功但没法用”的图纸。大模型本身不具备空间分析能力,这类精确几何判断交给规则引擎再合适不过。
第三个方向是做多轮迭代修改。很多用户第一次提需求不会说得那么全,往往是“先画一个大概的,我看看再改”。这一步需要 Agent 能读取已生成的 DXF 文件,识别关键实体,然后依据用户的修改要求直接改对应实体的属性。这个方向我在测试环境已经能跑通基础的“改尺寸”流程,离生产还有段距离,主要卡在“用户指着一个图形说把它挪一下”这类指代消解上。
就我个人这段时间的体会而言,OpenClaw 这类 Agent 框架结合 CAD 数据解析生成,真正改变的其实不是画图速度,而是把“画图”这件事从软件操作层面解放出来,让你能直接把注意力放在设计目标本身。当然,这条路走起来也不是没有代价,中间要处理格式兼容、单位换算、标注规范这些不起眼但特别耗时的细节。上面这些内容是我实际跑项目中积累下来的一手经验,希望能给准备入这个方向的同行省掉一些试错的成本。
最后再分享一个小技巧:不管 Agent 生成得多顺畅,交付前一定要亲自打开 CAD 看一眼图纸。自动化能解决 90% 的重复劳动,但剩下的 10% 判断力,永远得留在人这边。
