news 2026/5/28 6:02:24

Elasticsearch:使用预计算上下文降低 agent 成本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Elasticsearch:使用预计算上下文降低 agent 成本

作者:来自 Elastic Joe McElroy

将上下文预计算为 Knowledge Indicators 可将 LLM agent 的 token 成本最多降低 75%,并将答案准确率从 60% 提升至 92%。这篇文章介绍了使其生效的提取、检索与反馈循环,并基于 BrowseComp-Plus 基准进行了测试。

Agent Builder 现已正式发布可用。立即开始使用 Elastic Cloud Trial,并在这里查看 Agent Builder 的文档。


围绕 agent 上下文的大多数讨论都将其视为一个记忆问题。如何为模型提供更大的空间、更长的窗口、更好的召回能力。但这是错误的视角。上下文是一个检索问题。Agent 在真实工作负载中停滞,是因为它们在到达答案之前,将 token 和步骤预算消耗在浏览原始数据源上,而解决方案是更好的检索,而不是更多的记忆。在这篇文章中,我们探索了一个实验:利用 LLM 提前提取结构化事实(“Knowledge Indicators”,简称 KI),agent 可以通过由混合语义与词法检索支持的自然语言接口来查询这些事实。

使用 BrowseComp-Plus 公共数据集以及一个受成本控制的 agent harness,在三轮迭代中,准确率从 60% 提升到 70%,再提升到 92%,同时与标准 RAG 相比,输入 token 最多减少了 75%。最终的大部分提升来自于将 agent 自身的错误答案反馈回提取器,从而生成新的 KI。

预计算上下文只有在一个能够良好检索、能够随时间管理数据并能从自身失败中学习的系统中才有效。

Agent 在到达答案之前就停滞了

当前最先进的模型在具备访问信息源能力时非常强大 —— 它们可以抓取网页、解析电子表格、浏览日志、运行查询。挑战在于,如何在到达答案之前不耗尽 token。

这个挑战对于正在构建可访问数据的 agent 的工程领导者来说并不陌生。Agent 接收到任务后,会判断自己需要信息,于是开始搜索、检索、评估,然后发现还需要更多信息,于是再次搜索、阅读、拼接部分内容、循环往复。等到模型准备回答时,大部分 token 和延迟预算已经耗尽。有时答案其实就在语料库中,但上下文窗口在 agent 找到它之前就已经被填满。有时 agent 选择了错误的线索,并且再也无法恢复。

OpenAI 在构建他们自己的内部数据 agent时也遇到了这个问题。原始数据访问无法扩展。他们不得不加入人工标注、机构知识以及学习得到的修正,系统才足够可靠,能够日常使用。我们也在使用 Elastic Agent Builder 的客户中看到了同样的问题。模型智能很少是限制因素;真正让 agent 崩溃的是推理步骤之前的上下文。

不同领域中的工作负载形态差异巨大:

  • 日志异常分类:处理机器生成的系统告警。由于单个数据点缺乏足够上下文,目标是从多个异常中提取洞察,以区分良性、周期性模式和真正需要处理的事件。
  • 金融支付分析:查询历史日志,通过模糊标识符追踪端到端交易路径。这需要跨记录检索,以映射完整的服务链路,并诊断支付失败或延迟问题。
  • 产品支持:利用内部文档帮助客户解决产品问题,从多个文档中构建洞察。

这篇文章介绍了我们正在测试的一种策略来解决这个问题:提前一次性完成数据定向工作,然后让 agent 直接读取结果。

自底向上的上下文策略:从源数据中提取知识

这种方法包含两个部分:使用 Knowledge Indicators 提前提取上下文,以及为 agent 提供一种干净的查询方式。

使用 agent 学习如何高效提取和维护上下文

Agent 所需的大部分数据实际上已经存在于企业内部的某个地方 —— 数据库中的记录、 Google Drive 、 Confluence 或 SharePoint 中的文档、 Elasticsearch 中的日志与指标、 S3 中的文件。该策略直接作用于这些数据原本所在的位置,并沿用它们已有的访问控制。

