Learning to Retrieve from Agent Trajectories
Paper: arXiv:2604.04949 Code: Yuqi-Zhou/LRAT Code reference:
main@4ea45eb6(2026-04-08)
1. Motivation (研究动机)
现有 IR / learning-to-rank 系统的核心假设仍然是“服务人类用户”:训练信号来自 click、dwell time、skip-above 等人类交互日志,模型学到的是人如何提交 query、如何扫视排序列表、如何表达 relevance。LLM search agent 出现后,retriever 的真实使用者变成了 agent:它会在长链任务中反复生成中间 query、阅读 snippet、执行 [Browse]、再把页面内容写入后续 reasoning。这使 retriever 不再只是一个给人类看的终点,而是 agent reasoning/action loop 中决定可观察信息边界的工具。
本文要解决的具体问题是:如何把 agent trajectory 本身转化为 retriever 训练监督。如果继续用 human-centric retriever,agent 的中间 query 往往不是最终用户意图,而是为了推进某个子目标;agent 对文档的“有用”判断也不只体现在点击,而体现在是否 browse、browse 后是否继续分析、分析链有多长。论文把这个问题形式化为 Learning to Retrieve from Agent Trajectories,并提出 LRAT:从 Search→Browse transition、post-Browse reasoning、reasoning length 中挖掘 positive / negative / relevance intensity。
这个问题值得做,因为 agent trajectory 是每次 agent 调用自然产生的副产物,不需要额外人工标注。如果能把它变成稳定监督,就可以形成类似 web search click-log 的数据飞轮:agent 使用 retriever 产生轨迹,轨迹反过来训练更 agent-aligned 的 retriever,更好的 retriever 又让 agent 更容易找到 evidence、减少无效 search/browse 步数。
Figure 2 解读:左侧传统 Human Search 中,training data 来自 Human Log,service users 也是 Human;右侧 Agentic Search 中,服务对象变为 Agent,而训练数据也应从 Agent Trajectory 产生。图中红色虚线强调 mismatch:如果只把 human-trained retriever 接到 agent 上,训练目标和真实消费方式并不一致。
2. Idea (核心思想)
核心 insight 是:agent trajectory 里已经包含比 click log 更接近 agent 需求的 implicit feedback。[Browse] 表示 agent 认为 snippet 值得展开,未 browse 的候选文档更像显式拒绝,browse 后的 reasoning trace 则告诉我们这个文档是否真正推进了任务,以及推进强度有多大。
LRAT 的关键创新是把这三类信号串成一个 progressive mining pipeline:先用 Search→Browse 构造粗 positive / negative,再用 LLM-as-judge 过滤 browsed-but-useless false positives,最后用 post-Browse reasoning length 估计连续的 relevance intensity,并把它注入 weighted contrastive learning。它和传统 click/dwell-time learning-to-rank 的根本差异在于:传统方法建模“人看到排序结果后的行为”,LRAT 建模“agent 在多轮 reasoning 中如何消费 retrieved documents”。
Figure 1 解读:这张图给出 Qwen3-Embedding-0.6B retriever 下的整体效果概览。InfoSeek-Eval 的平均 success rate gain 为 +28.6%,BrowseComp-Plus 的平均 gain 为 +27.5%;六个 agent backbone 从 4B 到 358B 都受益,说明 retrieval quality 即使在强 agent 上仍是瓶颈。
3. Method (方法)
3.1 Overall framework:从 trajectory 到 weighted retriever training
LRAT 输入是一组有效 agent trajectories 。每条 trajectory 包含 question 、多轮 reasoning 、action 、Search 返回的 candidate set 、Browse 的文档 ,以及最终答案 。框架输出是一个训练 dense bi-encoder retriever 的 JSONL 样本集合:query、pos、neg、reasoning_len、satisfied、reweight_rate。
直觉上,LRAT 把 agent 的“搜索过程”拆成两层监督:第一层是离散 relevance,即这个文档是否值得作为 positive;第二层是连续 utility,即这个文档对后续 reasoning 的贡献强度。前者解决训练样本从哪里来,后者解决不同 positive 是否应该等权。因为 agent 会显式写出 browse 后的分析,trajectory 比 click log 多了一个可读的中间状态,LRAT 正是利用这个状态来降低 browse 信号中的噪声。
Figure 5 解读:上半部分展示 agent 执行链:question 进入 agent,agent 在 reasoning 后发出 Search,读取 top- snippets,再 Browse 某个文档,随后产生 post-Browse reasoning,最后给出 answer。下半部分是训练管线:(a) 把被 browse 的文档标为 naive positive,未 browse 的同批候选作为 negative;(b) 用 post-Browse reasoning 和 LLM judge 判断 browsed document 是否真 relevant;(c) 用 reasoning length 估计 relevance intensity;(d) 用 weighted InfoNCE 让 query embedding 更接近 high-utility positive、远离 negative。
3.2 Trajectory 生成与行为分析
论文先构造 trajectory 数据再验证这些信号是否合理。Seed data 选用 InfoSeekQA:超过 50K 个需要 hierarchical reasoning 和 iterative information acquisition 的 QA;作者选择 top 10K 个有 verified ground-truth answer 的 query。Corpus 使用 Wiki-25-Dump,包含超过 11.2M 个 512-token document chunks。轨迹收集时部署 BM25、Qwen3-Embedding-0.6B、Qwen3-Embedding-4B、Qwen3-Embedding-8B 四个 retriever;每次 [Search] 返回 top-10 candidate snippets,每个 snippet 是文档前 64 tokens。
Agent 使用 Tongyi-DeepResearch-30B-A3B,最大交互轮数 ;若到达上限仍未结束,则基于已收集信息输出最终答案。有效 trajectory 需要最终答案与 InfoSeekQA ground truth 匹配,正确性由 Qwen3-30B-A3B-Thinking-2507 judge 验证。最终共有 34,619 条 completed trajectories,其中 26,482 条 correct、8,137 条 incorrect;用于主 LRAT 实例化的是 26,482 条 correct trajectories,生成 91,713 个训练 pairs。
Figure 4 解读:(a) 正确 trajectory 的 Search→Browse 概率是 23.0%,错误 trajectory 只有 7.1%;错误 trajectory 更容易停留在 Search→Search loop(92.9%)。(b) Browse 到的 evidence 数越多,answer accuracy 越高;没有 browse 到 evidence 时 accuracy 为 0。(c) Agent 的 browse rank distribution 比 human click 更接近均匀分布,说明未 browse 不只是 position bias,而更像主动拒绝。(d) 正确 trajectory 与 evidence document 后的 post-Browse reasoning 更长,因此 reasoning length 可作为 relevance intensity proxy。
3.3 Naive relevance mining:Search→Browse 产生粗监督
对某个 search turn ,agent 发出中间 query ,retriever 返回 top- candidate set:
如果下一步 agent 对其中某个文档执行 [Browse],LRAT 将 browsed document 视为 naive positive。因为 Figure 4 显示 browse 是成功任务的必要信号,browse 至少说明 agent 认为 snippet 值得展开。对应地,同一 retrieved candidate set 中未被 browse 的文档被当作 naive negatives:
这样得到粗训练实例 。和 human click log 不同,LRAT 不需要 skip-above 这类保守负采样:agent 浏览位置分布没有强 top-rank bias,未 browse 更可能表示“看过 snippet 后拒绝”。
3.4 Reasoning-aware positive filtering:用 post-Browse reasoning 去噪
Browse 仍然是 imperfect proxy:agent 可能只是因为 snippet 看起来相关而打开页面,随后发现页面无用。LRAT 因此收集 browse 后紧接的 reasoning trace ,用 LLM-as-judge 判断分析文本是否明确使用了文档内容推进任务。论文中 judge model 是 Qwen3-30B-A3B-Thinking-2507,输出 Relevant 或 Irrelevant。
Released code 中的 src/data_builder.py 使用更具体的 conservative prompt:只有当 analysis text 明确出现 not relevant / unrelated / off-topic / no useful info 等负面判断时才输出 NOT_RELEVANT,否则输出 RELEVANT。这与论文的设计意图一致:宁可保留部分 agent-specific utility,也不要误删 strong positives。论文在 BrowseComp-Plus evidence annotations 上验证,filter 保留 97.2% ground-truth evidence documents,同时保留 74.8% browsed non-evidence documents;后者说明它确实去掉了明显噪声,但也承认 dataset evidence label 之外可能存在 agent-specific helpful context。
3.5 Relevance intensity:reasoning length 到权重
LRAT 不把所有 positive 等权。它借鉴 time-aware click model:human dwell time 越长,相关性累计收益越高但边际收益递减;agent 中则用 post-Browse reasoning length 作为类似 dwell time 的信号。边际收益函数为: 其中 是 half-life。积分得到累计 utility: 最终训练权重省略常数因子并做全局均值归一化: 其中 是 browse 后 reasoning token 数, 在 code 中取所有 positive reasoning length 的 median, 是未归一化权重的全局均值,使 。这个 saturating design 避免特别长的 reasoning trace 支配训练,同时仍让“引发深度分析”的文档贡献更大梯度。
Figure 6 解读:post-Browse thought length 呈明显长尾 / 衰减趋势,因此线性按长度加权会让少数超长 trace 过度影响训练。LRAT 用 exponential saturation 把“更长 reasoning 更重要”和“边际收益递减”同时编码进权重。
3.6 Weighted contrastive learning
Retriever 使用标准 bi-encoder:query 和 document 分别编码为 ,相似度为 。对 mini-batch size ,论文写出的 weighted InfoNCE 为: 负样本来自两部分:同一 retrieved candidate set 中未 browse 的 documents,以及 mini-batch 中其他 query 的 paired documents。这样既利用 agent 明确拒绝的候选,又保留 dense retriever 常用的 in-batch negatives。
论文公式与 released code 实现差异:论文公式是 ;FlagEmbedding/FlagEmbedding/finetune/embedder/encoder_only/base/modeling.py 与 decoder-only 版本实际实现为 (per_sample * w).sum() / w.sum().clamp_min(1e-12),即按 归一化的 weighted mean。由于 src/data_builder.py::add_reweight_rate 已让全局 ,二者在大 batch / 全局平均意义上接近,但单个 batch 内梯度尺度会更稳定。
3.7 Source-grounded pseudocode
import math
import torch
import torch.nn.functional as F
BROWSE_TOOLS = {"get_document", "visit"}
def judge_relevance_with_prompt(analysis_text: str, llm_client) -> bool:
prompt = f"""
Classify whether AnalysisText suggests the browsing text is relevant.
Output NOT_RELEVANT only for explicit negative judgments such as
irrelevant, unrelated, off-topic, no useful info. Otherwise output RELEVANT.
AnalysisText:\n{analysis_text}
"""
first_token = llm_client(prompt).strip().split()[0]
return first_token == "RELEVANT"def build_lrat_pairs(trajectory: dict, corpus: dict, tokenizer, judge_fn):
steps = trajectory["result"]
samples, history_search_results, history_browsed_unsat = [], [], []
current_query = None
i = 0
while i < len(steps):
step = steps[i]
if step.get("type") == "tool_call" and step.get("tool_name") == "search":
current_query, current_docs = parse_search(step) # query, top-K doc ids
history_search_results.append(current_docs)
i += 1
continue
if step.get("type") == "tool_call" and step.get("tool_name") in BROWSE_TOOLS:
run, j = [], i
while j < len(steps) and steps[j].get("tool_name") in BROWSE_TOOLS:
docid = get_docid_from_browse_step(steps[j])
reasoning = extract_reasoning_text_from_next_step(steps, j)
run.append({
"docid": docid,
"reasoning_len": len(tokenizer.encode(reasoning)),
"satisfied": judge_fn(reasoning),
})
j += 2 if j + 1 < len(steps) and steps[j + 1].get("type") == "reasoning" else 1
sat_docs = [x["docid"] for x in run if x["satisfied"]]
unsat_docs = [x["docid"] for x in run if not x["satisfied"]]
browsed = set(history_browsed_unsat) | set(sat_docs) | set(unsat_docs)
unbrowsed = collect_unbrowsed_docs(history_search_results, browsed)
negatives_base = list(reversed(unsat_docs)) + list(reversed(history_browsed_unsat)) + unbrowsed
for x in run:
if x["docid"] not in corpus:
continue
neg_ids = unique([d for d in negatives_base if d != x["docid"] and d not in sat_docs])
samples.append({
"query": current_query,
"pos": [corpus[x["docid"]]],
"neg": [corpus[d] for d in neg_ids if d in corpus],
"pos_id": [x["docid"]],
"neg_id": [d for d in neg_ids if d in corpus],
"reasoning_len": x["reasoning_len"],
"satisfied": bool(x["satisfied"]),
})
history_browsed_unsat.extend(unsat_docs)
if sat_docs:
history_search_results, history_browsed_unsat, current_query = [], [], None
i = j
continue
i += 1
return samplesdef add_reweight_rate(samples):
lens = [float(s["reasoning_len"]) for s in samples if s.get("reasoning_len", 0) > 0]
beta = torch.tensor(lens).median().item() if lens else 1.0
raw = []
for s in samples:
l = float(s.get("reasoning_len") or 0)
raw.append(1 - math.exp(-l * math.log(2.0) / beta) if l > 0 else None)
mean_w = sum(x for x in raw if x is not None) / max(1, sum(x is not None for x in raw))
for s, x in zip(samples, raw):
s["reweight_rate"] = x / mean_w if x is not None and mean_w != 0 else 1.0
return samplesdef weighted_contrastive_loss(query_emb, doc_emb, target, reweight_rates, temperature=0.02):
scores = query_emb @ doc_emb.T / temperature
per_sample = F.cross_entropy(scores, target, reduction="none")
w = torch.as_tensor(reweight_rates, device=scores.device, dtype=scores.dtype).view(-1)
return (per_sample * w).sum() / w.sum().clamp_min(1e-12)Code reference:
main@4ea45eb6(2026-04-08) — pseudocode and mapping based on this commit
| Paper Concept | Source File | Key Class/Function |
|---|---|---|
| trajectory JSON → LRAT samples | src/data_builder.py | extract_pairs_with_satisfaction_groups, _parse_search, _collect_unbrowsed_docs |
| segmented trajectory sampling | src/data_builder_segmented.py | extract_segmented_pairs, _in_segment, segment-mode arguments |
| LLM-as-judge filtering | src/data_builder.py | JUDGE_PROMPT, judge_relevance, call_chat_completions |
| reasoning-length reweighting | src/data_builder.py | add_reweight_rate |
| training sample collation | FlagEmbedding/FlagEmbedding/abc/finetune/embedder/AbsDataset.py | reweight_rate loading, reweight_rates collation |
| weighted contrastive loss | FlagEmbedding/FlagEmbedding/finetune/embedder/encoder_only/base/modeling.py; .../decoder_only/base/modeling.py | compute_loss(..., reweight_rates=...) |
| actual training launch config | FlagEmbedding/examples/finetune/embedder/run.sh | Qwen3-Embedding-0.6B, group size 10, LR 1e-6, batch 32, 2 epochs |
4. Experimental Setup (实验设置)
4.1 Datasets and corpora
- Trajectory construction:InfoSeekQA,超过 50K QA;作者选择 top 10K verified-ground-truth queries 生成训练轨迹。检索 corpus 是 Wiki-25-Dump,超过 11.2M 个 512-token document chunks。
- In-domain evaluation:InfoSeek-Eval,300 个 multi-hop information-seeking queries,且与训练数据严格 disjoint。
- Out-of-domain evaluation:BrowseComp-Plus,830 个 complex human-authored questions;官方 evaluation corpus 有 100,195 documents,并提供 evidence annotations 以计算 Evidence Recall。
4.2 Baselines / backbones
Retrieval backbones 包括 Multilingual-E5-Large-Instruct(encoder-based)和 Qwen3-Embedding-0.6B(decoder-based embedding model)。Agent backbones 分两组:task-optimized search agents:AgentCPM-Explore-4B、WebExplore-8B、Tongyi-DeepResearch-30B;generalist agentic foundation models:GPT-OSS-120B、MiniMax-M2.1-229B、GLM-4.7-358B。主要比较是原始 retriever vs. + LRAT (Ours)。
4.3 Metrics
- Success Rate (SR):由 Qwen3-30B-A3B-Thinking-2507 automated judge 判定最终答案正确率。
- Average Step Count:agent 完成任务平均交互步数,越低表示 retriever 提供的信息更直接,减少 search/browse 探索。
- Evidence Recall:BrowseComp-Plus 上,agent 执行过程中是否 retrieve 到 annotated evidence document;InfoSeek-Eval 无 trace-level evidence annotation,因此不报告 Recall。
4.4 Training and generation config
Paper 报告并由 released code 的 FlagEmbedding/examples/finetune/embedder/run.sh 对齐的 retriever fine-tuning 配置为:FlagEmbedding framework;--model_name_or_path Qwen3/Qwen3-Embedding-0.6B;--train_group_size 10;query/passsage max length 均为 512;--learning_rate 1e-6;--num_train_epochs 2;--per_device_train_batch_size 32;--temperature 0.02;--bf16;--negatives_cross_device;--normalize_embeddings True;torchrun --nproc_per_node 8。论文正文没有说明 GPU 型号;source 中有一行被注释掉的 “8 NVIDIA A100 80GB GPUs”,因此这里不把 GPU 型号作为 confirmed training setting。
Agent generation side 固定 random seed 2025,temperature 0.85,,presence penalty 1.1;evaluation 时每个 query 限制 50 turns。Trajectory collection 的分析阶段最大交互轮数是 。
5. Experimental Results (实验结果)
5.1 Main results
Table 2 的主结论是:LRAT 在两个 retriever backbone 与六个 agent backbone 上都提升 SR / Recall,并且常常减少 InfoSeek-Eval 的 average steps。Qwen3-Embedding-0.6B 下的代表性结果:
| Agent | InfoSeek SR Base → LRAT | BrowseComp SR Base → LRAT | BrowseComp Recall Base → LRAT |
|---|---|---|---|
| AgentCPM-Explore (4B) | 40.3 → 55.7 (+38.2%) | 13.5 → 15.8 (+17.0%) | 23.2 → 32.0 (+37.9%) |
| WebExplore (8B) | 52.0 → 68.7 (+32.1%) | 21.0 → 27.2 (+29.5%) | 47.7 → 55.9 (+17.2%) |
| Tongyi-DeepResearch (30B) | 52.7 → 68.0 (+29.0%) | 17.8 → 23.7 (+33.1%) | 49.2 → 60.7 (+23.4%) |
| GPT-OSS (120B) | 40.0 → 47.0 (+17.5%) | 9.0 → 12.1 (+34.4%) | 43.7 → 56.4 (+29.1%) |
| MiniMax-M2.1 (229B) | 58.7 → 78.3 (+33.4%) | 38.2 → 48.3 (+26.4%) | 57.2 → 69.2 (+21.0%) |
| GLM-4.7 (358B) | 67.7 → 82.0 (+21.1%) | 43.9 → 54.6 (+24.4%) | 66.6 → 77.8 (+16.8%) |
E5-Large 下同样提升:例如 GLM-4.7 的 InfoSeek SR 从 73.7 到 81.7(+10.9%),BrowseComp SR 从 46.4 到 50.6(+9.1%),Recall 从 68.7 到 76.3(+11.1%);MiniMax-M2.1 的 BrowseComp Recall 从 64.9 到 69.7(+7.4%)。论文总结 BrowseComp-Plus 上 evidence recall 的 relative gains 覆盖 7% 到超过 37%。
5.2 Ablation: Naive / Filter / Reweight
Figure 7 解读:ablation 使用 BrowseComp-Plus、Qwen3-Embedding-0.6B,并逐步加入组件。GPT-OSS 从 Base 9.0 到 +Naive 11.5、+Filter 11.8、+Reweight 12.2;MiniMax-M2.1 从 38.2 到 39.0、44.8、48.3;GLM-4.7 从 43.9 到 53.2、55.3、54.6。Naive 已有明显收益,说明 browsed / unbrowsed 信号可用;Filter 对 MiniMax 和 GLM 明显有帮助;Reweight 对 GPT-OSS 和 MiniMax 继续提升,但 GLM-4.7 上略低于 Filter-only,说明 relevance intensity 不是对所有 agent 都单调更优。
5.3 Correct vs. incorrect trajectories
论文进一步检验 data flywheel 场景下是否必须只用 correct trajectories。Table 3 中,每种训练数据都使用 10K examples:
| Training Data | GPT-OSS | MiniMax-M2.1 | GLM-4.7 |
|---|---|---|---|
| Base (without LRAT) | 9.0 | 38.2 | 43.9 |
| LRAT with Incorrect Trajectories | 10.7 (+18.9%) | 43.6 (+14.1%) | 50.6 (+15.3%) |
| LRAT with Correct Trajectories | 11.8 (+31.1%) | 45.3 (+18.6%) | 52.6 (+19.8%) |
结果说明:incorrect trajectory 的最终答案错了,但其中的中间 browse / reject 行为仍有 retrieval utility 信号;只是 correct trajectories 更干净、收益更大。这对真实部署很重要,因为线上 agent trajectory 不一定都有可靠 final correctness label。
5.4 Scalability, top-K robustness, and data flywheel
Figure 8 解读:左图显示随着 InfoSeekQA trajectory 数据从 baseline 增至 10K / 20K / 30K,GPT-OSS、MiniMax-M2.1、GLM-4.7 的 SR 大体继续上升,没有早期饱和;右图比较不同 top- retrieval budgets,LRAT 在 下总体都优于 base,但过大的 并不总是更好,尤其 GLM-4.7 可能因噪声和上下文容量限制而下降。
Figure 9 解读:左侧是模拟 streaming deployment:每一轮 agent 使用当前 retriever 产生 trajectories,随后更新 retriever,再进入下一轮;右侧显示 loop step 增加时 agent success rate 与 retriever recall 都保持上升趋势。该结果支持论文的核心 claim:agent trajectories 不只是一次性训练数据,也可能像 click logs 一样支撑持续的数据飞轮。
5.5 Limitations and practical caveats
论文没有给出系统性的 limitations section,但从方法和 released code 可以看到几个实践 caveat。第一,LLM-as-judge filtering 依赖 Qwen3-30B-A3B-Thinking-2507 或兼容 judge endpoint;judge prompt 在 code 中偏 conservative,可能保留一些 weak positives。第二,training signals 来自 BrowseComp / InfoSeek 风格的 deep research agent;对短问答、工具调用混合更多的 agent、或非 Wikipedia corpus 是否同样有效需要额外验证。第三,论文正文未确认硬件型号,且 actual launch script 是 Qwen3-Embedding-0.6B 的 recipe;迁移到 E5-Large 或更大 retriever 时仍需核对对应训练脚本。第四,paper formula 与 released code 的 loss normalization 存在小差异,复现实验时应以 main@4ea45eb6 的 weighted mean 实现为准。