LightRAG 源码级讲解
本地安装 light RAG + ollama 本地启动 看https://blog.csdn.net/weixin_43664254/article/details/148788828?spm=1011.2415.3001.5331
class LightRAG 类讲解

目录与缓存管理
- working_dir: 定义了工作目录路径,用于存储缓存和临时文件,默认值为当前时间戳命名的目录,确保实例化时不会发生冲突1
存储后端
- kv_storage,vector_storage, graph_storage, doc_status_storage: 分别定义了键值存储、向量存储、知识图谱存储以及文档状态存储的后端类型 。
日志管理 (已弃用)
- log_level, log_file_path: 虽然日志级别和文件路径被标记为已弃用,但它们原本用于设置日志级别和指定日志文件的存储位置 。
实体提取
- entity_extract_max_gleaning: 设置了实体提取的最大尝试次数,这对于处理模糊内容特别有用 。
- summary_to_max_tokens, force_llm_summary_on_merge: 控制摘要的最大 token 数以及是否强制使用 LLM 生成摘要 1。
文本分块
- chunk_token_size, chunk_overlap_token_size: 确定了文本分块的最大 token 数以及相邻文本块之间的重叠 token 数,保证上下文的连续性 1。
- tokenizer, tiktoken_model_name: 提供了分词器的配置选项,包括是否使用特定模型名称进行分词 。
- chunking_func: 自定义的文本分块函数,允许用户根据需要调整文本如何被分割成更小的部分 。
async def ainsert()方法讲解
apipeline_enqueue_document()方法
apipeline_enqueue_documents 是 LightRAG 类中的一个异步方法,用于将文档插入到系统中,并进行一系列预处理步骤,包括去重、生成唯一 ID、记录文档状态等。该方法的设计目标是确保传入的文档能够被正确地识别、存储和排队,以便后续进行嵌入、实体提取、图谱构建等操作。
方法功能概述
这个方法的核心流程如下:
- 输入标准化:统一处理输入字符串或列表。
- ID 验证与生成:如果用户提供了文档 ID,则验证其唯一性和数量是否匹配;否则自动生成基于内容 MD5 的唯一 ID。
- 内容清洗与去重:去除文本前后空白字符,并根据内容去重。
- 文档状态初始化:为每个新文档创建初始状态信息(如状态为 PENDING、摘要、长度、时间戳等)。
- 过滤已处理文档:检查哪些文档还未处理过,避免重复处理。
- 更新文档状态:将新的未处理文档的状态写入状态存储中,准备后续处理。
相关函数和类说明
clean_text():清洗文本内容。compute_mdhash_id():根据内容生成 MD5 哈希 ID。get_content_summary():生成文档内容摘要(可能使用 LLM)。DocStatus: 枚举类型,表示文档状态(如 PENDING、PROCESSING、COMPLETED)。self.doc_status文档状态存储对象,支持和方法。
apipeline_process_enqueue_documents()方法
apipeline_process_enqueue_documents 的异步函数,它是 LightRAG 类的一部分。该函数的主要目的是处理待处理的文档,通过将它们分割成块,并对每个块进行实体和关系提取,最后更新文档的状态。下面是对这个函数的详细解析:
获取状态和锁
首先,函数获取管道状态共享数据和锁,以确保在多进程环境中只有一个工作线程正在处理文档队列
pipeline_status = await get_namespace_data("pipeline_status")
pipeline_status_lock = get_pipeline_status_lock()
检查是否已有其他进程正在处理队列
使用async with pipeline_status_lock: 创建一个上下文管理器,确保只有当没有其他进程正在处理队列时才继续执行。如果已经有其他进程在处理,则设置请求挂起标志并返回
。
if not pipeline_status.get("busy", False):
# 处理逻辑...
else:
pipeline_status["request_pending"] = True
return
获取待处理的文档列表
这里,函数会获取所有处于处理中、失败或待处理状态的文档,并将它们合并到一个字典中,准备进一步处理。
processing_docs, failed_docs, pending_docs = await asyncio.gather(
self.doc_status.get_docs_by_status(DocStatus.PROCESSING),
self.doc_status.get_docs_by_status(DocStatus.FAILED),
self.doc_status.get_docs_by_status(DocStatus.PENDING),
)
to_process_docs: dict[str, DocProcessingStatus] = {}
to_process_docs.update(processing_docs)
to_process_docs.update(failed_docs)
to_process_docs.update(pending_docs)
处理文档直到没有更多文档或请求
接下来是一个循环,它会持续处理文档,直到没有更多的文档需要处理或者有新的请求到来。对于每个文档,它会生成块,然后并行地执行几个任务来处理这些块。
while True:
if not to_process_docs:
break
log_message = f"Processing {len(to_process_docs)} document(s)"
logger.info(log_message)
# 更新状态信息
pipeline_status["docs"] = len(to_process_docs)
pipeline_status["batchs"] = len(to_process_docs)
pipeline_status["cur_batch"] = 0
pipeline_status["latest_message"] = log_message
pipeline_status["history_messages"].append(log_message)
# 其他处理逻辑...
并发处理文档
为了提高效率,文档中的块会被并发处理。这里使用了asyncio.Semaphore 来限制同时处理的文件数量,防止资源过载
semaphore = asyncio.Semaphore(self.max_parallel_insert)
async def process_document(...):
async with semaphore:
# 处理单个文档的逻辑
...
综上所述,apipeline_process_enqueue_documents 函数实现了高效的文档处理流程,利用了 Python 的异步编程特性来提升性能。通过这种方式,它可以高效地管理和处理大量的文档数据,同时保持系统响应性和稳定性。此外,通过对文档进行分块处理,以及并行化实体和关系提取等操作,该函数能够有效地应对高负载的数据处理需求。
Insert 文档分析逻辑
测试一下 embedding. 是否正确

