精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

如何使用 Neo4j、知識圖譜和 LLM 構建聊天機器人

人工智能
在這篇文章中,我將嘗試解釋我在從事該項目期間對知識圖譜的學習,并嘗試解釋如何使用它們在結構化數據集上執行問答和檢索增強生成 (RAG) 的各種方法。我將提供下面提到的 3 種關鍵方法,您可以使用 LLM 與 GraphDB 進行聊天,為此,我將使用Neo4j Database.

最近,我正在為一位醫療行業的客戶做一個項目。他們擁有大量的病歷、研究論文和診斷報告,散布在數千個 Excel 文件和 PDF 文件中。每當他們需要洞察時,他們的分析師都會花費數小時有時甚至數天來交叉比對這些來源,以解答哪怕是最基本的問題,例如“哪種治療方案最適合患有 X 疾病的患者?”

起初,我們嘗試了標準的檢索增強生成 (RAG) 流程,其中包含嵌入和向量數據庫。對于表面查詢,它效果還不錯,但當問題變得更加復雜時,比如將病史與治療結果結合起來就遇到了瓶頸。就在那時,我意識到:我們需要一個知識圖譜。

在這篇文章中,我將嘗試解釋我在從事該項目期間對知識圖譜的學習,并嘗試解釋如何使用它們在結構化數據集上執行問答和檢索增強生成 (RAG) 的各種方法。我將提供下面提到的 3 種關鍵方法,您可以使用 LLM 與 GraphDB 進行聊天,為此,我將使用Neo4j Database。

使用知識圖譜和 LLM 的基本 QnA 流程

CypherQAChain:一種將自然語言問題轉換為 Cypher 查詢的簡單方法。我將演示這種方法如何簡化圖譜查詢并提供快速、精準的答案。

高級查詢:對于更復雜的問題,我們將探索一種結合實體提取和數據庫值映射的技術。這種方法非常適合處理需要更深入分析的細微查詢。

基于 RAG 的方法:為了提高相關性和檢索能力,我們將向量索引與知識圖譜集成。通過這種方式,我們能夠妥善處理作為問答任務節點屬性存儲的非結構化數據,例如文本描述。

為了解釋這些方法,我將使用一個movie dataset包含電影、演員、導演、類型、ImDB 評分和上映日期信息的數據集。通過這個數據集,你將了解如何使用知識圖譜和 LLM 高效地處理結構化數據集,以及如何使用 RAG 處理作為節點屬性存儲的非結構化數據。

在本文結束時,您不僅會了解這些技術,而且還會擁有在您的項目中親自實現這些技術的實踐知識。

一、知識圖譜和 GraphDB 的基本概述

在我們開始使用知識圖譜構建聊天系統之前,必須了解圖數據庫(GraphDB)的基本概念以及它們為何在涉及復雜、互聯數據的場景中表現出色。

什么是圖數據庫(GraphDB)

圖數據庫(GraphDB)是一種旨在將數據作為實體及其關系網絡進行存儲和管理的數據庫。GraphDB 不像傳統關系數據庫那樣使用行和列,而是使用以下主要組件來存儲數據:

這種結構使得 GraphDB 非常適合處理互聯數據,尤其是在關系對于理解整體情況至關重要的情況下,例如在社交媒體平臺中。在這種情況下使用 GraphDB 具有以下優勢:

1. 關系的自然表達

在傳統的關系數據庫中,我們將用戶存儲在一個表中,并將他們的關系(例如“關注”或“好友”)存儲在另一個表中,并使用外鍵。例如:

  • 用戶表:每一行代表一個用戶。
  • 關系表:使用用戶 ID 跟蹤誰關注誰。
    雖然這種方法有效,但隨著網絡規模的增長,查詢這些關系會變得復雜且緩慢。
    在 GraphDB 中,這些關系直接建模為節點(用戶)之間的邊。例如:
  • 節點A:代表用戶A。
  • 節點B:代表用戶B。
  • Edge:代表“用戶 A 關注用戶 B”。

用戶 A 關注用戶 B 的 Cypher 查詢

這種方法讓我們可以直接遍歷關系,比如找到“共同的朋友”或“建議的聯系人”,而不需要復雜的表連接。

2. 節點和關系的語義豐富性和屬性

GraphDB 允許邊承載關于關系的詳細信息,從而將其轉換為知識圖譜。例如,除了簡單的“關注”邊之外,我們可以定義:

  • “評論”表示與帖子的互動。
  • “標記”用于在照片或視頻中提及。
  • “反應”表示喜歡、喜愛或其他反應。

這種語義豐富性為數據增添了有意義的上下文。例如:

  • 查詢:“哪些用戶在同一個項目上進行了合作?”
  • 答案:遍歷標記為“合作”的邊來尋找連接

此外,GraphDB 中的每個節點和邊不僅具有節點及其之間的關系,而且每個節點和邊還帶有屬性,如下圖所示,從而使它們成為知識圖譜

3.動態更新

GraphDB 是為動態更新而構建的,這意味著當新數據出現時,如果它屬于現有的節點和邊關系,那么它就會被放置在那里,否則就會形成新的節點和關系,從而動態更新數據庫。

考慮不斷變化的社交媒體網站的例子——新的友誼形成、帖子被分享、評論被添加。

  • 添加新的關系(如“關注”或“評論”)就像添加邊一樣簡單。
  • 刪除關系(如“取消關注”)會移除邊緣,而不會破壞其他數據。

例如,當用戶 A 關注用戶 B 時,GraphDB 會立即更新,在他們各自的節點之間創建新的邊。這種動態特性有助于使網絡保持最新信息。

4. 遍歷效率

GraphDB 針對遍歷算法進行了優化,例如:

  • 深度優先搜索(DFS):探索深層關系,例如兩個用戶之間的互動鏈。
  • 廣度優先搜索(BFS):探索所有直接連接,例如查找用戶的所有朋友。
  • Delta-Stepping 單源最短路徑:有效計算從單個源到所有其他節點的最短路徑,有助于找到網絡中最快路線。
  • Dijkstra 源-目標最短路徑:查找兩個特定節點之間的最短路徑,非常適合確定兩個用戶之間最有效的連接。

