Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

基于嵌入的AI代理工具选择

Posted on 2025-12-22

我最初开发我们的人工智能助手时,它只有五个工具:查询订单、处理退款、查看票务情况。都是些简单的功能。六个月后,我们的工具数量已经接近 40 个,涵盖订单、活动、营销活动、竞赛和客户管理等领域。

在一次例行成本审查中,问题变得显而易见:我们每次请求都浪费数千个代币,而这些请求仅仅是为了描述模型永远不会用到的工具。比如有人问“我的节目几点开始?”,我们却发送了process_refund 、 create_email_campaign和manage_contest_prizes的完整规范。这太浪费了。

工具爆炸问题

每个工具定义都不简单。你需要一个名称,一段足够详细的描述(以便LLM能够理解何时使用它),以及包含类型和约束的参数规范。以下是我们代码库中的一个示例:

 % ToolDefinition {  
  姓名: "处理退款" ,  
  描述: """  
  处理特定订单的退款。验证退款金额  
与原订单总额和可用余额进行比较。需要  
从 get_order_details 获取 order_id。返回包含退款 ID 的确认信息。  
  """ ,  
  参数: [  
    %{姓名: "order_id" , 类型: :细绳, 必需的: 真的},  
    %{姓名: “数量” , 类型: :数字, 必需的: 真的},  
    %{姓名: “原因” , 类型: :细绳, 必需的: 错误的}  
  ],  
  处理程序: {退款登记处, :handle_process_refund },  
  类别: 退款  
}  

乘以 40,用户还没开口说话,就已经产生了 3000 多个令牌。成本不断累积,延迟增加,更糟糕的是:工具太多反而会降低模型选择正确工具的能力。噪音越多,混乱越多。

基于嵌入的语义选择

解决方案的概念很简单。我们不再每次请求都发送所有工具,而是将所有工具描述嵌入到向量中,并使用 pgvector 将它们存储在 Postgres 数据库中。当收到查询时,我们也将其嵌入到向量中,然后使用余弦距离找到语义最相似的 5-10 个工具。

查询“退款订单 #12345”被嵌入,与所有工具嵌入进行比较,并返回process_refund 、 calculate_refund_amount和get_order_details 。我们只将这些发送给 LLM。

这可以将我们工具在大多数请求中的负载减少 75% 到 90%。模型看到的选项更少,但更相关,因此能够做出更好的选择。

选择嵌入提供商

我们讨论了两种主要方法:调用 OpenAI 的嵌入 API 或运行我们自己的模型。

OpenAI 的text-embedding-3-small是阻力最小的方案。它通过 REST 调用返回 1536 维向量,每个嵌入的成本仅为百分之一美分左右,而且开箱即用。语义理解能力非常出色。缺点在于它对外部资源的依赖。每次查询都需要一次网络往返,你的数据会经过他们的服务器,并且你会受到他们的速率限制和服务器故障的影响。

在本地运行 ModernBERT 之类的模型有很多吸引人的地方。它几乎没有边际成本,延迟低于毫秒级(因为无需网络跳转),并且完全保障数据隐私。但与此同时,你也需要管理基础设施。你需要一台运行模型的服务器,还要考虑监控、扩展性等问题,并且模型的选择和更新也由你负责。对于小型团队来说,这种运维负担是实实在在的。

还有一种混合方法:在生产环境中使用 OpenAI 以确保可靠性,在开发和测试阶段运行本地模型以避免 API 成本和不稳定性。我们通过构建提供程序抽象层来实现这一点:

 defmodule Amplify.EmbeddingProvider 做  
  @打回来 generate_embedding ( String.t ( ) ) :: { :好的, list ( float ())} | { :错误, 任何()}  
  @打回来 方面() :: pos_integer ()  
  @打回来 model_id () :: 字符串.t ( )  
结尾  

切换服务提供商需要更改配置。虽然前期需要额外花费一个小时,但可以带来后续的灵活性。

我们为什么选择 OpenAI

就我们的数据量而言,OpenAI 显然是最佳选择。我们每天处理数百个查询,而不是数百万个。每个嵌入仅需 0.00001 美元,每月成本几乎可以忽略不计。它的可靠性极佳,语义质量也完全满足我们的电商领域需求,而且无需任何基础设施管理。

如果我们要处理数百万条查询,或者有严格的数据驻留要求,那么情况就不同了。但对于一个运营工单平台的小团队来说,花几分钱就能避免运行其他服务,这笔交易很划算。

在开发过程中生成嵌入

添加新工具或更新现有工具意味着需要重新生成嵌入。在开发过程中,这是一项混合任务:

混合 生成工具嵌入  

此操作会遍历所有工具定义,对每个工具调用 OpenAI,并将结果更新插入到tool_embeddings表中。处理 40 个工具大约需要 10 秒。该任务是幂等的,因此您可以随时运行它。

实现方法很简单。我们将每个ToolDefinition转换为嵌入文本,其中包含名称、描述和参数信息,然后将该向量与工具名称和模型 ID 一起存储。

