本项目基于 FastAPI + vLLM 构建本地大模型推理服务平台。
项目将 vLLM 提供的 OpenAI-compatible API 进一步封装为统一的后端服务接口,支持普通问答、流式输出、健康检查、基础 metrics、请求日志和响应时间统计。
当前版本主要目标是完成一个可运行、可复现、可扩展的 LLM Serving 项目雏形,为后续并发压测、性能分析、监控接入和工程化部署打基础。
当前版本:v0.1.0
已完成功能:
- vLLM 本地模型服务启动
- FastAPI 后端服务封装
- 普通问答接口
/api/chat - 流式输出接口
/api/chat/stream - 健康检查接口
/api/health - 基础指标接口
/api/metrics - 请求耗时统计
- prompt tokens / completion tokens 统计
- request_id 请求追踪
- 控制台日志与文件日志
- FlashInfer sampler 报错排查记录
- 环境依赖文件保存
当前测试环境:
| 项目 | 配置 |
|---|---|
| 平台 | AutoDL |
| GPU | NVIDIA RTX 4090 24GB |
| 模型 | Qwen/Qwen2.5-0.5B-Instruct |
| 本地模型路径 | /root/autodl-tmp/models/Qwen2.5-0.5B-Instruct |
当前使用的 Conda 环境:
conda activate vllm-demo主要依赖:
- Python
- FastAPI
- Uvicorn
- vLLM
- OpenAI Python SDK
- Pydantic
- Requests
安装依赖:
pip install -r requirements.txt或者使用 Conda 环境文件恢复:
conda env create -f environment.ymlllm-serving-platform/
├── backend/
│ ├── main.py
│ ├── vllm_client.py
│ ├── schemas.py
│ ├── logger.py
│ └── config.py
├── scripts/
│ ├── start_vllm.sh
│ ├── test_api.py
│ └── test_stream.py
├── docs/
│ ├── architecture.md
│ └── api.md
├── logs/
├── requirements.txt
├── environment.yml
└── README.md
后端服务核心代码目录。
| 文件 | 作用 |
|---|---|
main.py |
FastAPI 服务入口,定义 /api/chat、/api/chat/stream、/api/health、/api/metrics |
vllm_client.py |
封装对 vLLM OpenAI-compatible API 的调用 |
schemas.py |
使用 Pydantic 定义请求和响应结构 |
logger.py |
统一日志配置,支持控制台和文件日志 |
config.py |
项目配置中心,管理 vLLM 地址、模型名、默认生成参数等 |
项目启动和测试脚本目录。
| 文件 | 作用 |
|---|---|
start_vllm.sh |
启动 vLLM 模型服务 |
test_api.py |
测试普通问答接口 /api/chat |
test_stream.py |
测试流式输出接口 /api/chat/stream |
项目文档目录。
| 文件 | 作用 |
|---|---|
architecture.md |
系统架构说明 |
api.md |
API 接口说明 |
日志目录。
运行服务后会生成:
logs/server.log
日志中记录:
- request_id
- 请求状态
- prompt 字符数
- prompt tokens
- completion tokens
- 响应耗时
- 错误信息
整体调用链路如下:
Client
|
| HTTP 请求
v
FastAPI Backend
|
| OpenAI-compatible API
v
vLLM Server
|
| GPU 推理
v
Qwen2.5-0.5B-Instruct
FastAPI 和 vLLM 的关系:
- vLLM 负责高性能模型推理。
- FastAPI 负责业务接口封装、参数校验、日志、metrics 和异常处理。
- 用户或业务系统只需要访问 FastAPI 暴露的接口,不需要直接调用 vLLM 原生接口。
vLLM 已经提供了 OpenAI-compatible API,但在实际工程中,业务方通常不直接调用底层推理服务。
增加 FastAPI 封装层后,可以实现:
- 统一 API 格式
- 统一参数校验
- 统一异常处理
- 请求日志记录
- request_id 链路追踪
- 响应时间统计
- 基础 metrics 统计
- 后续方便扩展鉴权、限流、压测和监控
因此,本项目的核心不是简单调用模型,而是完成一个具备基本工程结构的 LLM Serving 后端服务。
进入项目目录:
cd ~/llm-serving-platform启动 vLLM:
bash scripts/start_vllm.sh当前 scripts/start_vllm.sh 内容示例:
#!/bin/bash
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo
export VLLM_USE_FLASHINFER_SAMPLER=0
MODEL_PATH="/root/autodl-tmp/models/Qwen2.5-0.5B-Instruct"
SERVED_MODEL_NAME="Qwen2.5-0.5B-Instruct"
vllm serve $MODEL_PATH \
--served-model-name $SERVED_MODEL_NAME \
--host 0.0.0.0 \
--port 8000 \
--dtype auto \
--max-model-len 2048 \
--gpu-memory-utilization 0.85新开一个终端,执行:
curl http://127.0.0.1:8000/v1/models正常情况下会返回模型列表,例如:
{
"object": "list",
"data": [
{
"id": "Qwen2.5-0.5B-Instruct",
"object": "model",
"owned_by": "vllm",
"root": "/root/autodl-tmp/models/Qwen2.5-0.5B-Instruct"
}
]
}新开一个终端,执行:
cd ~/llm-serving-platform
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo
uvicorn backend.main:app --host 0.0.0.0 --port 8080 --reload启动成功后,FastAPI 服务地址为:
http://127.0.0.1:8080
此时两个服务分别是:
| 服务 | 地址 |
|---|---|
| vLLM | http://127.0.0.1:8000/v1 |
| FastAPI | http://127.0.0.1:8080 |
接口:
POST /api/chat
请求示例:
curl -X POST "http://127.0.0.1:8080/api/chat" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "请用三句话解释什么是 FastAPI"
}
],
"temperature": 0.7,
"max_tokens": 128
}'响应字段示例:
{
"request_id": "xxxx",
"model": "Qwen2.5-0.5B-Instruct",
"content": "FastAPI 是一个用于构建 Web API 的 Python 框架……",
"prompt_tokens": 20,
"completion_tokens": 80,
"total_tokens": 100,
"latency_ms": 1234.56
}接口:
POST /api/chat/stream
请求示例:
curl -X POST "http://127.0.0.1:8080/api/chat/stream" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "请用五句话解释 PagedAttention"
}
],
"temperature": 0.7,
"max_tokens": 256
}'说明:
/api/chat会等待模型完整生成后一次性返回。/api/chat/stream会在模型生成过程中逐 chunk 返回内容。- 流式输出可以降低用户感知等待时间,但不一定缩短总生成时间。
接口:
GET /api/health
请求:
curl http://127.0.0.1:8080/api/health响应示例:
{
"status": "ok",
"fastapi": "ok",
"vllm": "ok",
"vllm_base_url": "http://127.0.0.1:8000/v1",
"model": "Qwen2.5-0.5B-Instruct"
}说明:
fastapi表示后端服务状态。vllm表示 vLLM 推理服务是否可访问。status=ok表示整体服务正常。status=degraded表示 FastAPI 可访问,但 vLLM 可能不可用。
接口:
GET /api/metrics
请求:
curl http://127.0.0.1:8080/api/metrics响应示例:
{
"total_requests": 10,
"success_requests": 9,
"failed_requests": 1,
"failed_rate": 0.1,
"avg_latency_ms": 856.32
}当前 metrics 统计内容:
| 指标 | 含义 |
|---|---|
total_requests |
总请求数 |
success_requests |
成功请求数 |
failed_requests |
失败请求数 |
failed_rate |
请求失败率 |
avg_latency_ms |
平均响应延迟 |
python scripts/test_api.py该脚本会请求:
POST http://127.0.0.1:8080/api/chat
并打印:
- HTTP 状态码
- 客户端总耗时
- JSON 响应内容
python scripts/test_stream.py该脚本会请求:
POST http://127.0.0.1:8080/api/chat/stream
并逐 chunk 打印模型输出,同时统计客户端侧 TTFT 和总耗时。
查看服务日志:
tail -f logs/server.log日志示例:
2026-05-27 15:30:01 | INFO | request_id=xxx | status=success | prompt_chars=20 | prompt_tokens=15 | completion_tokens=80 | latency_ms=1234.56
日志中不建议保存:
- 完整 prompt
- 完整模型回答
- API key
- 用户隐私数据
- 业务敏感信息
当前项目只记录 prompt 长度、token 数、请求状态和耗时,便于后续压测分析。
终端 1:
cd ~/llm-serving-platform
bash scripts/start_vllm.sh验证:
curl http://127.0.0.1:8000/v1/models终端 2:
cd ~/llm-serving-platform
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo
uvicorn backend.main:app --host 0.0.0.0 --port 8080 --reload终端 3:
cd ~/llm-serving-platform
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo
curl http://127.0.0.1:8080/api/health
python scripts/test_api.py
python scripts/test_stream.py
curl http://127.0.0.1:8080/api/metrics问题表现:
scripts/start_vllm.sh: line 6: vllm: command not found
原因:
当前终端没有激活安装 vLLM 的 Conda 环境。
解决方法:
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo
which vllm或者在 scripts/start_vllm.sh 中加入:
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo问题表现:
CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'
解决方法:
source /root/miniconda3/etc/profile.d/conda.sh
conda activate vllm-demo也可以初始化 shell:
conda init bash
source ~/.bashrc问题表现:
nvcc fatal: Unsupported gpu architecture 'compute_89'
RuntimeError: Ninja build failed
原因:
RTX 4090 对应 Ada 架构,FlashInfer 在编译 sampler 时尝试使用 compute_89 / sm_89,但当前容器中的 CUDA Toolkit / nvcc 不支持该架构,导致编译失败。
解决方法:
在 scripts/start_vllm.sh 中禁用 FlashInfer sampler:
export VLLM_USE_FLASHINFER_SAMPLER=0清理缓存后重新启动:
rm -rf ~/.cache/flashinfer
rm -rf ~/.cache/vllm/torch_compile_cache
bash scripts/start_vllm.sh先检查 vLLM 是否正常:
curl http://127.0.0.1:8000/v1/models如果该命令失败,说明问题在 vLLM 服务侧,而不是 FastAPI。
如果 vLLM 正常,再检查 FastAPI 配置:
cat backend/config.py确认:
VLLM_BASE_URL=http://127.0.0.1:8000/v1
MODEL_NAME=Qwen2.5-0.5B-Instruct
问题表现:
Address already in use
查看占用端口的进程:
lsof -i:8000
lsof -i:8080结束进程:
kill -9 <PID>本项目已经实现了一个基础可用的 LLM Serving 后端系统。
当前完整链路:
测试脚本 / curl
↓
FastAPI Backend
↓
vLLM OpenAI-compatible API
↓
Qwen2.5-0.5B-Instruct
↓
返回普通或流式模型输出
已具备:
- 本地模型推理服务
- 后端接口封装
- 普通问答能力
- 流式输出能力
- 服务健康检查
- 基础运行指标
- 请求日志追踪
- 环境可复现能力
后续计划进入压测与监控阶段,主要包括:
- 并发请求压测
- 平均延迟统计
- P95 / P99 延迟统计
- TTFT 测量
- tokens/s 统计
- 不同
max_tokens对响应时间的影响 - 不同并发数对吞吐量的影响
- GPU 显存和利用率监控
- Prometheus / Grafana 监控接入
- Docker 化部署
- API Key 鉴权
- 请求限流
- 多模型切换
后续可新增目录:
benchmark/
├── benchmark_api.py
├── benchmark_stream.py
└── benchmark_report.md