RAG是什么:從理論到LangChain實(shí)踐

作者:zhilong · 2025-02-05 · 閱讀時(shí)間:6分鐘

檢索增強(qiáng)生成(RAG)是一種創(chuàng)新的技術(shù),通過(guò)結(jié)合生成模型和檢索模塊,為大語(yǔ)言模型(LLM)提供額外的外部知識(shí)支持。這種方法旨在提升生成模型的精確性和上下文相關(guān)性,同時(shí)減少誤導(dǎo)性信息的可能性。在本文中,我們將深入探討RAG的理論背景、實(shí)現(xiàn)方法以及在Python中的具體應(yīng)用。通過(guò)結(jié)合OpenAI、Weaviate和LangChain,我們將展示如何構(gòu)建一個(gè)完整的RAG流程。

理解RAG的基本概念

檢索增強(qiáng)生成(RAG)作為一種新興的技術(shù),旨在為大語(yǔ)言模型(LLM)提供額外的外部知識(shí)支持,以生成更為精確和上下文相關(guān)的回答。傳統(tǒng)的大語(yǔ)言模型通常依賴于訓(xùn)練數(shù)據(jù)的廣泛性和多樣性,但在處理特定領(lǐng)域或?qū)崟r(shí)更新的信息時(shí)可能會(huì)遇到困難。RAG通過(guò)引入外部知識(shí)源來(lái)彌補(bǔ)這一不足。

RAG的起源

RAG技術(shù)最早由Lewis等人在2020年的論文《知識(shí)密集型NLP任務(wù)的檢索增強(qiáng)生成》中提出。該研究通過(guò)結(jié)合生成模型和檢索模塊,能夠從易于更新的外部知識(shí)源中獲取額外信息,從而提升生成模型的性能。RAG的核心在于將事實(shí)性知識(shí)與模型的推理能力相分離,這一點(diǎn)類似于開卷考試中學(xué)生可以查閱資料的方式。

RAG的工作流程詳解

在RAG的工作流程中,用戶的查詢經(jīng)過(guò)向量數(shù)據(jù)庫(kù)的檢索,再通過(guò)填充提示,最終生成回答。具體步驟如下:

檢索步驟

在第一步,系統(tǒng)將用戶的查詢通過(guò)嵌入模型轉(zhuǎn)換為向量,并在向量數(shù)據(jù)庫(kù)中進(jìn)行比對(duì)。通過(guò)相似性搜索,系統(tǒng)可以找到數(shù)據(jù)庫(kù)中最匹配的前k個(gè)數(shù)據(jù)。這一過(guò)程確保了查詢與外部知識(shí)源的相關(guān)性。

增強(qiáng)步驟

在檢索到相關(guān)信息后,系統(tǒng)將用戶的查詢和檢索到的額外信息一起嵌入到一個(gè)預(yù)設(shè)的提示模板中。這一過(guò)程被稱為增強(qiáng),旨在為生成模型提供更為完整的上下文信息。

生成步驟

最后,經(jīng)過(guò)檢索增強(qiáng)的提示內(nèi)容會(huì)被輸入到大語(yǔ)言模型中,以生成最終的輸出。通過(guò)這一流程,生成模型能夠結(jié)合外部知識(shí)源,實(shí)現(xiàn)更高效的回答生成。

基于LangChain的RAG實(shí)現(xiàn)

在這部分中,我們將展示如何利用Python結(jié)合OpenAI的大語(yǔ)言模型、Weaviate的向量數(shù)據(jù)庫(kù)以及LangChain進(jìn)行RAG流程的實(shí)現(xiàn)。LangChain作為一個(gè)強(qiáng)大的編排工具,可以幫助我們協(xié)調(diào)各個(gè)組件的工作。

準(zhǔn)備工作

在開始之前,請(qǐng)確保您的系統(tǒng)中已安裝以下Python包:

  • langchain —— 用于整體編排
  • openai —— 提供嵌入模型和大語(yǔ)言模型
  • weaviate-client —— 用于操作向量數(shù)據(jù)庫(kù)
#!pip install langchain openai weaviate-client

在項(xiàng)目的根目錄下設(shè)置OpenAI的API密鑰,確保能夠訪問(wèn)相關(guān)服務(wù)。

OPENAI_API_KEY=""

數(shù)據(jù)準(zhǔn)備和加載

