精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

久久视频在线看| 在线视频欧美精品| 国产精品一区二区三区免费| 精品少妇一二三区| 色爱av综合网| 欧美日韩一区在线观看| 永久免费看av| 欧美白人做受xxxx视频| 久久精品免费看| 欧美高清视频在线观看| 日本高清www| 成人免费91| 一本久久a久久精品亚洲| 杨幂一区欧美专区| 四季av日韩精品一区| 免费高清在线视频一区·| 欧美日韩国产91| 人与嘼交av免费| 国产精品中文字幕制服诱惑| 欧美裸体一区二区三区| 久久综合九色综合88i| 3d成人动漫在线| 91女神在线视频| 91成人免费视频| 又骚又黄的视频| 欧美亚洲一级| 欧美精品精品精品精品免费| 天堂а√在线中文在线鲁大师| 图片婷婷一区| 欧美r级在线观看| 国产精品久久久久久9999| 色多多在线观看| 亚洲电影在线免费观看| 在线视频不卡一区二区三区| 欧洲天堂在线观看| 成人视屏免费看| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 在线观看v片| 亚洲一卡二卡三卡四卡| 亚洲日本一区二区三区在线不卡| 欧美 中文字幕| 国产精品99久| 成人国产精品色哟哟| 久久久精品毛片| 国产精品一二| 97超级碰在线看视频免费在线看| 久久免费视频99| 中文字幕一区二区三区久久网站| 中文字幕亚洲一区在线观看| 亚洲精品午夜视频| 免费看av成人| 亚洲精品自在久久| 欧美大片免费播放器| 岛国成人av| 亚洲国产一区二区三区在线观看| 久久久久久久久久久久国产精品| 日韩亚洲精品在线观看| 欧美变态凌虐bdsm| 秋霞午夜鲁丝一区二区| 国产精品亚洲四区在线观看 | 成人午夜激情av| 影视一区二区三区| 欧美伊人久久久久久午夜久久久久| aaa毛片在线观看| 成人做爰视频www网站小优视频| 欧美色欧美亚洲高清在线视频| 精品少妇人妻av免费久久洗澡| 黄色漫画在线免费看| 欧美日韩国产精品专区| 成人小视频在线看| 91福利精品在线观看| 欧美日韩精品免费| 超碰在线超碰在线| av综合网址| 亚洲美女精品成人在线视频| 人妻一区二区视频| 欧美顶级大胆免费视频| 久久中文字幕在线| 久久久久黄色片| 99精品免费| 国产精品6699| 国产伦理吴梦梦伦理| 国产精品99久久久| 久久青青草原一区二区| 黄色影院在线播放| 亚洲天堂2016| 国产午夜福利视频在线观看| 欧美123区| 日韩欧美一级二级三级| 波多野结衣影院| 欧美综合久久| 欧美激情一区二区久久久| 在线观看黄网站| 久久激情五月婷婷| 国产丝袜不卡| 91欧美在线视频| 亚洲一区在线观看免费 | 精品视频一区二区三区四区五区| 欧美猛男gaygay网站| 亚洲v在线观看| 欧洲激情综合| 国内免费精品永久在线视频| 欧美在线视频精品| 成人高清av在线| 亚洲国产欧美日韩| 两个人看的在线视频www| 在线观看视频一区二区| 乱码一区二区三区| 欧美少妇性xxxx| 97激碰免费视频| 6—12呦国产精品| 91免费看片在线观看| 宅男一区二区三区| 国产欧美一区二区三区精品酒店| 欧美一区二区啪啪| japanese中文字幕| 亚洲韩日在线| 97netav| 午夜在线视频| 欧美日韩激情小视频| 亚洲第一色av| 成人中文在线| 欧美在线视频一区| 殴美一级特黄aaaaaa| 中文字幕视频一区| 成人免费毛片播放| 色老板在线视频一区二区| 色综合色综合网色综合| 最新国产中文字幕| 久久久蜜臀国产一区二区| 欧美乱做爰xxxⅹ久久久| 亚洲久草在线| 中文字幕国产精品| 超碰在线观看91| 92国产精品观看| 欧美一级视频在线播放| 日本亚洲视频| 欧美成人免费小视频| 国产精品一区二区黑人巨大| 中文字幕一区二区三| 久久九九国产视频| 亚洲瘦老头同性70tv| 97视频免费看| 天天操天天操天天| 亚洲成人自拍网| 国产精品麻豆入口| 亚洲另类视频| 国产综合 伊人色| 丰满大乳少妇在线观看网站| 精品免费视频一区二区| 久久97人妻无码一区二区三区| 国产在线乱码一区二区三区| 亚洲一区二区三区精品动漫| 久久免费影院| 日韩在线高清视频| 在线免费看91| 亚洲欧洲日韩av| 欧美又黄又嫩大片a级| 婷婷亚洲图片| 97自拍视频| 999福利在线视频| 国产丝袜精品第一页| 三级视频在线观看| 日本一区二区三区在线观看| 国产精品区在线| 在线黄色免费看| 在线日韩成人| 97精品国产91久久久久久| 无码国产精品一区二区免费16| 亚洲国产精品自拍| 欧美 变态 另类 人妖| 性欧美videos另类喷潮| 日韩精品av一区二区三区| 成人午夜在线| 欧美超级乱淫片喷水| 手机看片一区二区三区| 色综合咪咪久久| 日本二区三区视频| 国产精品一区二区黑丝| 亚洲精品蜜桃久久久久久| 丝袜久久网站| 国产中文日韩欧美| 欧美激情成人动漫| 日韩精品丝袜在线| 怡红院男人天堂| 亚洲一卡二卡三卡四卡无卡久久| 美国黄色一级毛片| 日本成人在线视频网站| 国产精品一区在线免费观看| 老牛国内精品亚洲成av人片| 国产精品九九九| 日本动漫同人动漫在线观看| 精品亚洲aⅴ在线观看| 成人中心免费视频| 1区2区3区在线观看| 日韩三级中文字幕| 在线观看日韩中文字幕| 国产精品久久久久精k8| 亚洲美女在线播放| 奇米影视一区二区三区小说| 黄色片免费在线观看视频| 色吊丝一区二区| 亚洲一区二区日本| 91精品韩国| 久久久久久久97| 色大18成网站www在线观看| 欧美精品一区视频| 亚洲影院一区二区三区| 五月综合激情日本mⅴ| 顶级黑人搡bbw搡bbbb搡| av中文字幕在线不卡| 欧美激情国内自拍| 性色av一区二区怡红| 免费在线黄网站| 不卡中文一二三区| 国内一区在线| 三级欧美日韩| 国产一区二区丝袜| 韩国成人漫画| 久久理论片午夜琪琪电影网| 毛片免费不卡| 亚洲少妇中文在线| 色噜噜在线播放| 日韩美女主播在线视频一区二区三区| 日韩国产成人在线| 精品日韩视频在线观看| 免费在线观看黄视频| 中文久久乱码一区二区| 国产精品毛片一区二区| 99久久777色| 最新日本中文字幕| 国产一区二区三区四区五区入口| 日本www.色| 久久精品一本| 人妻少妇被粗大爽9797pw| 亚洲视频狠狠| 国产精品免费看久久久无码| 俄罗斯毛片基地| 久久国产精品色婷婷| 欧美精品一区二区三区免费播放| 亚洲精选在线| 男女啪啪免费视频网站| 欧美另类女人| 777久久精品一区二区三区无码| 91精品精品| 在线观看免费黄色片| 93在线视频精品免费观看| 日韩精品福利视频| 欧美理论在线播放| 欧美日韩高清免费| 亚洲精品动态| 麻豆成人av| 精品国产91乱码一区二区三区四区 | 蜜臀99久久精品久久久久小说| 日韩欧美国产骚| 精品人妻一区二区三区免费看| 五月激情综合婷婷| 在线观看黄网站| 色欧美88888久久久久久影院| 亚洲欧美一区二区三区在线观看| 欧美日韩一二三四五区| 日韩免费视频一区二区视频在线观看| 姬川优奈aav一区二区| 四虎成人永久免费视频| 日本二三区不卡| 黄色av一区二区| 欧美日韩大陆一区二区| 国产美女明星三级做爰| 欧美成人一区二区三区| 欧美性受xxxx狂喷水| 国产婷婷色综合av蜜臀av| 国产对白叫床清晰在线播放| 中文欧美日本在线资源| 在线午夜影院| 97精品视频在线观看| 芒果视频成人app| 国产精品视频一区国模私拍| 成人精品视频在线观看| 国产亚洲精品久久飘花| 国产一区二区三区91| 五月天av影院| 日韩视频在线一区二区三区| 欧美综合在线观看视频| 国内成人精品2018免费看| 成人做爰69片免费| 久久影视一区二区| 亚洲综合社区网| 搡老岳熟女国产熟妇| 亚洲精品永久免费| 日本视频在线免费观看| 欧美精品www在线观看| 亚洲国产欧美日本视频| 96pao国产成视频永久免费| 久久97精品| 一区二区三区四区视频在线 | 欧美牲交a欧美牲交| 免费在线视频一区| 亚洲欧美日韩色| 中文字幕第一页久久| 国产一级二级三级| 欧洲精品在线观看| www.av网站| 一区二区三区国产视频| 手机av免费在线| 国产精品久久久91| 激情小说亚洲图片| 在线观看成人一级片| 一区二区三区成人精品| 激情成人在线观看| 国产欧美日韩不卡免费| 国产精品99精品| 制服.丝袜.亚洲.另类.中文| 欧美新色视频| 久久久久久久久久久网站| 欧美男女视频| 日本成人三级电影网站| 精品动漫3d一区二区三区免费| 国产精品一区二区羞羞答答| 99在线精品观看| 人妻人人澡人人添人人爽| 欧美在线你懂的| 神马久久精品| 欧美精品aaa| 国产一区二区三区免费观看在线| 日本高清久久一区二区三区| 亚洲一区不卡| 黄色国产在线视频| 一区二区三区丝袜| 国产又粗又猛又爽| 国产一区二区三区在线免费观看 | 2023国产精品久久久精品双| 国产又黄又猛又粗| 久久精品欧美日韩精品| 99精品视频99| 亚洲国产中文字幕在线观看 | 国产精品91久久久久久| 欧美一区自拍| 久久黄色片视频| 成人教育av在线| 日产欧产va高清| 国产亚洲午夜高清国产拍精品 | yjizz视频| 一区二区三区在线免费| 国产伦一区二区| 美女少妇精品视频| 精品网站999| 91成人在线视频观看| 国产裸体歌舞团一区二区| 91麻豆免费视频网站| 日韩一区二区在线观看| 黄色片网站在线观看| 91久久久精品| 欧美91精品| 亚洲精品久久一区二区三区777 | 麻豆一区在线| 国产一级片91| 成人黄页在线观看| 日本中文字幕在线免费观看| 日韩av在线免费观看一区| 咪咪网在线视频| 欧美一区国产一区| 日本中文字幕一区二区有限公司| 先锋影音av在线| 欧美日韩成人一区| 国产区在线观看| 成人自拍网站| 国产一区二区三区的电影 | 日韩一区欧美小说| 国产婷婷在线视频| 欧美激情综合色| 免费精品国产的网站免费观看| 成人午夜激情av| 亚洲精品成人在线| 四虎影院在线域名免费观看| 国产精品高潮粉嫩av| 自产国语精品视频| 一级黄色免费视频| 91豆麻精品91久久久久久| 天堂аⅴ在线地址8| 91精品久久久久久蜜桃| 中文日韩在线| 国产成人在线网址| 日韩视频一区二区三区 | 狠狠干狠狠久久| 又爽又大又黄a级毛片在线视频| 亚洲综合在线播放| 香蕉视频成人在线观看| 女人裸体性做爰全过| 精品国产污污免费网站入口 | 老司机午夜在线| 国新精品乱码一区二区三区18| 久久天堂成人| 国产一区二区三区在线视频观看| 日韩精品免费视频| 久久69成人| 欧美在线视频网| aaa大片在线观看| 亚洲自拍在线观看| 久久最新视频| 精品99在线观看|