ix-scout/ix_scout.py
2026-02-25 02:56:56 +00:00

110 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
IX Scout — Global Hardware Node Registry
Part of the Inference-X Ecosystem
# SALKA ELMADANI | inference-x.com | BSL-1.1
Copyright (C) 2024-2026 Salka Elmadani. BSL-1.1.
https://git.inference-x.com/inference-x-community/ix-scout
Real-time map of every IX node on Earth.
Anonymous. Voluntary. Community-powered.
"""
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
import sqlite3, json, time, os, hashlib
app = FastAPI(title="IX Scout", version="1.0.0",
description="Real-time global map of every Inference-X node.")
app.add_middleware(CORSMiddleware, allow_origins=["*"],
allow_methods=["*"], allow_headers=["*"])
DB = os.environ.get("SCOUT_DB", "./scout.db")
def db():
conn = sqlite3.connect(DB)
conn.row_factory = sqlite3.Row
return conn
def init_db():
with db() as c:
c.execute("""CREATE TABLE IF NOT EXISTS nodes (
id TEXT PRIMARY KEY,
backend TEXT NOT NULL,
model TEXT,
tokens_per_sec REAL DEFAULT 0,
ram_gb REAL DEFAULT 0,
country TEXT DEFAULT '',
version TEXT DEFAULT '1.0',
reported_at INTEGER,
load_pct REAL DEFAULT 0
)""")
c.commit()
@app.on_event("startup")
async def startup(): init_db()
@app.post("/report")
async def report_node(request: Request):
"""IX Engine nodes report telemetry here (opt-in via --scout flag)."""
try:
data = await request.json()
node_id = hashlib.sha256(
f"{data.get('backend','')}{data.get('ram_gb',0)}".encode()
).hexdigest()[:16]
with db() as c:
c.execute("""INSERT OR REPLACE INTO nodes
(id,backend,model,tokens_per_sec,ram_gb,country,version,reported_at,load_pct)
VALUES (?,?,?,?,?,?,?,?,?)""",
(node_id, data.get("backend","cpu"), data.get("model",""),
float(data.get("tokens_per_sec",0)), float(data.get("ram_gb",0)),
data.get("country",""), data.get("version","1.0"),
int(time.time()), float(data.get("load_pct",0))))
c.commit()
return {"status":"ok","node_id":node_id}
except Exception as e:
return JSONResponse({"error":str(e)}, status_code=400)
@app.get("/stats")
async def stats():
"""Aggregated network stats — last 24 hours."""
cutoff = int(time.time()) - 86400
with db() as c:
backends = c.execute("""
SELECT backend, COUNT(*) as nodes,
AVG(tokens_per_sec) as avg_tps,
AVG(ram_gb) as avg_ram,
AVG(load_pct) as avg_load
FROM nodes WHERE reported_at > ?
GROUP BY backend ORDER BY nodes DESC
""", (cutoff,)).fetchall()
total = c.execute("SELECT COUNT(*) as t FROM nodes WHERE reported_at > ?",
(cutoff,)).fetchone()
return {
"total_nodes": total["t"] if total else 0,
"window": "24h",
"backends": [dict(b) for b in backends]
}
@app.get("/nodes")
async def list_nodes(limit: int = 100):
"""List recent nodes (anonymized)."""
cutoff = int(time.time()) - 3600
with db() as c:
rows = c.execute("""
SELECT backend, model, tokens_per_sec, ram_gb, country, version
FROM nodes WHERE reported_at > ? ORDER BY reported_at DESC LIMIT ?
""", (cutoff, limit)).fetchall()
return {"nodes": [dict(r) for r in rows], "count": len(rows)}
@app.get("/health")
async def health():
return {"status":"ok","service":"IX Scout","author":"Salka Elmadani","version":"1.0.0"}
if __name__ == "__main__":
import uvicorn
print("IX Scout — Global Hardware Node Registry")
print("Anonymous. Voluntary. Real.")
print("Built in Morocco for the world.")
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT","7936")))