[langchain教程]langchain03——用langchain構建RAG應用

RAG

RAG過程

離線過程:

  1. 加載文檔
  2. 將文檔按一定條件切割成片段
  3. 將切割的文本片段轉為向量,存入檢索引擎(向量庫)

在線過程:

  1. 用戶輸入Query,將Query轉為向量
  2. 從向量庫檢索,獲得相似度TopN信息
  3. 將檢索結果和用戶輸入,共同組成Prompt
  4. 將Prompt 輸入大模型,獲取LLM的回復

用langchian構建RAG

1. 加載文檔

LangChain中的文檔對象Document有兩個屬性:

  • page_content: str類型,記錄此文檔的內容。
  • metadata: dict類型,保存與此文檔相關的元數據,包括文檔ID、文件名等。

在langchain中,加載文檔使用 文檔加載器DocumentLoader 來實現,它從源文檔加載數據并返回文檔列表。每個DocumentLoader都有其特定的參數,但它們都可以通過.load()方法以相同的方式調用。

加載pdf

需要先安裝pypdf庫

pip install pypdf

PyPDFLoader加載pdf,輸入是文件路徑,輸出提取出的內容列表:

from langchain_community.document_loaders import PyPDFLoaderloader = PyPDFLoader(file_path)
pages = []
for page in loader.load():pages.append(page)

返回的文檔列表如下所示:

[
Document(metadata={'source': 'D:\\桌面\\RAG分析.pdf', 'page': 0}, page_content='11111111111111111111111111111111111111111111111111111111'), 
Document(metadata={'source': 'D:\\桌面\\RAG分析.pdf', 'page': 1}, page_content='2222222222222222222222222222222222222222222222222222222')
]

加載網頁

簡單快速的文本提取

對于“簡單快速”解析,需要 langchain-community 和 beautifulsoup4 庫:

pip install  langchain-community beautifulsoup4

使用WebBaseLoader,輸入是url的列表,返回一個 Document 對象的列表,列表里的內容是一系列包含頁面文本的字符串。在底層,它使用的是 beautifulsoup4 庫。

import bs4
from langchain_community.document_loaders import WebBaseLoaderpage_url = "https://python.langchain.com/docs/how_to/chatbots_memory/"loader = WebBaseLoader(web_paths=[page_url])
docs = loader.load()assert len(docs) == 1
print(docs)

這樣提取出的基本上是頁面 HTML 中文本的轉儲,可能包含多余的信息,提取的信息如下所示(截取了首部)

[Document(metadata={'source': 'https://python.langchain.com/', 'title': 'How to add memory to chatbots | 🦜?🔗 LangChain',},page_content='\n\n\n\n\nHow to add memory to chatbots | 🦜?🔗 LangChain\n\n\n\n\n\n\nSkip to main contentJoin us at  ')
]

如果了解底層 HTML 中主體文本的表示,可以通過 BeautifulSoup 指定所需的 <div> 類和其他參數。

下面僅解析文章的主體文本:

loader = WebBaseLoader(web_paths=[page_url],bs_kwargs={"parse_only": bs4.SoupStrainer(class_="theme-doc-markdown markdown"),},bs_get_text_kwargs={"separator": " | ", "strip": True},
)docs = []
async for doc in loader.alazy_load():docs.append(doc)assert len(docs) == 1
doc = docs[0]

提取出的內容如下所示:

[Document(metadata={'source': 'https://python.langchain.com/docs/how_to/chatbots_memory/'}, 	page_content='How to add memory to chatbots | A key feature of chatbots is their ability to use the content of previous conversational turns as context. ')
]

可以使用各種設置對 WebBaseLoader 進行參數化,允許指定請求頭、速率限制、解析器和其他 BeautifulSoup 的關鍵字參數。詳細信息參見 API 參考。

高級解析

如果想對頁面內容進行更細粒度的控制或處理,可以用langchain-unstructured進行高級解析。

