面向用户记忆评估的 Agentic RAG


文档摘要

源文件:chapter3/agentic-rag-for-user-memory/README.md 面向用户记忆评估的 Agentic RAG 一个教学项目,把检索增强生成(RAG)与用户记忆评估结合,展示 AI Agent 如何高效地管理与查询长期对话历史。 🎯 学习目标 本项目教你: 如何把长对话分块为可索引的可管理片段 如何对接外部检索流水线做混合搜索 如何用工具调用与 ReAct 模式实现 Agentic RAG 如何用自动化的 LLM 评分评估记忆系统 如何针对基于对话的查询优化检索 如何整合不同项目的评估框架 🏗️ 架构概览 📚 关键概念 对话分块 长对话历史被切成约 20 轮(user-assistant 交换)一块。

源文件:chapter3/agentic-rag-for-user-memory/README.md

面向用户记忆评估的 Agentic RAG

一个教学项目,把检索增强生成(RAG)用户记忆评估结合,展示 AI Agent 如何高效地管理与查询长期对话历史。

🎯 学习目标

本项目教你:

  1. 如何把长对话分块为可索引的可管理片段
  2. 如何对接外部检索流水线做混合搜索
  3. 如何用工具调用与 ReAct 模式实现 Agentic RAG
  4. 如何用自动化的 LLM 评分评估记忆系统
  5. 如何针对基于对话的查询优化检索
  6. 如何整合不同项目的评估框架

🏗️ 架构概览

┌─────────────────────────────────────────┐ │ User Memory Test Cases │ │ (60 test cases, 3 difficulty layers) │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Conversation Chunker │ │ (Splits into 20-round segments with │ │ overlap and contextual enrichment) │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ External Retrieval Pipeline │ │ (Port 4242 - Hybrid Search) │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │Dense Search │ │ Sparse Search │ │ │ │ (Embeddings)│ │ (BM25) │ │ │ └─────────────┘ └──────────────────┘ │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Agentic RAG Agent │ │ (ReAct pattern with memory tools) │ │ │ │ Tools: │ │ • search_memory │ │ • get_conversation_context │ │ • get_full_conversation │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ LLM Evaluation System │ │ (Automatic scoring and reasoning) │ │ • Reward score (0.0-1.0) │ │ • Pass/Fail determination │ │ • Detailed reasoning │ └─────────────────────────────────────────┘

📚 关键概念

1. 对话分块

长对话历史被切成约 20 轮(user-assistant 交换)一块。这样让它们:

  • 可搜索:更小的单元更易索引与检索
  • 有上下文:每块都保留与前后对话的上下文
  • 高效:减少 LLM 需要处理的文本量

2. 混合检索(通过外部流水线)

系统与一个外部检索流水线服务集成,提供:

  • 稠密检索:用嵌入做语义相似度搜索
  • 稀疏检索:用 BM25 做关键词匹配与精确短语搜索
  • 混合融合:结合两种方法的得分以获得最优结果
  • 可扩展架构:把索引与搜索卸载到专门的服务

3. Agentic RAG 模式

Agent 遵循 ReAct(Reasoning + Acting)模式:

  1. 推理需要哪些信息
  2. 通过调用搜索工具行动
  3. 观察结果
  4. 迭代直到找到足够信息

4. 自动 LLM 评估

系统与 week2/user-memory-evaluation 集成,提供:

  • 奖励打分:0.0 到 1.0 的连续分数
  • 通过/失败判定:自动判定(≥0.6 通过)
  • 详细推理:对评估决定的解释
  • 完全可见:增强 LLM 响应与工具调用的日志

5. 上下文增强

文本块会被增强:

  • 关于对话的元数据(业务、部门、时间戳)
  • 前后块的上下文
  • 便于检索的语义标签

🚀 快速开始

前置条件

  • Python 3.8+
  • 4242 端口上的检索流水线服务现在是可选的。 默认情况下索引器使用
    retrieval_backend="auto":若外部流水线可达就用它,否则透明回退到
    内置、零依赖的本地 BM25 索引,使整条 分块 → 索引 → 检索 路径完全离线运行。
  • 只有 LLM 驱动的部分才需要 API Key:
    • 一个受支持的 LLM 提供方(Kimi/Moonshot、OpenAI、SiliconFlow、DeepSeek 等),用于
      生成 Agent 答案(--mode batch/interactive/demo)。
    • 离线对比 demo(--mode offline-demo)既不需要 API Key,也不需要 4242 端口的服务。

