《AI Agent智能應用從0到1定制開發》學習筆記:使用RAG技術增強大模型能力,實現與各種文檔的對話

思維導圖

在這里插入圖片描述

📚 引言

大型語言模型(如ChatGPT)雖然功能強大,但它們存在一些明顯的局限性。這些模型的知識庫更新較慢,無法實時學習最新內容,而且對私有數據或特定領域的專業知識了解有限。例如,ChatGPT的知識截止到特定時間點,無法感知用戶本地電腦或內網中的數據。這就是為什么當我們詢問非常具體或專業的內容時,它的回答可能顯得泛泛而談。

那么,如何讓大模型變得更"聰明",能夠獲取最新知識并回答更專業的問題呢?這就是本文要介紹的RAG(檢索增強生成)技術。

🔍 RAG技術概述

什么是RAG?

RAG(Retrieval-Augmented Generation,檢索增強生成)是一種結合檢索和生成兩種技術的方法,旨在幫助計算機更好地理解和回答問題。簡單來說,它讓AI模型能夠在回答問題前先"查閱資料",從而提供更準確、更專業的回答。

RAG的基本流程

在這里插入圖片描述

RAG技術的典型流程包括:

  1. 加載數據(Loader):從各種來源加載文檔數據
  2. 處理文檔(Transform):對文檔進行切割、整理等處理
  3. 向量化(Embedding):將文本轉換為向量表示
  4. 存儲(Store):將向量數據存儲在向量數據庫中
  5. 檢索(Retrieve):根據問題檢索相關文檔片段
  6. 生成回答(Generate):基于檢索結果生成答案

🔧 LangChain中的RAG實現

Loader:讓大模型具備實時學習的能力

LangChain包裝了各種Loader,使大模型能夠加載各種格式的文檔:

  • CSV Loader:加載表格數據
  • Directory Loader:加載整個目錄的文件
  • HTML Loader:加載網頁內容
  • JSON Loader:加載JSON格式數據
  • Markdown Loader:加載Markdown文檔
  • PDF Loader:加載PDF文件

除此之外,LangChain還支持超過100種不同的數據源接口,包括B站、YouTube、GitHub等平臺的數據。

# 加載Markdown文件示例
from langchain.document_loaders import UnstructuredMarkdownLoaderloader = UnstructuredMarkdownLoader("path/to/file.md")
data = loader.load()# 加載CSV文件示例
from langchain.document_loaders import CSVLoaderloader = CSVLoader("path/to/file.csv")
data = loader.load()# 加載目錄中的文件
from langchain.document_loaders import DirectoryLoaderloader = DirectoryLoader("path/to/directory", glob="**/*.pdf")
data = loader.load()

文檔轉換:切割、總結和翻譯

加載文檔后,通常需要對其進行處理,以便更好地利用文檔內容:

文檔切割

文檔切割的目的是:

  1. 降低成本,適應大模型的上下文窗口限制
  2. 將文檔轉換為結構化數據,便于查詢

LangChain提供了多種切割器:

# 字符串分割
from langchain.text_splitter import CharacterTextSplittertext_splitter = CharacterTextSplitter(separator="\n\n",chunk_size=1000,chunk_overlap=200,length_function=len
)
docs = text_splitter.split_documents(documents)# 按代碼分割
from langchain.text_splitter import RecursiveCharacterTextSplitterpython_splitter = RecursiveCharacterTextSplitter.from_language(language="python",chunk_size=1000,chunk_overlap=200
)
文檔總結、精煉和翻譯

LangChain還提供了文檔總結、精煉和翻譯的功能:

# 文檔總結
from langchain.chains.summarize import load_summarize_chain
from langchain_openai import ChatOpenAIllm = ChatOpenAI(temperature=0)
chain = load_summarize_chain(llm, chain_type="map_reduce")
summary = chain.run(docs)# 文檔翻譯
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplatetemplate = """Translate the following text from {source_language} to {target_language}:
{text}"""prompt = PromptTemplate(input_variables=["source_language", "target_language", "text"],template=template
)chain = LLMChain(llm=llm, prompt=prompt)
translated = chain.run(source_language="English", target_language="Chinese", text=text)

解決"Lost in the Middle"問題

研究表明,當處理長文本時,檢索性能會出現"迷失在中間"的現象:當相關信息位于輸入上下文的開頭或結尾時,模型表現最佳;而當相關信息位于中間位置時,即使對于專門設計的上下文模型,性能也會顯著下降。

解決方案包括:

  1. 通過檢索找到相關文本塊
  2. 對檢索結果進行重新排序,將最相關的內容放在開頭和結尾
  3. 使用排序后的文本進行生成