例如,在社交媒體平臺中,遍歷對于以下任務至關重要:

  • 朋友建議:通過遍歷共同的朋友來確定潛在的聯系。
  • 內容推薦:根據共享標簽或喜歡查找類似的帖子。
  • 社區檢測:識別具有共同興趣的用戶群體。

5.可解釋性和可追溯性

GraphDB 可以輕松追蹤用戶或實體之間的連接方式。例如:

  • 查詢:“用戶 A 如何連接到用戶 C?”
  • 答案:該圖可能顯示如下路徑:
  • 用戶 A 關注用戶 B(Edge 1)。
  • 用戶 B 對用戶 C 的帖子 (Edge 2) 進行了評論。

這種透明度對于調試、用戶洞察以及建立對推薦算法的信任非常重要。

點個贊 ??:如果您覺得這篇文章有用,請關注我、點贊??,或者分享給其他可能受益的人。謝謝!我們回到正文吧

二、LLM 和 GraphDB 如何在問答應用程序中交互

為了使用知識圖譜構建智能高效的聊天機器人系統,我們首先需要了解 LLM 和 GraphDB 實際上是如何協同工作的。

GraphDB,例如 Neo4j(如上所述)在存儲和導航互連數據方面非常高效。它們使用節點(實體)、邊(實體之間的關系)和屬性(節點和邊的屬性)的結構來表示和管理復雜的關系。

而 LLM 則是將類似人類的非結構化輸入轉換為有意義的結構化查詢的主要大腦。例如,如果用戶問聊天機器人“誰出演了電影《盜夢空間》?”,LLM 會將這種自然語言查詢轉換為精確的查詢語言,例如 Cypher(Neo4j 使用):

匹配(m :電影{標題: “盜夢空間” } ) - [ : ACTED_IN ] - (p :人物)  
返回p.name;

然后,LLM 解釋 GraphDB 檢索到的結果并向用戶提供對話響應,例如:“The cast of Inception includes Leonardo DiCaprio, Ellen Page, and Joseph Gordon-Levitt.”

隨著編碼和推理能力的不斷進步,現代大型語言模型 (LLM) 已成為以下領域的卓越工具:

  1. 自然語言理解:將模糊或非結構化的用戶查詢轉換為數據庫的精確、可執行命令,如上所示。
  2. 生成類似人類的反應:將從數據庫檢索的數據轉換為對話回復。

但它們的作用遠不止于此。除了查詢數據之外,LLM 還reating通過處理非結構化數據在 C 知識圖譜中發揮著重要作用。

LLM 用于將非結構化數據轉換為圖

GraphDB 生態系統中 LLM 最令人興奮的應用之一是它們能夠將 PDF、文檔形式的非結構化信息轉換為結構化圖數據。這涉及識別文本中與之相關的實體(節點)和關系(邊)和屬性,然后將它們表示為圖。

示例:從文本中提取圖數據

考慮一份文本文檔:“萊昂納多·迪卡普里奧出演了克里斯托弗·諾蘭執導的《盜夢空間》”。

使用LLMGraphTransformer之類的工具,可以將文本轉換為圖:

  • 節點:
    - Leonardo DiCaprio人物)
    - Inception(電影)
    - Christopher Nolan(人物)
  • 關系:
    - Leonardo DiCaprio→ACTED_IN→→→Inception
    - Christopher NolanDIRECTEDInception

請注意,由于 LLMGraphTransformer 或類似工具使用 LLM 作為基礎,因此圖的構建過程是不確定的。因此,每次執行的結果可能略有不同,并且圖的質量在很大程度上取決于所使用的 LLM 類型。

LLMGraphTransformer 使用 LLM 來

  1. 解析非結構化文本文檔。
  2. 識別和分類實體(例如人物、電影)。
  3. 建立這些實體之間的有意義的關系。

圖形成的有效性取決于所選的 LLM 模型,因為它會影響提取的圖數據的準確性和粒度。

三、方法1:使用CypherChainQA進行QnA的實際實現

現在我們已經對 GraphDB 如何與 LLM 交互有了基本的了解,現在讓我們使用 Langchain 框架中的 CypherChainQA 開始使用 GraphDB 的 QnA 聊天機器人的第一階段。

Neo4j 設置:

在我們的實現中,我們將使用Neo4j,這是一個功能強大的圖數據庫管理系統,以其高效處理和查詢圖數據而聞名。Neo4j 提供了多種功能,使其成為聊天機器人開發的絕佳選擇:

  • Cypher 查詢語言:Neo4j 使用Cypher,這是一種聲明性且用戶友好的查詢語言,可簡化檢索和操作圖表中數據的過程。
  • 易于集成:Neo4j 提供了一個 Python 驅動程序,這使得可以輕松地從 LangChain(一種用于處理 LLM 的流行框架)直接連接數據庫并與之交互。

此外,Neo4j 與 LangChain 框架的良好集成使其非常適合構建基于圖的聊天機器人系統。Neo4j 與 LangChain 的集成使我們能夠:

讓我們設置 neo4j AuraDB

  • 前往 Neo4j Aura 并登錄或注冊。
  • 創建一個新的數據庫實例。
  • 實例準備就緒后,請.txt在提示時記下并下載連接憑據:
    - URI(例如bolt://<your_database>.databases.neo4j.io)
    -用戶名(默認neo4j:)
    -密碼(在設置期間生成)。

使用以下代碼,使用上面提到的憑據連接到 Neo4j DB:

從kaggle_secrets導入UserSecretsClient
從langchain_community.graphs導入Neo4jGraph 

user_secrets = UserSecretsClient() 
groq_api_key = user_secrets.get_secret( "groq_api_key" ) 
hf_api_key = user_secrets.get_secret( "hf_api_key" ) 
NEO4J_PASSWORD = user_secrets.get_secret( "NEO4J_PASSWORD" ) 
NEO4J_URI = user_secrets.get_secret( "NEO4J_URI" ) 
NEO4J_USERNAME = user_secrets.get_secret( "NEO4J_USERNAME" ) 
graph = Neo4jGraph( 
    url=NEO4J_URI,     username=NEO4J_USERNAME, 
    password=NEO4J_PASSWORD) 
print ( "已連接到 Neo4j!" )

數據預處理和創建圖表

現在我們已經與數據庫建立了連接,現在我們可以導入數據集,對其進行一些預處理并更新 Neo4j 數據庫。

步驟 1??:我們首先加載一個示例電影數據集。該數據集包含電影的關鍵信息,例如片名、導演、演員、類型和評分。讓我們讀取數據并快速瀏覽一下:

df=pd.read_csv("https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/movies/movies_small.csv" , nrows= 20 ) 
display(df.head( 3 )) 
print (df.shape) 
print ( "=" * 40 ) 
print (df.columns) 
print ( "=" * 40 ) 
print (df[ "title" ][: 20 ].values)

步驟2??:為了使數據集對于RAG任務的查詢和檢索更有意義,我為每部電影創建了一個詳細的描述列。這些描述列結合了各種列,例如片名、導演、演員、類型、IMDb評分和上映日期。

此外,我還創建了額外的虛擬列。

detail = df[ 'title' ][ 0 ] 
detail 
df[ 'movie_detail' ] = df.apply( lambda row: f"電影{row[ 'title' ]}由{row[ 'director' ]}執導,
演員名為{row[ 'actors' ].replace( '|' , ' , ' )},屬于 { row[ 'genres' ].replace( '|' , ' , ' )}
類型的電影。其評分為{row[ 'imdbRating' ]} \ ,上映日期為{row[ 'released' ]} "
 ,axis= 1 ) 
df.head() 
# 添加地點和類似電影的自定義數據  
location = [ "美國" , "美國" , "美國" , "美國" , "美國" ,   
            "美國美國"、"美國"、"美國"、"美國"、"英國"、"美國"、   
            "美國"、 "美國" 、"美國" 、 "馬耳他"、   "美國"、"英國"、"美國"、"美國"、"美國" ]   
similar_movie = [ 《海底總動員》、《勇敢者游戲:決戰叢林》、《遺愿清單》、《伴郎假期》 、《兒女一籮筐》、《無間行者》、   《諾丁山》、 《哈克貝利·費恩歷險記》 、《虎膽龍威》、   《碟中諜》、《戴夫》、《愛而不得:年輕的科學怪人》、   《小馬駒》、《刺殺肯尼迪》、   《《加勒比海盜:黑珍珠號的詛咒》、《好家伙》、   《傲慢與偏見》、《低俗小說》、《變相怪杰》、《生死時速》 ]   
df[ 'location'] = location   
df[ 'similar_movie' ] = similar_movie   
# 保存豐富的數據集以用于圖構建  
df.to_csv( "movie.csv" , sep= "," , index= False )

步驟3??:構建 Neo4j 圖

現在,我們將使用處理后的數據集更新 Neo4j 數據庫。該圖將包含電影、導演、演員、類型、地點和類似電影的節點。這些實體之間的關系也將相應地創建。

# 創建以下輸入值只是為了確保不會再次執行此代碼來意外創建圖value = input(“您真的要執行此單元格并再次創建 GraphDB 嗎?y/n”)
movie_csv_path = 'movie.csv' 
if value == 'y' : 
    graph.query( “”” 
    LOAD CSV WITH HEADERS FROM 
    'https://raw.githubusercontent.com/manindersingh120996/RAG-Related-Projects/refs/heads/main/movie%20(1).csv' 
    AS row 
    MERGE(m:Movie {id:row.movieId})
    SET m.released = row.released,
        m.title = row.title,
        m.movie_detail = row.movie_detail,
        m.imdbRating = toFloat(row.imdbRating)    FOREACH(director in split(row.director,'|')| 
        MERGE (p:Person {name:trim(director)}) 
        MERGE (p)-[:DIRECTED]->(m))     FOREACH (actor in split(row.actors,'|') | 
        MERGE (p:Person {name:trim(actor)}) 
        MERGE (p)-[:ACTED_IN] ->(m))     FOREACH (genre in split(row.genres,'|') | 
        MERGE (g:Genre {name:trim(genre)}) 
        MERGE (m)-[:IN_GENRE]->(g))     MERGE (l:location {name:trim(row.location)}) 
    MERGE (m)-[:WAS_TAKEN_IN]->(l)     MERGE (s: SimilarMovies {name:trim(row.similar_movie)}) 
    MERGE (m)-[:IS_SIMILAR_TO]->(s) 
    """ )

為了創建圖表,我們使用 Cypher 查詢語言,為此我們循環遍歷數據集行并創建:

  1. 具有標題、詳情和 IMDb 評級等屬性的電影節點。
  2. 導演節點通過關系鏈接到電影DIRECTED。
  3. 演員節點通過關系鏈接到電影ACTED_IN。
  4. 類型節點通過關系鏈接到電影IN_GENRE。
  5. 位置節點通過關系鏈接到電影WAS_TAKEN_IN。
  6. 類似電影節點通過關系鏈接到電影IS_SIMILAR_TO。


我們可以看到創建的圖數據庫的模式如下:

graph.refresh_schema ()
print(graph.schema )

圖模式的輸出

GraphCypherQAChain


現在我們已經設置了 Neo4j 數據庫,并使用所需的節點和關系對其進行了結構化,我們可以使用GraphCypherQAChain了。該鏈提供了一種直接有效的機制來與數據庫進行交互,它接收一個問題,將其轉換為 Cypher 查詢,執行查詢,并使用結果來回答原始問題。

為了確保 Cypher 查詢的準確性和高效性,使用足夠成熟的大語言模型 (LLM) 來理解和生成 Cypher 語法至關重要。選擇性能不足的 LLM 可能會導致:

為了獲得最佳效果,建議使用為此目的而接受過高級 LLM 培訓的人員。

例如,在我使用 LLaMA 3.1 (8B) 進行測試期間,我無法獲得達到標準的結果,但當我轉換到 LLaMA 3.3 (70B) 時,我的系統就能夠回答更復雜的查詢。

GraphCypherQAChain 的實現如下:

從langchain.chains導入GraphCypherQAChain 

# 我們可以將其稱為簡單代理,因為這里
# 我們只運行了兩行代碼
# 但它并不那么強大,正如我們將在問題 2 和問題 3 中看到的
那樣 # 問題變得更加復雜
"""
改進此過程的一種方法是使用
能夠生成準確 Cypher 查詢的更強大的語言模型。例如,
我最初使用 LLaMA 3.1 (8B),它很難回答兩個具體問題。
然而,升級到 LLaMA 3.3 (70B) 成功解決了第 1 個和第 3 個問題。
"""
 cypher_execution_chain = GraphCypherQAChain.from_llm(graph=graph,   # 這里它檢索圖 Schema
   llm=llm_model, 
   verbose= True ,   allow_dangerous_requests= True ) respond = cypher_execution_chain.invoke({ "query" : q_one}) 
print(響應)print(“\nLLM 響應:”,響應[ “結果” ])

雖然對于簡單的問題它可以表現良好,但一旦問題變得復雜,它就無法回答,如下所示:

q_two =  "1995 年上映的電影最常見的類型是什么?"
 response = cypher_execution_chain.invoke({ "query" : q_two}) 
print (response) 
print ( " \n LLM respond:" , respond[ "result" ])

GraphCypherQAChain 在回答更復雜的問題時會遇到困難,例如包含多個條件或間接關系的問題。這表明我們需要一個更強大、更智能的解決方案來處理此類情況。

在下一節“高級查詢”中,我們將看到如何通過一些附加的步驟使 QnA 系統更加健壯,例如從用戶輸入中提取實體等。這些步驟會逐步分解和處理復雜的查詢,從而能夠以更高的準確性和洞察力回答詳細或分層的問題。

四、方法2:高級查詢

正如我們上面所觀察到的,當用戶問題變得更加復雜時,例如涉及多個條件或間接關系的問題,CypherQAChain 很難提供答案。這是因為,雖然 CypherQAChain 理解數據庫架構,但它并不知道數據庫中的實際數據。例如,它可能識別“title”這樣的屬性,但不知道存在哪些電影名稱。這會導致查詢無法返回有用的結果。為了解決這個問題,我添加了一個映射層,將用戶輸入與實際數據庫值進行匹配,并利用這些值創建更精確的查詢,從而提高系統可靠性。

高級查詢QnA流程

它的工作原理如下:

檢測用戶輸入中的實體的第一步:對于所有用戶輸入查詢,它會提取諸如潛在人名、電影名稱和年份等實體。

從鍵入導入 列表:

# 從 langchain.chains.openai_functions 導入 create_structured_output_chain
從langchain.chains導入create_structured_output_runnable
從langchain_core.prompts導入ChatPromptTemplate 
# 從 langchain_core.pydantic_v1 導入 BaseModel、Field
從pydantic導入BaseModel、Field、field_validator 
class  Entities ( BaseModel ): 
    """識別有關實體的信息并
    從文本中提取人物、電影和年份實體。"""
     names: List [ str ] = Field( 
        ..., 
        descriptinotallow= "文本中出現的所有人物、年份或電影" , 
    ) 
entity_extractor_model = llm_model.with_structured_output(Entities)

從鍵入導入 列表:

步驟 2:將實體映射到數據庫值

一旦識別出實體,我們就會將其與實際數據庫值進行匹配。為此,我使用了 LangChain 文檔中的一個通用查詢,以檢索圖數據庫中節點(例如 Movie 或 Person)及其關系(例如 ACTED_IN、IN_GENRE)的詳細信息。此查詢提供了節點及其上下文的清晰、易讀的摘要。

該過程涉及三個關鍵步驟:

  1. 使用將檢測到的實體(電影、人物)插入查詢中$value。
  2. 映射關系和連接節點以呈現相關細節。
  3. 為每個匹配的節點生成結構化摘要,以提高答案的清晰度和深度。
match_query = """ 
MATCH (m:Movie|Person) 
WHERE m.title CONTAINS $value OR m.name CONTAINS $value OR m.released CONTAINS $value 
MATCH (m)-[r:ACTED_IN|IN_GENRE]-(t) 
WITH m, type(r) as type, collect(coalesce(t.name, t.title)) as names 
WITH m, type+": "+reduce(s="", n IN names | s + n + ", ") as types 
WITH m, collect(types) as contexts 
WITH m, "type:" + tags(m)[0] + "\ntitle: "+ coalesce(m.title, m.name) 
       + "\nyear: "+coalesce(m.released,"") +"\n" + 
       reduce(s="", c in contexts | s + substring(c, 0, size(c)-2) +"\n") as result 
RETURN result 
""" 
def  map_to_database ( values )-> str : 
    """
    將值映射到數據庫中的實體并返回映射信息。Args     : 
        values (list): 要映射到數據庫中實體的值列表。    返回:
        str: 一個字符串,包含每個值到數據庫中實體的映射信息。
    """
     result = "" 
    for entity in values.names: 
        response = graph.query(match_query, { "value" : entity}) 
        # print(response) 
        try : 
            for values in responding: 
                result += f" {entity} map to {values[ 'result' ]}   in database\n\n"  # 查詢數據庫以查找實體的映射
        except IndexError: 
            pass 
    return result

為了提高映射效率,我們使用了 Cypher 查詢,該查詢利用CONTAINS子句來查找匹配項。為了提高靈活性(例如解決拼寫錯誤),還可以使用模糊搜索或全文索引等技術。

步驟 3:生成上下文感知的 Cypher 查詢

使用提取的信息和數據庫模式,我們創建了一個準確且針對用戶問題定制的 Cypher 查詢。此自定義 Cypher 查詢確保其涵蓋數據庫中所有相關的屬性、關系和數據值。

從langchain_core.output_parsers導入StrOutputParser
從langchain_core.runnables導入RunnablePassthrough # 根據自然語言輸入生成 Cypher 語句
cypher_template = """基于下面的 Neo4j 圖模式,編寫一個 Cypher 查詢來回答用戶的問題:
{schema}
問題中的實體映射到以下數據庫值:
{entities_list}
問題:{question}
注意:請勿在回復中包含任何解釋或道歉。
請勿將回復包裹在任何反引號或其他任何內容中。
僅使用 Cypher 語句回復!

Cypher 查詢:""" cypher_prompt = ChatPromptTemplate.from_messages( 
    [ 
        ( 
            "system" , 
            "Given an input question, convert it to a Cypher query. No pre-amble.." , 
        ), 
        ( "human" , cypher_template), 
    ] ) 
# cypher_prompt.invoke({'schema'})
 chain = cypher_prompt | llm_model.bind(stop=[ "\nCypherResult:" ])| StrOutputParser()

步驟 4:根據數據庫結果生成答案

現在我們有了生成目標 Cypher 查詢的鏈,我們需要對數據庫執行 Cypher 查詢并將數據庫結果發送回 LLM 以生成最終答案。

from langchain.chains.graph_qa.cypher_utils import CypherQueryCorrector, Schema 
# 用于關系方向的 Cypher 驗證工具
Corrector_schema = [ 
    Schema(el[ "start" ], el[ "type" ], el[ "end" ]) 
    for el in graph.structured_schema.get( "relationships" ) 
] 
cypher_validation = CypherQueryCorrector(corrector_schema) # 根據數據庫結果生成自然語言響應
respond_template = """根據問題、Cypher 查詢和 Cypher 響應,編寫自然語言響應:
問題:{question} 
Cypher 查詢:{query} 
Cypher 響應:{response}""" respond_prompt = ChatPromptTemplate.from_messages( 
    [ 
        ( 
            "system" , 
            "給定輸入問題和 Cypher 響應,將其轉換為自然
            語言答案。給出答案以結構化的格式,讓用戶在視覺上更容易閱讀。" 
            "沒有前言。" , 
        ), 
        ( "human" , respond_template), 
    ] 
) chain_2 = respond_prompt | llm_model | StrOutputParser()

將上面提到的所有代碼組合在一個管道中,將得到問題 2 的結果,其中上述方法 1 失敗了,如下所示:

def  questions_asked(question_asked:str):
    question = question_asked 
    entities = entity_extractor_model.invoke(question)
    entities_list = map_to_database(entities)
    schema = graph.get_schema 
    chain = cypher_prompt | llm_model.bind(stop=[ “\nCypherResult:” ])| StrOutputParser() 
    cypher_query = chain.invoke({ 'schema' : schema, 
                 'entities_list' : entities_list,                  'question' : question})     print ( f"Cypher 查詢生成 : {cypher_query} " ) 
    print ( "=" * 40 ) 
    graph.query(cypher_query)     final_answer = chain_2.invoke({ 'response' : graph.query(cypher_query), 
                 'query' : cypher_query, 
                 'question' : question})     print ( f'問題的最終答案 : " {question} " --> \n {final_answer} ' ) questions_asked(q_two)


我們發現,這種方法成功地解答了 CypherQAChain 所欠缺的問題。這種額外的上下文信息使 LLM 能夠生成更精確的 Cypher 查詢,從而只檢索最相關的信息。

在我的實驗中,這種方法在所有測試案例中都完美地運行,盡管我可能錯過了一些邊緣情況。

到目前為止,我們重點介紹了 Cypher 查詢生成、數據檢索和答案生成。接下來,我們將深入探討如何使用 Neo4j GraphDB 構建一個基本的檢索增強生成 (RAG) 流程。

五、方法 3:使用 RAG 和 GraphDB(neo4j)

到目前為止,我們一直專注于結構化文本數據,但如果數據集中也包含非結構化文本呢?這正是 Neo4j 等知識圖譜真正擅長的地方。它們可以將結構化和非結構化數據以及 RAG 任務所需的非結構化數據嵌入存儲在一個地方。這簡化了向 LLM 提供檢索增強生成 (RAG) 所需上下文的過程。

GraphRAG 是一種利用知識圖譜增強上下文檢索的 RAG 方法。在本節中,我將演示如何使用 LangChain 和 Neo4j 實現 GraphRAG。我們將使用在預處理過程中,通過組合所有相關列,創建的附加列movie_details來構建 RAG 的向量索引。

當在 GraphRAG 中僅使用單個屬性來檢索所有相關信息時,建議使用我們確信能夠根據預期問題保存足夠所需信息的屬性。

步驟 1:對于 GraphRAG,第一步是創建所選字段的向量嵌入,如下所示:

我們將為“影片詳情”列創建向量嵌入,并將這些嵌入存儲在名為movie_detail_embeddings的新列中。這些嵌入隨后將用于填充GraphDB 中“影片詳情”的向量索引,從而實現 RAG 任務期間的高效檢索。

導入torch 
device = 'cuda'  if torch.cuda.is_available() else  'cpu'
 embeddings = HuggingFaceEmbeddings(model_name= "jinaai/jina-embeddings-v3" , 
  encode_kwargs = { 'normalize_embeddings' : True }, 
   model_kwargs = { 'device' : device, 'trust_remote_code' : 'True' ,}) 
def  embed_text ( text: str )-> List : 
    """
    使用指定的模型嵌入給定的文本。    參數:
        text (str): 要嵌入的文本。    返回:
        List: 包含文本嵌入的列表。
    """
     respond = embeddings.embed_query(text)     return respond embedding_list = [embed_text(i) for i in df[ "movie_detail" ]] 
embedding_list 
print ( "Number of向量:”,len(embedding_list))
print(“嵌入維度:”,len(embedding_list [ 0 ]))
embedding_list [ 0 ][: 5 ] df [ “movie_detail_embeddings” ] = embedding_list 
df.head(3)

步驟 2:在 neo4j DB 中創建空向量索引,稍后我們將使用步驟 1 中創建的嵌入來填充該索引。

我們將設置一個與嵌入模型具有相同維度的空向量索引,并指定用于檢索的相似度函數,如下所示。

# 這里將在 graphDB 中創建向量索引
# 目前它是空的
# 創建下面的輸入值只是為了確保不會再次執行此代碼來創建向量索引
value = input ( "Do You really want to perform this cell and create the Vector Index again ? y/n" ) 
if value == 'y' : 
    graph.query( """ 
      CREATE VECTOR INDEX movie_detail_embeddings IF NOT EXISTS // 如果不存在,則創建一個名為 'movie_tagline_embeddings' 的向量索引  
      FOR (m:Movie) ON (m.movie_detail_embeddings) // 索引 Movie 節點的 'taglineEmbedding' 屬性      OPTIONS { indexConfig: { // 設置索引選項
        `vector.dimensions`: 1024, // 指定向量空間的維數(1024 維)
        `vector.similarity_function`: 'cosine' // 指定相似度函數余弦相似度
      }}"""
     ) 
graph.query( """ 
SHOW VECTOR INDEXES // 檢索有關數據庫中所有向量索引的信息
""" )

步驟 3:使用步驟 1 中創建的向量嵌入填充向量索引

# 使用向量嵌入值填充數據庫中的向量索引
# 創建下面的輸入值作為安全措施,以防止意外重新執行此代碼,
# 這可能會無意中重新創建圖。
value = input(“您真的要執行此單元格并再次填充向量索引嗎?y / n”)
if value == 'y':
    for index,row in df.iterrows():
        movie_id = row [ 'movieId' ] 
        embedding = row [ 'movie_detail_embeddings' ] 
        graph.query(f“MATCH(m:Movie {{id:' {movie_id} '}})SET m.movie_detail_embeddings = {embedding} “)


現在,我們已經使用所需的向量索引和嵌入創建并更新了圖數據庫,現在我們可以使用以下代碼對輸入查詢執行向量搜索:

result = graph.query( """ 
with $question_embedding as question_embedding 
CALL db.index.vector.queryNodes(     'movie_detail_embeddings', 
    $top_k, 
    question_embedding 
    ) YIELD node AS movie, score 
