小白也能讀懂的GraphRAG知識圖譜全流程解析,多圖預警! 原創
今天,我要和你分享的是如何用GraphRAG從一個普通的txt文件中創建知識圖譜,準備好了嗎?那就讓我們開始吧!
GraphRAG解決了什么問題
當你問:“這個數據集的主題是什么?”這類高級別、概括性的問題時,傳統的RAG可能就會束手無策。為什么呢?那是因為這本質上是一個聚焦于查詢的總結性任務(Query-Focused Summarization,QFS),而不是一個明確的檢索任務。
我知道你現在可能在想,“那我們該如何解決這個問題呢?”好消息是,有人已經找到了解決方案,而且還被詳細地描述在論文中:
In contrast with related work that exploits the structured retrieval and traversal affordances of graph indexes (subsection 4.2),we focus on a previously unexplored quality of graphs in this context: their inherent modularity (Newman,2006) and the ability of community detection algorithms to partition graphs into modular communities of closely-related nodes (e.g.,Louvain,Blondel et al.,2008; Leiden,Traag et al.,2019). LLM-generated summaries of these community descriptions provide complete coverage of the underlying graph index and the input documents it represents. Query-focused summarization of an entire corpus is then made possible using a map-reduce approach: first using each community summary to answer the query independently and in parallel,then summarizing all relevant partial answers into a final global answer.
簡單來說,就是利用社區檢測算法(如Leiden算法)將整個知識圖譜劃分模塊化的社區(包含相關性較高的節點),然后大模型自下而上對社區進行摘要,最終再采取map-reduce方式實現QFS: 每個社區先并行執行Query,最終匯總成全局性的完整答案.
與其他RAG系統類似,GraphRAG整個Pipeline也可劃分為索引(Indexing)與查詢(Query)兩個階段。索引過程利用LLM提取出節點(如實體)、邊(如關系)和協變量(如 claim),然后利用社區檢測技術對整個知識圖譜進行劃分,再利用LLM進一步總結。
鑒于篇幅原因,今天的這篇文章主要聚焦于indexing, 下一篇文章會介紹Query的工作原理,敬請期待!
pipeline
當你運行 "poetry run poe index" 命令時,它會執行 graphrag.index.cli 目錄下的 index_cli 入口函數。在 GraphRAG 中,構建知識圖譜被視為一個流水線(pipeline)過程,這個流水線包含多個工作流(workflow),例如文本分塊、使用LLM來識別實體等。pipeline涵蓋的workflow是通過 settings.yml 配置文件進行指定的。index_cli 的主要任務是創建 pipeline_config 對象,并利用 run_pipeline_with_config 函數來運行流水線。所以,我們可以將整個流程概括如下:
整個過程體現了自上而下的編程思想——每個結果依賴于更底層函數的執行,從頂部開始調用,然后逐步深入到底層函數。這樣的結構使得整體流程清晰明了,這也是我們平時在項目開發中的編程思路。
workflow
討論workflow之前,先簡單了解下項目使用的另一個框架: DataShaper 是微軟開源的一款用于執行工作流處理的庫,內置了很多組件(專業名詞叫做Verb). 通過定義一個數據處理的工作流,你可以對輸入的數據(比如Pandas的DataFrame)定義一系列數據操作的動作(DataShaper中稱作Verb)、參數與步驟,執行這個工作流即可完成數據處理過程。在DataShaper中提供了很多開箱即用的Verb,你也可以自定義Verb。多個子工作流也可以組合定義成一個更大的工作流。
當你通過命令行執行完indexing之后,你會看到如下的輸出內容:
從這個可以看出GraphRAG的indexing共經歷了14個workflow:
- create_base_documents
- create_final_documents
- create_base_text_units
- join_text_units_to_entity_ids
- join_text_units_to_relationship_ids
- create_final_text_units
- create_base_extracted_entities
- create_summarized_entities
- create_base_entity_graph
- create_final_entities
- create_final_relationships
- create_final_nodes
- create_final_communities
- create_final_community_reports
基本的處理過程如下:首先,它會將輸入文本進行拆分,然后提取實體與關系,生成摘要信息,并根據這些信息構建內存中的圖(Graph)結構。接下來,它會從這個圖中識別出各個社區,為每個社區創建報告,并在圖中創建文本塊節點和文檔節點。
當然,以上只是些核心步驟,但在實際的處理過程中還涉及到許多細節處理,比如生成嵌入(embedding),持久化到存儲,以及應用不同的算法策略等等。當然這些并不是這篇文章的重點。如果感興趣,評論區留言我會單獨開別的文章來講解。
這里可以多說一點,這14個workflow其實又可以進一步細分為四大類:
1.關于文檔的document_workflows
- create_base_document
- craete_final_documents
2.關于文檔單元的text_unit_workflows
- create_base_text_units
- join_text_units_to_entity_ids
- join_text_units_to_relationship_ids
- create_final_text_units
3.構建圖譜的graph_workflows
- create_base_extracted_entities
- create_summarized_entities
- create_base_entity_graph
- create_final_entities
- create_final_relationships
- create_final_nodes
4.社區聚類的community_workflows
- create_final_communities
- create_final_community_reports
此外,各個工作流之間存在一定的依賴關系,形成了一個工作流流程圖。輸入數據為存放在 input 目錄下的 txt 或 csv 文件(目前只支持這兩種,后面我會自己支持更多格式),經過這些工作流組成的流程圖處理后,輸出的結果就是最終構建的知識圖譜。
接下來,我將以一個包含 "海賊王" 的 txt 文件為例(摘自百度百科),逐步解析它經歷的各個工作流,以及每個工作流的輸入和輸出是什么.
1. create_base_text_units
整個pipeline的入口輸入在源碼中是個叫dataset的變量,其存儲的值Pandas DataFrame,Pandas DataFrame可以簡單看做是一張table, 這個table的每一行代表一個txt文件,text列是txt文件的內容:
create_base_text_units 是整個pipeline的第一個workflow, 它的作用是對txt的文件內容按照特定的策略進行切分(chunking)操作,目前只支持兩種策略: 按照token和按照sentence,默認是按照token, chunk操作的輸入是text:
對于一個text 經過chunking操作后會得到多個chunks:
Microsoft GraphRAG在索引構建的過程中其中間數據主要使用Pandas DataFrame這種結構化類型進行交換, 可以簡單理解為Mysql中的table,對DataFrame的一些操作比如select、join等可以類比mysql的select, join等sql語句來理解。
2. create_base_extracted_entities
一旦我們得到了相應的chunk,GraphRAG就會采用特定的策略從每個chunk來提取需要的實體entity。
目前,GraphRAG支持兩種抽取策略:
- graph_intelligence:這是默認的策略。
- nltk:另一種可選策略。
在源碼中的ExtractEntityStrategyType里,盡管定義了一個名為“graph_intelligence_json”的枚舉值,但是目前還未對它進行支持。
當處理多個數據塊時,GraphRAG會并行調用LLM來抽取實體,而且默認情況下,它會選擇使用多線程。不過,如果你想的話,也可以通過配置修改成asyncio模式。
在此流程中,GraphRAG會調用run_extract_entities進行實體抽取,該函數會利用目錄下的entity_extraction.txt中的prompt來調用LLM完成實體提取。默認的 entity_extraction prompt 抽取的實體類型是 ['organization', 'person', 'geo', 'event'],你可以根據你的文件內容來修改settings.yml中entity_extraction,后面我會介紹如何通過prompt tuning來自動適配prompt.
entity_extraction:
## llm: override the global llm settings for this task
## parallelization: override the global parallelization settings for this task
## async_mode: override the global async_mode settings for this task
prompt: "prompts/entity_extraction.txt"
entity_types: [organization,person,geo,event]
max_gleanings: 1
我截取了其中一個chunk得到的LLM調用結果的部分內容:
("entity"<|>歐羅·杰克遜號<|>ORGANIZATION<|>歐羅·杰克遜號是羅杰海賊團的船只)
##
("entity"<|>白胡子<|>PERSON<|>白胡子是“頂上戰爭”之前的四皇之一,懸賞金為50億4600萬)
##
("entity"<|>百獸<|>PERSON<|>百獸是“頂上戰爭”之前和之后的四皇之一,懸賞金為46億1110萬)
##
("entity"<|>BIG MOM<|>PERSON<|>BIG MOM是“頂上戰爭”之前和之后的四皇之一,懸賞金為43億8800萬)
##
("entity"<|>紅發<|>PERSON<|>紅發是“頂上戰爭”之前和之后的四皇之一,懸賞金為40億4890萬)
##
("entity"<|>黑胡子海賊團<|>ORGANIZATION<|>黑胡子海賊團是黑胡子的勢力)
##
("relationship"<|>弗蘭奇<|>卡雷拉公司<|>弗蘭奇設計的海賊船由卡雷拉公司協助制作<|>8)
##
("relationship"<|>草帽大船團<|>俊美海賊團<|>俊美海賊團是草帽大船團旗下的一個海賊團<|>7)
##
("relationship"<|>卡文迪許<|>俊美海賊團<|>卡文迪許是俊美海賊團的船長<|>9)
##
("relationship"<|>斯萊曼<|>俊美海賊團<|>斯萊曼是俊美海賊團的船員<|>8)
GraphRAG會對LLM的輸出結果進行后處理post_processing,最終形成Graph對象的。我們先看一下實體(entities),每一個實體都有四個主要的屬性:name、description、source_id 和 type。
- Name:這是實體的名稱。
- Description:對實體的描述。
- Source_id:在此情況下,source_id是指那些生成這個特定實體的數據塊(chunk)的識別號。
- Type:實體的類型。
每個chunk都生成對應的實體后,會把這些實體添加到一個列表entities中,并把每段chunk對應的表達圖形結構的Graphml也放到一個列表entity_graph中:
Microsoft GraphRAG在索引構建的過程中對于Graph數據的交換使用Graphml(一種xml表示的graph)
這里有個情況需要考慮,不同的數據塊(chunks)可能會抽取出相同的實體。比如說,第一個和第二個數據塊都可能包含"草帽路飛"這個實體。這時候,GraphRAG會采用一種名為merge_graphs的操作,把多個子圖合并成一個新的大圖。如果遇到相同的節點,那么GraphRAG就會執行concat操作,也就是將對應的屬性和關系進行合并。
比如對于一個實體:'哥爾·D·羅杰', 經過merge之后會包含多個description的列表: ['哥爾·D·羅杰是羅杰海賊團的船長', '哥爾·D·羅杰是被稱為“海賊王”的男人,他在被行刑受死之前說了一句話,開啟了“大海賊時代”']
通過merge_graphs操作,GraphRAG能夠有效地處理重復的實體,并把多個chunk對應的Graph整合成一個新的Graph,形成一個更加完善和詳細的數據圖:
3. create_summarized_entities
通過merge_graphs的操作,將多個子圖合并到一個全新的大圖之后,GraphRAG會進一步這個大圖的節點(node)和關系(relationship)的描述(descriptions)進行總結。
這樣做的目的是為了方便查詢,因為查詢時需要根據問題匹配知識庫中的實體信息和關系信息時,只需要根據總結后的實體描述和關系描述就可以進行匹配了. 不然得遍歷description list進行匹配。
GraphRAG目前支持的summarize的策略只有一種:graph_intelligence。
summarize使用的prompt中文翻譯如下:
你是一位負責生成以下提供數據的綜合摘要的有用助手。
根據一個或兩個實體,以及一系列描述,這些描述都與同一個實體或一組實體有關。
請將所有這些描述合并成一個單一的、全面的描述。確保包括所有描述中收集到的信息。
如果提供的描述存在矛盾,請解決這些矛盾,并提供一個單一的、連貫的摘要。
確保用第三人稱寫作,并包括實體名稱,以便我們擁有完整的上下文。
#######
-數據-
實體: {entity_name}
描述列表: {description_list}
#######
輸出:
執行summarize_descriptions操作后,原來圖形中的多個description就被整合為了一個全新的、詳盡的描述??梢哉f,summarize_descriptions是把前一步得到的Graph進行整理的過程,使得Graph更加清晰、準確。
經過summarize之后,上一個workflow create_base_extracted_entities 得到的Graph被更進一步完善了:
生成這種摘要的好處是:可以借助嵌入embedding向量更有效與準確的對這些實體與關系進行檢索。
4. create_base_entity_graph
這一步是做社群檢查的: 將實體進行分類,拿三國舉例,比如周瑜和孫策屬于吳國,曹操和司馬懿屬于魏國,劉備和關羽屬于蜀國,而吳國、魏國、蜀國都屬于東漢,其中東漢是一個大社群,魏蜀吳是三個小社群,當執行查詢時,可以指定社區的級別,如果指定的是低級別社群,那么查找的結果就比較微觀,比如問三國時期有哪些著名人物,如果指定的社群為吳國,那么匹配的就只有周瑜和孫策,如果指定的社群為東漢,那么就能找到更多的著名人物。
create_base_entity_graph這個workflow會對Graph應用應用層次聚類算法(對應源碼中的cluster_graph方法), 在Graph中識別出層次結構和社區結構:一個Level對應多個community。
GraphRAG在源碼中借助了Graspologic庫實現的Leiden算法: Leiden算法通常比許多其他的社區檢測算法更穩定,能更可靠地復現結果, 但是Leiden算法在某些情況下可能會比其他方法慢一些。
在這個workflow中先會進行run_layout 布局分析,應用Leiden算法對nodes分社區,完成這些步驟后,每一個社區的節點都會被賦予以下屬性:
- Level:表示節點所在的層次。
- Cluster:表示節點所在社區的編號。
- Human_readable_id:這可以被看做是實體(entity)在同一個社區內的編碼,從0開始
經過create_base_entity_graph之后,Graph按照層級被劃分出多個子圖,每個子圖對應一個level:
5. create_final_entities
create_final_entities這個workflow的功能是對節點做embedding,方便進行之后的query。
在做embedding之前,為了更好地表示每個節點,我們將節點的'name'和'description'字段拼接起來,形成一個新的'name_description'字段。這樣,每個節點都將有一個通俗易懂,并且信息豐富的標簽。
然后,我們把這個新生成的'name_description'字段通過嵌入過程轉換成一個向量表示。這種方法能夠捕獲和表示文本數據的復雜模式,也使得我們可以針對這些節點進行高效的計算和分析。
經過上面的一些圖的修整之后,我們還需要對entity做進一步的embedding操作。在這之前,會經過embedding操作,embedding會對node的 name和description 拼接的 name: description 組成name_description字段,對這個字段做embedding操作。
經過embedding之后,新增了一列description_embedding字段:
image-20240809153319632
6. create_final_nodes
Network Visualization 階段,由于生成的圖譜一般不是一個平面圖(可以通過在平面上繪制其頂點和邊而不出現邊的交叉),通過使用降維技術操作將非平面圖映射到平面上,可以更直觀地觀察和理解數據的結構和模式。
在圖論和網絡分析中,圖的布局算法(layout algorithm)用于將圖中的節點和邊在二維或三維空間中進行合理的排列和可視化。其主要目標是使圖的結構和關系盡可能清晰地展示出來,以便于人類理解和分析。create_final_nodes會對Graph應用layout算法,GraphRAG目前支持兩種算法:
- umap:默認值
- zero
workflow的輸入是create_base_entity_graph的輸出:
每個entity的所有屬性現在長這樣:
7. create_final_communities
這個workflow用于創建community table, 步驟如下:
我們從第4步生成的create_base_entity_graph中抽取節點數據,形成一個名為graph_nodes的表:
然后,我們同樣從create_base_entity_graph中提取邊信息,生成另一個名為graph_edges的表:
然后,我們將graph_nodes和graph_edges進行left_join操作,這個新生成的表命名為combined_clusters:
緊接著,我們對combined_clusters進行進一步的聚合操作,同樣是按照cluster和level進行分組。在這個過程中,我們會把edge的id_2去重后組合成一個數組,命名為relationship_ids;同時,也會把node的source_id_1去重后組合成另一個數組,命名為text_unit_ids:
以cluster = 1為例,通過text_unit_ids,我們能夠知道這個社區來源于哪些chunk;通過relationship_ids,我們則可以確定這個社區包含了哪些邊。
最后,我們還會對上述數據進行一次處理,主要是生成每個社區的名稱:
image-20240810214443777
8. join_text_units_to_entity_ids
join_text_units_to_entity_ids的作用是建立text_unit到entity的映射關系。
首先,GraphRAG會提取出每個實體的"id",以及表示實體來源的字段"text_unit_ids"。接著,我們對"text_unit_ids"進行“打平”操作,也就是將嵌套的數據結構轉化為一維的形式。
然后,我們進行聚合操作。具體來說,我們會按照"text_unit_id"對數據進行分類,并把相同類別的實體id聚合成一個數組,命名為"entity_ids"。
這樣,在最終的結果中,每一條記錄都會包含一個"text_unit_id",以及一個與之關聯的"entity_ids"數組:
image-20240810091048672
9. create_final_relationships
create_final_relationships用于創建relationship table, 步驟如下:
首先,我們從create_base_entity_graph中得到的Graph提取出所有的邊關系:
接下來,我們會對edge和nodes使用left_join操作,在這個步驟中,我們將新增兩列:source_degree和target_degree。這兩列分別表示源實體和目標實體的度數,也就是每個實體連接的邊的數量。
最后,我們會創建一個新的列"rank"。這個列的值是通過將source_degree和target_degree相加得到的。這樣,我們就可以根據rank的值,了解每條邊連接的兩個實體的總度數:
source | target | weight | description | text_unit_ids | id | human_readable_id | source_degree | target_degree | rank |
蒙奇·D·路飛 | 草帽一伙 | 1.0 | 蒙奇·D·路飛是草帽一伙的船長和創立者 | ['2808e991f29115cba505836944beb514'] | 392be891f8b649fabdc20e7bf549f669 | 0 | 11 | 19 | 30 |
蒙奇·D·路飛 | 香克斯 | 1.0 | 蒙奇·D·路飛為了實現與香克斯的約定而出海 | ['2808e991f29115cba505836944beb514'] | 0111777c4e9e4260ab2e5ddea7cbcf58 | 1 | 11 | 2 | 13 |
蒙奇·D·路飛 | ONE PIECE | 1.0 | 蒙奇·D·路飛為了尋找傳說中的大秘寶ONE PIECE而揚帆起航 | ['2808e991f29115cba505836944beb514'] | 785f7f32471c439e89601ab81c828d1d | 2 | 11 | 1 | 12 |
10. join_text_units_to_relationship_ids
這個workflow和我們之前討論過的join_text_units_to_entity_ids非常相似,主要區別在于,現在我們是將text_unit_id映射到它所包含的relationship_id,而不再是entity_ids。
簡單來說,我們的目標是理解每個text_unit_id(對應"chunk")都包含了哪些關系(relationship)。為了實現這個目標,我們會創建一種映射關系,把每個text_unit_id連接到它所涉及的所有relationship_id。結果將以類似于字典的形式呈現,其中鍵是text_unit_id,值是一個列表,包含了所有相關的relationship_id:
image-20240810094149840
11. create_final_community_reports
這個workflow用于生成社區摘要:借助LLM生成每個社區的摘要信息,用來了解數據集的全局主題結構和語義。這也是Microsoft GraphRAG的核心價值所在,也是回答QFS問題的關鍵。具體步驟如下:
首先借助??create_final_nodes?
??的輸出,并添加了一個??node_details?
?列以存儲更多關于節點的信息:
然后對這些nodes使用??community_hierarchy?
?來構建社區的層次結構,通過對(community, level) 的分組,將同一組內的節點title聚合成數組:
從上圖我們可以看到每個community包含了哪些entity。
接下來,GraphRAG開始分析父子社區的構造情況,如果上一級的社區包含了全部下一級社區的成員,那么它們之間就構成了父子社區的關系,我們發現社區1是個大社區,包含了12、13、14三個子社區,但是它們都屬于同一個level:
緊接著GraphRAG會基于三個table: node_df、edge_df、claim_df 做聚合操作,生成每個社區的context_string: 包含社區的所有節點和relationships信息:
image-20240810122232624
為了方便你看到context_string的內容,我摘取了某個社區的context_string內容:
'-----Entities-----\n'
'human_readable_id,title,description,degree\n'
'2,蒙奇·D·路飛,蒙奇·D·路飛是“草帽一伙”的船長,外號“草帽小子”,夢想成為“海賊王”,懸賞金30億貝里,11\n'
'20,ONE PIECE,,1\n'
'17,五老星,五老星認為蒙奇·D·路飛食用的橡膠果實實際上是人人果實·幻獸種·尼卡形態,1\n'
'10,和之國事件,和之國事件是蒙奇·D·路飛擊敗原“四皇”之一的“百獸”凱多的事件,1\n'
'19,尼卡,尼卡是五老星認為蒙奇·D·路飛食用的人人果實·幻獸種的形態,1\n'
'9,惡魔果實,惡魔果實是一種神秘的果實,食用后可以獲得超人能力,但會失去游泳的能力,1\n'
'11,百獸凱多,百獸凱多是原“四皇”之一,被蒙奇·D·路飛在和之國事件中擊敗,1\n'
'\n'
'\n'
'-----Relationships-----\n'
'human_readable_id,source,target,description,rank\n'
'0,蒙奇·D·路飛,草帽一伙,蒙奇·D·路飛是草帽一伙的船長和創立者,30\n'
'7,蒙奇·D·路飛,東海,蒙奇·D·路飛的出身地是東海,16\n'
'1,蒙奇·D·路飛,香克斯,蒙奇·D·路飛為了實現與香克斯的約定而出海,13\n'
'6,蒙奇·D·路飛,香波地群島,蒙奇·D·路飛是“極惡的世代”中登陸香波地群島的11位超新星之一,13\n'
'9,蒙奇·D·路飛,極惡的世代,蒙奇·D·路飛是“極惡的世代”中登陸香波地群島的11位超新星之一,13\n'
'2,蒙奇·D·路飛,ONE PIECE,蒙奇·D·路飛為了尋找傳說中的大秘寶ONE PIECE而揚帆起航,12\n'
'8,蒙奇·D·路飛,五老星,五老星認為蒙奇·D·路飛食用的橡膠果實實際上是人人果實·幻獸種·尼卡形態,12\n'
'4,蒙奇·D·路飛,和之國事件,蒙奇·D·路飛在和之國事件中擊敗了百獸凱多,12\n'
'10,蒙奇·D·路飛,尼卡,五老星認為蒙奇·D·路飛食用的橡膠果實實際上是人人果實·幻獸種·尼卡形態,12\n'
'3,蒙奇·D·路飛,惡魔果實,蒙奇·D·路飛因誤食惡魔果實而成為了橡皮人,12\n'
'5,蒙奇·D·路飛,百獸凱多,蒙奇·D·路飛在和之國事件中擊敗了百獸凱多,12\n'
接著LLM會使用community_report.txt中的prompt并把context_string作為輸入,對社區按照level進行自下而上的總結,使用的默認prompt中文翻譯如下:
你是一個人工智能助手,幫助人類分析員進行一般的信息發現。信息發現是識別和評估與某些實體(例如,組織和個人)相關的相關信息的過程。
# 目標
在給定屬于社區的實體列表及其關系和可選的相關聲明的情況下,編寫社區的全面報告。報告將用于通知決策者有關社區及其潛在影響的信息。報告內容包括社區關鍵實體的概述、他們的法律合規性、技術能力、聲譽和值得注意的聲明。
# 報告結構
報告應包括以下部分:
- 標題:代表其關鍵實體的社區名稱——標題應簡短但具體。盡可能在標題中包括具有代表性的命名實體。
- 摘要:對社區整體結構、其實體之間的關系以及與其實體相關的重大信息的執行摘要。
- 影響嚴重性評分:一個介于0-10之間的浮動評分,表示社區內實體所構成的影響的嚴重程度。影響是社區的重要性評分。
- 評分解釋:用一句話解釋影響嚴重性評分。
- 詳細發現:關于社區的5-10個關鍵見解的列表。每個見解應有一個簡短的摘要,后跟根據以下基礎規則進行的多段解釋性文本。要全面。
返回輸出為格式良好的JSON格式的字符串,格式如下:
```json
{
"title": <report_title>,
"summary": <executive_summary>,
"rating": <impact_severity_rating>,
"rating_explanation": <rating_explanation>,
"findings": [
{
"summary":<insight_1_summary>,
"explanation": <insight_1_explanation>
},
{
"summary":<insight_2_summary>,
"explanation": <insight_2_explanation>
}
]
}
```
# 基礎規則
支持數據的點應列出其數據引用,如下所示:
“這是一個由多個數據引用支持的示例句子[數據: <dataset name> (記錄ID); <dataset name> (記錄ID)]?!?
在單個引用中不要列出超過5個記錄ID。相反,列出最相關的前5個記錄ID,并加上“+更多”以表示還有更多。
例如:
“Person X是Company Y的所有者,并且受到許多不當行為指控[數據: 報告 (1), 實體 (5, 7); 關系 (23); 聲明 (7, 2, 34, 64, 46, +更多)]?!?
其中1, 5, 7, 23, 2, 34, 46和64代表相關數據記錄的ID(而不是索引)。
不要包括沒有提供支持證據的信息。
# 示例輸入
-----------
文本:
實體
id,entity,description
5,VERDANT OASIS PLAZA,綠洲廣場是團結游行的地點
6,HARMONY ASSEMBLY,和諧集會是一個在綠洲廣場舉行游行的組織
關系
id,source,target,description
37,VERDANT OASIS PLAZA,UNITY MARCH,綠洲廣場是團結游行的地點
38,VERDANT OASIS PLAZA,HARMONY ASSEMBLY,和諧集會在綠洲廣場舉行游行
39,VERDANT OASIS PLAZA,UNITY MARCH,團結游行正在綠洲廣場進行
40,VERDANT OASIS PLAZA,TRIBUNE SPOTLIGHT,論壇焦點正在報道綠洲廣場上的團結游行
41,VERDANT OASIS PLAZA,BAILEY ASADI,Bailey Asadi在綠洲廣場上就游行發表演講
43,HARMONY ASSEMBLY,UNITY MARCH,和諧集會正在組織團結游行
輸出:
```json
{
"title": "綠洲廣場和團結游行",
"summary": "社區圍繞綠洲廣場展開,該廣場是團結游行的地點。廣場與和諧集會、團結游行和論壇焦點都有關系,這些都與游行事件有關。",
"rating": 5.0,
"rating_explanation": "由于團結游行期間可能發生的騷亂或沖突,影響嚴重性評分為中等。",
"findings": [
{
"summary": "綠洲廣場作為中心地點",
"explanation": "綠洲廣場是該社區的中心實體,作為團結游行的地點。該廣場是所有其他實體的共同聯系點,表明其在社區中的重要性。廣場與游行的關聯可能會導致如公共秩序問題或沖突等問題,具體取決于游行的性質和它引起的反應。[數據: 實體 (5), 關系 (37, 38, 39, 40, 41,+更多)]"
},
{
"summary": "和諧集會在社區中的角色",
"explanation": "和諧集會是社區中的另一個關鍵實體,他們在綠洲廣場組織游行。和諧集會的性質和他們的游行可能是潛在的威脅來源,這取決于他們的目標和引起的反應。和諧集會和廣場之間的關系對于理解該社區的動態至關重要。[數據: 實體(6), 關系 (38, 43)]"
},
{
"summary": "團結游行作為重要事件",
"explanation": "團結游行是一個在綠洲廣場上發生的重要事件。該事件是社區動態的關鍵因素,具體取決于游行的性質和它引起的反應,可能是潛在的威脅來源。游行和廣場之間的關系對于理解社區的動態至關重要。[數據: 關系 (39)]"
},
{
"summary": "論壇焦點的作用",
"explanation": "論壇焦點正在報道在綠洲廣場上舉行的團結游行。這表明該事件吸引了媒體的關注,可能會放大其對社區的影響。論壇焦點的作用可能在塑造公眾對事件和相關實體的看法方面具有重要意義。[數據: 關系 (40)]"
}
]
}
```
# 真實數據
使用以下文本作為答案的依據。不要在答案中編造任何內容。
文本:
{input_text}
報告應包括以下部分:
- 標題:代表其關鍵實體的社區名稱——標題應簡短但具體。盡可能在標題中包括具有代表性的命名實體。
- 摘要:對社區整體結構、其實體之間的關系以及與其實體相關的重大信息的執行摘要。
- 影響嚴重性評分:一個介于0-10之間的浮動評分,表示社區內實體所構成的影響的嚴重程度。影響是社區的重要性評分。
- 評分解釋:用一句話解釋影響嚴重性評分。
- 詳細發現:關于社區的5-10個關鍵見解的列表。每個見解應有一個簡短的摘要,后跟根據以下基礎規則進行的多段解釋性文本。要全面。
返回輸出為格式良好的JSON格式的字符串,格式如下:
```json
{
"title": <report_title>,
"summary": <executive_summary>,
"rating": <impact_severity_rating>,
"rating_explanation": <rating_explanation>,
"findings": [
{
"summary":<insight_1_summary>,
"explanation": <insight_1_explanation>
},
{
"summary":<insight_2_summary>,
"explanation": <insight_2_explanation>
}
]
}
```
# 基礎規則
支持數據的點應列出其數據引用,如下所示:
“這是一個由多個數據引用支持的示例句子[數據: <dataset name> (記錄ID); <dataset name> (記錄ID)]。”
在單個引用中不要列出超過5個記錄ID。相反,列出最相關的前5個記錄ID,并加上“+更多”以表示還有更多。
例如:
“Person X是Company Y的所有者,并且受到許多不當行為指控[數據: 報告 (1), 實體 (5, 7); 關系 (23); 聲明 (7, 2, 34, 64, 46, +更多)]?!?
其中1, 5, 7, 23, 2, 34, 46和64代表相關數據記錄的ID(而不是索引)。
不要包括沒有提供支持證據的信息。
輸出:
我們看下某個社區的報告內容:
{'findings': [{'explanation': '蒙奇·D·路飛是草帽一伙的船長和創立者,他的夢想是成為海賊王。他的出身地是東海,并且為了實現與香克斯的約定而出海。他還因誤食惡魔果實而成為了橡皮人,這使他獲得了超人能力但失去了游泳的能力 '
'[Data: Entities (2, 9); Relationships (0, 7, 1, '
'3)].',
'summary': '蒙奇·D·路飛的核心地位'},
{'explanation': '和之國事件是蒙奇·D·路飛擊敗原“四皇”之一的百獸凱多的事件。這一事件標志著他在海賊世界中的地位進一步提升,并對世界格局產生了深遠影響 '
'[Data: Entities (10, 11); Relationships (4, '
'5)].',
'summary': '和之國事件的重要性'},
{'explanation': '五老星認為蒙奇·D·路飛食用的橡膠果實實際上是人人果實·幻獸種·尼卡形態。這一觀點揭示了蒙奇·D·路飛的能力可能比之前認為的更為強大和神秘 '
'[Data: Entities (17, 19); Relationships (8, '
'10)].',
'summary': '五老星的觀點'},
{'explanation': '惡魔果實是一種神秘的果實,食用后可以獲得超人能力,但會失去游泳的能力。蒙奇·D·路飛因誤食惡魔果實而成為了橡皮人,這使他在戰斗中具有獨特的優勢 '
'[Data: Entities (9); Relationships (3)].',
'summary': '惡魔果實的影響'},
{'explanation': '草帽一伙是由蒙奇·D·路飛創立的海賊團體,他們在海賊世界中扮演著重要角色。蒙奇·D·路飛作為船長,帶領著這支團隊在尋找傳說中的大秘寶ONE '
'PIECE的過程中經歷了許多冒險 [Data: Entities (2, 20); '
'Relationships (0, 2)].',
'summary': '草帽一伙的角色'},
{'explanation': '蒙奇·D·路飛是“極惡的世代”中登陸香波地群島的11位超新星之一。這一身份使他在海賊世界中備受關注,并進一步提升了他的影響力 '
'[Data: Relationships (6, 9)].',
'summary': '極惡的世代'}],
'rating': 8.5,
'rating_explanation': '該社區的影響力很高,因為蒙奇·D·路飛在和之國事件中的勝利對整個世界格局產生了重大影響。',
'summary': '該社區圍繞著蒙奇·D·路飛展開,他是草帽一伙的船長,夢想成為海賊王。蒙奇·D·路飛與多個實體有著緊密的聯系,包括和之國事件、五老星、百獸凱多等。和之國事件是他擊敗原“四皇”之一的百獸凱多的重要事件。五老星認為他食用的橡膠果實實際上是人人果實·幻獸種·尼卡形態。',
'title': '蒙奇·D·路飛與和之國事件'}
這份報告包含了社區的總體title、summary和發現等等,這個過程也是最耗費token的。
12. create_final_text_units
這個workflow很簡單,就是把對應的chunk和這個chunk有的document_ids, entity_ids, relationship_ids 做關聯,成一張表
- id: 表示每條記錄的唯一標識符。
- text: 包含文本內容的列。
- n_tokens: 表示文本內容中包含的標記(token)的數量。
- document_ids: 包含一個或多個文檔標識符的列,表示該記錄與哪些文檔相關聯。
- entity_ids: 包含一個或多個實體標識符的列,表示該記錄中提到的實體。
- relationship_ids: 包含一個或多個關系標識符的列,表示該記錄中涉及到的關系。
image-20240810150028338
13. create_base_documents
這個流程也很簡單,主要是建立document和text_unit的對應關系表
image-20240810150221714
14. create_final_documents
這個流程完成的工作基本和create_base_documents一致,只是把text_units列名換成了text_unit_ids而已
image-20240810223341019
總結
當GraphRAG完成索引過程后,它默認會將構建知識圖譜所需的所有數據持久化。這些數據被存儲在輸出目錄中,并采用Parquet文件格式。Parquet是一種列式壓縮存儲格式,專為高效的數據存儲和分析而設計。你可以將其視為DataFrame的一種持久化方式。
在查詢階段,這些Parquet文件會被加載到內存和向量數據庫中。這樣做的好處在于,我們可以直接從內存和數據庫中檢索信息,而無需再次從原始數據源抽取和處理數據。這大大提高了查詢的效率和速度。
由于parquet是一種底層文件格式,我們無法用來直觀的了解與觀察上面構建的知識圖譜索引的細節,有什么辦法可以做更直觀的可視化、分析與檢索呢?
由于parquet文件可以很簡單的通過pandas庫讀取成DataFrame表,所以在了解其結構后,就可以通過Cypher語句導入成Neo4j圖數據庫中的節點與關系。在Github上已經有人完成這樣的工作:https://github.com/tomasonjo/blogs/blob/master/msft_graphrag/ms_graphrag_import.ipynb。你如果嫌麻煩,也可以把parquet轉成csv格式進行查看,代碼也非常簡單,不到20行左右,感興趣的可以評論區留言。下圖是抽取的Entity的Neo4j展示:
image-20240811200959883
基于GraphRAG生成的數據導入到Neo4j之后,我們完全可以不再依賴于GraphRAG項目自帶的Query功能,可以結合自己的項目需求在自己的Neo4j圖數據庫上定義自己的RAG應用檢索與生成器,從而帶來極大的靈活性。
本文轉載自公眾號AI 博物院 作者:longyunfeigu