# 排序檢索結果的示例代碼
def reorder_results(results):# 按相關性排序sorted_results = sorted(results, key=lambda x: x.score, reverse=True)# 重新排列,將高相關度的放在頭尾reordered = []for i in range(len(sorted_results)):if i % 2 == 0:reordered.append(sorted_results[i//2])else:reordered.append(sorted_results[len(sorted_results) - 1 - i//2])return reordered

文本向量化

為什么需要文本向量化?主要有兩個原因:

  1. 純文本形式難以進行語義相關性搜索
  2. 文本處理效率低且占用空間大

文本向量化(Embedding)將文本轉換為高維向量空間中的點,使得語義相似的文本在向量空間中距離更近。

# 使用OpenAI的文本嵌入模型
from langchain_openai import OpenAIEmbeddingsembeddings = OpenAIEmbeddings()
query_vector = embeddings.embed_query("How does RAG work?")# 使用HuggingFace的文本嵌入模型
from langchain_huggingface import HuggingFaceEmbeddingsembeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")

向量數據庫:存儲和檢索

向量數據庫是RAG技術中不可或缺的組成部分,它能夠高效地存儲和檢索高維向量數據。向量數據庫的主要作用包括:

  1. 管理數據:以原始形式有效管理數據
  2. 存儲向量:存儲AI需要的高維數據
  3. 高效檢索:快速找到語義相似的內容

市面上有多種向量數據庫可供選擇:

  • Milvus:開源向量數據庫,功能完善,性能強大
  • Pinecone:云原生向量數據庫,易于使用
  • Chroma:輕量級向量數據庫,適合本地開發
  • FAISS:Facebook AI開發的相似性搜索庫
  • Qdrant:開源向量搜索引擎
# 使用Chroma向量數據庫
from langchain_community.vectorstores import Chromavectordb = Chroma.from_documents(documents=docs,embedding=embeddings,persist_directory="./chroma_db"
)# 檢索相似文檔
docs = vectordb.similarity_search("What is RAG technology?", k=3)

🛠? 實戰項目:ChatDoc智能文檔助手

下面,我們將學習如何構建一個名為ChatDoc的智能文檔助手,它能夠:

  1. 加載PDF、DOCX或Excel等格式的文檔
  2. 對文檔進行適當切分
  3. 使用OpenAI進行向量化
  4. 使用Chroma DB實現本地向量存儲
  5. 實現與文檔的對話功能

實現步驟

1. 初始化ChatDoc類
import os
from langchain.document_loaders import PDFMinerLoader, CSVLoader
from langchain.document_loaders import Docx2txtLoader, UnstructuredExcelLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQAclass ChatDoc:def __init__(self):self.file_path = Noneself.file_content = Noneself.db = Noneself.embeddings = OpenAIEmbeddings()self.llm = ChatOpenAI(temperature=0)
2. 實現文件加載功能
def get_file(self, file_path):self.file_path = file_path_, file_extension = os.path.splitext(file_path)try:if file_extension == '.pdf':loader = PDFMinerLoader(file_path)elif file_extension == '.csv':loader = CSVLoader(file_path)elif file_extension == '.docx':loader = Docx2txtLoader(file_path)elif file_extension == '.xlsx' or file_extension == '.xls':loader = UnstructuredExcelLoader(file_path)else:print(f"不支持的文件格式: {file_extension}")return Noneself.file_content = loader.load()print(f"文件 {file_path} 加載成功!")return self.file_contentexcept Exception as e:print(f"加載文件時出錯: {e}")return None
3. 文本切分與向量化
def separate_and_embed(self):if self.file_content is None:print("沒有加載文件內容,請先加載文件。")return None# 文本切分text_splitter = CharacterTextSplitter(separator="\n",chunk_size=1000,chunk_overlap=200,length_function=len)chunks = text_splitter.split_documents(self.file_content)# 向量化存儲self.db = Chroma.from_documents(documents=chunks,embedding=self.embeddings,persist_directory="./chroma_db")print(f"文本已切分為 {len(chunks)} 個塊并完成向量化存儲。")return self.db
4. 實現基本問答功能
def ask_and_find(self, question):if self.db is None:print("向量數據庫未初始化,請先處理文檔。")return None# 檢索相關文檔docs = self.db.similarity_search(question, k=3)# 構建上下文context = "\n\n".join([doc.page_content for doc in docs])# 創建提示prompt = f"""根據以下信息回答問題:{context}問題: {question}"""# 生成回答response = self.llm.predict(prompt)return response
5. 使用多重查詢優化檢索效果
from langchain.retrievers.multi_query import MultiQueryRetrieverdef improved_ask_and_find(self, question):if self.db is None:print("向量數據庫未初始化,請先處理文檔。")return None# 創建多重查詢檢索器retriever = MultiQueryRetriever.from_llm(retriever=self.db.as_retriever(),llm=self.llm)# 進行檢索docs = retriever.get_relevant_documents(question)# 構建上下文context = "\n\n".join([doc.page_content for doc in docs])# 創建提示prompt = f"""根據以下信息回答問題:{context}問題: {question}"""# 生成回答response = self.llm.predict(prompt)return response
6. 實現對話功能
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChaindef chat_with_doc(self):if self.db is None:print("向量數據庫未初始化,請先處理文檔。")return None# 創建對話記憶memory = ConversationBufferMemory(memory_key="chat_history",return_messages=True)# 創建對話鏈qa_chain = ConversationalRetrievalChain.from_llm(llm=self.llm,retriever=self.db.as_retriever(),memory=memory)# 開始對話print("開始與文檔對話,輸入'exit'退出")while True:question = input("你: ")if question.lower() == 'exit':breakresult = qa_chain({"question": question})print(f"AI: {result['answer']}")

