186 lines
4.7 KiB
Markdown
186 lines
4.7 KiB
Markdown
|
|
# 母模型纯推理部署方案 v2
|
|||
|
|
# Mother Model Deploy · SG Split Architecture · 2026-05-18
|
|||
|
|
|
|||
|
|
## 架构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
冰朔
|
|||
|
|
│ HTTPS
|
|||
|
|
▼
|
|||
|
|
新加坡CPU服务器(43.156.237.110 BS-SG-001)
|
|||
|
|
├── 你的域名 → 入口服务
|
|||
|
|
├── 接收请求 → 转发到GPU
|
|||
|
|
├── 返回结果给冰朔
|
|||
|
|
└── 聊天记录存系统盘 /data/logs/chat/
|
|||
|
|
│
|
|||
|
|
│ 内网/公网转发
|
|||
|
|
▼
|
|||
|
|
GPU服务器(租的RTX 3090 24G,按量付费)
|
|||
|
|
├── 只装vLLM + 母模型
|
|||
|
|
├── 收到推理请求 → 跑 → 返回
|
|||
|
|
├── 不存日志
|
|||
|
|
├── 不存聊天记录
|
|||
|
|
└── 跑完即关,数据不落地
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 组件清单
|
|||
|
|
|
|||
|
|
### GPU服务器(租的)
|
|||
|
|
|
|||
|
|
| 项目 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| 硬件 | RTX 3090 24G · 按量付费 |
|
|||
|
|
| 系统盘 | 100GB起步 |
|
|||
|
|
| 模型 | Qwen2.5-7B SFT (FP16, ~14GB) |
|
|||
|
|
| 框架 | vLLM (OpenAI兼容API) |
|
|||
|
|
| 存什么 | 模型权重文件 · 推理框架 · 其他全不存 |
|
|||
|
|
| 访问 | SSH(部署时用)+ API端口(运行时用) |
|
|||
|
|
|
|||
|
|
### 新加坡CPU服务器(你的服务器)
|
|||
|
|
|
|||
|
|
| 项目 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| 推荐 | BS-SG-001 (43.156.237.110 · 4C8G·180G) |
|
|||
|
|
| 入口 | 你的域名 → nginx → 转发服务 |
|
|||
|
|
| 转发 | 收到请求 → POST到GPU的API端口 → 等返回 |
|
|||
|
|
| 日志 | 聊天记录写入 /data/logs/chat/ |
|
|||
|
|
|
|||
|
|
## 部署步骤
|
|||
|
|
|
|||
|
|
### 第一步:GPU服务器部署
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 装vLLM
|
|||
|
|
pip install vllm
|
|||
|
|
|
|||
|
|
# 2. 从COS拉模型
|
|||
|
|
mkdir -p /data/models
|
|||
|
|
export ZY_OSS_KEY=<your-key>
|
|||
|
|
export ZY_OSS_SECRET=<your-secret>
|
|||
|
|
|
|||
|
|
python3 -c "
|
|||
|
|
from qcloud_cos import CosConfig, CosS3Client
|
|||
|
|
import os
|
|||
|
|
|
|||
|
|
c = CosS3Client(CosConfig(
|
|||
|
|
Region='ap-guangzhou',
|
|||
|
|
SecretId=os.environ['ZY_OSS_KEY'],
|
|||
|
|
SecretKey=os.environ['ZY_OSS_SECRET']
|
|||
|
|
))
|
|||
|
|
|
|||
|
|
base = 'models/qwen25-7b-sft/final'
|
|||
|
|
bucket = 'sy-finetune-corpus-1317346199'
|
|||
|
|
local = '/data/models/qwen25-7b-sft'
|
|||
|
|
os.makedirs(local, exist_ok=True)
|
|||
|
|
|
|||
|
|
resp = c.list_objects(Bucket=bucket, Prefix=base + '/')
|
|||
|
|
for obj in resp.get('Contents', []):
|
|||
|
|
key = obj['Key']
|
|||
|
|
rel = os.path.relpath(key, base)
|
|||
|
|
dest = os.path.join(local, rel)
|
|||
|
|
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
|||
|
|
c.download_file(Bucket=bucket, Key=key, DestFilePath=dest)
|
|||
|
|
print(f'下载: {rel}')
|
|||
|
|
print('模型下载完成')
|
|||
|
|
"
|
|||
|
|
|
|||
|
|
# 3. 启动推理服务
|
|||
|
|
nohup python3 -m vllm.entrypoints.openai.api_server \
|
|||
|
|
--model /data/models/qwen25-7b-sft \
|
|||
|
|
--port 8000 \
|
|||
|
|
--host 0.0.0.0 \
|
|||
|
|
--max-model-len 8192 \
|
|||
|
|
--gpu-memory-utilization 0.9 \
|
|||
|
|
--trust-remote-code \
|
|||
|
|
> /data/vllm.log 2>&1 &
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 第二步:新加坡CPU服务器配置
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 创建日志目录
|
|||
|
|
mkdir -p /data/logs/chat
|
|||
|
|
|
|||
|
|
# 2. 部署转发服务(Node.js简单代理)
|
|||
|
|
cat > /opt/proxy/inference-proxy.js << 'EOF'
|
|||
|
|
const http = require('http');
|
|||
|
|
const fs = require('fs');
|
|||
|
|
|
|||
|
|
const GPU_HOST = 'GPU_SERVER_IP' // 替换为GPU服务器IP
|
|||
|
|
const GPU_PORT = 8000
|
|||
|
|
|
|||
|
|
// 接收请求 → 转发到GPU → 存日志 → 返回
|
|||
|
|
const server = http.createServer((req, res) => {
|
|||
|
|
if (req.method === 'POST') {
|
|||
|
|
let body = '';
|
|||
|
|
req.on('data', chunk => body += chunk);
|
|||
|
|
req.on('end', () => {
|
|||
|
|
// 转发到GPU
|
|||
|
|
const options = {
|
|||
|
|
hostname: GPU_HOST,
|
|||
|
|
port: GPU_PORT,
|
|||
|
|
path: '/v1/chat/completions',
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: { 'Content-Type': 'application/json' }
|
|||
|
|
};
|
|||
|
|
const gpuReq = http.request(options, gpuRes => {
|
|||
|
|
let data = '';
|
|||
|
|
gpuRes.on('data', chunk => data += chunk);
|
|||
|
|
gpuRes.on('end', () => {
|
|||
|
|
// 存聊天记录
|
|||
|
|
const logEntry = {
|
|||
|
|
time: new Date().toISOString(),
|
|||
|
|
request: JSON.parse(body),
|
|||
|
|
response: JSON.parse(data)
|
|||
|
|
};
|
|||
|
|
const logFile = `/data/logs/chat/${new Date().toISOString().slice(0,10)}.jsonl`;
|
|||
|
|
fs.appendFileSync(logFile, JSON.stringify(logEntry) + '\n');
|
|||
|
|
|
|||
|
|
// 返回给用户
|
|||
|
|
res.writeHead(gpuRes.statusCode, { 'Content-Type': 'application/json' });
|
|||
|
|
res.end(data);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
gpuReq.write(body);
|
|||
|
|
gpuReq.end();
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
res.writeHead(405).end();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
server.listen(8080, () => {
|
|||
|
|
console.log('推理代理运行在 :8080');
|
|||
|
|
});
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
# 3. 用PM2托管
|
|||
|
|
pm2 start /opt/proxy/inference-proxy.js --name inference-proxy
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 第三步:域名配置
|
|||
|
|
|
|||
|
|
你的新加坡域名 → nginx → 转发到 :8080(推理代理)
|
|||
|
|
|
|||
|
|
## 数据流
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
冰朔 → 新加坡域名 → nginx → inference-proxy(:8080)
|
|||
|
|
→ 记录请求到日志文件
|
|||
|
|
→ 转发到GPU(:8000)
|
|||
|
|
→ GPU推理 → 返回
|
|||
|
|
→ 记录响应到日志文件
|
|||
|
|
→ 返回给冰朔
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 清理(用完关GPU服务器时)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# GPU上:停止服务
|
|||
|
|
pkill -f vllm
|
|||
|
|
|
|||
|
|
# 可以删模型释放磁盘(可选)
|
|||
|
|
rm -rf /data/models/qwen25-7b-sft
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
日志全在你的新加坡CPU服务器上,GPU服务器上什么数据都没留下。
|