将拆分后的段落进行向量分析

data = await ollama_client.embed(model=embed_model, input=texts)
return np.array(data["embeddings"])
让大模型帮忙分析文档中关系
---目标---
给定一份可能与该活动相关的文本文件以及一个实体类型的列表,从文本中识别出所有这些类型的实体以及所识别实体之间的所有关系。
使用{语言}作为输出语言。
---步骤---1. 识别所有实体。对于每个已识别的实体,提取以下信息:
- 实体名称:实体的名称,使用与输入文本相同的语言。如果是英文,请将名称首字母大写。
- 实体类型:以下类型之一:[{entity_types}]
- 实体描述:对实体属性和活动的全面描述
将每个实体格式化为 ("实体"{元组分隔符}<实体名称>{元组分隔符}<实体类型>{元组分隔符}<实体描述
2. 从第一步中识别出的实体中,找出所有彼此之间存在*明确关联*的(源实体,目标实体)对。
对于每一对相关实体,提取以下信息:
- 源实体:在第一步中识别出的源实体名称
- 目标实体:在第一步中识别出的目标实体名称
- 关系描述:解释您认为源实体和目标实体之间存在关联的原因
- 关系强度:一个数字分数,表示源实体和目标实体之间关系的强度
- 关系关键词:一个或多个概括关系总体性质的高级关键词,侧重于概念或主题而非具体细节
将每个关系格式化为 ("关系"{元组分隔符}<源实体>{元组分隔符}<目标实体>{元组分隔符}<关系描述>{元组分隔符}<关系关键词>{元组分隔符}<关系强度>)
3. 识别出能够概括整个文本主要概念、主题或话题的高层次关键词。这些关键词应当能够捕捉到文档中呈现的总体思想。
将内容层面的关键词格式化为("内容关键词"{元组分隔符}<高层次关键词>)
4. 以 {语言} 形式返回输出,作为在步骤 1 和 2 中识别出的所有实体和关系的单个列表。使用 **{记录分隔符}** 作为列表分隔符。
5. 完成时,输出 {completion_delimiter}
得到分析结果, 再次询问模型
在上一次的提取过程中,有许多实体和关系被遗漏了。
--- 请记住这些步骤 ---
1. 识别所有实体。对于每个识别出的实体,提取以下信息:
- entity_name:实体的名称,使用与输入文本相同的语言。如果是英语,则将名称大写。
- entity_type:以下类型之一:[组织、个人、地理区域、事件、类别]
- entity_description:对实体属性和活动的全面描述
将每个实体格式化为(“实体”<|>“实体名称”<|>“实体类型”<|>“实体描述”)
2. 从步骤 1 中确定的实体中,找出所有彼此“明显相关”的(source_entity, target_entity)对。
对于每对相关的实体,提取以下信息:
- source_entity:在步骤 1 中确定的源实体的名称
- target_entity:在步骤 1 中确定的目标实体的名称
- relationship_description:解释您认为源实体和目标实体为何相互关联的说明
- relationship_strength:表示源实体和目标实体之间关系强度的数字评分
- relationship_keywords:一个或多个概括关系总体性质的高级关键词,侧重于概念或主题而非具体细节
将每个关系格式化为(“relationship”<|><source_entity><|><target_entity><|><relationship_description><|><relationship_keywords><|><relationship_strength>)
3. 找出能够概括整篇文本主要概念、主题或议题的高级关键词。这些关键词应涵盖文档中所呈现的总体思想。
将内容层面的关键词格式化为(“内容关键词”<|><高级关键词)
4. 将输出以中文形式呈现为步骤 1 和 2 中识别出的所有实体和关系的单一列表。使用“**##**”作为列表分隔符。
5. 完成之后,输出“<|COMPLETE|>”
--- 输出 ---
请使用相同的格式将它们添加在下面:

得到结果

拿到结果后再次进行向量计算

查询步骤分析
Query mode: naive
- 现在缓存中取是否有过同样的响应


- 先对问题进行一次向量计算

- 根据向量值找到符合查询关键的的文档

- 调用大模型将文章总结

角色
您是一位乐于助人的助手,正在回应用户关于以下以 JSON 格式提供的文档片段的查询。
---目标---
根据文档片段生成简洁的回答,并遵循回答规则,同时考虑对话历史和当前查询。总结所提供的文档片段中的所有信息,并结合与文档片段相关的常识。不要包含文档片段未提供的信息。
在处理带有时间戳的内容时:1. 每条内容都有一个“created_at”时间戳,表明我们获取此知识的时间。2. 遇到相互矛盾的信息时,要同时考虑内容和时间戳。3. 不要自动倾向于最新内容——要根据上下文做出判断4. 对于特定时间的查询,在考虑创建时间戳之前,优先考虑内容中的时间信息。
---对话历史---
第 1 回 惊天地美猴王出世
这是一个神话故事,传说在很久很久以前,天下分为东胜神洲、西牛贺洲、南赡部洲、北俱芦洲。在东胜神洲傲来国,有一座花果山,山上有一块仙石,一天仙石崩裂,从石头中滚出一个卵,这个卵一见风就变成一个石猴,猴眼射出一道道金光,向四方朝拜。那只猴子能走能跑,渴了就喝些山涧里的泉水,饿了就吃些山上的果子。
---回复规则---
由于您没有提供需要翻译的文本,我无法给出相应的翻译。如果您有需要翻译的内容,请提供给我,我会很乐意帮助您。
回复:
- 处理响应数据, 添加缓存, 返回流式响应数据

- 结果

Query mode: “local”, “global”, “hybrid”, “mix”
- 在缓存中查询是否有历史记录
- 获取一个低级和一个高级的关键词

调用逻辑模型, 询问查询的关键词并生成
---角色---
您是一名协助人员,负责从用户的查询内容以及对话历史中识别出关键词,包括高级关键词和低级关键词。
---目标---
根据查询内容和对话历史,列出高阶和低阶关键词。高阶关键词侧重于总体概念或主题,而低阶关键词则侧重于具体的实体、细节或具体术语。
---说明---
- 在提取关键词时,需同时考虑当前的查询内容以及相关的对话历史记录。
- 将关键词以 JSON 格式输出,该格式将由 JSON 解析器进行解析,输出中不得添加任何额外内容。
- JSON 应包含两个键:
- "high_level_keywords" 用于概括性的概念或主题
- "low_level_keywords" 用于具体的实体或细节
######################
--- 示例 ---######################
示例 1:
问题:“国际贸易如何影响全球经济的稳定性?”################
输出:
{
“高级关键词”:["国际贸易", "全球经济稳定", "经济影响"]
“低级关键词”:["贸易协定", "关税", "货币兑换", "进口", "出口"]}
#############################
示例 2:
问题:“森林砍伐会对生物多样性造成哪些环境影响?”################
输出:
{
“高级关键词”:["环境影响", "森林砍伐", "生物多样性丧失"]
“低级关键词”:["物种灭绝", "栖息地破坏", "碳排放", "雨林", "生态系统"]}
#############################
示例 3:
问题:“教育在减少贫困方面发挥着怎样的作用?”################
输出:
{
“高级关键词”:["教育", "减贫", "社会经济发展"]
“低级关键词”:["学校入学率", "识字率", "职业培训", "收入不平等"]}
#############################
#############################
---真实数据---######################
对话历史:
当前问题:这是一个什么样的故事?######################
“输出”内容应为人类可读的文字,而非 Unicode 字符。请保持与“查询”相同的语言。输出:

- 根据关键词是否存在转换查询逻辑

- 对关键词进行向量计算,并在文本端中进行向量检索找出符合的文本
local 模式只使用 低级关键词
global 模式只使用 高级关键词
hybrid or mix 两个关键词都使用

在 mix 模式下还会再次获取一次 vector data

最终生成一个 包含实体关系, 人物关系, 和相关文章的 大json数据
# `` 这点事三个, markdown 语法限制, 不能叠加 我删掉了一个
-----Entities(KG)-----
``json
[{"id": 1, "entity": "仙石", "type": "category", "description": "仙石是故事中的一个关键物体,象征着生命的起源。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 2, "entity": "第1回惊天地美猴王出世", "type": "event", "description": "这是一个神话故事的开端,讲述了一个关于孙悟空出生的故事。", "rank": 1, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 3, "entity": "傲来国", "type": "organization", "description": "傲来国是一个虚构的小国家,在花果山中存在。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 4, "entity": "东胜神洲", "type": "geo", "description": "东胜神洲是故事中划分的四大洲之一,位于故事发生的地理背景中。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}]
``
-----Relationships(KG)-----
``json
[{"id": 1, "entity1": "仙石崩裂", "entity2": "第1回惊天地美猴王出世", "description": "故事开始时,仙石的崩裂标志着新生命的诞生.", "keywords": "事件触发,生命起源", "weight": 7.0, "rank": 2, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}]
``
-----Document Chunks(DC)-----
``json
[{"id": 1, "content": "第1回 惊天地美猴王出世\n 这是一个神话故事,传说在很久很久以前,天下分为东胜神洲、西牛贺洲、南赡部洲、北俱芦洲。在东胜神洲傲来国,有一座花果山,山上有一块仙石,一天仙石崩裂,从石头中滚出一个卵,这个卵一见风就变成一个石猴,猴眼射出一道道金光,向四方朝拜。\n 那猴能走、能跑,渴了就喝些山涧中的泉水,饿了就吃些山上的果子。", "file_path": "unknown_source"}]
``
- 将关系封装后调用语言模型进行分析, 并返回结果
---角色---
您是一位能够响应用户关于以下以 JSON 格式提供的知识图谱和文档块相关问题的助手。
---目标---
根据知识库生成简洁的回复,并遵循回复规则,同时考虑对话历史和当前查询内容。综合所提供的知识库中的所有信息,并结合与知识库相关的通用知识。不要包含知识库中未提供的信息。
在处理与时间戳相关的事务时:1. 每段关系都有一个“创建时间戳”,它表明我们何时获得了这些信息。2. 当遇到相互矛盾的关系时,要同时考虑其语义内容和时间戳。3. 不要盲目地优先选择最近建立的关系——要根据具体情况做出判断。4. 对于具有特定时间要求的查询,应先根据内容中的时间信息进行优先排序,然后再考虑创建时间。
---Conversation History---
---Knowledge Graph and Document Chunks---
-----Entities(KG)-----
``json
[{"id": 1, "entity": "仙石", "type": "category", "description": "仙石是故事中的一个关键物体,象征着生命的起源。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 2, "entity": "第1回惊天地美猴王出世", "type": "event", "description": "这是一个神话故事的开端,讲述了一个关于孙悟空出生的故事。", "rank": 1, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 3, "entity": "傲来国", "type": "organization", "description": "傲来国是一个虚构的小国家,在花果山中存在。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}, {"id": 4, "entity": "东胜神洲", "type": "geo", "description": "东胜神洲是故事中划分的四大洲之一,位于故事发生的地理背景中。", "rank": 0, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}]
``
-----Relationships(KG)-----
``json
[{"id": 1, "entity1": "仙石崩裂", "entity2": "第1回惊天地美猴王出世", "description": "故事开始时,仙石的崩裂标志着新生命的诞生.", "keywords": "事件触发,生命起源", "weight": 7.0, "rank": 2, "created_at": "2025-06-17 16:10:10", "file_path": "unknown_source"}]
``
-----Document Chunks(DC)-----
``json
[{"id": 1, "content": "第1回 惊天地美猴王出世\n 这是一个神话故事,传说在很久很久以前,天下分为东胜神洲、西牛贺洲、南赡部洲、北俱芦洲。在东胜神洲傲来国,有一座花果山,山上有一块仙石,一天仙石崩裂,从石头中滚出一个卵,这个卵一见风就变成一个石猴,猴眼射出一道道金光,向四方朝拜。\n 那猴能走、能跑,渴了就喝些山涧中的泉水,饿了就吃些山上的果子。", "file_path": "unknown_source"}]
``
---Response Rules---
- 目标格式和长度:多段落
- 使用 Markdown 格式,并添加适当的章节标题
- 请以与用户问题相同的语言进行回复。
- 确保回复与对话历史保持连贯性。
- 在“参考文献”部分列出最多 5 个最重要的参考来源。清楚地表明每个来源是来自知识图谱(KG)还是文档块(DC),如果有文件路径,请以以下格式包含:[KG/DC] 文件路径
- 如果您不知道答案,请直接说。
- 不要编造任何内容。不要包含知识库未提供的信息。
- 无需添加额外的用户提示。
Response:


更多推荐

所有评论(0)