使用示例

# 使用ChatDoc
chat_doc = ChatDoc()# 加載文檔
chat_doc.get_file("example.pdf")# 處理文檔
chat_doc.separate_and_embed()# 問答示例
response = chat_doc.ask_and_find("這個文檔主要講了什么?")
print(response)# 啟動交互式對話
chat_doc.chat_with_doc()

📈 RAG技術的優化方法

多重查詢優化

多重查詢(Multi-query)通過擴展原始問題,從不同角度生成多個相關查詢,然后綜合檢索結果。這種方法可以提高檢索的召回率和準確性。

# 多重查詢示例
from langchain.retrievers.multi_query import MultiQueryRetrieverretriever = MultiQueryRetriever.from_llm(retriever=vectordb.as_retriever(),llm=ChatOpenAI(temperature=0)
)# 原始問題
question = "如何實現RAG技術?"# 生成的多重查詢可能包括:
# 1. "RAG技術的實現步驟是什么?"
# 2. "如何在項目中使用檢索增強生成?"
# 3. "實現RAG需要哪些組件?"
# 4. "RAG的代碼實現示例"

上下文壓縮

上下文壓縮(Context compression)通過篩選和壓縮檢索到的文檔,確保只有最相關的內容被包含在上下文中,從而提高回答質量并降低成本。

from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain.retrievers import ContextualCompressionRetriever# 創建壓縮器
compressor = LLMChainExtractor.from_llm(llm)# 創建壓縮檢索器
compression_retriever = ContextualCompressionRetriever(base_retriever=vectordb.as_retriever(),doc_compressor=compressor
)# 使用壓縮檢索器獲取文檔
compressed_docs = compression_retriever.get_relevant_documents(query)

基于重排序的優化

針對"迷失在中間"問題,可以對檢索結果進行重新排序,將最相關的文檔放在上下文的開頭和結尾:

def rerank_documents(docs, query):# 計算每個文檔與查詢的相關性分數# 這里可以使用更復雜的相關性評分方法scored_docs = [(doc, doc.metadata.get("score", 0)) for doc in docs]# 按分數排序sorted_docs = sorted(scored_docs, key=lambda x: x[1], reverse=True)# 重新排列文檔,使最相關的在開頭和結尾result = []for i in range(len(sorted_docs)):if i % 2 == 0 and i//2 < len(sorted_docs):result.append(sorted_docs[i//2][0])elif i//2 < len(sorted_docs) // 2:result.append(sorted_docs[len(sorted_docs) - 1 - i//2][0])return result

🌟 總結與展望

通過本文,我們深入學習了RAG技術及其在LangChain中的實現。RAG技術通過將檢索與生成相結合,有效解決了大模型知識時效性和專業性不足的問題,使AI能夠訪問最新的、專業的、私有的信息。

我們詳細探討了RAG的實現步驟:

  1. 使用各種Loader加載文檔
  2. 通過文本切割、總結等方法處理文檔
  3. 將文本向量化并存儲在向量數據庫中
  4. 根據用戶問題檢索相關文檔
  5. 基于檢索結果生成回答

同時,我們還介紹了多重查詢、上下文壓縮和重排序等優化技術,以提高RAG系統的性能。

最后,我們通過構建ChatDoc智能文檔助手,將學到的知識應用到實踐中,實現了與任意文檔對話的功能。

