首頁 > 後端開發 > Python教學 > 檢索增強生成 (RAG) 的終極指南

檢索增強生成 (RAG) 的終極指南

Barbara Streisand
發布: 2024-12-21 18:55:10
原創
839 人瀏覽過

像 OpenAI 的 ChatGPT 這樣的生成式 AI 模型的快速發展徹底改變了自然語言處理,使這些系統能夠產生連貫且上下文相關的響應。然而,即使是最先進的模型在處理特定領域的查詢或提供高度準確的資訊時也面臨限制。這通常會導致諸如幻覺之類的挑戰——模型產生不準確或捏造的細節的情況。

檢索增強生成(RAG),一個旨在彌合這一差距的創新框架。透過無縫整合外部資料來源,RAG 使生成模型能夠檢索即時、利基訊息,從而顯著提高其準確性和可靠性。

在本文中,我們將深入研究 RAG 的機制,探索其架構,並討論激發其創作靈感的傳統生成模型的限制。我們還將重點介紹實際實現、先進技術和評估方法,展示 RAG 如何改變人工智慧與專業數據互動的方式。

入門

目錄

  • 什麼是RAG
  • RAG 的架構
  • RAG 流程
  • RAG 與微調
  • RAG 的類型
  • RAG 的應用
  • 使用 RAG 建立 PDF 聊天系統
  • 資源

什麼是RAG

檢索增強生成(RAG)是一種先進的框架,透過整合外部資料的即時檢索來增強生成式人工智慧模型的能力。雖然生成模型擅長產生連貫的、類似人類的文本,但當要求提供準確、最新或特定領域的資訊時,它們可能會猶豫不決。這就是 RAG 介入的地方,確保回覆不僅具有創意,而且基於可靠且相關的來源。

RAG 透過將生成模型與檢索機制連接起來進行操作,通常由向量資料庫或搜尋系統提供支援。當收到查詢時,檢索元件會搜尋大量外部資料集以取得相關資訊。然後,產生模型綜合這些數據,產生既準確又具有上下文洞察力的輸出。

透過解決幻覺和有限領域知識等關鍵挑戰,RAG 釋放了生成模型在專業領域中脫穎而出的潛力。其應用涵蓋各個行業,從提供精確答案的自動化客戶支持,到使研究人員能夠按需獲取精選知識。 RAG 代表著在使 AI 系統在現實場景中更加聰明、值得信賴和有用方面向前邁出了重要一步。

RAG的架構

清楚了解 RAG 架構對於釋放其全部潛力和優勢至關重要。這個框架的核心是建立在兩個主要組件之上:檢索器和生成器,它們在無縫的資訊處理流程中協同工作。

整個過程如下圖:
The ultimate guide to Retrieval-Augmented Generation (RAG)
來源:https://weaviate.io/blog/introduction-to-rag

  • 檢索 - RAG 中的推理階段從檢索開始,其中從外部知識來源獲取與使用者查詢相關的資料。在基本的 RAG 設定中,通常使用相似性搜索,將查詢和外部資料嵌入到同一向量空間中以識別最接近的匹配。檢索器在取得文件方面發揮關鍵作用,採用稀疏檢索和密集檢索等方法。稀疏檢索使用TF-IDF 或BM25 等技術,依賴精確的單字匹配,但在同義詞和釋義方面遇到困難,而密集檢索則利用BERT 或RoBERTa 等轉換器模型來創建語義向量表示,從而實現更準確和細緻的匹配。
  • 增強 - 從外部來源檢索最相關的資料點後,增強過程透過將其嵌入到預先定義的提示範本中來合併此資訊。
  • 產生 - 在生成階段,模型使用增強提示,透過將其內部語言理解與檢索到的外部資料結合來製作連貫的、上下文準確的回應。雖然增強集成了外部事實,但生成將這些豐富的信息轉換為根據用戶查詢定制的自然的、類似人類的文本。

RAG製程

RAG 流程的所有階段和基本組成部分,如下圖所示。

