你的智能体没糊涂,是本体的问题

我对相同的 2,435 个事实用三种不同方式建模,给 Microsoft Foundry 上的一个智能体四个遍历工具,没有其他通往答案的路径,然后测量知识的形状每道题的成本,因为当智能体表现不佳时,每个人都会想到的修复方案是用更大的模型,这确实有效,但代价大约是修复图结构的十四倍。

关于数据和数字的说明。

本实验中的每个实体都是合成的、虚构的:人物、公司、地点和保险公司本身都是从发明的词表中用固定种子生成的,没有任何一个指代真实的人物、公司或地点。第 IV 节中的数字来自瑞典中部的实时活动:推理在专用的 Microsoft Foundry 部署上进行,知识存储在 Azure Cosmos DB for Apache Gremlin 账户中,每个工具调用都是对实时图的 Gremlin 查询——四百八十个智能体片段,430 万 token,8.09 美元。同一网格第一次运行时工具读取的是生成器的文件而非数据库,花费 7.74 美元。那次早期的网格在全文中被称为交叉检查运行;这里报告的所有测量都来自 Cosmos 活动,交叉检查仅在两次运行能揭示单次运行无法说明的内容时才出现。

1、没人升级的那一层

现在每个发布智能体的团队中都上演着一个仪式。智能体漏掉了它应该回答的问题。有人提出用更大的模型。账单翻倍,遗漏点转移,然后回顾总结得出结论:智能体还没准备好。

我参加过那种回顾。几乎从不被提上桌面的是智能体实际推理的东西:它被给予的知识的形状。不是事实,是形状。理赔员是一个节点还是 JSON 块里的一个字符串。边是叫 assessed_by 还是 related。从一个索赔到达一个保单持有人需要一跳还是五跳。

我之前两篇文章测量了一个做决策的系统,然后构建了固定其决策的工具 [1][2]。与此同时,Towards Data Science 上的一个三部分系列构建了一个持久知识层并把智能体放在其上,使用了一个合成保险语料库 [3]——这是将知识视为设计产物而非检索桶的架构论证。本文是该系列从未有过的测量:它向下深入一层,到智能体推理的基底,问了一个我没见过有人用数字回答的问题:保持模型、工具、提示和事实不变,只改变本体论的形状,智能体的准确性、它必须做的工作以及账单会发生什么变化?

然后,因为第一个答案引出了一个明显的反对意见,我在一个大得多的模型上重新运行了整个实验,问后续问题:你能用钱绕过一个形状糟糕的图吗?你可以。有趣的是价格,以及它说明你应该构建哪种形状。

方法与之前一样。没有收据就没有观点。

2、一个真相的三种形状

领域是一本保险业务簿——保单持有人、保单、保障范围、索赔、理赔员、维修提供商、付款、地区。全部是合成的,全部是虚构的,从一个带种子的脚本生成一次:关于 507 个实体的 2,435 个规范事实,没有一个是真实的。

从这个单一事实库我构建了三个本体论。不是三个数据集——是同一数据集的三种形状,这个规则是实验的核心:每个变体必须不增不减地重新表达这些事实。 脚本遍历每个构建的图,从中重建事实集,并断言它与源完全相等。如果一个变体比另一个多知道或少知道一个事实,那场比赛衡量的就是数据覆盖范围而非设计。该证明在仓库的 CI 中运行,每次推送到主分支和每个拉取请求时都会运行,同时检查提交的数据是否与种子重新生成的字节相同,除非两者都通过,否则实验无效。公平起见有一个注意事项:扁平和有形状的构建器是独立于该事实集编写的,因此它们的检查是实质性的,而规范化图是从事实集直接编码的,因此无损性更接近于构造而非证明。

扁平的那个是大多数团队实际首先发布的:两种胖节点类型。保单持有人节点以 JSON 块的形式在其属性中携带其保单及其保障范围。索赔节点以相同方式嵌入其理赔员、其提供商和其付款。一种通用边类型——related——连接持有人到索赔,这就是整个模式。没有什么缺失;一切都是被埋藏的。

