当前位置: 首页 > news >正文

结合prompt源码分析NodeRAG的build过程

NodeRAG将文档抽象为7层节点,这里从prompt代码角度分析NodeRAG如何将文档转化为节点、关联关系。

1 整体处理流程

NodeRAG定义了如下所示状态及处理流程。

# define the state to pipeline mapping
self.state_pipeline_map = {
            State.DOCUMENT_PIPELINE: document_pipline,
            State.TEXT_PIPELINE: text_pipline,
            State.GRAPH_PIPELINE: Graph_pipeline,
            State.ATTRIBUTE_PIPELINE: Attribution_generation_pipeline,
            State.EMBEDDING_PIPELINE: Embedding_pipeline,
            State.SUMMARY_PIPELINE: SummaryGeneration,
            State.INSERT_TEXT: Insert_text,
            State.HNSW_PIPELINE: HNSW_pipeline
}
        

状态转化序列如下所示,依次是INIT、DOCUMENT、TEXT、GRAPH、ATTRIBUTE、EMBEDDING、SUMMARY、INSERT、HNSW和FINISHED,涵盖文档划分、图谱化、特征提取、向量化、内容摘要等。

# define the state sequence
self.state_sequence = [
            State.INIT,
            State.DOCUMENT_PIPELINE,
            State.TEXT_PIPELINE,
            State.GRAPH_PIPELINE,
            State.ATTRIBUTE_PIPELINE,
            State.EMBEDDING_PIPELINE,
            State.SUMMARY_PIPELINE,
            State.INSERT_TEXT,
            State.HNSW_PIPELINE,
            State.FINISHED
]

https://github.com/Terry-Xu-666/NodeRAG/blob/main/NodeRAG/build/Node.py

这里重点关注文档切分、语义单元提取(摘要、实体、关系)、关联关系构建过程。

2 文档初步切分

State.DOCUMENT_PIPELINE: document_pipline环节

NodeRAG文档切分代码,输入是文件读出的字符串,块大小chunk_size对应token数,实际切分end边界按token数计算。

from typing import List
from .token_utils import get_token_counterclass SemanticTextSplitter:def __init__(self, chunk_size: int = 1048, model_name: str = "gpt-4o-mini"):"""Initialize the text splitter with chunk size and model name parameters.Args:chunk_size (int): Maximum number of tokens per chunkmodel_name (str): Model name for token counting"""self.chunk_size = chunk_sizeself.token_counter = get_token_counter(model_name)def split(self, text: str) -> List[str]:"""Split text into chunks based on both token count and semantic boundaries."""chunks = []start = 0text_len = len(text)while start < text_len:# add 4 times of chunk_size string to the start positionend = start + self.chunk_size * 4  # assume each token is 4 charactersif end > text_len:end = text_len# get the current text fragmentcurrent_chunk = text[start:end]# if the token count of the current fragment exceeds the limit, need to find the split pointwhile self.token_counter(current_chunk) > self.chunk_size and start < end:# find semantic boundary in the current rangeboundaries = ['\n\n', '\n', '。', '.', '!', '!', '?', '?', ';', ';']semantic_end = endfor boundary in boundaries:boundary_pos = current_chunk.rfind(boundary)if boundary_pos != -1:semantic_end = start + boundary_pos + len(boundary)break# if found semantic boundary, use it; otherwise, force truncation by characterif semantic_end < end:end = semantic_endelse:# 没找到合适的语义边界,往回数token直到满足大小限制end = start + int(len(current_chunk) // 1.2)current_chunk = text[start:end]# 添加处理好的文本块chunk = current_chunk.strip()if chunk:chunks.append(chunk)# 移动到下一个起始位置start = endreturn chunks

NodeRAG/NodeRAG/utils/text_spliter.py at main · Terry-Xu-666/NodeRAG · GitHub

3 语义单元提取

State.TEXT_PIPELINE: text_pipline环节

将文本切分为块后,进一步从块中提取语义单元,每个单元包含对特定事件或活动的详细描述哦

1)为每个语义单元提供总结,同时保留与原始上下文相关的所有关键细节。
2)直接从每个语义单元的原始文本中提取所有实体,而不是从改写的总结中提取。
3)从第2步中提取的实体中列出语义单元内的所有关系,其中关系类型可以是描述性句子。使用格式"ENTITY_A,RELATION_TYPE,ENTITY_B",请确保字符串中包含三个元素,分别表示两个实体和关系类型。

