全部文章

一个会自己量尺寸的 CAD agent

· 约 4 分钟

语言模型写 CAD 代码有一个根本的难处:它看不见结果。代码跑通了,它就倾向于认为对了。一个本该在 x = 40 的孔被写到了 35,构建照样成功,报告里没有报错,模型在屏幕上也像那么回事。

所以「构建成功」这件事,我们在给 agent 的说明里专门写了一句:一次干净的构建意味着它能编译,不意味着它是对的。 剩下的就是给它一些能读的反馈,让它自己发现 35 不是 40。

构建报告:一个固体的指纹

每次改完代码,agent 必须重新构建一次,拿回来的不是「成功」两个字,是一份报告:

这份报告不是裁判,是指纹。agent 要拿它对着需求读:要求 Ø13 通孔在 x = 40,报告里有一行 Ø13 @ x 35,位置错了;要求一个 4 mm 深的台阶,平面那一行里本该出现一个相差 4 的坐标,没有,就是台阶没切出来;多出一行「disjoint solids」,说明某个倒角或者切口把一个凸台切断了。

诊断里的每一条我们都当真。fillet-capped 是说某个圆角帮手给的比你要的小,因为你要的尺寸在那个角落放不下,该做的是改周围的形状,而不是接受被削掉的数值。body-interference 是两个零件在同一处占了体积,这是真缺陷,不是噪声,解法是改间隙或者位置,永远不是调高容差。接触不算干涉,不会出现在这里。

截图:先看,再量

报告建干净了,下一步是看。snapshot 出一张 2 × 2 的图:俯视、等轴测、正视、右视,三个正交视图共享同一个比例和中心,所以同一个特征在三张图里能对上位置。

着色的图只画看得见的轮廓,所以不能从一张着色图断定「孔没了」。要对照工程图的时候用线框加透视模式:隐藏在材料后面的边画成虚线,和图纸一样,一个腔、一道壁厚、一个盲孔都显出来,一个投影一个投影地比。

探针:报告答不了的问题,自己写一段去量

有些问题报告答不了:一条接缝有没有真的合上,一道壁厚到底多少,一个圆角到底切没切到那条边。agent 可以写一小段代码,附在模型后面跑,模型里所有顶层的名字都在作用域里,再加一个 measure 库。

def test_bore_position():
    bores = measure.cylinders(model, radius=6.5)
    assert len(bores) == 1
    assert abs(bores[0].at("X") - 40) < 0.01

def test_wall():
    walls = measure.walls(model)
    assert min(w.thickness for w in walls) >= 1.6

每个 test_* 单独跑,一个 API 猜错只让那一条失败,别的照常。断言对的是建出来的几何,对一个常量断言它自己什么也证明不了。

有一条规矩值得单独说:量尺寸用 `measure`,别自己过滤 `.faces()`。 一个条件写松了,一个不相干的面就平均进了数字,结果错了但看起来很合理,这比直接报错糟糕得多。

还有一条:同一步失败两次之后,别再整个模型重建第三次,把那一步单独拎出来,打印它真正产生的东西,边数、面积、体积、合不合法。一次孤立的探针能钉住出错的那一步,再一次盲目的整体重建不能。

旋钮:每一个滑块推到两端

模型里标了 #@ 的常量会变成分享页上的滑块和开关。这是对打开链接的人的承诺:这个滑块从这里到那里都能动。knobs 把每个旋钮单独推到两个极端各建一次,结果是 OK、INERT(动了但几何没变,通常是这个数没接到几何上)、WARNS 或 BROKEN。交付前跑一次。

它解决了什么,没解决什么

有了这一套,简单件常常能一次拿到:盒子、支架、垫片、一个带孔的板,agent 自己量出错位、自己改。复杂件还是要磨几轮,尤其是需要空间想象的装配关系。而且「它能自己量」和「它每次都去量」是两回事,让它养成习惯花的功夫,不比写这些工具少。

怎么知道磨得有没有进步,是另一个问题,也是下一篇。那一篇不太好看。

更多文章