inference-aiops 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. inference_aiops-0.1.0/.gitignore +7 -0
  2. inference_aiops-0.1.0/CHANGELOG.md +58 -0
  3. inference_aiops-0.1.0/LICENSE +21 -0
  4. inference_aiops-0.1.0/PKG-INFO +129 -0
  5. inference_aiops-0.1.0/README.md +113 -0
  6. inference_aiops-0.1.0/RELEASE_NOTES.md +55 -0
  7. inference_aiops-0.1.0/SECURITY.md +79 -0
  8. inference_aiops-0.1.0/inference_aiops/__init__.py +9 -0
  9. inference_aiops-0.1.0/inference_aiops/cli/__init__.py +9 -0
  10. inference_aiops-0.1.0/inference_aiops/cli/_common.py +78 -0
  11. inference_aiops-0.1.0/inference_aiops/cli/_root.py +57 -0
  12. inference_aiops-0.1.0/inference_aiops/cli/doctor.py +21 -0
  13. inference_aiops-0.1.0/inference_aiops/cli/init.py +97 -0
  14. inference_aiops-0.1.0/inference_aiops/cli/metrics.py +45 -0
  15. inference_aiops-0.1.0/inference_aiops/cli/overview.py +16 -0
  16. inference_aiops-0.1.0/inference_aiops/cli/secret.py +105 -0
  17. inference_aiops-0.1.0/inference_aiops/cli/serve.py +90 -0
  18. inference_aiops-0.1.0/inference_aiops/config.py +140 -0
  19. inference_aiops-0.1.0/inference_aiops/connection.py +215 -0
  20. inference_aiops-0.1.0/inference_aiops/doctor.py +84 -0
  21. inference_aiops-0.1.0/inference_aiops/governance/__init__.py +40 -0
  22. inference_aiops-0.1.0/inference_aiops/governance/audit.py +377 -0
  23. inference_aiops-0.1.0/inference_aiops/governance/budget.py +225 -0
  24. inference_aiops-0.1.0/inference_aiops/governance/decorators.py +474 -0
  25. inference_aiops-0.1.0/inference_aiops/governance/paths.py +23 -0
  26. inference_aiops-0.1.0/inference_aiops/governance/patterns.py +378 -0
  27. inference_aiops-0.1.0/inference_aiops/governance/policy.py +411 -0
  28. inference_aiops-0.1.0/inference_aiops/governance/sanitize.py +39 -0
  29. inference_aiops-0.1.0/inference_aiops/governance/undo.py +218 -0
  30. inference_aiops-0.1.0/inference_aiops/ops/__init__.py +1 -0
  31. inference_aiops-0.1.0/inference_aiops/ops/_util.py +60 -0
  32. inference_aiops-0.1.0/inference_aiops/ops/cost.py +52 -0
  33. inference_aiops-0.1.0/inference_aiops/ops/deploy.py +75 -0
  34. inference_aiops-0.1.0/inference_aiops/ops/metrics.py +152 -0
  35. inference_aiops-0.1.0/inference_aiops/ops/models.py +88 -0
  36. inference_aiops-0.1.0/inference_aiops/ops/overview.py +38 -0
  37. inference_aiops-0.1.0/inference_aiops/ops/ray_cluster.py +154 -0
  38. inference_aiops-0.1.0/inference_aiops/ops/serve.py +154 -0
  39. inference_aiops-0.1.0/inference_aiops/secretstore.py +302 -0
  40. inference_aiops-0.1.0/mcp_server/__init__.py +1 -0
  41. inference_aiops-0.1.0/mcp_server/_shared.py +101 -0
  42. inference_aiops-0.1.0/mcp_server/server.py +35 -0
  43. inference_aiops-0.1.0/mcp_server/tools/__init__.py +1 -0
  44. inference_aiops-0.1.0/mcp_server/tools/cost.py +27 -0
  45. inference_aiops-0.1.0/mcp_server/tools/deploy.py +110 -0
  46. inference_aiops-0.1.0/mcp_server/tools/metrics.py +70 -0
  47. inference_aiops-0.1.0/mcp_server/tools/models.py +101 -0
  48. inference_aiops-0.1.0/mcp_server/tools/ray_cluster.py +104 -0
  49. inference_aiops-0.1.0/mcp_server/tools/serve.py +216 -0
  50. inference_aiops-0.1.0/pyproject.toml +59 -0
  51. inference_aiops-0.1.0/server.json +21 -0
  52. inference_aiops-0.1.0/skills/inference-aiops/SKILL.md +116 -0
  53. inference_aiops-0.1.0/skills/inference-aiops/references/capabilities.md +80 -0
  54. inference_aiops-0.1.0/skills/inference-aiops/references/cli-reference.md +56 -0
  55. inference_aiops-0.1.0/skills/inference-aiops/references/setup-guide.md +107 -0
  56. inference_aiops-0.1.0/smithery.yaml +9 -0
  57. inference_aiops-0.1.0/tests/test_cost.py +47 -0
  58. inference_aiops-0.1.0/tests/test_deploy.py +86 -0
  59. inference_aiops-0.1.0/tests/test_models.py +69 -0
  60. inference_aiops-0.1.0/tests/test_ray_cluster.py +74 -0
  61. inference_aiops-0.1.0/tests/test_secretstore.py +99 -0
  62. inference_aiops-0.1.0/tests/test_smoke.py +280 -0
  63. inference_aiops-0.1.0/uv.lock +962 -0