未來,隨著大模型和向量數據庫技術的不斷發展,RAG技術將變得更加高效、準確,并在更多領域發揮作用。通過掌握RAG技術,我們可以充分發揮大模型的潛力,構建更智能、更專業的AI應用。

💡 小提示:如果你想要進一步提升RAG系統的性能,可以考慮:

  • 嘗試不同的文本嵌入模型
  • 優化文檔切割策略
  • 使用混合檢索方法
  • 引入用戶反饋機制

希望本文能夠幫助你理解和應用RAG技術,構建屬于自己的智能文檔助手!


🔗 參考資料

  • AI Agent智能應用從0到1定制開發
  • LangChain官方文檔:https://python.langchain.com/docs/
  • “Lost in the Middle: How Language Models Use Long Contexts” 研究論文
  • 向量數據庫官方文檔:Milvus、Chroma、Pinecone等

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

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

相關文章

Python 爬蟲(4)HTTP協議

文章目錄 一、HTTP協議1、HTTP特點2、HTTP工作原理3、HTTP與HTTPS的區別 前言&#xff1a; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;是互聯網上應用最為廣泛的一種網絡協議&#xff0c;用于在客戶端和服務器之間傳輸超文本&#xf…

測試工程 常用Python庫

以下是測試工程師在Python中必須掌握的常用庫、框架以及提升日常工作效率的技巧總結&#xff1a; 一、必須掌握的Python庫與框架 1. 測試框架 unittest Python內置的單元測試框架&#xff0c;提供測試用例、測試套件、斷言等功能&#xff0c;適合單元測試和集成測試。核心組件…

【線程安全問題的原因和方法】【java形式】【圖片詳解】

在本章節中采用實例圖片的方式&#xff0c;以一個學習者的姿態進行描述問題解決問題&#xff0c;更加清晰明了&#xff0c;以及過程中會發問的問題都會一一進行呈現 目錄 線程安全演示線程不安全情況圖片解釋&#xff1a; 將上述代碼進行修改【從并行轉化成穿行的方式】不會出…

Infinite you:flexible photo recrafting while preserving your identity

基于DiT的id保留圖像生成面臨著多種挑戰,缺乏定制模塊設計,模型擴展的困難以及高質量數據的匱乏,因此基于flux的解決方案是相對稀缺的,pulid-flux是基于flux的id保留的初步嘗試,包括instantx和xlabs-ai的flux.1-dev ip-adapters,現有方法在三個關鍵方面保險不足:1.身份相…

Unity 實現一個簡易可拓展性的對話系統

本人能力有限,一切實現僅供參考,如有不足還請斧正 起因是我看到學校社團內有人做了對話系統的分享,我想了想之前沒寫過這種東西,而Fungus插件教程太老了,NodeCanvas插件學習成本又比較高,我就干脆尋找資料 加上自己迭代一下,花了一天時間完成了這個對話系統 目錄 1.介紹 2.核…

linux常用指令(6)

今天我們繼續學習一些linux常用指令,豐富我們linux基礎知識,那么話不多說,來看. 1.cp指令 功能描述&#xff1a;拷貝文件到指定目錄 基本語法&#xff1a;cp [選項] source dest 常用選項&#xff1a;-r&#xff1a;遞歸復制整個文件夾 拷貝文件&#xff1a; 拷貝文件夾&am…

Vue 3 中的路由傳參詳解※※※※

前言 在Vue應用中&#xff0c;路由傳參是非常常見的需求&#xff0c;它允許我們在不同的組件之間傳遞數據。Vue Router提供了兩種主要的方式來傳遞參數&#xff1a;query參數和params參數。下面我們將詳細探討這兩種傳參方式的使用方法和注意事項。 一、query參數 Query參數…

如何創建一個socket服務器?

1. 導入必要的庫 首先&#xff0c;需要導入Python的socket庫&#xff0c;它提供了創建和管理socket連接的功能。 python import socket 2. 創建服務器端socket 使用socket.socket()函數創建一個服務器端的socket對象&#xff0c;指定協議族&#xff08;如socket.AF_INET表示…

lua垃圾回收

lua垃圾回收 lua 垃圾回收 lua 垃圾回收 collectgarbage(“count”)獲取當前lua腳本占用內存字節數(單位為KB)。 collectgarbage(“collect”)執行一次垃圾回收。 xxxnil 將變量置為空&#xff0c;會釋放內存。 lua中的機制和c#中回收機制很類似 解除羈絆(置為空)。 --垃圾回…

友思特應用 | 行業首創:基于深度學習視覺平臺的AI驅動輪胎檢測自動化