规范化的那个是相反的失败,它不是稻草人——它是教科书会赞扬的东西。完全实例化:实体是裸露的 Resource 节点,只携带自己的类型,每个属性都是自己的 Attribute 节点,通过通用的 has 边到达,每个关系都是自己的 Relation 节点,带有 subjectobject 边。学术上无可挑剔。要了解任何东西需要四跳。

有形状的那个是为它实际的消费者设计的:具有刻意粒度的类型化节点,名称说明其含义的类型化方向边——filed_againstassessed_bysettles。保单被保单持有人 held_by,有形状的图重复使用相同的名称进行一个刻意的添加:九十个派生的 held_by 边,从索赔直接跳到保单持有人,将索赔-保单-持有人路径折叠成单跳。重复使用名称是关键——无论从哪端看关系意味着相同的东西,所以智能体不必学习第二套词汇。那九十个边在图中被标记为 派生,它们不增加知识,无损性证明将它们排除在重建之外,因为它们是已有事实上的算术运算,不是它们自己的信息。

仅计数就预示了论点。相同的真相在扁平图中是 130 个节点,在有形状的图中是 507 个,在规范化的图中是 2,942 个。每个额外的节点都是智能体可能必须访问的地方。

而且因为差异比描述更容易看到,这里是一个实体——结果部分将使其闻名的保单,作为每个变体实际存储的原始数据:

三种形状都存在于 Azure Cosmos DB for Apache Gremlin [4] 中,每种一个图容器,这就是智能体遍历的内容:下面每次测量中的每个工具调用都解析为对实时图数据库的 Gremlin 遍历。生成器写入事实库,加载器将其物化到 Cosmos 中,加载会自我验证——顶点和边计数必须与源完全匹配,否则报告不匹配,而不是留半个构建的图以后被发现。

将三种设计放入同一个数据库,在同一个工具层下,使用相同的索引默认值,这使它们可比较。这也使它们可见。属性图无处可藏:你可以问它知道什么,答案就是设计。

再读一遍第一列。扁平本体论的边比顶点少,它的五个节点完全没有连接——它们是碰巧没有索赔的保单持有人,在这个设计中世界上没有其他东西能到达它们。这是一个持有几乎不是图的东西的图数据库。所有结构仍然在那里,但它已溶解到每个顶点 8.2 个属性中,在那里它是文本而非拓扑。这就是第 IV 节关于的设计决定,图存储将其陈述为事实而非观点。

规范化列是镜像。它是三种中最均匀的图——几乎恰好每顶点一条边,没有孤立,每个节点携带 1.6 个属性,因为实例化将每个事实变成相同的三种形状重复 2,942 次。它结构过剩但完全没有词汇:整个保险业务只有三种顶点标签和三种边标签。

有形状的图连接最多,每顶点 1.36 条边,也是唯一一个标签命名领域的图。八种顶点标签,九种边类型。问每个图它包含什么类型的东西,差异立即显现:

g.V().groupCount().by(label)
g.V().groupCount().by(label)
  • 扁平:{claim: 90, policyholder: 40}
  • 规范化:{Resource: 507, Attribute: 1834, Relation: 601}
  • 有形状:{claim: 90, policy: 75, coverage: 216, policyholder: 40, payment: 59, provider: 12, adjuster: 10, region: 5}

一行比本节更好地说明了观点:

g.V().hasLabel('policy').count()
g.V().hasLabel('policy').count()

那两个零意味着不同的事情,第 IV 节主要关于那个差异。扁平图丢失了实体。规范化图保留了实体但丢失了词汇:你可以在那里到达保单,但只能通过走到它,永远不能通过命名它。这些都不是我选择存储数据方式的人为产物,它们是同一数据库中的三种模式,回答同一个查询。

同样的不对称性出现在回答真实问题的成本中。拿一个来说:索赔 C-31020 所针对的保单的保单持有人住在哪个城市? 三个图都返回 Larkfield,因为三个都包含相同的事实。不同的是行走路径。

# 有形状 - 派生快捷方式折叠了路径
g.V().has('number','C-31020').out('held_by').values('city')
# 扁平 - 一跳,但只是因为索赔和持有人是仅有的两样东西
g.V().has('number','C-31020').in('related').values('city')
# 规范化 - 相同的答案,五步和两次解包之后
g.V().has('value','C-31020').in('has')
     .in('subject').has('kind','filed_against').out('object')
     .in('subject').has('kind','held_by').out('object')
     .out('has').has('attr','city').values('value')
# 有形状 - 派生快捷方式折叠了路径
g.V().has('number','C-31020').out('held_by').values('city')
# 扁平 - 一跳,但只是因为索赔和持有人是仅有的两样东西
g.V().has('number','C-31020').in('related').values('city')
# 规范化 - 相同的答案,五步和两次解包之后
g.V().has('value','C-31020').in('has')
     .in('subject').has('kind','filed_against').out('object')
     .in('subject').has('kind','held_by').out('object')
     .out('has').has('attr','city').values('value')

智能体不会写那些查询——它一次一个工具调用地发现路径,这正是整个实验。但查询展示了它在发现什么,以及有多少东西可以发现。

3、工具——四个工具和一张收据

智能体刻意保持最小化,因为智能体不是实验。一个针对 Microsoft Foundry 模型部署的普通函数调用循环,完全按照 Foundry 文档描述的 Chat Completions API 工具使用方式构建 [5];一个固定的系统提示;每个问题十六轮模型调用的预算,之后该片段被放弃;以及四个工具,在所有三种本体论中签名相同:

  • find_nodes - 对节点属性和 ID 的子字符串搜索,上限二十个匹配
  • get_node - 读取一个节点的类型和属性
  • traverse - 列出节点的邻居,可选按边类型和方向,上限三十
  • describe_edges - 从这里可以走到什么,带计数

每个都解析为对 Cosmos 的 Gremlin。get_nodefind_nodes 各是一个遍历——点读和扫描;traversedescribe_edges 各发出三个,因为它们先检查节点是否存在,然后分别遍历出边和入边。智能体自己不发出这些——它请求一个节点或邻居,得到一个小 JSON 答案回来,这是图存储上工具表面在生产中的通常外观,也使查询语言远离模型。

遍历是通往答案的唯一路径。智能体永远看不到模式,永远不写 Gremlin,并被指示用字面的 NOT_MODELED 拒绝——当图不包含问题所需的事实时。

上限很重要:形状糟糕的图以额外的工具调用支付其扇出成本,而不是一个巨大的响应,这正是生产中真实工具预算的行为方式。注意十六轮预算限制的是对话轮次,不是工具调用——单轮可能同时请求多个工具,所以这些活动中最忙的片段在十六轮内做了六十个调用。

在真实图数据库上运行这些有三件事值得一提,因为每个都让我重建了一次。Cosmos 拒绝多语句脚本,所以批量加载是每个请求一个遍历,吞吐量来自并发而非批处理。有一个硬的六十秒请求超时,这意味着 g.V().drop() 无法清除几千个顶点——它在中途超时,留下一个部分删除的图,所以清除必须分片进行。无服务器有一个吞吐量上限,将四十个并发写入的突发变成超时,所以加载器和智能体的工具层都用退避重试。这些都不 exotic;所有这些都区分了图表中的图存储和负载下的图存储。

评分是我最关心的部分,因为智能体评估通常是方法论变得松懈的地方。本实验中没有任何 LLM 判断。四十个问题——十个单事实查找,十个两到三跳的短遍历,十个需要长路径或子图聚合的,以及十个刻意不可回答的——由脚本从事实库生成,直接从原始事实计算每个正确答案。然后评分是机械的:数字必须匹配计算值,字符串必须包含它,不可回答的问题只有在智能体明确说明时才正确。没有本体论给自己的作业评分,没有模型判断另一个,正确性是比较而非观点。

而且因为智能体只能通过四个工具行动,每个答案都带着产生它的完整调用列表。我路由器文章的读者会认出那个模式:model 字段是那里的收据,路由锁使收据可执行,而这里路径就是收据

  • 当智能体回答时,我可以向你展示导致它的确切行走路径,当它失败时,追踪显示哪里形状丢失了它。

