☰
DeepSeek RAG三机环境搭建与vLLM避坑
2026/10/28 12:43:04 网站建设 项目流程

简介:围绕DeepSeek搭建RAG系统的环境部署实战教程,面向已具备Linux与深度学习基础、希望跑通私有化检索增强链路的开发者与运维人员。文档从技术栈概览切入,依次给出Dify平台服务器、Rerank与Embedding模型服务器、DeepSeek模型服务器的分机部署方案,并覆盖CUDA驱动、Docker、vLLM、Xinference等工具的安装配置,以及bge-reranker-large、bge-large-zh-v1.5等模型在中文检索场景中的落地细节,同时说明三台ECS实例的分工与Tesla T4、CUDA 11.4、Python 3.8等版本选定。资料包为单个docx文档,约580KB,按技术栈概要与安装部署两大章节编排,目录层级清晰,便于按服务器角色定位对应步骤。目前已有330人学习,读者可从中获得环境规划与版本选型思路、镜像与依赖安装清单、模型加载与接口调用的验证方法,也可作为部署排错时的对照手册。

1. 别在一台机器上硬塞:DeepSeek RAG 环境搭建先拆三台主机

把基于 DeepSeek 搭建 RAG 系统的环境搭建实战教程翻到最后,真正耗时间的不是写提示词,而是把 Dify、向量模型、重排模型和 vLLM 推理服务塞进三台主机的资源边界里。很多人以为 RAG 就是一个 Docker Compose 起几个容器,实际翻车点集中在 CUDA 版本、显存余量和模型服务端口这三件事上。这份资源把环境拆成 Dify 平台、Embedding/Rerank 模型服务、DeepSeek 推理服务三层,适合已经能登录 Linux 主机、准备把知识库问答跑起来的一线开发者。它解决的是“模型能下载但服务串不起来”的问题,不是讲 RAG 原理的科普材料。

2. 资源与端口先定死:Dify、Embedding/Rerank、DeepSeek 推理的三机分工

2.1 为什么 Dify 不抢 GPU:平台层和模型层分开的选型理由

Dify 在这套环境里承担的是应用编排、知识库管理和对话入口,它自己不需要吃 GPU。常见做法是把 Dify 放在 ECS-1 上,用 Docker 起平台服务,显卡没有硬性要求;ECS-2 专门跑 Xinference,承载 bge-reranker-large 和 bge-large-zh-v1.5;ECS-3 用 vLLM 跑 DeepSeek-R1-Distill-Qwen-14B。这个拆法的好处是故障边界清楚:Dify 挂了不影响模型服务,rerank 超时也不会把 vLLM 拖死。

我一般不建议把 Dify 和 vLLM 塞同一台机器。Dify 的容器、数据库、后台任务会抢内存,vLLM 又对显存连续性敏感,二者混部后一旦触发 OOM,日志里很难看出是谁先动的手。三台主机的代价是网络配置多一点,但换来的是可以单独重启、单独回滚、单独压测。对 RAG 这种“检索链路长、任一环节都可能超时”的系统,这个边界比省一台机器值钱。

资源教程里 ECS-1 的系统是 CentOS 7.5 64bit,ECS-2 是 Ubuntu 20.04 server 64bit,带 GPU 驱动 470.223.02 和 CUDA 11.4,显卡是 1 张 T4 16GB;ECS-3 是 CentOS 7.9 64bit、CUDA 11.4、Python 3.8 的底子,但实际部署 vLLM 时选的是 CUDA 12.1、Python 3.10、vLLM 0.4.3,显卡是 1 张 V100 32GB。这里有一个容易忽略的点:ECS-2 的 CUDA 11.4 是镜像自带,Xinference 跑 embedding/rerank 够用;ECS-3 要跑 vLLM 和 14B 模型,驱动和 CUDA 必须重新对齐到 12.1,不能直接沿用镜像里的 11.4。

2.2 版本矩阵:系统、Python、CUDA、显存和模型精度的对应关系

先把版本矩阵写进部署记录,不要等报错再猜。下面这张表是按教程里的实际选型整理的,拿到资源后先对照自己的机器改,尤其是显卡显存和模型精度两列。