首先,我們需要建立一個(gè)向量數(shù)據(jù)庫(kù),作為外部知識(shí)源,包含所有必要的額外信息。以下步驟將指導(dǎo)您如何收集、分塊和嵌入數(shù)據(jù)。

收集和加載數(shù)據(jù)

在這個(gè)示例中,我們使用2022年拜登總統(tǒng)的國(guó)情咨文作為背景材料。文本數(shù)據(jù)可以通過(guò)LangChain的DocumentLoader加載。

import requests
from langchain.document_loaders import TextLoader

url = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"
res = requests.get(url)
with open("state_of_the_union.txt", "w") as f:
    f.write(res.text)

loader = TextLoader('./state_of_the_union.txt')
documents = loader.load()

文本分塊

由于文檔的原始大小超出了LLM的處理能力,我們需要將其切割成更小的片段。使用LangChain的CharacterTextSplitter進(jìn)行分塊。

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)

嵌入和存儲(chǔ)

為了實(shí)現(xiàn)對(duì)文本塊的語(yǔ)義搜索,需要為每個(gè)塊生成向量嵌入,并將它們存儲(chǔ)在Weaviate向量數(shù)據(jù)庫(kù)中。

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
import weaviate
from weaviate.embedded import EmbeddedOptions

client = weaviate.Client(
  embedded_options = EmbeddedOptions()
)

vectorstore = Weaviate.from_documents(
    client = client,
    documents = chunks,
    embedding = OpenAIEmbeddings(),
    by_text = False
)

構(gòu)建RAG流程

一旦向量數(shù)據(jù)庫(kù)準(zhǔn)備好,我們就可以將它設(shè)定為檢索組件,通過(guò)語(yǔ)義相似度檢索出額外的上下文信息。

檢索

retriever = vectorstore.as_retriever()

增強(qiáng)

準(zhǔn)備一個(gè)提示模板,以便用額外的上下文信息來(lái)增強(qiáng)原始的提示。

from langchain.prompts import ChatPromptTemplate

template = """You are an assistant for question-answering tasks.

Use the following pieces of retrieved context to answer the question.

If you don't know the answer, just say that you don't know.

Use three sentences maximum and keep the answer concise.

Question: {question}

Context: {context}

Answer:

"""
prompt = ChatPromptTemplate.from_template(template)

print(prompt)

生成

在RAG管道的構(gòu)建過(guò)程中,通過(guò)將檢索器、提示模板與大語(yǔ)言模型結(jié)合來(lái)形成一個(gè)序列。

from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

rag_chain = (
    {"context": retriever,  "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

query = "What did the president say about Justice Breyer"
rag_chain.invoke(query)

總結(jié)與展望

本文詳細(xì)介紹了RAG技術(shù)的理論背景、實(shí)現(xiàn)方法以及具體應(yīng)用。在快速變化的信息時(shí)代,RAG為大語(yǔ)言模型的應(yīng)用提供了一種靈活且高效的解決方案。未來(lái),隨著技術(shù)的不斷發(fā)展,RAG可能在更多領(lǐng)域展現(xiàn)其潛力。

FAQ

  1. 問(wèn):RAG與傳統(tǒng)的微調(diào)方法有何不同?

    • 答:RAG通過(guò)結(jié)合外部知識(shí)源實(shí)現(xiàn)信息的快速更新,而微調(diào)則需要重新訓(xùn)練模型,成本更高且不夠靈活。
  2. 問(wèn):如何確保RAG中的外部知識(shí)庫(kù)是最新的?

    • 答:通過(guò)定期更新向量數(shù)據(jù)庫(kù)中的數(shù)據(jù),可以確保RAG使用的外部知識(shí)庫(kù)是最新的。
  3. 問(wèn):RAG可以應(yīng)用于哪些領(lǐng)域?

    • 答:RAG可以應(yīng)用于需要實(shí)時(shí)更新信息的領(lǐng)域,如新聞、金融和醫(yī)療等。
  4. 問(wèn):RAG的實(shí)現(xiàn)需要什么樣的硬件支持?

    • 答:RAG的實(shí)現(xiàn)主要依賴于大語(yǔ)言模型和向量數(shù)據(jù)庫(kù)的支持,通常需要較強(qiáng)的計(jì)算能力和存儲(chǔ)資源。
  5. 問(wèn):使用RAG時(shí)需要注意哪些問(wèn)題?

    • 答:確保外部知識(shí)源的準(zhǔn)確性和及時(shí)性是使用RAG時(shí)需要特別關(guān)注的問(wèn)題。