The ultimate guide to Retrieval-Augmented Generation (RAG)
來源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 文件載入:RAG 流程的第一步涉及資料準備,包括從儲存中載入文件、提取、解析、清理和格式化文字以進行文件拆分。文字資料可以採用多種格式,例如純文字、PDF、Word 文件、CSV、JSON、HTML、Markdown 或程式碼。為法學碩士準備這些不同的來源通常需要透過提取、解析和清理將它們轉換為純文本。
  • 文件分割:透過文字分割或分塊將文件分成更小的、可管理的片段,這對於處理大型文件和遵守LLM 中的令牌限制(例如GPT-3 的2048個令牌)至關重要。策略包括固定大小或內容感知分塊,其方法取決於資料的結構和要求。 The ultimate guide to Retrieval-Augmented Generation (RAG)

將文件分成更小的區塊可能看起來很簡單,但需要仔細考慮語義,以避免不恰當地分割句子,這可能會影響後續步驟,例如回答問題。簡單的固定大小分塊方法可能會導致每個區塊中資訊的不完整。大多數文件分段演算法使用區塊大小和重疊,其中區塊大小由字元、單字或標記計數確定,而重疊透過在相鄰區塊之間共享文字來確保連續性。該策略保留了跨區塊的語義上下文。

  • 文字嵌入:文字區塊被轉換為向量嵌入,它以一種可以輕鬆比較語義相似性的方式表示每個區塊。向量嵌入將複雜資料(例如文字)映射到相似資料點聚集在一起的數學空間。此過程捕獲文本的語義,因此具有相似含義的句子,即使措辭不同,也會在向量空間中緊密地映射在一起。例如,「貓追老鼠」和「貓追囓齒動物」將被映射到附近的點,儘管它們的措辭不同。

The ultimate guide to Retrieval-Augmented Generation (RAG)
來源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 向量儲存:文件被分割並轉換為向量嵌入後,它們被儲存在向量儲存中,這是一個用於儲存和管理向量的專用資料庫。向量儲存可以有效搜尋相似向量,這對於 RAG 模型的執行至關重要。向量儲存的選擇取決於資料規模和可用運算資源等因素。

一些重要的向量資料庫是:

  • FAISS:FAISS 由 Facebook AI 開發,可有效管理大量高維度向量集合,並在高維度環境中執行相似性搜尋和聚類。它優化了記憶體使用和查詢持續時間,使其適合處理數十億個向量。
  • Chroma:Chroma 是一個開源記憶體向量資料庫,專為法學碩士應用程式而設計,為向量儲存、搜尋和檢索提供可擴展的平台。它支援雲端和本地部署,並且能夠處理各種資料類型和格式。
  • Weaviate:一個可以自架或完全管理的開源向量資料庫。它專注於高效能、可擴展性和靈活性,支援廣泛的資料類型和應用程式。它允許儲存向量和對象,從而實現基於向量和基於關鍵字的搜尋技術的組合。
  • Pinecone:基於雲端的託管向量資料庫,旨在簡化大規模機器學習應用程式的開發和部署。與許多向量資料庫不同,Pinecone 使用專有的封閉原始碼。它擅長處理高維向量,適用於相似性搜尋、推薦系統、個人化和語義搜尋等應用。 Pinecone 還具有單級過濾功能。
  • 文件檢索:資訊檢索系統中的檢索過程(例如文件搜尋或問答)從接收到查詢並使用與文件索引相同的嵌入模型轉換為向量時開始。目標是透過將查詢向量與索引(向量儲存)中儲存的區塊向量進行比較來傳回相關文件區塊。檢索器的作用是識別並傳回相關文件區塊的 ID,而不儲存文件。可以使用各種搜尋方法,例如相似性搜尋(基於餘弦相似性)和基於閾值的檢索,僅傳回超過特定相似性分數的文件。此外,LLM 輔助檢索對於涉及內容和元資料過濾的查詢非常有用。

