本文由 无忆研习社 站长 莫潇羽 原创撰写,转载请注明出处。
首发于无忆研习社,专注于开源项目深度解析与实战教程。
写在前面
最近在GitHub上刷热榜的时候,发现了一个让我眼前一亮的项目——LightRAG。说实话,作为一个在RAG领域摸爬滚打了两三年的老玩家,看到这个项目的第一反应是:"又一个RAG框架?能有什么新意?"
但当我深入研究了它的论文和代码之后,我承认我被打脸了。
这玩意儿是真的香。
LightRAG来自香港大学数据科学实验室,论文已被EMNLP 2025收录。截至我写这篇文章的时候,它在GitHub上已经斩获了23000+的Star,而且增长势头非常猛。
为什么它能火?简单来说,传统RAG有两个老大难问题:
第一,扁平化检索的局限性。 传统RAG把文档切成一块一块,然后用向量相似度来找相关内容。这种方式处理简单问答没问题,但遇到需要跨文档推理、多实体关联的复杂问题就抓瞎了。
第二,知识更新的高成本。 每次有新文档进来,很多系统需要重新索引整个知识库。数据量一大,这个开销就非常恐怖。
LightRAG用知识图谱+双层检索的方式,把这两个问题都给解决了。而且它的设计非常轻量,不像微软的GraphRAG那样需要复杂的社区聚类,部署和使用都相当友好。
这篇文章,我会从原理讲到实战,尽可能把LightRAG的方方面面都给你讲透。不管你是刚入门的小白,还是已经有RAG开发经验的老手,相信都能从中有所收获。
莫潇羽@无忆研习社 提醒:本文较长,建议收藏后慢慢阅读。我会尽量用大白话来解释技术细节,让每个人都能看懂。
一、传统RAG的困境:为什么我们需要LightRAG?
在聊LightRAG之前,我们得先搞清楚:传统的RAG到底有什么问题?
1.1 什么是RAG?
RAG的全称是Retrieval-Augmented Generation,翻译过来就是"检索增强生成"。它的核心思想很简单:
- 你问大模型一个问题
- 系统先从知识库里检索相关内容
- 把检索到的内容作为上下文喂给大模型
- 大模型基于这些上下文生成答案
这个流程解决了大模型的一个致命问题——幻觉。大模型有时候会一本正经地胡说八道,但有了RAG,它就能基于真实的知识来回答,靠谱多了。
1.2 传统RAG的三大痛点
但传统RAG用久了,你会发现它有几个很难受的地方:
痛点一:无法处理复杂的关联推理
假设你有一个企业知识库,里面包含员工信息、项目文档、会议记录等。现在你问:"张三参与的项目中,哪个项目的负责人和他是同一个部门的?"
这个问题涉及到:
- 张三参与了哪些项目
- 每个项目的负责人是谁
- 张三和这些负责人的部门归属
传统RAG会怎么做?它会用"张三"、"项目"这些关键词去检索文档块,然后把检索到的内容丢给大模型。
问题是,这些信息可能分散在多个文档的不同段落里。检索系统没法理解"张三-参与-项目"、"项目-负责人-某人"、"某人-所属-部门"这些实体之间的关系链条。最终的结果往往是答非所问,或者干脆回答不了。
痛点二:上下文碎片化
传统RAG为了检索效率,会把文档切成固定大小的块(通常是几百个token)。但这种机械切分经常会把完整的语义单元给切断。
比如一段话讲的是"苹果公司2023年的财报表现",结果被切成了两块:第一块只有"苹果公司2023年",第二块只有"的财报表现显示营收同比增长..."。检索的时候,这两块可能一块被召回、一块没被召回,大模型拿到的上下文就是残缺的。
痛点三:知识更新代价大
企业场景下,知识库是不断更新的。新文档进来、旧文档修改,都是家常便饭。
传统RAG要应对这种更新,最暴力的做法是重新构建整个向量索引。数据量小还好说,数据量一大,每次更新都得跑几个小时甚至几天,这在生产环境里是不可接受的。
有些框架支持增量更新,但往往只是简单地追加新向量,没有办法处理知识之间的关联变化。比如"张三调到了新部门"这个信息进来,所有和张三相关的问答可能都需要更新,但系统没法自动感知这种依赖关系。
1.3 LightRAG的解题思路
LightRAG的核心创新在于:用知识图谱来弥补向量检索的关系建模缺陷,用双层检索来同时满足细粒度和粗粒度的查询需求,用增量更新机制来降低维护成本。
说人话就是:
- 它不只是把文档切块存起来,还会从中抽取实体和关系,构建一张"知识网络"
- 查询的时候,既能找具体的事实点,也能把握整体的主题脉络
- 新数据来了,只需要补充节点和边,不用推倒重来
这三点加在一起,就让LightRAG在处理复杂问答时表现出了明显的优势。根据论文实验,在多跳推理任务上,LightRAG的准确率比传统RAG提升了约30%。
二、LightRAG架构全解析:它到底是怎么工作的?
好,铺垫完了,现在进入正题。LightRAG的架构分为两大核心模块:索引构建和查询响应。我们一个一个来拆解。
2.1 索引构建流程
索引构建是LightRAG的"入库"过程,目标是把原始文档转化成可供高效检索的知识结构。整个流程可以分为四个步骤:
第一步:文档分块(Chunking)
和传统RAG一样,LightRAG也需要先把长文档切成小块。但它的分块策略更讲究一些:
- 默认使用token级别的滑动窗口,每块大约1024个token
- 相邻块之间有128个token的重叠,避免语义断裂
- 支持自定义分块函数,你可以根据文档类型调整策略
分块的代码逻辑大概是这样的:
def chunking_by_token_size(content: str, overlap_token_size=128, max_token_size=1024):
tokens = encode_string_by_tiktoken(content)
# 滑动窗口分块
chunks = []
for i in range(0, len(tokens), max_token_size - overlap_token_size):
chunk_tokens = tokens[i:i + max_token_size]
chunks.append(decode_tokens(chunk_tokens))
return chunks
第二步:实体和关系抽取(Entity & Relation Extraction)
这是LightRAG的核心环节,也是它和传统RAG最大的区别。
对于每一个文档块,LightRAG会调用大模型,从中提取:
- 实体(Entities):人名、地名、组织、概念等
- 关系(Relations):实体之间的联系,比如"创办"、"隶属于"、"参与"等
它的提示词模板是精心设计过的,大概长这样(我给翻译简化了一下):
目标:给定一段文本和可能的实体类型列表,识别出所有实体及其关系。
步骤:
1. 识别所有实体,提取以下信息:
- entity_name:实体名称(大写)
- entity_type:实体类型
- entity_description:对该实体的详细描述
2. 识别所有明显相关的实体对,提取以下信息:
- source_entity:源实体
- target_entity:目标实体
- relationship_description:为什么它们相关
- relationship_strength:关系强度(数值)
- relationship_keywords:关系的高层次关键词
输出格式:
("entity"{分隔符}<实体名>{分隔符}<类型>{分隔符}<描述>)
("relationship"{分隔符}<源实体>{分隔符}<目标实体>{分隔符}<描述>{分隔符}<关键词>{分隔符}<强度>)
举个例子,假设输入文本是:
"乔布斯于1976年在美国加州创办了苹果公司,后来苹果公司推出了革命性的iPhone产品。"
大模型会输出类似这样的结果:
("entity", "乔布斯", "人物", "苹果公司创始人")
("entity", "苹果公司", "组织", "美国科技公司")
("entity", "iPhone", "产品", "苹果公司推出的智能手机")
("entity", "美国加州", "地点", "苹果公司创立地")
("relationship", "乔布斯", "苹果公司", "乔布斯创办了苹果公司", "创办", 9)
("relationship", "苹果公司", "iPhone", "苹果公司推出了iPhone", "推出,研发", 8)
("relationship", "苹果公司", "美国加州", "苹果公司在美国加州创立", "创立地点", 7)
这一步对大模型的能力要求比较高,所以LightRAG官方建议使用GPT-4级别的模型来做抽取。用小模型的话,抽取质量会打折扣。
莫潇羽@无忆研习社提示: 如果你用的是本地部署的开源模型,推荐选择Qwen2.5-32B或以上规格,太小的模型在实体关系抽取任务上容易出错。
第三步:图谱构建与去重(Graph Construction & Deduplication)
有了实体和关系,下一步就是把它们组织成知识图谱。
但这里有个问题:不同的文档块可能会抽出相同的实体。比如文档A里提到"苹果公司",文档B里也提到"苹果公司",这两个其实是同一个实体,不能重复存储。
LightRAG会进行去重操作:
- 对于相同的实体名称,合并它们的描述信息
- 合并后的描述如果太长,再调用大模型进行精炼总结
- 关系的去重逻辑类似
去重之后,系统会构建一个networkx格式的图结构,存储到graph_chunk_entity_relation.graphml文件中。
图谱里的每个节点(实体)包含以下属性:
- entity_name:实体名称
- entity_type:实体类型
- description:实体描述
- source_id:来源文档块的ID
每条边(关系)包含:
- source:源实体
- target:目标实体
- weight:关系权重
- description:关系描述
- keywords:关系关键词
第四步:向量化存储(Vectorization)
光有图谱还不够,还需要把实体和关系的描述文本转成向量,方便后续的相似度检索。
LightRAG会分别对以下内容进行向量化:
- 实体的描述(存到
vdb_entities.json) - 关系的描述(存到
vdb_relationships.json) - 原始文档块(存到
vdb_chunks.json)
这样在查询阶段,既可以通过图结构进行精确的关系遍历,也可以通过向量相似度进行模糊匹配。两种方式互补,大大提高了检索的覆盖率和准确率。
2.2 查询响应流程
索引建好之后,就可以响应用户的查询了。LightRAG的查询流程也很有特色,核心是它的双层检索机制。
第一步:关键词提取
用户输入一个问题后,LightRAG首先会调用大模型,从问题中提取两类关键词:
- Low-level keywords(低层关键词):具体的实体名称、事实性词汇,比如"苹果公司"、"iPhone"、"2023年"
- High-level keywords(高层关键词):抽象的主题、概念词汇,比如"科技发展"、"创新"、"商业模式"
提取关键词的提示词模板是这样的:
给定一个查询,请提取两类关键词:
1. 低层关键词:具体的实体、名称、日期、数值等
2. 高层关键词:主题、概念、趋势、抽象概念等
查询:{用户问题}
输出格式:
{
"low_level_keywords": ["关键词1", "关键词2", ...],
"high_level_keywords": ["关键词1", "关键词2", ...]
}
第二步:双层检索
有了关键词,就可以开始检索了。LightRAG支持四种检索模式:
模式一:naive(朴素模式)
最简单的向量检索,直接用用户问题去匹配文档块向量,适合简单的事实性问答。
模式二:local(局部模式)
用低层关键词在实体向量库中检索,找到相关的实体,然后沿着图谱的边找到与这些实体直接关联的关系和其他实体。
这种模式适合需要精确事实的问题,比如"谁创办了苹果公司?"
模式三:global(全局模式)
用高层关键词在关系向量库中检索,找到相关的关系,然后把这些关系涉及的实体都拉出来。
这种模式适合需要宏观理解的问题,比如"人工智能如何影响现代教育?"
模式四:hybrid(混合模式)
同时执行local和global检索,把两边的结果合并。这是默认推荐的模式,也是效果最好的模式。
第三步:上下文构建与生成
检索完成后,LightRAG会把检索到的信息整理成结构化的上下文,大概是这样的格式:
-----实体信息-----
实体名称:苹果公司
类型:组织
描述:美国科技公司,由乔布斯等人于1976年创立...
实体名称:乔布斯
类型:人物
描述:苹果公司创始人...
-----关系信息-----
乔布斯 -> 苹果公司:创办关系,乔布斯于1976年创办了苹果公司
-----相关文档片段-----
[来源: doc_001] 1976年,史蒂夫·乔布斯与沃兹尼亚克在车库里...
最后,把这个上下文和用户问题一起发给大模型,生成最终答案。
2.3 增量更新机制
前面提到,LightRAG支持高效的增量更新。这是怎么实现的呢?
其实原理很简单:知识图谱天然支持增量操作。
当新文档进来时:
- 对新文档进行分块和实体关系抽取
- 把新的实体和关系与已有图谱进行合并
- 如果遇到重复实体,合并描述并重新向量化
- 如果是全新实体/关系,直接追加
整个过程不需要重建已有的图结构,只需要在图上"打补丁"就行。
对比一下微软的GraphRAG:它用了社区聚类的机制,每次有新数据进来,需要重新计算所有社区的划分和摘要。数据量大的时候,光是社区报告的生成就要消耗大量的token。
LightRAG甩掉了社区聚类这个包袱,增量更新的成本低了一个数量级。
三、LightRAG数据存储结构详解
理解了原理,我们再来看看LightRAG具体会生成哪些文件。这部分内容对于后续的调试和二次开发很重要。
当你用LightRAG处理完文档后,会在工作目录下看到这些文件:
working_dir/
├── graph_chunk_entity_relation.graphml # 知识图谱主文件
├── vdb_entities.json # 实体向量库
├── vdb_relationships.json # 关系向量库
├── vdb_chunks.json # 文档块向量库
├── kv_store_full_docs.json # 原始文档存储
├── kv_store_text_chunks.json # 文档块存储
└── kv_store_llm_response_cache.json # LLM响应缓存
我们逐个解释:
3.1 graph_chunk_entity_relation.graphml
这是知识图谱的核心文件,用GraphML格式存储。你可以用networkx加载它:
import networkx as nx
G = nx.read_graphml("graph_chunk_entity_relation.graphml")
# 查看节点数量
print(f"实体数量: {G.number_of_nodes()}")
# 查看边数量
print(f"关系数量: {G.number_of_edges()}")
# 遍历实体
for node in G.nodes(data=True):
print(f"实体: {node[0]}, 属性: {node[1]}")
# 遍历关系
for edge in G.edges(data=True):
print(f"关系: {edge[0]} -> {edge[1]}, 属性: {edge[2]}")
这个文件也可以用Gephi等图可视化工具打开,直观地看到知识图谱的结构。
3.2 vdb_entities.json / vdb_relationships.json
这两个是向量数据库文件,存储实体和关系的向量表示。结构大概是这样的:
{
"data": [
{
"id": "entity_001",
"content": "苹果公司:美国科技公司...",
"vector": [0.123, 0.456, ...]
}
],
"matrix": [...] // 向量矩阵,用于快速检索
}
3.3 kv_store_llm_response_cache.json
这是LLM响应的缓存文件。LightRAG会把实体抽取的结果缓存下来,相同的文档块不会重复调用LLM。
这个机制非常实用:
- 测试阶段可以反复调试,不用担心API费用
- 生产环境下如果处理中断,可以从缓存恢复
你可以通过环境变量ENABLE_LLM_CACHE_FOR_EXTRACT=true来开启这个功能(默认开启)。
四、LightRAG安装部署全攻略
理论讲得差不多了,接下来进入实操环节。我会覆盖几种常见的部署场景,从最简单的本地测试到生产级别的Docker部署。
4.1 环境准备
LightRAG支持Python 3.9及以上版本。推荐使用Python 3.10或3.11,兼容性最好。
首先安装LightRAG核心包:
# 方式一:使用pip安装
pip install lightrag-hku
# 方式二:如果需要API服务和Web UI
pip install "lightrag-hku[api]"
# 方式三:使用uv(官方推荐,速度更快)
uv pip install "lightrag-hku[api]"
如果你打算用本地模型,还需要安装Ollama相关的依赖:
pip install ollama
4.2 方式一:使用OpenAI API(最简单)
如果你有OpenAI的API Key,这是最快的上手方式。
创建一个Python文件quickstart.py:
import os
import asyncio
from lightrag import LightRAG, QueryParam
from lightrag.llm.openai import gpt_4o_mini_complete, openai_embed
from lightrag.kg.shared_storage import initialize_pipeline_status
from lightrag.utils import setup_logger
# 设置日志
setup_logger("lightrag", level="INFO")
# 设置API Key
os.environ["OPENAI_API_KEY"] = "sk-your-api-key-here"
# 创建工作目录
WORKING_DIR = "./my_rag_project"
os.makedirs(WORKING_DIR, exist_ok=True)
async def main():
# 初始化LightRAG
rag = LightRAG(
working_dir=WORKING_DIR,
embedding_func=openai_embed,
llm_model_func=gpt_4o_mini_complete,
)
# 重要:初始化存储和管道状态
await rag.initialize_storages()
await initialize_pipeline_status()
# 准备示例文档
documents = """
人工智能(Artificial Intelligence,简称AI)是计算机科学的一个重要分支,
致力于开发能够模拟人类智能的系统。机器学习是AI的核心技术之一,
它使计算机能够从数据中学习和改进,而无需进行明确的编程。
深度学习是机器学习的一个子领域,它使用多层神经网络来处理复杂问题。
神经网络的设计灵感来源于人脑的结构,通过大量的参数和层次来学习数据的表示。
近年来,大语言模型(LLM)成为AI领域的热点。GPT、Claude、Gemini等模型
展现了惊人的语言理解和生成能力,推动了AI在各行各业的应用。
"""
# 插入文档
await rag.ainsert(documents)
print("文档插入完成!")
# 测试查询
queries = [
"什么是深度学习?",
"机器学习和人工智能是什么关系?",
"目前有哪些主流的大语言模型?"
]
for query in queries:
print(f"\n问题:{query}")
result = await rag.aquery(query, param=QueryParam(mode="hybrid"))
print(f"回答:{result}")
if __name__ == "__main__":
asyncio.run(main())
运行:
python quickstart.py
首次运行时,LightRAG会对文档进行实体抽取和图谱构建,需要调用几次LLM API。处理完成后,后续的查询就很快了。
4.3 方式二:使用Ollama本地模型(省钱方案)
不想花API费用?用Ollama部署本地模型是个好选择。
第一步:安装并启动Ollama
# macOS/Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows
# 去 ollama.com 下载安装包
第二步:拉取模型
# 拉取LLM模型(推荐qwen2.5系列)
ollama pull qwen2.5:32b
# 拉取Embedding模型
ollama pull nomic-embed-text
# 如果显存有限,可以用小一点的模型
ollama pull qwen2.5:7b
ollama pull mxbai-embed-large
第三步:编写代码
创建ollama_demo.py:
import os
import asyncio
from lightrag import LightRAG, QueryParam
from lightrag.llm.ollama import ollama_model_complete, ollama_embedding
from lightrag.utils import EmbeddingFunc
WORKING_DIR = "./ollama_rag_project"
os.makedirs(WORKING_DIR, exist_ok=True)
async def main():
# 初始化LightRAG,使用Ollama模型
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=ollama_model_complete,
llm_model_name="qwen2.5:32b", # 使用你拉取的模型
llm_model_kwargs={"options": {"num_ctx": 32768}}, # 上下文长度
embedding_func=EmbeddingFunc(
embedding_dim=768, # 根据模型调整
max_token_size=8192,
func=lambda texts: ollama_embedding(
texts,
embed_model="nomic-embed-text"
)
),
)
await rag.initialize_storages()
# 读取文档(这里用一个示例文件)
with open("your_document.txt", "r", encoding="utf-8") as f:
content = f.read()
# 插入文档
await rag.ainsert(content)
# 查询
result = await rag.aquery(
"你的问题",
param=QueryParam(mode="hybrid")
)
print(result)
if __name__ == "__main__":
asyncio.run(main())
莫潇羽@无忆研习社温馨提示: 本地模型的选择很重要。根据我的测试:
- qwen2.5:32b 实体抽取效果最好,但需要至少24GB显存
- qwen2.5:14b 性价比之选,16GB显存可跑
- qwen2.5:7b 入门级,8GB显存可用,但抽取质量会下降
Embedding模型推荐nomic-embed-text,维度适中(768),效果不错。
4.4 方式三:使用LightRAG Server(生产级部署)
LightRAG自带了一个API Server和Web UI,非常适合团队使用或生产部署。
快速启动:
# 配置环境变量
cp env.example .env
# 编辑.env文件,填入你的API配置
# 启动服务
lightrag-server
服务启动后,访问http://localhost:9621就能看到Web UI界面。
使用Docker部署(推荐):
# 克隆项目
git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
# 配置环境
cp env.example .env
# 编辑.env文件
# 启动Docker
docker compose up -d
.env文件的关键配置项:
# LLM配置
LLM_BINDING=openai # 或 ollama
LLM_MODEL=gpt-4o-mini
OPENAI_API_KEY=sk-xxx
# Embedding配置
EMBEDDING_BINDING=openai
EMBEDDING_MODEL=text-embedding-3-small
# 如果用Ollama
# LLM_BINDING=ollama
# LLM_MODEL=qwen2.5:32b
# OLLAMA_HOST=http://localhost:11434
# 存储配置
WORKING_DIR=/data/lightrag
KV_STORAGE=JsonKVStorage
VECTOR_STORAGE=NanoVectorDB