主机角色系统底子PythonCUDA/驱动显卡与显存关键模型
ECS-1Dify 平台CentOS 7.5 64bit按容器镜像无 GPU 要求无硬性要求Dify 容器
ECS-2Embedding/RerankUbuntu 20.043.8CUDA 11.4 / 驱动 470.223.02T4 16GBbge-reranker-large、bge-large-zh-v1.5
ECS-3DeepSeek 推理CentOS 7.9 64bit3.10CUDA 12.1 / 驱动 530.30.02V100 32GBDeepSeek-R1-Distill-Qwen-14B

这张表里最紧的是 ECS-3。14B 模型用 half 精度加载,权重本身就要占接近 28GB 显存,V100 32GB 只剩几个 GB 给 KV Cache 和框架开销。教程里把--max-model-len设成 5120、--gpu-memory-utilization设成 0.95、--max-num-seqs设成 5,本质是在小余量里保启动。T4 16GB 跑 14B half 是跑不动的,除非换量化模型,但教程没有走量化路线,这一点要先认清,别在 ECS-2 上试 14B。

2.3 端口与回调地址:9997、8008 和 Dify 访问路径怎么留

Xinference 的端口在教程里固定为 9997,并且特别标注“端口号不可变”。这不是玄学,是因为 Dify 里配置的模型服务地址一旦写死,后面改端口要同时改 Dify 的模型供应商配置、知识库索引配置和可能存在的反向代理。vLLM 的 OpenAI 兼容接口端口设成 8008,--served-model-name设成 DeepSeek-R1-14B,Dify 侧填模型名时要对上这个别名,不是对目录名。

我一般会把三台主机的端口先画成一张小表:ECS-1 只开放 Dify 的 Web 端口和容器间通信;ECS-2 对内开放 9997;ECS-3 对内开放 8008。安全组不要图省事全开,RAG 环境里模型服务通常不需要公网入口。Dify 调模型服务时走内网地址,如果三台机器跨网段,先确认安全组和路由,再去看服务日志,否则很容易把网络不通误判成模型加载失败。

2.4 动手前的三条基线检查:磁盘、GPU、端口占用

在装任何东西之前,先在三台机器上各跑一遍基线检查。下面这段命令不复杂,但能省掉后面很多“黑匣子”式排错。

# 查看系统版本和内核,确认和教程底子是否一致 cat /etc/os-release uname -r # 查看磁盘,模型文件动辄十几 GB,/root 或 /data 要有足够空间 df -h # 有 GPU 的机器看驱动和显存;没有 GPU 的机器这条会报 command not found,正常 nvidia-smi # 看 9997、8008 是否已被占用,避免起服务时端口冲突 ss -lntp | grep -E '9997|8008'

这几条命令的逻辑很简单:系统版本决定驱动和 CUDA 的安装方式,磁盘空间决定模型文件能不能落地,nvidia-smi里的 Driver Version 和 CUDA Version 决定后面装哪个版本的 PyTorch 和 vLLM,端口占用决定服务能不能按教程的固定端口启动。参数上重点看df -h的可用空间,14B 模型原始文件加上转换缓存,建议至少留 60GB 以上;nvidia-smi右上角的 CUDA Version 是驱动支持的最高版本,不是当前安装的 CUDA Toolkit 版本,别把这两个混了。

3. ECS-2 上的 Xinference:rerank 与 embedding 自定义模型注册全流程

3.1 安装 Xinference 并固定模型目录

ECS-2 上先装 Xinference。教程给的命令是pip install "xinference[all]",这个写法会把 Web UI、所有后端依赖一起装,体积不小,但省得后面缺组件。Python 用镜像自带的 3.8 即可,和 CUDA 11.4 对得上。安装完成后不要急着启动,先把XINFERENCE_HOME指到一个持久目录。教程里写的是/tmp/xinference,这个目录重启即丢,模型注册信息也跟着没,属于典型的“当时能跑,过两天服务没了”的坑。