@@ -0,0 +1,7 @@
1
+ .venv/
2
+ dist/
3
+ __pycache__/
4
+ *.pyc
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ *.egg-info/
@@ -0,0 +1,58 @@
1
+ # Changelog
2
+
3
+ All notable changes to inference-aiops are documented here. This project adheres
4
+ to [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [0.1.0] — preview
7
+
8
+ Initial preview release: governed AI-ops for GPU inference clusters (vLLM + Ray
9
+ Serve / Ray Jobs) with a bundled governance harness. **Mock-validated only — not
10
+ yet verified against a live cluster.**
11
+
12
+ ### Added
13
+
14
+ - **30 MCP tools** (16 read, 14 write), every one wrapped with the bundled
15
+ `@governed_tool` harness (audit, policy, token/runaway budget, undo,
16
+ risk-tiers):
17
+ - **Metrics & RCA** — `request_metrics` (TTFT/TPOT/e2e latency + token
18
+ totals), `queue_depth` (running vs waiting backpressure), `kv_cache_stats`
19
+ (KV utilisation, prefix-cache hit rate, preemptions), and the flagship
20
+ correlators `diagnose_latency_spike` and `diagnose_low_utilization` (fold
21
+ queue depth + KV-cache pressure + prefix-cache locality into a ranked cause
22
+ plus the specific knob to turn).
23
+ - **Ray Serve** — reads `serve_deployment_list`, `deployment_status`,
24
+ `replica_list`, `autoscale_config_get`; writes `scale_replicas_up` (med,
25
+ undo), `scale_replicas_down` (high, dry-run, undo), `scale_to_zero` (high,
26
+ dry-run, undo), `autoscale_config_update` (med, undo), `drain_replica`
27
+ (high, dry-run, graceful — finishes in-flight requests).
28
+ - **Models / vLLM** — `model_list`, `model_info` (read); `lora_load` (med),
29
+ `lora_unload` (high, dry-run), `model_hot_swap` (high, dry-run — Sleep-Mode
30
+ base swap, captures the prior model).
31
+ - **Ray cluster / jobs / GPU** — `ray_cluster_resources` (CPU/GPU alloc),
32
+ `ray_dashboard_status`, `ray_job_list`, `gpu_utilization` (per-node) as
33
+ reads; `ray_job_cancel` (med) and `replica_restart` (high, dry-run) as writes.
34
+ - **Deploy lifecycle** — `model_deploy` (med), `model_undeploy` (high,
35
+ dry-run), `deployment_redeploy` (high, dry-run), `routing_policy_update`
36
+ (med, undo — prefix-aware / session-affinity routing to fix cache locality).
37
+ - **Cost** — `cost_per_token` (deterministic $/1M tokens from throughput ×
38
+ GPU $/hr).
39
+ - **Prometheus-native metrics** — parses vLLM's `/metrics` endpoint directly; no
40
+ Prometheus server required.
41
+ - **Optional encrypted secret store** — a bearer token is optional (many stacks
42
+ run open); when required it is stored encrypted in
43
+ `~/.inference-aiops/secrets.enc` (Fernet + scrypt), never plaintext on disk.
44
+ Legacy `INFERENCE_<TARGET>_TOKEN` env var honoured as a fallback.
45
+ - **CLI** (`inference-aiops`) — `init` wizard, `overview`, `serve`
46
+ (list/status/scale/scale-to-zero), `metrics` (requests/queue/diagnose),
47
+ `secret` management, `mcp`, and a `doctor` that probes the Ray dashboard and
48
+ vLLM independently.
49
+ - **Connection layer** over the Ray dashboard (Serve + Jobs) and the vLLM
50
+ services with centralised teaching error translation.
51
+
52
+ ### Known limitations
53
+
54
+ - Preview / mock-only: validated against mocked vLLM `/metrics`, vLLM OpenAI
55
+ API, and Ray dashboard responses; needs live verification.
56
+ - Unverified against real hardware / topology: multi-GPU tensor-parallel /
57
+ pipeline-parallel deployments, real GPU thermal/throttle telemetry, and
58
+ multi-node drain / node-reboot orchestration.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wei <zhouwei008@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: inference-aiops
3
+ Version: 0.1.0
4
+ Summary: Governed AI-ops for GPU inference clusters (vLLM + Ray Serve/Jobs): latency/utilization RCA, replica scaling, drain, model lifecycle, and destructive-op guardrails with a built-in governance harness (audit, budget, undo, risk tiers)
5
+ Author-email: wei <zhouwei008@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: cryptography>=42.0
10
+ Requires-Dist: httpx<1.0,>=0.27
11
+ Requires-Dist: mcp[cli]<2.0,>=1.10
12
+ Requires-Dist: pyyaml<7.0,>=6.0
13
+ Requires-Dist: rich<16.0,>=13.0
14
+ Requires-Dist: typer<1.0,>=0.12
15
+ Description-Content-Type: text/markdown
16
+
17
+ <!-- mcp-name: io.github.AIops-tools/inference-aiops -->
18
+
19
+ # Inference AIops (preview)
20
+
21
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the vLLM or Ray projects or any inference-serving vendor.** Product and trademark names belong to their owners. MIT licensed.
22
+
23
+ Governed AI-ops for **GPU inference clusters** — **vLLM** (OpenAI API + Prometheus
24
+ `/metrics`) and **Ray Serve / Ray Jobs** (Ray dashboard) — with a **built-in
25
+ governance harness**: unified audit log, policy engine, token/runaway budget
26
+ guard, undo-token recording, and graduated-autonomy risk tiers. It parses
27
+ vLLM's Prometheus `/metrics` directly (no Prometheus server required) and probes
28
+ the Ray dashboard independently. A bearer token is **optional** (many stacks run
29
+ open). **Preview — mock-validated only, not yet verified against a live cluster.**
30
+
31
+ ## What it does
32
+
33
+ The flagship value is **root-cause analysis**, wrapped in guarded reads and writes:
34
+
35
+ - **`diagnose_latency_spike`** (flagship RCA) — when TTFT/TPOT/e2e latency
36
+ climbs, it correlates **queue depth** (running vs waiting), **KV-cache
37
+ pressure / preemptions**, and **prefix-cache locality** into a *ranked* cause
38
+ plus the **specific knob to turn** (add replicas, raise `max-num-seqs`, fix
39
+ routing, enlarge KV cache). Every flag is a number, not a black-box verdict.
40
+ - **`diagnose_low_utilization`** — the inverse: idle GPUs, over-provisioned
41
+ replicas, or routing that strands a cache-warm replica → what to scale down.
42
+ - **Prometheus-native** — reads vLLM's `/metrics` endpoint directly; no
43
+ Prometheus/Grafana deployment needed.
44
+ - **Governance-grade** — the **first governance-grade entrant** in this niche:
45
+ audit + budget + risk-tier approval + undo-token + prompt-injection sanitize,
46
+ with **dry-run + double-confirm** on the fragile prod ops (scale-down,
47
+ scale-to-zero, drain, redeploy, hot-swap) the community reports as dangerous.
48
+ - **Laptop self-test** — ~80% of the tool self-tests free: vLLM on a single GPU
49
+ or CPU-mock + Ray in one local container (`ray start --head`).
50
+
51
+ ## Capability matrix (30 MCP tools)
52
+
53
+ | Group | Tools | Count | R/W (risk) |
54
+ |-------|-------|:-----:|:-----------|
55
+ | **Metrics & RCA** | `request_metrics`, `queue_depth`, `kv_cache_stats`, `diagnose_latency_spike`, `diagnose_low_utilization` | 5 | read |
56
+ | **Ray Serve (read)** | `serve_deployment_list`, `deployment_status`, `replica_list`, `autoscale_config_get` | 4 | read |
57
+ | **Ray Serve (write)** | `scale_replicas_up`, `scale_replicas_down`, `scale_to_zero`, `autoscale_config_update`, `drain_replica` | 5 | write (med / **high**) |
58
+ | **Models / vLLM** | `model_list`, `model_info`, `lora_load`, `lora_unload`, `model_hot_swap` | 5 | read + write (med / **high**) |
59
+ | **Ray cluster / jobs / GPU** | `ray_cluster_resources`, `ray_dashboard_status`, `ray_job_list`, `gpu_utilization`, `ray_job_cancel`, `replica_restart` | 6 | read + write (med / **high**) |
60
+ | **Deploy lifecycle** | `model_deploy`, `model_undeploy`, `deployment_redeploy`, `routing_policy_update` | 4 | write (med / **high**) |
61
+ | **Cost** | `cost_per_token` | 1 | read |
62
+
63
+ **16 read, 14 write.** High-risk writes (`scale_replicas_down`,
64
+ `scale_to_zero`, `drain_replica`, `lora_unload`, `model_hot_swap`,
65
+ `replica_restart`, `model_undeploy`, `deployment_redeploy`) all support
66
+ `dry_run` + double-confirm; reversible writes record an undo descriptor.
67
+
68
+ ## Install
69
+
70
+ ```bash
71
+ uv tool install inference-aiops # or: pipx install inference-aiops
72
+ ```
73
+
74
+ ## Quick start
75
+
76
+ ```bash
77
+ inference-aiops init # wizard: host + ray_port + vllm_port + scheme
78
+ inference-aiops doctor # probes BOTH the Ray dashboard and vLLM independently
79
+ inference-aiops overview # deployments + total replicas + queue backpressure
80
+ inference-aiops metrics diagnose # why is inference slow? ranked RCA + the knob to turn
81
+ inference-aiops serve list # Ray Serve deployments + replica counts
82
+ ```
83
+
84
+ Run as an MCP server (stdio) for the full 30-tool surface:
85
+
86
+ ```bash
87
+ export INFERENCE_AIOPS_MASTER_PASSWORD=... # only if a bearer token is stored
88
+ inference-aiops mcp
89
+ ```
90
+
91
+ The CLI is a convenience subset (`init`, `overview`, `serve …`, `metrics …`,
92
+ `secret …`, `doctor`, `mcp`); the full 30 tools are exposed via the MCP server.
93
+
94
+ ## Governance
95
+
96
+ Every MCP tool passes through the bundled `@governed_tool` harness:
97
+
98
+ - **Audit** — every call (params, result, status, duration, risk tier,
99
+ approver, rationale) logged to `~/.inference-aiops/audit.db` (relocatable via
100
+ `INFERENCE_AIOPS_HOME`).
101
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker on
102
+ tight poll/retry loops.
103
+ - **Risk tiers** — graduated autonomy; high-risk ops can require a named
104
+ approver (`INFERENCE_AUDIT_APPROVED_BY` / `INFERENCE_AUDIT_RATIONALE`).
105
+ - **Undo recording** — reversible writes (scale, autoscale-config, routing,
106
+ hot-swap, LoRA load) record an inverse descriptor.
107
+
108
+ ## Supported scope + limitations
109
+
110
+ **Preview / mock-only.** All behaviour is validated against mocked vLLM
111
+ `/metrics`, vLLM OpenAI API, and Ray dashboard responses. **~80% of the tool
112
+ self-tests on a laptop** — vLLM on a single GPU or CPU-mock plus a local
113
+ one-node Ray head. Not yet verified against a live production cluster.
114
+
115
+ Unverified against real hardware / topology:
116
+
117
+ - multi-GPU **tensor-parallel / pipeline-parallel** deployments,
118
+ - real GPU **thermal / throttle** telemetry (utilisation is best-effort from
119
+ the Ray dashboard's `/api/nodes`),
120
+ - **multi-node drain** and node-reboot orchestration.
121
+
122
+ The fastest live check is `inference-aiops doctor`.
123
+
124
+ ## Missing a capability?
125
+
126
+ This is the GPU-inference member of the AIops-tools family (governed AI-ops with
127
+ audit + budget + undo + risk tiers). If a vLLM or Ray capability you need is
128
+ missing, or your stack speaks a dialect these tools don't yet handle — open an
129
+ issue or a PR. Contributions welcome.
@@ -0,0 +1,113 @@
1
+ <!-- mcp-name: io.github.AIops-tools/inference-aiops -->
2
+
3
+ # Inference AIops (preview)
4
+
5
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the vLLM or Ray projects or any inference-serving vendor.** Product and trademark names belong to their owners. MIT licensed.
6
+
7
+ Governed AI-ops for **GPU inference clusters** — **vLLM** (OpenAI API + Prometheus
8
+ `/metrics`) and **Ray Serve / Ray Jobs** (Ray dashboard) — with a **built-in
9
+ governance harness**: unified audit log, policy engine, token/runaway budget
10
+ guard, undo-token recording, and graduated-autonomy risk tiers. It parses
11
+ vLLM's Prometheus `/metrics` directly (no Prometheus server required) and probes
12
+ the Ray dashboard independently. A bearer token is **optional** (many stacks run
13
+ open). **Preview — mock-validated only, not yet verified against a live cluster.**
14
+
15
+ ## What it does
16
+
17
+ The flagship value is **root-cause analysis**, wrapped in guarded reads and writes:
18
+
19
+ - **`diagnose_latency_spike`** (flagship RCA) — when TTFT/TPOT/e2e latency
20
+ climbs, it correlates **queue depth** (running vs waiting), **KV-cache
21
+ pressure / preemptions**, and **prefix-cache locality** into a *ranked* cause
22
+ plus the **specific knob to turn** (add replicas, raise `max-num-seqs`, fix
23
+ routing, enlarge KV cache). Every flag is a number, not a black-box verdict.
24
+ - **`diagnose_low_utilization`** — the inverse: idle GPUs, over-provisioned
25
+ replicas, or routing that strands a cache-warm replica → what to scale down.
26
+ - **Prometheus-native** — reads vLLM's `/metrics` endpoint directly; no
27
+ Prometheus/Grafana deployment needed.
28
+ - **Governance-grade** — the **first governance-grade entrant** in this niche:
29
+ audit + budget + risk-tier approval + undo-token + prompt-injection sanitize,
30
+ with **dry-run + double-confirm** on the fragile prod ops (scale-down,
31
+ scale-to-zero, drain, redeploy, hot-swap) the community reports as dangerous.
32
+ - **Laptop self-test** — ~80% of the tool self-tests free: vLLM on a single GPU
33
+ or CPU-mock + Ray in one local container (`ray start --head`).
34
+
35
+ ## Capability matrix (30 MCP tools)
36
+
37
+ | Group | Tools | Count | R/W (risk) |
38
+ |-------|-------|:-----:|:-----------|
39
+ | **Metrics & RCA** | `request_metrics`, `queue_depth`, `kv_cache_stats`, `diagnose_latency_spike`, `diagnose_low_utilization` | 5 | read |
40
+ | **Ray Serve (read)** | `serve_deployment_list`, `deployment_status`, `replica_list`, `autoscale_config_get` | 4 | read |
41
+ | **Ray Serve (write)** | `scale_replicas_up`, `scale_replicas_down`, `scale_to_zero`, `autoscale_config_update`, `drain_replica` | 5 | write (med / **high**) |
42
+ | **Models / vLLM** | `model_list`, `model_info`, `lora_load`, `lora_unload`, `model_hot_swap` | 5 | read + write (med / **high**) |
43
+ | **Ray cluster / jobs / GPU** | `ray_cluster_resources`, `ray_dashboard_status`, `ray_job_list`, `gpu_utilization`, `ray_job_cancel`, `replica_restart` | 6 | read + write (med / **high**) |
44
+ | **Deploy lifecycle** | `model_deploy`, `model_undeploy`, `deployment_redeploy`, `routing_policy_update` | 4 | write (med / **high**) |
45
+ | **Cost** | `cost_per_token` | 1 | read |
46
+
47
+ **16 read, 14 write.** High-risk writes (`scale_replicas_down`,
48
+ `scale_to_zero`, `drain_replica`, `lora_unload`, `model_hot_swap`,
49
+ `replica_restart`, `model_undeploy`, `deployment_redeploy`) all support
50
+ `dry_run` + double-confirm; reversible writes record an undo descriptor.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ uv tool install inference-aiops # or: pipx install inference-aiops
56
+ ```
57
+
58
+ ## Quick start
59
+
60
+ ```bash
61
+ inference-aiops init # wizard: host + ray_port + vllm_port + scheme
62
+ inference-aiops doctor # probes BOTH the Ray dashboard and vLLM independently
63
+ inference-aiops overview # deployments + total replicas + queue backpressure
64
+ inference-aiops metrics diagnose # why is inference slow? ranked RCA + the knob to turn
65
+ inference-aiops serve list # Ray Serve deployments + replica counts
66
+ ```
67
+
68
+ Run as an MCP server (stdio) for the full 30-tool surface:
69
+
70
+ ```bash
71
+ export INFERENCE_AIOPS_MASTER_PASSWORD=... # only if a bearer token is stored
72
+ inference-aiops mcp
73
+ ```
74
+
75
+ The CLI is a convenience subset (`init`, `overview`, `serve …`, `metrics …`,
76
+ `secret …`, `doctor`, `mcp`); the full 30 tools are exposed via the MCP server.
77
+
78
+ ## Governance
79
+
80
+ Every MCP tool passes through the bundled `@governed_tool` harness:
81
+
82
+ - **Audit** — every call (params, result, status, duration, risk tier,
83
+ approver, rationale) logged to `~/.inference-aiops/audit.db` (relocatable via
84
+ `INFERENCE_AIOPS_HOME`).
85
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker on
86
+ tight poll/retry loops.
87
+ - **Risk tiers** — graduated autonomy; high-risk ops can require a named
88
+ approver (`INFERENCE_AUDIT_APPROVED_BY` / `INFERENCE_AUDIT_RATIONALE`).
89
+ - **Undo recording** — reversible writes (scale, autoscale-config, routing,
90
+ hot-swap, LoRA load) record an inverse descriptor.
91
+
92
+ ## Supported scope + limitations
93
+
94
+ **Preview / mock-only.** All behaviour is validated against mocked vLLM
95
+ `/metrics`, vLLM OpenAI API, and Ray dashboard responses. **~80% of the tool
96
+ self-tests on a laptop** — vLLM on a single GPU or CPU-mock plus a local
97
+ one-node Ray head. Not yet verified against a live production cluster.
98
+
99
+ Unverified against real hardware / topology:
100
+
101
+ - multi-GPU **tensor-parallel / pipeline-parallel** deployments,
102
+ - real GPU **thermal / throttle** telemetry (utilisation is best-effort from
103
+ the Ray dashboard's `/api/nodes`),
104
+ - **multi-node drain** and node-reboot orchestration.
105
+
106
+ The fastest live check is `inference-aiops doctor`.
107
+
108
+ ## Missing a capability?
109
+
110
+ This is the GPU-inference member of the AIops-tools family (governed AI-ops with
111
+ audit + budget + undo + risk tiers). If a vLLM or Ray capability you need is
112
+ missing, or your stack speaks a dialect these tools don't yet handle — open an
113
+ issue or a PR. Contributions welcome.
@@ -0,0 +1,55 @@
1
+ # Inference AIops v0.1.0 — preview
2
+
3
+ Governed AI-ops for **GPU inference clusters** — **vLLM** (OpenAI API +
4
+ Prometheus `/metrics`) and **Ray Serve / Ray Jobs** (Ray dashboard) — for AI
5
+ agents, with a built-in governance harness (audit, policy, token/runaway budget,
6
+ undo-token recording, graduated risk tiers) and an optional encrypted credential
7
+ store. Standalone — no external skill-family dependency.
8
+
9
+ > **Preview / mock-only.** All behaviour is validated against mocked vLLM
10
+ > `/metrics`, vLLM OpenAI API, and Ray dashboard responses; it has not been run
11
+ > against a live cluster. The fastest live check is `inference-aiops doctor`.
12
+
13
+ ## Highlights
14
+
15
+ - **30 MCP tools** (16 read, 14 write), every one wrapped with `@governed_tool`.
16
+ - **Metrics & RCA** (read): `request_metrics` (TTFT/TPOT/e2e + token totals),
17
+ `queue_depth` (running vs waiting backpressure), `kv_cache_stats` (KV util,
18
+ prefix-cache hit rate, preemptions), and the flagship correlators
19
+ `diagnose_latency_spike` / `diagnose_low_utilization`.
20
+ - **Ray Serve**: reads (`serve_deployment_list`, `deployment_status`,
21
+ `replica_list`, `autoscale_config_get`) + guarded writes (`scale_replicas_up`,
22
+ `scale_replicas_down`, `scale_to_zero`, `autoscale_config_update`,
23
+ `drain_replica`).
24
+ - **Models / vLLM**: `model_list`, `model_info`, `lora_load`, `lora_unload`,
25
+ `model_hot_swap` (Sleep-Mode base swap, captures prior model).
26
+ - **Ray cluster / jobs / GPU**: `ray_cluster_resources`, `ray_dashboard_status`,
27
+ `ray_job_list`, `gpu_utilization`, `ray_job_cancel`, `replica_restart`.
28
+ - **Deploy lifecycle**: `model_deploy`, `model_undeploy`, `deployment_redeploy`,
29
+ `routing_policy_update` (prefix-aware / session-affinity routing).
30
+ - **Cost**: `cost_per_token` (deterministic $/1M tokens from throughput × GPU $/hr).
31
+ - **Prometheus-native** — parses vLLM's `/metrics` directly; no Prometheus
32
+ server required.
33
+ - **Safety on the fragile ops** — `scale_replicas_down`, `scale_to_zero`,
34
+ `drain_replica`, `lora_unload`, `model_hot_swap`, `replica_restart`,
35
+ `model_undeploy`, `deployment_redeploy` are high-risk with `dry_run` +
36
+ double-confirm; reversible writes record an undo descriptor.
37
+ - **Optional-token auth** — a bearer token is optional (many stacks run open);
38
+ when required it is stored **encrypted** (`~/.inference-aiops/secrets.enc`,
39
+ Fernet + scrypt) — never plaintext on disk.
40
+ - **CLI** with an `init` onboarding wizard, `secret` management, and a `doctor`
41
+ that probes the Ray dashboard and vLLM independently.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ uv tool install inference-aiops
47
+ inference-aiops init
48
+ inference-aiops doctor
49
+ ```
50
+
51
+ ## Caveats
52
+
53
+ - Preview / mock-only: validated against mocked responses; needs live verification.
54
+ - Unverified against real hardware: multi-GPU tensor/pipeline-parallel
55
+ deployments, real GPU thermal/throttle telemetry, and multi-node drain.
@@ -0,0 +1,79 @@
1
+ # Security Policy
2
+
3
+ ## Disclaimer
4
+
5
+ Community-maintained open-source project. **Not affiliated with, endorsed by, or
6
+ sponsored by the vLLM or Ray projects.** Product and trademark names belong to
7
+ their owners. Source is publicly auditable under the MIT license.
8
+
9
+ ## Reporting Vulnerabilities
10
+
11
+ Report privately via a GitHub Security Advisory on
12
+ [github.com/AIops-tools/Inference-AIops](https://github.com/AIops-tools/Inference-AIops/security/advisories)
13
+ or email zhouwei008@gmail.com. Please do not open public issues for security
14
+ reports.
15
+
16
+ ## Security Design
17
+
18
+ ### Credential Management
19
+ - A bearer token is **optional** (many on-prem inference stacks run open). When
20
+ used, per-target tokens live **encrypted** in `~/.inference-aiops/secrets.enc`
21
+ (Fernet/AES-128 + scrypt-derived key; chmod 600), never in `config.yaml` and
22
+ never in source. The master password is never stored — only a per-store random
23
+ salt and the ciphertext are on disk.
24
+ - A legacy plaintext env var `INFERENCE_<TARGET_NAME_UPPER>_TOKEN` is still
25
+ honoured as a fallback with a deprecation warning (migrate with
26
+ `inference-aiops secret migrate`).
27
+ - When present, the token is sent as an `Authorization: Bearer` header and held
28
+ only in memory; it is never logged or echoed. The config file holds only host,
29
+ Ray/vLLM ports, scheme, and TLS settings.
30
+
31
+ ### Governed Operations
32
+ Every MCP tool runs through the bundled `@governed_tool` harness
33
+ (`inference_aiops.governance`):
34
+ - **Audit** — every call logged to a local SQLite DB under `~/.inference-aiops/`
35
+ (relocatable via `INFERENCE_AIOPS_HOME`), agent-attributed, secret-redacted.
36
+ - **Token/runaway budget** — hard ceilings (`INFERENCE_MAX_TOOL_CALLS` /
37
+ `INFERENCE_MAX_TOOL_SECONDS`) plus an on-by-default guard that trips a tight
38
+ poll/retry loop, preventing unbounded API consumption (e.g. polling a slow
39
+ session).
40
+ - **Graduated risk tiers** — `~/.inference-aiops/rules.yaml` `risk_tiers` gate
41
+ writes by environment/tag; the highest tiers require a recorded approver.
42
+ - **Undo-token recording** — reversible writes capture the BEFORE state and
43
+ record an inverse descriptor (e.g. a scale op → restore the prior replica
44
+ count, `autoscale_config_update` → restore prior bounds, `routing_policy_update`
45
+ → restore the prior policy) so the change can be rolled back.
46
+
47
+ ### State-Changing Operations
48
+ Destructive/traffic-affecting writes — `scale_replicas_down`, `scale_to_zero`,
49
+ `drain_replica`, `lora_unload`, `model_hot_swap`, `model_undeploy`,
50
+ `deployment_redeploy`, `replica_restart` — are `risk_level=high`, accept a
51
+ `dry_run` preview, and (under `risk_tiers`) require a recorded approver
52
+ (`INFERENCE_AUDIT_APPROVED_BY` + `INFERENCE_AUDIT_RATIONALE`). The CLI
53
+ additionally double-confirms `serve scale-to-zero` and supports `--dry-run`.
54
+ Reversible medium/low writes capture before-state and record an undo token.
55
+
56
+ ### SSL/TLS Verification
57
+ `verify_ssl` is off by default (inference stacks commonly serve plain HTTP on a
58
+ trusted network); set `scheme: https` + `verify_ssl: true` for TLS endpoints.
59
+
60
+ ### Prompt-Injection Protection
61
+ All server-returned text (model ids, deployment/replica names, job entrypoints,
62
+ Prometheus label values) is passed through a `sanitize()` truncate +
63
+ control-character strip before reaching the agent.
64
+
65
+ ### Network Scope
66
+ No webhooks, no telemetry, no outbound calls beyond the configured Ray dashboard
67
+ and vLLM endpoints. No post-install scripts or background services.
68
+
69
+ ## Static Analysis
70
+
71
+ ```bash
72
+ uvx bandit -r inference_aiops/ mcp_server/
73
+ uv run ruff check .
74
+ ```
75
+
76
+ ## Supported Versions
77
+
78
+ The latest released version receives security fixes. This is a preview (0.x);
79
+ pin a version in production.
@@ -0,0 +1,9 @@
1
+ """inference-aiops — governed Inference SCALE operations for AI agents.
2
+
3
+ Standalone and self-contained: the governance harness (audit, token budget,
4
+ undo-token recording, graduated risk tiers, prompt-injection sanitize) is
5
+ bundled under ``inference_aiops.governance`` — this package has no external
6
+ skill-family dependency. Preview: not yet full-coverage.
7
+ """
8
+
9
+ __version__ = "0.1.0"
@@ -0,0 +1,9 @@
1
+ """CLI package for inference-aiops.
2
+
3
+ Re-exports ``app`` so the pyproject entry point
4
+ ``inference-aiops = "inference_aiops.cli:app"`` works unchanged.
5
+ """
6
+
7
+ from inference_aiops.cli._root import app
8
+
9
+ __all__ = ["app"]
@@ -0,0 +1,78 @@
1
+ """Shared helpers for inference-aiops CLI sub-modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ from collections.abc import Callable
7
+ from pathlib import Path
8
+ from typing import Annotated, Any
9
+
10
+ import typer
11
+ from rich.console import Console
12
+
13
+ console = Console()
14
+
15
+ # ─── Shared Option types ───────────────────────────────────────────────────
16
+
17
+ TargetOption = Annotated[
18
+ str | None, typer.Option("--target", "-t", help="Target name from config")
19
+ ]
20
+ DryRunOption = Annotated[
21
+ bool, typer.Option("--dry-run", help="Print the API call without executing")
22
+ ]
23
+
24
+
25
+ def _cli_error_types() -> tuple[type[BaseException], ...]:
26
+ """Exceptions translated to a one-line teaching error instead of a traceback."""
27
+ from inference_aiops.connection import InferenceApiError
28
+
29
+ return (InferenceApiError, KeyError, OSError, ValueError)
30
+
31
+
32
+ def cli_errors(fn: Callable) -> Callable:
33
+ """Translate known exceptions into one red line + exit code 1."""
34
+
35
+ @functools.wraps(fn)
36
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
37
+ try:
38
+ return fn(*args, **kwargs)
39
+ except (typer.Exit, typer.Abort):
40
+ raise
41
+ except _cli_error_types() as e:
42
+ message = str(e)
43
+ if isinstance(e, KeyError):
44
+ message = f"Missing required key or environment variable: {message}"
45
+ console.print(f"[red]Error: {message}[/]")
46
+ raise typer.Exit(1) from e
47
+
48
+ return wrapper
49
+
50
+
51
+ def get_connection(target: str | None, config_path: Path | None = None):
52
+ """Return a (conn, config) tuple for the given target."""
53
+ from inference_aiops.config import load_config
54
+ from inference_aiops.connection import ConnectionManager
55
+
56
+ cfg = load_config(config_path)
57
+ mgr = ConnectionManager(cfg)
58
+ return mgr.connect(target), cfg
59
+
60
+
61
+ def dry_run_print(*, operation: str, api_call: str, parameters: dict | None = None) -> None:
62
+ """Print a dry-run preview of the API call that would be made."""
63
+ console.print("\n[bold magenta][DRY-RUN] No changes will be made.[/]")
64
+ console.print(f"[magenta] Operation: {operation}[/]")
65
+ console.print(f"[magenta] API Call: {api_call}[/]")
66
+ for k, v in (parameters or {}).items():
67
+ console.print(f"[magenta] Param: {k} = {v}[/]")
68
+ console.print("[magenta] Run without --dry-run to execute.[/]\n")
69
+
70
+
71
+ def double_confirm(action: str, resource: str) -> None:
72
+ """Require two confirmations for a destructive operation."""
73
+ console.print(f"[bold yellow]⚠️ About to: {action} '{resource}'[/]")
74
+ typer.confirm(f"Confirm 1/2: {action} '{resource}'?", abort=True)
75
+ typer.confirm(
76
+ f"Confirm 2/2: really {action} '{resource}'? This may be irreversible.",
77
+ abort=True,
78
+ )
@@ -0,0 +1,57 @@
1
+ """Top-level Typer app: assembles sub-apps and top-level commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typer
6
+
7
+ from inference_aiops.cli._common import cli_errors
8
+ from inference_aiops.cli.doctor import doctor_cmd
9
+ from inference_aiops.cli.init import init_cmd
10
+ from inference_aiops.cli.metrics import metrics_app
11
+ from inference_aiops.cli.overview import overview_cmd
12
+ from inference_aiops.cli.secret import secret_app
13
+ from inference_aiops.cli.serve import serve_app
14
+
15
+ app = typer.Typer(
16
+ name="inference-aiops",
17
+ help="Governed AI-ops for GPU inference (vLLM + Ray Serve): metrics/RCA, "
18
+ "scaling, drain, models, jobs.",
19
+ no_args_is_help=True,
20
+ )
21
+
22
+ app.add_typer(serve_app, name="serve")
23
+ app.add_typer(metrics_app, name="metrics")
24
+ app.add_typer(secret_app, name="secret")
25
+ app.command("init")(init_cmd)
26
+ app.command("overview")(overview_cmd)
27
+ app.command("doctor")(doctor_cmd)
28
+
29
+
30
+ @app.command("mcp")
31
+ @cli_errors
32
+ def mcp_cmd() -> None:
33
+ """Start the MCP server (stdio transport).
34
+
35
+ Single-command entry point for MCP clients (does not go through uvx/PyPI
36
+ resolution at launch):
37
+ inference-aiops mcp
38
+ """
39
+ import sys
40
+
41
+ if sys.version_info < (3, 11):
42
+ typer.echo(
43
+ f"ERROR: inference-aiops requires Python >= 3.11 "
44
+ f"(got {sys.version_info.major}.{sys.version_info.minor}).\n"
45
+ f"Fix: uv python install 3.12 && "
46
+ f"uv tool install --python 3.12 --force inference-aiops",
47
+ err=True,
48
+ )
49
+ raise typer.Exit(2)
50
+
51
+ from mcp_server.server import main as _mcp_main
52
+
53
+ _mcp_main()
54
+
55
+
56
+ if __name__ == "__main__":
57
+ app()
@@ -0,0 +1,21 @@
1
+ """Doctor top-level command: environment and connectivity check."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from inference_aiops.cli._common import cli_errors
10
+
11
+
12
+ @cli_errors
13
+ def doctor_cmd(
14
+ skip_auth: Annotated[
15
+ bool, typer.Option("--skip-auth", help="Skip connectivity check (faster)")
16
+ ] = False,
17
+ ) -> None:
18
+ """Check environment, config, secrets, and connectivity."""
19
+ from inference_aiops.doctor import run_doctor
20
+
21
+ raise typer.Exit(run_doctor(skip_auth=skip_auth))