導讀 全球領先的輪胎制造商 NEXEN TIRE 在其輪胎生產檢測過程中使用了基于友思特伙伴Neurocle開發的AI深度學習視覺平臺&#xff0c;實現缺陷檢測率高達99.96%&#xff0c;是該行業首個使用AI平臺技術推動缺陷檢測自動化流程的企業。 將AI應用從輪胎開發擴展到制造過程 2024年…

前后端+數據庫的項目實戰:hbu迎新網-較復雜(下)javaweb

目錄 十一、實現對內容的富文本編輯&#xff08;換行、圖片顏色等等樣式&#xff09; &#xff08;1&#xff09;下載富文本編輯器&#xff0c;引入資源 &#xff08;2&#xff09;將原項目的內容部分替換為富文本編輯器 1、替換添加頁面 2、替換修改頁面&#xff08;和添…

腳本語言 Lua

概念 Lua由標準C編寫而成&#xff0c;幾乎在所有操作系統和平臺上都可以編譯、運行。Lua腳本可以很容易地被C/C 代碼調用&#xff0c;也可以反過來調用C/C的函數&#xff0c;這使得Lua在應用程序中可以被廣泛應用。Lua并沒有提供強大的庫&#xff0c;它是不適合作為開發獨立應…

【數據分享】2000—2024年我國鄉鎮的逐月歸一化植被指數(NDVI)數據(Shp/Excel格式)

之前我們分享過2000—2024年我國省市縣三級逐月歸一化植被指數&#xff08;NDVI&#xff09;數據&#xff0c;該數據是基于NASA定期發布的MOD13A3數據集中的月度NDVI柵格數據&#xff08;可查看之前的文章獲悉詳情&#xff09;計算得出。很多小伙伴拿到數據后反饋是否可以處理出…

【負載均衡系列】HAProxy

HAProxy(High Availability Proxy)是一款高性能的 ?TCP/HTTP 負載均衡器,專注于提供高可用性、靈活性和可靠性。以下是關于HAProxy的詳細解析,涵蓋其工作原理、工作機制、工作模式等核心方面: 一、HAProxy 工作原理 HAProxy的核心職責是將客戶端請求高效、可靠地分發到后…

輕松遷移 Elasticsearch 數據:如何將自建索引導出并導入到另一個實例

概述 在日常的 Elasticsearch 運維和數據管理中&#xff0c;數據遷移是一個常見的需求。無論是為了備份、升級&#xff0c;還是將數據從一個集群遷移到另一個集群&#xff0c;導出和導入索引數據都是至關重要的操作。本文將詳細介紹如何將自建 Elasticsearch 實例中的索引數據…

JVM 類加載器之間的層次關系,以及類加載的委托機制

JVM 類加載器之間存在一種層次關系&#xff0c;通常被稱為雙親委派模型 (Parent Delegation Model)。這種層次關系和委托機制是 Java 類加載機制的核心&#xff0c;對于保證 Java 程序的安全性和避免類沖突至關重要。 1. 類加載器的層次關系: JVM 中的類加載器&#xff08;Cl…

基于 Vue 3 的PDF和Excel導出

以下是基于 Vue 3 Composition API 的完整實現&#xff0c;包括 PDF 和 Excel 導出。 一、PDF 導出 (Vue 3) 安裝依賴 在項目中安裝相關庫&#xff1a; npm install html2canvas jspdf Vue 3 代碼實現 <template><div><div ref"pdfContent" cla…

【Jupyter】notebook無法顯示tqdm進度條

錯誤描述 from tqdm.notebook import tqdm 用的時候報錯&#xff1a; Error displaying widget解決方式 # 先裝nodejs conda install -c conda-forge nodejs20# 重裝ipywidgets pip uninstall ipywidgets pip install ipywidgets jupyter labextension install jupyter-wid…

ubuntu20如何升級nginx到最新版本(其它版本大概率也可以)

前言&#xff1a; Nginx非常常用&#xff0c;所以在網絡安全方面備受“關注”。其漏洞非常多&#xff0c;要經常保持軟件更新版本才能更好的保證安全。但是Ubuntu官網適配nginx非常慢&#xff0c;所以nginx官方也會推出針對主流Linux操作系統的包管理工具安裝方式。 步驟&…

word插入Mathtype公式居中和自動更新

word插入公式自動更新 前提&#xff1a;安裝Mathtype 1.word中查看頁的寬度 出現如下 2.設置樣式 出現這個窗口 給樣式隨便起個名字 3.修改樣式 3.1 設置兩個制表位 第二個 3.2 修改公式字體 如下所示 4. 修改公式格式 4.1在word中打開 Mathtype 4.2 修改公式的格式 變成…