# 安装 Xinference 全量依赖,Python 3.8 环境 pip install "xinference[all]" # 建持久化目录,别用 /tmp;下面以 /data/xinference 为例 mkdir -p /data/xinference export XINFERENCE_HOME=/data/xinference # 把环境变量写进 shell 配置,避免每次登录都要手动 export echo 'export XINFERENCE_HOME=/data/xinference' >> ~/.bashrc source ~/.bashrc # 检查命令是否可用 xinference --help

这段里pip install "xinference[all]"的[all]是 extras,装全量后端;XINFERENCE_HOME是 Xinference 存模型注册信息和缓存的根目录,必须可写且持久;xinference --help只验证命令入口,不验证模型能不能跑。参数上如果磁盘紧张,可以把[all]换成按需后端,但教程场景下直接全量更稳,避免后面注册 rerank 时缺依赖。

启动方式分前台和后台。前台适合第一次调试,能看到注册和加载日志;后台用 nohup 托管,适合长期跑。教程要求端口 9997 不变,下面两条命令二选一。

# 前台启动,调试时用;Ctrl+C 会停服务 xinference-local --host 0.0.0.0 --port 9997 # 后台启动,日志写到 nohup.out;正式跑用这条 nohup xinference-local --host 0.0.0.0 --port 9997 &> nohup.out &

--host 0.0.0.0是为了让 ECS-1 上的 Dify 能通过内网访问,不是让公网随便调;--port 9997是教程固定端口,后面 Dify 的模型服务地址要按这个填。后台启动后不要只看命令有没有返回,要tail -f nohup.out看到服务监听成功,再用ss -lntp | grep 9997确认端口真的起来了。我见过有人 nohup 启动了但进程秒退,日志里是端口占用或目录权限,结果 Dify 那边一直报连接超时。

3.2 注册 bge-reranker-large:config.json 与 register 命令

rerank 模型的作用是对检索结果做二次排序。RAG 里先用 embedding 召回一批文档,再用 rerank 把真正相关的往前排,Top K 给生成模型时质量会稳很多。教程选的是 bge-reranker-large,模型文件先从模型仓库下载到本地,再上传到 ECS-2。下载和安装 Xinference 可以并行做,但注册必须在模型文件落地之后。

先写自定义模型配置。下面这份 JSON 是教程给出的结构,model_name是你在 Xinference 里用的自定义名,model_id填模型标识,model_uri指向本地目录。不同模型仓库的目录名可能带前缀,实际填的时候以你下载下来的文件夹为准,下面用简称示意。

{ "model_name": "custom-bge-reranker-large", "type": "normal", "language": ["en", "zh"], "model_id": "bge-reranker-large", "model_uri": "file:///data/models/bge-reranker-large" }

model_name建议带custom-前缀,避免和 Xinference 内置模型名冲突;type用normal表示普通模型;language写中英文;model_id是模型身份标识,注册和启动时用得到;model_uri必须是file://加绝对路径,路径写错时注册可能成功,但 launch 会报找不到模型文件。把这个文件保存成rerank-model.json,然后执行注册。

# 将自定义 rerank 模型注册到 Xinference,--persist 表示持久化 xinference register --model-type rerank --file rerank-model.json --persist # 检查 rerank 注册列表里有没有 custom-bge-reranker-large xinference registrations --model-type rerank # 启动自定义 rerank 模型 xinference launch --model-name custom-bge-reranker-large --model-type rerank

--model-type rerank告诉 Xinference 这是重排模型,不能写成 embedding;--file指向刚才的 JSON;--persist让注册信息写进XINFERENCE_HOME,不持久化的话重启就丢。xinference launch启动后会给一个 model UID,日志里能看到加载进度。参数上重点检查model_uri权限,运行 Xinference 的用户必须能读模型目录,否则 launch 阶段才会暴露,注册阶段看不出来。

3.3 注册 bge-large-zh-v1.5:维度、最大 token 与启动验证

embedding 模型负责把知识库文本转成向量。教程选的是 bge-large-zh-v1.5,配置里有两个参数必须和模型对上:dimensions是 768,max_tokens是 512。这两个值不是随手填的,维度错了会导致相似度计算全乱,最大 token 错了会在长文本切分时截断异常。

{ "model_name": "custom-bge-large-zh-v1.5", "dimensions": 768, "max_tokens": 512, "language": ["zh"], "model_id": "bge-large-zh-v1.5", "model_uri": "file:///data/models/bge-large-zh-v1.5" }

dimensions对应模型输出向量维度,bge-large-zh-v1.5 是 768;max_tokens是单次输入的最大 token 数,知识库分段大小要跟它对齐,Dify 里分段长度设得比 512 大很多时,超出部分会被截断,检索召回会莫名其妙变差;language写zh是因为这个模型主要面向中文。保存成embedding-model.json后注册。

# 注册自定义 embedding 模型,注意 --model-type embedding 后面要有空格 xinference register --model-type embedding --file embedding-model.json --persist # 检查 embedding 注册列表 xinference registrations --model-type embedding # 启动自定义 embedding 模型 xinference launch --model-name custom-bge-large-zh-v1.5 --model-type embedding

输入正文里有一条命令写成--model-type embedding--file,中间少了空格,直接抄会报参数错误。--persist同样不能省。启动后如果日志里出现显存不足,先看是不是两个模型同时加载把 T4 16GB 吃满了。常见做法是 rerank 和 embedding 都常驻,但如果显存紧张,可以按需启动,Dify 侧配置好地址后不要频繁重启。

3.4 用 OpenAI 兼容接口做一次 embedding 和 rerank 验证

服务起来后不要直接去 Dify 里点测试,先在 ECS-2 本机用 curl 打一次接口。这样能把“模型服务问题”和“Dify 配置问题”分开。Xinference 提供 OpenAI 兼容接口,embedding 走/v1/embeddings,rerank 走/v1/rerank,模型名用你注册时的model_name。

# 验证 embedding 接口,返回向量维度应该是 768 curl http://127.0.0.1:9997/v1/embeddings \ -H "Content-Type: application/json" \ -d '{"model":"custom-bge-large-zh-v1.5","input":["RAG 系统环境搭建"]}' # 验证 rerank 接口,看返回分数是否正常 curl http://127.0.0.1:9997/v1/rerank \ -H "Content-Type: application/json" \ -d '{"model":"custom-bge-reranker-large","query":"RAG 环境怎么搭","documents":["vLLM 启动参数","今天天气不错"]}'

embedding 请求里input可以是字符串数组,返回的data[0].embedding长度应为 768;如果长度不对,先查dimensions配置。rerank 请求里query是用户问题,documents是候选文档,返回分数应该能把相关文档排前面。参数上注意Content-Type必须是application/json,模型名必须和注册名完全一致。本机 curl 通了再去 Dify 配,能少绕很多弯路。

3.5 注销与回滚:模型服务要能干净下线

自定义模型注册多了以后,xinference registrations列表会越来越长,启动时也可能因为重名或旧配置干扰。教程给了注销命令,这个要留着当后悔药。回滚顺序是先停模型、再注销注册,不要反过来。

# 注销自定义 rerank 模型 xinference unregister --model-type rerank --model-name custom-bge-reranker-large # 注销自定义 embedding 模型 xinference unregister --model-type embedding --model-name custom-bge-large-zh-v1.5

--model-name用的是注册时的model_name,不是model_id。如果 launch 已经起了实例,先通过 Xinference 的管理接口或重启服务释放显存,再注销。参数上--persist注册的模型需要显式注销,不然会一直留在注册表里。我一般会在部署记录里写清楚“注册名、模型目录、端口、启动命令”四项,后面换模型时按这四项回滚,不靠记忆。

4. ECS-3 上的 vLLM:DeepSeek-R1-Distill-Qwen-14B 的驱动、CUDA 与启动参数

4.1 驱动和 CUDA 对齐:先看 nvidia-smi 再装 530.30.02

ECS-3 的镜像底子是 CentOS 7.9、CUDA 11.4、Python 3.8,但 vLLM 这条线要 CUDA 12.1。教程的做法是先装 GPU 驱动 530.30.02,这个版本对应 CUDA 12.1,然后再单独装 CUDA Toolkit。安装驱动时不要勾选 CUDA,否则会和后面的 Toolkit 打架。先看当前驱动和 CUDA 支持版本。

# 查看当前驱动版本和驱动支持的最高 CUDA 版本 nvidia-smi # 如果已经装过 CUDA Toolkit,再看当前 Toolkit 版本 nvcc -V

nvidia-smi右上角的 CUDA Version 是驱动能力上限,不是 Toolkit 版本;nvcc -V才是当前编译工具链版本。两者不一致不一定是错,但 vLLM 装 PyTorch 扩展时要看 Toolkit。驱动安装命令按实际包名替换,下面只保留关键参数。

# 安装 GPU 驱动,只装驱动,不装 OpenGL 相关组件 sudo sh ./gpu-driver-530.30.02.run --no-opengl-files # 安装 CUDA Toolkit 12.1,驱动已经单独装过,这里不再重复装驱动 sudo sh cuda_12.1.0_530.30.02_linux.run --toolkit --silent --override

--no-opengl-files避免服务器环境装图形组件;--toolkit只装工具链;--silent --override用于非交互安装。装完后把 CUDA 路径写进环境变量,注意把示例里的12.1换成你实际安装的目录名。

# 编辑当前用户环境变量 vim ~/.bashrc # 在文件末尾加入下面两行,路径按实际 CUDA 安装目录调整 export PATH=/usr/local/cuda-12.1/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH # 刷新环境变量并验证 source ~/.bashrc nvcc -V nvidia-smi

PATH让nvcc能找到;LD_LIBRARY_PATH让运行时能找到 CUDA 动态库;source只对当前 shell 生效,新开终端会重新读~/.bashrc。验证时nvcc -V显示 12.1,nvidia-smi的 Driver Version 显示 530.30.02,两个都对上再往下走。如果nvcc -V还是旧版本,先which nvcc看路径是不是被旧环境变量抢了。

4.2 Python 3.10 与 PyTorch 2.3.0:把 vLLM 的依赖锁在虚拟环境里

ECS-3 系统 Python 是 3.8,vLLM 这条线要 3.10。用 conda 建独立环境,避免污染系统 Python。PyTorch 要装和 CUDA 12.1 匹配的版本,教程给的是 2.3.0、torchvision 0.18.0、torchaudio 2.3.0,索引源指向 cu121。

# 创建 Python 3.10 虚拟环境 conda create -n myenv python=3.10 -y # 激活环境 conda activate myenv # 安装与 CUDA 12.1 匹配的 PyTorch 三件套 pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 \ --index-url https://download.pytorch.org/whl/cu121 # 验证 PyTorch 是否能识别 GPU python -c "import torch; print(torch.__version__); print(torch.cuda.is_available())"

conda create -n myenv里的环境名可以改,但后面所有命令都要跟着改;--index-url指定 cu121 的轮子源,避免 pip 装到 CPU 版本;验证脚本输出True才说明 PyTorch 能拿到 GPU。我一般会把这个验证放在装 vLLM 之前,因为 vLLM 安装失败时,有一部分原因是 PyTorch 版本不对,先固定 torch 能减少变量。参数上不要混用系统 pip 和 conda 环境里的 pip,激活环境后which pip确认一下。

4.3 vLLM 0.4.3 安装与 14B 模型启动命令

vLLM 安装用pip install vllm==0.4.3。教程里写作 0.43,按补丁版本理解就是 0.4.3,如果依赖解析报找不到这个版本,回到教程记录的 0.43 环境里核对,不要临时升到最新版,vLLM 的小版本对启动参数和 CUDA 扩展影响很大。安装过程中可能出现需要指定版本的依赖报错,按报错要求装对应版本即可,不要一口气--upgrade全部包。

# 安装 vLLM,版本按教程锁定 pip install vllm==0.4.3 # 提前把 DeepSeek-R1-Distill-Qwen-14B 模型文件放到本地目录 ls -lh /root/work/ds/pretrained # 启动 OpenAI 兼容 API 服务 nohup 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 &> vllm.log &

