Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

GGzili/Model-Monitoring

Repository files navigation

模型监测平台

面向多台服务器上 LLM 推理服务 的轻量运维工具:健康探测、仪表盘、SSH 远程重启,以及可选的 OpenAI 兼容网关(按模型限并发与排队,缓解 tokenizer 等串行瓶颈导致的假死)。

Model Monitor — health checks, dashboard, Docker-based remote restart, and an optional gated /v1 proxy for OpenAI-compatible clients.

仓库: https://github.com/GGzili/Model-Monitoring


功能概览

能力 说明
定时探测 http://{host}:{port}/v1/chat/completions 发送极简推理请求(max_tokens: 1),记录延迟与状态
仪表盘 卡片展示各模型最近状态、延迟、检测时间;支持复制「网关调用名」(不展示 IP/容器等敏感连接信息)
立即检测 手动触发单次探测
远程重启 SSH(密码 + sudo)执行 docker restart 与容器内启动命令
双机 两台服务器上并发执行同一套重启流程
历史 延迟折线图与检测记录
配置 模型 CRUD,SQLite 持久化;敏感文本字段可选 Fernet 加密落库
网关 POST /v1/chat/completionsGET /v1/models;每模型独立 最大并发消息队列容量;需「监测启用」且「开放网关」

技术栈

组件 技术
后端 Python 3.11、FastAPI、APScheduler、httpx、Paramiko、cryptography(Fernet)
前端 Vue 3、Element Plus、ECharts
存储 SQLite
部署 Docker Compose;Nginx 反代 /api/v1

快速开始(监控机可联网)

git clone https://github.com/GGzili/Model-Monitoring.git model-monitor
cd model-monitor
docker compose up -d --build

数据文件默认挂载为项目下的 ./data/monitor.db


环境变量(后端)

变量 默认 说明
DB_PATH /data/monitor.db 数据库路径(容器内)
MONITOR_FERNET_KEY 设置后,名称/host/容器/命令/SSH 等 文本字段 以 Fernet 加密写入 SQLite;须备份密钥,与库文件一致才能解密
GATEWAY_UPSTREAM_TIMEOUT 600 网关转发上游超时(秒)

生成密钥:

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

docker-compose.yml 已预留 MONITOR_FERNET_KEY=${MONITOR_FERNET_KEY:-},可在项目根目录 .env 中配置。

端口(port / port_b / ssh_port)仍为整型明文列;未设置密钥时敏感文本以明文写入(启动会打日志警告)。


目录结构

model-monitor/
├── backend/
│ ├── main.py # FastAPI 入口与路由
│ ├── gateway.py # OpenAI 兼容网关(/v1)
│ ├── database.py # SQLite、加解密与对外 API 字典
│ ├── field_crypto.py # Fernet 字段加密(可选)
│ ├── models.py # Pydantic
│ ├── checker.py # 健康探测
│ ├── scheduler.py # 定时任务
│ ├── restart.py # SSH 重启
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ ├── ModelFormAdd.vue # 添加模型(完整表单)
│ │ │ └── ModelFormEdit.vue # 调整运行参数(仅网关与队列)
│ │ └── ...
│ ├── nginx.conf # /api、/v1 反代到后端
│ └── Dockerfile
├── scripts/ # 参考与网关压测(见 scripts/README.md)
├── docker-compose.yml
├── pack.ps1 / pack.bat # Windows 离线打包
├── deploy_offline.sh # Linux 内网部署(会重建后端 + 前端镜像)
└── LICENSE # MIT

网关(OpenAI 兼容)

客户端将原先生到模型推理地址的请求,改为打到监控站:

  • URL:http://<监控机>:4444/v1/chat/completions(与页面同域,经 Nginx)
  • 请求体 model:须与界面中的 网关调用名 一致(「API 模型名」非空则用其值,否则用「名称」)
  • 前提:该模型在配置中 启用监测开放网关

每模型可配置 最大并发消息队列容量(满则 503;0 表示不限制排队长度)。双机模型网关当前仅使用 主节点 Ahost:port

压测脚本:scripts/test_gateway_limit.py(宿主机需 httpx,见 scripts/requirements-test.txt)。


离线打包与内网部署

Windows:生成 dist_package/

需本机安装 Python、Node.js;Docker 用于导出基础镜像(可用 -SkipDockerPull / -SkipDockerSave,见脚本头注释)。

仓库根目录执行:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
cd model-monitor
.\pack.ps1
# 或双击 / 调用 pack.bat(参数相同)
# 本机已有 python:3.11-slim / nginx:alpine:.\pack.ps1 -SkipDockerPull
# 已放入 dist_package\images\*.tar:.\pack.ps1 -SkipDockerSave

pack.ps1 已包含完整前端流程,无需再手动 npm run build:

  1. frontend\ 执行 npm install + npm run build(会先删 frontend\dist 再构建,避免旧产物混入)
  2. 清空并更新 dist_package\frontend_dist\(与 frontend\dist\ 一致,避免旧 chunk 残留)

脚本会打印 打包根目录(须与当前要发布的仓库一致),并在 dist_package\PACK_MANIFEST.txt 写入时间与 git rev-parse HEAD(若有 Git);打 zip 前请打开核对,避免误打包旧目录副本。

