merge: chore/cleanup-remove-bloat-and-secrets into main
This commit is contained in:
commit
bde2f3a97d
1173 changed files with 437609 additions and 0 deletions
155
infra/alert_rules.yml
Normal file
155
infra/alert_rules.yml
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
groups:
|
||||
- name: rmi-critical
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: BackendDown
|
||||
expr: up{job="rmi-backend"} == 0
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
service: rmi-backend
|
||||
annotations:
|
||||
summary: "RMI backend is DOWN"
|
||||
description: "rmi-backend has been unreachable for 2+ minutes. Check RB-001."
|
||||
runbook_url: "https://docs.rugmunch.io/runbooks/rb-001"
|
||||
|
||||
- alert: HighErrorRate
|
||||
expr: |
|
||||
(
|
||||
sum(rate(rmi_requests_total{status=~"5.."}[5m]))
|
||||
/ sum(rate(rmi_requests_total[5m]))
|
||||
) > 0.05
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
service: rmi-backend
|
||||
annotations:
|
||||
summary: "5xx error rate > 5% for 5 minutes"
|
||||
|
||||
- alert: RedisDown
|
||||
expr: up{job="rmi-redis"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "Redis is down"
|
||||
description: "Cache layer unreachable. Backend will degrade to no-cache."
|
||||
|
||||
- alert: PostgresDown
|
||||
expr: up{job="rmi-postgres"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "Postgres is down"
|
||||
description: "Source of truth unreachable."
|
||||
|
||||
- alert: ClickhouseDown
|
||||
expr: up{job="rmi-clickhouse"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "ClickHouse is down"
|
||||
description: "Analytics queries will fail."
|
||||
|
||||
- alert: QdrantDown
|
||||
expr: up{job="rmi-qdrant"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Qdrant is down"
|
||||
description: "RAG queries will fail."
|
||||
|
||||
- alert: Neo4jDown
|
||||
expr: up{job="rmi-neo4j"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Neo4j is down"
|
||||
description: "Entity resolution queries will fail."
|
||||
|
||||
- alert: GlitchtipDown
|
||||
expr: up{job="rmi-glitchtip"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "GlitchTip is down"
|
||||
description: "Errors are not being captured."
|
||||
|
||||
- name: rmi-warning
|
||||
interval: 1m
|
||||
rules:
|
||||
- alert: HighLatencyP99
|
||||
expr: |
|
||||
histogram_quantile(0.99,
|
||||
sum by (le, path) (rate(rmi_request_duration_seconds_bucket[5m]))
|
||||
) > 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: rmi-backend
|
||||
annotations:
|
||||
summary: "p99 latency > 1s on {{ $labels.path }}"
|
||||
|
||||
- alert: BackendHighMemory
|
||||
expr: |
|
||||
(
|
||||
container_memory_usage_bytes{name=~".*rmi-backend.*"}
|
||||
/ container_spec_memory_limit_bytes{name=~".*rmi-backend.*"}
|
||||
) > 0.85
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Backend memory > 85%"
|
||||
|
||||
- alert: DiskSpaceLow
|
||||
expr: |
|
||||
(
|
||||
1 - node_filesystem_avail_bytes{job="node"}
|
||||
/ node_filesystem_size_bytes{job="node"}
|
||||
) > 0.85
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Disk > 85% full"
|
||||
|
||||
- alert: AlertManagerDown
|
||||
expr: up{job="alertmanager"} == 0
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "AlertManager itself is down"
|
||||
|
||||
- name: rmi-slo-burn
|
||||
interval: 1m
|
||||
rules:
|
||||
- alert: SLOBurnRate2x
|
||||
expr: |
|
||||
(
|
||||
sum(rate(rmi_requests_total{status=~"5.."}[1h]))
|
||||
/ sum(rate(rmi_requests_total[1h]))
|
||||
) > 0.02
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "SLO burn rate 2x"
|
||||
|
||||
- alert: SLOBurnRate4x
|
||||
expr: |
|
||||
(
|
||||
sum(rate(rmi_requests_total{status=~"5.."}[1h]))
|
||||
/ sum(rate(rmi_requests_total[1h]))
|
||||
) > 0.04
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "SLO burn rate 4x — DEPLOY FREEZE"
|
||||
56
infra/clickhouse_schema.sql
Normal file
56
infra/clickhouse_schema.sql
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
-- RMI v5.0 ClickHouse Schema (T07)
|
||||
-- Apply: docker exec rmi-clickhouse clickhouse-client < infra/clickhouse_schema.sql
|
||||
-- Idempotent: all CREATE statements use IF NOT EXISTS.
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS rmi;
|
||||
|
||||
USE rmi;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS x402_revenue (
|
||||
tx_hash String,
|
||||
tool_id String,
|
||||
agent_id String,
|
||||
amount_usd Float64,
|
||||
chain String,
|
||||
paid_at DateTime,
|
||||
tier String
|
||||
) ENGINE = MergeTree() ORDER BY paid_at;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS mcp_calls (
|
||||
call_id String,
|
||||
tool_id String,
|
||||
agent_id String,
|
||||
latency_ms UInt32,
|
||||
success UInt8,
|
||||
called_at DateTime
|
||||
) ENGINE = MergeTree() ORDER BY called_at;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS indexer_lag (
|
||||
chain String,
|
||||
block_lag UInt32,
|
||||
last_block UInt64,
|
||||
updated_at DateTime
|
||||
) ENGINE = MergeTree() ORDER BY (chain, updated_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reputation_deltas (
|
||||
deployer_id String,
|
||||
old_alpha UInt32,
|
||||
old_beta UInt32,
|
||||
new_alpha UInt32,
|
||||
new_beta UInt32,
|
||||
event_type String,
|
||||
updated_at DateTime
|
||||
) ENGINE = MergeTree() ORDER BY (deployer_id, updated_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS cost_attribution (
|
||||
ts DateTime,
|
||||
tool_id String,
|
||||
agent_id String,
|
||||
llm_tokens_cents UInt32,
|
||||
rpc_requests_cents UInt32,
|
||||
storage_reads_cents UInt32,
|
||||
compute_cents UInt32,
|
||||
price_charged_cents UInt32
|
||||
) ENGINE = MergeTree()
|
||||
ORDER BY (ts, tool_id, agent_id)
|
||||
PARTITION BY toYYYYMM(ts);
|
||||
86
infra/litellm-config.yaml
Normal file
86
infra/litellm-config.yaml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# LiteLLM — sovereign LLM router per v4.0 master stack
|
||||
# OpenRouter = universal provider (1 key, all models)
|
||||
# Direct DeepSeek + Groq as backups
|
||||
#
|
||||
# ACTIVE providers with real keys:
|
||||
# - openrouter → DeepSeek, MiniMax, Gemini, Mistral, Llama
|
||||
# - deepseek → direct
|
||||
# - groq → fast inference
|
||||
#
|
||||
# PLACEHOLDER (no real key, skipped): gemini, zai, minimax, mistral-direct, kimi
|
||||
|
||||
model_list:
|
||||
# PRIMARY: OpenRouter (universal)
|
||||
- model_name: deepseek-v3
|
||||
litellm_params:
|
||||
model: openrouter/deepseek/deepseek-chat
|
||||
api_key: os.environ/OPENROUTER_API_KEY
|
||||
api_base: https://openrouter.ai/api/v1
|
||||
rpm: 60
|
||||
timeout: 60
|
||||
- model_name: MiniMax-M3
|
||||
litellm_params:
|
||||
model: openrouter/MiniMax/MiniMax-M3
|
||||
api_key: os.environ/OPENROUTER_API_KEY
|
||||
api_base: https://openrouter.ai/api/v1
|
||||
rpm: 60
|
||||
timeout: 60
|
||||
- model_name: gemini-2.5-flash
|
||||
litellm_params:
|
||||
model: openrouter/google/gemini-2.5-flash
|
||||
api_key: os.environ/OPENROUTER_API_KEY
|
||||
api_base: https://openrouter.ai/api/v1
|
||||
rpm: 60
|
||||
timeout: 60
|
||||
- model_name: mistral-large
|
||||
litellm_params:
|
||||
model: openrouter/mistralai/mistral-large-latest
|
||||
api_key: os.environ/OPENROUTER_API_KEY
|
||||
api_base: https://openrouter.ai/api/v1
|
||||
rpm: 60
|
||||
timeout: 60
|
||||
- model_name: llama-3-70b
|
||||
litellm_params:
|
||||
model: openrouter/meta-llama/llama-3-70b-instruct
|
||||
api_key: os.environ/OPENROUTER_API_KEY
|
||||
api_base: https://openrouter.ai/api/v1
|
||||
rpm: 60
|
||||
timeout: 60
|
||||
|
||||
# BACKUP: direct DeepSeek
|
||||
- model_name: deepseek-direct
|
||||
litellm_params:
|
||||
model: deepseek/deepseek-chat
|
||||
api_key: os.environ/DEEPSEEK_API_KEY
|
||||
api_base: https://api.deepseek.com/v1
|
||||
rpm: 60
|
||||
timeout: 30
|
||||
|
||||
# DIRECT: Groq (fast inference)
|
||||
- model_name: groq-llama-3.3-70b
|
||||
litellm_params:
|
||||
model: groq/llama-3.3-70b-versatile
|
||||
api_key: os.environ/GROQ_API_KEY
|
||||
rpm: 100
|
||||
timeout: 30
|
||||
- model_name: groq-llama-3.1-8b
|
||||
litellm_params:
|
||||
model: groq/llama-3.1-8b-instant
|
||||
api_key: os.environ/GROQ_API_KEY
|
||||
rpm: 100
|
||||
timeout: 30
|
||||
|
||||
# FALLBACK: local Ollama
|
||||
- model_name: ollama-llama
|
||||
litellm_params:
|
||||
model: ollama/llama3.2
|
||||
api_base: http://host.docker.internal:11434
|
||||
rpm: 30
|
||||
timeout: 60
|
||||
|
||||
litellm_settings:
|
||||
drop_params: true
|
||||
set_verbose: false
|
||||
request_timeout: 60
|
||||
num_retries: 2
|
||||
telemetry: false
|
||||
30
infra/litellm-docker-compose.yml
Normal file
30
infra/litellm-docker-compose.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
version: "3.9"
|
||||
|
||||
# LiteLLM — sovereign LLM router
|
||||
# Run: DEEPSEEK_API_KEY=... OPENROUTER_API_KEY=... GROQ_API_KEY=... docker compose up -d
|
||||
#
|
||||
# ACTIVE keys: openrouter, deepseek, groq (set as env vars when running)
|
||||
# PLACEHOLDER: gemini, zai, minimax, mistral, kimi (skipped until real keys)
|
||||
|
||||
services:
|
||||
litellm:
|
||||
image: ghcr.io/berriai/litellm:main-stable
|
||||
container_name: rmi-litellm
|
||||
network_mode: rmi_network
|
||||
volumes:
|
||||
- ./litellm-config.yaml:/app/config.yaml
|
||||
ports:
|
||||
- "127.0.0.1:4000:4000"
|
||||
environment:
|
||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}
|
||||
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
|
||||
- GROQ_API_KEY=${GROQ_API_KEY:-}
|
||||
- MISTRAL_API_KEY=${MISTRAL_API_KEY:-}
|
||||
- KIMI_API_KEY=${KIMI_API_KEY:-}
|
||||
command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "2"]
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:4000/health/liveliness"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
81
infra/model_map.py
Normal file
81
infra/model_map.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
"""Model access map — who has tokens for what.
|
||||
|
||||
Updated whenever API keys change. Run with `python -m infra.model_map` from
|
||||
the repo root, or `bash infra/model_map.sh` for a shell-only view.
|
||||
|
||||
ACTIVE providers (real keys):
|
||||
- openrouter → DeepSeek, MiniMax, Gemini, Mistral, Llama (universal)
|
||||
- deepseek → direct DeepSeek API
|
||||
- groq → fast inference (llama-3.3-70b, llama-3.1-8b)
|
||||
|
||||
PLACEHOLDER (no real key, skipped):
|
||||
- gemini, zai, minimax, mistral-direct, kimi
|
||||
|
||||
Per v4.0 master stack: all hosted APIs are routed through LiteLLM proxy at
|
||||
http://rmi-litellm:4000 with the sovereign OpenAI-compatible interface.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Provider:
|
||||
name: str
|
||||
active: bool
|
||||
key_len: int
|
||||
key_prefix: str
|
||||
models: list[str]
|
||||
|
||||
|
||||
def _read_env(name: str) -> str:
|
||||
return os.environ.get(name, "")
|
||||
|
||||
|
||||
def _check(name: str, env_var: str, models: list[str], min_len: int = 30) -> Provider:
|
||||
key = _read_env(env_var)
|
||||
active = len(key) >= min_len
|
||||
return Provider(
|
||||
name=name,
|
||||
active=active,
|
||||
key_len=len(key),
|
||||
key_prefix=key[:8] if key else "",
|
||||
models=models,
|
||||
)
|
||||
|
||||
|
||||
def get_model_map() -> list[Provider]:
|
||||
"""Read all API keys from env. Returns provider status."""
|
||||
return [
|
||||
_check("openrouter", "OPENROUTER_API_KEY", [
|
||||
"deepseek/deepseek-chat", "MiniMax/MiniMax-M3",
|
||||
"google/gemini-2.5-flash", "mistralai/mistral-large-latest",
|
||||
"meta-llama/llama-3-70b-instruct",
|
||||
]),
|
||||
_check("deepseek", "DEEPSEEK_API_KEY", ["deepseek-chat"], min_len=30),
|
||||
_check("groq", "GROQ_API_KEY", [
|
||||
"llama-3.3-70b-versatile", "llama-3.1-8b-instant",
|
||||
]),
|
||||
_check("gemini", "GEMINI_API_KEY", ["gemini-2.5-flash"], min_len=30),
|
||||
_check("minimax", "MiniMax_API_KEY", ["MiniMax-M3"], min_len=30),
|
||||
_check("mistral", "MISTRAL_API_KEY", ["mistral-large-latest"], min_len=30),
|
||||
_check("kimi", "KIMI_API_KEY", ["kimi-k2-0711-preview"], min_len=30),
|
||||
_check("ollama-cloud", "OLLAMA_API_KEY", ["llama3.2", "qwen2.5"], min_len=30),
|
||||
]
|
||||
|
||||
|
||||
def print_map() -> None:
|
||||
"""Print human-readable model access map."""
|
||||
print(f"{'PROVIDER':<14} {'STATUS':<10} {'LEN':<5} MODELS")
|
||||
print("─" * 70)
|
||||
for p in get_model_map():
|
||||
status = "ACTIVE" if p.active else "PLACEHLD"
|
||||
models = ", ".join(p.models[:3])
|
||||
if len(p.models) > 3:
|
||||
models += f" +{len(p.models) - 3}"
|
||||
print(f"{p.name:<14} {status:<10} {p.key_len:<5} {models}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print_map()
|
||||
Loading…
Add table
Add a link
Reference in a new issue