通义千问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-client3.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(methodmethod, endpointendpoint).inc() self.request_duration.labels(methodmethod, endpointendpoint).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_typeerror_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_sideleft, trust_remote_codeTrue ) self.model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ).eval() load_time time.time() - start_time print(fModel 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, instructionNone): 重排序主函数带监控 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 fInstruct: {instruction}\nQuery: {query}\nDocument: {doc} # 推理 inference_start time.time() inputs self.tokenizer(text, return_tensorspt).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]], dim1 )[:, 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, keylambda x: x[score], reverseTrue) # 构建输出 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(titleQwen3-Reranker with Monitoring) as demo: gr.Markdown(# Qwen3-Reranker 文本重排序服务) gr.Markdown(### 带Prometheus监控的增强版本) with gr.Row(): with gr.Column(scale2): query gr.Textbox( label查询语句, placeholder请输入您要查询的问题或关键词..., lines2 ) documents gr.Textbox( label候选文档每行一个, placeholder请输入候选文档每行一个..., lines10 ) instruction gr.Textbox( label自定义指令可选, placeholder例如Given a query, retrieve relevant passages, valueGiven a query, retrieve relevant passages ) submit_btn gr.Button(开始排序, variantprimary) with gr.Column(scale3): output gr.Textbox( label排序结果, lines20, interactiveFalse ) # 监控信息展示 with gr.Accordion( 实时监控信息, openFalse): 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( 示例, openFalse): 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( fnreranker.rerank, inputs[query, documents, instruction], outputsoutput ) 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_name0.0.0.0, server_port7860, shareFalse )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.time200h - --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_PASSWORDadmin - GF_USERS_ALLOW_SIGN_UPfalse 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.py4. 配置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 Test4.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 UIhttp://localhost:9090Prometheus管理界面Grafana看板http://localhost:3000可视化监控看板5.2 关键指标解读5.2.1 服务健康指标请求速率正常情况应该稳定突然下降可能表示服务有问题错误率应该接近0%超过1%需要关注响应时间P9595%的请求在这个时间内完成是衡量服务性能的关键指标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_typequery_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 general6.2 性能优化建议基于监控数据你可以做以下优化批处理优化如果单个请求的文档很多可以考虑批处理缓存策略对相同的查询结果进行缓存模型量化使用INT8量化减少内存占用动态批处理根据GPU使用情况动态调整批处理大小6.3 长期数据存储对于长期监控建议将数据存储到时序数据库中# 使用VictoriaMetrics长期存储 # 修改prometheus.yml remote_write: - url: http://victoriametrics:8428/api/v1/write7. 总结通过给Qwen3-Reranker-0.6B模型服务添加Prometheus指标埋点和Grafana监控看板我们实现了全方位监控从服务性能、资源使用到模型质量的全方位监控实时可视化通过Grafana看板实时查看服务状态问题预警配置告警规则及时发现和处理问题数据驱动优化基于监控数据优化服务配置和模型使用这个监控方案不仅适用于Qwen3-Reranker也可以轻松适配其他AI模型服务。关键是要设计好监控指标既要覆盖全面又要避免指标过多导致维护困难。7.1 主要收获服务可观测性不再是黑盒而是可以清晰看到内部状态问题快速定位通过监控指标快速定位性能瓶颈容量规划依据基于历史数据做出合理的扩容决策模型效果评估持续监控模型在实际使用中的表现7.2 下一步建议添加更多业务指标根据实际业务需求添加特定指标设置自动化告警配置邮件、钉钉等告警通知建立监控规范为团队其他服务建立统一的监控标准性能基准测试定期进行性能测试建立性能基线监控不是一次性的工作而是一个持续的过程。随着业务发展监控系统也需要不断优化和调整。希望这个方案能帮助你更好地管理和优化AI模型服务。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。