每个领域对数据源的使用方式都不同。因此,我们并不打算创建将所有数据源和领域一视同仁的通用提取流水线,而是计划使用 agent 来定制提取需求。Agent 会读取源数据样本,理解其结构 —— 模式、字段语义以及数据通常的查询方式 —— 并将这种理解写出为结构化元数据。其中一部分元数据是从数据中预计算得到的事实;另一部分则描述了如何查询数据源本身。

Document: docid: <docid> url: <url> text: <body text> Return a JSON object with key "facts" containing 0–15 atomic facts. Long, fact-dense documents (Wikipedia articles, news features, profiles, academic-staff pages) typically warrant 8–15 facts. Short or generic documents may warrant 0–3. Each fact MUST be self-contained: title + description together fully answer the implied W-question (who/what/when/where/how/which) without requiring the source document. A future agent should be able to commit to an answer by reading just title+description — the description must include the answer value, supporting evidence (date, location, named witness, exact quantity, physical detail), and a short verbatim quote (≤30 words) when it adds disambiguating signal. This bias toward density is intentional even at the cost of slightly longer descriptions. Each fact: { "title": "<one natural sentence ≤140 chars stating the fact, ending with the answer value when possible (e.g. \"Townsend was last seen wearing a red shirt.\")>", "description": x "<2-3 sentences ≤350 chars carrying the answer + evidence: entity, relation, value, date/location/source detail, and an inline verbatim quote when it disambiguates. Avoid restating the title verbatim.>", "subject": "<canonical entity name>", "predicate": "<precise snake_case relation, ≤32 chars>", "object": "<the value of the fact, plain prose>", "evidence_span": "<verbatim 1-3 sentence quote, substring of the doc text above>", "confidence": <0..100 integer>, "tags": ["<entity/topic/year tags, lowercase, alphanumeric+hyphen>", ...] } Coverage priorities — extract a fact for EACH of the following whenever it's grounded in the doc text: - Every named person mentioned + their role / position / title (no matter how briefly named — a one-line mention of "the secretary, Mary" still warrants its own fact). - Every named organisation + its relation to the main entity. - Every concrete date + the event that occurred on it (graduation 22 June 2003, trip 1 Nov 2022, etc.). - Every named location + what happened there. - Every distinctive descriptive detail: clothing colour, building material, exact age, weight, height, vehicle, distinguishing feature, last-seen description. - Every cross-entity relationship: X collaborated with Y, X worked for Y, X spoke at Y's conference, X's child is Z, X co-edited a book with Y. Anti-patterns — do NOT do these: - Don't only extract facts about the most famous / dominant entity in the doc. Secondary individuals named once still warrant their own fact. - Don't fill the budget with generic claims (founded-year, location, leadership) at the expense of specific concrete details that sit deeper in the doc body. - Don't skip a fact because it seems minor — minor facts are often what disambiguate two similar entities at retrieval time. Predicate guidance: - Use a precise snake_case predicate (≤32 chars). Prefer reusing common terms when they fit: located_in, founded_in, founded_by, held_event, published_article, won_award, member_of, position_held, born_in, died_in, created_by, parent_of, succeeded_by, field_of_study, co_authored_with, organized_by, attended_by, physical_description, last_seen_wearing, clothing_worn, cross_link. - Coin a new specific predicate when none of those fit. AVOID the catch-all `affiliated_with`. Title and description constraints (CRITICAL — items violating these are dropped): - title and description MUST read as natural standalone fact statements. - They MUST NOT contain the strings: "BrowseComp", "qid", "qid:", "use this fact", "anchor a criterion", "without re-reading". - They MUST NOT mention the document, the dataset, or this task. Fact constraints: - Favor specificity (proper nouns, dates, numbers) over generic claims. - Skip the doc entirely (return empty facts list) for navigation pages, login walls, error pages, very short or generic content. - evidence_span must be a verbatim substring of the doc text supplied above.

提取提示词是由 agent 创建的。你可以在这里找到 agent 之前创建的提示词。

Knowledge Indicators

