ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

86.图RAG-LightRAG框架的使用(中文生成、简单原理)

86.图RAG-LightRAG框架的使用(中文生成、简单原理) 内容参考于图灵AI大模型全栈注意LightRAG和llamaindex是两个不相关的东西LightRAG是一个独立的框架LightRAG它只是图RAG这方面比较强如果不用图RAG还是使用llamaindex或者在图RAG中加一些东西也是用llamaindex好一点LightRAG的说明去看37和38节安装库pip install lightrag-hku它可以使用的数据库上图是查找的方式首先按着CTRL鼠标左键单击下图红框然后鼠标左键单击下图红框下图红框的内容鼠标移动过去就显示了然后鼠标右键单击下图红框然后鼠标左键单击下图蓝框然后搜索下图蓝框里的内容FaissVectorDBStorage找到下图红框并鼠标左键双击下图红框然后再次单击下图红框就可以找到了它默认支持的如下图红框图数据库下图蓝框向量数据库下图的内容也是通过Find in Files搜索找到的代码中使用的Neo4j它的连接信息是写到环境变量中的如下图红框连接地址、用户名、密码的环境变量key如下图环境变量配置Python代码中使用了load_dotenv()它会把.env里面的内容设置成环境变量NEO4J_URI、NEO4J_USERNAME、NEO4J_PASSWORDlightrag它也是通过提示词来优化的它的提示词按着CTRL鼠标左键单击下图红框这个prompt文件中都是提示词路径的提示词系统提示词知识图谱提取的好不好就取决于提示词提取三元组结构的提示词三元组就是xxx和xxx的关系LightRAG写的提示词就很好系统提示词中文翻译---角色--- 您是知识图专家负责从用户提示的---Input Text---部分提取实体和关系。 ---说明书--- 1.**实体提取** -仅在当前用户提示的fenced ---Input Text---部分中标识明确定义的有意义的实体。 -对于每个实体提取 -entity_name实体的名称。如果实体名称不区分大小写请将每个有效单词的第一个字母大写标题大小写。在整个提取过程中确保**命名**一致。 -entity_type使用下面的---实体类型---部分中提供的类型指南对实体进行分类。如果提供的实体类型均不适用请将其分类为“其他”。 -entity_description仅*基于输入文本中的信息提供实体属性和活动的简明而全面的描述。 2.**关系提取** -确定先前提取的实体之间的直接、明确和有意义的关系。 -如果单个语句描述了涉及两个以上实体的关系请将其分解为多个二进制关系。 -对于每个二进制关系提取 -source_entity源实体的名称。确保**命名**与实体提取一致。如果名称不区分大小写请将每个有效单词的第一个字母标题大小写大写。 -target_entity目标实体的名称。确保**命名**与实体提取一致。如果名称不区分大小写请将每个有效单词的第一个字母标题大小写大写。 -relationship_keywords一个或多个概述关系的高级关键字。此字段中的多个关键字必须用逗号分隔。**请勿使用{tuple_delimitor}分隔此字段中的多个关键字** -relationship_description源实体和目标实体之间关系的性质的简明解释。 3.**记录类型** -“entity”仅用于实体行这些行始终包含总共4个元组部分。 -“relationship”仅用于关系行这些行始终包含总共5个元组部分。 -具有两个实体名称加上关系关键字和关系描述的行必须以“relationship”开头决不能以“entity”开头。 -在最后一个实体行之后将每个关系行的前缀切换为“relationship”。 4.**输出格式** -实体行Entity{tuple_delimiter}entity_name{tuple_delimiter}entity_type{tuple_delimiter}entity_description -关系行Relation{tuple_delimiter}source_entity{tuple_delimiter}target_entity{tuple_delimiter}relationship_keywords{tuple_delimiter}relationship_description -错误entity{tuple_delelimitor}source_entity{tuple_Delelimiter}target_entity{tuple-delelimitter}relationship_keywords{tuble_delelipter}relation ship_description -正确relationship{tuple_delelimitor}source_entity{tuple_Delelimiter}target_entity{tuple-delelimitter}relationship.keywords{tuble_delelipter}relation ship_description 5.**分隔符用法** -{tuple_delimitor}是一个完整的原子标记**不能用内容**填充。它严格用作字段分隔符。 -错误entity{tuple_delimitor}entity_name|entity_type|entity_description -正确entity{tuple_delimitor}entity_name{tuple_Delimitor{entity_type{tuble_delimiter}entity描述 6.**输出顺序和重复数据消除** -首先输出所有提取的实体然后输出所有提取关系。 -在此响应中跨实体和关系最多输出{max_total_records}行总数。 -在此响应中最多输出{max_entity_records}个实体行。 -如果存在较少的高值项则输出较少的行。不要试图填充限制。 -仅输出关系行其源实体和目标实体都包含在此响应的选定实体行中。 -如果达到限制请立即停止添加新行并输出{completion_delimiter}。 -除非另有明确说明否则将所有关系视为**无向**。将源实体和目标实体交换为无向关系不会构成新的关系。 -避免输出重复的关系。 -在关系列表中首先将**最重要**的关系输出到输入文本的核心含义。 7.**上下文和语言** -如果用户提示包含---Section Context---节则它给出文档的节层次结构例如h1→ h2 → h3。仅将其**用作背景**以在正确的上下文中消除引用和基础实体和关系描述的歧义。**不要**从节标题文本本身中提取实体或关系不要提及标题除非它们也出现在输入文本中。 -确保所有LightRAG默认生成的内容是英文的需要在环境变量中添加下图红框的内容SUMMARY_LANGUAGEzh如下图红框LightRAG生成的知识图谱然后点击下图红框展开默认都没有展开下图红框的按钮点击一下节点就有了如下图红框都展开后内容就全了如下图红框的内容字段的说明entity_id实体的标准名称也就是抽取到的实体本名这里是「孙悟空」是这个节点的核心业务标识。entity_type实体的分类标签LightRAG 会让大模型给每个识别出的实体打上类别比如person人物、location地点、event事件、object物品等。你图中周围的「花果山」「水帘洞」就属于地点类实体。description实体的总结描述是大模型基于所有提到该实体的原文片段自动生成的实体简介既用来快速表达节点含义也会参与后续的检索匹配。source_id这是最核心的溯源字段里面存储的是所有提及过该实体的文档切片chunk的 ID 列表。 简单来说「孙悟空」这个节点的所有信息都是从这些原文片段里抽取汇总来的当检索命中这个节点时LightRAG 会顺着这些 ID 找到对应的原始文本块作为回答的上下文证据实现 “图谱检索 原文佐证”。file_path原始文档的路径标识。这里显示unknown_source说明你导入数据时没有绑定具体的源文件比如是直接输入文本、没有指定文件名所以标记为未知来源。elementId和id这两个是 Neo4j 数据库自带的内部唯一编号不是 LightRAG 生成的是数据库存储节点时自动分配的内部主键。created_at节点的入库时间戳是 LightRAG 把节点写入 Neo4j 时自动记录的创建时间。然后它还有本地的缓存文件为了增量更新下图红框都是一些id这个id就表示了 灵台方寸山都有哪些节点这里的节点指的是文档分块通过下图红框的id就可以找到注意这里的id是文档分块的id它通过这种方式就可以进行增量更新通过文档分块增量更新前提是内容是在后面添加不能修改前面和后面的内容从文档中抽取出来的所有实体关系的名字下图红框文件作用LightRAG 红框文件完整说明整体分为两大组kv_store_*.json Key-Value 持久存储原始文本、元数据、缓存faiss_index_* FAISS 向量库向量索引 映射元文件一、kv_store 系列JsonKVStorage 默认文件kv_store_doc_status.json文档状态库。保存每个doc-xxx文档 ID处理状态pending /processing/completed /failed里面就是你刚才看到那种doc-xxxx→ entity_names 实体列表、count、时间作用增量插入、判断文档是否已经入库、文档删除溯源入口kv_store_text_chunks.jsonChunk 文本库。key chunk-md5xxxvalue 分片完整文本、元信息归属 doc_id核心溯源文件检索拿到 chunk_id 后从这里取出原文实体source_id最终靠它还原段落内容kv_store_entity_chunks.json实体 ↔ chunk 反向映射key实体名称value所有包含该实体的 chunk_id 列表快速查询哪些文本片段提到了这个实体kv_store_relation_chunks.json关系 ↔ chunk 反向映射key(实体A→实体B)关系标识value出现这条关系的 chunk_id 列表对应关系上的source_idkv_store_full_entities.json全量实体库每条实体完整信息名称、描述、source_idchunk 集合GraphRAG 查询实体详情时读取kv_store_full_relations.json全量关系库每条三元组src 实体tgt 实体关系描述 source_id图谱查询、关系检索数据源kv_store_llm_response_cache.jsonLLM 调用缓存相同 prompt 参数命中时直接返回缓存结果避免重复调用大模型开发调试可以删除线上能显著节约 token 开销⚠️ KV 文件是业务原始数据如果删掉向量库失去映射无法溯源原文二、faiss_index 系列FAISS 向量存储你代码里配置vector_storageFaissVectorStorage成对出现.index二进制向量索引文件 .meta.jsonID 映射表faiss_index_chunks.index / faiss_index_chunks.meta.json文本分片 (chunk) 向量库index所有文本分片 embedding 向量用于 naive 模式普通 RAG 检索meta.jsonfaiss 内部数字 id ↔chunk_id映射关系faiss_index_entities.index / faiss_index_entities.meta.json实体向量库index所有实体名称 / 描述的 embeddingmeta.jsonfaiss 数字 id ↔ 实体名称映射GraphRAG 模式用来语义匹配实体faiss_index_relationships.index / faiss_index_relationships.meta.json关系向量库index所有三元组关系描述 embeddingmeta.jsonfaiss 数字 id ↔ 关系标识映射用于语义检索相关知识关系效果图向量检索底层精确高层全局混合检索它会把 问题、向量检索到的节点、通过知识图谱图关系节点之间的关系 拼接成提示词代码代码运行之前先清空Neo4j免费版只有一个数据库删除命令MATCH (n) detach delete nimport asyncio import os from lightrag import LightRAG, QueryParam from lightrag.llm.openai import openai_complete_if_cache, openai_embed from dotenv import load_dotenv from lightrag.utils import EmbeddingFunc from lightrag.kg.shared_storage import initialize_pipeline_status from sentence_transformers import SentenceTransformer from lightrag import prompt load_dotenv() # 本地嵌入模型目录 model_name rE:\AiModel\Local_model\BAAI\bge-m3 # 工作目录 WORKING_DIR light_test # 创建向量模型 model SentenceTransformer(model_name) # 这个方法中的入参和内容都是固定写法 async def llm_func(prompt, system_promptNone, history_messages[], **kwargs): # 创建大模型连接这里使用的千问模型 return await openai_complete_if_cache( modelqwen-plus-latest, promptprompt, system_promptsystem_prompt, history_messageshistory_messages, base_urlos.getenv(DASHSCOPE_BASE_URL), api_keyos.getenv(DASHSCOPE_API_KEY), **kwargs ) async def local_embedding_func(texts): embeddings model.encode( # 要生成向量的文本 texts, convert_to_numpyTrue, # 同时处理 batch_size 批次数据 batch_size2 ) return embeddings async def initialize_rag(): # 创建 LightRAG rag LightRAG( # 设置大语言模型 llm_model_funcllm_func, # 设置向量模型 embedding_funcEmbeddingFunc( embedding_dim1024, # 模型维度要去向量模型官网或其它位置找使用的向量模型是多少维度的 max_token_size8192, # 最大 token 长度根据模型调整 funclocal_embedding_func # 传入你的函数异步或同步 ), # 向量数据存储位置值的来源去看文章中搜索的步骤 vector_storageFaissVectorDBStorage, # window 添加之后会报错 RuntimeError: Event loop is closed 使用get_event_loop启动协程 # 设置图数据库 graph_storageNeo4JStorage, ) # IMPORTANT: Both initialization calls are required! await rag.initialize_storages() # Initialize storage backends await initialize_pipeline_status() # Initialize processing pipeline return rag async def main(): # 初始化需要的东西 rag await initialize_rag() # 清全部缓存 # await rag.aclear_cache() with open(./data_file/西游记.txt, r, encodingutf-8) as f: data f.read() # 拿到文档内容直接给 rag.ainsert 也就是给LightRAG进行处理 # 它自己就会分割 task loop.create_task(rag.ainsert(data)) await asyncio.gather(task) await rag.ainsert(data) da1 await rag.aquery(谁告诉孙悟空有金箍棒的, paramQueryParam(modenaive)) # 传统向量检索 print(向量检索结果, da1) print(---------------------------------------------------------------------------------------------------------) da2 await rag.aquery(谁告诉孙悟空有金箍棒的, paramQueryParam(modelocal)) # 底层精确 print(底层精确结果, da2) print(---------------------------------------------------------------------------------------------------------) da3 await rag.aquery(谁告诉孙悟空有金箍棒的, paramQueryParam(modeglobal)) # 高层全局 print(高层全局结果, da3) print(---------------------------------------------------------------------------------------------------------) da4 await rag.aquery(谁告诉孙悟空有金箍棒的, paramQueryParam(modehybrid)) # 推荐融合 print(混合检索结果, da4) # 增量操作 插入新的数据 重新插入后续的内容 # await rag.ainsert(data) if __name__ __main__: # asyncio.run(main()) loop asyncio.get_event_loop() loop.run_until_complete(main())
返回列表