我們知道LLM(大語言模型)的底模是基於已經過期的公開數據訓練出來的,對於新的知識或者私有化的數據LLM一般無法作答,此時LLM會出現「幻覺」。針對「幻覺」問題,一般的解決方案是采用RAG做檢索增強。
但是我們不可能把所有數據都丟給LLM去學習,比如某個公司積累的某個行業的大量內部知識。此時就需要一個私有化的文件搜尋工具了。
本文聊聊如何使用LangChain結合LLM快速做一個私有化的文件搜尋工具。之前介紹過,LangChain幾乎是LLM套用開發的第一選擇,它的野心也比較大,它致力於將自己打造成LLM套用開發的最大社群。自然,它有這方面的成熟解決方案。
文末,還會向朋友們推薦一款非常好用的AI機器人和LLM API超市,價格實惠又穩定,還可以領一波福利。
1. RAG檢索流程
使用 LangChain 實作私有化文件搜尋的主要流程,如下圖所示:
文件載入 → 文件分割 → 文件嵌入 → 向量化儲存 → 文件檢索 → 生成回答
2. 程式碼實踐細節
2.1. 文件載入
首先,我們需要載入文件數據。文件可以是各種格式,比如文字檔案、PDF、Word 等。使用 LangChain,可以輕松地載入這些文件。下面以PDF為例:
from langchain_community.document_loaders import PyPDFLoaderloader = PyPDFLoader("./GV2.pdf")docs = loader.load()
2.2. 文件分割
載入的文件通常會比較大,為了更高效地處理和檢索,我們需要將文件分割成更小的段落或句子。LangChain 提供了便捷的文本分割工具,可以按句子、塊長度等方式分割文件。
from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter( chunk_size=50, chunk_overlap=20, separators=["\n", "。", "!", "?", ",", "、", ""], add_start_index=True,)texts = text_splitter.split_documents(docs)
分割後的文件內容可以進一步用於生成向量。
2.3. 文件嵌入 Embeddings
文件分割後,我們需要將每一段文本轉換成向量,這個過程稱為文件嵌入。文件嵌入是將文本轉換成高維向量,這是相似性搜尋的關鍵。這裏我們選擇OpenAI的嵌入模型來生成文件的嵌入向量。
from langchain_openai import OpenAIEmbeddingsembeddings_model = OpenAIEmbeddings( openai_api_key="sk-xxxxxxxxxxx", openai_api_base="https://api.302.ai/v1",)txts = [txt.page_content for txt in texts]embeddings = embeddings_model.embed_documents(txts)
2.4. 文件向量化儲存
接下來,我們需要將生成的向量化的文件,存入向量資料庫中。向量資料庫主要用來做相似性搜尋,可以高效地儲存和檢索高維向量。LangChain 支持與多種向量資料庫的整合,比如 Pinecone、FAISS、Chroma 等。
本文以FAISS為例,首先需要安裝FAISS,直接使用pip install faiss-cpu安裝。
from langchain_community.vectorstores import FAISSdb = FAISS.from_documents(texts, embeddings_model)FAISS.save_local(db, "faiss_db2")
2.5. 文件檢索
當使用者提出問題時,我們需要在向量資料庫中檢索最相關的文件。檢索過程是計算使用者問題的向量表示,然後在向量資料庫中尋找與之最相似的文件。最後將找到的文件內容,拼接成一個大的上下文。
向量資料庫的檢索支持多種模式,本文先用最簡單的,後續再出文章繼續介紹別的模式。
from langchain.retrievers.multi_query import MultiQueryRetrieverretriever = db.as_retriever()# retriever = db.as_retriever(search_type="similarity_score_threshold",search_kwargs={"score_threshold":.1,"k":5})# retriever = db.as_retriever(search_type="mmr")# retriever = MultiQueryRetriever.from_llm(# retriever = db.as_retriever(),# llm = model,# )context = retriever.get_relevant_documents(query="張學立是誰?")_content = ""for i in context: _content += i.page_content
2.6. 將檢索內容丟給LLM作答
最後,我們需要將檢索到的文件內容丟入到 prompt 中,讓LLM生成回答。LangChain 可以PromptTemplate樣版的方式,將檢索到的上下文動態嵌入到 prompt 中,然後丟給LLM,這樣可以生成準確的回答。
from langchain.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParserquestion = "張學立是誰?"template = [ ( "system", "你是一個處理文件的助手,你會根據下面提供<context>標簽裏的上下文內容來繼續回答問題.\n 上下文內容\n <context>\n{context} \n</context>\n", ), ("human", "你好!"), ("ai", "你好"), ("human", "{question}"),]prompt = ChatPromptTemplate.from_messages(template)messages = prompt.format_messages(context=_content, question=question)response = model.invoke(messages)output_parser = StrOutputParser()output_parser.invoke(response)
2.7. 完整程式碼
最後,將以上所有程式碼串起來,整合到一起,如下:
from langchain_openai import ChatOpenAIfrom langchain_community.document_loaders import PyPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain_openai import OpenAIEmbeddingsfrom langchain_community.vectorstores import FAISSfrom langchain.retrievers.multi_query import MultiQueryRetrieverfrom langchain.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParsermodel = ChatOpenAI( model_name="gpt-3.5-turbo", openai_api_key="sk-xxxxxxx", openai_api_base="https://api.302.ai/v1",)loader = PyPDFLoader("./GV2.pdf")docs = loader.load()text_splitter = RecursiveCharacterTextSplitter( chunk_size=50, chunk_overlap=20, separators=["\n", "。", "!", "?", ",", "、", ""], add_start_index=True,)texts = text_splitter.split_documents(docs)embeddings_model = OpenAIEmbeddings( openai_api_key="sk-xxxxxxx", openai_api_base="https://api.302.ai/v1",)txts = [txt.page_content for txt in texts]embeddings = embeddings_model.embed_documents(txts)db = FAISS.from_documents(texts, embeddings_model)FAISS.save_local(db, "faiss_db2")retriever = db.as_retriever()template = [ ( "system", "你是一個處理文件的助手,你會根據下面提供<context>標簽裏的上下文內容來繼續回答問題.\n 上下文內容\n <context>\n{context} \n</context>\n", ), ("human", "你好!"), ("ai", "你好"), ("human", "{question}"),]prompt = ChatPromptTemplate.from_messages(template)question = "張學立是誰?"context = retriever.get_relevant_documents(query=question)_content = ""for i in context: _content += i.page_contentmessages = prompt.format_messages(context=_content, question=question)response = model.invoke(messages)output_parser = StrOutputParser()output_parser.invoke(response)
2.8. 總結、推薦
透過 LangChain可以輕松實作私有化文件搜尋,充分利用LLM的能力來處理和檢索文件資訊。按照文中的步驟,你也可以輕松實作。
好的問答系統離不開優秀的LLM,根據我的個人經驗,OpenAI的大模型能力排名是Top1的。但是使用OpenAI不方便,不但需要梯子而且還不穩定。
一款好的LLM擺在面前,卻用不了,著實頭疼。有沒有方便穩定的方式呢?當然有啦,下面我來推薦一款AI自助平台,不但有問答機器人、文生圖機器人、文生視訊機器人,還有常見的LLM API,穩定又還便宜。
3. 推薦一款好用的AI平台 - 302.AI
3.1. 什麽是302.AI
302.AI是一個匯集全球頂級AI的自助平台,匯集全球各類頂尖AI大模型,提供多種AI機器人,各種AI工具的使用和AI API接入。
這個平台太適合開發者了,一站式配齊了 支持各種模型的工具 和 AI API ,再也不用這個網站用一下,那個網站用一下了。
自由配置機器人、自由配置各種模型,每一款都很能打。
3.2. 302.AI的優勢
我為什麽願意使用302.AI呢?主要還是優點比較多:
下面上幾個截圖,功能較多,我就不一一解說了,歡迎朋友們自行嘗試。
總之,302.AI是一個可以滿足從工具到API的聚合AI網站,也是一個可以滿足從小白到開發者的需求的AI網站,同時,又兼顧了穩定性和價效比。更多功能,歡迎朋友們自行嘗試解鎖。
3.3. 粉絲福利
我這邊建立了AI全能工具箱分享給大家體驗,每天都會有 5美元額度,先到先用。
AI全能工具箱連結:https://aitoolbox1-all.tools302.com?pwd=0658 分享碼0658,註冊完填寫個問卷會得到1美元的試用額度。
對於開發者朋友,可以私信我獲取免費token,薅一波羊毛。
=====>>>>>> 關於我 <<<<<<=====
本篇完結!歡迎點贊 關註 收藏!!!
原文連結:LangChain結合LLM做私有化文件搜尋