ChatPDF 最近比較火,上傳 PDF 檔案後,即可透過問答的方式讓他幫你總結內容,比如讓它幫你概括核心觀點、詢問問題,或者做觀點判斷。
背後用到了幾個比較時髦的技術,還好有 ChatGPT for YOUR OWN PDF files with LangChain 解釋了背後的原理,我覺得非常精彩,因此記錄下來並做一些思考,希望可以幫到大家。
技術思路概括
由於 GPT 非常強大,只要你把 PDF 文章內容發給他,他就可以解答你對於該文章的任何問題了。-- 全文完。
等等,那麼為什麼要提到 langChain 與 vector dataBase?因為 PDF 文章內容太長了,直接傳給 GPT 很容易超出 Token 限制,就算他允許無限制的 Token 傳輸,可能一個問題可能需要花費 10~100 美元,這個 成本 也是不可接受的。
因此黑魔法來了,下圖擷取自影片 ChatGPT for YOUR OWN PDF files with LangChain:
我們一步步解讀:
- 找一些庫把 PDF 內容文字提取出來。
- 把這些文字拆分成 N 份更小的文字,用 openai 進行文字向量化。
- 當使用者提問時,對使用者提問進行向量化,並用數學函式計算與 PDF 已向量化內容的相似程度。
- 把最相似的文字傳送給 openai,讓他總結並回答你的問題。
利用 GPT 解讀 PDF 的實現步驟
我把影片裡每一步操作重新介紹一遍,並補上自己的理解。
登入 colab
你可以在本地電腦執行 python 一步步執行,也可以直接登入 colab 這個 python 執行平臺,它提供了很方便的 python 環境,並且可以一步步執行程式碼並儲存,非常適合做研究。
只要你有谷歌賬號就可以使用 colab。
安裝依賴
要執行一堆 gpt 相關函式,需要安裝一些包,雖然本質上都是不斷給 gpt openapi 發 http 請求,但封裝後確實會語義化很多:
!pip install langchain
!pip install openai
!pip install PyPDF2
!pip install faiss-cpu
!pip install tiktoken
其中 tiktoken
包是教程裡沒有的,我執行某處程式碼時被提示缺少這個包,大家可以提前按上。接下來提前引入一些後面需要用到的函式:
from PyPDF2 import PdfReader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import ElasticVectorSearch, pinecone, Weaviate, FAISS
定義 openapi token
為了呼叫 openapi 服務,需要先申請 token,當你申請到 token 後,透過如下方式定義:
import os
os.environ["OPENAI_API_KEY"] = "***"
預設 langchain
與 openai
都會訪問 python 環境的 os.environ
來尋找 token,所以這裡定義後,接下來就可以直接呼叫服務了。
如果你還沒有 GPT openapi 的賬號,詳見 保姆級註冊教程。(可惜的是中國被牆了,為了學習第一手新鮮知識,你需要自己找 vpn,甚至花錢買國外手機號驗證碼接收服務,雖然過程比較坎坷,但親測可行)。
讀取 PDF 內容
為了方便在 colab 平臺讀取 PDF,你可以先把 PDF 上傳到自己的 Google Drive,它是谷歌推出的個人雲服務,整合了包括 colab 與檔案儲存等所有云服務(PS:微軟類似的服務叫 One Drive,好吧,理論上你用哪個巨頭的服務都行)。
傳上去之後,在 colab 執行如下程式碼,會彈開一個授權網頁,授權後就可以訪問你的 drive 路徑下資源了:
from google.colab import drive
drive.mount('/content/gdrive', force_remount=True)
root_dir = "/content/gdrive/My Drive/"
reader = PdfReader('/content/gdrive/My Drive/2023_GPT4All_Technical_Report.pdf')
我們讀取了 2023_GPT4All_Technical_Report.pdf
報告,這是一個號稱本地可跑對標 GPT4 的服務(測評)。
將 PDF 內容文字化並拆分為多個小 chunk
首先執行如下程式碼讀取 PDF 文字內容:
raw_text = ''
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text:
raw_text += text
接下來要為呼叫 openapi 服務對文字向量化做準備,因為一次呼叫的 token 數量有限制,因此我們需要將一大段文字拆分為若干小文字:
text_splitter = CharacterTextSplitter(
separator = "\n",
chunk_size = 1000,
chunk_overlap = 200,
length_function = len,
)
texts = text_splitter.split_text(raw_text)
其中 chunk_size=1000
表示一個 chunk 有 1000 個字元,而 chunk_overlap
表示下一個 chunk 會重複上一個 chunk 最後 200 字元的內容,方便給每個 chunk 做銜接,這樣可以讓找相似性的時候儘量多找幾個 chunk,找到更多的上下文。
向量化來了!
最重要的一步,利用 openapi 對之前拆分好的文字 chunk 做向量化:
embeddings = OpenAIEmbeddings()
docsearch = FAISS.from_texts(texts, embeddings)
就是這麼簡單,docsearch
是一個封裝物件,在這一步已經迴圈呼叫了若干次 openapi 介面將文字轉化為非常長的向量。
文字向量化又是一個深水區,可以看下這個 介紹影片,簡單來說就是一把文字轉化為一系列數字,表示 N 維的向量,利用數學計算相似度,可以把文書處理轉化為連續的數字進行數學處理,甚至進行文字加減法(比如 北京-中國+美國=華盛頓)。
總之這一步之後,我們本地就拿到了各段文字與其向量的對應關係,比如 “這是一段文字” 對應的向量為 [-0.231, 0.423, -0.2347831, ...]
。
利用 chain 生成問答服務
接下來要串起完整流程了,初始化一個 QA chain 表示與 GPT 使用 chat 模型進行問答:
from langchain.chains.question_answering import load_qa_chain
from langchain.llms import OpenAI
chain = load_qa_chain(OpenAI(), chain_type="stuff")
接下來就可以問他 PDF 相關問題了:
query = "who are the main author of the article?"
docs = docsearch.similarity_search(query)
chain.run(input_documents=docs, question=query)
# The main authors of the article are Yuvanesh Anand, Zach Nussbaum, Brandon Duderstadt, Benjamin Schmidt, and Andriy Mulyar.
當然也可以用中文提問,openapi 會呼叫內建模組翻譯給你:
query = "訓練 GPT4ALL 的成本是多少?"
docs = docsearch.similarity_search(query)
chain.run(input_documents=docs, question=query)
# 根據文章,大約四天的工作,800美元的GPU成本(包括幾次失敗的訓練)和500美元的OpenAI API開銷。我們釋出的模型gpt4all-lora大約在Lambda Labs DGX A100 8x 80GB上需要八個小時的訓練,總成本約為100美元。
QA 環節發生了什麼?
根據我的理解,當你問出 who are the main author of the article?
這個問題時,發生瞭如下幾步。
第一步:呼叫 openapi 將問題進行向量化,得到一堆向量。
第二步:利用數學函式與本地向量資料庫進行匹配,找到匹配度最高的幾個文字 chunk(之前我們拆分的 PDF 文字內容)。
第三步:把這些相關度最高的文字傳送給 openapi,讓他幫我們歸納。
對於第三步是否結合了 langchain 進行多步驟對答還不得而知,下次我準備抓包看一下這個程式與 openapi 的通訊內容,才能解開其中的秘密。
當然,如果問題需要結合 PDF 所有內容才能概括出來,這種向量匹配的方式就不太行了,因為他總是傳送與問題最相關的文字片段。但是呢,因為第三步的秘密還沒有解決,很有可能當內容片段不夠時,gpt4 會詢問尋找更多相似片段,這樣不斷重複知道 gpt4 覺得可以回答了,再給出答案(想想覺得後背一涼)。
總結
解讀 PDF 的技術思路還可以用在任意問題上,比如網頁搜尋:
網頁搜尋就是一個典型的從知識海洋裡搜尋關鍵資訊並解讀的場景,只要背後將所有網頁資訊向量化,儲存在某個向量資料庫,就可以做一個 GPT 搜尋引擎了,步驟是:一、將使用者輸入關鍵字分詞並向量化。二:在資料庫進行向量匹配,把匹配度最高的幾個網頁內容提取出來。三:把這些內容餵給 GPT,讓他總結裡面的知識並回答使用者問題。
向量化可以解決任意場景模糊化匹配,比如我自己的備忘錄會儲存許多平臺賬號與密碼,但有一天搜尋 ChatGPT 密碼卻沒搜到,後來發現關鍵詞寫成了 OpenAPI。向量化就可以解決這個問題,他可以將無法匹配的關鍵詞也在備忘錄裡搜尋到。
配合向量化搜尋,再加上 GPT 的思考與總結能力,一個超級 AI 助手可做的事將會遠遠超過我們的想象。
留給大家一個思考題:結合向量化與 GPT 這兩個能力,你還能想到哪些使用場景?
討論地址是:精讀《利用 GPT 解讀 PDF》· Issue #479 · dt-fe/weekly
如果你想參與討論,請 點選這裡,每週都有新的主題,週末或週一釋出。前端精讀 - 幫你篩選靠譜的內容。
關注 前端精讀微信公眾號
版權宣告:自由轉載-非商用-非衍生-保持署名(創意共享 3.0 許可證)