# Gensyn **Published by:** [antisav.eth](https://paragraph.com/@antisav/) **Published on:** 2025-04-25 **URL:** https://paragraph.com/@antisav/gensyn ## Content Gensyn1. Clone dan Jalankan ViKey Inferencegit clone https://github.com/direkturcrypto/vikey-inference cd vikey-inference Edit file .env:nano .env Isi seperti ini:VIKEY_API_KEY=ISI_DENGAN_API_KEY_KAMU NODE_PORT=11434 Buat ScreenScreen -S vkey1 lalu jalankanchmod +x vikey-inference-linux ./vikey-inference-linuxKalau muncul: Ollama server running on port 14444 2. Jalankan ViKey Inference di BackgroundBuat ScreenScreen -S vkey1 Supaya inference tetap jalan meskipun kamu keluar dari terminal:nohup ./vikey-inference-linux > vikey.log & Artinya inference sudah jalan!, ketik ctrl + A +D untuk exit dari aplikasi ini3. Nonaktifkan Inference Lokal di GensynEdit file YAML konfigurasi:nano hivemind_exp/configs/gpu/grpo-qwen-2.5-0.5b-deepseek-r1.yaml Ubah:use_vllm: true Menjadi:use_vllm: false Ini akan menonaktifkan vLLM agar tidak jalanin model lokal.4. Tambahkan Proxy API ke VikeyGensyn tidak tahu caranya pakai API eksternal secara default. Jadi kita: ➡️ Tambahkan server proxy FastAPI yang akan menerima permintaan dari swarm, lalu teruskan ke Vikey AI.🔧 Edit web/api/server.py → Tambahkan ini:Import Requests + Fungsi call ke Vikey (di paling atas):nano web/api/server.py import argparse import json import logging import os import time from datetime import datetime, timedelta from threading import Thread import aiofiles import httpx import uvicorn from fastapi import FastAPI, HTTPException, Query, Request, Response from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from pythonjsonlogger import jsonlogger import requests # Added import for requests from hivemind_exp.chain_utils import ModalSwarmCoordinator, setup_web3 from hivemind_exp.dht_utils import * from hivemind_exp.name_utils import * from . import global_dht from .dht_pub import GossipDHTPublisher, RewardsDHTPublisher from .kinesis import Kinesis # Vikey call function def call_vikey(prompt): headers = { "Authorization": f"Bearer {os.getenv('VIKEY_API_KEY')}", "Content-Type": "application/json" } payload = { "model": "gpt-3.5-turbo", "messages": [ {"role": "user", "content": prompt} ], "temperature": 0.7, "max_tokens": 1024 } try: response = requests.post("http://localhost:11434/v1/chat/completions", json=payload, headers=headers) response.raise_for_status() return response.json()["choices"][0]["message"]["content"] except Exception as e: return f"Vikey error: {str(e)}" # UI is served from the filesystem BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DIST_DIR = os.path.join(BASE_DIR, "ui", "dist") index_html = None async def load_index_html(): global index_html if index_html is None: index_path = os.path.join(BASE_DIR, "ui", "dist", "index.html") async with aiofiles.open(index_path, mode="r") as f: index_html = await f.read() class CustomJsonFormatter(jsonlogger.JsonFormatter): def add_fields(self, log_record, record, message): # Ensure that 'extra' fields are included in the log record super().add_fields(log_record, record, message) # Include both adapter extra fields and log call extra fields if hasattr(record, "extra_fields"): for key, value in record.extra_fields.items(): log_record[key] = value json_formatter = CustomJsonFormatter("%(asctime)s %(levelname)s %(message)s") # Configure the root logger root_logger = logging.getLogger() handler = logging.StreamHandler() handler.setFormatter(json_formatter) root_logger.addHandler(handler) root_logger.setLevel(logging.INFO) # Get the module logger logger = logging.getLogger(__name__) app = FastAPI() port = os.getenv("SWARM_UI_PORT", "8000") try: port = int(port) except ValueError: logger.warning(f"invalid port {port}. Defaulting to 8000") port = 8000 config = uvicorn.Config( app, host="0.0.0.0", port=port, timeout_keep_alive=10, timeout_graceful_shutdown=10, h11_max_incomplete_event_size=8192, # Max header size in bytes ) server = uvicorn.Server(config) @app.exception_handler(Exception) async def internal_server_error_handler(request: Request, exc: Exception): logger.error(f"Internal server error: {exc}") return JSONResponse( status_code=500, content={ "detail": "Internal Server Error", "message": str(exc), }, ) @app.get("/api/healthz") async def get_health(): lpt = global_dht.dht_cache.get_last_polled() if lpt is None: raise HTTPException(status_code=500, detail="dht never polled") diff = datetime.now() - lpt if diff > timedelta(minutes=5): raise HTTPException(status_code=500, detail="dht last poll exceeded 5 minutes") return { "message": "OK", "lastPolled": diff, } @app.post("/api/infer") async def infer_vikey(request: Request): body = await request.json() prompt = body.get("prompt", "") if not prompt: raise HTTPException(status_code=400, detail="Missing prompt") output = call_vikey(prompt) return {"response": output} @app.get("/api/round_and_stage") def get_round_and_stage(): r, s = global_dht.dht_cache.get_round_and_stage() return { "round": r, "stage": s, } @app.get("/api/leaderboard") def get_leaderboard(): leaderboard = global_dht.dht_cache.get_leaderboard() res = dict(leaderboard) if res is not None: return { "leaders": res.get("leaders", []), "total": res.get("total", 0), } @app.get("/api/leaderboard-cumulative") def get_leaderboard_cumulative(): leaderboard = global_dht.dht_cache.get_leaderboard_cumulative() res = dict(leaderboard) if res is not None: return { "leaders": res.get("leaders", []), "total": res.get("total", 0), } else: return { "leaders": [], "total": 0, } @app.get("/api/rewards-history") def get_rewards_history(): leaderboard = global_dht.dht_cache.get_leaderboard() res = dict(leaderboard) if res is not None: return { "leaders": res.get("rewardsHistory", []), } @app.get("/api/name-to-id") def get_id_from_name(name: str = Query("")): leaderboard = global_dht.dht_cache.get_leaderboard() leader_ids = [leader["id"] for leader in leaderboard["leaders"]] or [] peer_id = search_peer_ids_for_name(leader_ids, name) return { "id": peer_id, } @app.post("/api/id-to-name") async def id_to_name(request: Request): # Check request body size (100KB limit) content_length = request.headers.get("content-length") if content_length and int(content_length) > 100 * 1024: # 100KB in bytes raise HTTPException( status_code=413, detail="Request body too large. Maximum size is 100KB." ) # Parse request body try: body = await request.json() if not isinstance(body, list): raise HTTPException( status_code=400, detail="Request body must be a list of peer IDs" ) except json.JSONDecodeError as e: raise HTTPException(status_code=400, detail=f"Invalid JSON: {str(e)}") except Exception as e: raise HTTPException(status_code=400, detail=f"Invalid request body: {str(e)}") # Validate input size if len(body) > 1000: # Limit number of IDs that can be processed raise HTTPException( status_code=400, detail="Too many peer IDs. Maximum is 1000." ) # Process each ID id_to_name_map = {} for peer_id in body: try: name = get_name_from_peer_id(peer_id) if name is not None: id_to_name_map[peer_id] = name except Exception as e: logger.error(f"Error looking up name for peer ID {peer_id}: {str(e)}") return id_to_name_map @app.get("/api/gossip") def get_gossip(): gs = global_dht.dht_cache.get_gossips() return dict(gs) if os.getenv("API_ENV") != "dev": app.mount( "/assets", StaticFiles(directory=os.path.join(DIST_DIR, "assets")), name="assets", ) app.mount( "/fonts", StaticFiles(directory=os.path.join(DIST_DIR, "fonts")), name="fonts" ) app.mount( "/images", StaticFiles(directory=os.path.join(DIST_DIR, "images")), name="images", ) @app.get("/{full_path:path}") async def catch_all(full_path: str, request: Request): # Development reverse proxies to ui dev server if os.getenv("API_ENV") == "dev": logger.info( f"proxying {full_path} into local UI development environment on 5173..." ) async with httpx.AsyncClient() as client: resp = await client.get( url=f"http://localhost:5173/{full_path}", headers=request.headers ) headers = { k: v for k, v in resp.headers.items() if k.lower() not in ["content-length", "transfer-encoding"] } return Response( content=resp.content, status_code=resp.status_code, headers=headers ) # Live environment (serve from dist) await load_index_html() return HTMLResponse( content=index_html, headers={ "Cache-Control": "no-store, no-cache, must-revalidate, proxy-revalidate", "Pragma": "no-cache", "Expires": "0", }, ) def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument( "-ip", "--initial_peers", help="initial peers", nargs="+", type=str, default=[] ) return parser.parse_args() def populate_cache(): logger.info("populate_cache initialized") try: while True: logger.info("pulling latest dht data...") global_dht.dht_cache.poll_dht() time.sleep(10) logger.info("dht polled") except Exception as e: logger.error("uncaught exception while polling dht", e) def main(args): coordinator = ModalSwarmCoordinator( "", web3=setup_web3() ) # Only allows contract calls initial_peers = coordinator.get_bootnodes() # Supplied with the bootstrap node, the client will have access to the DHT. logger.info(f"initializing DHT with peers {initial_peers}") kinesis_stream = os.getenv("KINESIS_STREAM", "") kinesis_client = Kinesis(kinesis_stream) global_dht.setup_global_dht(initial_peers, coordinator, logger, kinesis_client) thread = Thread(target=populate_cache) thread.daemon = True thread.start() # Start publishing to kinesis. This will eventually replace the populate_cache thread. logger.info("Starting rewards publisher") rewards_publisher = RewardsDHTPublisher( dht=global_dht.dht, kinesis_client=kinesis_client, logger=logger, coordinator=coordinator, poll_interval_seconds=300, # 5 minute ) rewards_publisher.start() logger.info("Starting gossip publisher") gossip_publisher = GossipDHTPublisher( dht=global_dht.dht, kinesis_client=kinesis_client, logger=logger, coordinator=coordinator, poll_interval_seconds=150, # 2.5 minute ) gossip_publisher.start() logger.info(f"initializing server on port {port}") server.run() if __name__ == "__main__": main(parse_arguments()) 5. Build dan Jalankan DockerDari folder root project Gensyn (yang ada docker-compose.yaml):docker-compose build docker-compose up -d Ini akan menjalankan FastAPI yang bisa kamu akses di: http://localhost:8080/api/infercd /root/rl-swarm pip install boto3 pip install aiofiles httpx uvicorn fastapi python-json-logger requests pip install -r requirements.txt cd web/ui npm install npm run build:testnet cd /root/rl-swarm python -m web.api.server or#!/bin/bash ROOT=$PWD RED='\033[0;31m' GREEN='\033[0;32m' PURPLE='\033[0;95m' BLUE='\033[0;94m' YELLOW='\033[0;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' export PUB_MULTI_ADDRS export PEER_MULTI_ADDRS export HOST_MULTI_ADDRS export IDENTITY_PATH export ORG_ID export HF_HUB_DOWNLOAD_TIMEOUT=120 DEFAULT_PUB_MULTI_ADDRS="" PUB_MULTI_ADDRS=${PUB_MULTI_ADDRS:-$DEFAULT_PUB_MULTI_ADDRS} DEFAULT_PEER_MULTI_ADDRS="/ip4/38.101.215.13/tcp/30002/p2p/QmQ2gEXoPJg6iMBSUFWGzAabS2VhnzuS782Y637hGjfsRJ" PEER_MULTI_ADDRS=${PEER_MULTI_ADDRS:-$DEFAULT_PEER_MULTI_ADDRS} DEFAULT_HOST_MULTI_ADDRS="/ip4/0.0.0.0/tcp/38331" HOST_MULTI_ADDRS=${HOST_MULTI_ADDRS:-$DEFAULT_HOST_MULTI_ADDRS} DEFAULT_IDENTITY_PATH="$ROOT"/swarm.pem IDENTITY_PATH=${IDENTITY_PATH:-$DEFAULT_IDENTITY_PATH} cleanup() { echo -e "${YELLOW}${BOLD}[✓] Shutting down processes...${NC}" kill $SERVER_PID 2>/dev/null || true kill $TUNNEL_PID 2>/dev/null || true exit 0 } trap cleanup INT if [ -f "modal-login/temp-data/userData.json" ]; then cd modal-login echo -e "\n${CYAN}${BOLD}[✓] Installing dependencies with npm. This may take a few minutes, depending on your internet speed...${NC}" npm install --legacy-peer-deps echo -e "\n${CYAN}${BOLD}[✓] Starting the development server...${NC}" pid=$(lsof -ti:3000); if [ -n "$pid" ]; then kill -9 $pid; fi sleep 3 npm run dev > server.log 2>&1 & SERVER_PID=$! MAX_WAIT=60 for ((i = 0; i < MAX_WAIT; i++)); do if grep -q "Local: http://localhost:" server.log; then PORT=$(grep "Local: http://localhost:" server.log | sed -n 's/.*http:\/\/localhost:\([0-9]*\).*/\1/p') if [ -n "$PORT" ]; then echo -e "${GREEN}${BOLD}[✓] Server is running successfully on port $PORT.${NC}" break fi fi sleep 1 done if [ $i -eq $MAX_WAIT ]; then echo -e "${RED}${BOLD}[✗] Timeout waiting for server to start.${NC}" kill $SERVER_PID 2>/dev/null || true exit 1 fi cd .. ORG_ID=$(awk 'BEGIN { FS = "\"" } !/^[ \t]*[{}]/ { print $(NF - 1); exit }' modal-login/temp-data/userData.json) echo -e "\n${CYAN}${BOLD}[✓] ORG_ID has been set to: ${BOLD}$ORG_ID\n${NC}" else echo -e "${RED}${BOLD}[✗] modal-login/temp-data/userData.json not found! Please log in through modal first.${NC}" exit 1 fi echo -e "${CYAN}${BOLD}[✓] Installing required Python packages, may take few mins depending on your internet speed...${NC}" pip install --disable-pip-version-check -q -r "$ROOT"/requirements-hivemind.txt > /dev/null pip install --disable-pip-version-check -q -r "$ROOT"/requirements.txt > /dev/null echo -e "${GREEN}${BOLD}>>> All packages installed successfully!\n${NC}" # Vikey AI configuration and dependencies VikeyAI_PATH="$ROOT/vikeyai" if [ ! -d "$VikeyAI_PATH" ]; then echo -e "${YELLOW}[✓] Cloning Vikey AI repository...${NC}" git clone https://github.com/your-vikey-ai-repo.git "$VikeyAI_PATH" fi echo -e "${CYAN}[✓] Installing Vikey AI dependencies...${NC}" cd "$VikeyAI_PATH" pip install -r requirements.txt cd .. # Setup configuration for Vikey AI or use GPU if available if [ -z "$CONFIG_PATH" ]; then if command -v nvidia-smi &> /dev/null || [ -d "/proc/driver/nvidia" ]; then echo -e "${GREEN}${BOLD}[✓] GPU detected, using GPU configuration${NC}" CONFIG_PATH="$VikeyAI_PATH/configs/gpu/vikey_config_gpu.yaml" echo -e "${CYAN}${BOLD}[✓] Config file : ${BOLD}$CONFIG_PATH\n${NC}" else echo -e "${YELLOW}${BOLD}[✓] No GPU detected, using CPU configuration${NC}" CONFIG_PATH="$VikeyAI_PATH/configs/cpu/vikey_config_cpu.yaml" echo -e "${CYAN}${BOLD}[✓] Config file : ${BOLD}$CONFIG_PATH\n${NC}" fi fi # Vikey AI integration and inference echo -e "${CYAN}${BOLD}[✓] Starting Vikey AI inference with the provided configuration...${NC}" python "$VikeyAI_PATH/run_inference.py" --config "$CONFIG_PATH" --org_id "$ORG_ID" --identity_path "$IDENTITY_PATH" # Training session with Vikey AI integrated echo -e "${CYAN}${BOLD}[✓] Starting Vikey AI training session...${NC}" python -m hivemind_exp.gsm8k.train_single_gpu \ --hf_token "$HUGGINGFACE_ACCESS_TOKEN" \ --identity_path "$IDENTITY_PATH" \ --modal_org_id "$ORG_ID" \ --config "$CONFIG_PATH" echo -e "${GREEN}${BOLD}[✓] Vikey AI training session complete. Good luck with your project!${NC}" ## Publication Information - [antisav.eth](https://paragraph.com/@antisav/): Publication homepage - [All Posts](https://paragraph.com/@antisav/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@antisav): Subscribe to updates