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