因为文本被切分为一个个独立语义单元,NodeRAG有可能解决了RAG语义切分问题,

示例中text为文本切分后的块。

text_decomposition_prompt_Chinese = """
目标:给定一个文本,将该文本被划分为多个语义单元,每个单元包含对特定事件或活动的详细描述。 
执行以下任务:
1.为每个语义单元提供总结,同时保留与原始上下文相关的所有关键细节。
2.直接从每个语义单元的原始文本中提取所有实体,而不是从改写的总结中提取。
3.从第2步中提取的实体中列出语义单元内的所有关系,其中关系类型可以是描述性句子。使用格式"ENTITY_A,RELATION_TYPE,ENTITY_B",请确保字符串中包含三个元素,分别表示两个实体和关系类型。

要求:

时间实体:根据文本中提到的日期或时间的具体部分来表示时间实体,不填补缺失部分。

每个语义单元应以一个字典表示,包含三个键:semantic_unit(每个语义单元的概括性总结)、entities(直接从每个语义单元的原始文本中提取的实体列表,实体名格式为大写)、relationships(描述性句子形式的提取关系字符串三元组列表)。所有这些字典应存储在一个列表中,以便管理和访问。

示例:

文本:2024年9月,艾米莉·罗伯茨博士前往巴黎参加国际可再生能源会议。在她的访问期间,她与几家欧洲公司探讨了合作并介绍了她在提高太阳能板效率方面的最新研究。与此同时,在世界的另一边,她的同事约翰·米勒博士在亚马逊雨林进行实地工作。他记录了几种新物种,并观察了森林砍伐对当地野生动物的影响。两位学者的工作在各自的领域内至关重要,对环境保护工作做出了重大贡献。
输出:
[
  {{
    "semantic_unit": "2024年9月,艾米莉·罗伯茨博士参加了在巴黎举行的国际可再生能源会议,她在会上介绍了她关于太阳能板效率提高的研究并探讨了与欧洲公司的合作。",
    "entities": ["艾米莉·罗伯茨博士", "2024-09", "巴黎", "国际可再生能源会议", "欧洲公司", "太阳能板效率"],
    "relationships": [
      "艾米莉·罗伯茨博士, 参加了, 国际可再生能源会议",
      "艾米莉·罗伯茨博士, 探讨了合作, 欧洲公司",
      "艾米莉·罗伯茨博士, 介绍了研究, 太阳能板效率"
    ]
  }},
  {{
    "semantic_unit": "约翰·米勒博士在亚马逊雨林进行实地工作,记录了几种新物种并观察了森林砍伐对当地野生动物的影响。",
    "entities": ["约翰·米勒博士", "亚马逊雨林", "新物种", "森林砍伐", "当地野生动物"],
    "relationships": [
      "约翰·米勒博士, 在, 亚马逊雨林进行实地工作",
      "约翰·米勒博士, 记录了, 新物种",
      "约翰·米勒博士, 观察了, 森林砍伐对当地野生动物的影响"
    ]
  }},
  {{
    "semantic_unit": "艾米莉·罗伯茨博士和约翰·米勒博士的工作在各自的领域内至关重要,对环境保护工作做出了重大贡献。",
    "entities": ["艾米莉·罗伯茨博士", "约翰·米勒博士", "环境保护"],
    "relationships": [
      "艾米莉·罗伯茨博士, 贡献于, 环境保护",
      "约翰·米勒博士, 贡献于, 环境保护"
    ]
  }}
]

##########
实际数据: 
########## 
文本:{text} 
"""

NodeRAG/NodeRAG/utils/prompt/text_decomposition.py at main · Terry-Xu-666/NodeRAG · GitHub

4 实体关系重建

State.GRAPH_PIPELINE: Graph_pipeline环节

之前抽取的关系relationship,格式有可能是错误的,需要重新按照'实体A,关系类型,实体B'重构。

prompt示例如下。

relationship_reconstraction_prompt_Chinese = """
你将获得一个包含实体之间关系的元组字符串。这些关系的格式是错误的,需要被重新构建。正确的格式应为:'实体A,关系类型,实体B',每个元组应包含三个元素:两个实体和一个关系类型。你的任务是将每个关系重新构建为以下格式:{{'source': '实体A', 'relation': '关系类型', 'target': '实体B'}}。请确保输出遵循此结构,准确映射提供的实体和关系。
错误的关系元组:{relationship}
"""