生产环境中的嵌入生成

为了方便生产环境使用,我们搭建了一个简单的管理页面。用户只需导航至 AI 操作界面,即可查看当前的嵌入次数,然后点击按钮重新生成。非技术团队成员无需操作控制台,即可在工具更新后触发此功能。

另一种方法是直接入侵生产控制台:

 Amplify.Services.ToolSelector.regenerate_embeddings ( )​  

无论哪种方式,随时都可以安全地运行重新生成功能。它会删除现有的嵌入并创建新的嵌入。整个过程只需几秒钟。

需要注意的是:如果您更换了嵌入提供商,则必须重新生成所有内容。OpenAI 的 1536 维向量与本地模型的 768 维向量不兼容。我们在每个嵌入中存储了model_id ,以便捕获不匹配的情况并简化调试过程。

处理多步骤操作

纯粹的相似性搜索存在缺陷。如果有人说“退款订单 #12345”,我们会找到process_refund 。但 LLM 还需要get_order_details来查找订单详情,才能进行退款。这两个函数的语义相似度不够高,无法同时出现在搜索结果的前列。

我们通过扩展类别解决了这个问题。每个工具都有一个类别,例如:orders :refunds或:events 。当我们通过相似性选择工具时,我们会扩展类别以包含相关类别:

 @category_expansions %{  
  订单: [ :orders , 退款, :顾客],  
  退款: [ :orders , 退款, :付款],  
  事件: [ :events , :tickets ]  
}  

因此,查找process_refund (类别:refunds )会自动调用订单查询工具。LLM 即可获得多步骤工作流所需的一切信息。

pgvector 查询

对于那些对数据库方面感兴趣的人,以下是我们实际运行的查询:

选择 姓名, 1 - (嵌入) <=> 1美元) 作为 相似  
从 工具嵌入  
在哪里 (嵌入) <=> 1美元) <= 3美元  
命令 经过 嵌入 <=> 1美元  
限制 2美元  

<=>运算符是 pgvector 的余弦距离。我们使用相似度阈值(默认为 0.4)进行过滤,以避免返回完全不相关的工具,然后取前 K 个结果。整个过程运行时间不到 10 毫秒。

测试而不影响 OpenAI

我们在测试中使用 Mimic 进行模拟。每个涉及工具选择的测试都会对嵌入提供程序进行桩化,使其返回一致的向量:

模仿.存根(嵌入提供程序, :产生, 函数 _文本 ->  
  { :好的, 列表.重复( 0.1 , 1536 )}  
结尾)  

这样可以保证测试快速、确定性强,并且不依赖于 API。我们还可以模拟故障,测试系统在嵌入生成失败时能否优雅地回退到使用所有工具。

我们学到了什么

一路上发生了一些让我们感到意外的事情。

相似度阈值比我们预想的更重要。阈值太高会过滤掉有用的工具,阈值太低则只会得到噪声。经过一些实验,我们最终将阈值设为 0.4,但建议根据你的领域进行调整。

类别扩展最初是事后考虑的,但后来却变得至关重要。纯粹的语义相似性忽略了工具之间的依赖关系。如果你的助手需要执行多步骤操作,你就需要类似这样的功能。

即使我们没有更换提供商,提供商抽象也物有所值。它迫使我们以清晰的思路思考接口,并大大简化了测试。Mimic 桩之所以有效,是因为模拟的边界很明确。

冷启动确实是个问题。如果你的嵌入表为空,就需要备用方案。我们会记录警告并使用所有工具,虽然这并非理想方案,但可以避免彻底失败。

结果

部署此方案后,我们用于工具定义的单次请求令牌使用量下降了 60-80%。由于模型处理的令牌数量减少,延迟降低了约 200 毫秒。工具选择的准确率实际上略有提高,因为干扰模型的噪声减少了。

嵌入成本可以忽略不计。以我们的数据量来看,每天的成本可能只有 0.01 美元。整个系统每次请求会增加一次 10 毫秒的数据库查询,但这在 LLM 调用产生的噪声中几乎可以忽略不计。

对于任何需要处理人工智能代理工具爆炸问题的人来说,这种方法都值得考虑。它的实现并不复杂,成本极低,而且随着工具数量的增加,收益也会成倍增长。

原文: https://zarar.dev/embedding-based-tool-selection-for-ai-agents/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Alin Panaitiu
  • Anil Dash
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Big Technology
  • Bits about Money
  • Brandon Skerritt
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • eighty twenty
  • Elad Gil
  • Ellie Huxtable
  • Ethan Dalool
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • HeardThat Blog
  • Henrique Dias
  • Herman Martinus
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Li Haoyi
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Maggie Appleton
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mind Matters
  • Mostly metrics
  • Naval Ravikant
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • PostHog
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Rohit Patel
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Steph Ango
  • Stephen Wolfram
  • Steve Blank
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • Wes Kao
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme