[LangChain-01] RAG實戰第一站
透過製作筆記過程,加深學習記憶。
適合閱讀此篇筆記的人:沒有接觸過RAG或LLM的開發人員。
Source: https://python.langchain.com/docs/use_cases/question_answering/
RAG 檢索增強生成
RAG是利用額外資料來增強 LLM 知識的技術。
額外資料可以是:
- 公司內部的文件、手冊。
- 外部公開的資料庫,如法規條文、財報資訊。
- Google搜尋結果 (透過API)。
- DB Schema。
金融業使用RAG原因,通常為資安、個資與機密資料保護,而採取的解決方式。
— RAG檢索的資料可以留存於地端。
RAG的步驟(官方文件說明):
- RAG主要步驟為左圖,進行檢索(查詢),將檢索到的資料,連同一開始的問題一起丟給LLM進行回答。
- 右圖檢索資料前處理,讀取各種格式資料,將讀取的資料切成一小段一小段的文本資料,進行embedding,儲存到向量資料庫。
動手試試
官方sample code
import os
# for LLM model
os.environ["OPENAI_API_KEY"] = "填入你的OpenAI API KEY"
# for langSmith (可以不使用)
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "填入你的LangSmith API KEY(非必要)"
import bs4
from langchain import hub
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
# 讀取資料,轉為向量儲存
loader = WebBaseLoader(
web_path=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("post-content", "post-title", "post-header")
)
)
)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
print('完成向量化')
# 進行檢索與生成
retriever = vectorstore.as_retriever()
prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
print("完成建立RAG")
result = rag_chain.invoke("What is Task Decomposition? 請用繁體中文回答。")
print(result)
Output:
如有設定LangSmith,可以更容易檢視背後運作的資料流與耗時成本:
其中map:key:context為在這個input問題下,
參考了哪一段文字來讓LLM思考如何回答問題。
而我們可以看最後丟給OpenAI處理的Prompt有完整的格式,
請GPT扮演QA助手,要依據參考資料(Context)來回答問題(Question)。
嗯? 這個prompt格式從哪裡來的?
Ans: https://smith.langchain.com/hub/rlm/rag-prompt?organizationId=ab4ba6d8-e630-52fc-9341-901fea3e9907
一個在資料前處理的重點回顧:
當要檢索的文本太長怎麼辦?
切分資料!
我們在使用gpt-3.5的API目前仍需要考量文本長度,因此會需要在前處理時分割文本成等長的文字段落。完整的解答可以參考官網的步驟解說:
以上是一個最小的RAG使用範例。感謝閱讀~