基于LangChain構建高效RAG問答系統:向量檢索與LLM集成實戰

基于LangChain構建高效RAG問答系統:向量檢索與LLM集成實戰

在本文中,我將詳細介紹如何使用LangChain框架構建一個完整的RAG(檢索增強生成)問答系統。通過向量檢索獲取相關上下文,并結合大語言模型,我們能夠構建出一個能夠基于特定知識庫回答問題的智能系統。

1. 基礎設置與向量檢索準備

首先,我們需要導入必要的庫并設置向量存儲訪問:

import os
from dotenv import load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_redis import RedisConfig, RedisVectorStore# 加載環境變量
load_dotenv()# 定義查詢問題
query = "我的生日是幾月幾日?"# 初始化阿里云百煉平臺的向量模型
embedding = DashScopeEmbeddings(model="text-embedding-v3", dashscope_api_key=os.getenv("ALY_EMBADING_KEY"))
redis_url = "redis://localhost:6379"  # Redis數據庫的連接地址# 配置Redis向量存儲
config = RedisConfig(index_name="my_index2",  # 索引名稱redis_url=redis_url,  # Redis數據庫的連接地址
)# 創建向量存儲實例和檢索器
vector_store = RedisVectorStore(embedding, config=config)
retriever = vector_store.as_retriever()

這部分代碼完成了以下工作:

  • 加載環境變量以安全地使用API密鑰
  • 初始化阿里云文本嵌入模型
  • 配置Redis向量數據庫連接
  • 創建檢索器(retriever),用于執行向量相似度檢索

2. 執行向量檢索

接下來,我們使用檢索器從向量庫中獲取與查詢相關的文本段落:

# 執行檢索,獲取相關文本段落
retriever_segments = retriever.invoke(query, k=5)
print(retriever_segments)# 將檢索結果整合
text = []
for segment in retriever_segments:text.append(segment.page_content)

在這段代碼中:

  • retriever.invoke(query, k=5) 檢索與查詢語義最相關的5個文本段落
  • 我們將檢索到的每個段落的文本內容提取并整合到一個列表中

3. 構建Prompt模板

我們需要設計一個提示模板,將檢索到的相關信息和用戶問題一起傳遞給大語言模型:

from langchain_core.prompts import ChatPromptTemplateprompt_template = ChatPromptTemplate.from_messages([("system", """你是一個問答機器人,你的任務是根據下述給定的已知信息回答用戶的問題已知信息:{context}用戶問題:{query}如果已知問題不包含用戶問題的答案,或者已知信息不足以回答用戶的問題,請回答"抱歉,我無法回答這個問題。"請不要輸出已知信息中不包含的信息或者答案。用中文回答用戶問題"""),]
)# 格式化prompt
prompt = prompt_template.invoke({"context": text, "query": query})
print(prompt.to_messages()[0].content)

這個提示模板:

  • 明確定義了AI助手的角色和任務
  • 設置了兩個變量:{context}用于傳入檢索結果,{query}用于傳入用戶問題
  • 提供了清晰的回答指令,包括當信息不足時如何響應

4. 調用大語言模型獲取回答

現在,我們使用LLM來生成基于上下文的回答:

from langchain_openai import ChatOpenAI# 結果解析器,直接獲取純文本回復
parser = StrOutputParser()# 初始化LLM模型接口
model = ChatOpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.getenv("OPENAI_KEY"),model="qwen/qwq-32b:free")# 調用模型獲取回答
result = model.invoke(prompt)
print(result)

這里我們:

  • 使用了OpenRouter平臺上的通義千問模型
  • 通過model.invoke(prompt)將格式化后的提示發送給模型
  • 獲取模型的文本響應

5. 構建完整的RAG鏈

最后,我們將把所有步驟整合成一個完整的LangChain處理鏈,實現端到端的RAG問答:

from operator import itemgetter# 輔助函數:收集文檔內容
def collect_documents(segments):text = []for segment in segments:text.append(segment.page_content)return text# 構建完整的處理鏈
chain = ({"context": itemgetter("query") | retriever | collect_documents,"query": itemgetter("query")
} | prompt_template | model | parser)# 設置新的查詢并執行鏈
query = "你能幫助史可軒處理日常事務嗎"
response = chain.invoke({"query": query})
print(response)

這個鏈式處理流程:

  1. 接收用戶查詢
  2. 執行向量檢索獲取相關上下文
  3. 將上下文和查詢組合到提示模板中
  4. 調用LLM生成回答
  5. 解析并返回最終的文本響應

詳細解析鏈式處理

讓我們解析一下這個鏈式處理的構建方式:

chain = ({"context": itemgetter("query") | retriever | collect_documents,"query": itemgetter("query")
} | prompt_template | model | parser)

這個鏈式結構使用了LangChain的管道操作符 |,實現了以下流程:

  1. itemgetter("query") 從輸入字典中提取查詢文本
  2. 將查詢傳遞給 retriever 執行向量檢索
  3. collect_documents 函數處理檢索結果,提取文本內容
  4. 將處理后的上下文和原始查詢分別作為 contextquery 傳遞給提示模板
  5. 提示模板格式化后的內容發送給LLM模型處理
  6. 最后通過 parser 解析LLM的響應,獲取純文本結果

總結

本文介紹了如何使用LangChain框架構建一個完整的RAG問答系統,主要包含以下步驟:

  1. 向量檢索:從Redis向量數據庫中檢索與用戶問題語義相似的文本段落
  2. 提示工程:設計合適的提示模板,將檢索結果作為上下文與用戶問題一起發送給模型
  3. 模型調用:利用LangChain的接口調用大語言模型生成答案
  4. 鏈式處理:使用LangChain的管道操作將各個組件整合成一個端到端的工作流

這種RAG架構具有很好的可解釋性和可靠性,能夠基于特定的知識庫回答問題,避免了大語言模型"幻覺"問題,特別適合構建企業級知識問答系統、客服助手等應用。

通過向量檢索提供相關上下文,我們可以讓大語言模型更準確地回答特定領域的問題,同時也能降低知識更新的成本(只需更新向量庫而無需重新訓練模型)。這種方案在實際應用中具有很高的靈活性和可擴展性。

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

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

相關文章

【Java學習筆記】SringBuffer類(重點)

StringBuffer(重點) 1. 基本介紹 (1)StringBuffer是可變的字符序列,可以對字符串內容驚醒增刪 (2)很多方法喝String相同,但StringBuffer可變長度 (3)Strin…

計算機網絡領域所有CCF-A/B/C類期刊匯總!

本期小編統計了【計算機網絡】領域CCF推薦所有期刊的最新影響因子,分區、年發文量以及投稿經驗,供大家參考! CCF-A類 1 IEEE Journal on Selected Areas in Communications 【影響因子】13.8 【期刊分區】JCR1區,中科院1區TOP …

AI-Sphere-Butler之如何啟動AI全能管家教程(WSL測試環境下適用)

環境: Ubuntu20.04 WSL2 問題描述: AI-Sphere-Butler之如何啟動AI全能管家教程(WSL測試環境下適用) 解決方案: 打開管家大模型 1.運行大模型在cmd下輸入: ollama run qwen2.5-3bnsfwny運行管家 數字人運行腳本&#xff…

【python深度學習】Day 47 注意力熱圖可視化

知識點:熱力圖 作業:對比不同卷積層熱圖可視化的結果 一、概念 為了方便觀察輸出,將特征圖進行可視化。特征圖本質就是不同的卷積核的輸出,淺層指的是離輸入圖近的卷積層,淺層卷積層的特征圖通常較大,而深層…

C#語音識別:使用Whisper.net實現語音識別

C#語音識別:使用Whisper.net實現語音識別 在當今數字化時代,語音識別技術已廣泛應用于智能助手、語音轉文字、會議記錄等眾多領域。對于 C# 開發者而言,如何快速、高效地實現語音識別功能呢?今天,我們就來介紹一個強大…

開源分享|適合初創商家的餐飲系統,基于thinkphp8+element-plus

一、項目介紹 三勾餐飲點餐連鎖版系統是一個基于thinkphp8element-plusuniapp打造的面向開發的小程序商城的全面解決方案,旨在為連鎖餐飲企業提供高效的點餐與管理服務。該系統支持多端應用發布,包括微信小程序、H5、安卓及iOS平臺,實現數據…

rec_pphgnetv2完整代碼學習(一)