不可回答的频段值得它的一句话。十个问题询问事实库刻意不建模的东西——电话号码、电子邮件地址、天气、车辆识别号。正确的行为是回来说出来。一个发明一条边而非承认图没有边的智能体是这类系统中最危险的失败模式,据我所知几乎没人对此做检测。

4、遍历的成本

主要活动针对 Cosmos DB 中的实时图运行,推理在瑞典中部的专用 Microsoft Foundry 部署上进行:三种本体论,四十个问题,三轮完整运行,一个小模型保持不变——三百六十个智能体片段,310 万 token,七十美分。每个工具调用都是一个 Gremlin 查询。本节后面第二次活动在更大的模型上重复网格,再进行一百二十个片段,花费 7.39 美元。下面的每个数字都是由仓库中的脚本从记录的收据计算的;没有一个是手工输入的。

粗体标记一行中最佳结果。资源行被刻意不加粗:扁平图在所有四行中都是最低的,如下几节所示,部分节俭是它从未产生的答案的成本。

第一行是表中最不具信息性的数字,在有人引用它之前值得说明。 有形状的回答了 84.2% 的问题正确,扁平 78.3%,规范化 59.2%。但每个变体自己的准确性在三轮其他相同的运行中移动了 0.075、0.150 和 0.075,这意味着有形状和扁平之间六个百分点的差距没有超过自身的噪声。在这次活动中,三轮运行,我无法告诉你那两个形状在总体准确性上有差异。到规范化的二十五个百分点差距确实超过了,而且很轻松。

这看起来比实际结果弱。总体是不具信息性的,因为它平均了激烈不一致的频段,而不一致正是发现:

在单事实查找上,有形状的图以 0.967 击败扁平的 0.533——四十三个百分点的差距,对抗 0.100 和 0.200 的噪声基底,所以这个是信号,还有余量。在两到三跳遍历上,两者相同,都是 0.967。在最难的频段,它们的差距是 0.300 和 0.400,我不会宣布赢家。

所以两个形状不是更好和更差。它们以不同方式损坏,将它们平均成一个数字恰恰隐藏了值得知道的东西。当你必须找到某个东西时,扁平图失败并持续失败。当你已经有一个立足点只需要行走时,它和设计的一样好。

规范化是镜像,它的频段同样清楚地说出:查找 0.867——比扁平好,因为每个实体确实是一个顶点,然后随着行走变长是 0.467 和 0.133。它能找到任何东西但什么也完成不了。

它们也以不同方式失败,不只是在不同问题上。 每个形状面对三十个可回答问题三轮,所以九十个片段。按如何失败排序错过的地方就是机制显现的地方:

规范化耗尽轮次二十二次——其可回答片段的四分之一以智能体仍在行走结束。扁平几乎从未那样;它提前停止并自信地拒绝了十八个答案就在数据库中的问题。一个形状耗尽自己,另一个放弃。

扁平的失败更尖锐,追踪显示了一个我未预料的机制。这里是两个真实片段并排,同一个问题,保单 P-7009 的保费,同一个模型,同一个数据库,不同的模式:

扁平                                        有形状
find_nodes "P-7009"          -> 1 命中:     find_nodes "P-7009" type=policy
   保单持有人:PH-05 "Ivo Renner"            -> 1 命中: 保单:PL-009 "P-7009"
find_nodes "7009"            -> 1 命中      get_node 保单:PL-009
find_nodes "P-7009" type=policy       -> 0     -> 保费 750
find_nodes "P-7009" type=policyholder -> 1 命中
答案: NOT_MODELED                        答案: 750
扁平                                        有形状
find_nodes "P-7009"          -> 1 命中:     find_nodes "P-7009" type=policy
   保单持有人:PH-05 "Ivo Renner"            -> 1 命中: 保单:PL-009 "P-7009"
find_nodes "7009"            -> 1 命中      get_node 保单:PL-009
find_nodes "P-7009" type=policy       -> 0     -> 保费 750
find_nodes "P-7009" type=policyholder -> 1 命中
答案: NOT_MODELED                        答案: 750

在有形状的图上需要两个调用。按编号请求保单,得到保单顶点,读取保费,完成。