The ultimate guide to Retrieval-Augmented Generation (RAG)
來源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 答案產生:在檢索過程中,相關文件區塊與使用者查詢結合,產生LLM的上下文和提示。最簡單的方法,在 LangChain 中被稱為「Stuff」方法,涉及將所有區塊集中到同一個上下文視窗中,以獲得直接、直接的答案。然而,由於上下文視窗的限制,這種方法難以應對大文檔量和複雜查詢。為了解決這個問題,可以使用 Map-reduce、Refine 和 Map-rerank 等替代方法。 Map-reduce 將文件單獨傳送給 LLM,然後合併回應。 Refine 會迭代更新提示以完善答案,而 Map-rerank 根據相關性對文件進行排名,非常適合多個令人信服的答案。

The ultimate guide to Retrieval-Augmented Generation (RAG)

RAG 與微調

RAG(檢索增強生成)和微調是擴展LLM能力的兩種關鍵方法,每種方法適合不同的場景。微調涉及對特定領域數據的法學碩士進行再培訓,以執行專門的任務,非常適合靜態、狹窄的用例,例如需要特定語氣或風格的品牌或創意寫作。然而,它成本高昂、耗時,且不適合動態、頻繁更新的數據。

另一方面,RAG 透過動態檢索外部資料而不修改模型權重來增強 LLM,使其具有成本效益,非常適合法律、財務或客戶服務應用程式等即時資料驅動環境。 RAG 使法學碩士能夠處理大型、非結構化的內部文件語料庫,與導航混亂的資料儲存庫的傳統方法相比,具有顯著的優勢。

微調擅長創造細緻、一致的輸出,而 RAG 透過利用外部知識庫提供最新、準確的資訊。在實踐中,RAG 通常是需要即時、適應性回應的應用程式的首選,特別是在管理大量非結構化資料的企業中。

RAG 的類型

檢索增強產生 (RAG) 方法有多種類型,每種方法都針對特定用例和目標量身定制。主要類型包括:

The ultimate guide to Retrieval-Augmented Generation (RAG)
資料來源:https://x.com/weaviate_io/status/1866528335884325070

  • 原生 RAG:指的是一種緊密整合的方法,其中檢索增強生成系統的檢索和生成組件被設計為在同一架構中無縫工作。與依賴外部工具或 API 的傳統實作不同,原生 RAG 優化了檢索機制和生成模型之間的交互,從而實現更快的處理並提高上下文相關性。這種方法通常使用記憶體處理或高度最佳化的本地資料庫,從而減少延遲和資源開銷。原生 RAG 系統通常針對特定用例量身定制,透過消除對第三方服務的依賴來提高效率、準確性和成本效益。
  • 檢索和重新排名 RAG:專注於改進檢索過程以提高準確性和相關性。在此方法中,根據查詢的語意相似性檢索初始文件或區塊集,通常由嵌入空間中的餘弦相似性決定。隨後,重新排序模型根據檢索到的文檔與查詢的上下文相關性對它們進行重新排序。此重新排名步驟通常利用深度學習模型或轉換器,從而允許在基本相似性指標之外進行更細緻的排名。透過優先考慮最相關的文檔,此方法可確保生成模型接收上下文豐富的輸入,從而顯著提高響應品質。
  • 多模態 RAG:透過將文字、影像、音訊或視訊等多種資料模態合併到檢索增強生成管道中,擴展了傳統的 RAG 範式。它允許系統檢索並產生整合不同形式資料的回應。例如,在涉及基於圖像的查詢的場景中,系統可能會檢索相關圖像以及文字內容,以創建更全面的答案。多模態 RAG 在電子商務、醫​​學影像和多媒體內容分析等領域特別有用,這些領域的見解通常依賴文字和視覺資訊的組合。
  • Graph RAG:利用基於圖的資料結構根據實體之間的關係和連接來建模和檢索資訊。在這種方法中,知識被組織為一個圖,其中節點表示實體(例如概念、文件或物件),邊捕獲它們的關係(例如語義、層次或時間)。處理查詢以識別與輸入相關的子圖或路徑,然後將這些子圖輸入生成模型。這種方法在科學研究、社交網絡和知識管理等領域尤其有價值,這些領域的關係洞察力至關重要。
  • 混合 RAG:結合多種檢索技術,例如密集檢索和稀疏檢索,以增強不同查詢類型的效能。密集檢索使用向量嵌入來捕獲語義相似性,而稀疏檢索則依賴基於關鍵字的方法(例如 BM25)來實現精確匹配。透過整合這些方法,混合 RAG 平衡了精確度和召回率,使其在查詢可能高度具體或抽象的場景中具有通用性。它在異質資料環境中特別有效,確保在檢索過程中同時考慮高階語義和特定關鍵字。
  • 代理 RAG(路由器):採用決策層根據查詢的特性動態地將查詢路由到適當的檢索和產生模組。路由器分析傳入的查詢以確定最佳處理路徑,這可能涉及不同的檢索方法、資料來源,甚至專門的生成模型。這種方法確保系統根據每個查詢的特定需求自訂其操作,從而提高不同應用程式的效率和準確性。
  • 代理 RAG(多代理 RAG):多代理 RAG 涉及一個協作框架,其中多個專門代理處理檢索和生成過程的不同方面。每個代理程式負責特定的任務,例如從特定網域檢索資料、對結果重新排序或以特定樣式產生回應。這些代理商進行溝通和協作以提供有凝聚力的輸出。多代理 RAG 對於複雜的多域查詢特別強大,因為它使系統能夠利用不同代理的專業知識來提供全面且細緻入微的回應。

