ix-relay/ix_relay.py
2026-02-25 00:53:34 +00:00

101 lines
3.9 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
IX Relay — Federated Inference Network
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-relay
The khettara for AI power.
Your idle hardware earns you compute credits.
Share compute. Earn credits. Use when you need it.
"""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import sqlite3, json, time, os, hashlib, secrets
app = FastAPI(title="IX Relay", version="1.0.0")
app.add_middleware(CORSMiddleware, allow_origins=["*"],
allow_methods=["*"], allow_headers=["*"])
DB = os.environ.get("RELAY_DB", "./relay.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, endpoint TEXT,
backend TEXT DEFAULT 'cpu', capacity INTEGER DEFAULT 1,
credits REAL DEFAULT 0, last_seen INTEGER,
status TEXT DEFAULT 'idle', version TEXT DEFAULT '1.0'
)""")
c.execute("""CREATE TABLE IF NOT EXISTS accounts (
id TEXT PRIMARY KEY, credits REAL DEFAULT 10.0, created_at INTEGER
)""")
c.execute("""CREATE TABLE IF NOT EXISTS jobs (
id TEXT PRIMARY KEY, model TEXT, node_id TEXT,
credits_cost REAL DEFAULT 0.1, status TEXT DEFAULT 'pending',
created_at INTEGER, completed_at INTEGER
)""")
c.commit()
init_db()
@app.post("/register-node")
async def register_node(request: Request):
"""Register your IX instance as a relay node."""
data = await request.json()
node_id = hashlib.sha256(
f"{data.get('endpoint','')}{secrets.token_hex(8)}".encode()
).hexdigest()[:16]
with db() as c:
c.execute("""INSERT OR REPLACE INTO nodes (id,endpoint,backend,capacity,last_seen,version)
VALUES (?,?,?,?,?,?)""",
(node_id, data.get("endpoint",""), data.get("backend","cpu"),
int(data.get("capacity",1)), int(time.time()), data.get("version","1.0")))
c.commit()
return {"node_id":node_id,
"message":"Node registered. You will receive inference jobs and earn credits.",
"initial_credits":0}
@app.get("/nodes")
async def list_nodes():
"""List active relay nodes (last 5 minutes)."""
cutoff = int(time.time()) - 300
with db() as c:
rows = c.execute("""SELECT id,backend,capacity,credits,status
FROM nodes WHERE last_seen > ? ORDER BY credits DESC""", (cutoff,)).fetchall()
return {"active_nodes":len(rows),"nodes":[dict(r) for r in rows]}
@app.get("/credits/{account_id}")
async def get_credits(account_id: str):
with db() as c:
acc = c.execute("SELECT credits FROM accounts WHERE id=?", (account_id,)).fetchone()
if not acc:
return JSONResponse({"error":"Account not found"}, status_code=404)
return {"account_id":account_id,"credits":acc["credits"]}
@app.post("/create-account")
async def create_account():
account_id = secrets.token_hex(16)
with db() as c:
c.execute("INSERT INTO accounts (id,credits,created_at) VALUES (?,?,?)",
(account_id, 10.0, int(time.time())))
c.commit()
return {"account_id":account_id,"initial_credits":10.0,
"message":"Account created. 10 free credits to start."}
@app.get("/health")
async def health():
return {"status":"ok","service":"IX Relay","author":"Salka Elmadani","version":"1.0.0"}
if __name__ == "__main__":
import uvicorn
print("IX Relay — Federated Inference Network")
print("The khettara for AI power.")
print("Built in Morocco for the world.")
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT","7938")))