Download src/demo/render.py from cdotsanghvi/lfm2-transaction-encoder: direct link, hf CLI and curl.
- Browser
- Download file 46.6 kB
-
https://huggingface.co/spaces/cdotsanghvi/lfm2-transaction-encoder/resolve/main/src/demo/render.py
- Command line
-
hf download hf://spaces/cdotsanghvi/lfm2-transaction-encoder/src/demo/render.py
-
curl -L -o render.py https://huggingface.co/spaces/cdotsanghvi/lfm2-transaction-encoder/resolve/main/src/demo/render.py
46.6 kB
| """HTML rendering for the inference demo UI. | |
| Styling follows the Liquid AI design system from liquid-lfm-cloud: | |
| - Monochrome primary scale (#171717 primary, #f5f5f5 background) | |
| - Semantic accents: emerald (#10B981), amber (#F59E0B), red (#EF4444), blue (#3B82F6) | |
| - JetBrains Mono for technical/metric elements, system sans-serif for body | |
| - 16px rounded cards with subtle shadows | |
| - Pill-shaped buttons and badges | |
| """ | |
| from __future__ import annotations | |
| from typing import Callable | |
| import numpy as np | |
| from src.data.generator import AMOUNT_RANGE_LABELS | |
| from src.data.schema import VALUES_START | |
| from src.demo.decode import TransactionDecoder | |
| from src.demo.merchant_catalog import DemoMerchantCatalog, MCC_NAMES | |
| # Liquid design tokens — light mode (liquid-lfm-cloud design system) | |
| _BG = "#f5f5f5" | |
| _BG_CARD = "#ffffff" | |
| _BG_CARD_ALT = "#fafafa" | |
| _BORDER = "rgba(0,0,0,0.1)" | |
| _BORDER_SUBTLE = "rgba(0,0,0,0.05)" | |
| _TEXT = "#171717" | |
| _TEXT_MUTED = "#525252" | |
| _TEXT_DIM = "#737373" | |
| _ACCENT_BLUE = "#3B82F6" | |
| _ACCENT_GREEN = "#10B981" | |
| _ACCENT_AMBER = "#F59E0B" | |
| _ACCENT_RED = "#EF4444" | |
| _RADIUS_CARD = "16px" | |
| _RADIUS_SM = "8px" | |
| _FONT_MONO = "JetBrains Mono, ui-monospace, SFMono-Regular, monospace" | |
| _FONT_SANS = "-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif" | |
| def format_fraud_score(prob: float) -> str: | |
| """Format fraud probability as colored gauge bar.""" | |
| pct = prob * 100 | |
| if pct < 20: | |
| color = _ACCENT_GREEN | |
| risk = "LOW RISK" | |
| elif pct < 60: | |
| color = _ACCENT_AMBER | |
| risk = "MEDIUM RISK" | |
| else: | |
| color = _ACCENT_RED | |
| risk = "HIGH RISK" | |
| bar_width = max(2, min(100, int(pct))) | |
| return f""" | |
| <div style="margin: 8px 0;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 24px; font-weight: 600; | |
| color: {color}; margin-bottom: 4px; letter-spacing: -0.02em;"> | |
| {pct:.1f}% | |
| <span style="font-size: 12px; font-weight: 500; opacity: 0.8; | |
| letter-spacing: 0.05em;">{risk}</span> | |
| </div> | |
| <div style="background: #e5e5e5; border-radius: 9999px; height: 8px; | |
| width: 100%; overflow: hidden;"> | |
| <div style="background: {color}; height: 100%; width: {bar_width}%; | |
| border-radius: 9999px; transition: width 0.3s ease;"></div> | |
| </div> | |
| </div> | |
| """ | |
| def format_topk_predictions( | |
| probs: np.ndarray, | |
| k: int, | |
| label_fn: Callable[[int], str], | |
| ) -> str: | |
| """Format top-k predictions as styled rows with probability bars.""" | |
| top_indices = np.argsort(probs)[::-1][:k] | |
| rows = "" | |
| for i, idx in enumerate(top_indices): | |
| p = probs[idx] * 100 | |
| label = label_fn(int(idx)) | |
| bar_width = max(2, int(p * 2.5)) | |
| opacity = 1.0 - i * 0.15 | |
| weight = "600" if i == 0 else "400" | |
| # Show "<0.1%" for probabilities that round to 0.0% at 1 decimal place. | |
| # This happens with high-cardinality heads (10K merchants) when the model | |
| # hasn't learned a meaningful distribution (e.g. random-init baseline). | |
| p_str = f"{p:.1f}%" if p >= 0.05 else "<0.1%" | |
| rows += f""" | |
| <div style="display: flex; align-items: center; gap: 8px; padding: 4px 0;"> | |
| <div style="flex: 1; font-size: 13px; font-weight: {weight}; | |
| color: {_TEXT}; opacity: {opacity};">{label}</div> | |
| <div style="width: 50px; text-align: right; font-family: {_FONT_MONO}; | |
| font-size: 12px; color: {_TEXT_MUTED};">{p_str}</div> | |
| <div style="width: 120px;"> | |
| <div style="background: {_ACCENT_BLUE}; height: 6px; width: {bar_width}%; | |
| border-radius: 9999px; opacity: {opacity};"></div> | |
| </div> | |
| </div> | |
| """ | |
| return f'<div style="padding: 4px 0;">{rows}</div>' | |
| def format_merchant_predictions( | |
| probs: np.ndarray, | |
| merchant_catalog: DemoMerchantCatalog, | |
| k: int = 5, | |
| ) -> str: | |
| """Top-k merchant predictions with names and categories.""" | |
| def label_fn(idx: int) -> str: | |
| if idx < VALUES_START: | |
| return "[special]" | |
| mid = idx - VALUES_START | |
| info = merchant_catalog.get(mid) | |
| return f"{info.name} ({info.category})" | |
| return format_topk_predictions(probs, k, label_fn) | |
| def format_amount_predictions(probs: np.ndarray, k: int = 5) -> str: | |
| """Top-k amount range predictions.""" | |
| def label_fn(idx: int) -> str: | |
| return AMOUNT_RANGE_LABELS.get(idx, f"Range {idx}") | |
| return format_topk_predictions(probs, k, label_fn) | |
| def format_mcc_predictions(probs: np.ndarray, k: int = 5) -> str: | |
| """Top-k MCC predictions with category names.""" | |
| def label_fn(idx: int) -> str: | |
| if idx < VALUES_START: | |
| return "[special]" | |
| mcc_val = idx - VALUES_START | |
| return MCC_NAMES.get(mcc_val, f"MCC-{mcc_val}") | |
| return format_topk_predictions(probs, k, label_fn) | |
| def format_timeline(decoder: TransactionDecoder, token_ids: np.ndarray) -> str: | |
| """Render transaction sequence as a scrollable table.""" | |
| txns = decoder.decode_sequence(token_ids) | |
| header = f""" | |
| <div style="max-height: 380px; overflow-y: auto; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; background: {_BG_CARD};"> | |
| <table style="width: 100%; border-collapse: collapse; font-size: 12px; | |
| font-family: {_FONT_MONO};"> | |
| <thead> | |
| <tr style="border-bottom: 1px solid {_BORDER}; position: sticky; top: 0; | |
| background: {_BG_CARD}; z-index: 1;"> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;">Tx</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">When</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">Merchant</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">Category</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">Amount</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">Method</th> | |
| <th style="padding: 8px; text-align: left; color: {_TEXT_DIM}; | |
| font-size: 10px; text-transform: uppercase;">Country</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| """ | |
| rows = "" | |
| for txn in txns: | |
| when = f"{txn.dow} {txn.hour}" | |
| highlight = f"background: rgba(59, 130, 246, 0.08);" if txn.index == 63 else "" | |
| rows += f""" | |
| <tr style="border-bottom: 1px solid {_BORDER_SUBTLE}; {highlight}"> | |
| <td style="padding: 6px 8px; color: {_TEXT_DIM};">{txn.index}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT_MUTED};">{when}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT}; font-weight: 500;">{txn.merchant_name}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT_DIM};">{txn.merchant_category}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT_MUTED};">{txn.amount_range}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT_DIM};">{txn.entry_mode}</td> | |
| <td style="padding: 6px 8px; color: {_TEXT_DIM};">{txn.country}</td> | |
| </tr> | |
| """ | |
| return header + rows + "</tbody></table></div>" | |
| def render_production_architecture() -> str: | |
| """LFM2.5 production architecture and how it applies to payments.""" | |
| _purple = "#7c3aed" | |
| _purple_bg = "rgba(124,58,237,0.08)" | |
| _purple_border = "rgba(124,58,237,0.25)" | |
| def _layer_cell(label: str, idx: int, is_attn: bool) -> str: | |
| bg = _purple_bg if is_attn else "rgba(16,185,129,0.08)" | |
| bc = _purple_border if is_attn else "rgba(16,185,129,0.25)" | |
| color = _purple if is_attn else _ACCENT_GREEN | |
| return f"""<div style="flex: 1; padding: 6px 2px; background: {bg}; | |
| border: 1px solid {bc}; border-radius: 4px; text-align: center; min-width: 0;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 8px; color: {color}; | |
| font-weight: 600;">{label}</div> | |
| <div style="font-family: {_FONT_MONO}; font-size: 7px; color: {_TEXT_DIM};">L{idx}</div> | |
| </div>""" | |
| layers_1_2b = [ | |
| ("C", 0, False), ("C", 1, False), ("A", 2, True), ("C", 3, False), | |
| ("C", 4, False), ("A", 5, True), ("C", 6, False), ("C", 7, False), | |
| ("A", 8, True), ("C", 9, False), ("A", 10, True), ("C", 11, False), | |
| ("A", 12, True), ("C", 13, False), ("A", 14, True), ("C", 15, False), | |
| ] | |
| layer_cells = "".join(_layer_cell(l, i, a) for l, i, a in layers_1_2b) | |
| return f""" | |
| <div style="max-width: 1100px; margin: 0 auto; padding: 16px;"> | |
| <!-- Header --> | |
| <h2 style="margin: 0 0 4px 0; color: {_TEXT}; font-size: 22px; font-weight: 700; | |
| letter-spacing: -0.02em;"> | |
| LFM2.5 for Payment Sequences | |
| </h2> | |
| <p style="color: {_TEXT_DIM}; font-size: 13px; margin: 0 0 24px 0; line-height: 1.5;"> | |
| The published LFM2.5 architecture adapted for structured transaction data. | |
| Same hybrid conv-attention backbone. New per-feature embedding layer. | |
| </p> | |
| <!-- Config comparison table --> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 24px;"> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px;"> | |
| Production Target</div> | |
| <table style="width: 100%; font-size: 12px; border-collapse: collapse;"> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Parameters</td> | |
| <td style="padding: 3px 0; color: {_TEXT}; font-weight: 600; text-align: right;">1.2B</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Hidden dim</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">2048</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Layers</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;"> | |
| <span style="color: {_ACCENT_GREEN};">10 conv</span> + <span style="color: {_purple};">6 attn</span></td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Attention</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">32Q / 8KV (GQA)</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">MLP</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">SwiGLU 12288</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Sequence</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">128 tx × 30 feat = 3,840</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Latency target</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_ACCENT_GREEN}; font-weight: 600; text-align: right;">< 50ms (H100)</td></tr> | |
| </table> | |
| </div> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px;"> | |
| This Demo (Reference)</div> | |
| <table style="width: 100%; font-size: 12px; border-collapse: collapse;"> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Parameters</td> | |
| <td style="padding: 3px 0; color: {_TEXT}; font-weight: 600; text-align: right;">9.8M</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Hidden dim</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">256</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Layers</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;"> | |
| <span style="color: {_ACCENT_GREEN};">5 conv</span> + <span style="color: {_purple};">3 attn</span></td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Attention</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">4Q / 2KV (GQA)</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">MLP</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">SwiGLU 1024</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Sequence</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">64 tx × 15 feat = 960</td></tr> | |
| <tr><td style="padding: 3px 0; color: {_TEXT_DIM};">Measured latency</td> | |
| <td style="padding: 3px 0; font-family: {_FONT_MONO}; color: {_TEXT}; text-align: right;">< 80ms (CPU)</td></tr> | |
| </table> | |
| </div> | |
| </div> | |
| <!-- LFM2.5-1.2B layer diagram --> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 24px;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 12px;"> | |
| LFM2.5-1.2B Layer Pattern (16 layers)</div> | |
| <div style="display: flex; gap: 3px; margin-bottom: 8px;"> | |
| {layer_cells} | |
| </div> | |
| <div style="display: flex; gap: 16px; font-family: {_FONT_MONO}; font-size: 10px;"> | |
| <span style="color: {_ACCENT_GREEN};">■ Conv (10): local patterns, k=3, O(n)</span> | |
| <span style="color: {_purple};">■ Attention (6): global context, GQA, O(n²)</span> | |
| </div> | |
| <div style="margin-top: 8px; font-size: 11px; color: {_TEXT_DIM}; line-height: 1.5;"> | |
| First and last layers are convolutional. Attention is densest mid-stack. | |
| The LM head reads from a local-conv output, but 6 attention layers have already | |
| encoded global context upstream. | |
| </div> | |
| </div> | |
| <!-- Three key architectural adaptations --> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 24px;"> | |
| <!-- Embedding adaptation --> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_ACCENT_BLUE}; margin-bottom: 6px;"> | |
| Per-Feature Embedding</div> | |
| <p style="font-size: 12px; color: {_TEXT_MUTED}; line-height: 1.5; margin: 0 0 8px 0;"> | |
| Text LFM2 has one embedding table. Payment LFM2 has one table per feature | |
| (hour, merchant, MCC, amount, ...) plus a feature-type table. Summed to produce | |
| the same (B, T, D) the backbone expects.</p> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| padding: 6px 8px; background: {_BG_CARD_ALT}; border-radius: 6px;"> | |
| value_tables[f](token) + type_table(f)</div> | |
| </div> | |
| <!-- KV-cache advantage --> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_ACCENT_GREEN}; margin-bottom: 6px;"> | |
| KV-Cache Advantage</div> | |
| <p style="font-size: 12px; color: {_TEXT_MUTED}; line-height: 1.5; margin: 0 0 8px 0;"> | |
| Only 6 of 16 layers need KV cache (attention layers only). A pure-attention | |
| model at the same depth needs 16 layers of cache. At 3,840 token sequences | |
| with 1,024 concurrent requests:</p> | |
| <div style="font-family: {_FONT_MONO}; font-size: 11px;"> | |
| <span style="color: {_ACCENT_GREEN}; font-weight: 600;">LFM2: ~25 GB</span> | |
| <span style="color: {_TEXT_DIM};"> vs </span> | |
| <span style="color: {_ACCENT_RED};">Pure attn: ~64 GB</span> | |
| </div> | |
| </div> | |
| <!-- Weight-tied heads --> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_purple}; margin-bottom: 6px;"> | |
| Weight-Tied Heads</div> | |
| <p style="font-size: 12px; color: {_TEXT_MUTED}; line-height: 1.5; margin: 0 0 8px 0;"> | |
| Downstream heads that predict pretrained features (next merchant, MCC) | |
| project through the backbone's own embedding table. Zero extra parameters, | |
| +50% accuracy vs fresh MLP heads.</p> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| padding: 6px 8px; background: {_BG_CARD_ALT}; border-radius: 6px;"> | |
| adapter(h) @ embedding.weight.T</div> | |
| </div> | |
| </div> | |
| <!-- How it translates --> | |
| <div style="padding: 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 16px;"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_TEXT}; margin-bottom: 10px;"> | |
| How This Translates to Your Implementation</div> | |
| <div style="display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: 12px;"> | |
| <div style="font-family: {_FONT_MONO}; color: {_ACCENT_BLUE}; font-weight: 600;">Schema</div> | |
| <div style="color: {_TEXT_MUTED};">Your features, your vocab sizes, your ordering. We review the schema design.</div> | |
| <div style="font-family: {_FONT_MONO}; color: {_ACCENT_BLUE}; font-weight: 600;">Pretrain</div> | |
| <div style="color: {_TEXT_MUTED};">Self-supervised on your unlabeled transactions. No fraud labels needed.</div> | |
| <div style="font-family: {_FONT_MONO}; color: {_ACCENT_BLUE}; font-weight: 600;">Fine-tune</div> | |
| <div style="color: {_TEXT_MUTED};">Attach task heads (fraud, disputes, auth optimization). Multi-task with shared backbone.</div> | |
| <div style="font-family: {_FONT_MONO}; color: {_ACCENT_BLUE}; font-weight: 600;">Deploy</div> | |
| <div style="color: {_TEXT_MUTED};">Your infra, your GPUs, your compliance. Sub-100ms for real-time authorization decisioning.</div> | |
| <div style="font-family: {_FONT_MONO}; color: {_ACCENT_BLUE}; font-weight: 600;">Own</div> | |
| <div style="color: {_TEXT_MUTED};">No data leaves your infrastructure. No external API dependency. You own the model.</div> | |
| </div> | |
| </div> | |
| <!-- Architecture source --> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; text-align: center;"> | |
| Architecture: <a href="https://arxiv.org/abs/2511.23404" style="color: {_ACCENT_BLUE}; text-decoration: none;"> | |
| arXiv 2511.23404</a> · | |
| Weights: <a href="https://huggingface.co/LiquidAI" style="color: {_ACCENT_BLUE}; text-decoration: none;"> | |
| huggingface.co/LiquidAI</a> | |
| </div> | |
| </div> | |
| """ | |
| def render_comparison_header() -> str: | |
| """Header explaining the pretrained vs random-init comparison.""" | |
| return f""" | |
| <div style="padding: 10px 14px; background: rgba(245,158,11,0.06); | |
| border: 1px solid rgba(245,158,11,0.2); border-radius: {_RADIUS_SM}; | |
| margin-bottom: 12px; font-size: 12px; color: {_ACCENT_AMBER}; line-height: 1.5;"> | |
| <b>Pretrained vs Random Init:</b> | |
| <span style="color: {_TEXT_MUTED};">Same architecture, same input, same fine-tuning data. | |
| Left: pretrained on 200K unlabeled sequences first. Right: trained from scratch. | |
| The difference is the value of self-supervised pretraining.</span> | |
| </div> | |
| """ | |
| def render_why_liquid() -> str: | |
| """Render the 'Why Liquid AI' value proposition tab. | |
| Content drawn from docs/architecture-walkthrough.md §14. | |
| Uses measured reference-implementation numbers, not marketing claims. | |
| """ | |
| def _table_row(cells: list[str], bold_last: bool = False) -> str: | |
| tds = "" | |
| for i, c in enumerate(cells): | |
| weight = "600" if (bold_last and i == len(cells) - 1) else "400" | |
| align = "right" if i > 0 else "left" | |
| tds += ( | |
| f'<td style="padding: 5px 10px; font-family: {_FONT_MONO}; font-size: 11px;' | |
| f' color: {_TEXT}; font-weight: {weight}; text-align: {align};">{c}</td>' | |
| ) | |
| return f"<tr style='border-bottom: 1px solid {_BORDER_SUBTLE};'>{tds}</tr>" | |
| def _table_header(cols: list[str]) -> str: | |
| ths = "" | |
| for i, c in enumerate(cols): | |
| align = "right" if i > 0 else "left" | |
| ths += ( | |
| f'<th style="padding: 6px 10px; font-size: 10px; color: {_TEXT_DIM};' | |
| f' text-transform: uppercase; letter-spacing: 0.05em; text-align: {align};' | |
| f' font-weight: 600;">{c}</th>' | |
| ) | |
| return f"<tr style='border-bottom: 1px solid {_BORDER};'>{ths}</tr>" | |
| return f""" | |
| <div style="max-width: 1100px; margin: 0 auto; padding: 16px;"> | |
| <h2 style="margin: 0 0 4px 0; color: {_TEXT}; font-size: 22px; font-weight: 700; | |
| letter-spacing: -0.02em;"> | |
| Why LFM2.5 for Transaction Sequences | |
| </h2> | |
| <p style="color: {_TEXT_DIM}; font-size: 13px; margin: 0 0 24px 0; line-height: 1.5;"> | |
| Three claims, each backed by a different kind of evidence. Serving cost is arithmetic. | |
| Label efficiency is measured. Architectural fit is a first-principles argument. | |
| </p> | |
| <!-- 1. Serving cost --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 12px;"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| 1. Serving Cost Scales Better Than Pure Attention | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 13px; line-height: 1.6; margin: 0 0 12px 0;"> | |
| 10 of 16 layers use O(n) conv instead of O(n²) attention. The gap is structural | |
| and compounds as sequence length grows. Measured at matched parameter count on the same | |
| hardware: | |
| </p> | |
| <table style="width: 100%; border-collapse: collapse; margin-bottom: 8px;"> | |
| {_table_header(["Sequence", "Tokens", "Hybrid", "Pure Attn", "Speedup"])} | |
| {_table_row(["64 tx × 15 feat", "960", "5.96 ms", "9.01 ms", "1.5x"])} | |
| {_table_row(["64 tx × 30 feat", "1,920", "13.05 ms", "23.84 ms", "1.8x"])} | |
| {_table_row(["128 tx × 30 feat", "3,840", "35.65 ms", "75.95 ms", | |
| "<b>2.1x</b>"], bold_last=False)} | |
| {_table_row(["256 tx × 30 feat", "7,680", "119 ms", "283 ms", | |
| "<b>2.4x</b>"], bold_last=False)} | |
| </table> | |
| <p style="font-size: 11px; color: {_TEXT_DIM}; margin: 0; line-height: 1.5;"> | |
| At 3,840 tokens (production target), the FLOP analysis predicts 7.7% fewer operations. | |
| The actual speedup is larger because conv layers achieve better hardware utilization. | |
| At 7,680 tokens, savings reach 17% in FLOPs and 2.4x in wall-clock. | |
| </p> | |
| </div> | |
| <!-- 2. Label scarcity --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 12px;"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| 2. Pretraining Gets to 98% of Full-Data Quality with 10% of Labels | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 13px; line-height: 1.6; margin: 0 0 12px 0;"> | |
| Self-supervised pretraining on unlabeled transactions. No fraud labels needed. | |
| Then fine-tune with whatever labels you have. The pretrained model at 10% labels | |
| beats the random-init baseline at 100% labels. | |
| </p> | |
| <table style="width: 100%; border-collapse: collapse; margin-bottom: 8px;"> | |
| {_table_header(["Labels", "Sequences", "Pretrained PR-AUC", "Baseline PR-AUC", "Delta"])} | |
| {_table_row(["1%", "1,700", "<b>0.539</b>", "0.046", "<b>+0.493</b>"])} | |
| {_table_row(["10%", "17,000", "<b>0.948</b>", "0.690", "<b>+0.258</b>"])} | |
| {_table_row(["100%", "170,000", "<b>0.964</b>", "0.922", "+0.041"])} | |
| </table> | |
| <p style="font-size: 11px; color: {_TEXT_DIM}; margin: 0; line-height: 1.5;"> | |
| At 1% labels the baseline has learned nothing (0.046 is random guessing). | |
| The pretrained model is already useful. This is the defining advantage for | |
| institutions with billions of unlabeled transactions and limited fraud labels. | |
| </p> | |
| </div> | |
| <!-- 3. Convergence + multi-head --> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;"> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| 5x Convergence Speed | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 12px; line-height: 1.6; margin: 0 0 8px 0;"> | |
| The pretrained model hit 0.959 PR-AUC at step 1,000. The random-init baseline | |
| never reached that level in 5,000 steps (peaked at 0.922). | |
| </p> | |
| <p style="color: {_TEXT_MUTED}; font-size: 12px; line-height: 1.6; margin: 0;"> | |
| For quarterly model refreshes, this cuts GPU-hours per cycle by 80%. | |
| For weekly refreshes, it is the difference between feasible and infeasible. | |
| </p> | |
| </div> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| One Backbone, Many Tasks | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 12px; line-height: 1.6; margin: 0 0 8px 0;"> | |
| A single forward pass serves fraud detection, next-merchant prediction, amount | |
| forecasting, and merchant category classification. Add dispute prediction, default | |
| risk, or authorization optimization as new heads without retraining the backbone. | |
| </p> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| padding: 6px 8px; background: {_BG_CARD_ALT}; border-radius: 6px;"> | |
| Tied-embedding heads: +50% merchant accuracy at zero parameter cost | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 4. Architectural fit --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 12px;"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| 3. The Architecture Matches Transaction Data Structure | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 13px; line-height: 1.6; margin: 0 0 8px 0;"> | |
| Transaction data is not like text. Information density is concentrated locally | |
| (within-transaction feature correlations, adjacent-transaction continuity) with sparse | |
| global signal (behavioral baselines across the full history). LFM2.5 allocates | |
| O(n) conv to the dense local patterns and O(n²) attention to the sparse | |
| global patterns. A pure transformer allocates O(n²) compute uniformly | |
| across all distances. | |
| </p> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px;"> | |
| <div style="padding: 10px; background: {_BG_CARD_ALT}; border-radius: 8px;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT}; | |
| font-weight: 600; margin-bottom: 4px;">Within Transaction</div> | |
| <div style="font-size: 11px; color: {_TEXT_DIM}; line-height: 1.4;"> | |
| Merchant determines MCC. Entry mode correlates with amount. Dense, local, | |
| often deterministic. A 3-wide conv kernel captures this. | |
| </div> | |
| </div> | |
| <div style="padding: 10px; background: {_BG_CARD_ALT}; border-radius: 8px;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT}; | |
| font-weight: 600; margin-bottom: 4px;">Adjacent Transactions</div> | |
| <div style="font-size: 11px; color: {_TEXT_DIM}; line-height: 1.4;"> | |
| Strong temporal continuity. A customer at Starbucks is likely at a similar | |
| merchant next. The conditional distribution of t+1 given t is heavily peaked. | |
| </div> | |
| </div> | |
| <div style="padding: 10px; background: {_BG_CARD_ALT}; border-radius: 8px;"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT}; | |
| font-weight: 600; margin-bottom: 4px;">Distant Transactions</div> | |
| <div style="font-size: 11px; color: {_TEXT_DIM}; line-height: 1.4;"> | |
| Weak but non-zero signal. Behavioral profile matters for fraud baseline, | |
| but per-position information density is thin. This is where attention earns its cost. | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 5. Data ownership --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 12px;"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 4px 0; font-size: 15px; font-weight: 600;"> | |
| Your Data, Your Model, Your Infrastructure | |
| </h3> | |
| <p style="color: {_TEXT_MUTED}; font-size: 13px; line-height: 1.6; margin: 0;"> | |
| Liquid licenses the architecture and training recipe. You train on your proprietary | |
| data behind your firewall. No data leaves your infrastructure. No dependency on | |
| external model APIs. The result is a foundation model you own, optimized for your | |
| specific transaction patterns, deployed on your hardware. | |
| </p> | |
| </div> | |
| <!-- What we claim / don't claim --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 16px;"> | |
| <h3 style="color: {_TEXT}; margin: 0 0 8px 0; font-size: 14px; font-weight: 600;"> | |
| What We Claim vs What We Don't | |
| </h3> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; font-size: 12px;"> | |
| <div> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT}; | |
| font-weight: 600; margin-bottom: 6px; text-transform: uppercase; | |
| letter-spacing: 0.05em;">We claim</div> | |
| <ul style="margin: 0; padding-left: 14px; color: {_TEXT_MUTED}; line-height: 1.6;"> | |
| <li>Fewer FLOPs per forward pass above ~1,500 tokens (arithmetic)</li> | |
| <li>Cost gap widens with sequence length (structural, measured 2.1-2.4x)</li> | |
| <li>Pretraining dramatically improves low-label performance (measured)</li> | |
| <li>Full pipeline works end-to-end on LFM2.5 (built it)</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| font-weight: 600; margin-bottom: 6px; text-transform: uppercase; | |
| letter-spacing: 0.05em;">We don't claim</div> | |
| <ul style="margin: 0; padding-left: 14px; color: {_TEXT_MUTED}; line-height: 1.6;"> | |
| <li>Quality advantage over pure transformers at matched scale</li> | |
| <li>Absolute latency numbers extrapolated from 10M to 1.2B</li> | |
| <li>Superiority on all tasks (the advantage is specific to structured sequences)</li> | |
| <li>Real-data validation (all results are on synthetic data)</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; text-align: center;"> | |
| Source: <a href="https://arxiv.org/abs/2511.23404" style="color: {_TEXT_DIM}; | |
| text-decoration: underline;">arXiv 2511.23404</a> · | |
| Reference implementation measured at 9.85M params, Apple Silicon | |
| </div> | |
| </div> | |
| """ | |
| def render_integration_guide() -> str: | |
| """Render high-abstraction integration architecture flow. | |
| Distills docs/integration-guide.md into a visual pipeline overview. | |
| Monochrome design -- no rainbow pills or per-card color coding. | |
| """ | |
| def _phase_card(num: str, title: str, body: str, detail: str) -> str: | |
| return f""" | |
| <div style="padding: 14px 16px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD};"> | |
| <div style="display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px;"> | |
| <span style="font-family: {_FONT_MONO}; font-size: 11px; color: {_TEXT_DIM}; | |
| font-weight: 600;">{num}</span> | |
| <span style="font-size: 14px; font-weight: 600; color: {_TEXT};">{title}</span> | |
| </div> | |
| <p style="font-size: 12px; color: {_TEXT_MUTED}; line-height: 1.5; margin: 0 0 8px 0;"> | |
| {body}</p> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| padding: 6px 8px; background: {_BG_CARD_ALT}; border-radius: 6px; | |
| line-height: 1.5;"> | |
| {detail}</div> | |
| </div>""" | |
| def _gotcha(num: str, title: str, desc: str) -> str: | |
| return f""" | |
| <div style="display: flex; gap: 8px; padding: 5px 0; | |
| border-bottom: 1px solid {_BORDER_SUBTLE};"> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; | |
| font-weight: 600; min-width: 18px;">{num}.</div> | |
| <div> | |
| <span style="font-size: 12px; font-weight: 600; color: {_TEXT};">{title}</span> | |
| <span style="font-size: 12px; color: {_TEXT_MUTED};"> -- {desc}</span> | |
| </div> | |
| </div>""" | |
| return f""" | |
| <div style="max-width: 1100px; margin: 0 auto; padding: 16px;"> | |
| <h2 style="margin: 0 0 4px 0; color: {_TEXT}; font-size: 22px; font-weight: 700; | |
| letter-spacing: -0.02em;"> | |
| Integration Architecture | |
| </h2> | |
| <p style="color: {_TEXT_DIM}; font-size: 13px; margin: 0 0 20px 0; line-height: 1.5;"> | |
| Seven phases from raw transaction data to production fraud scoring. | |
| Each phase has a clear input, output, and set of decisions. | |
| </p> | |
| <!-- Pipeline flow --> | |
| <div style="display: flex; align-items: center; justify-content: center; gap: 6px; | |
| margin-bottom: 24px; padding: 10px 0; flex-wrap: wrap;"> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Schema</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Tokenize</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Embed</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Backbone</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Pretrain</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Heads</span> | |
| <span style="color: {_TEXT_DIM}; font-size: 12px;">→</span> | |
| <span style="padding: 5px 12px; background: {_TEXT}; color: #fff; | |
| border-radius: 9999px; font-family: {_FONT_MONO}; | |
| font-size: 10px; font-weight: 600;">Deploy</span> | |
| </div> | |
| <!-- Phase cards --> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px;"> | |
| {_phase_card("1", "Schema Design", | |
| "Define your features, vocab sizes, and feature ordering. This is the contract " | |
| "between your data team and your ML team. Three feature types: categorical " | |
| "(direct index), ordinal (hour, day-of-week), and bucketed-continuous (amount " | |
| "into quantile bins). Spend two weeks here.", | |
| "3 reserved tokens per feature (MASK, OOV, NULL) | " | |
| "Order features by semantic family for the conv window | " | |
| "Embed schema fingerprint in checkpoint metadata")} | |
| {_phase_card("2", "Tokenization", | |
| "Convert raw transaction fields into integer token IDs. Categorical features " | |
| "map directly to vocab indices. Continuous values (amount, days-since-last) get " | |
| "quantile-bucketed into N bins. High-cardinality features (merchant_id) need the " | |
| "long tail bucketed or factored into orthogonal features.", | |
| "amount → 16-256 quantile bins | " | |
| "merchant_id: top 10K distinct, rest into ~1K frequency buckets | " | |
| "Unseen values at inference → OOV token (ID 1)")} | |
| {_phase_card("3", "Structured Embedding", | |
| "One embedding table per feature (sized to its vocab) plus a feature-type table. " | |
| "Summed to produce the (B, T*F, D) tensor the backbone expects. " | |
| "No raw continuous features -- everything goes through an embedding table.", | |
| "value_tables[f](token) + type_table(f) | " | |
| "High-cardinality features dominate param budget -- " | |
| "bucket the merchant long tail")} | |
| {_phase_card("4", "Backbone Config", | |
| "Start from a published LFM2 scale point (350M, 700M, 1.2B, 2.6B). " | |
| "Keep the conv-to-attention ratio, GQA config, SwiGLU MLP, and RoPE theta. " | |
| "Do not deviate without a specific reason.", | |
| "10:6 conv:attn at 1.2B | 32Q/8KV GQA | " | |
| "QK-RMSNorm before RoPE | theta=1M | " | |
| "First and last layers are conv")} | |
| {_phase_card("5", "Pretraining", | |
| "Self-supervised on your unlabeled transactions. No fraud labels needed. " | |
| "Causal next-feature prediction or masked-transaction prediction. " | |
| "Average per-feature losses (do NOT sum).", | |
| "AdamW lr=3e-4, betas=(0.9, 0.95), wd=0.1 | " | |
| "Cosine decay to 10% | BF16 (loss in FP32) | " | |
| "Chinchilla: ~20 tokens per parameter")} | |
| {_phase_card("6", "Downstream Heads", | |
| "Attach task-specific heads. The critical decision: " | |
| "TiedEmbeddingHead for features that were in pretraining vocab " | |
| "(next_merchant, MCC). Fresh MLP for everything else (fraud, disputes).", | |
| "Tied head: adapter(h) @ embedding.weight.T (+50% accuracy) | " | |
| "Pool: last_tx_mean for sequence tasks, pre_last_tx for next-tx | " | |
| "Dual LR: backbone 5e-5, heads 1e-3")} | |
| </div> | |
| <!-- Deployment gets its own full-width card --> | |
| <div style="margin-bottom: 20px;"> | |
| {_phase_card("7", "Deployment", | |
| "KV cache only on 6 attention layers (not 16). Dynamic batching with " | |
| "5-10ms collection window. Conv-dominant models quantize cleanly to INT8. " | |
| "Same model runs on GPU or CPU.", | |
| "LFM2 @ 3,840 tokens: ~25 GB KV at 1K concurrent | " | |
| "Pure attn: ~64 GB | " | |
| "Sub-100ms on H100 for real-time auth decisioning")} | |
| </div> | |
| <!-- Gotchas --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 20px;"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_TEXT}; margin-bottom: 8px;"> | |
| Top Gotchas | |
| </div> | |
| {_gotcha("1", "Per-feature loss summing", | |
| "high-cardinality features dominate. Average, don't sum.")} | |
| {_gotcha("2", "Fresh MLP for pretrained features", | |
| "next_merchant stays at random. Use TiedEmbeddingHead.")} | |
| {_gotcha("3", "Schema-checkpoint drift", | |
| "training on schema v3, deploying on v2. Embed fingerprint in metadata.")} | |
| {_gotcha("4", "Frozen backbone", | |
| "PR-AUC drops from 0.96 to 0.16. Plan to fine-tune.")} | |
| {_gotcha("5", "Pool strategy leak", | |
| "last_tx_mean for next-tx prediction leaks the target. Use pre_last_tx.")} | |
| </div> | |
| <!-- Engagement model --> | |
| <div style="padding: 16px 20px; background: {_BG_CARD}; border: 1px solid {_BORDER}; | |
| border-radius: {_RADIUS_CARD}; margin-bottom: 16px;"> | |
| <div style="font-size: 14px; font-weight: 600; color: {_TEXT}; margin-bottom: 10px;"> | |
| Typical Engagement | |
| </div> | |
| <table style="width: 100%; border-collapse: collapse;"> | |
| <tr style="border-bottom: 1px solid {_BORDER};"> | |
| <th style="padding: 6px 10px; text-align: left; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Phase</th> | |
| <th style="padding: 6px 10px; text-align: left; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; font-weight: 600;">Duration</th> | |
| <th style="padding: 6px 10px; text-align: left; font-size: 10px; color: {_TEXT_DIM}; | |
| text-transform: uppercase; font-weight: 600;">What Happens</th> | |
| </tr> | |
| <tr style="border-bottom: 1px solid {_BORDER_SUBTLE};"> | |
| <td style="padding: 5px 10px; font-size: 12px; font-weight: 600; | |
| color: {_TEXT};">Discovery</td> | |
| <td style="padding: 5px 10px; font-family: {_FONT_MONO}; font-size: 11px; | |
| color: {_TEXT_MUTED};">2-4 weeks</td> | |
| <td style="padding: 5px 10px; font-size: 12px; color: {_TEXT_MUTED};"> | |
| Schema definition, data sample (~1M sequences), compliance review, architectural fit assessment</td> | |
| </tr> | |
| <tr style="border-bottom: 1px solid {_BORDER_SUBTLE};"> | |
| <td style="padding: 5px 10px; font-size: 12px; font-weight: 600; | |
| color: {_TEXT};">POC</td> | |
| <td style="padding: 5px 10px; font-family: {_FONT_MONO}; font-size: 11px; | |
| color: {_TEXT_MUTED};">2 weeks</td> | |
| <td style="padding: 5px 10px; font-size: 12px; color: {_TEXT_MUTED};"> | |
| Pretrain + fine-tune on your data sample, measurement report, go/no-go recommendation</td> | |
| </tr> | |
| <tr style="border-bottom: 1px solid {_BORDER_SUBTLE};"> | |
| <td style="padding: 5px 10px; font-size: 12px; font-weight: 600; | |
| color: {_TEXT};">Production</td> | |
| <td style="padding: 5px 10px; font-family: {_FONT_MONO}; font-size: 11px; | |
| color: {_TEXT_MUTED};">3-6 months</td> | |
| <td style="padding: 5px 10px; font-size: 12px; color: {_TEXT_MUTED};"> | |
| Engineering team builds, Liquid provides architectural support, weekly design review</td> | |
| </tr> | |
| <tr> | |
| <td style="padding: 5px 10px; font-size: 12px; font-weight: 600; | |
| color: {_TEXT};">Scale</td> | |
| <td style="padding: 5px 10px; font-family: {_FONT_MONO}; font-size: 11px; | |
| color: {_TEXT_MUTED};">Ongoing</td> | |
| <td style="padding: 5px 10px; font-size: 12px; color: {_TEXT_MUTED};"> | |
| Operations, monitoring, retraining cadence, architecture evolution</td> | |
| </tr> | |
| </table> | |
| </div> | |
| <div style="font-family: {_FONT_MONO}; font-size: 10px; color: {_TEXT_DIM}; text-align: center;"> | |
| Full guide: docs/integration-guide.md · | |
| Architecture: <a href="https://arxiv.org/abs/2511.23404" style="color: {_TEXT_DIM}; | |
| text-decoration: underline;">arXiv 2511.23404</a> | |
| </div> | |
| </div> | |
| """ | |