CoolFace
Datasetpublic

SafeVixAI/SafeVixAI-Dataset-Hub

SafeVixAI Dataset Hub πŸ›‘οΈ The Intelligence Layer for the SafeVixAI platform β€” IIT Madras Road Safety Hackathon 2026 This repository hosts all datasets, pre-trained models, notebooks, and reproducible data acquisition scripts that power the SafeVixAI application. It is designed to be cloned directly into Google Colab or any research environment. Main Application Repo: SafeVixAI/SafeVixAI ⚑ Quickstart (Google Colab) # Clone the entire intelligence layer !git… See the full description on the dataset page: https://huggingface.co/datasets/SafeVixAI/SafeVixAI-Dataset-Hub.

sourceHugging Faceapache-2.0updated 4mo agoView on Hugging Face
1likes147downloads
batch_upgrade_wiki.py259 linesDownload Raw Back to docs
1#!/usr/bin/env python32"""3Batch upgrade AST stubs to LLM docs with email alerts on failure.4Usage: python scripts/batch_upgrade_wiki.py [--limit N] [--delay SECS]5"""6import os, sys, re, json, time, smtplib7from pathlib import Path8from email.mime.text import MIMEText9from urllib.request import Request, urlopen10from urllib.error import HTTPError11 12ROOT = Path(__file__).resolve().parent.parent.parent13WIKI_CONTENT = ROOT / "docs" / "wiki" / "content"14 15# ── Email Alert ─────────────────────────────────────────────────────────────16def send_alert_email(subject, error_details, file_name, provider_errors):17    """Send email alert when wiki generation fails persistently."""18    smtp_user = os.environ.get("ALERT_EMAIL", "")19    smtp_pass = os.environ.get("ALERT_EMAIL_PASSWORD", "")20    alert_to = os.environ.get("ALERT_EMAIL_TO", smtp_user)21 22    if not smtp_user or not smtp_pass:23        print("  [ALERT] No email configured (set ALERT_EMAIL + ALERT_EMAIL_PASSWORD)")24        print(f"  [ALERT] Issue: {subject}")25        print(f"  [ALERT] Details: {error_details}")26        _print_solutions(provider_errors)27        return28 29    body = f"""SafeVixAI Wiki Manager β€” Alert30 31ISSUE: {subject}32FILE: {file_name}33TIME: {time.strftime('%Y-%m-%d %H:%M:%S')}34 35DETAILS:36{error_details}37 38PROVIDER ERRORS:39{chr(10).join(f'  - {p}: {e}' for p, e in provider_errors.items())}40 413 WAYS TO FIX THIS:42 431. RATE LIMIT EXHAUSTED44   β†’ Wait 1 hour and re-run: python scripts/batch_upgrade_wiki.py --limit 20 --delay 545   β†’ Or switch to a different provider by updating OPENROUTER_API_KEY or MISTRAL_API_KEY46 472. API KEY EXPIRED/INVALID48   β†’ Check your keys at: https://openrouter.ai/keys | https://console.mistral.ai/api-keys49   β†’ Update chatbot_service/.env with fresh keys50   β†’ Add keys as GitHub Secrets for CI: Settings β†’ Secrets β†’ OPENROUTER_API_KEY51 523. SERVICE OUTAGE53   β†’ Check status: https://status.openrouter.ai | https://status.mistral.ai54   β†’ The {len(provider_errors)} failed files will stay as AST stubs (still functional)55   β†’ Re-run later: python scripts/wiki_manager.py update56"""57    msg = MIMEText(body)58    msg["Subject"] = f"[SafeVixAI] {subject}"59    msg["From"] = smtp_user60    msg["To"] = alert_to61 62    try:63        with smtplib.SMTP("smtp.gmail.com", 587) as s:64            s.starttls()65            s.login(smtp_user, smtp_pass)66            s.send_message(msg)67        print(f"  [ALERT] Email sent to {alert_to}")68    except Exception as e:69        print(f"  [ALERT] Email failed: {e}")70        _print_solutions(provider_errors)71 72def _print_solutions(provider_errors):73    print("\n  === 3 WAYS TO FIX ===")74    print("  1. Rate limit β†’ wait 1hr, re-run with --delay 5")75    print("  2. Key expired β†’ refresh at openrouter.ai/keys or console.mistral.ai")76    print("  3. Service down β†’ check status pages, re-run later")77    print()78 79# ── LLM Calls ───────────────────────────────────────────────────────────────80def call_llm(prompt, or_key, ms_key, gk_key):81    """Try OpenRouter β†’ Mistral β†’ Gemini with per-provider error tracking."""82    errors = {}83    providers = [84        ("openrouter", or_key, "https://openrouter.ai/api/v1/chat/completions",85         {"model": "google/gemini-2.0-flash-lite-001", "messages": [{"role": "user", "content": prompt}], "max_tokens": 4096, "temperature": 0.3}),86        ("mistral", ms_key, "https://api.mistral.ai/v1/chat/completions",87         {"model": "mistral-small-latest", "messages": [{"role": "user", "content": prompt}], "max_tokens": 4096, "temperature": 0.3}),88    ]89    for name, key, url, payload in providers:90        if not key:91            continue92        for attempt in range(2):  # 2 retries per provider93            try:94                body = json.dumps(payload).encode("utf-8")95                headers = {"Content-Type": "application/json", "Authorization": f"Bearer {key}"}96                req = Request(url, data=body, headers=headers)97                resp = urlopen(req, timeout=60)98                data = json.loads(resp.read().decode("utf-8"))99                result = data["choices"][0]["message"]["content"]100                if result and len(result) > 100:101                    if len(result) > 8000:102                        result = result[:8000].rsplit("\n", 1)[0] + "\n"103                    return result, name, errors104            except HTTPError as e:105                errors[name] = f"HTTP {e.code} (attempt {attempt+1})"106                if e.code == 429:107                    time.sleep((attempt + 1) * 5)108                else:109                    break110            except Exception as e:111                errors[name] = str(e)112                break113 114    # Try Gemini direct as last resort115    if gk_key:116        try:117            gurl = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key={gk_key}"118            body = json.dumps({"contents": [{"parts": [{"text": prompt}]}], "generationConfig": {"maxOutputTokens": 4096, "temperature": 0.3}}).encode()119            req = Request(gurl, data=body, headers={"Content-Type": "application/json"})120            resp = urlopen(req, timeout=60)121            data = json.loads(resp.read().decode("utf-8"))122            result = data["candidates"][0]["content"]["parts"][0]["text"]123            if result and len(result) > 100:124                if len(result) > 8000:125                    result = result[:8000].rsplit("\n", 1)[0] + "\n"126                return result, "gemini", errors127        except HTTPError as e:128            errors["gemini"] = f"HTTP {e.code}"129        except Exception as e:130            errors["gemini"] = str(e)131 132    return None, None, errors133 134# ── Prompt ──────────────────────────────────────────────────────────────────135def build_prompt(name, ext, section, path, code):136    return f"""Technical documentation writer for SafeVixAI (AI road safety platform, IIT Madras Hackathon 2026).137 138Generate a comprehensive wiki page in Markdown for this module.139 140Module: `{name}{ext}` | Section: {section} | File: `{path}`141Platform: 9 LLM providers, Supabase Auth, Next.js, FastAPI, LocalHashEmbeddingFunction (SHA-256)142 143```{ext.lstrip('.')}144{code}145```146 147Generate these sections:1481. # Title1492. ## Overview (what it does, 2-3 sentences)1503. ## Architecture (where it fits)1514. ## Key Classes/Functions (table: name | params | return | description)1525. ## Dependencies (imports)1536. ## Configuration (env vars, constants)1547. ## Usage Examples (real code)1558. ## Error Handling1569. ## Related Modules157 158Rules: Use actual names from code. No TODOs. Be specific. Output ONLY markdown."""159 160# ── Main ────────────────────────────────────────────────────────────────────161def main():162    limit = 127163    delay = 3164    args = sys.argv[1:]165    for i, arg in enumerate(args):166        if arg == "--limit" and i + 1 < len(args): limit = int(args[i+1])167        if arg == "--delay" and i + 1 < len(args): delay = int(args[i+1])168 169    or_key = os.environ.get("OPENROUTER_API_KEY", "")170    ms_key = os.environ.get("MISTRAL_API_KEY", "")171    gk_key = os.environ.get("GOOGLE_API_KEY", "")172 173    if not or_key and not ms_key and not gk_key:174        print("ERROR: No LLM API keys found")175        sys.exit(1)176 177    active = [n for n, k in [("OpenRouter", or_key), ("Mistral", ms_key), ("Gemini", gk_key)] if k]178    print(f"Providers: {' β†’ '.join(active)}", flush=True)179 180    # Find stubs181    stubs = []182    for f in sorted(WIKI_CONTENT.rglob("*.md")):183        text = f.read_text(encoding="utf-8")184        if "Auto-generated:" not in text:185            continue186        src_match = re.search(r'Source: `(.+?)`', text)187        if not src_match:188            continue189        spath = src_match.group(1).replace("\\", "/")190        if (ROOT / spath).exists():191            stubs.append((f, spath))192 193    total = min(len(stubs), limit)194    print(f"Stubs: {len(stubs)} found, processing {total} (delay: {delay}s)", flush=True)195    print("=" * 50, flush=True)196 197    success, fail, consecutive_fails = 0, 0, 0198    all_errors = {}199 200    for i, (wiki_path, spath) in enumerate(stubs[:total]):201        ext = "." + spath.rsplit(".", 1)[-1]202        name = spath.rsplit("/", 1)[-1].rsplit(".", 1)[0]203        section = str(wiki_path.parent.relative_to(WIKI_CONTENT))204 205        try:206            src = (ROOT / spath).read_text(encoding="utf-8", errors="ignore")207            lines = src.split("\n")208            if len(lines) > 150:209                src = "\n".join(lines[:150]) + f"\n# ... ({len(lines)} total lines)"210        except Exception:211            print(f"[{i+1}/{total}] SKIP {name} (unreadable)", flush=True)212            continue213 214        print(f"[{i+1}/{total}] {name}{ext} ...", end=" ", flush=True)215 216        prompt = build_prompt(name, ext, section, spath, src)217        result, provider, errors = call_llm(prompt, or_key, ms_key, gk_key)218 219        if result:220            wiki_path.write_text(result, encoding="utf-8")221            success += 1222            consecutive_fails = 0223            print(f"OK ({len(result)} chars via {provider})", flush=True)224        else:225            fail += 1226            consecutive_fails += 1227            all_errors[name] = errors228            print(f"FAILED {errors}", flush=True)229 230            if consecutive_fails >= 5:231                print(f"\n5 consecutive failures β€” stopping early.", flush=True)232                send_alert_email(233                    "Wiki generation stopped β€” 5 consecutive LLM failures",234                    f"Failed at file #{i+1}: {name}{ext}\n{success} succeeded before failure.",235                    name + ext, errors236                )237                break238 239        time.sleep(delay)240 241    print("=" * 50, flush=True)242    remaining = len(stubs) - success - fail243    print(f"Results: {success} upgraded | {fail} failed | {remaining} remaining", flush=True)244 245    if fail > 0 and consecutive_fails < 5:246        send_alert_email(247            f"Wiki generation completed with {fail} failures",248            f"{success} upgraded, {fail} failed out of {total} attempted.",249            "multiple files", all_errors.get(list(all_errors.keys())[-1], {}) if all_errors else {}250        )251 252    # Clean up test script if it exists253    test_script = ROOT / "scripts" / "test_llm.py"254    if test_script.exists():255        test_script.unlink()256 257if __name__ == "__main__":258    main()259