在扁平图上,看看智能体实际完成了什么。它的第一次搜索找到了一个顶点。第二次找到一个。第三次请求 type=policy 得到空,因为该标签在此模式中不存在。第四次请求 type=policyholder——得到一个命中。智能体成功按类型定位了包含答案的确切顶点,然后报告数据缺失。

保费在那个顶点内,在一个属性中,一个 get_node 之遥。在十次失败的保费片段中,无过滤搜索十五次将那个包含顶点交给智能体,而 get_node 被调用零次。搜索返回的是标记为 "Ivo Renner" 的顶点——一个人的名字。在其他失败的保费片段中,它是另外两个保单持有人之一,从来不是保单:某人的名字没有任何暗示你请求的保单在里面。

这就是埋葬实体的具体危险,图数据库使其精确。数据不是不可达的;它是不可识别的。 顶点被索引,被查询返回,坐在智能体的上下文中。它只是不回应被请求的东西的名字。

规范化则诚实地、昂贵地失败。每次属性读取通过 Attribute 节点往返一次,每个关系通过 Relation 节点绕道一次,账单出现在 token 列中:每个问题 13,701 个 token 对比有形状图的 7,176,12.15 次工具调用对比 7.24。其一百二十个片段中有二十五个达到十六轮预算并停止,有形状的是三个,扁平的是两个,在最难的频段得分 0.133。那个图没有什么缺失。智能体就是无法在耗尽呼吸前说完一句话。

最便宜的列确实是最便宜的,这不是它看起来的恭维。 扁平每百个问题花费 0.109 美元,对比有形状图的 0.165 美元,我想在这里谨慎而非图方便:即使除以准确性它仍然更便宜,每百个正确答案 0.14 美元对比 0.20 美元。扁平模式在这个模型上确实更便宜。它不以任何价格卖给你的是那十八个它拒绝的答案。快速放弃是便宜的,低天花板上的低账单不是节省。这就是仅成本列永远不会向你展示的区别。

拒绝悖论:不可回答频段上最好和最差的分数在你检查可回答问题时互换位置。 扁平正确拒绝了所有三十个不可回答片段——一个完美分数,表中唯一一个完美分数。有形状得分 0.933,规范化 0.900,两者中错过的是耗尽轮次的片段而非发明。

单独读那一行你会加冕扁平模式。现在读它旁边的错误拒绝计数,顺序翻转:具有完美拒绝分数的形状拒绝了十八个它本可以回答的问题,具有最差拒绝分数的形状拒绝了十三个。扁平不是更擅长识别缺失。它偏向于宣布缺失,而在无答案问题上获得完美分数的同样偏见就是失去有答案问题的原因。没有可回答性指标旁边的拒绝指标是发布你能构建的最盲目图的邀请。

还有一个我自己付出代价的发现,这次活动让它变得更糟而非更好。 有形状的本体论恰好携带一种派生快捷方式,索赔到保单持有人的 held_by 边。在从索赔走到持有人城市的问题上它得分 0.83 对比规范化的 0.33——但扁平图在同一问题上得分 0.92,完全没有快捷方式,因为在此模式中索赔和持有人是仅有的两样东西。快捷方式不能因一个没有它的形状击败的结果而获得功劳。

更糟的是,我未能添加的快捷方式恰好在我预测的地方让我付出代价。统计持有人保单上的不同保障种类在我的精心设计的图上得分 0.17 对比扁平的 0.67,后者将它们全部保持在一个可读属性中。汇总持有人索赔上的付款以 0.33 平局。在子图上的聚合中,我为之辩护的设计是输的那个,而且输给了我称为破碎的设计。

反规范化不是对良好设计的妥协。它是设计的一部分,我在工作负载最需要它的地方应用了自己的原则不足。

然后我在一个大得多的模型上重新运行了整个网格,它回答了我真正关心的问题——以拒绝按我预期行事的方式。

我原以为小模型在精心设计的图上会击败大模型在糟糕设计的图上。事实并非如此。下面的比较仅使用可回答问题,所以不可回答问题的拒绝不能给任何人增光——小模型行跨三轮九十个片段,大模型行来自其单轮三十个:

