LangChain是如何實現RAG多輪問答的

目錄

  • 引言
  • 一、LangChain實現RAG多輪問答核心機制
      • 1. 對話歷史管理(Memory)
      • 2. 問題重寫(Query Rewriting)
      • 3. 檢索增強生成(RAG Core)
      • 4. 鏈式工作流(Chain)
  • 二、關鍵設計特點
  • 三、完整示例代碼
  • 四、優化建議

引言

小馬之所以寫今天這篇文章是因為在上一篇文章《多輪問答與指代消解》中的第一章節有提到“LangChain是怎么實現的多輪問答”,但很顯然沒有提到它在RAG下是怎么實現的多輪問答,畢竟這兩者還是有區別的。前一篇文章剛好提到自己實現RAG下的多輪問答要怎么實現,唯獨沒有提到LangChain在RAG下是怎么實現的多輪。
前篇文章中提到的MultiQueryRetriever小馬已經在文中聲明,這個并不是為了解決RAG多輪的機制。

慶幸的是,我們回過頭來看LangChain實現RAG多輪問答的方式其實和我們自己實現的思路不能說一模一樣,簡直是毫無區別。只是LangChain封裝了組件,我們直接調用就能實現了,省去了自己寫工程代碼來實現的過程。接下來我們有必要一起看下的,不過看過上一篇的同學其實看這篇文章就很好理解了。
在這里插入圖片描述

一、LangChain實現RAG多輪問答核心機制

在 LangChain 中實現 RAG(Retrieval-Augmented Generation)的多輪問答主要通過以下核心機制完成,確保對話歷史被有效利用:

1. 對話歷史管理(Memory)

LangChain 使用 Memory 組件 存儲和傳遞上下文:

  • ConversationBufferMemory
    存儲完整的原始對話歷史(用戶輸入 + AI 響應)。
  • ConversationSummaryMemory
    用 LLM 壓縮歷史為摘要,避免 token 超限。
  • ConversationBufferWindowMemory
    僅保留最近 K 輪對話,控制上下文長度。
from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory(memory_key="chat_history",  # 存儲對話的鍵名return_messages=True        # 返回消息列表而非字符串
)

2. 問題重寫(Query Rewriting)

將當前問題結合歷史重寫為獨立查詢,使檢索更準確:

  • ConversationalRetrievalChain 內置 condense_question 步驟:
    1. 輸入:當前問題 + 對話歷史
    2. 輸出:重寫后的獨立問題(如將代詞替換為具體實體)
from langchain.chains import ConversationalRetrievalChainqa_chain = ConversationalRetrievalChain.from_llm(llm=chat_model,             # 如 ChatOpenAIretriever=vectorstore.as_retriever(),  # 向量檢索器memory=memory,condense_question_llm=condense_model  # 可選:專用重寫模型
)

3. 檢索增強生成(RAG Core)

多輪流程如下:

  1. 檢索上下文
    用重寫后的查詢從向量庫檢索相關文檔片段。
  2. 組裝提示
    將以下內容組合為最終提示:
    • 檢索到的上下文
    • 對話歷史(原始或摘要)
    • 當前問題
  3. 生成答案
    LLM 基于完整上下文生成連貫回復。
提示詞示例:
[檢索到的文檔]
對話歷史:用戶: 量子計算是什么?AI: 量子計算利用量子比特...
當前問題:它有什么優勢?
最終答案:量子計算的優勢包括...

4. 鏈式工作流(Chain)

ConversationalRetrievalChain 自動處理整個流程:

# 第一輪
result = qa_chain({"question": "什么是RAG?"})
print(result["answer"])# 第二輪(自動攜帶歷史)
result = qa_chain({"question": "它如何解決幻覺問題?"})  # "它"指代RAG
print(result["answer"])

二、關鍵設計特點

組件作用
Memory持久化歷史對話,支持多種存儲策略(原始/摘要/滑動窗口)
Query Rewriting解決指代消解(如“它”指代上文的 RAG),提升檢索準確性
Contextual Prompt動態組裝提示,包含歷史 + 檢索結果 + 當前問題
檢索器優化支持自定義檢索器(如過濾元數據、調整相似度閾值)

三、完整示例代碼