rec_pphgnetv2是paddleocr_v5中的重要改進,因此對其完整代碼進行學習十分之有必要。 一、IdentityBasedConv1x1 這段代碼定義了 IdentityBasedConv1x1 類,它是 PaddleOCRv5 中 rec_pphgnetv2 模型的關鍵改進之一。該層通過將恒等映射(Ident…

vue3+dify從零手擼AI對話系統

vue3dify從零手擼AI對話系統 前言 近年來,人工智能技術呈現爆發式增長,其應用已深度滲透至各行各業。甚至家里長輩們也開始借助AI工具解決日常問題。作為程序員群體,我們更應保持技術敏銳度,緊跟這波浪潮。 回溯求學時期&#xf…

robot_lab train的整體邏輯

Go2機器人推理(Play)流程詳細分析 概述 本文檔詳細分析了使用命令 python scripts/rsl_rl/base/play.py --task RobotLab-Isaac-Velocity-Rough-Unitree-Go2-v0 進行Go2機器人推理的完整流程,基于實際的代碼實現,包括模型加載、環境配置調整、推理循環…

Python Day45

Task: 1.tensorboard的發展歷史和原理 2.tensorboard的常見操作 3.tensorboard在cifar上的實戰:MLP和CNN模型 效果展示如下,很適合拿去組會匯報撐頁數: 作業:對resnet18在cifar10上采用微調策略下,用tens…

MySQL SQL 優化:從 INSERT 到 LIMIT 的實戰與原理

在數據庫驅動的現代應用中,SQL 查詢的性能直接決定了用戶體驗和系統效率。本文將深入探討 MySQL (特別是 InnoDB 存儲引擎)中常見的 SQL 性能瓶頸,并結合實際案例,詳細剖析從數據插入到復雜分頁查詢的優化策略與底層實…

SQL 基礎入門

SQL 基礎入門 SQL(全稱 Structured Query Language,結構化查詢語言)是用于操作關系型數據庫的標準語言,主要用于數據的查詢、新增、修改和刪除。本文面向初學者,介紹 SQL 的基礎概念和核心操作。 1. 常見的 SQL 數據…

HTTP 請求協議簡單介紹

目錄 常見的 HTTP 響應頭字段 Java 示例代碼:發送 HTTP 請求并處理響應 代碼解釋: 運行結果: 文件名: 總結: HTTP(HyperText Transfer Protocol)是用于客戶端與服務器之間通信的協議。它定…

《100天精通Python——基礎篇 2025 第5天:鞏固核心知識,選擇題實戰演練基礎語法》

目錄 一、踏上Python之旅二、Python輸入與輸出三、變量與基本數據類型四、運算符五、流程控制 一、踏上Python之旅 1.想要輸出 I Love Python,應該使用()函數。 A.printf() B.print() C.println() D.Print() 在Python中想要在屏幕中輸出內容,應該使用print()函數…

求解一次最佳平方逼近多項式

例 設 f ( x ) 1 x 2 f(x)\sqrt{1x^2} f(x)1x2 ?,求 [ 0 , 1 ] [0,1] [0,1]上的一個一次最佳平方逼近多項式。 解 : d 0 ∫ 0 1 1 x 2 d x 1 2 ln ? ( 1 2 ) 2 2 ≈ 1.147 d_0\int_{0}^{1}\sqrt{1x^2}dx\frac{1}{2}\ln(1\sqrt{2})\frac{\sqrt…

在Ubuntu上使用 dd 工具制作U盤啟動盤

在Ubuntu上使用 dd 工具制作U盤啟動盤 在Linux系統中,dd 是一個功能強大且原生支持的命令行工具,常用于復制文件和轉換數據。它也可以用來將ISO鏡像寫入U盤,從而創建一個可啟動的操作系統安裝盤。雖然圖形化工具(如 Startup Disk…

如何理解OSI七層模型和TCP/IP四層模型?HTTP作為如何保存用戶狀態?多服務器節點下 Session方案怎么做

本篇概覽: OSI 七層模型是什么?每一層的作用是什么?TCP/IP四層模型和OSI七層模型的區別是什么? HTTP 本身是無狀態協議,HTTP如何保存用戶狀態? 能不能具體說一下Cookie的工作原理、生命周期、作用域?使用…

深入剖析 RocketMQ 中的 DefaultMQPushConsumerImpl:消息推送消費的核心實現

前言 在 Apache RocketMQ 的消息消費體系中,RocketMQ 提供了DefaultMQPushConsumer(推送消費)和DefaultMQPullConsumer(拉取消費)兩種主要消費方式。DefaultMQPushConsumer與DefaultMQPullConsumer在消息獲取方式&…

Linux編程:2、進程基礎知識

一、進程基本概念 1、進程與程序的區別 程序:靜態的可執行文件(如電腦中的vs2022安裝程序)。進程:程序的動態執行過程(如啟動后的vs2022實例),是操作系統分配資源的單位(如 CPU 時…

React Router 中 navigate 后瀏覽器返回按鈕不起作用的問題記錄

React Router 中 navigate 后瀏覽器返回按鈕不起作用的問題記錄 在使用 React Router(v6)開發項目時,我遇到了一個讓人困惑的問題: 當我從 /article 頁面使用 navigate("/article/next") 進行跳轉后,點擊瀏…