Files
instagram-bot/scripts/benchmark_models.py
2026-04-16 18:58:18 +02:00

183 lines
6.5 KiB
Python

import os
import sys
import json
import time
import argparse
from datetime import datetime
# Add root project path so we can import internal modules safely
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from GramAddict.core.llm_provider import query_telepathic_llm
BENCHMARKS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "GramAddict/core/llm_benchmarks.json")
SCENARIOS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "GramAddict/core/benchmark_scenarios.json")
def load_json(path):
if os.path.exists(path):
try:
with open(path, "r") as f:
return json.load(f)
except Exception:
return None
return None
def save_json(path, data):
with open(path, "w") as f:
json.dump(data, f, indent=4)
def normalize_scores(db):
if not db.get("models"):
return db
# 1. Find the highest raw score across all models
max_raw = 0
leader_model = None
for name, data in db["models"].items():
raw = data.get("raw_score", 0)
if raw > max_raw:
max_raw = raw
leader_model = name
elif raw == max_raw and max_raw > 0:
# Tie-breaker: Latency
current_lat = data.get("latency_ms", 99999)
leader_lat = db["models"][leader_model].get("latency_ms", 99999)
if current_lat < leader_lat:
leader_model = name
if max_raw == 0:
return db
# 2. Update relative performance
for name, data in db["models"].items():
raw = data.get("raw_score", 0)
data["relative_performance_pct"] = round((raw / max_raw) * 100, 1)
data["is_leader"] = (name == leader_model)
return db
def benchmark_model(model_name: str, url: str, force: bool = False):
db = load_json(BENCHMARKS_FILE) or {"models": {}}
scenarios_data = load_json(SCENARIOS_FILE)
if not scenarios_data:
print("❌ Scenarios file missing!")
return
if not force and model_name in db.get("models", {}):
pct = db["models"][model_name].get("relative_performance_pct", "N/A")
print(f"Typical execution skip for {model_name} (Rel: {pct}%). Use --force.")
return
print(f"🚀 [Competitive Benchmarking] Model: {model_name}")
total_raw = 0
total_latency = 0
results_detail = {}
blank_b64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
system_prompt = (
"You identify which UI element to tap on an Android screen. "
"Output ONLY valid JSON: {\"index\": number, \"reason\": \"brief reason\"}"
)
for scenario in scenarios_data["scenarios"]:
print(f"--- Running: {scenario['name']} ---")
user_prompt = (
f"Which element should I tap to: {scenario['task']}\n\n"
f"Elements:\n{json.dumps(scenario['nodes'], indent=1)}\n\n"
"Rules:\n"
"- Pick the SMALLEST, most specific button or icon\n"
"- NEVER pick large containers\n"
"Return: {\"index\": number, \"reason\": \"...\"}"
)
start_time = time.time()
try:
resp_str = query_telepathic_llm(model_name, url, system_prompt, user_prompt)
latency = int((time.time() - start_time) * 1000)
total_latency += latency
except Exception as e:
print(f" ❌ API Request failed for scenario {scenario['id']}: {e}")
continue
raw_points = 0
try:
clean = resp_str.strip()
if clean.startswith("```json"): clean = clean[7:]
if clean.endswith("```"): clean = clean[:-3]
data = json.loads(clean)
# Points for structural adherence
if "index" in data and "reason" in data:
raw_points += 40
# Points for correctness
if data["index"] == scenario["target_index"]:
raw_points += 60
print(f" ✅ Correct index ({data['index']}).")
else:
print(f" ❌ Wrong index ({data['index']}). Target was {scenario['target_index']}.")
else:
print(" ❌ JSON missing fields.")
except Exception:
print(" ❌ JSON Parsing failed.")
results_detail[scenario["id"]] = raw_points
total_raw += raw_points
print(f"\n📊 Total Raw Score for {model_name}: {total_raw}")
if model_name not in db["models"]:
db["models"][model_name] = {}
db["models"][model_name].update({
"raw_score": total_raw,
"latency_ms": total_latency // len(scenarios_data["scenarios"]),
"last_tested": datetime.utcnow().isoformat() + "Z",
"details": results_detail
})
# Recalculate relative scores across all models
db = normalize_scores(db)
save_json(BENCHMARKS_FILE, db)
leader_name = [n for n, d in db["models"].items() if d.get("is_leader")][0]
rel_pct = db["models"][model_name]["relative_performance_pct"]
print(f"🏆 Current Leader: {leader_name}")
print(f"✨ Relative Performance for {model_name}: {rel_pct}%")
if __name__ == "__main__":
from GramAddict.core.config import Config
parser = argparse.ArgumentParser(description="Competitive Benchmark for Singularity", add_help=False)
parser.add_argument("--config", type=str, help="Bot config file")
parser.add_argument("--model", type=str, help="Explicit model name")
parser.add_argument("--url", type=str, help="Explicit endpoint URL")
parser.add_argument("--force", action="store_true", help="Force re-testing")
args, unknown = parser.parse_known_args()
models_to_test = []
if args.model and args.url:
models_to_test.append((args.model, args.url))
elif args.config:
configs = Config(first_run=True, config=args.config)
configs.parse_args()
for attr, pref in [("ai_telepathic_model", "ai_telepathic_url"), ("ai_model", "ai_model_url"), ("ai_condenser_model", "ai_condenser_url")]:
m = getattr(configs.args, attr, None)
u = getattr(configs.args, pref, "https://openrouter.ai/api/v1/chat/completions")
if m:
models_to_test.append((m, u))
else:
print("❌ Syntax: --config test_config.yml or --model x --url y")
sys.exit(1)
for m, u in set(models_to_test):
benchmark_model(m, u, args.force)
time.sleep(1)