"""The design's markup, rendered from state.
This module is the visible layer of the app. Every element here is the
design's own element with the design's own inline styles and token values --
not a Gradio component with CSS applied over it. Gradio owns the transport
(a hidden textbox, a hidden button, one HTML sink) and nothing that is seen.
Reading order matches the design top to bottom: sidebar, header, title row,
stat band, filter rail, model table, right rail, footer, drawer.
Two rules that are not negotiable:
**Everything interpolated is escaped.** Model ids, authors, licences, red-flag
text and training-data summaries all originate from model cards written by
strangers on the internet. They arrive here as data and are escaped on the way
into the page -- `e()` for text, `a()` for attribute values. A red flag reading
`` must render as characters, not as an element.
**Nothing is invented.** Where the design shows a number the Atlas cannot
know -- a download trend before two snapshots exist, a market price -- the slot
renders an em dash or is filled with something the index actually knows. The
design is the authority on layout; it is not a licence to fabricate data.
"""
from __future__ import annotations
from bit_ui import dialogs, palette, sidebar as bit_sidebar
from bit_ui.icons import icon
from bit_ui.markup import DASH, a, e
from .. import format as fmt
from .chrome import emit
# --------------------------------------------------------------------------
# Design vocabulary -- glyphs and colours, taken from the design's own maps
# --------------------------------------------------------------------------
TASK_GLYPHS = {
"sentiment": "◐", "ner": "⬗", "summarization": "≡", "qa": "?",
"forecasting": "∿", "classification": "▦", "embedding": "⋮",
"trading_signal": "⇅", "other": "·",
}
ASSET_GLYPHS = {
"equities": "▲", "crypto": "◈", "forex": "⇄", "macro": "◍", "general": "○",
}
LICENSE_STYLE = {
"permissive": ("◆", "var(--accent-moss-strong)", "var(--accent-moss-dim)",
"Apache-2.0 / MIT and similar — commercial use allowed"),
"restricted": ("◈", "var(--accent-amber-strong)", "var(--accent-amber-dim)",
"Non-commercial, gated or custom terms — read before use"),
"none": ("○", "var(--mute-red)", "var(--mute-red)",
"No license declared — legal status unclear"),
}
SORT_OPTIONS = ("Downloads", "Trending", "Recently updated", "Likes")
COLUMNS = (
("Model", "left", "id"),
("Task", "left", "task"),
("Asset", "left", "asset"),
("Downloads 30d", "right", "Downloads"),
("Likes", "right", "Likes"),
("License", "left", "lic"),
("Updated", "left", "Recently updated"),
("Badges", "left", "badges"),
)
GRID = ("minmax(230px,2.4fr) 104px 92px 148px 60px 116px 104px 112px")
SORTABLE_COLUMNS = {"Downloads", "Likes", "Recently updated"}
def task_glyph(task) -> str:
return TASK_GLYPHS.get(task, "·")
def asset_glyph(asset) -> str:
return ASSET_GLYPHS.get(asset, "○")
def license_style(bucket):
return LICENSE_STYLE.get(bucket, LICENSE_STYLE["none"])
def sparkline(series, width=64, height=18) -> str:
"""An SVG path for a real download series, or "" when there is no series.
Returning "" rather than a flat line is the point: the caller renders an
em dash instead, and the user can tell the difference between "no growth"
and "we have not been running long enough to know".
"""
if not series or len(series) < 2:
return ""
lo, hi = min(series), max(series)
span = (hi - lo) or 1
points = []
for i, value in enumerate(series):
x = i / (len(series) - 1) * width
y = height - ((value - lo) / span) * (height - 2) - 1
points.append(f"{'L' if i else 'M'}{x:.1f} {y:.1f}")
return " ".join(points)
# --------------------------------------------------------------------------
# Header
# --------------------------------------------------------------------------
def header(index, tape_rows) -> str:
"""Top bar and ticker tape.
The design's tape scrolls live market prices and the design's status pill
reads "REGIME: TRENDING". The Atlas has no price feed, and inventing one
would put fabricated market data on a page whose whole argument is that
unverified numbers should not be trusted. So both slots keep the design's
form and carry what this app actually knows: the tape scrolls the most
downloaded models in the index with their real counts, and the pill states
the index's provenance.
"""
items = []
for row in tape_rows:
series = row.get("series")
change = row.get("change")
if change is None:
change_text, colour = DASH, "var(--fin-flat)"
else:
arrow = "▲" if change > 0 else ("▼" if change < 0 else "·")
sign = "+" if change > 0 else ""
change_text = f"{sign}{change:.1f}% {arrow}"
colour = ("var(--fin-up)" if change > 0
else "var(--fin-down)" if change < 0 else "var(--fin-flat)")
name = row["id"].split("/")[-1]
items.append(
f'
"""
# --------------------------------------------------------------------------
# Title row and stat band
# --------------------------------------------------------------------------
def title_row(index, state, shown: int) -> str:
query = state.get("q") or ""
# The shared search bar: live-filters as you type and carries the ⌘K
# affordance the design draws, which now opens a real palette.
search = palette.search_bar(
query, emit,
count_label=f"{shown:,} / {index.total:,}",
placeholder=f"Search {index.total:,} models…",
)
stamp = index.last_indexed
ago = fmt.short_ago(stamp)
when = fmt.utc_stamp(stamp)
indexed_text = (f"LAST INDEXED {when} · {ago} AGO" if stamp
else "NEVER INDEXED — DATASET IS EMPTY")
return f"""
Finance Atlas
REGISTRY · HUGGING FACE HUB
{search}
{e(indexed_text)}
"""
def stat_band(index) -> str:
"""The six-cell stat band. Every figure is computed from the index."""
total = index.total
cells = (
("Models indexed", f"{total:,}", "finance models on the Hub",
"var(--text-primary)", "var(--border-default)"),
("Actively maintained", f"{index.maintained_count:,}",
"recent commit or active downloads", "var(--fin-up)", "var(--fin-up)"),
("Undocumented", fmt.percent(index.undocumented_count, total),
"no training data disclosed", "var(--fin-down)", "var(--fin-down)"),
("Claimed evaluations", f"{index.eval_count:,}",
"card names a test set", "var(--accent-amber-strong)", "var(--accent-amber)"),
("Human-verified", f"{index.verified_count:,}",
"checked by a Bit Trading researcher",
"var(--text-primary)", "var(--border-default)"),
("Last indexed", fmt.short_ago(index.last_indexed),
"weekly crawl", "var(--text-secondary)", "var(--border-default)"),
)
body = "".join(
f'
'
f'
{e(label)}
'
f'
{e(value)}
'
f'
{e(note)}
'
f'
'
for label, value, note, colour, mark in cells
)
return (f'
'
f'{body}
')
# --------------------------------------------------------------------------
# Filter rail
# --------------------------------------------------------------------------
def _chip(action_key: str, value: str, label: str, count: int, glyph: str,
active: bool) -> str:
background = "var(--accent-amber-dim)" if active else "transparent"
border = "var(--accent-amber)" if active else "var(--border-default)"
colour = "var(--text-primary)" if active else "var(--text-secondary)"
return (
f''
)
def _switch(action_key: str, label: str, on: bool) -> str:
"""The design system's Switch, rendered as a real button.
A `gr.Checkbox` here would be a different DOM with different metrics; this
is the design's own control, and it carries `role="switch"` so it is
announced correctly rather than as an unlabelled button.
"""
track = "var(--accent-amber)" if on else "var(--border-default)"
knob = "var(--stone-950)" if on else "var(--text-tertiary)"
offset = "10px" if on else "1px"
return (
f''
)
def _checkbox(action_key: str, label: str, on: bool) -> str:
mark = "✓" if on else ""
border = "var(--accent-amber)" if on else "var(--border-default)"
background = "var(--accent-amber)" if on else "transparent"
return (
f''
)
def _rail_section(title: str, body: str, last: bool = False) -> str:
border = "" if last else "border-bottom:1px solid var(--border-subtle);"
return (
f'
'
f'
{e(title)}
{body}
'
)
def filter_rail(index, state, hidden_count: int) -> str:
taxonomy = index.taxonomy
task_labels = taxonomy.get("task_labels", {})
asset_labels = taxonomy.get("asset_labels", {})
task_chips = "".join(
_chip("task", key, task_labels.get(key, key),
index.count_by("task", key), task_glyph(key),
key in (state.get("tasks") or ()))
for key in taxonomy.get("task_chips", ())
)
asset_chips = "".join(
_chip("asset", key, asset_labels.get(key, key),
index.count_by("asset_class", key), asset_glyph(key),
key in (state.get("assets") or ()))
for key in taxonomy.get("asset_chips", ())
)
licence_rows = []
for bucket in taxonomy.get("license_buckets", ()):
glyph, colour, _, tip = license_style(bucket)
active = bucket in (state.get("lic") or ())
background = "var(--accent-amber-dim)" if active else "transparent"
border = "var(--accent-amber)" if active else "var(--border-default)"
foreground = "var(--text-primary)" if active else colour
count = index.count_by("license_bucket", bucket)
licence_rows.append(
f''
)
sort_rows = []
for label in SORT_OPTIONS:
active = state.get("sort") == label
sort_rows.append(
f''
)
# The design prints "728 UNMAINTAINED HIDDEN". That number is derived from
# the live filter set rather than stored, so it always matches what the
# table is actually withholding.
if state.get("maintained_only"):
hidden_note = f"{hidden_count:,} UNMAINTAINED HIDDEN"
else:
hidden_note = "UNMAINTAINED SHOWN"
status_body = (
f'{_switch("verified", "✓ Verified by Bit Trading", bool(state.get("verified_only")))}'
f'{_switch("maintained", "Maintained only", bool(state.get("maintained_only")))}'
f'
'
f'†'
f'{e(hidden_note)}
'
)
evidence_body = (
f'{_checkbox("haseval", "Has evaluation", bool(state.get("has_eval")))}'
f'{_checkbox("hasdata", "Has documented training data", bool(state.get("has_data")))}'
)
return f"""
"""
# --------------------------------------------------------------------------
# Model table
# --------------------------------------------------------------------------
def _badges(row) -> str:
out = []
if row.get("verified"):
out.append(("✓", "Verified by a Bit Trading researcher",
"bit-badge-verified"))
flags = row.get("red_flags") or []
if len(flags):
out.append(("⚠", "; ".join(str(f) for f in flags), "bit-badge-flag"))
if row.get("has_eval"):
out.append(("▤", "Model card claims evaluation on a named test set", ""))
if row.get("relevant") == "unclear":
out.append(("?", "The classifier could not read this card confidently",
"bit-badge-unclear"))
return "".join(
f'{e(glyph)}'
for glyph, tip, variant in out
)
LICENSE_BUCKET_CLASS = {
"permissive": "bit-tag-lic-permissive",
"restricted": "bit-tag-lic-restricted",
"none": "bit-tag-lic-none",
}
def _age_class(months) -> str:
if months is None:
return "bit-age-none"
if months < 3:
return "bit-age-fresh"
if months < 12:
return "bit-age-warn"
return "bit-age-stale"
def _table_row(row, index, selected: bool) -> str:
"""One row of the model index.
Rendered with CSS classes rather than the design's inline styles. This is
the only markup that repeats 300 times, and inline it came to 2,644
characters a row -- ~793 KB per render, 95% of the page, re-sent on every
action. The design's values are unchanged; see `chrome.ATLAS_CSS`.
"""
model_id = row.get("id", "")
labels = index.taxonomy.get("task_labels", {})
assets = index.taxonomy.get("asset_labels", {})
verified = bool(row.get("verified"))
series = index.trends.get(model_id)
path = sparkline(series)
if path:
from ..atlas import growth
change = growth(series)
direction = "bit-spark-up" if (change or 0) >= 0 else "bit-spark-down"
spark = (f'')
else:
# No second snapshot yet: there is no trend to draw, and drawing one
# anyway would be inventing data.
spark = (f'{DASH}')
glyph, _colour, _border, tip = license_style(row.get("license_bucket"))
lic_class = LICENSE_BUCKET_CLASS.get(row.get("license_bucket"),
"bit-tag-lic-none")
age_class = _age_class(fmt.months_since(row.get("last_modified")))
_, age_glyph = fmt.age_tone(row.get("last_modified"))
base = row.get("base_model") or ""
sub = f"from {base}" if base else "no declared base model"
classes = "bit-row"
if verified:
classes += " bit-row-verified"
if selected:
classes += " bit-row-selected"
return (
f'
'
)
def model_table(index, state, rows, hidden_count: int,
matched: int = None, truncated: int = 0) -> str:
# `matched` is how many rows passed the filters; `rows` may be a capped
# slice of them. Every count shown below reports `matched`, and the cap
# is stated outright rather than quietly shrinking the number.
matched = len(rows) if matched is None else matched
sort = state.get("sort", "Downloads")
headers = []
for label, align, key in COLUMNS:
sortable = key in SORTABLE_COLUMNS
colour = ("var(--accent-amber-strong)" if sort == key
else "var(--text-tertiary)")
action = a(emit("sort", key)) if sortable else a(emit("noop"))
# Built outside the f-string: Python 3.10 does not allow a backslash
# inside an f-string expression, and the Space runs 3.10.
disabled = '' if sortable else 'aria-disabled="true" '
headers.append(
f''
)
summary = ("MAINTAINED · " if state.get("maintained_only") else "ALL · ")
if state.get("verified_only"):
summary += "VERIFIED · "
summary += f"{matched:,} MATCHING"
if not index.total:
body = _empty_index_state()
elif not rows:
body = _empty_results_state(state, hidden_count)
else:
selected = state.get("sel")
body = (
f'
'
+ "".join(_table_row(r, index, r.get("id") == selected) for r in rows)
+ f'
'
f''
f'{_page_note(len(rows), matched, truncated, index)}'
f'SCROLL FOR MORE ↓'
f'
'
)
return f"""
Model index{e(summary)}SORTED BY {e(sort.upper())}
{''.join(headers)}
{body}
iAuto-indexed weekly via the Hub API and LLM
classification; ✓ = human-verified by a Bit Trading researcher. Everything
else is a machine's reading of a model card.METHODOLOGY ↗
"""
def _page_note(shown: int, matched: int, truncated: int, index) -> str:
"""The footer line under the table.
When the render is capped, that is stated in the line rather than left for
the user to infer from a row count that stops at a round number.
"""
if truncated:
return (f"SHOWING FIRST {shown:,} OF {matched:,} MATCHING "
f"— NARROW THE FILTERS TO SEE THE REST")
return (f"SHOWING {shown:,} OF {index.maintained_count:,} MAINTAINED "
f"· {index.total:,} INDEXED")
def _empty_index_state() -> str:
"""Shown when the dataset itself is empty or unreachable."""
return (
f'
'
f'NO INDEX'
f'
'
f'The index has not been built yet
'
f'
This Space reads a dataset that is empty or '
f'unreachable. The weekly indexing job populates it; until it has run '
f'once there is nothing to show.
'
)
def _empty_results_state(state, hidden_count: int) -> str:
query = state.get("q") or ""
echo = f'"{query}"' if query else "these filters"
graveyard = ""
if state.get("maintained_only") and hidden_count:
graveyard = (
f''
)
return (
f'
'
f'0 RESULTS'
f'
'
f'Nothing matches {e(echo)}
'
f'
'
f'If a model exists on the Hub and is not here, that is a gap in our '
f'harvest terms or our classifier — not proof it does not exist.
'
f'
'
f''
f'{graveyard}
'
)
# --------------------------------------------------------------------------
# Right rail
# --------------------------------------------------------------------------
def _panel(title: str, body: str, meta: str = "") -> str:
meta_html = (f'{e(meta)}'
if meta else "")
return (
f'
'
f'
'
f''
f'{e(title)}{meta_html}
{body}
'
)
def trending_panel(index, rows) -> str:
"""Top movers by real week-over-week download growth.
Before two snapshots exist there is no growth to rank by, so the panel
says that instead of ranking on a fabricated number.
"""
if not rows:
body = (
f'
'
f'NO TREND YET'
f'Trends need at least two weekly snapshots. '
f'The first crawl has run; the next one makes this panel live.'
f'
'
)
return _panel("Trending this quarter", body)
items = []
for rank, (model_id, change, series) in enumerate(rows, start=1):
path = sparkline(series)
spark = (f'')
items.append(
f'
'
)
return _panel("Trending this quarter", "".join(items))
def lineage_panel(index) -> str:
root, kids = index.spotlight()
if not root or not kids:
body = (f'
'
f''
f'No declared lineage in the index yet.
')
return _panel("Lineage spotlight", body)
shown = kids[:4]
rows = []
for position, child in enumerate(shown):
last = position == len(shown) - 1 and len(kids) <= len(shown)
row = index.by_id.get(child, {})
rows.append(
f'
'
f'{"└─" if last else "├─"}'
f''
f'{e(child)}'
f''
f'{e(fmt.compact(row.get("downloads_30d")))}
'
)
if len(kids) > len(shown):
rows.append(
f'
'
f'└─'
f'+ {len(kids) - len(shown)} more descendants'
f'
'
for key, value, colour in fields
)
def _drawer_lineage(row, index) -> str:
from .. import lineage as lin
model_id = row.get("id", "")
parent = row.get("base_model") or ""
kin = lin.siblings(model_id, index.parents, index.children)[:4]
kids = lin.direct_children(model_id, index.children)
if not parent:
parent_html = (f'
no declared base model
')
else:
indexed = parent in index.by_id
note = "" if indexed else " (not indexed)"
parent_html = (
f'
fine-tuned from
'
f'
'
f'{e(parent)}{e(note)}
'
)
entries = [(k, "sibling") for k in kin] + [(k, "child") for k in kids[:4]]
rows = []
for position, (other, relation) in enumerate(entries):
last = position == len(entries) - 1
other_row = index.by_id.get(other, {})
tag = f"{relation} · {fmt.compact(other_row.get('downloads_30d'))} dl"
flagged = bool(len(other_row.get("red_flags") or []))
colour = ("var(--accent-amber-strong)" if flagged else "var(--text-secondary)")
rows.append(
f'
'
f'{"└─" if last else "├─"}'
f''
f'{e(other)}'
f'{e(tag)}{" ⚠" if flagged else ""}
'
)
if not rows:
rows.append(f'
'
f'no indexed relatives
')
return (
f'
'
f'
Data lineage
'
f'
{parent_html}'
f'
'
f'{"".join(rows)}
'
)
def _drawer_trend(row, index) -> str:
"""The weekly download chart, or an honest note that there is no series."""
series = index.trends.get(row.get("id"))
if not series or len(series) < 2:
return (
f'
'
f'
Downloads · weekly snapshots
'
f'
'
f'Not enough snapshots yet. A trend needs at least '
f'two weekly crawls; this model has {len(series or [1])}.
'
)
width, height = 480, 112
lo, hi = min(series), max(series)
span = (hi - lo) or 1
points = []
for i, value in enumerate(series):
x = i / (len(series) - 1) * width
y = height - ((value - lo) / span) * (height - 14) - 7
points.append(f"{'L' if i else 'M'}{x:.1f} {y:.1f}")
line = " ".join(points)
area = f"{line} L{width} {height} L0 {height} Z"
from ..atlas import growth
change = growth(series)
trend_text = DASH if change is None else f"{'+' if change >= 0 else ''}{change:.1f}% / {len(series)}W"
trend_colour = ("var(--fin-up)" if (change or 0) >= 0 else "var(--fin-down)")
grid = "".join(
f''
for f in (0.15, 0.4, 0.65, 0.9)
)
return (
f'
'
)
def _drawer_notes(row) -> str:
verified = bool(row.get("verified"))
flags = [str(f) for f in (row.get("red_flags") or [])]
unclear = row.get("relevant") == "unclear"
if verified:
title, colour, border = ("Verification notes", "var(--text-secondary)",
"var(--border-default)")
notes = [("✓", "var(--accent-moss-strong)",
"Promoted to verified by a Bit Trading researcher. The entry in "
"verified.json is a human's judgement, not the classifier's.")]
notes += [("⚠", "var(--accent-amber-strong)", f) for f in flags]
elif flags:
title, colour, border = ("Red flags", "var(--accent-amber-strong)",
"var(--accent-amber-dim)")
notes = [("⚠", "var(--accent-amber-strong)", f) for f in flags]
notes.append(("·", "var(--text-tertiary)",
"Auto-indexed only. No Bit Trading researcher has reproduced "
"anything on this card."))
else:
title, colour, border = ("Indexer notes", "var(--text-secondary)",
"var(--border-default)")
notes = [("·", "var(--text-tertiary)",
"Auto-indexed only. The classifier found no red flags, and no "
"human has verified this either.")]
notes.append(("·", "var(--text-tertiary)",
"Model card claims an evaluation on a named test set."
if row.get("has_eval") else
"Model card has no evaluation section we could find."))
if unclear:
notes.append(("?", "var(--text-tertiary)",
"The classifier could not read this card confidently, so the "
"task and asset class below are low-confidence guesses."))
body = "".join(
f'
'
f'{e(glyph)}'
f'{e(text)}
'
for glyph, tone, text in notes
)
return (
f'
'
f'
{e(title)}
'
f'
'
f'{body}
'
)
def backtestable(row, taxonomy) -> bool:
"""Whether to offer the Backtest Lab hand-off for this model.
Narrower than the design's own rule, deliberately. The design shows the
link for any forecasting or trading-signal model; this shows it only for
forecasting models in an adapter family the Backtest Lab can actually load
(chronos, timesfm). A link the destination Space cannot honour is worse
than no link.
"""
if row.get("task") != "forecasting":
return False
families = tuple(taxonomy.get("backtestable_families", ()))
return (row.get("adapter_family") or "") in families
def drawer(row, index) -> str:
if not row:
return ""
model_id = row.get("id", "")
verified = bool(row.get("verified"))
labels = index.taxonomy.get("task_labels", {})
assets = index.taxonomy.get("asset_labels", {})
lic_glyph, lic_colour, lic_border, _ = license_style(row.get("license_bucket"))
summary = (row.get("training_data_summary") or "").strip()
if not summary:
summary = ("The model card does not describe the training data. That is "
"the classifier's finding, not an oversight in this page.")
if backtestable(row, index.taxonomy):
url = index.taxonomy.get("backtest_space_url", "")
backtest = (
f'Backtest this model →'
)
else:
backtest = ""
return f"""
MODEL RECORD{"✓ VERIFIED BY BIT TRADING" if verified else "AUTO-INDEXED"}
{e(fmt.initials(model_id))}
{e(model_id)}
{e(task_glyph(row.get('task')))} {e(labels.get(row.get('task'), row.get('task')))}
{e(asset_glyph(row.get('asset_class')))} {e(assets.get(row.get('asset_class'), row.get('asset_class')))}
{e(lic_glyph)} {e(row.get('license') or 'none')}
"""
# --------------------------------------------------------------------------
# Page
# --------------------------------------------------------------------------
def page(index, state, view) -> str:
"""The whole page, assembled from one render pass over `view`.
`view` carries everything the renderers need that is derived rather than
stored -- the filtered rows, the hidden count, the trending list -- so
each section is a pure function of (index, state, view) and the filtering
runs once per request rather than once per section.
## No forced `vh` on the root
The root deliberately has no `min-height:100vh`. huggingface.co embeds a
Space in an `