機(jī)器搭建RAG環(huán)境:Dify+Xinference+vLLM部署實(shí)戰(zhàn))
簡(jiǎn)介這份實(shí)戰(zhàn)教程面向希望快速上手檢索增強(qiáng)生成系統(tǒng)的開(kāi)發(fā)者與運(yùn)維人員圍繞DeepSeek模型系統(tǒng)講解RAG環(huán)境從零搭建的完整流程。內(nèi)容涵蓋技術(shù)棧概要、Dify服務(wù)器、Rerank與Embedding模型服務(wù)器、DeepSeek模型服務(wù)器三臺(tái)ECS的分步部署并涉及CUDA驅(qū)動(dòng)、vLLM推理庫(kù)、Docker容器化、xinference框架以及bge-reranker-large、bge-large-zh-v1.5等中文模型的安裝與調(diào)用幫助讀者掌握多機(jī)協(xié)作下的模型部署與排錯(cuò)思路。資源包為1個(gè)docx文檔約580KB目錄結(jié)構(gòu)清晰按技術(shù)棧與安裝部署兩大模塊組織便于對(duì)照查閱。目前已有326人學(xué)習(xí)適合具備一定深度學(xué)習(xí)基礎(chǔ)、需要落地RAG系統(tǒng)的技術(shù)人員參考。1. 三臺(tái)機(jī)器、三個(gè)模型、一條鏈路這套 RAG 環(huán)境搭建到底在解決什么很多團(tuán)隊(duì)第一次搭 RAG都會(huì)卡在同一個(gè)地方模型能跑但檢索結(jié)果排序不對(duì)生成答案就開(kāi)始胡說(shuō)。這套教程的核心思路很直接——把 RAG 拆成三個(gè)獨(dú)立環(huán)節(jié)分別部署在三臺(tái)服務(wù)器上每臺(tái)只干一件事。Dify 負(fù)責(zé)流程編排和知識(shí)庫(kù)管理ECS-2 跑 Embedding 和 Rerank 兩個(gè)檢索側(cè)模型ECS-3 用 vLLM 拉起 DeepSeek-R1-Distill-Qwen-14B 做生成。三臺(tái)機(jī)器通過(guò)內(nèi)網(wǎng) API 串起來(lái)哪一環(huán)出問(wèn)題就單獨(dú)排查不用在同一個(gè)環(huán)境里反復(fù)折騰依賴(lài)沖突。適合正在做企業(yè)知識(shí)庫(kù)、智能客服、文檔問(wèn)答的開(kāi)發(fā)者尤其是手里有 GPU 但不知道怎么把模型部署和編排平臺(tái)接起來(lái)的場(chǎng)景。2. 技術(shù)棧選型為什么是 Dify Xinference vLLM 這套組合2.1 三個(gè)模塊各管什么這套方案里每個(gè)組件都有明確的邊界。Dify 是應(yīng)用開(kāi)發(fā)平臺(tái)負(fù)責(zé)知識(shí)庫(kù)上傳、分段、檢索策略配置、對(duì)話流程編排它本身不跑模型推理只通過(guò) API 調(diào)用外部模型服務(wù)。Xinference 是模型推理框架專(zhuān)門(mén)用來(lái)部署 Embedding 和 Rerank 這類(lèi)中小模型支持自定義模型注冊(cè)適合把 HuggingFace 上的模型拉到本地跑。vLLM 則是大模型推理引擎核心優(yōu)勢(shì)是 PagedAttention 和連續(xù)批處理能把 14B 級(jí)別的模型在單卡 V100 上跑出可用的吞吐。模塊部署位置作用關(guān)鍵依賴(lài)DifyECS-1流程編排、知識(shí)庫(kù)管理Docker、Docker ComposeXinferenceECS-2Embedding Rerank 推理Python 3.8、CUDA 11.4vLLMECS-3DeepSeek 大模型推理Python 3.10、CUDA 12.1選 Xinference 而不是自己寫(xiě) Flask 服務(wù)是因?yàn)樗詭P妥?cè)、啟動(dòng)、注銷(xiāo)的完整生命周期管理bge 系列模型直接注冊(cè)就能用省掉大量膠水代碼。選 vLLM 而不是 HuggingFace Transformers 直接推理是因?yàn)?14B 模型用 Transformers 跑顯存碎片嚴(yán)重并發(fā)一上來(lái)就 OOMvLLM 的顯存管理能把這部分壓下去。2.2 模型選型的實(shí)際考量Embedding 用bge-large-zh-v1.5輸出 768 維向量最大 512 token中文場(chǎng)景下檢索召回率比 m3e 系列穩(wěn)。Rerank 用bge-reranker-large對(duì)檢索回來(lái)的 top-k 結(jié)果做二次排序把真正相關(guān)的文檔頂?shù)角懊?。生成模型用DeepSeek-R1-Distill-Qwen-14B蒸餾自 Qwen-2.5 系列14B 參數(shù)量在 V100 32G 上剛好能跑精度用 half 模式顯存占用約 28G留一點(diǎn)余量給 KV Cache。注意模型選型不是越大越好。14B 在單卡 V100 上能跑起來(lái)?yè)Q成 32B 就需要多卡或者量化部署復(fù)雜度直接翻倍。先跑通鏈路再考慮升級(jí)。3. ECS-2 部署實(shí)戰(zhàn)Xinference 拉起 Embedding 和 Rerank3.1 環(huán)境準(zhǔn)備與 Xinference 安裝ECS-2 的鏡像是 Ubuntu 20.04 with Tesla Driver 470 和 CUDA 11.4Python 用 3.8。這個(gè)環(huán)境版本不是隨便選的——Xinference 對(duì) CUDA 版本有要求11.4 能兼容 bge 系列模型的推理后端再高反而容易遇到 PyTorch 版本不匹配。# 安裝 xinference 完整版包含所有推理后端 pip install xinference[all] # 配置模型存儲(chǔ)路徑避免默認(rèn)路徑磁盤(pán)爆滿(mǎn) export XINFERENCE_HOME/tmp/xinference # 驗(yàn)證安裝是否成功 xinference --helpXINFERENCE_HOME這個(gè)環(huán)境變量建議寫(xiě)進(jìn)~/.bashrc否則每次重啟終端都要重新 export。模型文件默認(rèn)下載到~/.xinference下如果系統(tǒng)盤(pán)小一定要改到數(shù)據(jù)盤(pán)。啟動(dòng) Xinference 有兩種方式調(diào)試階段用前臺(tái)啟動(dòng)看日志穩(wěn)定后用后臺(tái)啟動(dòng)# 前臺(tái)啟動(dòng)端口固定 9997 xinference-local --host 0.0.0.0 --port 9997 # 后臺(tái)啟動(dòng)日志輸出到 nohup.out nohup xinference-local --host 0.0.0.0 --port 9997 nohup.out 端口 9997 是 Xinference 的默認(rèn)端口Dify 那邊配置模型 API 地址時(shí)要對(duì)應(yīng)上。--host 0.0.0.0是為了讓 ECS-1 能通過(guò)內(nèi)網(wǎng) IP 訪問(wèn)如果只寫(xiě) 127.0.0.1Dify 就連不過(guò)來(lái)。3.2 注冊(cè)自定義 Rerank 模型bge-reranker-large 需要先從 HuggingFace 下載到本地再上傳到服務(wù)器。這一步和 Xinference 安裝可以并行做模型文件大概 1.3G上傳時(shí)間取決于內(nèi)網(wǎng)帶寬。模型上傳后在模型目錄下創(chuàng)建config.json{ model_name: custom-bge-reranker-large, type: normal, language: [en, zh], model_id: BAAI/bge-reranker-large, model_uri: file:///path/to/bge-reranker-large }model_name是自定義名稱(chēng)后面啟動(dòng)和調(diào)用都用這個(gè)名字。model_uri必須用file://前綴加絕對(duì)路徑相對(duì)路徑會(huì)注冊(cè)失敗。language字段聲明支持中英文不影響推理但影響 Xinference 的模型列表展示。注冊(cè)命令# 將自定義模型注冊(cè)到 xinference xinference register --model-type rerank --file model.json --persist # 檢查注冊(cè)結(jié)果 xinference registrations --model-type rerank--persist參數(shù)表示持久化注冊(cè)信息不加的話重啟 Xinference 后模型列表就丟了。注冊(cè)成功后用registrations命令能看到custom-bge-reranker-large出現(xiàn)在列表里。啟動(dòng) Rerank 模型xinference launch --model-name custom-bge-reranker-large --model-type rerank啟動(dòng)后 Xinference 會(huì)加載模型到 GPUT4 16G 顯存跑 bge-reranker-large 大概占 2G 左右余量充足。如果啟動(dòng)報(bào) CUDA out of memory先檢查是不是有其他進(jìn)程占著顯卡。3.3 注冊(cè)自定義 Embedding 模型Embedding 模型的注冊(cè)流程和 Rerank 幾乎一樣區(qū)別在config.json的字段{ model_name: custom-bge-large-zh-v1.5, dimensions: 768, max_tokens: 512, language: [zh], model_id: BAAI/bge-large-zh-v1.5, model_uri: file:///path/to/bge-large-zh-v1.5 }dimensions必須和模型實(shí)際輸出維度一致bge-large-zh-v1.5 是 768 維寫(xiě)錯(cuò)了 Dify 那邊向量檢索會(huì)直接報(bào)維度不匹配。max_tokens是 512超過(guò)這個(gè)長(zhǎng)度的文本會(huì)被截?cái)嘀R(shí)庫(kù)分段時(shí)要注意控制每段長(zhǎng)度。# 注冊(cè) embedding 模型 xinference register --model-type embedding --file model.json --persist # 驗(yàn)證注冊(cè) xinference registrations --model-type embedding # 啟動(dòng)模型 xinference launch --model-name custom-bge-large-zh-v1.5 --model-type embedding兩個(gè)模型都啟動(dòng)后Xinference 的 API 端點(diǎn)就準(zhǔn)備好了。Dify 里配置 Embedding 模型時(shí)填http://ECS-2內(nèi)網(wǎng)IP:9997/v1模型名填custom-bge-large-zh-v1.5Rerank 同理。提示如果后續(xù)要換模型先用xinference unregister注銷(xiāo)舊模型再注冊(cè)新的。直接覆蓋注冊(cè)有時(shí)候會(huì)殘留舊配置導(dǎo)致啟動(dòng)時(shí)加載錯(cuò)誤的模型文件。4. ECS-3 部署實(shí)戰(zhàn)vLLM 拉起 DeepSeek-14B4.1 驅(qū)動(dòng)、CUDA 與 Python 環(huán)境ECS-3 的鏡像是 CentOS 7.9CUDA 11.4但 vLLM 0.43 需要 CUDA 12.1所以驅(qū)動(dòng)和 CUDA 都要重新裝。這里有個(gè)坑如果先裝了 CUDA 再裝驅(qū)動(dòng)驅(qū)動(dòng)安裝程序會(huì)檢測(cè)到已有 CUDA 然后報(bào)錯(cuò)退出。正確順序是先裝驅(qū)動(dòng)再單獨(dú)裝 CUDA Toolkit安裝時(shí)取消勾選驅(qū)動(dòng)選項(xiàng)。驅(qū)動(dòng)選 530.30.02 版本對(duì)應(yīng) CUDA 12.1。安裝完成后驗(yàn)證# 查看驅(qū)動(dòng)版本 nvidia-smi # 查看 CUDA 版本 nvcc -V兩個(gè)命令輸出的 CUDA 版本要一致不一致說(shuō)明環(huán)境變量沒(méi)配好。CUDA 安裝后需要手動(dòng)加環(huán)境變量# 編輯 ~/.bashrc vim ~/.bashrc # 在文件末尾添加路徑根據(jù)實(shí)際安裝位置調(diào)整 export PATH/usr/local/cuda-12.1/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH # 刷新環(huán)境變量 source ~/.bashrcPython 用 conda 創(chuàng)建獨(dú)立環(huán)境版本 3.10conda create -n myenv python3.10 -y conda activate myenvPyTorch 必須裝和 CUDA 12.1 匹配的版本否則 vLLM 安裝時(shí)會(huì)報(bào)錯(cuò)pip install torch2.3.0 torchvision0.18.0 torchaudio2.3.0 --index-url https://download.pytorch.org/whl/cu121這個(gè)命令里的--index-url指定了 PyTorch 官方 CUDA 12.1 的 wheel 源不指定的話默認(rèn)裝 CPU 版本后面 vLLM 跑起來(lái)會(huì)提示找不到 GPU。4.2 vLLM 安裝與模型啟動(dòng)pip install vllm0.43安裝過(guò)程中如果報(bào)依賴(lài)版本沖突按照?qǐng)?bào)錯(cuò)信息逐個(gè)指定版本安裝。常見(jiàn)的是pydantic和fastapi版本不兼容vLLM 0.43 要求pydantic2.0如果環(huán)境里有舊版本先卸載。DeepSeek 模型文件提前下載好上傳到服務(wù)器14B 的 half 精度模型大約 28G上傳前確認(rèn)磁盤(pán)空間足夠。啟動(dòng)命令python -m vllm.entrypoints.openai.api_server \ --model /root/work/ds/pretrained \ --dtype half \ --trust-remote-code \ --tensor-parallel-size 1 \ --max-model-len 5120 \ --enforce-eager \ --gpu-memory-utilization 0.95 \ --max-num-batched-tokens 5120 \ --max-num-seqs 5 \ --host 0.0.0.0 \ --served-model-name DeepSeek-R1-14B \ --port 8008 逐項(xiàng)說(shuō)明關(guān)鍵參數(shù)--dtype half用 FP16 精度加載顯存占用減半V100 對(duì) FP16 有硬件加速。--tensor-parallel-size 1單卡推理如果是多卡就改成卡數(shù)。--max-model-len 5120最大上下文長(zhǎng)度設(shè)太大 KV Cache 會(huì)吃掉大量顯存。--enforce-eager禁用 CUDA Graph犧牲一點(diǎn)性能換穩(wěn)定性V100 上建議開(kāi)啟。--gpu-memory-utilization 0.95顯存利用率上限留 5% 給系統(tǒng)。--max-num-seqs 5最大并發(fā)序列數(shù)根據(jù)實(shí)際并發(fā)調(diào)整設(shè)太高會(huì) OOM。--served-model-name DeepSeek-R1-14BAPI 調(diào)用時(shí)的模型名稱(chēng)Dify 里填這個(gè)。啟動(dòng)后看到Uvicorn running on http://0.0.0.0:8008就說(shuō)明服務(wù)起來(lái)了。用 curl 測(cè)一下curl http://localhost:8008/v1/models返回模型列表里有DeepSeek-R1-14B就正常。4.3 Dify 側(cè)對(duì)接與鏈路驗(yàn)證Dify 用 Docker 部署在 ECS-1 上安裝流程參考官方文檔。部署完成后進(jìn)入設(shè)置頁(yè)面在模型供應(yīng)商里添加 OpenAI-API-compatible 類(lèi)型Embedding 模型API Base 填http://ECS-2內(nèi)網(wǎng)IP:9997/v1模型名custom-bge-large-zh-v1.5Rerank 模型API Base 同上模型名custom-bge-reranker-largeLLM 模型API Base 填http://ECS-3內(nèi)網(wǎng)IP:8008/v1模型名DeepSeek-R1-14B配置完成后創(chuàng)建一個(gè)知識(shí)庫(kù)上傳一個(gè)測(cè)試文檔用默認(rèn)分段策略。然后在應(yīng)用編排里把檢索策略設(shè)為混合檢索加 Rerank生成模型選 DeepSeek。問(wèn)一個(gè)文檔里有的問(wèn)題如果回答準(zhǔn)確且引用了原文說(shuō)明整條鏈路通了。5. 避坑與排查三臺(tái)機(jī)器聯(lián)調(diào)時(shí)最容易翻車(chē)的幾個(gè)點(diǎn)5.1 Xinference 注冊(cè)模型后啟動(dòng)報(bào) “model not found”現(xiàn)象是xinference launch時(shí)提示模型不存在但registrations列表里明明有。原因通常是注冊(cè)時(shí)--persist沒(méi)加或者XINFERENCE_HOME在注冊(cè)和啟動(dòng)時(shí)指向了不同路徑。解決方法是先確認(rèn)echo $XINFERENCE_HOME輸出一致然后重新注冊(cè)并加上--persist。5.2 vLLM 啟動(dòng)時(shí) CUDA out of memoryV100 32G 跑 14B half 模型權(quán)重占約 28G如果--gpu-memory-utilization設(shè)成 0.95留給 KV Cache 的空間只有 1.6G 左右。--max-model-len 5120和--max-num-seqs 5的組合下KV Cache 需求可能超過(guò)這個(gè)值。解決辦法是降低max-model-len到 4096或者把max-num-seqs降到 3。如果還是不夠檢查是不是有其他進(jìn)程占著顯卡nvidia-smi看一下。5.3 Dify 調(diào)用 Embedding 接口超時(shí)Dify 默認(rèn)的模型請(qǐng)求超時(shí)是 60 秒如果 ECS-2 和 ECS-1 之間網(wǎng)絡(luò)延遲高或者 Embedding 模型首次加載慢就會(huì)超時(shí)。在 Dify 的模型配置里把超時(shí)時(shí)間調(diào)到 120 秒。另外確認(rèn) ECS-2 的安全組開(kāi)放了 9997 端口只允許 ECS-1 的內(nèi)網(wǎng) IP 訪問(wèn)。5.4 Rerank 模型返回分?jǐn)?shù)全部接近檢索回來(lái)的文檔經(jīng)過(guò) Rerank 后分?jǐn)?shù)都在 0.5 左右區(qū)分度很低。這通常是因?yàn)閎ge-reranker-large對(duì)輸入文本的長(zhǎng)度敏感如果知識(shí)庫(kù)分段太長(zhǎng)超過(guò)了模型的最佳處理長(zhǎng)度分?jǐn)?shù)就會(huì)趨同。把 Dify 里的分段長(zhǎng)度從默認(rèn)的 500 調(diào)到 300 左右重疊 50重新索引后再試。5.5 vLLM 服務(wù)啟動(dòng)后 Dify 調(diào)用返回 404Dify 里配置的模型名和 vLLM 啟動(dòng)時(shí)的--served-model-name不一致會(huì)導(dǎo)致 404。檢查 Dify 模型配置里的模型名稱(chēng)是否嚴(yán)格等于DeepSeek-R1-14B大小寫(xiě)和連字符都不能差。另外確認(rèn) API Base 填的是http://IP:8008/v1末尾的/v1不能少。6. 二次開(kāi)發(fā)與調(diào)優(yōu)從跑通到跑好的幾個(gè)改造方向鏈路跑通只是第一步真正用到生產(chǎn)環(huán)境還要做幾件事。第一是 Embedding 和 Rerank 的批處理優(yōu)化。Xinference 默認(rèn)單條推理如果知識(shí)庫(kù)文檔量大索引速度會(huì)很慢。可以在 Dify 的知識(shí)庫(kù)設(shè)置里把批處理大小調(diào)大同時(shí)確認(rèn) Xinference 那邊的--batch-size參數(shù)如果有也相應(yīng)調(diào)整。我一般會(huì)先用 100 篇文檔測(cè)一下索引耗時(shí)再?zèng)Q定批大小。第二是 vLLM 的并發(fā)調(diào)優(yōu)。--max-num-seqs設(shè)成 5 是保守值實(shí)際能跑多少取決于請(qǐng)求的平均生成長(zhǎng)度。如果用戶(hù)問(wèn)題短、回答也短可以逐步往上調(diào)每次加 2觀察nvidia-smi的顯存占用和 vLLM 日志里的吞吐數(shù)據(jù)。調(diào)到顯存占用穩(wěn)定在 90% 左右就差不多了。第三是 Rerank 的 top-k 策略。Dify 默認(rèn)檢索 top-10 然后 Rerank 取 top-3如果發(fā)現(xiàn)回答經(jīng)常漏掉關(guān)鍵信息可以把 Rerank 后的 top-k 調(diào)到 5。但注意上下文長(zhǎng)度限制top-k 越大塞進(jìn) DeepSeek 的 token 越多超過(guò)max-model-len就會(huì)被截?cái)唷5谒氖羌右粚泳彺?。Embedding 和 Rerank 的結(jié)果對(duì)相同輸入是確定的可以在 Dify 前面加一個(gè) Redis 緩存把 query 的 embedding 向量和 rerank 分?jǐn)?shù)緩存起來(lái)重復(fù)問(wèn)題直接命中緩存減少 GPU 壓力。驗(yàn)證改造效果的方法很簡(jiǎn)單準(zhǔn)備 20 個(gè)測(cè)試問(wèn)題覆蓋知識(shí)庫(kù)里不同文檔的內(nèi)容記錄每個(gè)問(wèn)題的回答準(zhǔn)確率和響應(yīng)時(shí)間。改一個(gè)參數(shù)跑一遍對(duì)比數(shù)據(jù)。不要憑感覺(jué)調(diào)參血淚經(jīng)驗(yàn)是感覺(jué)往往不準(zhǔn)。從那以后我每次部署新環(huán)境都會(huì)先用一個(gè)最小知識(shí)庫(kù)跑通全鏈路再逐步加文檔、調(diào)參數(shù)。先保證鏈路通再談優(yōu)化這個(gè)順序不能反。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取