pip install langchain-unstructuredpip install unstructured

注意: 如果不安裝unstructured會報錯!

下面的代碼不是為每個頁面生成一個 Document 并通過 BeautifulSoup 控制其內容,而是生成多個 Document 對象,表示頁面上的不同結構。這些結構包括章節標題及其對應的主體文本、列表或枚舉、表格等。

from langchain_unstructured import UnstructuredLoaderpage_url = "https://python.langchain.com/docs/how_to/chatbots_memory/"
loader = UnstructuredLoader(web_url=page_url)docs = []
for doc in loader.load():docs.append(doc)print(docs[:5])

輸出如下所示(太長了,截取了部分):

[Document(metadata={'image_url': 'https://colab.research.google.com/assets/colab-badge.svg', 'link_texts': ['Open In Colab'], 'link_urls': ['https://colab.research.google.com/github/langchain-ai/langchain/blob/master/docs/docs/how_to/chatbots_memory.ipynb'], 'languages': ['eng'], 'filetype': 'text/html', 'url': 'https://python.langchain.com/docs/how_to/chatbots_memory/', 'category': 'Image', 'element_id': '76f10732f139a03f24ecf55613a5116a'}, page_content='Open In Colab'), Document(metadata={'category_depth': 0, 'languages': ['eng'], 'filetype': 'text/html', 'url': 'https://python.langchain.com/docs/how_to/chatbots_memory/','category': 'Title', 'element_id': 'b6bfe64119578f39e0dd7d0287b2964a'}, page_content='How to add memory to chatbots'), Document(metadata={'languages': ['eng'], 'filetype': 'text/html', 'parent_id': 'b6bfe64119578f39e0dd7d0287b2964a', 'url': 'https://python.langchain.com/docs/how_to/chatbots_memory/', 'category': 'NarrativeText', 'element_id': 'ac3524f3e30afbdf096b186a665188ef'},page_content='A key feature of chatbots is their ability to use the content of previous conversational turns as context. This state management can take several forms, including:'), Document(metadata={'category_depth': 1, 'languages': ['eng'], 'filetype': 'text/html', 'parent_id': 'b6bfe64119578f39e0dd7d0287b2964a', 'url': 'https://python.langchain.com/docs/how_to/chatbots_memory/', 'category': 'ListItem', 'element_id': '0c9193e450bacf9a4d716208b2e7b1ee'}, page_content='Simply stuffing previous messages into a chat model prompt.'), 
]

可以用doc.page_content來輸出正文文本:

for doc in docs[:5]:print(doc.page_content)

輸出如下所示:

Open In Colab
Open on GitHub
How to add memory to chatbots
A key feature of chatbots is their ability to use the content of previous conversational turns as context. This state management can take several forms, including:
Simply stuffing previous messages into a chat model prompt.    

2. 切割文檔

當文檔過長時,模型存在兩方面問題:一是可能無法完整加載至上下文窗口,二是即便能加載,從中提取有用信息也較為困難。

為破解此困境,可將文檔拆分成多個塊來進行嵌入與存儲,如此一來,分塊后還能快速精準地定位到與查詢最相關的部分。

在具體操作中,可以把文檔按照每塊 1000 個字符的規格進行拆分,同時在塊之間設置 200 個字符的重疊。之所以設置重疊,是為了降低將某塊有效信息與其關聯的重要上下文被人為割裂開的風險,保證內容的連貫性與完整性。

以下代碼采用的文本分割器是 RecursiveCharacterTextSplitter,它會利用常見分隔符對文檔進行遞歸拆分,直至各塊大小滿足既定要求。此外,代碼還啟用了 add_start_index=True 的設置,使每個分割后的文檔塊在初始文檔中的字符起始位置得以保留,這一位置信息將以元數據屬性 “start_index” 的形式呈現。

from langchain_text_splitters import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(docs)

3. 將塊轉為向量存儲到數據庫

為了在運行時能夠對文本塊進行高效搜索,我們通常需要對文本塊進行索引,而嵌入內容是實現這一目標的常見方法。

我們將每個文檔分割后的文本塊進行嵌入處理,并將這些嵌入插入到向量數據庫中。當要搜索這些分割后的文本塊時,可以將文本搜索查詢進行嵌入,然后執行“相似性”度量,以識別出與查詢嵌入最相似的存儲文本塊。其中,余弦相似性是一種簡單且常用的相似性度量方法,它通過測量每對嵌入(高維向量)之間的角度的余弦值,來評估它們的相似程度。

我們可以通過Chroma 向量存儲和 Ollama嵌入模型,完成對所有文檔分割后的文本塊的嵌入和存儲工作。

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddingsembedding = OllamaEmbeddings(model_url="http://localhost:11434")
vectorstore = Chroma.from_documents(documents=all_splits, embedding=embedding)

4. 檢索

創建一個簡單的應用程序,接受用戶問題,搜索相關文檔,并將檢索到的文檔和初始問題傳遞給模型以返回答案,具體步驟如下:

  • 定義搜索文檔的邏輯:LangChain 定義了一個檢索器接口,它封裝了一個可以根據字符串返回相關文檔的索引查詢。檢索器的唯一要求是能夠接受查詢并返回文檔,具體的底層邏輯由檢索器指定。

  • 使用向量存儲檢索器:最常見的檢索器類型是向量存儲檢索器,它利用向量存儲的相似性搜索能力來促進檢索。任何 VectorStore 都可以輕松轉換為一個 Retriever,使用 VectorStore.as_retriever() 方法。

retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6})retrieved_docs = retriever.invoke("What are the approaches to Task Decomposition?")print(retrieved_docs[0].page_content)

輸出如下所示:

Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.
Task decomposition can be done (1) by LLM with simple prompting like "Steps for XYZ.\n1.", "What are the subgoals for achieving XYZ?", (2) by using task-specific instructions; e.g. "Write a story outline." for writing a novel, or (3) with human inputs.

5. 生成

生成時,將所有內容整合到一個鏈中,該鏈接受一個問題,檢索相關文檔,構建提示,將其傳遞給模型,并解析輸出。

from langchain_community.document_loaders import UnstructuredURLLoader
from langchain_community.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.retrievers import VectorStoreRetriever
from langchain_community.prompts import PromptTemplate
from langchain_community.chains import RetrievalQA# 加載文檔
page_url = "https://python.langchain.com/docs/how_to/chatbots_memory/"
loader = UnstructuredURLLoader(urls=[page_url])# 拆分文檔
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(loader.load())# 創建向量存儲和嵌入
embedding = OllamaEmbeddings(model_url="http://localhost:11434")
vectorstore = Chroma.from_documents(documents=all_splits, embedding=embedding)
retriever = VectorStoreRetriever(vectorstore=vectorstore)# 構建提示和生成鏈
prompt_template = """Use the following context to answer the question at the end. If the answer isn't found in the context, just say that you don't know.{context}Question: {question}"""
PROMPT = PromptTemplate.from_template(prompt_template)# 創建 RAG 鏈
rag_chain = RetrievalQA.from_chain_type(retriever=retriever,chain_type="stuff",prompt=PROMPT
)# 執行查詢
result = rag_chain.invoke("What are the approaches to Task Decomposition?")
print(result['result'])

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

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

相關文章

C語言復習筆記--字符函數和字符串函數(下)

在上篇我們了解了部分字符函數及字符串函數,下面我們來看剩下的字符串函數. strstr 的使用和模擬實現 老規矩,我們先了解一下strstr這個函數,下面看下這個函數的函數原型. char * strstr ( const char * str1, const char * str2); 如果沒找到就返回NULL指針. 下面我們看下它的…

FreeRTOS中的優先級翻轉問題及其解決方案:互斥信號量詳解

FreeRTOS中的優先級翻轉問題及其解決方案&#xff1a;互斥信號量詳解 在實時操作系統中&#xff0c;任務調度是基于優先級的&#xff0c;高優先級任務應該優先于低優先級任務執行。但在實際應用中&#xff0c;有時會出現"優先級翻轉"的現象&#xff0c;嚴重影響系統…

深度學習-全連接神經網絡

四、參數初始化 神經網絡的參數初始化是訓練深度學習模型的關鍵步驟之一。初始化參數&#xff08;通常是權重和偏置&#xff09;會對模型的訓練速度、收斂性以及最終的性能產生重要影響。下面是關于神經網絡參數初始化的一些常見方法及其相關知識點。 官方文檔參考&#xff1…

GIS開發筆記(9)結合osg及osgEarth實現三維球經緯網格繪制及顯隱

一、實現效果 二、實現原理 按照5的間隔分別創建經緯線的節點,掛在到組合節點,組合節點掛接到根節點。可以根據需要設置間隔度數和線寬、線的顏色。 三、參考代碼 //創建經緯線的節點 osg::Node *GlobeWidget::createGraticuleGeometry(float interval, const osg::Vec4 …

《Relay IR的基石:expr.h 中的表達式類型系統剖析》

TVM Relay源碼深度解讀 文章目錄 TVM Relay源碼深度解讀一 、從Constant看Relay表達式的設計哲學1. 類定義概述2. ConstantNode 詳解1. 核心成員2. 關鍵方法3. 類型系統注冊 3. Constant 詳解1. 核心功能 二. 核心內容概述(1) Relay表達式基類1. RelayExprNode 和 RelayExpr 的…

自動駕駛地圖數據傳輸協議ADASIS v2

ADASIS&#xff08;Advanced Driver Assistance Systems Interface Specification&#xff09;直譯過來就是 ADAS 接口規格&#xff0c;它要負責的東西其實很簡單&#xff0c;就是為自動駕駛車輛提供前方道路交通相關的數據&#xff0c;這些數據被抽象成一個標準化的概念&#…

Flutter 狀態管理 Riverpod

Android Studio版本 Flutter SDK 版本 將依賴項添加到您的應用 flutter pub add flutter_riverpod flutter pub add riverpod_annotation flutter pub add dev:riverpod_generator flutter pub add dev:build_runner flutter pub add dev:custom_lint flutter pub add dev:riv…

【EasyPan】MySQL主鍵與索引核心作用解析

【EasyPan】項目常見問題解答&#xff08;自用&持續更新中…&#xff09;匯總版 MySQL主鍵與索引核心作用解析 一、主鍵&#xff08;PRIMARY KEY&#xff09;核心作用 1. 數據唯一標識 -- 創建表時定義主鍵 CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,use…

IcePlayer音樂播放器項目分析及學習指南

IcePlayer音樂播放器項目分析及學習指南 項目概述 IcePlayer是一個基于Qt5框架開發的音樂播放器應用程序&#xff0c;使用Visual Studio 2013作為開發環境。該項目實現了音樂播放、歌詞顯示、專輯圖片獲取等功能&#xff0c;展現了桌面應用程序開發的核心技術和設計思想。 技…

vscode 打開新頁簽

目錄 vscode 打開新頁簽 完整settings.json內容&#xff1a; vscode 打開新頁簽 .vscode目錄中 新建settings.json 在 settings.json 文件中&#xff0c;添加或修改以下行&#xff1a; json "workbench.editor.enablePreview": false 這將禁用預覽模式&#xff0…

C語言高頻面試題——常量指針與指針常量區別

1. 常量指針&#xff08;Pointer to Constant&#xff09; 定義&#xff1a; 常量指針是指向一個常量數據的指針&#xff0c;即指針指向的內容不能通過該指針被修改。 語法&#xff1a; const int* ptr;或者&#xff1a; int const* ptr;解釋&#xff1a; const修飾的是指…

