sriharsha150's picture
Skeleton: metabolic forensics evidence engine on synthetic data
14d4764 verified
Raw
History Blame Contribute Delete
4.98 kB
"""
Metabolic Forensics β€” N-of-1 biosignal evidence engine.
Skeleton on synthetic data. The deterministic evidence pipeline is real;
the LLM narration layer is stubbed (plug in a local llama.cpp model where
marked). No personal data ships in this repo β€” privacy by construction.
"""
import numpy as np
import pandas as pd
import gradio as gr
# ---------------------------------------------------------------------------
# Synthetic demo data β€” stands in for ~/Health/data/*.jsonl (CGM/HRV/recovery)
# Real version: load the user's Ultrahuman OAuth metrics locally, never in repo.
# ---------------------------------------------------------------------------
def make_demo_data(days: int = 46, seed: int = 7) -> pd.DataFrame:
rng = np.random.default_rng(seed)
dates = pd.date_range("2026-04-19", periods=days, freq="D")
late_meal = rng.random(days) < 0.35 # hidden "cause"
glucose_spike = 110 + late_meal * 45 + rng.normal(0, 8, days) # mg/dL peak
# next-day HRV suffers after a spike (with noise + counterexamples)
hrv = 55 - late_meal * 9 + rng.normal(0, 6, days)
recovery = np.clip(70 - late_meal * 18 + rng.normal(0, 10, days), 1, 100)
alertness = np.clip(75 - late_meal * 15 + rng.normal(0, 12, days), 1, 100)
return pd.DataFrame({
"date": dates,
"late_meal": late_meal.astype(int),
"glucose_peak": glucose_spike.round(0),
"hrv": hrv.round(0),
"recovery": recovery.round(0),
"morning_alertness": alertness.round(0),
})
DF = make_demo_data()
# ---------------------------------------------------------------------------
# THE EVIDENCE ENGINE (deterministic β€” this is the moat, not the model)
# Detect an event, split days into event vs non-event, report the contrast
# AND the counterexamples (days where the pattern breaks).
# ---------------------------------------------------------------------------
QUESTIONS = {
"What precedes my low-recovery mornings?": ("recovery", "low", "late_meal"),
"What precedes my glucose spikes?": ("glucose_peak", "high", "late_meal"),
"What precedes my low-alertness mornings?":("morning_alertness", "low", "late_meal"),
}
def forensics(question: str):
metric, direction, candidate = QUESTIONS[question]
df = DF.copy()
thr = df[metric].quantile(0.25 if direction == "low" else 0.75)
event = df[metric] <= thr if direction == "low" else df[metric] >= thr
with_cand = event & (df[candidate] == 1)
base_rate = df[candidate].mean()
event_rate = df.loc[event, candidate].mean()
lift = (event_rate / base_rate) if base_rate else float("nan")
# counterexamples: event days where the candidate cause was ABSENT
counterex = df[event & (df[candidate] == 0)]
evidence = {
"question": question,
"n_days": len(df),
"n_event_days": int(event.sum()),
"candidate_signal": candidate,
"candidate_present_on_event_days_pct": round(100 * event_rate, 0),
"candidate_baseline_pct": round(100 * base_rate, 0),
"lift": round(lift, 2),
"n_counterexamples": len(counterex),
}
# ---- LLM NARRATION LAYER (stub) -------------------------------------
# Real version: hand `evidence` to a local llama.cpp ≀32B model with a
# strict prompt: narrate ONLY this evidence, surface the counterexamples,
# propose ONE testable experiment. Cannot invent associations.
narration = (
f"**Observed association** β€” on your {evidence['n_event_days']} "
f"'{question.split('my ')[-1].rstrip('?')}' days, "
f"`{candidate}` was present {evidence['candidate_present_on_event_days_pct']:.0f}% "
f"of the time vs a {evidence['candidate_baseline_pct']:.0f}% baseline "
f"(**{evidence['lift']}Γ— lift**).\n\n"
f"**Counterexamples** β€” but {evidence['n_counterexamples']} of those days had "
f"NO `{candidate}`, so this is a tendency, not a law. Don't overfit.\n\n"
f"**Next experiment** β€” deliberately vary `{candidate}` for 7 days and watch "
f"whether '{metric}' separates. That turns correlation into something testable."
)
plot_df = df[["date", metric]].rename(columns={metric: "value"})
return narration, plot_df, evidence
with gr.Blocks(title="Metabolic Forensics", theme=gr.themes.Soft()) as demo:
gr.Markdown(
"# 🩸 Metabolic Forensics\n"
"*N-of-1 biosignal **evidence engine** β€” forensics, not coaching. "
"Running on synthetic demo data.*"
)
q = gr.Dropdown(list(QUESTIONS), value=list(QUESTIONS)[0], label="Forensic question")
btn = gr.Button("Investigate", variant="primary")
out_md = gr.Markdown()
out_plot = gr.LinePlot(x="date", y="value", label="Metric over your history")
out_json = gr.JSON(label="Raw evidence (what the model is allowed to narrate)")
btn.click(forensics, q, [out_md, out_plot, out_json])
if __name__ == "__main__":
demo.launch()