"""
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)
"
"
"
"| metric | DaisyChain | Carbon-500M |
"
"| Likelihood β bits/base (β better) | 1.86 | 1.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()