我们将这种预计算元数据单元称为Knowledge Indicator—— 简称 KI。 KI 对我们来说并不是一个新概念:它们已经在 Elastic Observability Streams 的生产环境中运行,其中同样的提取模式被应用于原始日志数据。在那里,一个 agent 会从数据流中采样日志,并提取有关环境的结构化事实 —— 运行了哪些服务、它们所在的基础设施、它们之间如何相互依赖、使用了哪些日志 schema —— 然后这些 KI 会被下游用于拓扑图、规则、仪表板以及 agent 调查。如果某个服务在 7 天内不再出现,对应的 KI 会自动过期,因此无需手动清理,索引也能保持最新状态。

本文中的工作将同样的模式应用到了另一种类型的语料库 —— 文档而不是日志 —— 但基本单元是相同的。有些 KI 是事实;另一些则描述数据源。它们共享相同的结构:

{ "type": "knowledge_indicator", "id": "ki-bcpc-d1478-tony-blair-position-held-prime-minister-of-the-un", "title": "Sir Tony Blair served as the Prime Minister of the United Kingdom from 1997 to 2007.", "description": "Blair was a British politician who held the office of Prime Minister for ten years starting in May 1997, and was the first person to lead the Labour Party to three consecutive general election victories. The text describes him as \"a British politician who served as Prime Minister of the United Kingdom from 1997 to 2007\".", "references": ["index://browsecomp-plus-corpus"], "tags": [ "entity:tony-blair", "doc:1478", "tony-blair", "prime-minister", "politics", "1997-2007" ], "evidence_doc_ids": ["1478"], "payload": { "type": "feature", "subtype": "dataset_fact", "properties": { "subject": "Tony Blair", "predicate": "position_held", "object": "Prime Minister of the United Kingdom", "docid": "1478" }, "evidence": [ "Sir Anthony Charles Lynton Blair (born 6 May 1953) is a British politician who served as Prime Minister of the United Kingdom from 1997 to 2007" ], "confidence": 100, "status": "active", "last_seen": "2026-05-10T11:12:41Z" } }

在实际中,这比听起来更困难,而这种困难正是为什么这项工作需要一个具备优化搜索、检索和数据工程能力的系统才能有效运行。

真正让这套方法发挥作用的关键,在于衡量这些元数据在实际中的表现。我们会观察 agent 如何使用这些元数据来回答真实问题、它们在哪里失败、在哪里退回去扫描原始数据源、又在哪里直接放弃。这些失败本身就是信号。它们会告诉 setup agent 它遗漏了什么,于是元数据会被重新生成,而下一批失败又会呈现出不同的模式。如果没有这个循环,提取 agent 就会过度拟合于它最初调优时所面对的那一小部分问题,而这套策略也无法扩展到 demo 之外。

整个循环的端到端结构如下:

用户只需提供一次输入 —— 一组示例问题以及指向数据源的入口。循环中的其余部分都会自行运行,并且会随着新的 trace 到来持续运行。

为 agent 提供一种提问方式

第二部分是接口。Agent 不应该需要知道它正在查询哪个数据源、索引 schema 是什么样子,或者答案究竟来自 Knowledge Indicators 还是来自对原始数据源的回退扫描。它应该只需要提出一个问题,然后获得一个可用的结果。

查询 Knowledge Indicators

我们最终选择了自然语言接口来查询这些元数据。Agent 发送一个问题;接口背后的 LLM 会将其重写为针对索引的底层查询。Agent 不需要了解 schema、检索策略,或者答案来自哪个数据源。

POST /api/_get_context { "query": "Wilkinson 2014 creatine review rheumatoid arthritis article title", "size": 10, "execute": true }

然后通过使用 LLM ,它会被转换为如下内容:

FROM .chat-context-items METADATA _id,_index,_score | FORK ( // Branch 1 — exact entity tag match for Wilkinson WHERE tags : "entity:wilkinson" OR tags : "wilkinson" | KEEP id, type, title, description, tags, references, evidence_doc_ids, _id, _index, _score | SORT _score DESC | LIMIT 25 ) ( // Branch 2 — lexical match on title for specific keywords WHERE MATCH(title, "Wilkinson 2014 creatine review rheumatoid arthritis") | KEEP id, type, title, description, tags, references, evidence_doc_ids, _id, _index, _score | SORT _score DESC | LIMIT 25 ) ( // Branch 3 — semantic match on description for the research intent WHERE MATCH(description.semantic, "Wilkinson 2014 review on creatine supplementation for rheumatoid arthritis") | KEEP id, type, title, description, tags, references, evidence_doc_ids, _id, _index, _score | SORT _score DESC | LIMIT 25 ) | FUSE | SORT _score DESC | LIMIT 10

返回结果携带的不仅仅是匹配到的 KI。每个 KI 都带有其标签和来源引用,而 API 会在结果集上返回聚合信息 —— 按标签、按来源、按实体进行统计 —— 这样 agent 在读取任何单个 KI 之前,就可以看到数据的整体结构。

如果第一次查询返回的结果像扇形一样分散在三个不同来源中,agent 就知道应该如何收敛。如果它们都标记为同一个实体,agent 就知道应该沿着这条线索继续探索。标签和聚合信息是它在索引中快速导航的方式,而不需要反复读取原始内容。

我们跟踪的三个指标

我们想知道,在相同语料库、相同预算条件下,将上下文预计算为 Knowledge Indicators,是否比标准 RAG 模式让 agent 回答更快、更准确。

我们关注三件事:

  • 准确率。agent 多频繁给出正确答案?通过与标准答案对齐进行评估(由 LLM 评判),并计算 F1 分数。
  • 输入 token 消耗。agent 每一步都会消耗 token。在相同答案质量下,使用更少 token 是该策略的核心目标。如果 “带上下文” 的方法能在相同预算下回答更多问题,但仍然消耗相同资源,那对真实部署来说并不算提升。
  • agent 是否能在 step 预算内收敛。错误但已提交的答案,以及 “步骤耗尽后放弃” 的答案,都是失败,但失败原因不同,对应的修复方式也不同。因此我们会单独跟踪超时情况。

我们追求的不是排行榜上的精度,而是在预算紧张的环境下策略是否仍然有效 —— 而这正是所有真实 agent 所处的环境。

实验设置

在展示结果之前,先快速说明一下实验配置:

数据集BrowseComp-Plus—— 测试集包含 830 道高难度事实型问题,每个问题都配有 gold source documents,来源于约 100k 文档规模的网页语料库。这些问题设计得比较隐晦且多条件组合;一个 agent 通常需要进行 2 到 5 次检索才能收敛到一个简短、精确的答案,例如姓名、标题或日期。

agent harness。两种设置都使用相同的 harness,基于 LangChain 的 deepagents middleware stack。agent 拥有本地 shell 权限,可以调用 skill 的脚本。两种运行之间唯一变化的是加载的 skill 不同。我们使用 Claude Sonnet 4.6 作为 agent 的模型。

agent harness 预算。该 harness 设置了 43 步的递归预算。BrowseComp-Plus leaderboard 的运行通常会给 agent 更大的空间。我们并不是要在原始准确率上竞争 —— 因为在足够多 step 的情况下,agent 最终都会找到正确答案。这个实验的重点是限制 step 和 token 预算,测量不同检索策略在真实预算约束下的收敛能力。

强制提交安全机制。如果 agent 在达到 43 step 上限后仍未输出 Answer: 行,harness 会进行一次最终 LLM 调用,要求它基于当前 trace 给出最可能的答案。超时不一定算失败 —— agent 在极限情况下仍可能命中正确结果。

基线(search-and-fetch RAG)。baseline skill 提供两个 helper:

  • Search 在语料库上执行 ES|QL semantic 与 lexical MATCH(text, …) 查询,并返回最多 10 条结果,每条包含 docid、url、_score,以及三段最多 700 字的正文 snippet。agent 在单次调用中读取相关片段,而不是完整文档。
  • get_by_doc_id 是逃生接口,用于在 snippet 无法覆盖答案时获取完整正文。

关于 baseline 的一个说明:这是当前大多数团队使用的标准 search-and-fetch 模式,但并不是最优化的 RAG 实现。针对该 benchmark 做深度调优的团队(chunking 策略、reranking、query expansion)可以缩小一部分差距。这里的对比对象是大多数客户实际运行的配置,而不是理论最优解。

上下文内置方案(in-context setup)。in-context skill 提供两个 helper:

  • get_context 将自然语言问题 POST 到 KI 查询接口。
  • execute_esql 作为原始回退手段,直接对语料库执行查询。

skill 的 SKILL.md 指导 agent 对 entity 锚定的多跳检索进行链式调用,并且只有在两次或更多 KI 查询失败后才会回退到正文搜索。

KIs 的索引方式。每个 KI 的 title 和 description 都被映射为 Elasticsearch 的 semantic_text 字段,并由 .jina-embeddings-v5-text-small inference endpoint 支持。这是一个混合检索(语义 + 词法)的匹配系统,针对预提取的知识进行搜索。

我们从 830 道问题中抽取了 96 道样本,并将 100k 文档语料库中的 25k 文档(25% 子集)转换为 KI,这其中包含每个问题的 gold docs。整个过程生成了约 240k 个 KI,由 Gemini Flash 在约 7 小时内构建完成。

阶段 1:setup agent 优化

在 setup 阶段,我们选取了 15 个问题的小样本,并与 agent 一起改进 KI extraction 过程——通过迭代 prompt 来减少 agent harness 在达到答案过程中消耗的 step 数和 token 数。

在同一组 15 个问题上,经过 4 轮 agent loop 迭代优化 KI extractor prompt 后,in-context setup 的表现如下:

指标baseline RAGwith-context变化
exact match4 / 15 (26.7%)9 / 15 (60.0%)+33 pp
F10.390.62+0.24
input tokens9.0M6.3M−30%
output tokens47.9k43.9k−8%
wall time1,475s1,448s基本持平

真正的重点并不是 30% 的 token 节省。在这里,exact-match 准确率提升到超过原来的两倍,而 wall time 保持不变,同时 token 还下降了。

更具体来说,有 5 个新的问题从 baseline 错误变成了正确,而在这一替换过程中,没有任何 baseline 原本答对的问题被丢失。

关于这些数字的一个说明:这里的准确率结果不能直接与 BrowseComp-Plus leaderboard 对比。leaderboard 的运行通常会使用更宽松的 step 和 token 预算来优化准确率。而本实验刻意限制了这两者,用来模拟我们真正关心的场景 —— 在有限预算下运行的 agent。在这种情况下,决定结果的不是更强的推理能力空间,而是检索效率是否足够高。

这些胜利主要集中在那些 KI 可以直接回答问题的场景中。在相同问题上,baseline 会不断进行一次又一次的关键词搜索调用,往往在收敛之前就触及递归步数上限。

在新增的 4 个正确案例中,baseline 并不是因为答错而失败,而是因为 step 用尽而失败。KI 路径只用了整体预算的一小部分就到达答案,这也正是这些具体问题上 80–95% token 节省的来源。

不过,这种提升并不是完全一致的。在少数问题上,in-context 方案实际消耗的 token 反而比 baseline 更多(一个问题 +151%,另一个 +723%),原因是没有任何 KI 能很好覆盖这些问题,agent 在耗尽 KI 路径后退回到了正文搜索。

这正是 feedback loop 设计要解决的失败模式 —— 这些 trace 本身就是信号,说明 extractor 漏掉了 agent 实际需要的信息。随后 agent 会不断改进 extractor prompt,从而在该领域更有效地捕获这些事实。

阶段 2:规模扩大,但失败模式发生变化

在一个较小子集上取得了较强结果之后,下一步是验证当 eval set 扩大时,这些收益还能保留多少。

我们在扩展到 96 道问题的集合上运行了相同的 setup,并再次与 snippet-baseline RAG 进行对比。

指标baseline RAGwith-context变化
judge correct60 / 96 (62.5%)67 / 96 (69.8%)+7.3 pp
F10.5610.624+0.063
input tokens174.8M48.3M−72%
output tokens373k345k−7%
timeouts(43-step 限制)28 / 9637 / 96+9

在准确率和成本上,“with-context” 都更优 —— 多答对了 7 道题,并且每题大约便宜 3.6 倍。但它的 timeout 也更高,从 28 增加到 37。这一点值得单独理解,因为它改变了我们对 timeout 数字的解读方式。

baseline 的 search 调用最多返回 10 条结果,每条包含三段 700 词的 snippet —— 单次调用就可能向 agent 的上下文中塞入约 21k 词的正文。agent 必须阅读这些内容,找到包含答案的句子,然后做出判断并提交。每一次未命中都意味着再一次搜索,以及更多正文内容的加入。

with-context 的 get_context 调用则返回约 10 条 KI —— 每条是单句级别的预提取事实,总量约 2k tokens。当 KI 直接陈述事实时,agent 只需要读一句话就可以提交答案。因此 with-context 的预算主要花在更多但更便宜、更精确的检索调用上;而 baseline 则花在更少但更昂贵的检索结果以及对这些正文的反复阅读上。

更高的 timeouts

在严格的 step 预算下,timeout 并不等于失败。它只是意味着 agent 在写出答案之前就用完了空间。这在任何受预算限制的真实部署中都是常态:agent 往往已经 “知道” 答案,但还没有来得及提交。

在本轮实验中,with-context 的 37 个 timeouts 中,有 21 个最终被判定为正确,因为在 step 43 时答案通常已经通过 KI 出现在上下文中,而 force-commit 安全机制把它 “捞” 了出来。相比之下,baseline 的 timeout 更常直接失败,因为它的上下文主要是原始正文,而最后的 force-commit 往往只是基于大量噪声进行猜测。

这个安全机制实际上是在 “捞回” agent 已经知道但尚未提交的答案 —— 也就是说,它在那些本可以更早、更低成本完成的问题上超时了。

我们希望 agent 更快提交答案。这本质上是在两个杠杆之间做权衡:一是 agent 的指令——何时继续检索、何时提交、何时回退到正文搜索;二是它所处的上下文 —— 前置的 KI 是否足够精确到可以直接用于提交答案。

这种平衡不是一次性优化可以解决的,它正是 feedback loop 要解决的问题:观察 agent 在哪里停滞、哪里延迟提交、哪里提交错误,然后把这些信号反馈回指令与 extraction 过程。第三阶段,就是这个循环的第一次真正迭代。

阶段 3:从 agent 自身错误中学习

阶段 2 已经让 with-context 在准确率上领先,并且在每个问题上便宜约 3.6 倍,但仍然留下了 29 个失败样本。我们拉取这些 trace,分析实际发生了什么问题。

失败主要分为三种形态:

  • 错误 “近邻实体提交”(29 个中的 19 个)。agent 检索到了语义上相关的 KI,但无法区分非常相似的邻近实体,并选择了 “看起来更像” 的那个。例如 q79 把 University of Aberdeen 错误提交为 University of Edinburgh,q193 把 Secret Oral Teachings in Tibetan Buddhist Sects 误判为 The Mystic Spiral,q775 把 Boston 误判为 Jerusalem。本质都是同一类错误 —— 对错误但相似实体的高置信提交。
  • 错误数值提交(29 个中的 3 个)。机制相同,但发生在数值上。例如 q209 的 9 被提交为 7,q624 的 65% 被提交为 26%,q1090 的 500 Egyptian pounds 被错误转换为 $1,500。
  • 无候选失败(29 个中的 7 个)。agent 的原始检索没有找到相关候选项,而 force-commit 安全机制基于不完整信息做出了错误猜测。

在所有这些案例中,agent 都 “拿到了某些信息”,但这些信息不足以清晰地区分正确答案与近似干扰项,最终导致错误提交。修复的关键在于:在 agent 作答之前,引入区分性判别标准。

对于每一个失败样本,我们都有四个输入:问题、正确答案、agent 的错误提交,以及 gold 文档正文。然后我们使用 LLM 为每个失败生成一个disambiguation KI,其 title 会同时包含两个实体,并明确给出区分它们的关键特征,例如:

Joseph Dalton Hooker (19th-century British botanist, Director at Kew) is associated with the second origin narrative — distinguished from 16th-century German botanist Leonhart Rauwolf./Joseph Dalton Hooker(19 世纪英国植物学家,Kew 主任)属于第二种起源叙述 —— 与 16 世纪德国植物学家 Leonhart Rauwolf 区分开来。”

同时设置了一个 guardrail:任何 KI 的 title 必须在字面上同时包含 gold answer 和 wrong prediction,否则直接拒绝。这样可以确保 disambiguator 一定会进入 semantic-text embedding,而不会因为被埋在 description 中而在检索阶段丢失。最终 38 个候选 KI 中有 33 个通过 guardrail 并被写入与 agent 相同的检索层;5 个失败是因为 wrong-pred 为空或包含 unicode 引号导致 lexical match 失败。

随后,我们对 96 题集合重新进行了一次完整的在线评测:

metricbaseline RAGwith-contextwith-context + disambigchange vs no-disambig
judge correct60 / 96 (62.5%)67 / 96 (69.8%)88 / 96 (91.7%)+21.9 pp
F10.5610.6240.827+0.203
input tokens174.8M48.3M42.6M−12%
timeouts (43-step limit)28 / 9637 / 9627 / 96−10

这次运行中,force-commit 在 28 次触发中有 22 次成功命中正确答案,这也是 timeout 下降且准确率提升的原因之一。

{ "title": "The manuscript was co-authored by TJ Wilkinson, TD O'Brien, and AB Lemmey.", "description": "The 2014 review article on creatine supplementation for rheumatoid arthritis was authored by TJ Wilkinson, TD O'Brien, and AB Lemmey, all from the Aberystwyth University research group.", "subject": "Wilkinson, O'Brien, Lemmey", "predicate": "co_authored_with", "object": "Oral creatine supplementation review", "tags": ["doc:51481", "entity:wilkinson", "td-obrien", "ab-lemmey", "2014", "co-authors"], "evidence_doc_ids": ["51481"] }

示例 disambig knowledge indicator

29个失败中有21个被翻转。Wrong-twin:19个中的16个。Numeric:3个中的1个——另外两个未在本轮中触发其 disambig KI,这看起来具有随机性。No-candidate:7个中的4个,因为一个带有答案型标题的 disambig KI 在 force-commit 安全机制触发之前就已经在检索中被召回。

准确率提升,同时 agent 变得更快。input tokens 下降12%,timeouts 从37下降到27,而典型的成功 trace 大约在25个 step 内收敛。

还剩8个持续失败案例。其中3个失败是因为 agent 在本轮中提交了一个不同的 wrong twin,而这个 twin 并不在 disambig 构建时覆盖的范围内——例如 q83 的 Stage-2 disambig 将 Hooker 与 Rauwolf 区分开,但本轮提交的是 Francisco Hernández,而该实体不在 KI title 中。挑战在于如何检索并引导 agent 远离新的 wrong twins。一个改进的 loop 是在多个可能的 wrong-pred 上进行命名,或者在多次运行中迭代 disambig 构建。这个 loop 必须持续运行,因为失败模式是漂移的。

这个 loop 的核心结果如下所示。Stage 1 和 Stage 2 的 knowledge indicators 是一次性构建并读取回来的。一个静态 index 有上限——在相同静态事实上的更好检索只能走到一定程度。

Stage 3 是同一个系统在使用自身失败作为下一批上下文。每一个错误但高置信的 commit 都是一个诊断信号:指出语料库未能区分的两种实体,以及 agent 实际选择了哪一个错误答案。这些会变成下一轮首先被读取的 KI。

结论:extraction、retrieval,以及 feedback loop

跨三个阶段,准确率从 60% 到 70% 再到 92%,同时 input tokens 相比 standard RAG 最多下降 75%。需要说明的是,这个实验并不是在宣称一个可以通用的固定倍数提升。baseline 可以进一步优化,不同领域也可能改变失败模式。

但实验展示的核心很简单:一个基于 pre-computed context 并以 knowledge indicators 表示的系统,可以在严格预算下击败 search-and-fetch,而且差距足够大,值得投入工程成本。

extraction 必须针对领域进行调优

一个通用 extractor 会产生通用 facts,而通用 facts 无法完成 disambiguation。之所以这个 96 问题的实验有效,是因为 extractor prompt 是针对人类构建的 eval dataset 进行调优的 —— 包括需要提取的实体类型、日期和细节。如果把同样的 extractor 用在 logs 语料库或 payments 语料库上,KIs 会变得没有意义。

这种调优也不是一次性的 setup 步骤。它以 agent loop 的形式持续运行并不断改进。extraction agent 编写 prompt,eval 展示失败点,然后 agent 基于这些失败重写 prompt。Stage 1 正是通过 4 轮迭代完成的。而这个 loop 在上线后仍然持续运行,因为数据源会变化,问题也会漂移。每个新领域都需要一个适配其数据源的 extractor,以及一个持续保持适配的过程。

retrieval 是把正确事实带给 agent 的关键

在 Stage 2 中,agent 在29个失败里有19个选错了相似邻居。正确事实通常在 index 中,但 agent 无法区分两个非常相似的实体。这是一个 retrieval 问题,仅靠文本相似度无法解决。

这也是为什么 hybrid semantic + lexical search、tags 和 aggregations 是必要的 —— agent 需要在提交答案之前看到结果集合的结构。aggregations 提供按 tag、source 和 entity 的统计,使 agent 知道答案是分散在三个来源还是集中在一个来源。tag filtering 允许它在一次调用中收敛到单一实体。这些能力让 agent 可以快速扫描大规模结果集并决定下一步,而不是逐条读取 KI 并消耗 step。

feedback loop 是提升上限的关键

Stage 1 和 Stage 2 是一次性提取 context 并读取回去。准确率停留在 70%。继续增加相同方式的 facts 并不会解决问题,因为问题不在缺少 facts,而在于 agent 在两个相似选项之间选错,而 extractor 单独调优无法解决。

真正提升上限的是 failure 本身。当 agent 提交错误答案时,trace 会给出非常精确的信息——语料库未能区分的两个实体,以及 agent 实际选择的错误项。这种信息足够可操作。系统会利用这些失败构建新的 KI,直接针对差异点,每个 KI 同时命名两个实体并说明它们的区别。Stage 1 的调优改善 fact 提取方式;feedback loop 则补充了 extractor 原本不会生成的定向 facts。Stage 3 正是这样做的,使准确率从70%提升到92%。

下一步

这只是我们希望分享的第一种策略 —— bottom-up extraction into knowledge indicators —— 我们还计划探索更多利用 retrieval、data management 和 agent feedback 的方法。我们认为在 token 紧张的情况下,让 agents 变得更便宜、更精准仍然有很大空间,我们也很期待展示接下来的进展。

原文:https://www.elastic.co/search-labs/blog/pre-computed-context-llm-agent-costs

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 6:01:37

SYN6658语音芯片踩坑实录:SPI和UART怎么选?GB2312编码发送总失败?

SYN6658语音芯片实战指南&#xff1a;接口选型与编码问题深度解析在嵌入式语音合成领域&#xff0c;SYN6658芯片凭借其稳定的性能和丰富的中文支持&#xff0c;成为许多智能硬件产品的首选。然而在实际开发中&#xff0c;工程师们常被接口选型和编码问题困扰。本文将基于真实项…

作者头像 李华
网站建设 2026/5/28 6:01:37

ViT微调时,position embedding插值那点事儿:从1D向量到2D网格的变形记

ViT微调中的位置编码插值&#xff1a;从1D向量到2D网格的几何奥秘当你第一次听说Vision Transformer&#xff08;ViT&#xff09;微调时需要对1D的位置编码进行2D插值&#xff0c;是不是觉得这像在变魔术&#xff1f;毕竟&#xff0c;我们习惯性认为位置编码就是个简单的序列向…

作者头像 李华
网站建设 2026/5/28 5:59:04

别再只调参了!用Scikit-learn的StackingClassifier提升模型性能的实战指南

别再只调参了&#xff01;用Scikit-learn的StackingClassifier提升模型性能的实战指南当你在Kaggle竞赛中反复调整随机森林的max_depth参数&#xff0c;或在业务场景中尝试了所有可能的XGBoost超参数组合后&#xff0c;模型性能依然卡在某个瓶颈——这时候&#xff0c;你需要的…

作者头像 李华
网站建设 2026/5/28 5:57:58

告别命令盲敲!用VS Code图形化界面搞定华为云Git代码上传

告别命令盲敲&#xff01;用VS Code图形化界面搞定华为云Git代码上传对于许多刚接触版本控制的开发者来说&#xff0c;Git的命令行操作就像一堵高墙&#xff0c;git add、git commit、git push这些看似简单的指令背后&#xff0c;隐藏着分支管理、冲突解决等复杂概念。而实际上…

作者头像 李华