大模型完美地读取被埋藏的属性。它回答了扁平图上每个可回答问题,三十个中的三十个,包括那些关于模式已溶解为文本的实体的问题——困扰小模型的十八个错误拒绝完全消失了。所以诚实的标题不是我想要的:

你可以用钱绕过一个糟糕形状的本体论。汇率大约是每个问题十四倍的成本——这就是大模型在扁平图上对比小模型在有形状图上的花费,每百个问题 1.90 美元对比十三美分。如果你保留扁平图并简单地升级其下的模型,你支付的是那个相同小模型在上面花费的二十倍。

这就是结果,它比我预测的更有用,因为它暗示的东西。在前沿模型的可回答问题上,形状不再是正确性问题而变成了成本问题:扁平和有形状都回答了全部三十个,区分它们的是账单。在小模型上,形状就是正确性。这意味着精心设计的本体论主要不是质量投资。它是让你运行廉价模型的东西。 扁平图悄悄地将你的知识层耦合到你的模型预算:只要你不惜代价支付足够大的东西来读透它,在每个问题上,永远如此。

在所有四个频段上,排序比仅可回答视图所暗示的更清晰。有形状的图在大模型上得分完美的 1.000——每个频段,包括不可回答的那个。扁平得分 0.950,规范化 0.825。即使在金钱解决正确性问题的地方,它也没有完全解决所有问题,而且它从不触及账单。

这里交叉检查运行教会了我一些关于我自己谨慎的东西。 在那次运行中,相同的网格,相同的问题,工具读取文件而非 Cosmos,有形状的图产生了整个项目中最令人震惊的结果:当被问到事件当天的天气时,一个本体论刻意不建模的事实,它回答"冰雹损害",找到了索赔的 cause 属性并将其作为天气提供。我把它写成我偏好的设计犯下了我称为这类系统中最危险的失败。我也写道那是单轮单次观察而非测量,我不会基于它建立法则。

在真实基础设施上重新运行是正确的选择。在测量的活动中,有形状的图正确拒绝了大模型的所有十个不可回答问题,而虚假回答出现在扁平图上,对同一问题回答"冰雹"。相同模型,相同问题,相同陷阱——不同的形状被它捕获。

所以发现不是丰富的图招致虚假回答。而是包含"冰雹损害"字样的 cause 属性会诱惑被问到天气的模型,无论你存储在哪里,哪个形状被捕获在运行中不稳定。这是我差点做出的更小主张,也是证据支持的那个。它还意味着危险是真实的且与形状无关:如果你的图持有一个读起来像问题答案的字段,某个地方的某个模型会把它交出来。

规范化本体论在两个模型上都输了——小模型中最差的,在大模型上可回答问题仍然落后于 0.867,同时每百个花费 9.31 美元,几乎是同一模型上扁平图的五倍,并且仍然七次耗尽轮次。实例化在接触更大模型时并不比接触小模型更好,因为它的问题从来不是理解。它是距离:每个问题 15 次工具调用对比有形状图的 8.3,即使使用一个从未误解所给内容的模型。

但它没有在每个轴上都输,例外是整个数据集中最有教育意义的东西。在单事实查找上,规范化图得分 0.867 对比扁平的 0.533,在扁平失败的两个问题上它是更好的形状,距离很大:保单保费 0.83 对比 0.17,提供商专长 0.83 对比 0.33。实例化极其昂贵,但它从不隐藏任何东西——每个实体确实是一个顶点,所以每个实体都可以被找到。

这就是用一行话说的整个论点:每个失败的形状保留了问题的一半而丢掉了另一半。 扁平保留了距离但丢失了可寻址性。规范化保留了可寻址性但丢失了距离。两者在保留的一半上有竞争力,在丢掉的一半上无望。

有形状的本体论不是它们之间的妥协。它在击败扁平的频段上得分 0.967,在击败规范化的频段上得分 0.967——它拒绝权衡。那是它优势实际所在的地方,将频段平均成单一准确性数字完全隐藏了它。

交叉检查运行无法支持的一个测量,这次可以:延迟。读取文件时,每次调用时间在相同运行之间剧烈波动——相同变体在一次运行中平均每次调用 1.17 秒,另一次 4.21 秒,我拒绝报告它,因为服务方差大于本体论所做的任何事情。