产物还包含 wheels/images/*.tarbackend/frontend/(源码)、docker-compose.ymldeploy_offline.sh 等。将 dist_package 打成 zip(勿提交 zip 到 Git,见 .gitignore)拷到内网。

Linux 监控机:部署

不要在服务器上运行 pack.ps1。解压后:

unzip dist_package.zip
cd dist_package
chmod +x deploy_offline.sh
./deploy_offline.sh

脚本会:docker load 基础镜像、改写后端 Dockerfile 使用离线 wheels清空并复制 frontend_distfrontend/dist,然后:

  • docker compose build --no-cache backend
  • docker compose build --no-cache frontend(务必执行;仅重建后端会导致前端仍是旧 JS)
  • docker compose up -d

若只有旧版 docker-compose 命令:

sed -i 's/docker compose/docker-compose/g' deploy_offline.sh
./deploy_offline.sh

离线包目录:backend/main.py 须与 Dockerfile 同级

若错误打成 dist_package/backend/backend/main.py,镜像内会出现 /app/main.py(旧)与 /app/backend/main.py(新),uvicorn main:app 仍加载旧入口。脚本会在检测到该结构时退出并提示合并目录。

升级与缓存

  • 升级时建议保留 data/monitor.db 并备份 MONITOR_FERNET_KEY(若启用加密)。
  • 库结构:启动时会对缺失列自动 ALTER TABLE 补列(如 ssh_port_b);无需为新版手改 SQLite,除非你选择删库重建。
  • 部署后界面异常:浏览器 Ctrl+F5;确认 deploy_offline.sh 已重建 frontend 镜像

查看后端业务日志

  • docker compose logs -f backend(或 docker-compose logs -f backend)
  • 经网关的模型调用(/v1/models/v1/chat/completions)及管理操作日志:经 logging_config.get_app_logger() 打到 stderr,前缀 [modelmonitor],与 Uvicorn 访问日志一起出现在 docker logs;/api/dashboard 轮询打业务日志,避免刷屏。
  • 创建模型 / 重启 会额外经 logging_config.log_stderr_line() 各写一行到 stderr(同样带 [modelmonitor]),避免仅依赖 logging 配置时看不到业务行。
  • 离线包内 scripts/check_ssh_ports.py 可在宿主机核对库中 ssh_port(见 scripts/README.md)。

SSH 端口界面填了非 22,重启仍连 22(与上游 GitHub 对照)

公开仓库 GGzili/Model-Monitoring 当前 backend/main.pycreate_modelINSERT 未包含 ssh_port(及双机 SSH 相关列),新建行会使用表定义里的默认值 ssh_port = 22restart.py 里 Paramiko 仍从 dec["ssh_port"] 读端口,因此表现永远是 22,与前端是否填写无关。

本仓库已修复:INSERT 写入 ssh_port / ssh_port_b 等与 database.py 表结构一致。若你部署的是 GitHub master 未合并修复的版本,请改用本仓库当前代码并 docker compose build --no-cache backend;已有错误数据可删行重建或自行 UPDATE model_targets SET ssh_port=...(管理 API 不暴露改连接信息)。


配置说明(添加模型 / 调整运行参数)

阶段 说明
首次添加 填写 API 模型名、显示名、主/备机、容器与启动命令、SSH、网关与检测等;连接信息写入后 不可 通过管理 API 修改
界面「调整运行参数」(编辑按钮) 开放网关、最大并发、消息队列容量(独立 ModelFormEdit 组件,无其它表单项)
PUT /api/models/{id} 仍仅接受:intervalenabledgateway_enabledgateway_max_concurrentgateway_max_queue(界面编辑当前只提交网关三项,间隔与启用可通过 API 修改)

列表/详情/仪表盘等 JSON 不返回 hostportcontainer、启动命令、SSH;仅返回 is_dual 等公开字段。


重启流程

  1. SSH 连接目标机
  2. sudo docker restart <容器名>
  3. sudo docker exec -d <容器名> bash -c "<容器内启动命令>"

双机时对 A、B 并发执行上述步骤。


HTTP API

管理接口(前缀 /api)

方法 路径 说明
GET /api/dashboard 仪表盘汇总(公开字段 + last_*)
GET /api/models 模型列表(公开字段)
POST /api/models 创建(须含 ssh_port,1–65535;可写 sshPort;省略或 null 返回 422)
PUT /api/models/{id} 仅更新可调字段(见上表)
DELETE /api/models/{id} 删除
POST /api/models/{id}/check 立即检测
POST /api/models/{id}/restart 重启
GET /api/models/{id}/history 历史记录

网关

方法 路径 说明
GET /v1/models 列出已开放网关的模型
POST /v1/chat/completions 排队限流后转发到上游

安全提示

  • 加密 ≠ 鉴权:设置 MONITOR_FERNET_KEY 可降低「拷走 DB 文件」后的可读性;不能阻止能访问 Web/API 的人调用接口。默认 无登录,请放在 内网 / VPN,或在前端加反代鉴权。
  • 默认 CORS 宽松;面向公网时请自行增加 HTTPS、认证、网络隔离
  • 勿将 .env、数据库备份、密钥提交到 Git(见 .gitignore)。

本地开发

# 后端
cd backend && pip install -r requirements.txt
# Windows 可 set MONITOR_FERNET_KEY=...
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# 前端(Vite 代理需指向后端)
cd frontend && npm install && npm run dev

开源协议

采用 MIT License(见仓库根目录 LICENSE)。

欢迎 Issue / PR 改进文档与功能。


相关文档

  • 各推理框架的容器内启动命令示例:scripts/README.md

About

基于多台服务器的模型监测平台

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /