| """ |
| 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 math |
|
|
| import gradio as gr |
|
|
| |
| |
| 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") |
|
|
| |
| |
| |
| if not os.path.exists(os.path.join(HERE, "eukaryote", "model.safetensors")): |
| from huggingface_hub import snapshot_download |
| snapshot_download(MODEL_REPO, local_dir=HERE, |
| token=os.environ.get("HF_TOKEN"), |
| allow_patterns=["*/model.safetensors", "tokenizer.json", "router2.pt"]) |
|
|
| _DC = {"m": None} |
| _WARMED = {"done": False} |
|
|
| EMOJI = {"eukaryote": "𧬠Eukaryote", "prokaryote": "π¦ Prokaryote", |
| "mrna": "π mRNA", "mrna_splice": "βοΈ mRNA-splice"} |
| |
| COLOR = {"eukaryote": "#5b4bb0", "prokaryote": "#1f7a99", |
| "mrna": "#b03a63", "mrna_splice": "#317f3f"} |
| DESC = DaisyChain.DESCRIPTIONS |
|
|
|
|
| def _moe(): |
| if _DC["m"] is None: |
| _DC["m"] = DaisyChain(root=HERE, device=DEVICE) |
| return _DC["m"] |
|
|
|
|
| |
| |
| |
| |
| _CSS = """<style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&family=JetBrains+Mono:wght@400;500;700&display=swap'); |
| :root{--paper:#f7f5ee;--paper2:#f2efe2;--ink:#1f1f1d;--muted:#8c918b;--hairline:#d6d3c4; |
| --green:#317f3f;--green2:#2a5931;--gold:#c79a2e;--gold2:#9c7714} |
| .dcx{font-family:"Inter","Helvetica Neue",sans-serif;font-weight:300;color:var(--ink); |
| font-size:13px;line-height:1.7;margin:4px 0} |
| .dcx .mono{font-family:"JetBrains Mono",ui-monospace,monospace} |
| .dcx .note{background:var(--paper2);border:1px solid var(--hairline);border-radius:4px; |
| padding:12px 14px;color:#5a5a55;font-size:13px} |
| .dcx .h{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:12px;font-weight:500; |
| letter-spacing:.16em;text-transform:uppercase;color:var(--ink);margin:6px 0 12px; |
| padding-bottom:8px;border-bottom:1px solid var(--hairline)} |
| .dcx .p{color:var(--muted)} |
| .dcx .g{color:var(--green2);font-weight:600} |
| .dcx .chain{display:flex;gap:0;align-items:stretch;flex-wrap:wrap;margin:8px 0} |
| .dcx .link{align-self:center;color:var(--hairline);font-size:18px;margin:0 2px 22px;font-weight:700} |
| .dcx .card{flex:1;min-width:180px;background:var(--paper);border:1px solid var(--hairline); |
| border-radius:4px;padding:12px 13px;position:relative;overflow:hidden;transition:box-shadow .3s,border-color .3s} |
| .dcx .card .nm{font-family:"JetBrains Mono",ui-monospace,monospace;font-weight:500;font-size:12px; |
| letter-spacing:.06em;text-transform:uppercase} |
| .dcx .card .meta{color:var(--muted);font-size:11px;margin-top:4px;min-height:28px;line-height:1.45} |
| .dcx .card .bar{height:6px;background:var(--paper2);border:1px solid var(--hairline);border-radius:99px;margin-top:9px;overflow:hidden} |
| .dcx .card .fill{height:100%;border-radius:99px;animation:dcxw .7s ease} |
| .dcx .card .pct{font-size:10px;color:var(--muted);margin-top:5px;letter-spacing:.04em;text-transform:uppercase;font-family:"JetBrains Mono",monospace} |
| .dcx .badge{position:absolute;top:9px;right:10px;font-family:"JetBrains Mono",monospace;font-size:9px; |
| font-weight:700;letter-spacing:.12em;padding:3px 8px;border-radius:99px;color:var(--paper);background:var(--green)} |
| @keyframes dcxw{from{width:0}} |
| .dcx .gen{background:var(--paper2);border:1px solid var(--hairline);border-radius:4px;padding:13px 15px; |
| margin:12px 0;font-size:14px;line-height:1.8;font-family:"JetBrains Mono",ui-monospace,monospace;word-break:break-all} |
| .dcx .caret{display:inline-block;width:8px;height:16px;border-radius:1px;background:var(--green); |
| margin-left:2px;vertical-align:text-bottom;animation:dcxb .8s steps(1) infinite} |
| @keyframes dcxb{50%{opacity:0}} |
| .dcx .sub{color:var(--muted);font-size:12px;line-height:1.6;margin-top:10px} |
| .dcx .stats{display:flex;gap:0;flex-wrap:wrap;margin:12px 0;border:1px solid var(--hairline);border-radius:4px;overflow:hidden} |
| .dcx .stat{flex:1;min-width:120px;text-align:center;background:var(--paper);padding:16px 10px;border-right:1px solid var(--hairline)} |
| .dcx .stat:last-child{border-right:none} |
| .dcx .stat .v{font-family:"JetBrains Mono",monospace;font-size:26px;font-weight:700;line-height:1;color:var(--green2)} |
| .dcx .stat .l{font-size:10px;color:var(--muted);margin-top:8px;letter-spacing:.06em;text-transform:uppercase;line-height:1.4} |
| .dcx table{border-collapse:collapse;width:100%;margin:10px 0;font-size:12.5px} |
| .dcx th,.dcx td{border:1px solid var(--hairline);padding:8px 11px;text-align:left} |
| .dcx th{background:var(--paper2);color:var(--ink);font-family:"JetBrains Mono",monospace;font-weight:500; |
| font-size:10px;letter-spacing:.1em;text-transform:uppercase} |
| .dcx td.n{text-align:right;font-variant-numeric:tabular-nums;font-family:"JetBrains Mono",monospace} |
| /* --- live 2D double-helix (our own take on a base-by-base DNA viz) --- */ |
| .dcx .helixwrap{background:var(--paper2);border:1px solid var(--hairline);border-radius:4px;padding:8px 12px;margin:12px 0;overflow-x:auto} |
| .dcx .helix-svg{display:block;margin:1px 0} |
| .dcx .hx-strand{fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;opacity:.5} |
| .dcx .hx-strand.back{opacity:.24} |
| .dcx .hx-rung{stroke:var(--hairline);stroke-width:1} |
| .dcx .hx-rung.user{stroke:#e6e3d6} |
| .dcx .hx-base{font-family:"JetBrains Mono",monospace;font-size:9px;font-weight:700;text-anchor:middle;dominant-baseline:central} |
| .dcx .hx-legend{display:flex;gap:13px;flex-wrap:wrap;font-family:"JetBrains Mono",monospace;font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:2px 0 4px} |
| .dcx .hx-dot{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px;vertical-align:middle} |
| /* --- tokenization tracks (our take on carbon-tokenization-02): per-base + 6-mer --- */ |
| .dcx .seqtrack{font-family:"JetBrains Mono",monospace;font-size:11px;background:var(--paper);border:1px solid var(--hairline);border-radius:4px;padding:8px 10px;display:flex;flex-wrap:wrap;gap:1px;margin:8px 0 2px} |
| .dcx .seqb{display:inline-flex;align-items:center;justify-content:center;width:18px;height:20px;border-radius:2px;color:#fff;font-weight:500} |
| .dcx .seqb.A{background:#1A7A40}.dcx .seqb.T{background:#b00020}.dcx .seqb.C{background:#2c5aa0}.dcx .seqb.G{background:#b8862c} |
| .dcx .tkrow{display:flex;gap:14px;align-items:baseline;margin:12px 0 2px;flex-wrap:wrap} |
| .dcx .tklabel{font-family:"JetBrains Mono",monospace;font-size:9.5px;font-weight:500;color:#5b5b56;text-transform:uppercase;letter-spacing:1.6px} |
| .dcx .tkstat{font-family:"JetBrains Mono",monospace;font-size:10px;color:var(--muted);letter-spacing:.5px} |
| .dcx .tkstat .n{font-weight:600;color:var(--green2)} |
| .dcx .tokrow{display:flex;flex-wrap:wrap;align-items:center;gap:0} |
| .dcx .tok{display:inline-flex;align-items:center;font-family:"JetBrains Mono",monospace;font-size:11px;letter-spacing:.5px;padding:4px 8px;margin:2px;border:1px solid #ccc;border-radius:3px;background:#fff;color:var(--ink)} |
| .dcx .tok.kmer{background:rgba(49,127,63,.10);border-color:rgba(49,127,63,.5);color:var(--green2);font-weight:500} |
| /* --- editorial hero banner (dotted texture + faint green edge stripes) --- */ |
| .dc-banner{position:relative;overflow:hidden;border:1px solid var(--hairline);border-radius:6px;margin:2px 0 6px; |
| background:radial-gradient(circle at 22% 32%,rgba(0,0,0,.06),transparent 1px), |
| radial-gradient(circle at 78% 64%,rgba(0,0,0,.055),transparent 1px), |
| linear-gradient(90deg,rgba(49,127,63,.04),transparent 32%,transparent 68%,rgba(199,154,46,.05)), |
| var(--paper); |
| background-size:7px 7px,11px 11px,auto,auto} |
| .dc-binner{position:relative;padding:22px 26px;font-family:"JetBrains Mono",ui-monospace,monospace} |
| .dc-ident{display:flex;align-items:center;gap:11px;margin-bottom:16px} |
| .dc-mark{font-size:30px;line-height:1} |
| .dc-title{font-size:13px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--ink)} |
| .dc-path{font-size:10px;font-weight:400;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);margin-top:2px} |
| .dc-word{font-family:"JetBrains Mono",monospace;font-size:40px;font-weight:700;letter-spacing:-.01em;color:var(--ink);line-height:1.05;margin:4px 0 6px} |
| .dc-word .dot{color:var(--gold)} |
| .dc-tag{font-family:"Inter",sans-serif;font-weight:300;font-size:13px;color:#5a5a55;max-width:560px;line-height:1.6} |
| .dc-motif{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-top:18px} |
| .dc-chip{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.06em;text-transform:uppercase; |
| background:var(--paper2);border:1px solid var(--hairline);border-radius:99px;padding:5px 11px;color:var(--ink)} |
| .dc-tie{color:var(--green);font-size:13px;font-weight:700} |
| .dc-rule{height:1px;background:var(--hairline);margin:14px 0} |
| </style>""" |
|
|
|
|
| def _wrap(body): |
| return _CSS + "<div class='dcx'>" + body + "</div>" |
|
|
|
|
| def _esc(s): |
| return _h.escape(s or "").replace("\n", "<br>") |
|
|
|
|
| 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"<div class='note'>β³ Loading the four ~74M specialists + {action.lower()}β¦ " |
| "first run can take ~20β40s on CPU; every run after is fast.</div>") |
| return _wrap(f"<div class='note'>β³ {action}β¦</div>") |
|
|
|
|
| def _msg(title, body): |
| return _wrap(f"<div class='note'><b>{title}</b><br>{body}</div>") |
|
|
|
|
| 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 |
| style = f"border-color:{c};box-shadow:0 0 16px {c}40" if win else "" |
| badge = f"<span class='badge' style='background:{c}'>ROUTED β</span>" if win else "" |
| meta = (f"{DESC.get(n,'')}<br>{v:.3f} bits/base (lower = more at home)" |
| if v is not None else f"{DESC.get(n,'')}<br>β¦") |
| bar = (f"<div class='bar'><div class='fill' style='width:{conf*100:.1f}%;background:{c}'></div></div>" |
| f"<div class='pct'>confidence {conf*100:.0f}%</div>") if v is not None else \ |
| "<div class='bar'></div><div class='pct'>β¦</div>" |
| cells.append( |
| f"<div class='card' style='{style}'>{badge}" |
| f"<div class='nm' style='color:{c}'>{EMOJI.get(n, n)}</div>" |
| f"<div class='meta'>{meta}</div>{bar}</div>") |
| if i < len(doms) - 1: |
| cells.append("<div class='link'>β¬</div>") |
| return "<div class='chain'>" + "".join(cells) + "</div>" |
|
|
|
|
| def _gen_box(prompt, gen, live=False): |
| caret = "<span class='caret'></span>" if live else "" |
| return (f"<div class='gen'><span class='p'>{_esc(prompt)}</span>" |
| f"<span class='g'>{_esc(gen)}</span>{caret}</div>") |
|
|
|
|
| |
| |
| |
| |
| |
| _COMP = {"A": "T", "T": "A", "C": "G", "G": "C", "N": "N"} |
| |
| _BASE_COL = {"A": "#1A7A40", "T": "#b00020", "C": "#2c5aa0", "G": "#b8862c"} |
| _USER_COL = "#bdbaa9" |
| _HX_SP, _HX_AMP, _HX_YC, _HX_ROWH, _HX_TURN, _HX_PERROW = 14, 12, 22, 48, 10.5, 46 |
|
|
|
|
| def _hx_strand(n, sign): |
| pts = [] |
| for s in range(n * 4 + 1): |
| t = s / 4 |
| x = t * _HX_SP + _HX_SP / 2 |
| ang = (t + 0.5) * 2 * math.pi / _HX_TURN |
| y = _HX_YC + sign * _HX_AMP * math.sin(ang) |
| pts.append(f"{x:.1f},{y:.1f}") |
| return " ".join(pts) |
|
|
|
|
| def _hx_row(bases, start, user_len, accent): |
| n = len(bases) |
| w = n * _HX_SP + 6 |
| out = [f"<svg class='helix-svg' width='{w}' height='{_HX_ROWH}' " |
| f"viewBox='0 0 {w} {_HX_ROWH}' xmlns='http://www.w3.org/2000/svg'>", |
| f"<polyline class='hx-strand' style='stroke:{accent}' points='{_hx_strand(n,1)}'/>", |
| f"<polyline class='hx-strand back' style='stroke:{accent}' points='{_hx_strand(n,-1)}'/>"] |
| for i in range(n): |
| x = i * _HX_SP + _HX_SP / 2 |
| ang = (i + 0.5) * 2 * math.pi / _HX_TURN |
| yt = _HX_YC + _HX_AMP * math.sin(ang); yb = _HX_YC - _HX_AMP * math.sin(ang) |
| kind = "user" if start + i < user_len else "gen" |
| out.append(f"<line class='hx-rung {kind}' x1='{x:.1f}' y1='{yt:.1f}' x2='{x:.1f}' y2='{yb:.1f}'/>") |
| for i in range(n): |
| x = i * _HX_SP + _HX_SP / 2 |
| ang = (i + 0.5) * 2 * math.pi / _HX_TURN |
| yt = _HX_YC + _HX_AMP * math.sin(ang); yb = _HX_YC - _HX_AMP * math.sin(ang) |
| b = bases[i]; comp = _COMP.get(b, "N") |
| gen = start + i >= user_len |
| col = _BASE_COL.get(b, "#999") if gen else _USER_COL |
| ccol = _BASE_COL.get(comp, "#999") if gen else _USER_COL |
| op = "1" if gen else ".6" |
| out.append(f"<text class='hx-base' x='{x:.1f}' y='{yt:.1f}' style='fill:{col};opacity:{op}'>{b}</text>") |
| out.append(f"<text class='hx-base' x='{x:.1f}' y='{yb:.1f}' style='fill:{ccol};opacity:{op}'>{comp}</text>") |
| out.append("</svg>") |
| return "".join(out) |
|
|
|
|
| def _helix(prompt, gen, accent, live=False): |
| bases = [c for c in (prompt + gen) if c in "ACGTN"] |
| user_len = len([c for c in prompt if c in "ACGTN"]) |
| rows, i = [], 0 |
| while i < len(bases): |
| rows.append(_hx_row(bases[i:i + _HX_PERROW], i, user_len, accent)) |
| i += _HX_PERROW |
| caret = "<span class='caret'></span>" if live else "" |
| legend = ("<div class='hx-legend'>" |
| + "".join(f"<span><span class='hx-dot' style='background:{_BASE_COL[b]}'></span>{b}</span>" for b in "ACGT") |
| + f"<span><span class='hx-dot' style='background:{_USER_COL}'></span>your input</span></div>") |
| return f"<div class='helixwrap'>{''.join(rows) or ' '}{caret}</div>{legend}" |
|
|
|
|
| def _seq_track(gen): |
| """Per-base colored track of the generated bases (our take on the tokenization demo).""" |
| cells = "".join(f"<span class='seqb {c}'>{c}</span>" for c in gen if c in "ACGT") |
| return f"<div class='seqtrack'>{cells or ' '}</div>" |
|
|
|
|
| def _kmer_strip(gen): |
| """The generated sequence cut into our model's actual non-overlapping 6-mer tokens.""" |
| s = "".join(c for c in gen if c in "ACGTN") |
| toks = [s[i:i + 6] for i in range(0, len(s) - len(s) % 6, 6)] |
| chips = "".join(f"<span class='tok kmer'>{t}</span>" for t in toks) |
| head = ("<div class='tkrow'><span class='tklabel'>6-mer tokens</span>" |
| f"<span class='tkstat'>tokens <span class='n'>{len(toks)}</span></span>" |
| f"<span class='tkstat'>bases <span class='n'>{len(s)}</span></span>" |
| "<span class='tkstat'>6 bases / token</span></div>") |
| return head + f"<div class='tokrow'>{chips}</div>" |
|
|
|
|
| FOOTER = ("Four ~74M DNA/RNA specialists (β295M total, <b>under Carbon-500M</b>), 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 <b>100.0%</b>. Only one " |
| "specialist runs per query (~7Γ cheaper than the 500M monolith).") |
|
|
|
|
| |
| @_gpu(duration=120) |
| def route_run(seq, n_bases, do_gen, decode="auto"): |
| 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} |
| |
| sc, hd = dc._scores_hidden(seq) |
| for d in doms: |
| bpb[d] = sc[d] / 6 / 0.6931 |
| yield _wrap("<div class='h'>π Sending the sequence down the chainβ¦</div>" + _cards(bpb)) |
| home, _ = dc.route(seq) |
| c = COLOR.get(home, "#9b59b6") |
| head = (f"<div class='h'>π§ Routed to <span style='color:{c}'>{EMOJI.get(home, home)}</span>" |
| f" β the specialist most at home with your sequence</div>" + _cards(bpb, winner=home)) |
| if do_gen: |
| |
| |
| |
| dl = (decode or "").lower() |
| greedy = "argmax" in dl |
| feed_ctx = seq |
| ctx = seq[-48:] |
| mode = "base-pair Β· FNS argmax" if greedy else "base-pair Β· FNS sampled" |
| hxhead = (f"<div class='h'>𧬠{EMOJI.get(home, home)} β building the strand base-by-base " |
| f"<span style='color:var(--muted)'>({mode})</span></div>") |
| rawhdr = "<div class='h'>raw sequence β select to copy</div>" |
| |
| |
| stream = dc.generate_baselevel_stream(home, length=int(n_bases), temperature=1.0, |
| top_p=0.9, prompt=feed_ctx, greedy=greedy) |
| for gen in stream: |
| yield _wrap(head + hxhead + _helix(ctx, gen, c, live=True) |
| + _seq_track(gen) + _kmer_strip(gen) |
| + rawhdr + _gen_box(ctx, gen, live=True)) |
| _WARMED["done"] = True |
| gennote = ("<div class='sub'>π§ͺ <b>Generation is exploratory</b> β these ~74M specialists are " |
| "trained on a slice of the corpus, so sampled DNA is low-complexity (and splice / " |
| "bacterial domains are genuinely AT-rich). The <b>routing</b> and per-base likelihood " |
| "are the result here, not Carbon-level generation.</div>") |
| yield _wrap(head + hxhead + _helix(ctx, gen, c, live=False) |
| + _seq_track(gen) + _kmer_strip(gen) |
| + rawhdr + _gen_box(ctx, gen, live=False) |
| + gennote + f"<div class='sub'>{FOOTER}</div>") |
| else: |
| _WARMED["done"] = True |
| yield _wrap(head + f"<div class='sub'>{FOOTER}</div>") |
|
|
|
|
| STATS_HTML = _wrap( |
| "<div class='h'>π DaisyChain vs Carbon-500M β the fair baseline</div>" |
| "<div class='stats'>" |
| "<div class='stat'><div class='v' style='color:#37b24d'>100.0%</div>" |
| "<div class='l'>routing accuracy<br>(held-out)</div></div>" |
| "<div class='stat'><div class='v' style='color:#7c5cff'>β295M</div>" |
| "<div class='l'>total params<br>(4 Γ ~74M) < Carbon-500M</div></div>" |
| "<div class='stat'><div class='v' style='color:#22b8cf'>~7Γ</div>" |
| "<div class='l'>cheaper per query<br>(one 74M specialist active)</div></div>" |
| "</div>" |
| "<table><tr><th>metric</th><th>DaisyChain</th><th>Carbon-500M</th></tr>" |
| "<tr><td>Likelihood β bits/base, base-pair FNS (β better)</td><td class='n'>1.88</td><td class='n'>1.79</td></tr>" |
| "<tr><td>Seq-recovery, eukaryote β FNS (β better)</td><td class='n'>31.5%</td><td class='n'>38.9%</td></tr>" |
| "<tr><td>Seq-recovery, bacteria β FNS (β better)</td><td class='n'>40.9%</td><td class='n'>54.1%</td></tr>" |
| "</table>" |
| "<div class='sub'>Four ~74M specialists (β295M total, <b>under Carbon-500M</b>); 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.</div>") |
|
|
|
|
| BANNER = _CSS + """ |
| <div class='dcx'><div class='dc-banner'><div class='dc-binner'> |
| <div class='dc-ident'> |
| <span class='dc-mark'>πΌ</span> |
| <div> |
| <div class='dc-title'>DAISYCHAIN</div> |
| <div class='dc-path'>DAISYCHAINAI / GENOMICS Β· ROUTED DNA SPECIALISTS</div> |
| </div> |
| </div> |
| <div class='dc-word'>DaisyChain<span class='dot'>.</span></div> |
| <div class='dc-tag'>A modular genomic mind. Four dense ~74M DNA/RNA specialists |
| (≈295M total, <b>under Carbon-500M</b>), each distilled per-domain from Carbon-500M. |
| A learned router reads how <i>surprised</i> each specialist is by your sequence |
| (bits/base) plus its hidden state, then hands the work to its home specialist β |
| held-out routing accuracy <b>100.0%</b>. Watch it route in real time.</div> |
| <div class='dc-motif'> |
| <span class='dc-chip'>𧬠Eukaryote</span><span class='dc-tie'>β</span> |
| <span class='dc-chip'>π¦ Prokaryote</span><span class='dc-tie'>β</span> |
| <span class='dc-chip'>π mRNA</span><span class='dc-tie'>β</span> |
| <span class='dc-chip'>βοΈ mRNA-splice</span> |
| </div> |
| </div></div></div>""" |
|
|
| |
| |
| |
| _PAGE_CSS = """ |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&family=JetBrains+Mono:wght@400;500;700&display=swap'); |
| .gradio-container, .gradio-container.dark, .dark, body, body.dark{ |
| --body-background-fill:#f7f5ee!important; |
| --background-fill-primary:#f7f5ee!important; |
| --background-fill-secondary:#f2efe2!important; |
| --block-background-fill:#fbfaf4!important; |
| --block-label-background-fill:#f2efe2!important; |
| --input-background-fill:#fffdf6!important; |
| --body-text-color:#1f1f1d!important; |
| --body-text-color-subdued:#5a5a55!important; |
| --block-title-text-color:#1f1f1d!important; |
| --block-label-text-color:#5a5a55!important; |
| --block-info-text-color:#5a5a55!important; |
| --border-color-primary:#d6d3c4!important; |
| --neutral-50:#f7f5ee!important; |
| --table-even-background-fill:#fbfaf4!important; |
| --table-odd-background-fill:#f2efe2!important; |
| --table-row-focus:#eef3e9!important; |
| --table-text-color:#1f1f1d!important; |
| background:#f7f5ee!important; |
| color:#1f1f1d!important; |
| } |
| /* Examples dataset table rows (were rendering black in dark mode) */ |
| .gradio-container .gr-samples-table, .gradio-container [class*='dataset'] table, |
| .gradio-container [class*='dataset'] td, .gradio-container [class*='dataset'] tr, |
| .gradio-container [class*='dataset'] tbody{background:#fbfaf4!important;color:#1f1f1d!important} |
| .gradio-container [class*='dataset'] tr:nth-child(even) td{background:#f2efe2!important} |
| /* Radio / checkbox options (were rendering black in dark mode) */ |
| .gradio-container [class*='radio'] label, .gradio-container fieldset label, |
| .gradio-container [class*='checkbox'] label, .gradio-container .wrap label{ |
| background:#fbfaf4!important;color:#1f1f1d!important;border:1px solid #d6d3c4!important} |
| .gradio-container [class*='radio'] label *, .gradio-container fieldset label *, |
| .gradio-container [class*='checkbox'] label *{color:#1f1f1d!important} |
| .gradio-container input[type=radio],.gradio-container input[type=checkbox]{accent-color:#317f3f!important} |
| .gradio-container{font-family:"Inter","Helvetica Neue",sans-serif!important;max-width:1080px!important} |
| /* force any Gradio-rendered label / markdown / example text to ink, never white */ |
| .gradio-container label, .gradio-container .prose, .gradio-container p, |
| .gradio-container span, .gradio-container td, .gradio-container th, |
| .gradio-container .gr-text-input, .gradio-container input, .gradio-container textarea{color:#1f1f1d!important} |
| .gradio-container input::placeholder, .gradio-container textarea::placeholder{color:#9c9989!important} |
| footer{display:none!important} |
| .gr-button-primary, button.primary{background:#317f3f!important;border:1px solid #2a5931!important;color:#f7f5ee!important; |
| font-family:"JetBrains Mono",monospace!important;letter-spacing:.08em!important;text-transform:uppercase!important;font-size:12px!important} |
| .gr-button-primary:hover, button.primary:hover{background:#2a5931!important} |
| .gr-button-primary *, button.primary *{color:#f7f5ee!important} |
| """ |
|
|
|
|
| def build(): |
| theme = gr.themes.Default(primary_hue="green", neutral_hue="stone", |
| font=[gr.themes.GoogleFont("Inter"), "sans-serif"], |
| font_mono=[gr.themes.GoogleFont("JetBrains Mono"), "monospace"]) |
| |
| _force_light = ("() => { const u = new URL(window.location.href);" |
| " if (u.searchParams.get('__theme') !== 'light') {" |
| " u.searchParams.set('__theme','light'); window.location.replace(u.href); } }") |
| with gr.Blocks(title="DaisyChain β modular genomic mind", theme=theme, css=_PAGE_CSS, |
| js=_force_light) as demo: |
| gr.HTML(BANNER) |
| 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=90, step=30, label="GENERATE BASES", scale=1) |
| with gr.Row(): |
| gen_ck = gr.Checkbox(value=True, label="stream a continuation from the routed specialist") |
| decode = gr.Radio(["base-pair (FNS)", "greedy (argmax)"], value="base-pair (FNS)", |
| label="DECODING", scale=1, |
| info="base-pair (FNS) = Carbon-style: each base sampled from the marginalized per-position distribution (base-pair control, no 6-mer repeat loops); argmax = deterministic best guess (matches recovery, collapses over long spans)") |
| btn = gr.Button("π Route through the DaisyChain", variant="primary") |
| out = gr.HTML(_wrap("<div class='h'>The chain Β· paste a sequence to light it up</div>" |
| + _cards({d: None for d in DaisyChain.DESCRIPTIONS}))) |
| btn.click(route_run, [seq, n, gen_ck, decode], out) |
| try: |
| ex = json.load(open(os.path.join(HERE, "examples.json"))) |
| gr.Examples([[v, 90, True, "base-pair (FNS)"] for v in ex.values()], |
| inputs=[seq, n, gen_ck, decode], |
| label="Example sequences (one per domain)") |
| except Exception: |
| pass |
| gr.HTML(STATS_HTML) |
| return demo |
|
|
|
|
| if __name__ == "__main__": |
| build().launch() |
|
|