https://github.com/Terry-Xu-666/NodeRAG/blob/main/NodeRAG/utils/prompt/relationship_reconstraction.py

除此之外,Graph环节还包括基本图结构的重建,具体参考以下链接。

https://github.com/Terry-Xu-666/NodeRAG/blob/main/NodeRAG/build/pipeline/graph_pipeline.py

reference

---

NodeRAG

https://github.com/Terry-Xu-666/NodeRAG

linux环境conda安装NodeRAG示例

https://blog.csdn.net/liliang199/article/details/151101894


文章转载自:

http://rsduoIwv.dcpbk.cn
http://pLdmqiUj.dcpbk.cn
http://3Dgby0cb.dcpbk.cn
http://oY26TzyI.dcpbk.cn
http://wXy6wWlz.dcpbk.cn
http://XW6olVoD.dcpbk.cn
http://9IfOiu1R.dcpbk.cn
http://6ZLvOCab.dcpbk.cn
http://sFAPft4n.dcpbk.cn
http://mp7hrib6.dcpbk.cn
http://LYi8yf1M.dcpbk.cn
http://wSwpsUIJ.dcpbk.cn
http://suWtyAkH.dcpbk.cn
http://vJBtqRX1.dcpbk.cn
http://5Nzafkgv.dcpbk.cn
http://RqpEF1Wb.dcpbk.cn
http://wnOECVVL.dcpbk.cn
http://hheSv3TD.dcpbk.cn
http://feLpuxu6.dcpbk.cn
http://6K2IV0l3.dcpbk.cn
http://JKf5P2hu.dcpbk.cn
http://WHD6O7go.dcpbk.cn
http://a5qpyGrD.dcpbk.cn
http://5pQJRGRL.dcpbk.cn
http://37zfxjsQ.dcpbk.cn
http://0go4zfsT.dcpbk.cn
http://8n35f5CW.dcpbk.cn
http://GdGATP2Y.dcpbk.cn
http://cpIAzzD4.dcpbk.cn
http://5G1kngVs.dcpbk.cn
http://www.dtcms.com/a/366193.html

相关文章:

  • 【C++闯关笔记】STL:list 的学习和使用
  • 解密大语言模型推理:Prompt Processing 的内存管理与计算优化
  • Redis vs Memcached vs MongoDB:深入对比与选型指南
  • C# 修改基类List中某一元素的子类类型
  • 如何在 iPhone 或 iPad 上删除文件
  • MongoDB 高可用部署:Replica Set 搭建与故障转移测试
  • MacOS微信双开,亲测有效
  • MySQL事务的四大特性(ACID)
  • 数说故事 | 2025年运动相机数据报告,深挖主流品牌运营策略及行业趋势​
  • K8S容器POD内存快照导出分析处理方案
  • 【面试题】Prompt是如何生成的,优化目标是什么,任务是什么?
  • Elasticsearch 备份和恢复
  • 软考中级习题与解答——第二章_程序语言与语言处理程序(2)
  • RTC实时时钟RX8025SA国产替代FRTC8025S
  • git基础命令 git基础操作
  • 2025市面上比较实用的财会行业证书,最值得考的8个职业证书推荐
  • 开源与定制化直播电商系统源码对比:如何选择开发方案?
  • Spring 事务提交成功后执行额外逻辑
  • Attention-Based Map Encoding for Learning Generalized Legged Locomotion
  • MMD动画(二)动作制作
  • Hoppscotch:开源轻量API测试工具,秒启动高效解决临时接口测试需求
  • 【机器学习】HanLP+Weka+Java算法模型
  • 算法随笔(一)
  • Electron 执行python脚本
  • Dubbo(分布式RPC调用和分布式文件储存)
  • 如何简单理解状态机、流程图和时序图
  • 成为一个年薪30W+的FPGA工程师是一种什么体验?
  • 进程与线程详解, IPC通信与RPC通信对比,Linux前台与后台作业
  • 在国企干了 5 年 Java,居然不知道 RPC?这正常吗?
  • VU9P板卡设计方案:基于VU9P的32@ SFP28+4@ QSFP28路光纤交换板卡