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