RAG的應用

檢索增強生成(RAG)框架由於其能夠將外部知識動態整合到生成語言模型中,因此在各個行業中具有廣泛的應用。以下是一些突出的應用:

  • 客戶支援和服務:RAG 系統廣泛用於客戶支持,以創建能夠透過從產品手冊、知識庫和公司政策文件中檢索相關資料來回答複雜查詢的智慧聊天機器人。這可確保客戶收到準確且最新的訊息,從而增強他們的體驗。
  • 法律文件分析:在法律領域,RAG 可以從大量判例法、合約和法律文件中解析、檢索並產生摘要或答案。它對於進行法律研究、起草合約和確保遵守法規特別有用。
  • 財務分析:RAG 在金融服務中用於分析收益報告、市場趨勢和監管文件。透過檢索相關財務數據,它可以幫助分析師產生見解、報告,甚至對有關市場表現的查詢提供即時答案。
  • 醫療保健和醫療診斷:在醫療保健中,RAG 用於檢索和綜合來自醫學文獻、患者記錄和治療指南的資訊。它有助於診斷支持、藥物發現和個人化治療建議,確保臨床醫生獲得最新、最相關的數據。
  • 教育與電子學習:RAG 驅動的工具透過檢索課程材料並產生量身定制的答案或學習指南來協助個人化教育。他們可以根據用戶查詢提供上下文解釋和動態內容來增強學習平台。
  • 電子商務和零售:在電子商務中,RAG 系統透過從目錄和客戶評論中檢索資料來改進產品搜尋和推薦引擎。它們還支援對話式購物助理,根據用戶偏好提供個人化的產品建議。
  • 智慧虛擬助理:RAG 透過提供準確且與上下文相關的回應來增強 Alexa 或 Siri 等虛擬助理,特別是對於需要外部知識的查詢,例如即時天氣更新或本地商業資訊。

使用RAG建立PDF聊天系統

在本節中,我們將開發一個 Streamlit 應用程序,能夠理解 PDF 的內容並使用檢索增強生成 (RAG) 根據該內容響應用戶查詢。該實施利用 LangChain 平台來促進與法學碩士和向量商店的互動。我們將利用 OpenAI 的 LLM 及其嵌入模型來建立 FAISS 向量存儲,以實現高效的資訊檢索。

安裝依賴項

  • 透過執行以下命令來建立並啟動虛擬環境。
python -m venv venv
source venv/bin/activate #for ubuntu
venv/Scripts/activate #for windows
登入後複製
  • 使用 pip 安裝 langchain、langchain_community、openai、faiss-cpu、PyPDF2、streamlit、python-dotenv、tiktoken 函式庫。