RETURN movie.title, movie.movie_detail, score 
""" , 
params={ 
    "question_embedding" :question_embeddings, 
    "top_k" : 3
 }) import pprint 
pprint.pprint(result)

prompt = f"# 問題:\n {question} \n\n# 圖數據庫搜索結果:\n {result} "
 messages = [ 
    { "role" : "system" , "content" : str ( 
        "您將獲得用戶問題以及該問題在 Neo4j 圖數據庫上的搜索結果。給用戶正確的答案。"
     )}, 
    { "role" : "user" , "content" : prompt} 
] respond = llm_model.invoke(messages) print (response.content)

上述完整代碼可以在單個流水線中編譯,如下所示:

def  rag_pipeline ( question: str ): 
    question_embeddings = embed_text(question) 
    result = graph.query( """ 
with $question_embedding as question_embedding 
CALL db.index.vector.queryNodes( 
    'movie_detail_embeddings', 
    $top_k, 
    question_embedding 
    ) YIELD node AS movie, score 
RETURN movie.title, movie.tagline, score 
""" , 
params={ 
    "question_embedding" :question_embeddings, 
    "top_k" : 5
 }) 
    prompt = f"# Question:\n {question} \n\n# Graph DB 搜索結果:\n {result} "
     messages = [ 
    { "role" : "system" , "content" : str ( 
        "您將獲得用戶問題以及該問題在 Neo4j 圖數據庫中的搜索結果。請給用戶正確的答案。"
     )}, 
    { "role" : “用戶”,“內容”:提示} 
]response = llm_model.invoke(消息)return responseanswer = rag_pipeline(“關于冒險的電影都有哪些?”)

至此,我們已經探索了 GraphDB 上的檢索增強生成 (RAG),需要注意的是,雖然 RAG 和查詢生成本身都很強大,但在檢索相關內容方面各自都存在局限性。為了克服這些挑戰并構建更可靠的系統,可以采用一種混合方法:

  1. Agentic Workflows:允許代理根據用戶的問題在 RAG 或查詢生成之間動態選擇。
  2. 并行執行:同時運行 RAG 和查詢生成管道,組合它們的輸出,并向用戶提供統一的答案。

這種混合方法同時使用結構化和非結構化數據,從而創建一個能夠有效處理復雜查詢的強大系統。

六、小結

在這篇文章中,我分享了關于知識圖譜的學習成果,包括它們如何與大型語言模型 (LLM) 協同工作,以及如何使用它們構建結構化數據聊天機器人。我介紹了一些簡單的方法,例如 CypherQAChain,以及一些更高級的方法,例如用于處理非結構化數據的 GraphRAG。這些技術幫助我實現了一個醫療保健項目的自動化,節省了數小時的手動工作,并在幾分鐘內給出了準確的答案。

我力求簡潔,以便初學者也能通過知識圖譜輕松上手使用聊天機器人。通過嘗試這些方法和代理工作流,您可以創建一個高效靈活的系統,即使面對復雜的查詢也能輕松應對。

這只是使用結構化數據的一個例子。非結構化數據,例如 PDF、文檔甚至視頻中的文本,則是一個完全不同的挑戰。

責任編輯:龐桂玉 來源: 數據驅動智能
相關推薦

2025-10-09 00:00:00

Neo4jLLMs結構化

2018-05-16 08:26:39

知識圖譜Neo4j

2023-03-01 14:59:58

2024-08-08 08:31:32

SpringNeo4j優化

2024-09-30 13:11:09

2024-06-03 10:53:18

LLMRAGGraphRAG

2019-01-25 16:30:34

機器人機器學習人工智能

2025-06-04 08:21:28

2023-09-18 09:00:00

聊天機器人DeepInfraLangChain

2025-07-18 08:15:55

2022-07-03 10:23:06

機器人場景個性化

2022-07-05 06:42:01

聊天機器人人工智能

2023-05-04 08:00:00

機器人GPT4模型機器學習

2019-03-22 09:00:00

AI人工智能聊天機器人

2019-07-03 10:02:47

聊天機器人平臺機器人

2017-08-21 13:31:44

AI聊天機器人facebook

2017-03-28 12:21:21

機器人定義

2023-05-18 10:06:00

聊天機器人醫療保健

2024-11-01 14:52:24

2024-10-07 08:49:25

點贊
收藏

51CTO技術棧公眾號

中文字幕第17页| 日本一区二区在线视频| 欧美人妻一区二区| 另类在线视频| 色猫猫国产区一区二在线视频| 日韩尤物视频| 狠狠人妻久久久久久综合麻豆| 在线亚洲自拍| 日韩中文字幕第一页| 午夜福利三级理论电影| 三上悠亚激情av一区二区三区| 中文字幕一区二区三区乱码在线| 国产一区二区三区四区hd| 最新在线中文字幕| 影音先锋中文字幕一区二区| 在线观看91久久久久久| 精品无码人妻少妇久久久久久| 日本电影欧美片| 亚洲综合视频在线观看| 午夜欧美性电影| 香蕉视频免费在线看| 韩国三级中文字幕hd久久精品| 26uuu亚洲伊人春色| 日本黄色片免费观看| 伊人久久大香线蕉综合网站| 日韩美女在线视频| 一本岛在线视频| 蜜桃视频m3u8在线观看| 亚洲天堂2016| 视频一区二区三区免费观看| 亚洲av成人精品一区二区三区在线播放 | 超碰超碰在线| 久久精品一区蜜桃臀影院| 9a蜜桃久久久久久免费| 在线观看国产小视频| 性色一区二区| 性欧美在线看片a免费观看| 免费黄色激情视频| 欧美精品乱码| 国产一区二区三区在线| av2014天堂网| 成人三级毛片| 日韩午夜在线播放| 国产又粗又长又爽又黄的视频| 日韩成人av电影| 懂色av一区二区三区| 欧美一级黄色录像片| 老司机福利在线视频| 中文字幕不卡一区| 日韩欧美亚洲日产国| 黑人与亚洲人色ⅹvideos| 91在线国产福利| 精品亚洲欧美日韩| 五月激情婷婷综合| 99久久免费视频.com| 国产精品一级久久久| 亚洲奶汁xxxx哺乳期| 成人免费视频播放| 国产精品一区二区免费| 秋霞网一区二区| 成人精品gif动图一区| 国产精品初高中精品久久| 丰满人妻熟女aⅴ一区| 国产91富婆露脸刺激对白| 不卡日韩av| 熟妇人妻中文av无码| 99九九99九九九视频精品| 久久久久久久久久码影片| 特黄aaaaaaaaa真人毛片| www.在线成人| 欧美激情视频一区二区三区| 久久综合九色综合久| 中文字幕精品在线不卡| 亚洲一区二区三区精品视频 | 精品中文字幕乱| 欧美性猛交xxxxx少妇| 精品91视频| 全球成人中文在线| 91午夜交换视频| 国产99一区视频免费| 精品欧美一区二区三区久久久| 亚洲 小说区 图片区 都市| 国产婷婷色一区二区三区在线| 日韩精品伦理第一区| 久草资源在线| 午夜亚洲国产au精品一区二区| 久章草在线视频| 日韩第二十一页| 欧美成人video| 久久精品老司机| 国产精品国内免费一区二区三区| 色综合天天狠天天透天天伊人 | 欧美中文字幕一区| 日本网站在线看| 亚欧洲精品视频在线观看| 中文字幕在线成人| 九九九免费视频| 久久亚洲风情| 97人人澡人人爽| 男人的天堂在线| 亚洲另类色综合网站| heyzo国产| www.欧美| 亚洲人高潮女人毛茸茸| 免费在线观看一级片| 欧美一级专区| www.一区二区三区| av在线电影观看| 欧美日韩国产丝袜另类| 免费在线观看污网站| 国产成人一区二区三区影院| 九九久久综合网站| 亚洲国产无线乱码在线观看| 丁香亚洲综合激情啪啪综合| 亚洲一区三区| 国产精品迅雷| 精品黑人一区二区三区久久| 日韩一卡二卡在线观看| 欧美一级一区| 精品一区二区三区免费毛片| 午夜伦理在线视频| 欧美性极品少妇| 欧美大片免费播放器| 女主播福利一区| 国产欧美一区二区三区在线| 久草福利在线视频| 亚洲国产综合在线| 99视频在线观看视频| 北条麻妃国产九九九精品小说| 97视频在线观看免费| 亚洲国产欧美另类| 亚洲精品少妇30p| 午夜xxxxx| 日韩精品久久久久久久电影99爱| 日本午夜人人精品| 亚洲三区在线播放| 亚洲成人精品一区| 久久久国产精品久久久| 久久综合av| 国产精品丝袜视频| 888av在线| 在线观看91视频| 2019男人天堂| 人人爽香蕉精品| 五月天丁香综合久久国产| 欧美性suv| 亚洲网站在线看| 天堂av免费在线观看| 国产午夜一区二区三区| 99视频精品免费| 精品国产a一区二区三区v免费| 青草成人免费视频| 男人的天堂av高清在线| 色妞www精品视频| 国产又黄又粗的视频| 奇米色一区二区三区四区| 亚洲视频小说| 亚洲精品777| 欧美人交a欧美精品| 成人小说亚洲一区二区三区| 亚洲国产精品视频| 最近中文字幕无免费| 一区二区三区国产在线| 久久99欧美| 精品3atv在线视频| 在线看欧美日韩| 99精品人妻无码专区在线视频区| 亚洲欧洲成人自拍| 337p日本欧洲亚洲大胆张筱雨| 午夜激情一区| 精品免费视频123区| 欧美黄色网页| 久久精品一偷一偷国产| www香蕉视频| 色综合天天综合在线视频| 亚洲最大成人综合网| 激情欧美一区二区| 久久久久久久9| 在线观看欧美理论a影院| 国产精品专区一| 欧美卡一卡二| 亚洲区中文字幕| 国产欧美日韩成人| 精品福利在线视频| 国产黄色录像视频| 国产成人三级在线观看| 男人靠女人免费视频网站| 热久久天天拍国产| 国产精品果冻传媒潘| 激情亚洲影院在线观看| 美女精品视频一区| 欧美色图另类| 3atv一区二区三区| 日韩不卡在线播放| 中文字幕一区二区三区在线不卡 | 日韩中文字幕在线观看| www.好吊色| 在线视频国内一区二区| 国产中文字字幕乱码无限| 国产人妖乱国产精品人妖| 激情av中文字幕| 日韩av网站在线观看| 成年人看的毛片| 久久神马影院| 麻豆av一区二区三区久久| 国产一精品一av一免费爽爽| 国产成人精品电影久久久| 天堂成人av| 中文字幕国产精品| 性xxxxbbbb| 日韩一区二区影院| 亚洲天堂视频网| 日韩欧亚中文在线| 日韩xxxxxxxxx| 亚洲桃色在线一区| 538精品视频| 久久午夜老司机| 国产性生活毛片| 国产一区视频在线看| 日韩av手机版| 美女久久网站| 大j8黑人w巨大888a片| 国内精品福利| 久操手机在线视频| 中文字幕一区二区av| 亚洲精品一区二区三区av| 五月综合久久| 国产伦精品一区二区三区照片 | 视频在线在亚洲| 日韩一级性生活片| 黄色亚洲精品| www.国产亚洲| 亚洲国产精品久久久天堂| 亚洲精品成人自拍| 经典一区二区| 欧洲精品码一区二区三区免费看| 国产女人18毛片水真多18精品| yy111111少妇影院日韩夜片| 2019中文亚洲字幕| 国产中文字幕亚洲| 久久不卡日韩美女| 国产日韩欧美影视| 另类一区二区| 成人av在线网址| 99视频这里有精品| 成人亚洲欧美一区二区三区| 欧美亚洲黄色| 国产主播欧美精品| 日韩精品成人| 动漫3d精品一区二区三区| 亚洲综合色婷婷在线观看| 官网99热精品| 伦理一区二区| 欧美大陆一区二区| 久操成人av| 日韩欧美一区二区三区久久婷婷| 成人在线国产| 中文字幕在线亚洲精品| 小小影院久久| 精品视频在线观看一区二区| 伊人久久亚洲热| 国内自拍在线观看| 日韩av在线播放中文字幕| 天天爽夜夜爽一区二区三区| 韩国精品一区二区| 潘金莲一级淫片aaaaa| 粉嫩绯色av一区二区在线观看| yjizz视频| 久久美女艺术照精彩视频福利播放| 熟女少妇一区二区三区| 国产精品免费人成网站| 五月天av网站| 黑人精品xxx一区一二区| 久久久久久无码午夜精品直播| 欧美视频一区在线| а√天堂资源在线| 日韩成人xxxx| 91视频在线观看| 欧美大奶子在线| 中老年在线免费视频| 国产精品亚洲аv天堂网| 免费一级欧美片在线观看网站| 精品国产日本| 手机在线一区二区三区| 国产精品三级一区二区| 久久午夜av| 一本岛在线视频| kk眼镜猥琐国模调教系列一区二区 | 国内少妇毛片视频| 蜜乳av另类精品一区二区| 视频免费1区二区三区| 91亚洲精华国产精华精华液| а天堂中文在线资源| 亚洲高清不卡在线| 中文字幕免费视频观看| 欧美成人性战久久| 二区在线观看| 国内精品久久久久久| 久久青草视频| 久久99精品久久久久久水蜜桃| 国产精品久久久久久久久久10秀| av之家在线观看| 国产麻豆成人精品| 国产在线观看h| 亚洲一区二区三区四区在线观看 | av免费在线视| 成人av番号网| 欧洲grand老妇人| 人人干视频在线| 国产一区不卡视频| www.黄色在线| 精品久久久久久国产| av手机免费看| 日韩在线国产精品| 在线日韩影院| 国内视频一区| 亚洲欧美文学| 亚洲精品在线视频播放| 国产亚洲精久久久久久| 中文字幕在线观看免费视频| 日韩一级片网址| 麻豆网站在线免费观看| 国产成人精品免费久久久久| 精品网站aaa| 国产成人亚洲综合无码| 九九**精品视频免费播放| 337人体粉嫩噜噜噜| 色综合天天综合在线视频| 日本xxxxwww| 久久久人成影片一区二区三区观看 | 国产女人在线视频| 8x拔播拔播x8国产精品| 都市激情亚洲| 欧美一级免费播放| 福利一区二区在线观看| 欧美黄色免费看| 91精品国产黑色紧身裤美女| 欧美精品日韩少妇| 成人黄色片在线| 偷偷www综合久久久久久久| 三上悠亚在线一区二区| 国产精品嫩草99a| 中文字幕免费播放| 影音先锋日韩有码| 福利一区二区三区视频在线观看| 色姑娘综合网| 蜜臀久久99精品久久久久久9| 精品无码一区二区三区| 欧美性xxxxxx| 成全电影播放在线观看国语| 国产精品日韩一区| 婷婷亚洲最大| 污免费在线观看| 亚洲成人手机在线| 日韩中文字幕影院| 欧美在线观看一区二区三区| 亚洲人成网77777色在线播放| 免费观看成人网| 国产精品视频一二三区| 97精品人妻一区二区三区在线| 久久夜色撩人精品| 亚洲开心激情| 精品国产一区三区| 久久精品一区蜜桃臀影院| 成人黄色片在线观看| 久久av红桃一区二区小说| 日韩中文字幕| ww国产内射精品后入国产| 久久蜜桃一区二区| 国产又粗又长又黄| 欧美激情性做爰免费视频| 欧美丝袜足交| 日韩肉感妇bbwbbwbbw| 亚洲精品视频在线| 手机在线观看毛片| 国产精品aaaa| 综合激情视频| 熟妇人妻久久中文字幕| 欧洲视频一区二区| 国产精品久久久久久福利| 国产原创精品| 奇米在线7777在线精品| 免费一级a毛片夜夜看| 亚洲精品小视频| 亚洲欧美在线人成swag| av高清在线免费观看| 中文字幕欧美日本乱码一线二线 | 全球最大av网站久久| 国产精品无码乱伦| 26uuu国产一区二区三区| 97在线公开视频| 91av视频导航| 婷婷激情综合| 一级黄色片大全| 日韩视频一区二区| 欧美日韩精品免费观看视欧美高清免费大片| 中文字幕av日韩精品| 91在线免费播放| 国产xxxxxx| 国产精品入口夜色视频大尺度|