安装

# Enter the project cd chapter3/agentic-rag-for-user-memory # Install dependencies pip install -r requirements.txt # Setup environment variables cp env.example .env # Edit .env with your API keys

检索后端(默认离线,流水线可选)

检索后端可通过 --backend(或 IndexConfig.retrieval_backend)选择:

取值 行为
auto 默认 — 若 4242 端口流水线可达就用它,否则用本地 BM25
local 始终使用内置离线 BM25 索引(无外部服务)
pipeline 始终使用 4242 端口上的外部检索流水线

若要用外部流水线(做稠密/混合嵌入 + 重排序),请先启动它:

# In a separate terminal (OPTIONAL) cd ../retrieval-pipeline python api_server.py # serves http://localhost:4242

运行 Demo

# Offline comparison demo — NO API key, NO port 4242 needed. # Shows agentic multi-hop memory retrieval beating naive single-query recall, # on the multi-session layer2_01_multiple_vehicles case, with a metric table. python main.py --mode offline-demo python offline_demo.py # equivalent, standalone entry point python offline_demo.py --output results/offline_demo.json # also dump JSON # Test the system setup python test_pipeline.py # Run interactive mode python main.py # Quick demo with a simple test case (needs an LLM API key) python main.py --mode demo # Batch evaluation of a category (needs an LLM API key; --backend local stays offline) python main.py --mode batch --category layer1 --backend local

离线 demo 结果(可复现)

layer2_01_multiple_vehicles(用户拥有一辆已预约 Firestone 保养的 Honda Accord
和一辆未预约的 Tesla Model 3,相关信息分散在两次独立通话中)上运行
python offline_demo.py,基于真实 BM25 检索的结果如下:

指标 朴素单查询 agentic 多跳
发起的检索查询数 1 5
检索到的记忆块数 3 5
关键证据召回率 50% 100%
能否完全消歧并作答

朴素查询被 "schedule service" 关键词主导,漏掉了 Honda 预约确认块
FS-447291)。Agentic 策略从首轮结果中发现第二辆车,针对每辆车发起聚焦的后续查询,
找回了缺失的证据。召回数字由实际检索计算得出,不是写死的。

