跳到主要内容

LightRAG — 架构与原理

30 秒导读: LightRAG 是港大数据智能实验室(HKUDS)开源的一套 RAG(检索增强生成)框架。它的卖点是:入库时不只把文档切块塞进向量库,还额外用 LLM 把文档抽成一张知识图谱(实体是点、关系是边);查询时把问题拆成「高层主题词 + 低层实体词」两路,分别去图谱的上做检索——这就是论文名字里的 dual-level retrieval(双层检索)。比起纯向量 RAG,它更擅长回答需要「跨多个文档串联关系」的问题。

本项目较大(lightrag.py 4469 行、operate.py 5995 行),本文档拆成 index + 4 章。本页给你 Layer 0(这是什么)+ Layer 1(顶层全景)+ 阅读地图;各机制的原理与源码走读在分章里。


1. 这是什么(零基础也能懂)

一句话定义: LightRAG 是一个「文档进、带引用的答案出」的 RAG 引擎,核心差异是它在普通向量检索之外,额外维护了一张由 LLM 抽出来的知识图谱,查询时同时利用图谱的点和边。

解决什么问题 / 给谁用:

假设你有一堆 PDF / 网页 / 内部文档,想做一个「问答机器人」:用户问一句话,机器人从你的文档里找答案并附上出处。最朴素的做法(naive RAG)是:把文档切成小块、每块算个向量、问题也算个向量、找最相似的几块塞给 LLM。

这套朴素做法在一类问题上很弱:需要把分散在多处的信息串起来的问题。例如「A 公司和 B 公司是什么关系?」——答案可能要拼接「A 投资了 C」+「C 被 B 收购」这种跨块的链条。纯向量检索找的是「和问题最像的块」,不擅长沿关系链跳转。

LightRAG 给这类问题用的是「知识图谱」这条额外的检索通道。它面向:

  • 做企业内部知识库 / 文档问答的工程师;
  • 需要「实体—关系」推理而非单纯语义相似的检索场景;
  • 想要可切换存储后端(本地文件 → PostgreSQL / Neo4j / Milvus 等)的部署者。

它能做什么(功能):

  • 入库:把文本/PDF 等切块,抽实体与关系,建知识图谱 + 三个向量库(实体、关系、原文块)。
  • 查询:支持 local / global / hybrid / mix / naive / bypass 六种模式(见下)。
  • 增量更新与删除:新文档增量并入图谱;删文档时回收并重建受影响的图谱节点。
  • 带引用回答:回答末尾生成 ### References 引用列表,可溯源到具体文档。
  • 可插拔:LLM、嵌入模型、重排模型、四类存储后端都可替换;还能给「抽取 / 查询 / 关键词 / 视觉」配不同的 LLM(role-specific)。

用起来什么样: 最小调用(示意,基于 LightRAG/QueryParam 真实 API):

# 示意,非源码。展示对外 API 形状
import asyncio
from lightrag import LightRAG, QueryParam

async def main():
rag = LightRAG(
working_dir="./my_kb", # 本地文件存储默认落在这里
llm_model_func=my_llm, # 你的 LLM 调用函数
embedding_func=my_embedding, # 你的嵌入函数
)
await rag.initialize_storages() # 必须先初始化存储

await rag.ainsert("OpenAI 由 Sam Altman 等人在 2015 年创立。") # 入库

# 查询:mix 模式 = 知识图谱 + 向量,双管齐下
res = await rag.aquery("谁创立了 OpenAI?", param=QueryParam(mode="mix"))
print(res)

asyncio.run(main())

对外入口与参数对象都在 lightrag/__init__.py:5-11__all__ 里导出:LightRAGQueryParamRoleLLMConfigRoleSpecROLESQueryParam 的字段定义在 lightrag/base.py:82-157

一句话直觉/类比: 把它想成「图书馆 + 关系网」两套索引并存。纯向量 RAG 只有「按内容相似度找书页」;LightRAG 额外有一张「谁认识谁、谁属于谁」的关系网,问到需要顺藤摸瓜的问题时,它能沿着关系网爬。


2. 顶层全景(它大概怎么转)

LightRAG 有两条主线:入库(indexing)查询(query)。两条线共用同一组存储。

2.1 整体数据流

入库主线 (ainsert) 查询主线 (aquery)
┌────────────────────────────┐ ┌──────────────────────────────┐
│ 文档原文 │ │ 用户问题 │
│ │ 切块 (chunker) │ │ │ LLM 抽关键词 │
│ ▼ │ │ ▼ │
│ 文本块 chunks │ │ 高层词 hl_keywords │
│ │ LLM 抽实体/关系 │ │ 低层词 ll_keywords │
│ ▼ (extract_entities) │ │ │ │
│ 实体 + 关系 (per-chunk) │ │ ├─ ll → 查实体VDB → 图的点 │
│ │ 跨块合并去重+LLM摘要 │ │ ├─ hl → 查关系VDB → 图的边 │
│ ▼ (merge_nodes_and_edges)│ │ └─ query → 查原文块VDB(mix)│
│ 写入 4 套存储 ↓ │ │ ▼ │
└────────────┬────────────────┘ │ 融合+截断+找支撑块+组prompt │
▼ │ ▼ (_build_query_context) │
┌──────────────────┐ ◄───── 查询读 ──┤ LLM 生成带引用的答案 │
│ 知识图谱 (点+边) │ └──────────────────────────────┘
│ 实体向量库 │
│ 关系向量库 │
│ 原文块向量库 + KV │
└──────────────────┘

