文章目錄
- 前言
- 數據存放
- 申請api
- 開始代碼
- 安裝依賴
- 從文件夾中讀取文檔
- 文檔切塊
- 將分割嵌入并存儲在向量庫中
- 檢索部分代碼
- 構造用戶接口
- 演示提示
- 整體代碼
前言
本章只是簡單使用rag的一個示例,為了引出以后的學習,將整個rag的流程串起來
數據存放
一個示例的文件夾OneFlower下,存放了三種不同類型的文檔:
申請api
本文檔中使用的在線api為gpt4,所以需要先申請,如果是國內也可以按照文檔使用glm:glm使用文檔
開始代碼
下面會對每一部分的代碼進行說明
安裝依賴
pip install langchain
pip install openai
pip install qdrant-client
從文件夾中讀取文檔
通過便利文件夾OneFlower下,找到所以文件,通過文件的后綴,使用不同的解析器,將解析后的文檔存放到documents中
import os
os.environ["OPENAI_API_KEY"] = 'sk-openai的key'# 1.Load 導入Document Loaders
from langchain.document_loaders import PyPDFLoader
from langchain.document_loaders import Docx2txtLoader
from langchain.document_loaders import TextLoader# 加載Documents
documents = []
for file in os.listdir('OneFlower'): if file.endswith('.pdf'):pdf_path = './OneFlower/' + fileloader = PyPDFLoader(pdf_path)documents.extend(loader.load())elif file.endswith('.docx') or file.endswith('.doc'):doc_path = './OneFlower/' + fileloader = Docx2txtLoader(doc_path)documents.extend(loader.load())elif file.endswith('.txt'):text_path = './OneFlower/' + fileloader = TextLoader(text_path)documents.extend(loader.load())
文檔切塊
一大片的文檔對檢索是不友好的,我們需要按照小塊進行切分,也就是chunk,每塊的大小為200個字符(并且在api中對亂碼進行了處理),塊與塊之間有10個長度的重疊,這種形式的切塊使用RecursiveCharacterTextSplitter這個api來操作
# 2.Split 將Documents切分成塊以便后續進行嵌入和向量存儲
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=10)
chunked_documents = text_splitter.split_documents(documents)
將分割嵌入并存儲在向量庫中
向量庫我們使用的是Qdrant,當然還可以使用faiss或者chromedb都是可以的
# 3.Store 將分割嵌入并存儲在矢量數據庫Qdrant中
from langchain.vectorstores import Qdrant
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Qdrant.from_documents(documents=chunked_documents, # 以分塊的文檔embedding=OpenAIEmbeddings(), # 用OpenAI的Embedding Model做嵌入location=":memory:", # in-memory 存儲collection_name="my_documents",) # 指定collection_name
檢索部分代碼
這個部分,我們主要狗見了一個大模型的檢索,他接收的是vectorstore返回的檢索,MultiQueryRetriever的意思是我們需要llm幫我們生成多個MultiQuery,比如:
- “區塊鏈如何運作?”
- “區塊鏈的核心技術是什么?”
- “區塊鏈的數據結構是如何設計的?”
然后MultiQueryRetriever 依次執行這些查詢,并合并結果,最終返回更多相關的文檔,提高召回率。
logging的引入,方便我們進行提問的輸出
# 4. Retrieval 準備模型和Retrieval鏈
import logging # 導入Logging工具
from langchain.chat_models import ChatOpenAI # ChatOpenAI模型
from langchain.retrievers.multi_query import MultiQueryRetriever # MultiQueryRetriever工具
from langchain.chains import RetrievalQA # RetrievalQA鏈# 設置Logging
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)# 實例化一個大模型工具 - OpenAI的GPT-3.5
llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)# 實例化一個MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectorstore.as_retriever(), llm=llm)# 實例化一個RetrievalQA鏈
# qa_chain = RetrievalQA.from_chain_type(llm,retriever=vectorstore.as_retriever()) # 單個的問題
qa_chain = RetrievalQA.from_chain_type(llm,retriever=retriever_from_llm)
構造用戶接口
輸出一個input,讓用戶進行提問,只要不是exit就繼續,ask_question是執行langchain的調用
# 5. 問答展示
def ask_question(query):# 使用RetrievalQA鏈來獲取答案response = qa_chain(query)# 返回得到的答案return response# 為用戶提供交互界面進行問答
while True:# 獲取用戶的問題user_query = input("請隨意提問 (或者輸入'exit'退出): ")# 如果用戶輸入"exit",則退出循環if user_query.lower() == 'exit':break# 使用定義的函數獲取答案,并打印answer = ask_question(user_query)print("答案:", answer)print("謝謝使用 QA 系統!")
演示提示
對應pdf文檔中可以看到對應的內容
整體代碼
整體代碼如下,方便在PyCharm中直接運行
import os
os.environ["OPENAI_API_KEY"] = 'sk-openai的key'# 1.Load 導入Document Loaders
from langchain.document_loaders import PyPDFLoader
from langchain.document_loaders import Docx2txtLoader
from langchain.document_loaders import TextLoader# 加載Documents
documents = []
for file in os.listdir('OneFlower'): if file.endswith('.pdf'):pdf_path = './OneFlower/' + fileloader = PyPDFLoader(pdf_path)documents.extend(loader.load())elif file.endswith('.docx') or file.endswith('.doc'):doc_path = './OneFlower/' + fileloader = Docx2txtLoader(doc_path)documents.extend(loader.load())elif file.endswith('.txt'):text_path = './OneFlower/' + fileloader = TextLoader(text_path)documents.extend(loader.load())import os# 設置環境變量
os.environ['http_proxy'] = 'http://127.0.0.1:7890'
os.environ['https_proxy'] = 'http://127.0.0.1:7890'
os.environ['all_proxy'] = 'http://127.0.0.1:7890'# export HTTP_PROXY=http://127.0.0.1:7890; #換成你自己的代理地址
# export HTTPS_PROXY=http://127.0.0.1:7890; #換成你自己的代理地址
# export ALL_PROXY=socks5://127.0.0.1:7890#換成你自己的代理地址# 2.Split 將Documents切分成塊以便后續進行嵌入和向量存儲
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=10)
chunked_documents = text_splitter.split_documents(documents)# 3.Store 將分割嵌入并存儲在矢量數據庫Qdrant中
from langchain.vectorstores import Qdrant
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Qdrant.from_documents(documents=chunked_documents, # 以分塊的文檔embedding=OpenAIEmbeddings(), # 用OpenAI的Embedding Model做嵌入location=":memory:", # in-memory 存儲collection_name="my_documents",) # 指定collection_name# 4. Retrieval 準備模型和Retrieval鏈
import logging # 導入Logging工具
from langchain.chat_models import ChatOpenAI # ChatOpenAI模型
from langchain.retrievers.multi_query import MultiQueryRetriever # MultiQueryRetriever工具
from langchain.chains import RetrievalQA # RetrievalQA鏈# 設置Logging
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)# 實例化一個大模型工具 - OpenAI的GPT-3.5
llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)# 實例化一個MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectorstore.as_retriever(), llm=llm)# 實例化一個RetrievalQA鏈
# qa_chain = RetrievalQA.from_chain_type(llm,retriever=vectorstore.as_retriever())
qa_chain = RetrievalQA.from_chain_type(llm,retriever=retriever_from_llm)# 5. 問答展示
def ask_question(query):# 使用RetrievalQA鏈來獲取答案response = qa_chain(query)# 返回得到的答案return response# 為用戶提供交互界面進行問答
while True:# 獲取用戶的問題user_query = input("請隨意提問 (或者輸入'exit'退出): ")# 如果用戶輸入"exit",則退出循環if user_query.lower() == 'exit':break# 使用定義的函數獲取答案,并打印answer = ask_question(user_query)print("答案:", answer)print("謝謝使用 QA 系統!")
資源csdn鏈接:等待更新