很少有一種技術既能充當幕后扛旗的無名英雄,又能兼具網紅明星的氣質。
而DeepSeek做到了這一點。
作為提升生產力的利器,DeepSeek正吸引著眾多個人開發者與企業用戶的興趣,他們紛紛尋求在本地環境中部署DeepSeek-R1模型,以充分利用其強大的AI能力。
隨著大語言模型和RAG技術的快速發展,AI知識庫系統正在全面滲透各行各業。
目前,我們已經在多個領域見證了其成功應用,包括跨境電商平臺的智能客服、教育機構的個性化學習助手、醫療機構的診斷支持系統,以及餐飲行業的智能點餐服務等實際落地案例。
下面博主將詳細介紹如何利用 一張RTX 4090顯卡 在本地部署基于DeepSeek-R1(深度思考模型)和RAG技術的知識庫系統(Knowledge Base System)。
該系統可廣泛應用于智能客服、企業內部知識管理、學術研究及教育等多個領域,為企業智能化轉型提供新動能,助力企業實現提質增效。
首先體驗一下部署效果(圖片來自MaxKB),一睹為快。
若有系統搭建或咨詢需求,請留言或關注本公眾號私信博主。
汽車跨境電商智能AI客服 生物醫藥AI客服 微信客服 釘釘機器人 配置飛書機器人 飛書機器人 深圳信用中心 AI 助手 華萊士智能AI客服助手 高校教學管理AI小助手 高校教學管理AI小助手-微信公眾號 低代碼可視化業務流程編排 創建函數腳本 后端應用監控 在數字化轉型的浪潮下,個人和企業內部的信息管理面臨著很大的挑戰。傳統的信息管理系統往往存在數據分散、檢索效率低下、缺乏智-能化支持等問題。尤其是在面對海量非結構化數據時,企業難以快速提取有價值的信息,導致決策效率低下。
在專有領域,AI大模型LLM無法學習到所有的專業知識細節,因此在面向專業領域知識的提問時,無法給出可靠準確的回答,甚至會“胡言亂語”,這種現象稱之為LLM的“幻覺”。
為此,實現AI大模型商用級知識庫主要有兩種方法:
第一種:通過專業知識的再訓練或模型微調來增強模型能力,但這種方法需要大量標注數據和計算資源,成本高昂,對個人用戶來說不太可行;
第二種:在向大模型提問時提供相關背景知識,使模型能夠基于這些上下文信息生成更準確的回答。這種知識庫構建方法的核心就是RAG(Retrieval-Augmented Generation,檢索增強生成)技術。
RAG將信息檢索與生成模型相結合,其核心流程是:
在生成回答前,先從外部知識庫中檢索相關信息,讓模型能夠引用訓練數據之外的專業知識,使其在生成響應之前能夠引用訓練數據來源之外的權威知識庫,再將檢索結果與用戶輸入結合,指導生成模型輸出更可靠的回答。
這種方法允許大型語言模型在不重新訓練的情況下訪問特定領域或組織的內部知識庫,從而保持其輸出的相關性、準確性和實用性。
檢索增強生成(RAG)把信息檢索技術和大模型結合起來,將檢索出來的文檔和提示詞一起提供給大模型服務,從而生成更可靠的答案,有效地緩解大模型推理的“幻覺”問題。
作為商用級的知識庫,不僅僅需要通過RAG和其它基礎組件滿足用戶問題分類、敏感詞檢索等各類復雜場景需求,還能夠內置強大的工作流引擎和函數庫,支持業務流程編排,甚至是通過低代碼實現可視化自定義工作流,從而指導大模型的工作過程,滿足復雜業務場景下的需求,而這些則交由Agent智能體解決。
如果把AI大模型LLM比作學生的大腦,把RAG比作教材教輔,那么,就可以把Agent比作眼、耳、鼻、舌、身,協助LLM完成“應試教育”之外的“素質教育”。為了過五關斬六將,應對各種考試,學霸則需要LangChain這樣的工程化框架,統籌以上各項能力的發揮。
實際上,LangChain提供了Models、Prompts、Indexes、Memory、Chains、Agents六大核心抽象,在降低系統實現復雜度的同時,提升系統整體的擴展性。它的能力邊界只取決于LLM的智力水平和LangChain能提供的工具集的豐富程度。
一、整體框架 1、技術架構 · 硬件:一張RTX 4090顯卡(24GB顯存) · 大語言模型:DeepSeek-R1-Distill-Qwen-32B(Qwen 320億參數Q4量化版DeepSeek-R1蒸餾模型) · 向量模型:text2vec-base-chinese · 向量數據庫:PostgreSQL / PG Vector 2、RAG 原理 二、本地部署DeepSeek 1、GPU顯卡內存估算 如何準確計算大模型所需的顯存大小,是許多開發者經常遇到的問題。掌握GPU內存的估算方法,并據此合理配置硬件資源以支持模型運行,是確保大模型成功部署和擴展的關鍵。這一能力也是衡量開發者對大模型生產環境部署和可擴展性理解程度的重要指標。
要估算服務大型語言模型所需的 GPU 內存,可以使用以下公式:
· M是所需的 GPU 顯卡內存(單位:GB千兆字節)。 · P是模型中的參數數量,表示模型的大小。例如,這里使用的 Llama 90B模型有 900 億個參數,則該值將為 90。 · 4B表示每個參數使用 4 個字節。每個參數通常需要 4 個字節的內存。這是因為浮點精度通常占用 4 個字節(32 位)。但是,如果使用半精度(16 位),則計算將相應調整。 · Q是加載模型的位數(例如,16 位或 32 位)。根據以 16 位還是 32 位精度加載模型,此值將會發生變化。16 位精度在許多大模型部署中很常見,因為它可以減少內存使用量,同時保持足夠的準確性。 · 1.2 乘數增加了 20% 的開銷,以解決推理期間使用的額外內存問題。這不僅僅是一個安全緩沖區;它對于覆蓋模型執行期間激活和其他中間結果所需的內存至關重要。 估算GPU顯存大小 舉例:以滿血版DeepSeek-R1(671B參數、加載 16 位精度)為例,計算其推理所需的顯存:
這個計算告訴我們,需要大約1610.4 GB 的 GPU 顯存來為 16 位模式下具有 6710 億個參數的滿血版 DeepSeek-R1 大模型提供推理服務。
因此,單個具有 80 GB 顯存的 NVIDIA A100 GPU 或者 H00 GPU 不足以滿足此模型的需求,需要至少20張具有 80 GB 內存的 A100 GPU 才能有效處理內存負載。
此外,僅加載 CUDA 內核就會消耗 1-2GB 的內存。實際上,無法僅使用參數填滿整個 GPU 顯存作為估算依據。
如果是訓練大模型,則需要更多的 GPU 顯存,因為優化器狀態、梯度和前向激活每個參數都需要額外的內存。
2、選擇模型 目前DeepSeek-R1系列模型在 Huggingface [1] 上共計開源了8種。
DeepSeek-R1系列模型 完整系列一覽(按參數規模排序):
· DeepSeek-R1-Zero (671B) · DeepSeek-R1-Distill-Llama-70B · DeepSeek-R1-Distill-Qwen-32B · DeepSeek-R1-Distill-Qwen-14B · DeepSeek-R1-Distill-Llama-8B · DeepSeek-R1-Distill-Qwen-7B · DeepSeek-R1-Distill-Qwen-1.5B DeepSeek-R1系列的兩大明星產品:
DeepSeek-R1-Zero:AI界的'極限探索者'
· 超強算力:6710億參數(采用MoE架構,每個token可調動370億參數) · 實戰表現:在AIME 2024基準測試中取得71%的亮眼成績 DeepSeek-R1:AI界的'全能冠軍'
· 卓越成就:在AIME 2024測試中達到79.8%的驚人準確率 值得一提的是,DeepSeek團隊通過知識蒸餾技術,成功將這些頂級模型的能力傳承給更輕量級的版本。
這種創新方式不僅大幅降低了模型應用門檻,還提升了小型模型的推理能力,這正是DeepSeek在AI領域備受矚目的重要原因之一。
DeepSeek-R1 蒸餾模型的幾款小尺寸模型,是使用 DeepSeek-R1 生成的包含 <think>...</think>
標記的思考鏈數據進行微調后的蒸餾版本,繼承了 R1的推理能力。
畢竟博主囊中羞澀,為了完成這篇文章,選擇 bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF [2] 的DeepSeek-R1-Distill-Qwen-32B大模型的4bit量化模型,根據上面的估算公式,僅使用1張具有 24 GB 內存的 4090 GPU 就可以運行完成本文所需的推理任務。
Qwen2.5-32B是一個通用的預訓練語言模型,而DeepSeek-R1-Distill-Qwen-32B是基于Qwen2.5-32B使用DeepSeek-R1生成的包含 <think>...</think>
標記的思考鏈數據進行微調后的蒸餾版本,因此繼承了R1的推理能力。
這些微調數據包含問題拆解、中間推導等推理過程,通過強化學習讓DeepSeek-R1-Distill-Qwen-32B對齊了R1生成推理步驟的行為模式。通過這種蒸餾機制,小型模型既能保持計算效率,又獲得了接近大模型的復雜推理能力,這在資源受限場景下具有重要應用價值。
3、選擇模型推理服務器和推理框架 在選擇模型后,本地部署面臨的第二個問題便是如何選擇推理服務器和推理框架 ??
對于LLM推理服務器的選擇,目前主要有三種方法。
提供LLM推理服務的三種方法 第一種方法是將個人電腦或租用的服務器配置成一臺LLM推理服務器,本文采取的便是這種搭建方式。
第二種方法是利用OpenAI、Anthropic等大型公司的LLM服務,只需通過API密鑰直接調用,而無需訪問其官網。
第三種方法是在云平臺上構建LLM服務器,并調用該服務器的API,常見的選擇包括阿里云、騰訊云、百度云、AWS、Azure、谷歌云,甚至Modal和SkyPilot等服務。
在具體選擇時,一定要綜合考慮成本,謹慎挑選最適合的模型。
為編寫本文,博主租了一臺帶有一張RTX 4090 GPU 顯卡的服務器(花費大概10元左右就能完成本文案例的部署,當然還需要一些降低費用的小技巧,比如提前租用配置的服務器把模型文件下載到服務器,這樣就可以節省很多費用??,具體情況可以關注本公眾號咨詢博主)。
模型推理服務器的配置如下:
· CPU:16 核,Xeon(R) Platinum 8352V · 數據盤:50 GB(用于存放模型文件、分詞器文件) 在選擇模型推理服務器后,本地部署面臨的第二個問題便是如何選擇推理框架,今天我們就來盤一盤四大主流推理框架的優缺點:
?? 四大天王對決: 1?? SGLang - 大規模集群部署專家 2?? Ollama - 輕量級玩家最愛 3?? vLLM - GPU推理性能王者 4?? LLaMA.cpp - CPU部署救星
?? 選擇秘籍: ? 要極致性能 → 選vLLM ? 要簡單易用 → 選Ollama ? 要集群部署 → 選SGLang ? 要CPU運行 → 選LLaMA.cpp
?? 性能對比:
· 推理速度:vLLM > SGLang > Ollama > LLaMA.cpp · 易用程度:Ollama > LLaMA.cpp > vLLM > SGLang · 硬件要求:vLLM(需GPU) > SGLang > Ollama > LLaMA.cpp ?? 實戰建議:
目前市面上關于如何用Ollama拉取Q4或Q8量化模型進行本地推理的教程已經層出不窮,Ollama 確實以簡單易用俘獲了一大批開發者,但如果你和我一樣,追求的是 生產環境的穩定高效 ,那么Ollama可能就不是你的菜了!
為什么我最終選擇了 vLLM?
· ?? 性能才是硬道理 :Ollama 在高并發和推理速度上,相比 vLLM 真的弱了不少,尤其是在吃 GPU 算力的場景下。 · ?? 生產環境 Real Talk :如果你是認認真真要搞生產部署 DeepSeek-R1,vLLM 這種專為生產設計的框架才是更穩的選擇。 · ?? RTX 4090 最佳拍檔 :單卡 4090 想發揮最大威力?vLLM 的優化更到位!SGLang 那種大規模集群方案,對我們來說就太重了。 4、搭建環境 如果模型推理服務器沒有安裝CUDA和cuDNN的話,需要自行安裝CUDA和cuDNN,并配置環境變量,具體方法可以參考英偉達官網:
CUDA cuDNN 本文所需的的CUDA、cuDNN、Python和PyTorch版本如下:
· Linux版本:Ubuntu 22.04.3 LTS 讀者可以使用VSCode、Cursor或者其它SSH客戶端連接到云服務器,然后使用以下命令安裝CUDA和cuDNN。
安裝前需要確保服務器上已經安裝了NVIDIA驅動,可以使用以下命令查看是否安裝了NVIDIA驅動:
$ nvidia-smi
安裝前,需要確保 PyTorch [5] 與CUDA的版本對應,否則會報錯。
PyTorch與CUDA的對應版本 # 添加 CUDA 存儲庫 $ sudo apt update $ sudo apt install -y software-properties-common $ sudo add-apt-repository ppa:graphics-drivers/ppa # 下載并安裝 CUDA 12.1 $ wget https://developer.download./compute/cuda/12.1/12.1.0/local_installers/cuda_12.1.0_520.61.05_linux.run $ sudo sh cuda_12.1.0_520.61.05_linux.run
在安裝過程中,選擇是否安裝 NVIDIA 驅動(如果你已經有安裝過,可以跳過)。
設置環境變量:
# 在 .bashrc 中添加 CUDA 路徑 $ echo 'export PATH=/usr/local/cuda-12.1/bin: $PATH ' >> ~/.bashrc $ echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64: $LD_LIBRARY_PATH ' >> ~/.bashrc $ source ~/.bashrc
要安裝 cuDNN,首先需要從 NVIDIA 官方下載 cuDNN 8.9.0。
下載后,解壓并安裝 cuDNN。
# 假設 cuDNN 安裝包下載到當前目錄 $ tar -xzvf cudnn-12.1-linux-x64-v8.9.0.131.tgz # 將 cuDNN 文件復制到 CUDA 路徑 $ sudo cp cuda/include/cudnn*.h /usr/local/cuda-12.1/include $ sudo cp cuda/lib64/libcudnn* /usr/local/cuda-12.1/lib64 $ sudo chmod a+r /usr/local/cuda-12.1/include/cudnn*.h /usr/local/cuda-12.1/lib64/libcudnn* # 更新庫路徑 $ echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64: $LD_LIBRARY_PATH ' >> ~/.bashrc $ source ~/.bashrc
# 安裝 Python 3.10 $ sudo apt update $ sudo apt install -y python3.10 python3.10-dev python3.10-distutils # 設置 Python 3.10 為默認版本 $ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 # 檢查 Python 版本 $ python3 --version
# 安裝 pip $ sudo apt install -y python3-pip # 安裝 PyTorch 2.5.1+cu124 $ pip install torch==2.5.1+cu124 torchvision torchaudio # 驗證安裝 $ python -c 'import torch; print(torch.__version__)'
驗證 CUDA 和 cuDNN 是否正確安裝:
# 檢查 CUDA 版本 $ nvcc --version # 檢查 cuDNN 版本 $ cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
驗證 PyTorch 是否可以使用 GPU:
$ python -c 'import torch; print(torch.cuda.is_available())'
現在已經成功地安裝了 CUDA 12.1、cuDNN 8.9.0、Python 3.10.8 和 PyTorch 2.5.1+cu124 環境。
可以使用以下命令查看GPU內存信息
$ nvidia-smi
如果安裝正確,則可以看到類似如下的GPU內存信息
nvidia-smi 執行結果 5、下載DeepSeek模型權重文件 為了在本地部署模型,事先需要從Huggingface上手動下載量化過的DeepSeek-R1的4 bit量化模型 bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF [6] 。
bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF 在這個頁面中存在26種尺寸的量化模型。
為了能夠在單卡4090(24GB顯存)進行推理,我們選擇其中的DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf。
根據上文中的GPU顯存估算公式,4bit量化模型理論上會占用19.2GB左右的顯存,實際該文件大小為19.9GB。
由于模型權重文件較大,不建議直連下載,根據博主的經驗,按照下面的方式下載速度較快。
$ source /etc/network_turbo
$ pip install -U huggingface_hub
· 設置Huggingface鏡像源(必須設置,否則下載模型會報錯??) $ export HF_ENDPOINT=https://
$ huggingface-cli login
$ huggingface-cli download bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF --include 'DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf' --local-dir ./ # 【這里的./可替換為模型在本地的其它存放路徑】
下載成功后的DeepSeek-R1大模型的文件列表如下:
total 19386083 drwxr-xr-x 3 root root 4096 Feb 14 12:34 ./ drwxr-xr-x 4 root root 4096 Feb 14 21:00 ../ drwxr-xr-x 3 root root 4096 Feb 14 10:29 .cache/ -rw-r--r-- 1 root root 19851335840 Feb 14 12:34 DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf
6、下載DeepSeek分詞器tokenizer文件 正常情況下,使用vLLM加載上面DeepSeek模型GGUF權重文件后,不需要單獨加載分詞器文件,即可實現推理。
然而,博主在本地部署DeepSeek后,發現DeepSeek的官方模型庫的一個bug,需要通過修改DeepSeek的分詞器配置文件予以解決。
由于這個月DeepSeek的官方模型庫更新了分詞器配置文件tokenizer_config.json里的chat-template,導致本地部署DeepSeek-R1-Distill-Qwen-32B后, 向模型提問時,模型只輸出 </think>
,沒有開頭的 <think>
,從而導致前端應用無法正確識別DeepSeek的思考過程(Reasoning)。
還有一種解決辦法是:
通過源碼編譯安裝vLLM ,修改deepseek_r1_reasoning_parser.py文件中的相關代碼,把解析think標簽的部分更新一下;說不定還能順便給 vLLM 提個 PR 呢
此外,網上有開發者建議建議使用DeepSeek基礎模型的 tokenizer 而不是 GGUF 模型的 tokenizer。因為從 GGUF 轉換 tokenizer 既耗時又不穩定, 尤其是對于一些詞匯量較大的模型。
基于以上兩點原因,博主單獨下載DeepSeek分詞器文件,并使用vLLM進行加載。
在瀏覽器進入 DeepSeek的Hugging Face官方模型庫 [7] 頁面, 打開 Files and versions 標簽,找下面2個文件。
將圖中2個文件下載到本地。
通過文本編輯器打開tokenizer_config.json文件,找到字段'chat_template',將其字段值末尾的 <think>\\n
刪除掉即可。
注意:這種解決bug的workaround方式,需要在提示詞中顯式增加 <think></think>
標簽,才能啟動DeepSeek模型的推理Reasoning能力。后文的提示詞中有所體現,請讀者留意。
{ 'add_bos_token' : true , 'add_eos_token' : false , 'bos_token' : { '__type' : 'AddedToken' , 'content' : '<|begin▁of▁sentence|>' , 'lstrip' : false , 'normalized' : true , 'rstrip' : false , 'single_word' : false } , 'clean_up_tokenization_spaces' : false , 'eos_token' : { '__type' : 'AddedToken' , 'content' : '<|end▁of▁sentence|>' , 'lstrip' : false , 'normalized' : true , 'rstrip' : false , 'single_word' : false } , 'legacy' : true , 'model_max_length' : 16384 , 'pad_token' : { '__type' : 'AddedToken' , 'content' : '<|end▁of▁sentence|>' , 'lstrip' : false , 'normalized' : true , 'rstrip' : false , 'single_word' : false } , 'sp_model_kwargs' : { } , 'unk_token' : null , 'tokenizer_class' : 'LlamaTokenizerFast' , 'chat_template' : '#此處內容省略' }
然后通過scp等方式分別上傳到模型推理服務器。
$ scp -rP [端口號] [本地文路徑] root@[遠程服務器地址]:[遠程服務器目錄]
或者,通過以下命令將上述2個文件下載到模型推理服務器,直接在服務器上修改。
$ huggingface-cli download deepseek-ai/DeepSeek-R1-Distill-Qwen-32B --include 'tokenizer.json' 'tokenizer_config.json' --local-dir ./tokenizer
7、搭建推理框架vLLM 高效運行DeepSeek R1需要一個高性能的推理引擎,上文博主已分析過了 vLLM 是最佳選擇之一,因為它具有優化的內存管理、快速的執行速度以及與 Hugging Face 模型的無縫集成。
本文使用 vLLM v1 在本地安裝和運行 DeepSeek R1,以實現消費級 GPU 上的高速推理。
$ pip install vllm --upgrade
無縫啟用 vLLM v1,只需將 VLLM_USE_V1=1 環境變量設置為 1,而無需對現有 API 進行任何更改。
$ export VLLM_USE_V1=1
8、啟動DeepSeek推理服務 一切準備就緒后,執行以下命令使用vLLM加載DeepSeek模型,提供與OpenAI API兼容的DeepSeek推理服務接口。
部署大模型具挑戰性的部分是需要根據你自己的具體情況配置每個組件,有可能會頻繁發生內存不足 (OOM) 錯誤,因此選擇正確的模型并調整運行參數至關重要。
$ python -m vllm.entrypoints.openai.api_server \ --served-model-name bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF \ --model [DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf文件的存儲路徑] \ --trust-remote-code \ --host 0.0.0.0 \ --port 6006 \ --max-model-len 2048 \ --dtype float16 \ --enable-prefix-caching \ --enforce-eager \ --max_num_seqs 1 \ --api-key [API訪問密鑰] \ --tokenizer [分詞器tokenizer的存儲路徑]
根據博主的經驗,以上便是最佳設置,針對每個參數,說明如下:
· served-model-name,指定模型的名稱。 · model,DeepSeek模型權重文件的路徑。 · max-model-len,模型上下文長度。如果未指定,將繼承模型自身配置。將max_model_len設置為2048、4096或8196,以找到在沒有錯誤的情況下工作的最大值。如果取值過大,你可能會遇到OOM錯誤。 · max_num_seqs,用于配置同時處理多少個請求;由于這將使內存使用量增加一倍,因此最好將其設置為1。 · trust-remote-code,加載HuggingFace自定義代碼時必須啟用。 · host和port,可以根據你的服務器機器的具體情況進行配置。 · dtype,權重和激活參數的數據類型,用于控制計算精度,常用float16/bfloat16。 · enforce-eager,用于啟用 eager 模式,加快推理速度。 · enable-prefix-caching,重復調用接口時緩存提示詞內容,以加快推理速度。例如,如果你輸入一個長文檔并詢問有關它的各種問題,啟用該參數將提高性能。 · api-key,用于設置API訪問秘鑰,保證自己的DeepSeek不會被隨便訪問,自行設置一個字符串即可;當后文部署的知識庫應用訪問DeepSeek推理服務器時,會檢查其請求頭中的 API 密鑰。 · tokenizer,如前文所述,單獨下載的DeepSeek分詞器存儲目錄。 · tensor-parallel-size,指定GPU數量,本文只用單卡,因此不用設置此參數。 另一種方法是運行 vllm serve
命令,加載DeepSeek-R1-Distill-Qwen-32B-GGUF模型。
$ vllm serve [DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf文件的存儲路徑] \ --served-model-name bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF \ --trust-remote-code \ --host 0.0.0.0 \ --port 6006 \ --max-model-len 2048 \ --dtype float16 \ --enable-prefix-caching \ --enforce-eager \ --max_num_seqs 1 \ --api-key [API訪問密鑰] \ --tokenizer [分詞器tokenizer的存儲路徑]
在執行如上所述的命令后,希望沒有錯誤發生。
加載完畢后出現如下信息說明服務成功啟動。
INFO 02-19 19:49:36 gpu_model_runner.py:872] Loading model weights took 18.5326 GB INFO 02-19 19:49:45 kv_cache_utils.py:407] # GPU blocks: 376 INFO 02-19 19:49:45 kv_cache_utils.py:410] Maximum concurrency for 2048 tokens per request: 2.94x INFO 02-19 19:49:45 core.py:91] init engine (profile, create kv cache, warmup model) took 8.87 seconds INFO 02-19 19:49:45 api_server.py:756] Using supplied chat template: INFO 02-19 19:49:45 api_server.py:756] None INFO 02-19 19:49:45 launcher.py:21] Available routes are: INFO 02-19 19:49:45 launcher.py:29] Route: /openapi.json, Methods: GET, HEAD INFO 02-19 19:49:45 launcher.py:29] Route: /docs, Methods: GET, HEAD INFO 02-19 19:49:45 launcher.py:29] Route: /docs/oauth2-redirect, Methods: GET, HEAD INFO 02-19 19:49:45 launcher.py:29] Route: /redoc, Methods: GET, HEAD INFO 02-19 19:49:45 launcher.py:29] Route: /health, Methods: GET INFO 02-19 19:49:45 launcher.py:29] Route: /ping, Methods: POST, GET INFO 02-19 19:49:45 launcher.py:29] Route: /tokenize, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /detokenize, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v1/models, Methods: GET INFO 02-19 19:49:45 launcher.py:29] Route: /version, Methods: GET INFO 02-19 19:49:45 launcher.py:29] Route: /v1/chat/completions, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v1/completions, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v1/embeddings, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /pooling, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /score, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v1/score, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /rerank, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v1/rerank, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /v2/rerank, Methods: POST INFO 02-19 19:49:45 launcher.py:29] Route: /invocations, Methods: POST INFO: Started server process [3433] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:6006 (Press CTRL+C to quit)
此時,使用 nvidia-smi
查看顯存占用情況。
加載DeepSeek后顯存占用情況 可以看到,加載DeepSeek后,24GB的顯存已被占用21GB。
顯存實際占用 = 模型權重占用 + KV cache占用 + 其他內存開銷
根據日志信息,這里對顯存占用進行分析:
· 這是量化后的 Q4_K_M 格式模型,原始 32B 模型如果是 FP16 格式約需 64GB,量化后顯存占用大幅降低 · 包含 embedding 層、transformer 層參數等 · 分配了 376 個 GPU blocks 用于存儲 KV cache · 每個 block 存儲的 token 數由 block_size
參數決定(默認 16) · 計算公式: KV Cache 內存 = 2 * num_layers * num_heads * head_dim * seq_length * batch_size * dtype_size
· 支持 2048 token 請求時的最大并發達到 2.94 倍;這部分內存在生成過程中按需分配,可大幅提高推理效率,但也會增加總體顯存占用。 因此,整個 GPU 內存消耗可以看作是靜態的模型參數和動態計算緩存(KV cache)兩大塊的合并。
確保 GPU 顯存充足不僅要滿足模型權重加載的 18.5GB,還需要預留足夠空間應付 KV cache 及其他運行時需求。
使用vLLM成功加載模型后,現在就可以使用DeepSeek R1模型了。
通過瀏覽器訪問 http://localhost:6006/docs 查看 vLLM 支持的 DeepSeek API 接口
DeepSeek API $ curl http://localhost:6006/v1/models -H 'Authorization: Bearer ds-key-001'
輸出結果:
{ 'object' : 'list' , 'data' : [ { 'id' : '/root/autodl-fs/model/deepseek/bartowski/DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf' , 'object' : 'model' , 'created' : 1739969336 , 'owned_by' : 'vllm' , 'root' : '/root/autodl-fs/model/deepseek/bartowski/DeepSeek-R1-Distill-Qwen-32B-Q4_K_M.gguf' , 'parent' : null , 'max_model_len' : 2048 , 'permission' : [ { 'id' : 'modelperm-f96541eb4c5849baa7d25b138009a094' , 'object' : 'model_permission' , 'created' : 1739969336 , 'allow_create_engine' : false , 'allow_sampling' : true , 'allow_logprobs' : true , 'allow_search_indices' : false , 'allow_view' : true , 'allow_fine_tuning' : false , 'organization' : '*' , 'group' : null , 'is_blocking' : false } ] } ] }
· 使用 curl 命令測試 DeepSeek API $ curl http://localhost:6006/v1/chat/completions \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ds-key-001' \ -d '{ 'model': 'bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF', 'messages': [ {'role': 'user', 'content': '問題:玄武門之變結束的當天,李世民在深夜寫下一段獨白,他會寫什么?要求:先思考,然后按照以下格式回答用戶的問題:<think>推理內容</think>內容'} ], 'temperature': 0.6 }'
注:如前文所述,為了啟用DeepSeek的推理能力,需要在提示詞中的問題后面增加以下內容:
先思考,然后按照以下格式回答用戶的問題:
<think>推理內容</think>
內容
使用建議:
為了獲得預期的性能,建議在使用 DeepSeek-R1 系列模型(包括基準測試)時,遵循以下配置:
· 將溫度設置在 0.5-0.7 范圍內(推薦 0.6),以防止無休止的重復或語無倫次的輸出。 · 避免添加系統提示;所有指令都應包含在用戶提示中。 · 對于數學問題,建議在提示中包含如下指令:“請逐步推理,并將最終答案放在 \boxed{} 中。” · 在評估模型性能時,建議進行多次測試并對結果取平均值。 執行以上命令后,在啟動vLLM服務的終端窗口,可以看到以下日志:
INFO 02-19 20:55:19 loggers.py:72] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Waiting: 0 reqs GPU KV cache usage: 0.0%. INFO 02-19 20:55:24 loggers.py:72] Avg prompt throughput: 9.2 tokens/s, Avg generation throughput: 36.8 tokens/s, Running: 1 reqs, Waiting: 0 reqs GPU KV cache usage: 4.5%. INFO 02-19 20:55:29 loggers.py:72] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 38.7 tokens/s, Running: 1 reqs, Waiting: 0 reqs GPU KV cache usage: 7.2%. INFO: 127.0.0.1:54702 - 'POST /v1/chat/completions HTTP/1.1' 200 OK
下面對日志中提到的幾個指標進行說明:
· Avg prompt throughput 反映了 prompt 處理的速度,數值可能因 prompt 大小及初始處理開銷而波動; · Avg generation throughput 則表示生成輸出過程中的 token 速率,數值較高表明生成效率較好; · Running reqs 和 Waiting reqs 分別展示了當前正在處理與等待處理的請求數量,當前系統負載較低(運行1個請求、無等待請求); · GPU KV cache usage 表示生成過程中用于緩存的 GPU 內存占用率,隨生成 token 數的累計逐步增加,反映模型在動態生成時對內存的使用情況。 這些指標綜合起來有助于監控系統的實時性能和資源使用,能夠為調優和擴容提供依據。
· Avg prompt throughput(平均提示吞吐率) · 含義 :該指標表示系統處理輸入 prompt 時,單位時間內處理的 token 數量,通常以 tokens/s 為單位。 · 日志中顯示有一次為 0.0 tokens/s
,另一處為 9.2 tokens/s
。 · 這說明在某個時刻(例如剛接收到請求時)prompt 的 token 數處理速度可能較低,而在實際載入或處理 prompt 數據后,平均每秒可以處理大約 9.2 個 token。 · Avg generation throughput(平均生成吞吐率) · 含義 :該指標描述模型在生成響應(即生成 tokens 時)的 token 生成速度,同樣以 tokens/s 為單位。 · 日志中分別顯示 36.8 tokens/s
和 38.7 tokens/s
。 · 這表示模型在生成階段的算力較強,平均每秒能產生大約 37 個 token,反映了模型生成階段的高效性。 · Running reqs(正在運行的請求數量) · 含義 :這是當前系統中正處于活躍狀態、正在被處理(例如生成響應)的請求數。 · 日志中狀態顯示為 Running: 1 reqs
,這表明當前有一個請求在被系統積極處理。 · 含義 :表示目前在隊列中等待處理、尚未啟動生成的請求數量。 · 日志中顯示為 Waiting: 0 reqs
,說明沒有請求處于排隊等待狀態,系統的調度和資源分配都能及時處理進入的請求。 · GPU KV cache usage(GPU KV緩存使用率) · 含義 :KV cache(Key-Value Cache)用于 Transformer 模型中保存此前計算得到的 key 和 value,以便在生成過程中復用這些信息,從而避免重復計算。該指標顯示當前這部分緩存占用了 GPU 顯存的百分比。 · 日志中先后顯示 4.5%
和 7.2%
的使用率。 · 這說明隨著生成 token 數量的增加,KV cache 會逐漸占用更多的 GPU 顯存,反映了生成過程動態累積緩存的結果。 · KV cache 的設計目的是為避免重復計算,同時支持更高的并發和長序列生成,因此其內存占用會隨著生成任務的 token 數增加而逐步上升。 · 用 Python 腳本測試 DeepSeek API from openai import OpenAI openai_api_key = 'ds-key-001' #填寫前文啟動DeepSeek推理服務時設置的API秘鑰 openai_api_base = 'http://localhost:6006/v1' model_name= 'bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF' client = OpenAI( api_key=openai_api_key, base_url=openai_api_base, ) prompt= ''' 問題: 玄武門之變結束的當天,李世民在深夜寫下一段獨白,你覺得他會寫什么? 要求: 先思考,然后按照以下格式回答用戶的問題: <think>推理內容</think> 內容 ''' chat_response = client.chat.completions.create( model=model_name, messages=[ { 'role' : 'user' , 'content' : prompt}, ], temperature= 0.6 ) print ( 'Chat response:' , chat_response)
Python腳本測試DeepSeek API的輸出結果如下:
<think> 好,我需要幫用戶想一下李世民在玄武門之變結束當天深夜寫下的獨白。首先,我要了解玄武門之變的背景。這場變故發生在626年,李世民為了爭奪皇位,發動了政變,殺死了自己的兄弟李建成和李元吉。 李世民當時的心理應該是復雜的。一方面,他成功地鞏固了自己的地位,成為太子,為后來的皇帝鋪平了道路。另一方面,他也背負了兄弟相殘的罪名,內心一定有很多掙扎和反思。 所以,他的獨白可能會反映出他的復雜情緒。他可能會表達對權力的渴望,同時也感到內心的壓力和不安。他可能會提到自己曾經的猶豫,以及最終做出決定的艱難。 另外,李世民后來成為了唐太宗,開創了“貞觀之治”,這說明他有治國理政的雄心。因此,他的獨白中也可能流露出對未來的期望和責任感。 我還需要考慮獨白的語氣。他可能會用一種反思和嚴肅的口吻,既不掩飾自己的野心,也不回避內心的矛盾。 綜合這些因素,我可以構思一段獨白,既展現他的決心,也反映他的內心掙扎,同時為未來的統治埋下伏筆。 最后,我需要確保這段獨白符合歷史背景和人物性格,讓讀者能夠感受到李世民當時的復雜心境。 </think> ## 《權力的代價》 寒風刺骨,我獨自站在玄武門城樓上,看著地上斑駁的血跡。遠處的宮燈明明滅滅,像是無數雙眼睛在注視著這個改變命運的夜晚。 長嘆息一聲,我點燃了桌上的蠟燭。火苗在黑暗中搖曳,將我的影子投射在墻上,那影子比往日還要高大幾分。 '權力...終究是要用鮮血來澆灌的。'我喃喃自語,指尖無意識地摩挲著腰間的佩劍。劍鞘上還殘留著清晨的血跡,那是我親手抹去的。 腦海中又浮現出那個場景:大哥李建成端著酒杯,臉上帶著一貫的溫和笑容;四弟李元吉在一旁促狹地笑著,攛掇大哥多喝幾杯。我看著他們,突然覺得這兄弟情義太過虛偽可笑。 '你們以為我愿意這樣嗎?'我握緊了拳頭,指甲深深陷入掌心。記得當年在東宮,我夜以繼日地讀書,謀劃著如何治理國家,如何讓百姓安居樂業。可他們,卻只顧著爭權奪利,甚至想要取我性命。 燭光下,我的影子忽明忽暗。我閉上眼睛,仿佛又回到了那個雨夜。雨聲中,我聽到大哥在后院與人密謀,要如何除掉我這個眼中釘。那一刻,我握緊了刀柄,渾身的血液仿佛都凝固了。 '對不起,大哥。'我低聲說著,淚水在眼眶中打轉。可轉念一想,若我不先動手,今日的我早已是刀下之鬼。這天下,終究是要由有能力的人來治理。 桌上的茶已經涼了,我端起來一飲而盡。苦澀的味道在口中蔓延,像是這權力帶來的所有辛酸。遠處傳來更夫的梆聲,新的一天即將開始。 我站起身,拍了拍衣襟上的塵土。既然已經踏上了這條路,就再無回頭的余地。我李世民,定不會辜負這大好河山,也定會讓大唐盛世重現人間。
三、部署知識庫應用 1、開放DeepSeek推理服務接口 一般情況下,LLM大模型推理服務與應用服務不會部署在同一臺服務器上。
由于知識庫應用服務器會調用DeepSeek推理服務,因此需要將DeepSeek推理服務接口開放出來。
通過終端登錄知識庫應用服務器,執行以下命令后回車(注意:執行后不要關閉該終端窗口):
$ ssh -CNg -L 6006:127.0.0.1:6006 root@[DeepSeek服務器地址] -p [DeepSeek服務器端口號]
如詢問yes/no請回答yes,并輸入ssh服務的密碼。
輸入密碼回車后無任何其他輸出則為正常,如顯示Permission denied則可能密碼粘貼失敗,請手動輸入密碼 (Win10終端易出現無法粘貼密碼問題)
該命令用于建立SSH 隧道實現帶端口轉發的 SSH 連接,這樣可以通過知識庫應用服務器上的本地端口( localhost:6006 )訪問DeepSeek推理服務器上的API接口。
這通常用于保護對DeepSeek服務器上運行的推理服務的訪問,或訪問那些無法直接從互聯網訪問的DeepSeek服務器。
為了測試DeepSeek推理服務接口是否成功開放,請在知識庫應用服務器上打開瀏覽器,訪問 http://localhost:6006/docs ,查看是否成功顯示如前文所述的DeepSeek接口頁面。
如在本地電腦上遠程訪問知識庫應用服務器驗證DeepSeek推理服務的的話,需要通過以下命令打開知識庫應用服務器的防火墻端口。
$ sudo ufw allow 6006/tcp
2、部署知識庫應用 前文完成DeepSeek推理服務的部署后,下一步就是部署和運行LLM應用——知識庫。
知識庫應用服務器配置要求:
· 操作系統:Ubuntu 22.04 / CentOS 7.6 64 位系統 執行以下命令通過Docker方式在線安裝 MaxKB [8] 知識庫應用。
$ docker run -d --name=maxkb --restart=always -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data -v ~/.python-packages:/opt/maxkb/app/sandbox/python-packages registry.fit2cloud.com/maxkb/maxkb
待所有容器狀態顯示為healthy后,可通過瀏覽器訪問知識庫。
打開瀏覽器,輸入以下地址:
http://[知識庫應用服務器地址]:8080
默認登錄信息
如在本地電腦上遠程訪問知識庫應用服務器的話,需要通過以下命令打開知識庫應用服務器的防火墻端口。
$ sudo ufw allow 8080/tcp
知識庫成功部署后,能夠打開以下登錄頁面。
知識庫登錄頁面 3、知識庫應用對接DeepSeek模型 知識庫應用的使用操作流程一般可分為四步:添加模型、創建知識庫、創建應用、發布應用。
在高級編排應用中還可以通過函數庫的功能,實現數據處理、邏輯判斷、信息提取等功能,提供更加強大、靈活的能力。
知識庫操作流程 模型管理用于對接供應商的大語言模型,支持對接主流的大模型,包括本地私有大模型(DeepSeek / Llama 等)。
除了DeepSeek等文本生成模型外,還支持向量模型、重排、語音識別、語音合成、視覺模型、圖片生成等模型。
登錄 MaxKB 系統后,在供應商列表中選擇vLLM,然后點擊【添加模型】,進入模型配置表單配置參數如下:
· 權限:分為私有和公用兩種權限,私有模型僅當前用戶可用,公用模型即系統內所有用戶均可使用,但其它用戶不能編輯。 · 基礎模型:輸入前文中部署的DeepSeek地址。 · API Key:輸入前文啟動DeepSeek推理服務時所設置的API Key。 如下圖所示,將前述DeepSeek大語言模型配置到知識庫應用中。
接入DeepSeek模型 如前文所述,由于DeepSeek的官方模型庫的一個bug,需要通過修改DeepSeek的分詞器配置文件予以解決。
這種解決bug的workaround方式,需要在提示詞中顯式增加 <think></think>
標簽,才能啟動DeepSeek模型的推理Reasoning能力。
提示詞增加think標簽 4、低代碼可視化流程編排 點擊【創建應用】,輸入應用名稱,選擇【高級編排】,點擊【創建】,進入工作流編排頁面。
工作流默認樣例 每個工作流都有基本信息與開始兩個基礎節點:
· 基本信息:應用的基本信息設置節點,如應用名稱、描述、開場白等設置,每個應用只有一個基本信息節點,不能刪除和復制。 · 開始節點:工作流程的開始,每個應用只能有一個開始節點,不能刪除和復制。 編排工作流 點擊右上角的【添加組件】,可以點擊或拖拽到畫布進行工作流編排。以下是每個組件的用途說明:
· 知識庫檢索:關聯知識庫,檢索與問題相關分段的節點。 · 多路召回:使用重排模型隊多個知識庫的檢索結果進行二次召回。 · 表單收集:通過表單的方式收集問答所需要的必要信息。 · 問題優化:AI對話的一種,設定了默認的角色和提示詞,根據上下文優化問題。 文檔上傳 :支持在對話時上傳文檔、圖片以及音頻文件,并在后續節點中可以對上傳后的文件進行解析。
文檔上傳節點 圖片理解 :對用戶上傳的圖片文件進行分析和理解。
圖片理解節點 節點設置:
· 選擇圖片:待理解和分析的圖片,默認為當前用戶上傳的圖片文件。 參數輸出:
· AI回答內容{answer}:根據上傳的圖片以及角色、提示詞等信息圖片理解模型返回的內容。 圖片生成 :根據文本描述生成對應的圖片。
圖片生成節點 節點設置:
· 提示詞(正向):引導模型生成積極、建設性輸出的文字輸入。 · 提示詞(負向):不應該包含在生成輸出中的元素、主題或特征的描述。 參數輸出:
· AI回答內容 {answer}:即圖片生成模型根據文本輸入生成的圖片。 知識庫檢索 :如果應用需要關聯知識庫,則需要在編排中添加知識庫檢索節點,選擇知識庫、設置檢索參數、選擇檢索的問題。
知識庫檢索節點 節點設置:
· 檢索參數:包括檢索模式、相似度閾值、引用分段數量以及最大引用字符數。 參數輸出:
· 檢索結果的分段列表 {paragraph_list}:數組類型,指根據檢索問題、檢索參數進行檢索后命中的分段列表,包含了分段的所有屬性; · 滿足直接回答的分段列表 {is_hit_handling_method_list}:數組類型,指根據檢索問題、檢索參數進行檢索后命中的分段中滿足直接回答的所有分段列表,包含了分段的所有屬性; · 檢索結果 {data}:字符串類型,指根據檢索問題、檢索參數進行檢索后命中的分段內容; · 滿足直接回答的分段內容 {directly_return}:字符串類型,指根據檢索問題、檢索參數進行檢索后命中的分段中滿足直接回答的所有分段內容。 多路召回 :根據需要重排的內容、檢索問題以及檢索參數進行多路召回。
多路召回節點 節點設置:
· 重排內容:待重排的多個內容,一般是多個不同知識庫的檢索結果。 · 檢索參數:包括 score 閾值、引用分段數以及最大引用字符數。 · 檢索問題:根據檢索問題進行重排,一般為用戶問題或問題優化后的結果。 參數輸出:
· 重排結果列表 {result_list}:數組類型,指根據重排后的結果列表。 · 重排結果 {result}:字符串類型,指根據檢索參數后的重排結果。 判斷器 :根據不同的條件進行邏輯判斷,每個判斷分支后面必須有后置執行節點。
判斷器 輸出參數說明:
· 分支名稱{branch_name}:每個判斷分支的名稱。 指定回復 :指定輸出文本內容,在知識庫查詢到的相關內容滿足直接回答的要求,可以輸出檢索內容,也可以在知識庫沒有查詢到關聯內容時,指定回復內容。
指定回復 輸出參數說明:
表單收集 :通過表單的設計,以引導的方式主動獲取必要的信息,一般應用于需要多次詢問的應答場景。
表單收集節點 節點設置:
· 表單輸出內容:表單提示說明以及表單內容,可以單項輸入,也可以輸入多項信息。 參數輸出:
· 表單全部內容{form_data}:表單的全部內容。 · 表單全部內容將作為固定的輸出,對于各個表單項也都進行參數化輸出。 問題優化 :根據當前會話的歷史聊天記錄,以及在節點設置的大預言模型和提示詞,對當前問題進行智能優化。
問題優化節點 節點設置:
· 歷史聊天記錄:在當前對話中有關聯的歷史會話內容。例如,歷史聊天記錄為1,表示當前問題以及上一次的對話內容一起輸送給大模型。 · 返回內容:是否在對話中顯示該節點返回的內容。。 參數輸出:
· 問題優化結果 {answer}:通過大模型優化后的問題。 文檔內容提取 :對用戶上傳的文檔進行內容總結。
文檔內容提取節點 節點設置:
· 選擇文檔:即用戶上傳的文檔,需要在基本信息節點開啟對文件上傳的支持。 參數輸出:
· 文檔輸出 {content}:對用戶上傳文件進行的總結輸出。 語音轉文本 :將音頻文件轉換為文本。
語音轉文本節點 節點設置:
· 語音文件:即上傳的音頻文件,支持的格式包括:mp3、wav、ogg、acc。 參數輸出:
· 結果 {result}:語音轉換后的文本內容。 文本轉語音 :將文本轉換為音頻。
文本轉語音節點 節點設置:
參數輸出:
· 結果 {result}:將文本轉成的音頻內容。 添加函數 :在高級編排流程中,可以添加函數庫函數作為流程中的一個處理節點,以靈活處理復雜需求。
添加函數 添加應用 :在高級編排流程中,可以添加其它應用(簡單配置應用和流程編排應用)作為流程中的一個處理節點,直接快速利用子應用的問答結果。
添加應用 節點設置:
· 返回內容:開啟后在對話過程中將子應用的返回結果。 參數輸出:
執行條件 :工作流中支持多出多進,在這個情況下,匯集節點可以根據與前置節點的邏輯關系,選擇執行條件。
執行條件 · ALL:需要等所有前置連線節點全部執行完成后,才可執行當前節點。 · ANY:任一前置連線節點執行完成后,即可執行當前節點。 調試預覽 :完成所有的編排設計后,可點擊【調試】后,先校驗流程是否合規,校驗通過后可在當前頁面進行對話測試。在調試對話框中進行提問,AI回答完成后,會顯示【執行詳情】,點擊【執行詳情】后,在彈出執行詳情對話框中可以查看每個流程節點的執行狀態、耗時以及其它執行信息。
調試預覽 應用接入 :知識庫支持創建的應用的與企業微信應用、企業微信客服、公眾號(服務號和訂閱號)、釘釘應用、飛書應用接入,實現企業內部員工、外部公眾進行對話。
配置企業微信應用 企業微信機器人 接入微信客服 釘釘機器人 配置飛書機器人 飛書機器人 四、知識庫核心業務邏輯 知識庫通過模塊化的設計,將知識召回、對話交互、圖像處理等多個核心功能拆分為獨立的節點,每個節點都有清晰的業務邏輯與上下文管理。前端則通過 LogicFlow 實現圖形化配置與實時交互,而后端則依賴 Django、LangChain 與 PG Vector 等組件保證高效的數據檢索與 LLM 推理服務接口。整個系統為用戶提供了一個靈活、可擴展的知識問答平臺,能夠快速整合多種數據與模型服務,響應用戶提出的各類查詢問題。
下面給出一個對該知識庫的核心業務邏輯的概述,以便快速理解整體架構和主要功能模塊:
1、整體架構 知識庫整合了以下核心技術和模塊:
· 前端 :基于 Vue.js 和 LogicFlow 的工作流編輯器。用戶可以在圖形化界面中通過拖拽方式配置工作流程,比如設置“開始節點”、“問答節點”、“搜索節點”等,從而構建不同的使用場景。 · 后端 :使用 Django 作為 Web 框架,通過 Python 實現后端服務。利用 LangChain 框架對接大語言模型(LLM)的推理服務,支持流式和非流式輸出。 · 數據處理 :使用 PostgreSQL 作為數據庫,并借助 PG Vector 插件實現文檔向量化存儲與相似度搜索,為知識召回、語義匹配等提供支持。 · 模型服務 :構建了對接 LLM 推理服務的各個模塊,包括直接調用 LLM 模型生成回答、對搜索結果進行重新排序(reranker)、圖像生成與理解等業務邏輯。各個節點模塊之間通過共享上下文數據,實現了整個工作流的銜接。 知識庫應用代碼庫地址:https://github.com/1Panel-dev/MaxKB
以下是知識庫應用Django后端代碼結構。
root ├── apps # Django后端代碼根目錄 │ ├── application # 主要應用模塊 │ │ ├── flow # 工作流引擎相關模塊 │ │ │ ├── step_node # 工作流節點定義目錄 │ │ │ │ ├── ai_chat_step_node # AI 對話節點相關代碼 (例如: base_chat_node.py) │ │ │ │ │ └── impl # AI 對話節點實現 (例如: base_chat_node.py 的具體實現) │ │ │ │ ├── application_node # 應用節點相關代碼 (例如: base_application_node.py) │ │ │ │ │ └── impl # 應用節點實現 (例如: base_application_node.py 的具體實現) │ │ │ │ ├── image_generate_step_node # 圖像生成節點相關代碼 (例如: base_image_generate_node.py) │ │ │ │ │ └── impl # 圖像生成節點實現 (例如: base_image_generate_node.py 的具體實現) │ │ │ │ ├── image_understand_step_node # 圖像理解節點相關代碼 (例如: base_image_understand_node.py) │ │ │ │ │ └── impl # 圖像理解節點實現 (例如: base_image_understand_node.py 的具體實現) │ │ │ │ ├── question_node # 問題節點/通用對話節點相關代碼 (例如: base_question_node.py) │ │ │ │ │ └── impl # 問題節點實現 (例如: base_question_node.py 的具體實現) │ │ │ │ ├── reranker_node # 重排序節點相關代碼 (例如: base_reranker_node.py) │ │ │ │ │ └── impl # 重排序節點實現 (例如: base_reranker_node.py 的具體實現) │ │ │ │ ├── search_dataset_node # 知識庫搜索節點相關代碼 (例如: base_search_dataset_node.py) │ │ │ │ │ └── impl # 知識庫搜索節點實現 (例如: base_search_dataset_node.py 的具體實現) │ │ │ │ └── i_step_node.py # 工作流節點接口定義 (例如: INode 接口) │ │ │ ├── impl # 工作流引擎核心實現 │ │ │ │ └── workflow_manage.py # 工作流管理類 (WorkflowManage) │ │ │ ├── tools.py # 工作流工具類 (例如: Reasoning, 流式響應工具) │ │ │ └── default_workflow.json # 默認工作流配置示例 │ │ ├── tools.py # 應用級別的工具模塊 │ │ └── flow.py # 工作流定義或相關類 │ ├── common # 通用模塊 │ │ ├── config # 通用配置 (例如: embedding_config.py 向量配置) │ │ ├── db # 數據庫相關模塊 │ │ │ └── search.py # 數據庫搜索相關功能 (例如: native_search) │ │ ├── response # 通用響應處理 (例如: result 函數) │ │ │ └── base_response.py # 基礎響應類定義 │ │ ├── util # 通用工具函數 │ │ │ ├── common.py # 常用工具函數 (例如: bytes_to_uploaded_file) │ │ │ └── file_util.py # 文件操作工具 (例如: get_file_content) │ │ └── response.py # 響應處理相關 │ ├── dataset # 數據集/知識庫相關模塊 │ │ ├── models.py # 數據集模型定義 (例如: Document, Paragraph, DataSet, File) │ │ └── serializers # 數據集序列化器 (例如: file_serializers.py FileSerializer) │ │ └── file_serializers.py │ ├── embedding # 向量嵌入相關模塊 │ │ └── models.py # 嵌入模型相關定義 (例如: SearchMode) │ ├── setting # 系統設置/模型設置模塊 │ │ ├── models.py # 設置相關模型 (例如: Model, ModelCredential) │ │ └── models_provider # 模型提供者相關 │ │ └── tools.py # 模型提供工具函數 (例如: get_model_instance_by_model_user_id, get_model_credential) │ └── smartdoc # 項目根目錄或智能文檔相關模塊 │ └── conf # 項目配置 │ └── __init__.py └── manage.py # Django 項目管理腳本
以下是知識庫應用Vue前端代碼結構。
ui/src # Vue前端代碼根目錄 ├── assets # 靜態資源目錄 │ ├── images # 圖片資源 │ └── styles # 全局樣式文件 (如 CSS, SCSS) ├── components # 通用組件目錄 │ ├── Common # 通用UI組件 (例如按鈕,對話框,表格等) │ ├── Specific # 特定業務場景組件 (例如工作流節點組件,圖表組件) ├── layouts # 布局組件目錄 (例如頭部,側邊欄,頁腳等) ├── views # 視圖頁面目錄 (每個頁面通常對應一個路由) │ ├── Home.vue # 首頁視圖 │ ├── Workflow.vue # 工作流管理視圖 │ ├── Dataset.vue # 數據集管理視圖 │ └── ... # 其他業務視圖頁面 ├── router # 路由配置目錄 │ └── index.js # 路由配置文件 ├── store # Vuex 狀態管理目錄 (如果項目使用了 Vuex) │ ├── modules # 模塊化的狀態管理 │ │ ├── user.js # 用戶狀態管理模塊 │ │ └── app.js # 應用全局狀態管理模塊 │ └── index.js # Vuex store 入口文件 ├── utils # 工具函數庫目錄 │ ├── request.js # HTTP 請求封裝 │ ├── helpers.js # 通用輔助函數 │ └── ... # 其他工具函數 ├── App.vue # 根組件 ├── main.js # 入口文件,Vue 應用初始化 └── index.html # HTML 模板文件
2、前端工作流編輯與展示 · LogicFlow 與 Vue.js 前端基于 Vue 組件構建,利用 LogicFlow 實現工作流圖形展示與操作。開發者可以在頁面上構建一個包含多個節點的流程圖,每個節點對應后端中不同的業務處理邏輯。例如: · “開始節點”:收集用戶輸入(提問、時間、全局信息等)。 · “AI Chat 節點”:調用 LLM 模型進行回答生成。 · “搜索數據集節點”:根據用戶問題,利用向量匹配技術檢索相關文檔。 · 實時反饋與交互 前端利用 LogicFlow 提供的拖拽、縮放等功能,讓用戶可以直觀地配置工作流,同時也支持響應式展示大模型返回的流式回答內容。 3、后端工作流節點與業務邏輯 后端主要采用“節點化”的工作流架構,每個節點對應一段業務邏輯,常見的節點類型包括:
· 搜索數據集節點 在 BaseSearchDatasetNode
中,邏輯主要包括: · 根據用戶問題,獲取相應知識庫的嵌入模型 ID。 · 調用嵌入模型將問題轉為向量,并用 PG Vector 實現向量查詢,檢索與問題語義最相近的文檔段落。 · 對檢索結果進行過濾與排序,然后返回給下游節點使用。 · 問答節點 / AI Chat 節點 在 BaseChatNode
和 BaseQuestionNode
中: · 先從節點上下文中獲取歷史對話記錄,以及當前問題。 · 調用 LangChain 封裝的 LLM 模型,通過 invoke
或 stream
方法得到模型回答。 · 回答過程中支持流式輸出,通過分塊拼接內容,并對答案進行 token 計數、上下文保存等操作。 · 每個節點還實現了 save_context
方法,將節點執行信息(如回答、耗時、 token 數量)保存到上下文中,方便后續結果組裝與調試。 · 重新排序節點 (Reranker) 在 BaseRerankerNode
中: · 將檢索出的候選文檔利用一個重排模型(如 SiliconCloud 或本地重排模型)進行壓縮與重新排序,提高最終答案的相關性。 · 返回的結果通常經過進一步聚合,形成最終的答案或文檔摘要。 · 圖像生成與理解節點 例如在 BaseImageGenerateNode
與 BaseImageUnderstandNode
中: · 根據用戶描述調用相應模型生成圖像,或對上傳的圖像進行理解處理。 · 生成的圖像會經過文件處理,上傳后返回 URL,供前端展示。 · 應用節點 應用節點(Application Node)將前面各個節點的處理結果進行整合,最終生成整體回答。它不僅保存了回答文本,還匯總了各個節點的詳細信息、token 使用情況、上下文數據等。 · 工作流整體管理 工作流各節點之間通過上下文數據(例如 node_chunk
、 workflow_manage
等)共享信息。整體流程從用戶輸入開始,依次經過各個節點處理,最終在返回答案同時也保存一個詳細的執行日志,便于追蹤整個會話流程。 4、數據向量與知識庫召回 · 向量存儲與檢索 利用 PostgreSQL 與 PG Vector 插件,對知識庫中的文檔進行向量化存儲。用戶輸入的問題首先會通過嵌入模型轉換成一個向量,再在向量庫中搜索語義相似的文檔。 · 嵌入模型與向量庫邏輯 在相關模塊如 pg_vector.py
、 search_dataset_node
中,可以看到: · 構建查詢語句,使用向量距離作為排序依據,返回最匹配的結果。 5、模型服務及對接 后端通過多種模型提供者(比如 SiliconCloud 重排模型、本地重排模型等)對接外部 LLM 推理服務。調用流程通常如下:
1. 獲取模型實例 利用 get_model_instance_by_model_user_id
根據模型 ID 和用戶信息獲取具體的模型包裝類實例。 2. 調用推理或流式 API 根據業務場景,調用模型實例的 invoke
(同步)或 stream
(流式)方法進行推理,返回回答文本或分塊回答。 3. 上下文組裝與輸出 推理結果通過 _write_context
或類似方法保存,并經過 Reasoning 類處理附加 “思考” 邏輯,最后組裝成完整回答返回給前端。 五、核心代碼解析 下面介紹該知識庫系統中如何利用 LangChain 框架來連接大語言模型(LLM)、調用輔助函數、以及基于向量數據庫的知識檢索等核心組件。
整個系統采用模塊化設計,每個“節點”負責完成特定的任務,節點內部通過調用 get_model_instance_by_model_user_id 等工廠方法,獲取由 LangChain 封裝的模型實例,然后調用相應的方法(如 invoke、stream、embed_query 等)實現推理、流式響應以及向量搜索等操作。
下面給出幾個關鍵模塊的示例代碼及詳細說明。
1、LLM 推理模塊(基于 LangChain) 在問答和對話節點中,系統通過調用 LangChain 封裝的 LLM 模型來生成回答。核心邏輯包括:
· 利用工廠函數 get_model_instance_by_model_user_id 根據模型 ID 和用戶信息獲取具體的模型實例; · 構造系統提示、歷史對話消息、用戶提問等,拼裝成消息列表(消息類型使用 HumanMessage、SystemMessage 等); · 根據是否需要流式響應,調用模型的 invoke(同步)或 stream(流式)方法; · 在返回結果前調用 _write_context 將節點執行過程和 token 統計信息寫入上下文。 下面是一個類似 BaseChatNode 節點中 LLM 調用的示例代碼:
def execute ( self, model_id, system, prompt, dialogue_number, history_chat_record, stream, chat_id, chat_record_id, model_params_setting= None , dialogue_type= None , model_setting= None , **kwargs ) -> NodeResult: if dialogue_type is None : dialogue_type = 'WORKFLOW' if model_params_setting is None : model_params_setting = get_default_model_params_setting(model_id) if model_setting is None : model_setting = { 'reasoning_content_enable' : False , 'reasoning_content_end' : '</think>' , 'reasoning_content_start' : '<think>' } self .context[ 'model_setting' ] = model_setting # 獲取 LLM 模型實例,底層借助 LangChain 封裝 chat_model = get_model_instance_by_model_user_id( model_id, self .flow_params_serializer.data.get( 'user_id' ), **model_params_setting) # 構建歷史消息 history_message = self .get_history_message(history_chat_record, dialogue_number, dialogue_type, self .runtime_node_id) self .context[ 'history_message' ] = history_message # 生成當前問題的提示信息 question = self .generate_prompt_question(prompt) self .context[ 'question' ] = question.content system = self .workflow_manage.generate_prompt(system) self .context[ 'system' ] = system # 構造最終交互的消息列表,利用 LangChain 中的消息類型進行封裝 message_list = self .generate_message_list(system, prompt, history_message) self .context[ 'message_list' ] = message_list if stream: response = chat_model.stream(message_list) return NodeResult({ 'result' : response, 'chat_model' : chat_model, 'message_list' : message_list, 'history_message' : history_message, 'question' : question.content }, {}, _write_context=write_context_stream) else : response = chat_model.invoke(message_list) return NodeResult({ 'result' : response, 'chat_model' : chat_model, 'message_list' : message_list, 'history_message' : history_message, 'question' : question.content }, {}, _write_context=write_context)
說明:
· get_model_instance_by_model_user_id 用于獲取具體的 LLM 模型實例,內部可能針對不同的模型調用不同的 API; · generate_message_list 將系統提示、歷史信息和用戶提問結合,生成符合 LangChain 格式的消息列表; · 根據 stream 參數選擇同步或流式調用,返回的 NodeResult 對象中包含后續處理需要的上下文信息。 2、向量數據庫(PG Vector)與語義檢索 在搜索數據集節點中,系統利用向量數據庫做知識召回。流程如下:
· 通過 get_embedding_id 確定使用哪個嵌入模型; · 通過 get_model_instance_by_model_user_id 獲取嵌入模型實例,并調用 embed_query 將自然語言問題轉換成向量表示; · 調用 VectorStore 中封裝好的向量檢索方法(例如 vector.query)進行向量相似度搜索,檢索與問題語義相近的文檔段落。 下面是一個基于 BaseSearchDatasetNode 的示例:
def execute ( self, dataset_id_list, dataset_setting, question, exclude_paragraph_id_list= None , **kwargs ) -> NodeResult: self .context[ 'question' ] = question if len (dataset_id_list) == 0 : return get_none_result(question) # 根據知識庫列表,獲取統一的嵌入模型ID model_id = get_embedding_id(dataset_id_list) # 獲取嵌入模型實例,基于 LangChain 調用嵌入接口 embedding_model = get_model_instance_by_model_user_id( model_id, self .flow_params_serializer.data.get( 'user_id' )) # 將問題轉換為向量 embedding_value = embedding_model.embed_query(question) # 獲取向量數據庫實例,此處基于 PG Vector 封裝 vector = VectorStore.get_embedding_vector() exclude_document_id_list = [ str (document. id ) for document in QuerySet(Document). filter ( dataset_id__in=dataset_id_list, is_active= False )] # 調用向量檢索接口,根據向量距離返回相似候選文檔 embedding_list = vector.query( question, embedding_value, dataset_id_list, exclude_document_id_list, exclude_paragraph_id_list, True , dataset_setting.get( 'top_n' ), dataset_setting.get( 'similarity' ), SearchMode(dataset_setting.get( 'search_mode' )) ) # 手動關閉數據庫連接 connection.close() if embedding_list is None : return get_none_result(question) paragraph_list = self .list_paragraph(embedding_list, vector) result = [ self .reset_paragraph(paragraph, embedding_list) for paragraph in paragraph_list] result = sorted (result, key= lambda p: p.get( 'similarity' ), reverse= True ) return NodeResult({ 'result' : result, 'question' : question}, {})
說明:
· 首先通過嵌入模型將問題編碼成向量,再調用 PG Vector 提供的查詢接口; · 向量檢索返回的是一系列候選段落,之后經過過濾和排序得到最匹配的結果; · 這些匹配結果可以后續傳遞給重排節點或直接用于回答生成。 3、函數調用與工具集成 除了對話和知識檢索外,系統還支持調用其他輔助函數來實現例如文檔重排、圖像生成/理解等功能。以重排節點(reranker)為例,其主要邏輯如下:
· 整合多個節點輸入的內容,通過 merge_reranker_list 合并; · 通過 get_model_instance_by_model_user_id 獲取重排模型實例; · 調用模型的 compress_documents 方法,對候選文檔進行內容壓縮和重新排序。 示例代碼如下:
def execute ( self, question, reranker_setting, reranker_list, reranker_model_id, **kwargs ) -> NodeResult: # 將不同來源的候選文本合并 documents = merge_reranker_list(reranker_list) top_n = reranker_setting.get( 'top_n' , 3 ) self .context[ 'document_list' ] = [ { 'page_content' : document.page_content, 'metadata' : document.metadata} for document in documents ] self .context[ 'question' ] = question # 獲取重排模型,并調用相關函數實現文檔壓縮 reranker_model = get_model_instance_by_model_user_id( reranker_model_id, self .flow_params_serializer.data.get( 'user_id' ), top_n=top_n) result = reranker_model.compress_documents(documents, question) similarity = reranker_setting.get( 'similarity' , 0.6 ) max_paragraph_char_number = reranker_setting.get( 'max_paragraph_char_number' , 5000 ) result = reset_result_list(result, documents) filtered_result = filter_result(result, max_paragraph_char_number, top_n, similarity) return NodeResult({ 'result_list' : filtered_result, 'result' : '' .join([item.get( 'page_content' ) for item in filtered_result]) }, {})
說明:
· merge_reranker_list 會把不同節點返回的候選文檔整合成統一的 Document 對象列表; · 重排操作通過調用模型實例中的 compress_documents 實現,從而得到更加準確和簡潔的回答內容。 總結 知識庫整個系統的核心邏輯在于:
1. 使用 LangChain 封裝的模型實例 通過 get_model_instance_by_model_user_id、embed_query、invoke 以及 stream 等方法,實現 LLM 整體調用,無縫對接大語言模型推理服務。 2. 構造上下文和消息列表 利用 HumanMessage、SystemMessage 等消息類型將系統提示、歷史對話、用戶輸入等進行整合,作為調用 LLM 的輸入。 3. 調用向量庫進行語義檢索 使用 PG Vector 對知識庫中的文檔進行嵌入存儲,并通過向量檢索找到與用戶問題語義最相關的內容。 4. 集成其他輔助功能 例如文檔重排、圖像生成/理解等均通過各自節點調用相應模型接口、工具函數完成。 這種基于節點化工作流的設計,使得系統能夠靈活地將大語言模型、向量數據庫以及其他工具組合起來,實現一個功能豐富、響應迅速的知識問答平臺。
引用鏈接 [1]
Huggingface: https:///collections/deepseek-ai/deepseek-r1-678e1e131c0169c0bc89728d [2]
bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF: https:///bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF [3]
CUDA安裝教程: https://developer./cuda-downloads [4]
cuDNN安裝教程: https://developer./cudnn [5]
PyTorch: https://pytorch.org/ [6]
bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF: https:///bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF [7]
DeepSeek的Hugging Face官方模型庫: https:///deepseek-ai/DeepSeek-R1-Distill-Qwen-32B [8]
MaxKB: https://github.com/1Panel-dev/MaxKB