提示工程——檢索增強(qiáng)生成(RAG)
隨著GPT-3等大語言模型的出現(xiàn),自然語言處理(NLP)領(lǐng)域取得了重大突破。這些語言模型具有生成類人文本的能力,并且已經(jīng)在各種場景中得到應(yīng)用,例如:聊天機(jī)器人、翻譯。
然而,當(dāng)涉及到專業(yè)化和定制化的應(yīng)用場景時(shí),通用的大語言模型可能在專業(yè)知識方面會有所不足。用專業(yè)的語料庫對這些模型進(jìn)行微調(diào)往往昂貴且耗時(shí)。“檢索增強(qiáng)生成”(RAG)為專業(yè)化應(yīng)用提供了一個(gè)新技術(shù)方案。
下面我們主要介紹RAG如何工作,并通過一個(gè)實(shí)際的例子,將產(chǎn)品手冊作為專業(yè)語料庫,使用GPT-3.5 Turbo來作為問答模型,驗(yàn)證其有效性。
案例:開發(fā)一個(gè)聊天機(jī)器人,可以回答有關(guān)特定產(chǎn)品的知識。該企業(yè)的產(chǎn)品自己獨(dú)特的用戶手冊。
RAG介紹
RAG 提供了一個(gè)有效的方式來解決在特定領(lǐng)域的問答,主要將行業(yè)知識轉(zhuǎn)化為向量進(jìn)行存儲和檢索,通過知識檢索的結(jié)果與用戶問題結(jié)合形成Prompt,最后利用大模型生成合適的回答。檢索機(jī)制與語言模型的相結(jié)合,增強(qiáng)了大模型的響應(yīng)能力。
下面是創(chuàng)建聊天機(jī)器人程序的步驟:
- 讀取PDF(用戶手冊PDF文件)并使用chunk_size為1000個(gè)令牌進(jìn)行令牌化。
- 創(chuàng)建向量(可以使用OpenAI EmbeddingsAPI來創(chuàng)建向量)。
- 在本地向量庫中存儲向量。我們將使用ChromaDB作為向量數(shù)據(jù)庫(向量數(shù)據(jù)庫也可以使用Pinecone或其他產(chǎn)品替代)。
- 用戶發(fā)出具有查詢/問題的提示。
- 根據(jù)用戶的問題從向量數(shù)據(jù)庫檢索出知識上下文數(shù)據(jù)。這個(gè)知識上下文數(shù)據(jù)將在后續(xù)步驟中與提示詞結(jié)合使用,來增強(qiáng)提示詞,通常被稱為上下文豐富。
- 提示詞包含用戶問題和增強(qiáng)的上下文知識一起被傳遞給LLM
- LLM 基于此上下文進(jìn)行回答。
動(dòng)手開發(fā)
(1)設(shè)置Python虛擬環(huán)境 設(shè)置一個(gè)虛擬環(huán)境來沙箱化我們的Python,以避免任何版本或依賴項(xiàng)沖突。執(zhí)行以下命令以創(chuàng)建新的Python虛擬環(huán)境。
pip install virtualenv
python3 -m venv ./venv
source venv/bin/activate
(2)創(chuàng)建OpenAI密鑰
需要一個(gè)OpenAI密鑰來訪問GPT。
(3)安裝依賴庫
安裝程序需要的各種依賴項(xiàng)。包括以下幾個(gè)庫:
- lanchain:一個(gè)開發(fā)LLM應(yīng)用程序的框架。
- chromaDB:這是用于持久化向量嵌入的VectorDB。
- unstructured:用于預(yù)處理Word/PDF文檔。
- tiktoken: Tokenizer framework
- pypdf:讀取和處理PDF文檔的框架。
- openai:訪問OpenAI的框架。
pip install langchain
pip install unstructured
pip install pypdf
pip install tiktoken
pip install chromadb
pip install openai
創(chuàng)建一個(gè)環(huán)境變量來存儲OpenAI密鑰。
export OPENAI_API_KEY=<OPENAI-KEY>
(4)將用戶手冊PDF文件轉(zhuǎn)化為向量并將其存儲在ChromaDB中
導(dǎo)入所有將要使用的依賴庫和函數(shù)。
import os
import openai
import tiktoken
import chromadb
from langchain.document_loaders import OnlinePDFLoader, UnstructuredPDFLoader, PyPDFLoader
from langchain.text_splitter import TokenTextSplitter
from langchain.memory import ConversationBufferMemory
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.llms import OpenAI
from langchain.chains import ConversationalRetrievalChain
讀取PDF,標(biāo)記化文檔并拆分文檔。
loader = PyPDFLoader("Clarett.pdf")
pdfData = loader.load()
text_splitter = TokenTextSplitter(chunk_size=1000, chunk_overlap=0)
splitData = text_splitter.split_documents(pdfData)
創(chuàng)建一個(gè)chroma集合,和一個(gè)存儲chroma數(shù)據(jù)的本地目錄。然后,創(chuàng)建一個(gè)向量(embeddings)并將其存儲在ChromaDB中。
collection_name = "clarett_collection"
local_directory = "clarett_vect_embedding"
persist_directory = os.path.join(os.getcwd(), local_directory)
openai_key=os.environ.get('OPENAI_API_KEY')
embeddings = OpenAIEmbeddings(openai_api_key=openai_key)
vectDB = Chroma.from_documents(splitData,
embeddings,
collection_name=collection_name,
persist_directory=persist_directory
)
vectDB.persist()
執(zhí)行此代碼后,您應(yīng)該看到一個(gè)已經(jīng)創(chuàng)建好的文件夾,用于存儲向量。
將向量嵌入存儲在ChromaDB后,接著使用LangChain中的ConversationalRetrievalChain API來啟動(dòng)一個(gè)聊天歷史組件。
memory = ConversationBufferMemory(memory_key=
"chat_history"
, return_messages=True)
chatQA = ConversationalRetrievalChain.from_llm(
OpenAI(openai_api_key=openai_key,
temperature=0, model_name="gpt-3.5-turbo"),
vectDB.as_retriever(),
memory=memory)
初始化了langchan之后,我們可以使用它來聊天/Q A。下面的代碼中,接受用戶輸入的問題,并在用戶輸入'done'之后,將問題傳遞給LLM,以獲得答復(fù)并打印出來。
chat_history = []
qry = ""
while qry != 'done':
qry = input('Question: ')
if qry != exit:
response = chatQA({"question": qry, "chat_history": chat_history})
print(response["answer"])
總之
RAG將GPT等語言模型的優(yōu)勢與信息檢索的優(yōu)勢結(jié)合在一起。通過使用特定的知識上下文的信息提高提示詞的豐富程度,使語言模型能夠生成更準(zhǔn)確的和知識上下文相關(guān)的回答。RAG提供了一種比“微調(diào)”更高效且具有成本效益的解決方案,為行業(yè)應(yīng)用或企業(yè)應(yīng)用提供可定制化的交互方案。