c++基礎·列表初始化

目錄 一、列表初始化的核心優勢 二、基礎數據類型與數組初始化 1. 基礎類型初始化 2. 數組初始化 三、類與結構體初始化 1. 構造函數匹配規則 2. 注意事項 四、標準容器初始化 五、聚合類型&#xff08;Aggregate Types&#xff09;初始化 1. 聚合類型定義 2. 初始化…

數據分析與產品、運營、市場之間如何有效對齊

數據分析的重要性在于它能夠將海量的原始信息轉化為可操作的洞察。以產品開發為例,通過用戶行為數據的分析,產品經理可以清晰了解哪些功能被頻繁使用,哪些設計導致用戶流失,從而優化迭代方向。運營團隊則依靠數據分析來監控供應鏈效率、預測需求波動,甚至通過實時數據調整…

[C]基礎11.深入理解指針(3)

博客主頁&#xff1a;向不悔本篇專欄&#xff1a;[C]您的支持&#xff0c;是我的創作動力。 文章目錄 0、總結1、字符指針變量2、數組指針變量2.1 數組指針變量是什么&#xff1f;2.2 數組指針變量怎么初始化&#xff1f; 3、二維數組傳參的本質4、函數指針變量4.1 函數指針變量…

【漏洞復現】CVE-2024-38856(ApacheOfbiz RCE)

【漏洞復現】CVE-2024-38856&#xff08;ApacheOfbiz RCE&#xff09; 1. 漏洞描述 Apache OFBiz 是一個開源的企業資源規劃&#xff08;ERP&#xff09;系統。它提供了一套企業應用程序&#xff0c;用于集成和自動化企業的許多業務流程。 這個漏洞是由于對 CVE-2023-51467 的…

C++入門小館: 深入string類(二)

嘿&#xff0c;各位技術潮人&#xff01;好久不見甚是想念。生活就像一場奇妙冒險&#xff0c;而編程就是那把超酷的萬能鑰匙。此刻&#xff0c;陽光灑在鍵盤上&#xff0c;靈感在指尖跳躍&#xff0c;讓我們拋開一切束縛&#xff0c;給平淡日子加點料&#xff0c;注入滿滿的pa…

【nginx】服務的信號控制

目錄 1. 說明2. 常用信號及作用3. 信號控制的具體操作3.1 獲取 Nginx 主進程 PID3.2 發送信號 4. 應用場景4.1 重新加載配置文件4.2 日志切割 5. 平滑升級 Nginx6. 注意事項 1. 說明 1.Nginx 的信號控制是其管理服務的重要機制&#xff0c;通過向主進程發送特定信號&#xff0…

Ubuntu下展銳刷機工具spd_dump使用說明

spd_dump使用說明 源碼地址&#xff1a;https://github.com/ilyakurdyukov/spreadtrum_flash 編譯環境準備&#xff1a; sudo apt update sudo apt install git sudo apt install build-essential sudo apt install libusb-1.0-0-devIf you create /etc/udev/rules.d/80-spd…

鴻蒙NEXT開發LRUCache緩存工具類(單例模式)(ArkTs)

import { util } from kit.ArkTS;/*** LRUCache緩存工具類&#xff08;單例模式&#xff09;* author 鴻蒙布道師* since 2025/04/21*/ export class LRUCacheUtil {private static instance: LRUCacheUtil;private lruCache: util.LRUCache<string, any>;/*** 私有構造函…

筆記:react中 父組件怎么獲取子組件中的屬性或方法

在子組件中我們可以使用下面兩個方法去暴露你所要放行的屬性或方法&#x1f447; 1.useImperativeHandle 2.orwardRef 搭配使用例子 import React, { useState, forwardRef, useImperativeHandle } from "react"function Son(props, ref) {const [data] useStat…