这段启动命令的每个参数都影响显存和并发。--model指向模型目录,目录里要有配置文件和权重;--dtype half用半精度加载,14B 在 32GB 显存上必须控制精度;--trust-remote-code允许加载模型自带代码,DeepSeek 系列常见需要;--tensor-parallel-size 1表示单卡,不要写成 2;--max-model-len 5120是保守上下文长度,设太大 KV Cache 会撑爆;--enforce-eager关掉 CUDA 图,省显存但损失一点吞吐;--gpu-memory-utilization 0.95是很激进的显存占用,留的余量很小,如果启动 OOM 可以先降到 0.9;--max-num-batched-tokens 5120和--max-num-seqs 5控制批处理规模,适合调试和小流量;--served-model-name DeepSeek-R1-14B是 Dify 里要填的模型名;--port 8008是推理服务端口。

启动后看vllm.log,不要只看进程在不在。日志里出现Uvicorn running和模型加载完成才算真正起来。如果卡在加载权重,先看磁盘 IO 和模型目录权限;如果卡在 CUDA 初始化,回到驱动和 Toolkit 版本。参数上--gpu-memory-utilization 0.95不是越高越好,V100 32GB 跑 14B half 本来就紧,0.95 在并发上来后容易 OOM,我一般会在压测后把它回调到 0.9 左右,用一点吞吐换稳定。

4.4 接口验证与显存边界:curl 一次,比盯日志十次快

服务起来后先用 curl 验证模型列表和对话接口。vLLM 提供 OpenAI 兼容接口,/v1/models看服务别名,/v1/chat/completions发一条最短请求。

# 看服务是否注册了 DeepSeek-R1-14B curl http://127.0.0.1:8008/v1/models # 发一条最短对话请求,确认生成链路通 curl http://127.0.0.1:8008/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"DeepSeek-R1-14B","messages":[{"role":"user","content":"你好"}],"max_tokens":32,"temperature":0}'

/v1/models返回的id要和--served-model-name对上;对话请求里model填DeepSeek-R1-14B,max_tokens先给 32 避免生成太长,temperature设 0 方便复现。参数上如果返回 404,先查模型名;如果返回 500,看vllm.log里的显存和 CUDA 报错。显存边界可以用nvidia-smi持续观察,启动完成后剩余显存如果低于 1GB,后面 Dify 并发一上来就可能触发 OOM,这时候要么降--gpu-memory-utilization,要么降--max-model-len,不要硬扛。

5. 避坑与排查:RAG 环境搭建里最容易翻车的五个版本错位

5.1 注册成功但 launch 报 model not found

现象是xinference registrations能看到custom-bge-reranker-large,但xinference launch报模型找不到或配置文件读取失败。原因通常有两个:model_uri指向的本地目录不存在,或者XINFERENCE_HOME不是注册时用的那个目录。注册信息写进了 A 目录,启动时环境变量指向 B 目录,注册表看起来是空的。解决顺序是先echo $XINFERENCE_HOME,再ls -l看model_uri路径,最后用xinference registrations确认注册表。修复时把环境变量写进~/.bashrc,重新注册并加--persist,不要靠临时 export 撑。

5.2 vLLM 启动 OOM 或被系统 Killed

现象是启动命令执行后日志停在加载权重,随后进程消失,dmesg里能看到 Killed,或者vllm.log里出现 CUDA out of memory。原因是 14B half 权重接近 28GB,V100 32GB 余量小,--gpu-memory-utilization 0.95又把可用显存压得很满,KV Cache 一申请就爆。解决先把--gpu-memory-utilization降到 0.9,再把--max-model-len从 5120 往下降,--max-num-seqs保持 5 或更低。如果还不行,确认是不是有其他进程占着 GPU,nvidia-smi看进程列表,别在旧 vLLM 没退干净时重复启动。

5.3 Dify 调 9997 连不上或 embedding 超时

