通义千问3-Reranker-0.6B代码实例:Prometheus指标埋点+Grafana看板
本文介绍了如何在星图GPU平台上自动化部署通义千问3-Reranker-0.6B镜像,并为其构建完整的服务监控体系。通过集成Prometheus指标埋点与Grafana可视化看板,该方案能实时监控AI模型服务的性能、资源使用及模型推理质量,为文本重排序等应用场景提供可观测性保障。
通义千问3-Reranker-0.6B代码实例:Prometheus指标埋点+Grafana看板
你是不是也遇到过这样的问题?部署了一个AI模型服务,比如文本重排序模型,用起来感觉不错,但心里总是没底——现在到底有多少人在用?响应速度怎么样?有没有出错?模型推理的准确率如何?
这些问题就像开车没有仪表盘,只能凭感觉。今天我就来分享一个实用的解决方案:给通义千问3-Reranker-0.6B模型服务加上完整的监控系统。通过Prometheus采集指标,用Grafana可视化展示,让你对模型服务的运行状态一目了然。
1. 为什么需要监控AI模型服务?
在介绍具体实现之前,我们先聊聊为什么监控这么重要。
1.1 模型服务的特殊性
AI模型服务跟传统的Web服务不太一样。它有几个特点:
- 资源消耗大:特别是GPU内存和显存,很容易成为瓶颈
- 响应时间波动:不同长度的输入文本,处理时间差异很大
- 准确率需要监控:模型效果不是100%稳定,需要持续关注
- 并发能力有限:GPU的并行处理能力有上限
1.2 监控能帮你解决什么问题?
有了监控系统,你就能:
- 实时了解服务状态:当前有多少请求在处理?响应时间是多少?
- 快速定位问题:服务变慢了?是GPU内存不够还是CPU瓶颈?
- 优化资源配置:根据实际使用情况调整服务器配置
- 评估模型效果:监控重排序的准确率和相关性分数分布
- 制定扩容计划:知道什么时候需要增加服务器
2. 整体架构设计
我们的监控系统采用经典的Prometheus + Grafana组合,下面是整体架构:
用户请求 → Qwen3-Reranker服务 → 指标埋点 → Prometheus采集 → Grafana展示
2.1 技术栈选择
- Prometheus:开源的监控系统,专门用于收集和存储时间序列数据
- Grafana:数据可视化平台,可以创建漂亮的监控仪表板
- Python Prometheus客户端:在模型服务中埋点,暴露指标
2.2 监控指标设计
我们需要监控以下几类指标:
| 指标类别 | 具体指标 | 说明 |
|---|---|---|
| 服务性能 | 请求总数、请求速率、响应时间 | 了解服务负载和性能 |
| 资源使用 | GPU内存使用率、GPU利用率、CPU使用率 | 监控硬件资源瓶颈 |
| 模型质量 | 相关性分数分布、平均分数、高分比例 | 评估模型效果 |
| 错误监控 | 错误请求数、错误率 | 及时发现服务问题 |
3. 代码实现:在Qwen3-Reranker中埋点
现在进入实战部分。我们要在原有的Qwen3-Reranker服务代码中加入Prometheus指标采集。
3.1 安装依赖
首先,在服务环境中安装必要的Python包:
pip install prometheus-client
3.2 创建指标定义文件
创建一个新的Python文件 metrics.py,专门用来定义和初始化所有监控指标:
# metrics.py
from prometheus_client import Counter, Histogram, Gauge, Summary, start_http_server
import time
class RerankerMetrics:
"""Qwen3-Reranker监控指标类"""
def __init__(self):
# 请求相关指标
self.request_total = Counter(
'reranker_requests_total',
'Total number of requests',
['method', 'endpoint']
)
self.request_duration = Histogram(
'reranker_request_duration_seconds',
'Request duration in seconds',
['method', 'endpoint'],
buckets=[0.1, 0.5, 1.0, 2.0, 5.0, 10.0]
)
# 模型推理指标
self.inference_time = Histogram(
'reranker_inference_duration_seconds',
'Model inference duration in seconds',
buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 2.0]
)
self.batch_size = Histogram(
'reranker_batch_size',
'Number of documents per request',
buckets=[1, 5, 10, 20, 50, 100]
)
# 相关性分数指标
self.score_distribution = Histogram(
'reranker_score_distribution',
'Distribution of relevance scores',
buckets=[0.1, 0.3, 0.5, 0.7, 0.9, 1.0]
)
self.high_score_count = Counter(
'reranker_high_scores_total',
'Number of high relevance scores (>=0.8)'
)
# 资源使用指标
self.gpu_memory_usage = Gauge(
'reranker_gpu_memory_usage_bytes',
'GPU memory usage in bytes'
)
self.gpu_utilization = Gauge(
'reranker_gpu_utilization_percent',
'GPU utilization percentage'
)
# 错误指标
self.error_total = Counter(
'reranker_errors_total',
'Total number of errors',
['error_type']
)
# 启动Prometheus HTTP服务器
start_http_server(8000)
print("Prometheus metrics server started on port 8000")
def record_request(self, method, endpoint, duration):
"""记录请求信息"""
self.request_total.labels(method=method, endpoint=endpoint).inc()
self.request_duration.labels(method=method, endpoint=endpoint).observe(duration)
def record_inference(self, duration, batch_size):
"""记录推理信息"""
self.inference_time.observe(duration)
self.batch_size.observe(batch_size)
def record_score(self, score):
"""记录相关性分数"""
self.score_distribution.observe(score)
if score >= 0.8:
self.high_score_count.inc()
def record_error(self, error_type):
"""记录错误信息"""
self.error_total.labels(error_type=error_type).inc()
def update_gpu_metrics(self, memory_used, memory_total, utilization):
"""更新GPU指标"""
self.gpu_memory_usage.set(memory_used)
if memory_total > 0:
memory_percent = (memory_used / memory_total) * 100
# 这里可以添加内存使用率指标
self.gpu_utilization.set(utilization)
# 创建全局指标实例
metrics = RerankerMetrics()
3.3 修改主服务代码
接下来,修改原有的Qwen3-Reranker服务代码,加入指标采集。这里以Gradio Web界面为例:
# app_with_metrics.py
import gradio as gr
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
import time
from metrics import metrics
import psutil
import pynvml # 用于获取GPU信息
# 初始化GPU监控
try:
pynvml.nvmlInit()
has_gpu = True
except:
has_gpu = False
print("GPU monitoring not available")
class Qwen3RerankerWithMetrics:
"""带监控的Qwen3-Reranker服务"""
def __init__(self, model_path):
print("Loading model...")
start_time = time.time()
# 加载tokenizer和模型
self.tokenizer = AutoTokenizer.from_pretrained(
model_path,
padding_side='left',
trust_remote_code=True
)
self.model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
).eval()
load_time = time.time() - start_time
print(f"Model loaded in {load_time:.2f} seconds")
# 记录模型加载时间
metrics.model_load_time = Gauge(
'reranker_model_load_time_seconds',
'Model loading time in seconds'
)
metrics.model_load_time.set(load_time)
def get_gpu_info(self):
"""获取GPU信息"""
if not has_gpu:
return 0, 0, 0
try:
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
memory_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
utilization = pynvml.nvmlDeviceGetUtilizationRates(handle)
return memory_info.used, memory_info.total, utilization.gpu
except:
return 0, 0, 0
def rerank(self, query, documents, instruction=None):
"""重排序主函数,带监控"""
request_start = time.time()
try:
# 更新GPU指标
gpu_used, gpu_total, gpu_util = self.get_gpu_info()
metrics.update_gpu_metrics(gpu_used, gpu_total, gpu_util)
# 解析输入
docs = [d.strip() for d in documents.strip().split('\n') if d.strip()]
if not docs:
return "请输入至少一个文档"
batch_size = len(docs)
# 构建指令
if not instruction:
instruction = "Given a query, retrieve relevant passages"
# 为每个文档计算分数
results = []
inference_total_time = 0
for doc in docs:
# 构建输入文本
text = f"<Instruct>: {instruction}\n<Query>: {query}\n<Document>: {doc}"
# 推理
inference_start = time.time()
inputs = self.tokenizer(text, return_tensors="pt").to(self.model.device)
with torch.no_grad():
logits = self.model(**inputs).logits[:, -1, :]
# 获取yes/no的logits
no_id = self.tokenizer.convert_tokens_to_ids("no")
yes_id = self.tokenizer.convert_tokens_to_ids("yes")
if no_id is not None and yes_id is not None:
score = torch.softmax(
logits[:, [no_id, yes_id]],
dim=1
)[:, 1].item()
else:
# 备用方案:使用其他方式计算分数
score = 0.5
inference_time = time.time() - inference_start
inference_total_time += inference_time
# 记录推理指标
metrics.record_inference(inference_time, 1)
metrics.record_score(score)
results.append({
'document': doc,
'score': score,
'inference_time': inference_time
})
# 按分数排序
sorted_results = sorted(results, key=lambda x: x['score'], reverse=True)
# 构建输出
output = "排序结果(按相关性从高到低):\n\n"
for i, result in enumerate(sorted_results, 1):
output += f"{i}. 分数: {result['score']:.4f}\n"
output += f" 文档: {result['document'][:100]}...\n"
output += f" 推理时间: {result['inference_time']:.3f}秒\n\n"
# 记录请求指标
request_duration = time.time() - request_start
metrics.record_request('POST', '/rerank', request_duration)
metrics.record_inference(inference_total_time, batch_size)
# 添加统计信息
avg_score = sum(r['score'] for r in results) / len(results)
output += f"\n统计信息:\n"
output += f"- 平均相关性分数: {avg_score:.4f}\n"
output += f"- 总推理时间: {inference_total_time:.3f}秒\n"
output += f"- 平均每文档: {inference_total_time/len(results):.3f}秒\n"
output += f"- 请求总耗时: {request_duration:.3f}秒"
return output
except Exception as e:
# 记录错误
error_type = type(e).__name__
metrics.record_error(error_type)
return f"处理出错: {str(e)}"
def create_web_interface():
"""创建Gradio Web界面"""
# 初始化模型
MODEL_PATH = "/opt/qwen3-reranker/model/Qwen3-Reranker-0.6B"
reranker = Qwen3RerankerWithMetrics(MODEL_PATH)
# 定义界面
with gr.Blocks(title="Qwen3-Reranker with Monitoring") as demo:
gr.Markdown("# 🎯 Qwen3-Reranker 文本重排序服务")
gr.Markdown("### 带Prometheus监控的增强版本")
with gr.Row():
with gr.Column(scale=2):
query = gr.Textbox(
label="查询语句",
placeholder="请输入您要查询的问题或关键词...",
lines=2
)
documents = gr.Textbox(
label="候选文档(每行一个)",
placeholder="请输入候选文档,每行一个...",
lines=10
)
instruction = gr.Textbox(
label="自定义指令(可选)",
placeholder="例如:Given a query, retrieve relevant passages",
value="Given a query, retrieve relevant passages"
)
submit_btn = gr.Button("开始排序", variant="primary")
with gr.Column(scale=3):
output = gr.Textbox(
label="排序结果",
lines=20,
interactive=False
)
# 监控信息展示
with gr.Accordion("📊 实时监控信息", open=False):
with gr.Row():
metrics_url = gr.Markdown(
f"### Prometheus指标地址: http://localhost:8000/metrics"
)
with gr.Row():
gr.Markdown("""
**监控指标说明:**
- `reranker_requests_total`: 总请求数
- `reranker_request_duration_seconds`: 请求耗时分布
- `reranker_inference_duration_seconds`: 模型推理耗时
- `reranker_score_distribution`: 相关性分数分布
- `reranker_errors_total`: 错误统计
""")
# 示例
with gr.Accordion("📝 示例", open=False):
gr.Examples(
examples=[
[
"什么是机器学习?",
"机器学习是人工智能的一个分支\n深度学习是机器学习的一种方法\n统计学是数据分析的基础",
"Given a query, retrieve relevant passages"
],
[
"如何学习Python编程?",
"Python是一种高级编程语言\n建议从基础语法开始学习\n多写代码实践很重要",
"Given a query, retrieve relevant passages"
]
],
inputs=[query, documents, instruction]
)
# 绑定事件
submit_btn.click(
fn=reranker.rerank,
inputs=[query, documents, instruction],
outputs=output
)
return demo
if __name__ == "__main__":
print("启动带监控的Qwen3-Reranker服务...")
print("Prometheus指标地址: http://localhost:8000/metrics")
print("Gradio Web界面地址: http://localhost:7860")
demo = create_web_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
)
3.4 创建Prometheus配置文件
为了让Prometheus能够采集我们的指标,需要创建一个配置文件 prometheus.yml:
# prometheus.yml
global:
scrape_interval: 15s # 每15秒采集一次
evaluation_interval: 15s
scrape_configs:
- job_name: 'qwen3-reranker'
static_configs:
- targets: ['localhost:8000'] # 我们的指标服务地址
metrics_path: '/metrics'
scrape_interval: 10s # 对这个job可以设置更频繁的采集
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100'] # 节点监控
- job_name: 'cadvisor'
static_configs:
- targets: ['localhost:8080'] # 容器监控(如果使用容器)
3.5 创建Docker部署文件
如果你使用Docker部署,可以创建以下Dockerfile和docker-compose文件:
# Dockerfile
FROM pytorch/pytorch:2.1.0-cuda11.8-cudnn8-runtime
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
curl \
wget \
git \
&& rm -rf /var/lib/apt/lists/*
# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 安装Prometheus和Grafana
RUN wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz && \
tar xvfz prometheus-*.tar.gz && \
mv prometheus-2.45.0.linux-amd64 /opt/prometheus && \
rm prometheus-*.tar.gz
RUN wget https://dl.grafana.com/oss/release/grafana-10.0.3.linux-amd64.tar.gz && \
tar -zxvf grafana-10.0.3.linux-amd64.tar.gz && \
mv grafana-10.0.3 /opt/grafana && \
rm grafana-10.0.3.linux-amd64.tar.gz
# 复制代码和配置文件
COPY . .
# 下载模型(如果模型不在镜像中)
# RUN python download_model.py
# 暴露端口
EXPOSE 7860 # Gradio Web界面
EXPOSE 8000 # Prometheus指标
EXPOSE 3000 # Grafana
EXPOSE 9090 # Prometheus UI
# 启动脚本
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]
# docker-compose.yml
version: '3.8'
services:
qwen3-reranker:
build: .
container_name: qwen3-reranker
ports:
- "7860:7860" # Gradio Web界面
- "8000:8000" # Prometheus指标端点
volumes:
- ./models:/app/models
- ./data:/app/data
environment:
- MODEL_PATH=/app/models/Qwen3-Reranker-0.6B
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
command: python app_with_metrics.py
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
# start.sh
#!/bin/bash
# 启动Prometheus指标服务(在后台)
python -c "from metrics import metrics; print('Metrics server ready')" &
# 启动主服务
python app_with_metrics.py
4. 配置Grafana监控看板
现在服务已经可以暴露指标了,接下来我们配置Grafana来可视化这些指标。
4.1 添加Prometheus数据源
- 访问Grafana(通常是 http://localhost:3000)
- 使用默认账号密码登录(admin/admin)
- 进入 Configuration → Data Sources
- 点击 Add data source,选择 Prometheus
- 配置URL为 http://prometheus:9090(如果在同一Docker网络)或 http://localhost:9090
- 点击 Save & Test
4.2 创建监控看板
我们可以创建一个完整的监控看板,包含多个面板。这里提供一个完整的JSON配置,你可以直接导入到Grafana中:
{
"dashboard": {
"title": "Qwen3-Reranker监控看板",
"description": "通义千问3重排序模型服务监控",
"tags": ["qwen3", "reranker", "ai", "monitoring"],
"style": "dark",
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "请求统计",
"type": "stat",
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0},
"targets": [{
"expr": "rate(reranker_requests_total[5m])",
"legendFormat": "请求速率",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "req/s",
"color": {"mode": "thresholds"},
"thresholds": {
"steps": [
{"color": "green", "value": null},
{"color": "red", "value": 80}
]
}
}
}
},
{
"id": 2,
"title": "平均响应时间",
"type": "stat",
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 0},
"targets": [{
"expr": "rate(reranker_request_duration_seconds_sum[5m]) / rate(reranker_request_duration_seconds_count[5m])",
"legendFormat": "平均响应时间",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "s",
"decimals": 3,
"color": {"mode": "thresholds"},
"thresholds": {
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 1},
{"color": "red", "value": 3}
]
}
}
}
},
{
"id": 3,
"title": "错误率",
"type": "stat",
"gridPos": {"h": 4, "w": 6, "x": 12, "y": 0},
"targets": [{
"expr": "rate(reranker_errors_total[5m]) / rate(reranker_requests_total[5m])",
"legendFormat": "错误率",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"decimals": 2,
"color": {"mode": "thresholds"},
"thresholds": {
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 0.01},
{"color": "red", "value": 0.05}
]
}
}
}
},
{
"id": 4,
"title": "GPU内存使用",
"type": "gauge",
"gridPos": {"h": 4, "w": 6, "x": 18, "y": 0},
"targets": [{
"expr": "reranker_gpu_memory_usage_bytes",
"legendFormat": "GPU内存",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "bytes",
"min": 0,
"max": 16000000000,
"thresholds": {
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 12000000000},
{"color": "red", "value": 14000000000}
]
}
}
}
},
{
"id": 5,
"title": "请求耗时分布",
"type": "heatmap",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4},
"targets": [{
"expr": "histogram_quantile(0.95, sum(rate(reranker_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "P95响应时间",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "s",
"color": {"mode": "scheme", "schemeName": "Oranges"}
}
}
},
{
"id": 6,
"title": "相关性分数分布",
"type": "histogram",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 4},
"targets": [{
"expr": "reranker_score_distribution",
"legendFormat": "分数分布",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"}
}
}
},
{
"id": 7,
"title": "请求趋势",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 12},
"targets": [
{
"expr": "rate(reranker_requests_total[5m])",
"legendFormat": "请求速率",
"refId": "A"
},
{
"expr": "reranker_requests_total",
"legendFormat": "总请求数",
"refId": "B"
}
],
"fieldConfig": {
"defaults": {
"unit": "req/s"
}
}
},
{
"id": 8,
"title": "模型推理时间",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 12},
"targets": [{
"expr": "rate(reranker_inference_duration_seconds_sum[5m]) / rate(reranker_inference_duration_seconds_count[5m])",
"legendFormat": "平均推理时间",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "s",
"decimals": 3
}
}
},
{
"id": 9,
"title": "错误类型分布",
"type": "barchart",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 20},
"targets": [{
"expr": "sum by (error_type) (rate(reranker_errors_total[5m]))",
"legendFormat": "{{error_type}}",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"},
"custom": {
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"showPoints": "auto",
"spanNulls": false,
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
}
}
}
},
{
"id": 10,
"title": "高分比例(>=0.8)",
"type": "gauge",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 20},
"targets": [{
"expr": "rate(reranker_high_scores_total[5m]) / rate(reranker_score_distribution_count[5m])",
"legendFormat": "高分比例",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"min": 0,
"max": 1,
"thresholds": {
"steps": [
{"color": "red", "value": null},
{"color": "yellow", "value": 0.3},
{"color": "green", "value": 0.6}
]
}
}
}
}
],
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"],
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
}
},
"overwrite": true
}
4.3 导入看板到Grafana
- 在Grafana中,点击左侧的"+"号,选择"Import"
- 将上面的JSON内容粘贴到"Import via panel json"框中
- 点击"Load"
- 选择Prometheus数据源
- 点击"Import"
现在你就有了一个完整的Qwen3-Reranker监控看板!
5. 监控系统使用指南
5.1 访问监控系统
系统启动后,你可以通过以下地址访问:
| 服务 | 地址 | 用途 |
|---|---|---|
| Qwen3-Reranker Web界面 | http://localhost:7860 | 模型服务界面 |
| Prometheus指标端点 | http://localhost:8000/metrics | 查看原始指标数据 |
| Prometheus UI | http://localhost:9090 | Prometheus管理界面 |
| Grafana看板 | http://localhost:3000 | 可视化监控看板 |
5.2 关键指标解读
5.2.1 服务健康指标
- 请求速率:正常情况应该稳定,突然下降可能表示服务有问题
- 错误率:应该接近0%,超过1%需要关注
- 响应时间P95:95%的请求在这个时间内完成,是衡量服务性能的关键指标
5.2.2 模型质量指标
- 相关性分数分布:大部分分数应该集中在0.5-1.0之间
- 高分比例:分数≥0.8的比例,越高说明模型效果越好
- 平均推理时间:反映模型处理速度,突然变慢可能有问题
5.2.3 资源使用指标
- GPU内存使用:接近显存上限时需要关注
- GPU利用率:理想情况应该较高,表示GPU被充分利用
5.3 告警配置
你还可以在Grafana中配置告警,当指标异常时自动通知:
- 在Grafana看板中,点击任意面板标题,选择"Edit"
- 切换到"Alert"标签页
- 配置告警规则,例如:
- 当错误率 > 5% 持续5分钟时告警
- 当平均响应时间 > 3秒 持续5分钟时告警
- 当GPU内存使用 > 90% 时告警
- 配置通知渠道(邮件、Slack、钉钉等)
6. 高级功能扩展
6.1 自定义业务指标
除了基础监控,你还可以添加业务特定的指标:
# 在metrics.py中添加
class BusinessMetrics:
"""业务特定指标"""
def __init__(self):
# 查询类型分布
self.query_type = Counter(
'reranker_query_type_total',
'Query type distribution',
['query_type']
)
# 文档长度分布
self.doc_length = Histogram(
'reranker_document_length_chars',
'Document length in characters',
buckets=[100, 500, 1000, 2000, 5000]
)
# 用户行为分析
self.user_sessions = Counter(
'reranker_user_sessions_total',
'Number of user sessions'
)
def record_query_type(self, query_text):
"""分析查询类型"""
query_type = self.analyze_query_type(query_text)
self.query_type.labels(query_type=query_type).inc()
def analyze_query_type(self, text):
"""简单的查询类型分析"""
text_lower = text.lower()
if any(word in text_lower for word in ['什么', '是什么', '定义']):
return 'definition'
elif any(word in text_lower for word in ['如何', '怎么', '方法']):
return 'howto'
elif any(word in text_lower for word in ['为什么', '原因']):
return 'why'
else:
return 'general'
6.2 性能优化建议
基于监控数据,你可以做以下优化:
- 批处理优化:如果单个请求的文档很多,可以考虑批处理
- 缓存策略:对相同的查询结果进行缓存
- 模型量化:使用INT8量化减少内存占用
- 动态批处理:根据GPU使用情况动态调整批处理大小
6.3 长期数据存储
对于长期监控,建议将数据存储到时序数据库中:
# 使用VictoriaMetrics长期存储
# 修改prometheus.yml
remote_write:
- url: http://victoriametrics:8428/api/v1/write
7. 总结
通过给Qwen3-Reranker-0.6B模型服务添加Prometheus指标埋点和Grafana监控看板,我们实现了:
- 全方位监控:从服务性能、资源使用到模型质量的全方位监控
- 实时可视化:通过Grafana看板实时查看服务状态
- 问题预警:配置告警规则,及时发现和处理问题
- 数据驱动优化:基于监控数据优化服务配置和模型使用
这个监控方案不仅适用于Qwen3-Reranker,也可以轻松适配其他AI模型服务。关键是要设计好监控指标,既要覆盖全面,又要避免指标过多导致维护困难。
7.1 主要收获
- 服务可观测性:不再是"黑盒",而是可以清晰看到内部状态
- 问题快速定位:通过监控指标快速定位性能瓶颈
- 容量规划依据:基于历史数据做出合理的扩容决策
- 模型效果评估:持续监控模型在实际使用中的表现
7.2 下一步建议
- 添加更多业务指标:根据实际业务需求添加特定指标
- 设置自动化告警:配置邮件、钉钉等告警通知
- 建立监控规范:为团队其他服务建立统一的监控标准
- 性能基准测试:定期进行性能测试,建立性能基线
监控不是一次性的工作,而是一个持续的过程。随着业务发展,监控系统也需要不断优化和调整。希望这个方案能帮助你更好地管理和优化AI模型服务。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)