""" DaisyChain β€” interactive routing demo (HuggingFace Space). Paste DNA; the learned router reads how *surprised* each ~74M specialist is (bits/base) plus its hidden state and hands the sequence to its home specialist β€” then that specialist streams a continuation live. Styled after the Modular-Mind panel: animated routing cards, a first-run loading notice, live token streaming. Every handler is a generator. """ import html as _h import os import json import gradio as gr # ZeroGPU: @spaces.GPU allocates a GPU only for the decorated call. Falls back to a no-op # decorator when `spaces` isn't installed (local / plain CPU). try: import spaces _gpu = spaces.GPU except Exception: def _gpu(fn=None, **kw): return fn if callable(fn) else (lambda f: f) from daisychain import DaisyChain HERE = os.path.dirname(os.path.abspath(__file__)) MODEL_REPO = os.environ.get("DAISYCHAIN_REPO", "DaisyChainAI/daisychain-genomics") DEVICE = os.environ.get("DAISYCHAIN_DEVICE", "cpu") # code + tokenizer + router are bundled here; pull the big specialist weights from the # model repo on first launch (keeps the Space repo light). if not os.path.exists(os.path.join(HERE, "eukaryote", "model.safetensors")): try: from huggingface_hub import snapshot_download snapshot_download(MODEL_REPO, local_dir=HERE, allow_patterns=["*/model.safetensors", "tokenizer.json", "router2.pt"]) except Exception: pass _DC = {"m": None} # lazy-loaded so CUDA is never touched at import _WARMED = {"done": False} # so the "loading" notice only shows on the first run EMOJI = {"eukaryote": "🧬 Eukaryote", "prokaryote": "🦠 Prokaryote", "mrna": "πŸ“œ mRNA", "mrna_splice": "βœ‚οΈ mRNA-splice"} COLOR = {"eukaryote": "#7c5cff", "prokaryote": "#22b8cf", "mrna": "#e64980", "mrna_splice": "#37b24d"} DESC = DaisyChain.DESCRIPTIONS def _moe(): if _DC["m"] is None: _DC["m"] = DaisyChain(root=HERE, device=DEVICE) return _DC["m"] # ---- HTML rendering (ported from the Modular-Mind panel) -------------------------- _CSS = """""" def _wrap(body): return _CSS + "
" + body + "
" def _esc(s): return _h.escape(s or "").replace("\n", "
") def _notice(action="Routing"): if not _WARMED["done"]: try: gr.Info("First run β€” loading the four ~74M specialists (~20–40s on CPU). After this it's quick.") except Exception: pass return _wrap(f"
⏳ Loading the four ~74M specialists + {action.lower()}… " "first run can take ~20–40s on CPU; every run after is fast.
") return _wrap(f"
⏳ {action}…
") def _msg(title, body): return _wrap(f"
{title}
{body}
") def _cards(bpb, winner=None): """One animated card per specialist: surprise (bits/base), confidence bar, winner badge + glow. bpb values may be None (not computed yet). Lower bits/base = more 'at home' = fuller bar.""" cells = [] doms = list(bpb.keys()) for i, n in enumerate(doms): c = COLOR.get(n, "#9b59b6") v = bpb[n] win = (n == winner) conf = max(0.0, min(1.0, (2.02 - v) / 0.5)) if v is not None else 0.0 # ~1.52..2.02 -> 1..0 style = f"border-color:{c};box-shadow:0 0 16px {c}40" if win else "" badge = f"ROUTED βœ“" if win else "" meta = (f"{DESC.get(n,'')}
{v:.3f} bits/base (lower = more at home)" if v is not None else f"{DESC.get(n,'')}
…") bar = (f"
" f"
confidence {conf*100:.0f}%
") if v is not None else \ "
…
" cells.append( f"
{badge}" f"
{EMOJI.get(n, n)}
" f"
{meta}
{bar}
") if i < len(doms) - 1: cells.append("") return "
" + "".join(cells) + "
" def _gen_box(prompt, gen, live=False): caret = "" if live else "" return (f"
{_esc(prompt)}" f"{_esc(gen)}{caret}
") FOOTER = ("Four ~74M DNA/RNA specialists (β‰ˆ295M total, under Carbon-500M), each distilled " "per-domain from Carbon-500M. A learned router reads every specialist's surprise + hidden " "state and routes to the home specialist β€” held-out routing accuracy 94.8%. Only one " "specialist runs per query (~7Γ— cheaper than the 500M monolith).") # ---- handler ---------------------------------------------------------------------- @_gpu(duration=120) def route_run(seq, n_bases, do_gen): yield _notice("Routing & generating") seq = (seq or "").strip() if len(seq) < 18: yield _msg("🧬 Enter a DNA sequence", "Paste at least 18 bases (A/C/G/T) β€” try an example below.") return dc = _moe() doms = dc.domains bpb = {d: None for d in doms} # progressively reveal each specialist's surprise (the chain lighting up) sc, hd = dc._scores_hidden(seq) for d in doms: bpb[d] = sc[d] / 6 / 0.6931 yield _wrap("
πŸ”— Sending the sequence down the chain…
" + _cards(bpb)) home, _ = dc.route(seq) c = COLOR.get(home, "#9b59b6") head = (f"
🧭 Routed to {EMOJI.get(home, home)}" f" β€” the specialist most at home with your sequence
" + _cards(bpb, winner=home)) if do_gen: for gen in dc.generate_stream(home, length=int(n_bases), temperature=0.9, top_k=20, prompt=seq[-60:]): yield _wrap(head + _gen_box(seq[-60:], gen, live=True)) _WARMED["done"] = True yield _wrap(head + _gen_box(seq[-60:], gen, live=False) + f"
{FOOTER}
") else: _WARMED["done"] = True yield _wrap(head + f"
{FOOTER}
") STATS_HTML = _wrap( "
πŸ“Š DaisyChain vs Carbon-500M β€” the fair baseline
" "
" "
94.8%
" "
routing accuracy
(held-out)
" "
β‰ˆ295M
" "
total params
(4 Γ— ~74M) < Carbon-500M
" "
~7Γ—
" "
cheaper per query
(one 74M specialist active)
" "
" "" "" "" "" "
metricDaisyChainCarbon-500M
Likelihood β€” bits/base (↓ better)1.861.75
Seq-recovery, eukaryote (↑ better)31.8%42.2%
Seq-recovery, bacteria (↑ better)34.0%49.5%
" "
Four ~74M specialists (β‰ˆ295M total, under Carbon-500M); only one runs per " "query, so it's ~7Γ— cheaper per token. Behind the 500M / 1T-token monolith but within striking " "distance β€” the gap is concentrated in the structured domains (mRNA, bacteria) and keeps closing " "with more per-domain training. Same protocols as Carbon's eval suite (sequence recovery; per-base " "likelihood). Carbon-500M is the right yardstick for a sub-500M modular set, not the 3B flagship.
") HERO = """# 🌼 DaisyChain β€” a modular genomic mind **Four ~74M DNA/RNA specialists (β‰ˆ295M total, under Carbon-500M)** β€” 🧬 Eukaryote, 🦠 Prokaryote, πŸ“œ mRNA, βœ‚οΈ mRNA-splice β€” each **distilled per-domain from Carbon-500M**. A learned router reads how *surprised* each specialist is by your sequence (bits/base) plus its hidden state, and hands the work to its **home specialist**. Paste DNA and watch it route in real time. > ℹ️ *Research demo: tiny specialists trained on a slice of the Carbon corpus β€” the **routing** (which > specialist is most at home) and the **sub-500M modular architecture** are the point, not Carbon-level > generation.*""" def build(): with gr.Blocks(title="DaisyChain β€” modular genomic mind", theme=gr.themes.Soft()) as demo: with gr.Accordion("🌼 DaisyChain β€” independent DNA specialists behind a learned router", open=True): gr.Markdown(HERO) with gr.Row(): seq = gr.Textbox(label="DNA sequence", lines=3, scale=4, placeholder="ACGT… (eukaryotic, bacterial, mRNA, or splice-site DNA)") n = gr.Slider(60, 300, value=150, step=30, label="generate bases", scale=1) with gr.Row(): gen_ck = gr.Checkbox(value=True, label="stream a continuation from the routed specialist") btn = gr.Button("πŸ”— Route through the DaisyChain", variant="primary") out = gr.HTML(_wrap(_cards({d: None for d in DaisyChain.DESCRIPTIONS}))) btn.click(route_run, [seq, n, gen_ck], out) try: ex = json.load(open(os.path.join(HERE, "examples.json"))) gr.Examples([[v, 150, True] for v in ex.values()], inputs=[seq, n, gen_ck], label="Example sequences (one per domain)") except Exception: pass gr.HTML(STATS_HTML) return demo if __name__ == "__main__": build().launch()