现象是 ECS-2 本机 curl 通,Dify 里测试 embedding 报连接超时或 502。原因多半是 Dify 容器访问不到 ECS-2 的内网地址,或者安全组没放行 9997。先在三台机器之间用curl和telnet验证连通性,再查 Xinference 是不是只听在 127.0.0.1。启动命令里的--host 0.0.0.0不能省,否则本机通、跨机不通。解决时把 Dify 的模型服务地址改成 ECS-2 内网 IP,安全组只放行 Dify 所在主机到 9997,不要图省事开公网。

5.4 rerank 分数异常或接口 404

现象是 rerank 接口返回 404,或者返回分数全是 0、排序完全不对。404 通常是模型名没对上,/v1/rerank请求里的model必须和model_name完全一致;分数异常先看请求体里query和documents的字段名有没有写错,再看模型是不是真的加载成功。还有一种情况是把 rerank 模型注册成了 embedding 类型,--model-type写错后启动的服务不提供 rerank 接口。解决时用xinference registrations --model-type rerank确认类型,注销后按正确类型重注册。

5.5 curl 能通但 Dify 调 8008 失败

现象是 ECS-3 本机curl /v1/models正常,Dify 里配 DeepSeek 模型却报 401、404 或超时。401 一般是 Dify 侧填了 API Key 但 vLLM 启动时没配鉴权,或者反过来;404 多半是模型名不是DeepSeek-R1-14B;超时则是网络或端口没放行。解决时先统一模型名,再确认 Dify 的 Base URL 是http://ECS-3内网IP:8008/v1这种带/v1的写法,最后看安全组。这个环节最怕“本机通就等于网络通”的假设,跨主机一定要单独验。

6. 跑通之后先别加知识库:用一条请求链路验证 RAG 环境的稳定性

6.1 端到端验证脚本:embedding、rerank、chat 三段耗时分开记

三台机器都能单独 curl 通之后,我会先做一条最小链路验证,不急着灌知识库。下面这段脚本把 embedding、rerank、chat 三段的耗时分开打出来,哪一段慢一眼就能看出来。

# 记录 embedding 耗时 curl -s -o /tmp/emb.json -w "embedding:%{time_total}\n" \ http://ECS-2_IP:9997/v1/embeddings \ -H "Content-Type: application/json" \ -d '{"model":"custom-bge-large-zh-v1.5","input":["RAG 环境搭建"]}' # 记录 rerank 耗时 curl -s -o /tmp/rerank.json -w "rerank:%{time_total}\n" \ http://ECS-2_IP:9997/v1/rerank \ -H "Content-Type: application/json" \ -d '{"model":"custom-bge-reranker-large","query":"RAG 环境搭建","documents":["vLLM 启动参数","无关文本"]}' # 记录 chat 耗时 curl -s -o /tmp/chat.json -w "chat:%{time_total}\n" \ http://ECS-3_IP:8008/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"DeepSeek-R1-14B","messages":[{"role":"user","content":"用一句话说明 RAG"}],"max_tokens":64,"temperature":0}'

-w "%{time_total}"只输出总耗时,适合快速对比;-o把响应体写到文件,方便后面看维度、分数和生成内容。三段耗时里 embedding 通常最快,rerank 次之,chat 受生成长度影响最大。如果 embedding 超过几百毫秒,先看 T4 是不是被两个模型同时加载拖慢;如果 chat 首 token 很慢,回看 vLLM 的--max-num-seqs和显存余量。

6.2 参数回滚表:哪些值必须写进部署记录

跑通一次不算完,RAG 环境最容易在“改了一个参数忘了改回去”时翻车。我一般把下面几项写进部署记录,后面换模型或压测时按表回滚。

记录项ECS-2 示例ECS-3 示例回滚影响
服务端口99978008改端口要同步改 Dify
模型注册名/别名custom-bge-large-zh-v1.5DeepSeek-R1-14B名字对不上直接 404
显存相关参数模型常驻显存gpu-memory-utilization 0.95调高易 OOM,调低降吞吐
上下文/分段max_tokens 512max-model-len 5120过大撑显存,过小截断

从那以后我每次动 vLLM 的显存参数或 Xinference 的模型目录,都强制先把这张表更新一遍,再重启服务;没有记录的回滚等于赌运气。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询