引言
- 介紹本地知識庫的概念和用途
在現代信息時代,我們面臨著海量的數據和信息,如何有效地管理和利用這些信息成為一項重要的任務。本地知識庫是一種基于本地存儲的知識管理系統,旨在幫助用戶收集、組織和檢索大量的知識和信息。它允許用戶在本地環境中構建和管理自己的知識資源,以便更高效地進行信息處理和決策。
本地知識庫通常采用數據庫、索引和搜索技術,以構建一個結構化的存儲系統,使用戶可以快速地訪問和查詢所需的信息。
- 引出使用GPT-3.5、LangChain和FAISS構建本地知識庫的動機
當面臨一個知識類問題時,我們往往需要利用自己獲取到的信息加以總結,對海量信息中包含的要點進行快速地查詢和了解,而現在出現的GPT-3.5技術則能夠使得用戶向語言模型提問并得到一個回答。LangChain則是對大語言模型技術所用到的一些功能進行了統一的封裝,這使得我們可以利用本地的知識資源,以獲得我們需要的信息,FAISS則是一個可以存儲這種類型數據的向量數據庫。
ChatGPT
ChatGPT 是由 OpenAI 開發的一種高級語言模型,可以根據給定的提示生成類似人類語言的文本,從而實現對話、文本摘要和問答等多種功能。
出于演示的目的,我們將專注于OpenAI的"gpt-3.5-turbo-16k"模型,因為它目前價格合適,速度較快,回答比較準確。
如果想深入了解chatgpt相關信息,請參考下面鏈接:
https://platform.openai.com/docs/api-reference
LangChain
LangChain 是一個庫(以 Python、JavaScript 或 TypeScript 提供),提供了一組用于處理語言模型、文本嵌入和文本處理任務的工具和實用程序。 它通過組合語言模型、向量存儲和文檔加載器等各種組件來簡化創建聊天機器人、處理文檔檢索和執行問答操作等任務。
我們將專注于創建一個問答聊天機器人,其中包含上面圖中所展示的綠色的部分。
如果想深入了解LangChain相關信息,請參考下面鏈接:
https://python.langchain.com/docs/get_started
FAISS
FAISS(Facebook AI相似性搜索)是Facebook AI Research開發的開源庫。 它旨在有效地搜索大量高維數據中的相似項(向量)。 FAISS 提供了索引和搜索向量的方法,使您可以更輕松、更快速地找到數據集中最相似的項目。現在的一個簡單理解是,FAISS并不能直接存儲數據,它只是一個索引和搜索向量的工具,這個工具可以根據emdebbing的后生成的向量,從文本中匹配跟問題相關的內容出來。FAISS的存儲數據只是把向量化后的一系列數據存在本地文件,之后需要的時候再從本地文件進行加載進去。所以我們設計的時候應該得分成兩步進行設計,一部分是生成本地文件的代碼,一部分是加載本地文件的代碼,當然加載本地文件就是直接寫在業務代碼里面,不需要單獨拆出來了。
它在以下任務中特別有用:
- 推薦系統
- 信息檢索
- 聚類——找到相似的項目很重要
如果您有一個基本的聊天機器人并且滿足以下條件,那么 FAISS 是一個可靠的矢量存儲選擇:
- 查詢可由CPU支持的有限數據集
- 尋求免費開源的矢量存儲解決方案
- 不打算在您的架構中引入其他服務器或云 API
如果想深入了解FAISS相關信息,請參考下面鏈接:
https://faiss.ai/
Document loaders
Document loaders是langchain中的一個組件,它的功能是從文件中讀取數據,比如PDF,csv,url,txt等。經過loaders加載后的數據Document主要由兩部分組成,即page_content和metadata。metadata中存儲了文件名,第幾頁等基礎信息,page_content中存儲了該頁的內容。
其基礎用法如下:
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader(r"loRA _refer.pdf")
print(loader.load())
代碼解釋:
- PyPDFLoader是document_loaders 中加載pdf的組件,這段代碼將pdf加載為一個loader對象,并打印了其中內容,可以看出打印為一個列表,這個列表中存放了一個Document對象。
- 除了PyPDFLoader,langchain還提供了
CSVLoader,HTMLLoader,JSONLoader,MarkdownLoader,File Directory,ExcelLoader,Microsoft Word,Microsoft PowerPoint,GitHub,EPub,Images,WebBaseLoader,URL等多種加載器,具體可查看其document_loaders文檔:
https://python.langchain.com/docs/modules/data_connection/document_loaders/
File Directory loader
File Directory loader可以從文件夾中同時加載多個文件,其基本用法如下:
from langchain.document_loaders import DirectoryLoader,PyPDFLoader loader_pdf=DirectoryLoader('./docs/',glob="**/*.pdf",loader_cls=PyPDFLoader)documents = loader_pdf.load()
代碼解釋:
from langchain.document_loaders import DirectoryLoader
: 這行代碼從langchain.document_loaders
模塊中導入DirectoryLoader
類。DirectoryLoader
類是用于從目錄加載文檔的工具。loader_pdf = DirectoryLoader('./docs/', glob="**/*.pdf", loader_cls= PyPDFLoader)
: 這行代碼創建一個名為loader_pdf
的對象,它是DirectoryLoader
類的一個實例。構造函數的參數如下所示:'./docs/'
: 這是要加載的目錄路徑,即包含PDF文檔的目錄。在這個例子中,路徑為'./docs/'
,表示當前目錄下的docs
文件夾。glob="**/*.pdf"
: 這是一個用于匹配文件的通配符模式。在這里,**/*.pdf
表示匹配任意目錄下的任意文件名以.pdf
結尾的文件。loader_cls=PyPDFLoader
: 這是一個指定要使用的加載器類的參數。在這個例子中,指定的加載器類是PyPDFLoader
。最佳實踐為,當明確需要加載文件類型時,應該明確指定這里的loader_cls
,即加載器是什么。
documents = loader_pdf.load()
: 這行代碼使用之前創建的loader_pdf
對象調用load()
方法來加載文檔。load()
方法將根據之前設置的目錄路徑、文件匹配模式和加載器類來加載滿足條件的PDF文檔,并將加載的文檔存儲在名為documents
的變量中。
Document transformers
因為在現在的技術條件下,chatgpt或其他的大語言模型均有受到文本長度的限制,所以對于一個大型文件或者很多個大型文件時,若將全部文本一次性發送給chatgpt,則模型往往會報錯token超出。在這種情況下,我們則會先將長文檔拆分為可以放入模型上下文窗口的較小塊。在langchain中內置了很多函數,使我們可以直接進行這個操作。、
from langchain.document_loaders import DirectoryLoader,PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter loader_pdf=DirectoryLoader('./docs/',glob="**/*.pdf",loader_cls=PyPDFLoader)
documents = loader_pdf.load()
text_splitter=CharacterTextSplitter(chunk_size=1000,chunk_overlap=0)
docs = text_splitter.split_documents(documents)
代碼解釋:
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
: 這行代碼創建一個名為text_splitter
的對象,它是CharacterTextSplitter
類的一個實例。構造函數的參數如下所示:chunk_size=1000
: 這是指定拆分文本片段的大小的參數。在這里,設置為1000,表示每個片段的字符數為1000。chunk_overlap=0
: 這是指定片段之間重疊部分的大小的參數。在這里,設置為0,表示片段之間沒有重疊。設置重疊部分有可能會在某些長句子面臨被切開情況會很有用,或者上下兩句聯系較為緊密時起作用。可以根據實際情況來寫入,默認可以設置為0.
docs = text_splitter.split_documents(documents)
: 這行代碼使用之前創建的text_splitter
對象調用split_documents()
方法來將加載的文檔拆分成較小的文本片段。拆分后的文本片段將存儲在名為docs
的變量中。split_documents()
方法的參數documents
是之前加載的文檔。
Text embedding models
embedding (嵌入)這個動作的目的是創建一段文本的矢量表示形式。矢量是一個數學領域的概念,若對這部分不熟悉請學習線性代數這門課程。
矢量在數學上一般以一個有序數組來表示,相關概念見下文:
https://zhuanlan.zhihu.com/p/339974158
文本向量化之后,就可以執行諸如語義搜索之類的操作,在其中我們可以尋找向量空間中最相似的文本片段。
當我們需要查找向量空間的最相似的文本片段時,就必須引入另一個工具,即向量數據庫。
Vector stores
存儲和搜索非結構化數據的最常見方法之一是將數據embedding并存儲生成的embedding向量。然后在查詢時檢索與查詢內容"最相似"的embedding向量。Vector stores(矢量存儲)負責存儲embedding數據并為您執行矢量搜索。(請注意,在數學中矢量與向量同義)。
from langchain.document_loaders import DirectoryLoader,PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter loader_pdf=DirectoryLoader('./docs/',glob="**/*.pdf",loader_cls=PyPDFLoader)
documents = loader_pdf.load()
text_splitter=CharacterTextSplitter(chunk_size=1000,chunk_overlap=0)
docs = text_splitter.split_documents(documents)
faissIndex = FAISS.from_documents(docs, OpenAIEmbeddings()) faissIndex.save_local("faiss_midjourney_docs")
- 從文檔塊創建 FAISS 索引,使用
OpenAIEmbeddings()
將文本塊轉換為矢量表示形式,并生成一個faiss對象. - 將創建的 FAISS 索引保存到名為"faiss_midjourney_docs"的本地文件中。然后,該索引可以重新用于將來的高效相似性搜索任務,而不需要重新從源文件中生成。
這個"faiss_midjourney_docs"的本地文件實際上是一個文件夾,其目錄結構如下圖:
從本地加載 FAISS 索引并加入到langchain的問答中
import os, dotenv
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain import PromptTemplate dotenv.load_dotenv() chatbot = RetrievalQA.from_chain_type( llm=ChatOpenAI( openai_api_key=os.getenv("OPENAI_API_KEY"), temperature=0, model_name="gpt-3.5-turbo", max_tokens=50 ),chain_type="stuff", retriever=FAISS.load_local("faiss_midjourney_docs", OpenAIEmbeddings()) .as_retriever(search_type="similarity", search_kwargs={"k":1}) ) template = """
respond as succinctly as possible. {query}?
""" prompt = PromptTemplate( input_variables=["query"], template=template,
) print(chatbot.run( prompt.format(query="what is --v")
))
- 導入必要的庫和模塊,包括
os
、、OpenAIEmbeddings
、FAISS
dotenv
RetrievalQA
、ChatOpenAI
和PromptTemplate
。 - 使用 從
dotenv
.env 文件加載環境變量(即 OPENAI_API_KEY)。 - 使用 GPT-3.5-turbo 模型初始化
ChatOpenAI
實例,溫度為 0,最多 50 個響應令牌和 OpenAI API 密鑰。默認溫度為 0.7 — 將值設置為 0 將降低 ChatGPT 完成的隨機性。 - 使用 加載
OpenAIEmbeddings
預構建的 FAISS 索引“faiss_midjourney_docs”。 - 設置包含
RetrievalQA
ChatOpenAI 實例、FAISS 索引以及搜索類型和參數的鏈。強烈建議設置search_type
和search_kwargs
- 不這樣做將具有成本效益,因為向量存儲中的所有塊都將發送到LLM。還值得注意的是,chain_type
是“東西”它試圖將所有塊填充到提示中作為您的LLM(即ChatGPT)的上下文。 - 定義一個包含變量“query”的提示模板,并要求提供簡潔的答案。
- 使用定義的模板創建
PromptTemplate
實例。 - 使用與中途相關的查詢來設置提示的格式。
- 使用格式化的提示問題執行聊天機器人。
- 打印聊天機器人的答案。