一、大模型開發整理流程
1.1、什么是大模型開發
我們將開發以大語言模型為功能核心、通過大語言模型的強大理解能力和生成能力、結合特殊的數據或業務邏輯來提供獨特功能的應用稱為大模型開發。
開發大模型相關應用,其技術核心點雖然在大語言模型上,但一般通過調用 API 或開源模型來實現核心的理解與生成,通過 Prompt Enginnering 來實現大語言模型的控制,因此,雖然大模型是深度學習領域的集大成之作,大模型開發卻更多是一個工程問題。
在大模型開發中,我們一般不會去大幅度改動模型,而是將大模型作為一個調用工具,通過 Prompt Engineering、數據工程、業務邏輯分解等手段來充分發揮大模型能力,適配應用任務,而不會將精力聚焦在優化模型本身上。
大模型開發與傳統的AI 開發在整體思路上有著較大的不同。
- 傳統AI 開發:首先需要將復雜的業務邏輯依次拆解,對于每個子業務構造訓練數據與驗證數據,對于每個子業務訓練優化模型,最后形成完整的模型鏈路來解決整個業務邏輯。
- 大模型開發:用 Prompt Engineering 來替代子模型的訓練調優,通過 Prompt 鏈路組合來實現業務邏輯,用一個通用大模型 + 若干業務 Prompt 來解決任務,從而將傳統的模型訓練調優轉變成了更簡單、輕松、低成本的 Prompt 設計調優。
大模型開發與傳統 AI 開發在評估思路上也有了質的差異。
- 傳統 AI 開發:構造訓練集、測試集、驗證集,通過在訓練集上訓練模型、在測試集上調優模型、在驗證集上最終驗證模型效果來實現性能的評估。
- 大模型開發:更敏捷、靈活,不會在初期顯式地確定訓練集、驗證集,而是直接從實際業務需求出發構造小批量驗證集,設計合理 Prompt 來滿足驗證集效果。然后,不斷從業務邏輯中收集當下 Prompt 的 Bad Case,并將 Bad Case 加入到驗證集中,針對性優化 Prompt,最后實現較好的泛化效果。
1.2、大模型開發整體流程
1.2.1、設計
包括確定目標,設計功能。
確定目標:在進行開發前,需要確定開發的目標,即要開發的應用的應用場景、目標人群、核心價值。一般應先設定最小化目標,從構建一個 mvp(最小可行性產品)開始,逐步進行完善和優化。
設計功能:確定開發目標后,設計本應用所要提供的功能,首先確定應用的核心功能,然后延展設計核心功能的上下游功能;例如,想打造一款個人知識庫助手,核心功能就是結合個人知識庫內容進行問題的回答,上游功能——用戶上傳知識庫、下游功能——用戶手動糾正模型回答,就是子功能。
1.2.2、架構搭建
搭建整體架構:搭建項目的整體架構,實現從用戶輸入到應用輸出的全流程貫通。包括搭建整體架構和搭建數據庫。
目前,絕大部分大模型應用都是采用的特定數據庫+ Prompt + 通用大模型的架構。
推薦基于 LangChain 框架進行開發。LangChain 提供了 Chain、Tool 等架構的實現,可以基于 LangChain 進行個性化定制,實現從用戶輸入到數據庫再到大模型最后輸出的整體架構連接。
搭建數據庫: 大模型應用需要進行向量語義檢索,一般使用諸如 chroma 的向量數據庫。搭建數據庫需要收集數據并進行預處理,再向量化存儲到數據庫中。數據預處理一般包括從多種格式向純文本的轉化,例如 pdf、markdown、html、音視頻等,以及對錯誤數據、異常數據、臟數據進行清洗。完成預處理后,需要進行切片、向量化構建出個性化數據庫。
1.2.3、Prompt Engineering
明確 Prompt 設計的一般原則及技巧,構建出一個來源于實際業務的小型驗證集,基于小型驗證集設計滿足基本要求、具備基本能力的 Prompt。
優質的 Prompt 對大模型能力具有極大影響,需要逐步迭代構建優質的 Prompt Engineering 來提升應用性能。
1.2.4、驗證迭代
驗證迭代在大模型開發中是極其重要的一步,指通過不斷發現 Bad Case 并針對性改進 Prompt Engineering 來提升系統效果、應對邊界情況。在完成上一步的初始化 Prompt 設計后,應該進行實際業務測試,探討邊界情況,找到 Bad Case,并針對性分析 Prompt 存在的問題,從而不斷迭代優化,直到達到一個較為穩定、可以基本實現目標的 Prompt 版本。
1.2.5、前后端搭建
完成 Prompt Engineering 及其迭代優化之后,就完成了應用的核心功能,可以充分發揮大語言模型的強大能力。接下來搭建前后端,設計產品頁面,讓應用上線成為產品。
兩種快速開發 Demo 的框架:Gradio 和 Streamlit,可以幫助個體開發者迅速搭建可視化頁面實現 Demo 上線。
在完成前后端搭建之后,應用就可以上線體驗了。接下來就需要進行長期的用戶體驗跟蹤,記錄 Bad Case 與用戶負反饋,再針對性進行優化即可。
二、項目流程簡析
基于個人知識庫的問答助手介紹項目流程。
項目原理:項目原理如下圖所示,過程包括加載本地文檔 -> 讀取文本 -> 文本分割 -> 文本向量化 -> question向量化 -> 在文本向量中匹配出與問句向量最相似的 top k個 -> 匹配出的文本作為上下文和問題一起添加到 prompt中 -> 提交給 LLM生成回答。
2.1、項目規劃與需求分析
1、項目目標:基于個人知識庫的問答助手
2、核心功能:
1、上傳文檔、創建知識庫;
2、選擇知識庫,檢索用戶提問的知識片段;
3、提供知識片段與提問,獲取大模型回答;
4、流式回復;
5、歷史對話記錄
3、確定技術架構和工具:
1、LangChain框架
2、Chroma知識庫
3、大模型使用 GPT、科大訊飛的星火大模型、文心一言、GLM 等
4、前后端使用 Gradio 和 Streamlit。
2.2、數據準備與向量知識庫構建
2.2.1、收集和整理用戶提供的文檔
用戶常用文檔格式有 pdf、txt、doc 等,首先使用工具讀取文本,通常使用 langchain 的文檔加載器模塊,也可以使用 python 比較成熟的包進行讀取。
由于目前大模型使用 token 的限制,需要對讀取的文本進行切分,將較長的文本切分為較小的文本,這時一段文本就是一個單位的知識。
2.2.2、將文檔詞向量化
使用文本嵌入(Embeddings)對分割后的文檔進行向量化,使語義相似的文本片段具有接近的向量表示。然后,存入向量數據庫,這個流程正是創建 索引(index) 的過程。
向量數據庫對各文檔片段進行索引,支持快速檢索。這樣,當用戶提出問題時,可以先將問題轉換為向量,在數據庫中快速找到語義最相關的文檔片段。然后將這些文檔片段與問題一起傳遞給語言模型,生成回答。
2.2.3、將向量化后的文檔導入Chroma知識庫,建立知識庫索引
Chroma 向量庫輕量級且數據存儲在內存中,非常容易啟動和開始使用。
用戶知識庫內容經過 embedding 存入向量知識庫,然后用戶每一次提問也會經過 embedding,利用向量相關性算法(例如余弦算法)找到最匹配的幾個知識庫片段,將這些知識庫片段作為上下文,與用戶問題一起作為 prompt 提交給 LLM 回答。
2.3、大模型集成與API連接
- 集成GPT、星火、文心、GLM 等大模型,配置 API 連接。
- 編寫代碼,實現與大模型 API 的交互,以便獲取問題答案。
2.4、核心功能實現
- 構建 Prompt Engineering,實現大模型回答功能,根據用戶提問和知識庫內容生成回答。
- 實現流式回復,允許用戶進行多輪對話。
- 添加歷史對話記錄功能,保存用戶與助手的交互歷史。
2.5、核心功能迭代優化
- 進行驗證評估,收集 Bad Case。
- 根據 Bad Case 迭代優化核心功能實現。
2.6、前端與用戶交互界面開發
- 使用 Gradio 和 Streamlit 搭建前端界面。
- 實現用戶上傳文檔、創建知識庫的功能。
- 設計用戶界面,包括問題輸入、知識庫選擇、歷史記錄展示等。
2.7、部署測試與上線
- 部署問答助手到服務器或云平臺,確??稍诨ヂ摼W上訪問。
- 進行生產環境測試,確保系統穩定。
- 上線并向用戶發布。
2.8、維護與持續改進
- 監測系統性能和用戶反饋,及時處理問題。
- 定期更新知識庫,添加新的文檔和信息。
- 收集用戶需求,進行系統改進和功能擴展。
三、項目架構簡析
3.1、整體架構
搭建一個基于大模型的個人知識庫助手,基于 LangChain 框架搭建,核心技術包括 LLM API 調用、向量數據庫、檢索問答鏈等。項目整體架構如下:
項目從底向上依次分為 LLM 層、數據層、數據庫層、應用層與服務層:
3.1.1、LLM 層
基于四種流行 LLM API (OpenAI-ChatGPT、百度文心、訊飛星火、智譜GLM)進行了 LLM 調用封裝,支持用戶以統一的入口、方式來訪問不同的模型,支持隨時進行模型的切換;
在 LLM 層,構建了一個 Self_LLM 基類,基類定義了所有 API 的一些共同參數(如 API_Key,temperature 等);在該基類基礎上繼承實現了上述四種 LLM API 的自定義 LLM。四種 LLM 的原生 API 封裝在了統一的 get_completion 函數中。
3.1.2、數據層
包括個人知識庫的源數據(包括 pdf、txt、md 等)以及 Embedding API,源數據經過 Embedding 處理可以被向量數據庫使用;
3.1.3、數據庫層
基于個人知識庫源數據搭建的向量數據庫,本項目中選擇了 Chroma。在該層實現了源數據處理、創建向量數據庫的方法;
3.1.4、應用層
應用層封裝了整個項目的全部核心功能?;?LangChain 提供的檢索問答鏈基類進行了進一步封裝,支持通過 model 參數進行不同模型切換以及便捷實現基于數據庫的檢索問答。
實現了兩個檢索問答鏈,分別是有歷史記錄的 Chat_QA_Chain 和沒有歷史記錄的 QA_Chain;
3.1.5、服務層
實現了 Gradio 搭建 Demo 與 FastAPI 組建 API 兩種方式來支持本項目的服務訪問。
3.2、代碼結構
-project
-readme.md 項目說明
-requirements.txt 使用依賴包的版本
-llm LLM調用封裝
-self_llm.py 自定義 LLM 基類
-wenxin_llm.py 自定義百度文心 LLM
-spark_llm.py 自定義訊飛星火 LLM
-zhipuai_llm.py 自定義智譜AI LLM
-call_llm.py 將各個 LLM 的原生接口封裝在一起
-test.ipynb 使用示例
-embedding embedding調用封裝
-zhipuai_embedding.py 自定義智譜AI embedding
-call_embedding.py 調用 embedding 模型
-data 源數據路徑
-database 數據庫層封裝
-create_db.py 處理源數據及初始化數據庫封裝
-qa_chain 應用層封裝
-qa_chain.py 封裝檢索問答鏈,返回一個檢索問答鏈對象
-chat_qa_chian.py:封裝對話檢索鏈,返回一個帶有歷史記錄的對話檢索鏈對象
-get_vectordb.py 返回向量數據庫對象
-model_to_llm.py 調用模型
-test.ipynb 使用示例
-serve 服務層封裝
-run_gradio.py 啟動 Gradio 界面
-api.py 封裝 FastAPI
-run_api.sh 啟動 API
-test.ipynb 使用示例
3.3、項目邏輯
1、用戶:可以通過 run_gradio 或者 run_api 啟動整個服務;
2、服務層調用 qa_chain.py 或 chat_qa_chain 實例化對話檢索鏈對象,實現全部核心功能;
3、服務層和應用層都可以調用、切換 prompt_template.py 中的 prompt 模板來實現 prompt 的迭代;
4、也可以直接調用 call_llm 中的 get_completion 函數來實現不使用數據庫的 LLM;
5、應用層調用已存在的數據庫和 llm 中的自定義 LLM 來構建檢索鏈;
6、如果數據庫不存在,應用層調用 create_db.py 創建數據庫,該腳本可以使用 openai embedding 也可以使用 embedding.py 中的自定義 embedding