数据截至 (上游 commit c617143f0147)
HippoRAG 2 — 架构与原理
30 秒导读: HippoRAG 2 是给大模型用的"长期记忆"框架。它把你喂进去的文档离线抽成一张知识图谱(节点=实体和段落,边=文档里的事实关系 + 同义词关系);提问时,先让检索模型和大模型挑出几条最相关的"事实"当种子,再在图上跑个性化 PageRank(PPR)让相关性顺着边扩散,最终排出该读哪些段落。一句话:用图上的"联想"补足普通向量检索抓不到的多跳关联。
本项目较复杂(离线建图 + 在线图检索两大子系统,多种模型后端),故拆成多文件。本页是 Layer 0/1:先讲"这是什么",再给顶层全景和阅读地图。深入细节见各章节。
1. 这是什么(零基础也能懂)
一句话定义
HippoRAG 2 是一个 RAG(检索增强生成)框架:在普通"向量检索"之外,额外建一张 知识图谱,让检索能沿着实体之间的关系"联想",从而回答需要跨多篇文档拼接的问题。
它要解决谁的什么问题
普通 RAG(把每段文字编码成向量、按相似度取最近的几段)在一类问题上很吃亏——多跳问题(multi-hop):
问:"斯坦福大学创始人的妻子叫什么?"
答案往往分散在两篇文档里:一篇说"斯坦福由 Leland Stanford 创办",另一篇说"Leland Stanford 的妻子是 Jane Stanford"。问题本身和第二篇几乎没有词面相似度,普通向量检索抓不到它。HippoRAG 2 的图谱能从"斯坦福"这个实体出发,顺着边走到"Leland Stanford",再走到"Jane Stanford",把两篇都捞上来。
它面向的是**要给大模型装"能联想的长期记忆"**的人:做知识库问答、企业内文档助手、需要把大量零散资料整合起来回答的场景。
它能做什么
- 建索引(index):把一批文档抽成三元组、连成知识图谱并存好。
- 检索(retrieve):给一个问题,返回排好序的相关段落。
- 问答(rag_qa):检索 + 让大模型基于检索到的段落生成答案,可选算 EM/F1 指标。
- 多步检索(IRCoT):检索一轮 → 让大模型想一步 → 再检索,循环逼近多跳答案。
- 增量维护:支持往图里增删文档(index / delete),无需全量重建。
用起来什么样
最小可运行流程(来自 README.md Quick Start):
from hipporag import HippoRAG
docs = ["George Rankin is a politician."]
queries = ["What is George Rankin's occupation?"]
hipporag = HippoRAG(
save_dir="outputs",
llm_model_name="gpt-4o-mini",
embedding_model_name="text-embedding-3-small",
)
hipporag.index(docs=docs) # 离线:抽三元组、建图
results = hipporag.rag_qa(queries=queries) # 在线:检索 + 生成答案
对外就两步:index() 喂文档,rag_qa() 提问。图谱、向量库、缓存都落在 save_dir 下,第二次跑会自动复用。
一句话直觉 / 类比
项目名来自大脑的海马体(hippocampus)——人类形成新记忆、并把相关记忆"串联联想"的关键器官。把 HippoRAG 的组件对应到这套神经学隐喻(这是论文和代码共用的心智模型):
| HippoRAG 组件 | 大脑类比 | 干的事 |
|---|---|---|
| 知识图谱(实体+段落节点) | 海马体索引 | 记住"谁和谁有关系" |
| 段落语料 / 大模型 | 新皮层 | 存原始知识、做语言理解 |
| 检索编码器(linking) | 海马旁回 | 把问题对上图里的入口 |
| 事实过滤器(识别记忆) | 海马体识别记忆 | 判断"这条事实和问题真的相关吗" |
| 个性化 PageRank | 记忆的"扩散激活" | 从种子实体出发,让相关性顺着关系蔓延 |
本节不碰底层代码。记住一件事:HippoRAG = 向量检索 + 一张能"联想"的图。
2. 顶层全景(它大概怎么转)
系统分离线和在线两条主线。离线把文档变成图,在线拿图回答问题。
2.1 全景图
离线(index,建一次,复用多次)
文档 ──► OpenIE 抽取 ──► 实体/段落/事实 三种向量 ──► 连边成图 ──► 存盘
(NER+三元组) (分开编码存储) (事实边/段落边/同义边) (graph.pickle)
─────────────────────────────────────────────────────────────────────
在线(retrieve / rag_qa,每个问题跑一遍)
问题 ──► ① 事实打分 ──► ② 识别记忆过滤 ──► ③ 图上跑 PPR ──► ④ 排段落 ──► 大模型答
(query vs 事实) (大模型挑≤5条) (种子扩散激活) (top-k) (读段落生成)
│
没挑到事实 → 退回纯向量检索(DPR)
怎么读这张图:从左到右是数据流。上半是离线一次性建图;下半是每次提问都走的四步检索。第②步挑不出事实时,系统"降级"成普通向量检索,保证不会比普通 RAG 更差(这是它"不牺牲简单任务"的设计)。
2.2 部件一句话职责
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
HippoRAG | 最高层门面:index / retrieve / rag_qa 全在这 | src/hipporag/HippoRAG.py |
OpenIE | 对每段文字做 NER + 三元组抽取 | src/hipporag/information_extraction/openie_openai.py |
EmbeddingStore | 存段落/实体/事实三类向量(默认 Parquet 文件) | src/hipporag/embedding_store.py |
igraph.Graph | 骨干知识图谱,跑 PPR 的地方 | HippoRAG.py(initialize_graph / run_ppr) |
DSPyFilter | 识别记忆:用大模型过滤候选事实 | src/hipporag/rerank.py |
BaseConfig | 唯一的全局配置(所有超参在这) | src/hipporag/utils/config_utils.py |
BaseEmbeddingModel / BaseLLM | 可插拔的向量模型 / 大模型后端 | src/hipporag/embedding_model/ · src/hipporag/llm/ |
2.3 主线走一遍(高层,不进代码)
离线:index(docs) → 切块 → 每块抽实体和三元组 → 把"段落文本 / 实体名 / 事实字符串"分别编码成向量 → 三元组的两个实体互相连边(事实边)、段落连到它含的实体(段落边)、语义相近的实体互连(同义边)→ 存成 graph.pickle(HippoRAG.py:262 index)。
在线:retrieve(query) → 问题编码 → 和所有"事实"向量算相似度打分 → 取分最高的几条候选事实、交给大模型过滤留下真正相关的 → 用这些事实里的实体当"种子"给图上节点赋权、叠加向量检索给段落的权重 → 跑个性化 PageRank 让权重扩散 → 按 PPR 分数排段落返回(HippoRAG.py:413 retrieve)。
看懂这张"大盘"后,去各章看每一步的原理与代码。
3. 阅读地图(建议顺序)
本子库按"由浅入深"拆成三章,建议顺序读:
-
01-indexing-openie-graph.md— 离线建索引。 讲清"文档怎么变成一张图":OpenIE 抽三元组、三种节点/三种边的含义、同义边和增量更新的技巧。想知道"图长什么样、边的权重怎么来"看这章。 -
02-online-retrieval-ppr.md— 在线检索。 HippoRAG 的心脏:事实打分 → 识别记忆过滤 → 个性化 PageRank 扩散 → 出段落,以及"没事实就退回向量检索"的降级逻辑。想知道"多跳到底怎么实现的"看这章。 -
03-deep-dive-and-map.md— 深入与导航。 PPR 种子权重的 IDF 式设计、识别记忆的 DSPy 提示、边界与已知坑、和普通向量 RAG / GraphRAG 的取舍对比,末尾是代码地图(symbol 级跳转表)。
如果你只想要一句话结论:HippoRAG 2 的独特价值在第 2 章的"事实种子 + PPR 扩散"——这是它区别于普通向量 RAG 的全部秘密。