from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain# 初始化向量庫和模型
vectorstore = FAISS.load_local("rag_vector_db", OpenAIEmbeddings())
llm = ChatOpenAI(model="gpt-4-turbo")
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)# 構建鏈
qa_chain = ConversationalRetrievalChain.from_llm(llm=llm,retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),memory=memory
)# 模擬多輪對話
questions = ["LangChain是什么?","它的核心組件有哪些?",  # "它" 指代LangChain"如何用RAG實現多輪對話?"
]
for q in questions:result = qa_chain.invoke({"question": q})print(f"問題: {q}\n答案: {result['answer']}\n")

四、優化建議

  1. 歷史摘要:長對話時使用 ConversationSummaryMemory 避免 token 超限。
  2. 重寫模型:用輕量級模型(如 GPT-3.5)專門處理問題重寫,降低成本。
  3. 檢索過濾:基于元數據(如對話 ID)過濾無關文檔。
  4. 提示工程:定制提示模板明確區分歷史/當前問題/檢索內容。

通過組合 Memory 管理智能查詢重寫上下文感知的 RAG 流程,LangChain 有效實現了多輪問答的連貫性與準確性。

本篇文章旨在補充上一篇文章的內容,建議結合上一篇文章食用,口感效果更加。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918648.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918648.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918648.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DAY 44 預訓練模型

知識點回顧: 預訓練的概念常見的分類預訓練模型圖像預訓練模型的發展史預訓練的策略預訓練代碼實戰:resnet18 一、預訓練的概念 我們之前在訓練中發現,準確率最開始隨著epoch的增加而增加。隨著循環的更新,參數在不斷發生更新。 所…

Java Stream API 中常用方法復習及項目實戰示例

在最近的練手項目中,對于stream流的操作愈加頻繁,我也越來越感覺stream流在處理數據是的干凈利落,因此寫博客用來記錄最近常用的方法以便于未來的復習。map() 方法map()是一個中間操作(intermediate operation)&#x…

從零開始手搓一個GPT大語言模型:從理論到實踐的完整指南(一)

現在人工智能飛速發展時代,LLM絕對可以算是人工智能領域得一顆明珠,也是現在許多AI項目落地得必不可少得一個模塊,可以說,不管你之前得研究領域是AI得哪個方向,現在都需要會一些LLM基礎,在這個系列&#xf…

Redis ubuntu下載Redis的C++客戶端

1. 安裝 redis-plus-plus C 操作 Redis 的庫有很多,這里選擇使用 redis-plus-plus,這個庫的功能強大,使用簡單。 Github 地址:GitHub - sewenew/redis-plus-plus: Redis client written in C 訪問不了Github 地址的可以使用Ste…

nm命令和nm -D命令參數