CLI 参数(main.py

--mode {interactive,batch,demo,offline-demo}--category--test-id--query
--provider--model--index-mode {dense,sparse,hybrid}
--backend {auto,local,pipeline}--top-k--rounds-per-chunk--store-path
--test-cases-dir--output--config。运行 python main.py --help 查看
(中文)说明。

📖 使用指南

交互模式

交互界面提供以下选项:

  1. 加载测试用例:从评估框架加载测试用例
  2. 查看测试用例:浏览已加载的测试用例及详情
  3. 配置设置:调整分块、索引与 Agent 参数
  4. 评估单个测试:对指定测试用例运行评估
  5. 按类别评估:测试某个难度层的全部用例
  6. 生成报告:生成详细的评估报告

示例工作流

# 1. Initialize the evaluator from config import Config from evaluator import UserMemoryEvaluator config = Config.from_env() evaluator = UserMemoryEvaluator(config) # 2. Load test cases test_cases = evaluator.load_test_cases(category="layer1") # 3. Evaluate a test case result = evaluator.evaluate_test_case("layer1_01_bank_account") # 4. Generate report report = evaluator.generate_report("results/evaluation_report.txt")

配置系统

config.py 中的关键配置项:

# Chunking settings config.chunking.rounds_per_chunk = 20 # Rounds per chunk config.chunking.overlap_rounds = 2 # Overlapping rounds # Index settings config.index.mode = "hybrid" # dense, sparse, or hybrid config.index.enable_contextual = True # Add contextual enrichment # Agent settings config.agent.max_search_results = 5 # Results per search config.evaluation.max_iterations = 10 # Max ReAct iterations

🧪 测试用例结构

测试用例遵循 user-memory-evaluation 框架的格式:

测试用例字段

  • test_id:唯一标识
  • category:难度层(layer1、layer2、layer3)
  • title:描述性标题
  • conversation_histories:要索引的历史对话
  • user_question:要回答的问题
  • evaluation_criteria:评估响应的标准
  • expected_behavior:可选的预期 Agent 行为

Layer 1:简单信息检索

  • 单段对话,信息明确
  • 针对具体细节的直白问题
  • 示例:"我的支票账户号是多少?"

Layer 2:多对话关联

  • 多段相关对话
  • 需要信息综合的问题
  • 示例:"我的哪辆车需要先保养?"

Layer 3:复杂推理

  • 隐藏模式与隐含关联
  • 需要深度分析的问题
  • 示例:"出行前我该优先处理哪些紧急事项?"

🔧 组件细节

分块器(chunker.py

  • 把对话切成固定大小的块
  • 通过重叠轮次保持对话流
  • 为每块添加上下文信息

索引器(indexer.py

  • 与外部检索流水线服务集成
  • 通过 HTTP API 发送文档进行索引
  • 管理文档 ID 映射
  • 通过流水线执行混合搜索

工具(tools.py

  • search_memory:主搜索接口,带完整内容检索
  • get_conversation_context:检索周围的块
  • get_full_conversation:获取完整对话历史
    注意:所有工具都返回完整内容(不截断)

Agent(agent.py

  • 实现带工具调用的 ReAct 模式
  • 管理对话状态
  • 基于检索到的信息生成响应

评估器(evaluator.py

  • 从 YAML 文件加载测试用例
  • 管理索引流水线
  • 跟踪评估指标与结果
  • 集成自动 LLM 评估

📊 评估指标

系统跟踪全面的指标:

  • 成功率:正确回答的问题比例
  • LLM 评估分数:自动奖励分(0.0–1.0),附详细推理
  • 迭代次数:ReAct 推理步数
  • 工具调用数:使用的工具数量与类型
  • 处理时间:响应生成耗时
  • 索引时间:构建搜索索引的耗时
  • 结果质量:通过可配置 top_k 的重排序来控制

🔍 故障排查

Top-K 结果问题

问题:无论 top_k 设为多少都只得到 10 条结果
解决:检索流水线使用两个参数:

  • top_k:初始检索数(候选)
  • rerank_top_k:最终结果数(你实际拿到的)

系统现在会同时正确设置这两个参数,以尊重你请求的结果数。

LLM 评估未运行

问题:Agent 响应后没有自动评估
解决:确保你有:

  • 有效的 OpenAI API Key 用于评估
  • 可访问 week2/user-memory-evaluation 模块
  • 正确的测试用例格式,含 evaluation_criteria

检索流水线连接

问题:无法连接检索流水线
解决:这不再是致命错误——在 --backend auto(默认)下系统会记录一条
警告并回退到内置的本地 BM25 后端。如果你确实想用外部流水线:

  • 启动服务:cd ../retrieval-pipeline && python api_server.py
  • 核实它在 http://localhost:4242 上运行
  • 或用 --backend local 显式强制离线模式

📄 许可证

本项目是 AI Agent 训练课程的一部分,用于教学目的。

🔗 相关项目

  • week2/user-memory:基础用户记忆系统
  • week2/user-memory-evaluation:评估框架
  • week3/agentic-rag:原始 Agentic RAG 实现
  • week3/contextual-retrieval:进阶检索技术

OpenRouter 通用回退 / Universal OpenRouter fallback

本实验现已为其对话 LLM 支持通用 OpenRouter 回退

  • 若主提供方 key(如 MOONSHOT_API_KEY / KIMI_API_KEY / OPENAI_API_KEY / DOUBAO_API_KEY …)存在,行为不变。
  • 否则若设置了 OPENROUTER_API_KEY,对话 LLM 会自动经 OpenRouter 路由(https://openrouter.ai/api/v1)。模型名会自动映射:gpt-*/o1-*openai/…claude-*anthropic/claude-opus-4.8kimi-*moonshotai/kimi-k2.6,已含 / 的 id 保持原样,其他提供方原生 id(如 doubao-*)回退为 openai/gpt-5.6-luna。设置 OPENROUTER_MODEL 可强制指定 OpenRouter 模型 id。
  • 否则会给出清晰错误,列出可接受的 key。

.env 中加入 OPENROUTER_API_KEY=... 即可启用(见 env.example)。


作者与出处
原作者: bojieli
来源:bojieli
许可证:Apache-2.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: bojieli 转发
评论区 (0)
U