怎么读这张图: 左边入库把文档「灌」进中间的四套存储;右边查询从这四套存储里「捞」内容。两条线唯一的耦合点就是中间的存储。

2.2 部件一句话职责

部件干什么在哪个文件
LightRAG(门面类)对外 API:ainsert/aquery 等;持有所有存储句柄lightrag/lightrag.py:263(class LightRAG)
入库流水线切块→抽取→合并→落库的多阶段 workerlightrag/pipeline.py(_PipelineMixin)
分块器4 种切块策略:Fix / Recursive / Vector / Paragraphlightrag/chunker/(chunking_by_*)
实体/关系抽取用 LLM 把 chunk 抽成实体行 + 关系行lightrag/operate.py:3320(extract_entities)
合并去重同名实体跨块合并、描述太多时 LLM 摘要lightrag/operate.py:2914(merge_nodes_and_edges)
双层检索把问题拆词、分走图的点和边lightrag/operate.py:3786(kg_query)、:4315(_perform_kg_search)
上下文组装融合实体/关系/块、token 预算、找支撑块、组 promptlightrag/operate.py:5024(_build_query_context)
提示词所有 LLM prompt 模板lightrag/prompt.py(PROMPTS)
存储抽象4 类存储的抽象基类lightrag/base.py(BaseKVStorage/BaseVectorStorage/BaseGraphStorage/DocStatusStorage)
存储工厂名字 → 具体后端类lightrag/kg/factory.py:17(get_storage_class)

2.3 四套存储 + 默认后端

LightRAG 把数据切成四种角色的存储,每种角色可以选不同后端实现。门面类的默认值在 lightrag/lightrag.py:275-284:

存储角色存什么抽象基类默认后端
KV 存储原文、文本块、LLM 缓存BaseKVStorageJsonKVStorage(本地 JSON 文件)
向量存储实体/关系/原文块的嵌入向量BaseVectorStorageNanoVectorDBStorage
图存储知识图谱的点和边BaseGraphStorageNetworkXStorage(NetworkX 内存图)
文档状态存储每篇文档的处理状态机DocStatusStorageJsonDocStatusStorage

这四个角色在 __post_init__ 里被实例化成具体句柄:text_chunksfull_docsllm_response_cachechunk_entity_relation_graphentities_vdbrelationships_vdbchunks_vdbdoc_status(lightrag/lightrag.py:1116-1185)。换后端只是换 kv_storage / vector_storage / graph_storage / doc_status_storage 这四个字符串,工厂会 lazy-import 对应实现(lightrag/kg/factory.py:17)。

2.4 六种查询模式(主线分叉)

QueryParam.mode 决定走哪条检索路径(lightrag/base.py:86-93):

模式检索什么直觉
local只用低层词查实体(图的点)「围绕具体实体的局部信息」
global只用高层词查关系(图的边)「跨实体的全局主题」
hybridlocal + global 都做并融合「点和边都要」
mixhybrid + 额外的原文块向量检索(默认)「图谱 + 朴素向量,全都要」
naive只做原文块向量检索,不碰图谱「退化成普通向量 RAG」
bypass不检索,直接问 LLM「纯聊天,不查库」

默认 mode="mix",即知识图谱与向量检索一起上(lightrag/base.py:86)。


3. 阅读地图(建议顺序)

按「先入库、再查询、再细节」的顺序读最顺:

  1. 01-indexing.md — 入库流水线。 文档怎么变成知识图谱 + 向量库:分块、用 LLM 抽实体/关系、跨块合并去重、描述太多时的 LLM 摘要、写入四套存储。读完你会理解图谱是「攒」出来的。
  2. 02-dual-level-retrieval.md — 双层检索(本项目的灵魂)。 查询时怎么把问题拆成高层/低层关键词,分别去图的边和点上检索,以及 local/global/hybrid/mix 的具体分叉。
  3. 03-context-assembly.md — 上下文组装。 检索到的实体/关系/块如何融合、token 预算怎么切、怎么从实体回溯到支撑它的原文块、怎么组成最终 prompt 并生成带引用的回答。
  4. 04-internals.md — 深入与边界。 巧妙之处(增量去重、缓存键、map-reduce 摘要)、边界与局限、与兄弟项目(MiniRAG / RAG-Anything / GraphRAG)的对比、完整代码地图。

如果你只想快速判断「LightRAG 适不适合我的场景」,读完本页第 1、2.4 节就够了。