出現這種差異的原因在于:動態庫中的符號分為兩種類型: 常規符號表(regular symbol table):通常用于靜態鏈接和調試,默認不包含在動態庫中(除非顯式保留)。動態符號表(dyn…

Windows下cuda的安裝和配置

今天開始做一個cuda教程。由于本人主要在windows下使用visual studio進行開發,因此這里講一下windows下的cuda開發環境。 下載cuda_toolkit 從網站https://developer.nvidia.com/cuda-toolkit中下載,先選擇Download Now,然后跳轉到如下頁面&#xff1a…

【代碼隨想錄day 19】 力扣 450.刪除二叉搜索樹中的節點

視頻講解:https://www.bilibili.com/video/BV1tP41177us/?share_sourcecopy_web&vd_sourcea935eaede74a204ec74fd041b917810c 文檔講解:https://programmercarl.com/0450.%E5%88%A0%E9%99%A4%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%A…

智慧養老丨實用科普+避坑指南:科技如何讓晚年生活更安全舒適?

隨著老齡化社會的到來,智慧養老產品逐漸成為改善老年人生活質量的重要工具。從智能手表到便攜洗浴機,科技正為老年人的健康、安全與生活便利提供創新解決方案。我們這次主要介紹四類典型智慧養老產品,結合真實體驗給出選購建議,并…

系統垃圾清理批處理腳本 (BAT)

系統垃圾清理批處理腳本 (BAT) 以下是一個Windows系統垃圾清理的批處理腳本,它可以清理常見的系統臨時文件、緩存和日志等: echo off title 系統垃圾清理工具 color 0a echo. echo 正在清理系統垃圾文件,請稍候... echo.:: 清理臨時文件 echo…

Terraform的零基礎學習教程

一、Terraform 是什么? Terraform 是由 HashiCorp 開發的開源工具,用于自動化管理云基礎設施(如 AWS、Azure、GCP 等)。 核心特點: 基礎設施即代碼(IaC):用代碼定義和管理資源。跨…

429. N 叉樹的層序遍歷(中等)題解

題目描述給定一個 N 叉樹,返回其節點值的層序遍歷。(即從左到右,逐層遍歷)。樹的序列化輸入是用層序遍歷,每組子節點都由 null 值分隔(參見示例)。示例 1:輸入:root [1,…

Java 課程,每天解讀一個簡單Java之題目:輸入一行字符,分別統計出其中英文字母、空格、數字和其它字符的個數。

package ytr250813;import java.io.IOException;public class CharacterCounter {public static void main(String[] args) throws IOException {// 初始化計數器變量int letterCount 0; // 英文字母計數器int spaceCount 0; // 空格計數器int digitCount 0; // 數字計數器i…

GitLab CI + Docker 自動構建前端項目并部署 — 完整流程文檔

一、環境準備1. 服務器準備一臺Linux服務器(CentOS/Ubuntu皆可),推薦至少4核8GB內存已安裝 Docker(及 Docker 服務已啟動)已安裝 GitLab Runner2. 服務器上安裝 Docker (如果沒裝)# CentOS9以下…

LCP 17. 速算機器人

目錄 題目鏈接: 題目: 解題思路: 代碼: 總結: 題目鏈接: LCP 17. 速算機器人 - 力扣(LeetCode) 題目: # LCP 17. 速算機器人 小扣在秋日市集發現了一款速算機器人。…

Spring cloud集成ElastictJob分布式定時任務完整攻略(含snakeyaml報錯處理方法)

ElasticJob 是一款輕量級、可擴展的分布式定時任務解決方案,基于 Quartz 二次開發,支持任務分片、失效轉移、任務追蹤等功能,非常適合在 Spring Cloud 微服務場景中使用。我將帶你完成 Spring Cloud 集成 ElasticJob 的全過程,并分…

了解 Linux 中的 /usr 目錄以及 bin、sbin 和 lib 的演變

Linux 文件系統層次結構是一個復雜且引人入勝的體系,其根源深植于類 Unix 操作系統的歷史之中。在這一結構的核心,/usr 目錄是一個至關重要的組成部分,隨著時間的推移,它經歷了顯著的演變。與此同時,/bin、/sbin、/lib…

高級IO(五種IO模型介紹)

文章目錄一、IO為什么慢?一、阻塞IO二、非阻塞IO三、信號驅動IO四、IO多路復用五、異步IO一、IO為什么慢? IO操作往往都是和外設交互,比如鍵盤、鼠標、打印機、磁盤。而最常見的就是內存與磁盤的交互,要知道磁盤是機械設備&#…

第十二節:粒子系統:海量點渲染

第十二節:粒子系統:海量點渲染 引言 粒子系統是創造動態視覺效果的神器,從漫天繁星到熊熊火焰,從魔法特效到數據可視化,都離不開粒子技術。Three.js提供了強大的粒子渲染能力,可輕松處理百萬級粒子。本文將…

LeetCode Day5 -- 二叉樹

目錄 1. 啥時候用二叉樹? (1)典型問題 (2)核心思路 2. BFS、DFS、BST 2.1 廣度優先搜索BFS (1)適用任務 (2)解決思路??:使用隊列逐層遍歷 2.2 深度…

<c1:C1DateTimePicker的日期時間控件,控制日期可以修改,時間不能修改,另外控制開始時間的最大值比結束時間小一天

兩個時間控件 <c1:C1DateTimePicker Width"170" EditMode"DateTime" CustomDateFormat"yyyy-MM-dd" CustomTimeFormat"HH:mm:ss" Style"{StaticResource ListSearch-DateTimePicker}" x:Name"dateTimePicker"…