对抗 Cosmos 的画面是有序的,原因有点令人泄气。

每个问题的时间现在在形状之间清晰分离且内部稳定:变体内部最宽的波动是七秒,而扁平和规范化之间有近五十秒的差距。规范化图上的一个问题花费的时间是扁平图上同一问题的两倍半。

令人泄气的部分是最后一列。每次调用,三种形状成本基本相同——在 6.2 到 7.4 秒之间,无论模式如何。所以这不是一个独立发现;它是工具调用计数以秒为单位重述。数据库增加的是一致性:到 Cosmos 的往返以一种本地字典不是的方式可预测,这正是使该数字可报告的原因。

这有一个值得保留的实际后果。如果每次调用延迟大致恒定,那么你的本体论形状直接设置你的智能体响应时间,就像它设置你的 token 账单一样,你可以在构建前估算它:数跳数。

5、原则,每条都附有收据

关于本体论设计的文章通常将原则呈现为品味。大多数原则附有赢得它的数字;没有数字的地方,我说明而不是修饰它。

如果它可能被问到,它必须是一个顶点。 这是我会刻在门上的那条。扁平图在与其他相同的数据库中持有每个保单保费和每个提供商专长,完全索引——小模型几乎没检索到任何:0.17 和 0.33,对比有形状图的 1.00 和 0.83。整个频段显示了它,0.533 对比 0.967。将实体埋葬在另一个实体的属性中不会使它难以到达;它使关于它的合理问题以别人的名字回来,智能体将其读为缺失的证明。

注意交叉迫使的条件:前沿模型将它们全部挖了出来。埋葬不是绝对障碍。它是以模型层级支付的税。

粒度是预算,实例化花得最快。 仅为模式纯度存在的每个节点在每次访问时收取租金。规范化图在单事实查找上支付了有形状图工具调用的 3.7 倍,在短遍历上 2.3 倍,在频段 L 上 4 倍 token,在一百二十个片段中二十五次耗尽轮次,有形状的是三个。一个每次输入 token 贵二十五倍的模型将其从 0.489 提升到可回答问题的 0.867,真正的恢复,以每百个问题 9.31 美元购买,几乎是同一模型在扁平图上成本的五倍。距离是任何预算都无法使之便宜的属性。

入口点是架构,它们是这里对模型最敏感的东西。 问题带着名字或数字到来,第一个工具调用决定智能体是开始工作还是开始猜测。小模型在有形状图上该调用在 10% 的片段中返回空,扁平 26%,规范化 53%,搜索落在 Attribute 节点而非事物本身上。前沿模型在任何形状上都没有返回空。所以浪费的第一步不纯粹是图的属性——它是当较弱模型遇到不匹配其期望的入口点时发生的事情。为你打算运行的模型设计门,而非你正在测试的那个。

刻意反规范化——当收据与你相悖时要诚实。 我添加了一个派生快捷方式 held_by,期望它在索赔到持有人路径上有效。它得分 0.83 对比规范化的 0.33——扁平图在同一问题上得分 0.92,完全没有快捷方式。我不能因一个没有它的形状击败的结果而给我的快捷方式功劳,干净的测试,有边的有形状对比无边的有形状,是我没有运行的那个。

我未能添加的快捷方式是更清晰的教训。统计持有人保单上的不同保障种类在我的精心设计的图上得分 0.17 对比扁平的 0.67,后者将它们全部保持在一个可读属性中。在子图上的聚合中,我为之辩护的设计输给了我称为破碎的设计。选择快捷方式就是设计,工作负载告诉你需要哪个——我选错了,数据说明了。

限制扇出。 二十结果搜索上限和三十结果遍历上限意味着过度连接的节点以可见、可计数的额外调用而非一个巨大响应支付成本。我没有运行无上限组,所以我不能告诉你上限节省了什么——我只能告诉你没有它们,成本隐藏在响应大小中,没有任何调用计数指标会找到它。

使缺失可读,并诚实地测量它。 不可回答频段是设计要求,不是测试技巧。但读它旁边的可回答频段:扁平完美的 1.000 拒绝分数旁边是十八个拒绝它本可以回答的问题,而有形状的图拒绝最少,放弃了它错过的两个不可回答片段而非发明任何东西。本体论应使"我们不建模这个"可到达且真实——你的评估需要两半,否则它无法区分知道自己极限的图和找不到自己内容的图。