pip install langchain langchain_community openai faiss-cpu PyPDF2 streamlit python-dotenv tiktoken
登入後複製

設定環境和憑證

  • 建立一個名為 .env 的檔案。該文件將儲存您的環境變量,包括 OpenAI 金鑰、模型和嵌入。
  • 開啟 .env 檔案並新增以下程式碼以指定您的 OpenAI 憑證:
OPENAI_API_KEY=sk-proj-xcQxBf5LslO62At...
OPENAI_MODEL_NAME=gpt-3.5-turbo
OPENAI_EMBEDDING_MODEL_NAME=text-embedding-3-small
登入後複製

導入環境變數

  • 建立一個名為app.py的檔案。
  • 將 OpenAI 憑證加入環境變數。
from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")
登入後複製

導入所需的庫

導入用於建立應用程式、處理 PDF 的基本庫,例如 langchain、streamlit、pyPDF。

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css
登入後複製

定義從 PDF 中提取文字的函數

  • 使用 PyPDF2 從上傳的 PDF 檔案中擷取文字。
def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text
登入後複製

將擷取的文字分割成區塊

使用 LangChain 的 CharacterTextSplitter 將大文字分成更小的、可管理的區塊。

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks
登入後複製

為文字嵌入建立向量存儲

產生文字區塊的嵌入並使用 FAISS 將它們儲存在向量資料庫中。

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore
登入後複製

建構會話檢索鏈

定義一個從向量儲存中檢索資訊並透過 LLM 與使用者互動的鏈。

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain
登入後複製

處理使用者查詢

處理使用者輸入,將其傳遞到對話鏈,並更新聊天記錄。

def handle_user_input(question):
    try:
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on Process.')
登入後複製

為簡化聊天建立自訂 HTML 模板

要使用 CSS 為使用者和機器人訊息建立自訂聊天介面,請設計自訂範本並使用 CSS 對其進行樣式設定。

  • 建立一個名為 htmlTemplates.py 的檔案並加入以下程式碼。
css = '''
<style>
.chat-message {
    padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem; display: flex
}
.chat-message.user {
    background-color: #2b313e
}
.chat-message.bot {
    background-color: #475063
}
.chat-message .avatar {
  width: 10%;
}
.chat-message .avatar img {
  max-width: 30px;
  max-height: 30px;
  border-radius: 50%;
  object-fit: cover;
}
.chat-message .message {
  width: 90%;
  padding: 0 1rem;
  color: #fff;
}
'''

bot_template = '''
<div>



<h3>
  
  
  Displaying chat history
</h3>

<p>Show the user and AI conversation history in a reverse order with HTML templates for formatting.<br>
</p>

<pre class="brush:php;toolbar:false">def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)
登入後複製

建立 Streamlit 應用程式介面

設定應用程式主介面,用於檔案上傳、問題輸入和聊天記錄顯示。

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()
登入後複製

PDF 聊天應用程式的完整程式碼

以下是 PDF 聊天應用程式的完整程式碼實作。它將環境變數設定、文字擷取、向量儲存和 RAG 功能整合到簡化的解決方案中:

from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css

def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain

def handle_user_input(question):
    try: 
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on OK.')

def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()

登入後複製

運行應用程式

使用以下命令透過 Streamlit 執行應用程式。

streamlit run app.py
登入後複製

您將得到以下輸出,
The ultimate guide to Retrieval-Augmented Generation (RAG)

感謝您閱讀這篇文章! !

感謝 Gowri M Bhatt 審閱內容。

如果您喜歡這篇文章,請點擊心形按鈕♥並分享以幫助其他人找到它!

本教學的完整原始碼可以在這裡找到,

codemaker2015/pdf-chat-using-RAG | github.com

資源

  • RAG 與 LLM 業務流程自動化:技術策略 - Grid Dynamics | www.griddynamics.com
  • 檢索增強產生 (RAG) 簡介 |維阿維
  • 增強語言模型的技術、挑戰與未來 - 梯度流
  • 行星規模檢索增強一代|弧形

以上是檢索增強生成 (RAG) 的終極指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板