Spaces:
Sleeping
Sleeping
File size: 4,037 Bytes
adb39f0 9bade7f 0802195 9bade7f adb39f0 0258ba4 adb39f0 0258ba4 adb39f0 0258ba4 adb39f0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | from __future__ import annotations
import os
import gradio as gr
from whatchanged.db import init_db
from whatchanged.inference import LlamaCppBackend
from whatchanged.ui.log_tab import build_log_tab
from whatchanged.ui.trends_tab import build_trends_tab
from whatchanged.ui.report_tab import build_report_tab
DB_PATH = os.environ.get("WC_DB", "data/whatchanged.db")
MODEL_PATH = os.environ.get("WC_MODEL", "") # local GGUF path (wins if it exists)
HF_REPO = os.environ.get("WC_HF_REPO", "zeon01/what-changed-1b") # else pull from the Hub
HF_FILE = os.environ.get("WC_HF_FILE", "MiniCPM5-1B.Q8_0.gguf")
def resolve_model_path() -> str:
"""Local WC_MODEL wins; otherwise download the published GGUF from the Hub (public,
no token needed) so the Space is self-contained on first boot."""
if MODEL_PATH and os.path.exists(MODEL_PATH):
return MODEL_PATH
if HF_REPO:
try:
from huggingface_hub import hf_hub_download
return hf_hub_download(repo_id=HF_REPO, filename=HF_FILE)
except Exception as e: # noqa: BLE001
print(f"[model] could not fetch {HF_REPO}/{HF_FILE}: {e}")
return ""
def make_backend():
path = resolve_model_path()
if not path:
return None
# Pin threads (WC_THREADS) so llama.cpp doesn't oversubscribe the host's core count on a
# 2-vCPU Space (the usual cause of absurdly slow CPU inference).
backend = LlamaCppBackend(path, n_threads=(int(os.environ.get("WC_THREADS", "0")) or None))
try:
backend._ensure() # warm-load now so a bad wheel/model degrades, never crashes mid-click
except Exception as e: # noqa: BLE001 — a model load failure must not 500 the UI
print(f"[model] load failed ({type(e).__name__}: {e}); using deterministic fallback")
return None
return backend
# When None: extraction is a no-op and the report narrative uses a deterministic
# fallback (bullet summaries joined into a plain sentence).
def maybe_seed(conn) -> None:
"""On the demo Space (WC_SEED_DEMO=1) only, populate an empty DB with a realistic
60-day decline arc so Trends/Report are non-empty on first open."""
if os.environ.get("WC_SEED_DEMO") != "1":
return
if conn.execute("SELECT COUNT(*) FROM entries").fetchone()[0] > 0:
return
try:
from scripts.seed_demo import seed
seed(conn)
print("[seed] demo data loaded")
except Exception as e: # noqa: BLE001
print(f"[seed] skipped: {e}")
# --- Off-Brand custom look: calm health palette, Inter, branded header, no Gradio footer ---
THEME = gr.themes.Soft(
primary_hue="teal", secondary_hue="cyan", neutral_hue="slate",
font=[gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"],
)
CSS = """
.gradio-container {max-width: 880px !important; margin: 0 auto !important;}
#wc-header {background: linear-gradient(135deg,#0d9488,#0e7490); color:#fff;
padding:22px 26px; border-radius:16px; margin-bottom:6px;}
#wc-header h1 {margin:0; font-size:26px; font-weight:700; color:#fff;}
#wc-header p {margin:6px 0 0; opacity:.92; font-size:14px; color:#fff;}
#wc-header .wc-pill {display:inline-block; background:rgba(255,255,255,.18);
padding:3px 11px; border-radius:999px; font-size:12px; margin-top:11px;}
footer {display:none !important;}
"""
HEADER = (
'<div id="wc-header"><h1>📋 What Changed</h1>'
"<p>A private, on-device Parkinson's diary — describe the day, and a local fine-tuned 1B "
"structures it into a doctor-ready summary.</p>"
'<span class="wc-pill">Runs 100% locally · fine-tuned 1B · llama.cpp · not medical advice</span>'
"</div>"
)
def build_app():
conn = init_db(DB_PATH)
maybe_seed(conn)
backend = make_backend()
with gr.Blocks(title="What Changed", theme=THEME, css=CSS) as demo:
gr.HTML(HEADER)
build_log_tab(conn, backend)
build_trends_tab(conn)
build_report_tab(conn, backend)
return demo
if __name__ == "__main__":
build_app().launch()
|