名称就是 API。 智能体读取边名称的方式就像开发者读取函数签名,本实验刻意将命名与结构捆绑成一个叫做设计的变量。那个没有自己的数字。分离它们是明显的下一个消融,我宁愿这么说也不愿声称比测量更多的东西。

6、这不是什么

这不是图数据库的基准测试。三种形状都在同一个 Cosmos DB 账户中,在同一个工具层下,使用相同的索引默认值,所以存储保持不变而非被测试——这里没有任何关于 Cosmos 对抗任何其他图数据库的内容,它没有调优。这不是声称遍历-only 是生产智能体检索一切的方式;没有干净入口点的模糊问题需要搜索,第 IV 节恰恰展示了纯遍历在哪里赢得它在哪里不会。这不是反对事务系统中规范化的论点——这里的规范化形状对这个消费者是错误的,一个按跳付费的智能体,不是一般错误。而且这不是供应商比较:Microsoft Foundry 是本实验中的常量,不是变量,相同的方法可以转移到任何具有函数调用的平台。

一个问题值得回答而非保证:将数据库放入循环会改变结果吗?在测量活动之前,我构建了相同的四个工具两次,一次在 Cosmos 上,一次在生成器发出的文件上,并重放了记录的工具调用对抗两者——3,056 个不同调用,活动中产生的每个工具和参数的唯一组合。两个实现在每个上都返回了相同答案。那不使数据库无关紧要:它花费延迟和请求单位,跨活动中智能体在 Cosmos 上多走了约 4% 的步骤,几乎全在规范化图上。它确实意味着智能体看到的答案是本体论形状的属性而非底层引擎的属性,这是第 IV 节比较需要为真的唯一事情。重放是仓库中的脚本,不是段落中的主张。

几个诚实要点,继承自路由器工作。一个合成领域上的四十个合成问题是小工具;对比尖锐因为形状是原型,你的生产本体论在它们之间的某处,这正是测量端点的意义。小模型活动运行了三轮完整运行,我全程引用了它的噪声基底,但大模型网格运行了一次——它饱和的结果(三十中三十,两次)很难误读,但其中任何两个问题的差异是观察而非测量,我没有基于一个建立论点。整个实验还对一个小模型和一个大模型评分;它们之间曲线的形状未被测量。

工具本身的两个局限,我在审计代码以发布时发现,宁愿发布也不愿悄悄修复。首先,traverse 在被请求图没有的边类型时返回空邻居列表,这与真正没有此类邻居的节点无法区分。跨活动中智能体做了一百一十二个这样的调用,规范化图的二十二个错误拒绝中有九个包含一个;分析脚本两个都计数。它不解释标题差距——有形状的图最多使用这些调用仍然拒绝最少的问题——但一个报告"这里没有"意味着"没有此类边类型"的工具是一个混淆,诚实版本会返回命名可用类型的错误。其次,无损性证明比较重建的事实,所以它对不携带自己事实的边视而不见:扁平图的连接边和有形状的图的派生快捷方式。我后来添加了第二个检查,验证它们对抗它们重新表达的事实,它捕获了每个的删除和错误指向——但活动在该检查存在之前运行,它现在提供的保证是当时我没有的。

7、尾声——形状就是系统提示

我们在模型前面放的词上投入了巨大的关怀,几乎没关注我们放在其后的知识的形状。但对于使用工具的智能体,本体论就是提示——它是世界提供的动作集合,以节点类型和边名称写成,一次一个工具调用地读取。为它实际的读者设计它。

事实库、三个本体论、无损性证明、问题、预言机、智能体和每个活动收据都在仓库 github.com/mcekikj/ontology-shape-race [7] 中。用第四种方式建模相同的真相,与我的比赛,如果你的形状在击败它们的问题上击败了这些,我真的想看到带你到那里的行走路径。


原文链接: Your Agent Is Not Confused, Your Ontology Is

汇智网翻译整理,转载请标明出处