| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Prefix ambiguity, in a vocabulary that holds five plausible next tokens</title> |
| <meta name="color-scheme" content="light"> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600&display=swap"> |
| <style> |
| |
| :root { |
| --bg: #f7f5ee; |
| --ink: #1f1f1d; |
| --ink-soft: #5b5b56; |
| --ink-faint: #8a8a83; |
| --rule: #e3e1d6; |
| --hair: #eee; |
| --green: #317f3f; |
| --green-dark: #1f5024; |
| --green-tint: #f4f8f4; |
| --amber: #b8862c; |
| --amber-dark: #6b4d18; |
| --red: #b00020; |
| --blue: #2c5aa0; |
| --card: #fff; |
| --soft-cream: #fafaf6; |
| --base-a: #1A7A40; |
| --base-t: #b00020; |
| --base-c: #2c5aa0; |
| --base-g: #b8862c; |
| } |
| * { margin: 0; padding: 0; box-sizing: border-box; } |
| html { scroll-behavior: smooth; } |
| body { |
| font-family: "Inter", "Helvetica Neue", sans-serif; |
| font-size: 14px; font-weight: 300; line-height: 1.7; |
| color: var(--ink); |
| background: var(--bg); |
| } |
| ::-webkit-scrollbar { width: 8px; height: 8px; } |
| ::-webkit-scrollbar-thumb { background: #ccc; border-radius: 4px; } |
| ::-webkit-scrollbar-track { background: transparent; } |
| |
| |
| .page-header { |
| border-bottom: 1px solid var(--rule); |
| background: var(--bg); |
| position: sticky; top: 0; z-index: 50; |
| backdrop-filter: saturate(180%) blur(6px); |
| } |
| .page-header__inner { |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 14px 32px; |
| display: flex; align-items: baseline; gap: 16px; |
| } |
| .wordmark { |
| font-family: "JetBrains Mono", monospace; |
| font-weight: 700; |
| font-size: 16px; |
| letter-spacing: 1px; |
| } |
| .wordmark .caret { color: var(--green); margin-right: 4px; } |
| .wordmark__sub { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; font-weight: 500; |
| text-transform: uppercase; letter-spacing: 2px; |
| color: var(--ink-soft); |
| margin-left: 4px; |
| } |
| .page-header__spacer { flex: 1; } |
| .page-header__crumbs { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; letter-spacing: 1.4px; |
| text-transform: uppercase; color: var(--ink-faint); |
| } |
| .page-header__crumbs a { color: var(--ink-soft); text-decoration: none; } |
| .page-header__crumbs a:hover { color: var(--green); } |
| |
| |
| .tab-lede { |
| max-width: 1200px; margin: 56px auto 0; |
| padding: 0 32px; |
| } |
| .tab-lede__rail { |
| border-left: 3px solid var(--green); |
| padding: 4px 0 4px 22px; |
| max-width: 820px; |
| } |
| .tab-lede__eyebrow { |
| display: block; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; font-weight: 500; |
| letter-spacing: 0.22em; text-transform: uppercase; |
| color: var(--green); margin-bottom: 12px; |
| } |
| .tab-lede__title { |
| margin: 0 0 22px; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 34px; font-weight: 500; |
| letter-spacing: -0.01em; line-height: 1.12; |
| color: var(--ink); |
| } |
| .tab-lede__lead { |
| margin: 0; max-width: 760px; |
| font-family: "Inter", sans-serif; |
| font-size: 19px; font-weight: 300; line-height: 1.5; |
| letter-spacing: -0.005em; color: #2d2d2a; |
| } |
| |
| |
| .post { |
| max-width: 760px; |
| margin: 32px auto 0; |
| padding: 0 32px 96px; |
| } |
| .post h2 { |
| margin: 64px 0 18px; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 22px; font-weight: 500; |
| letter-spacing: -0.005em; line-height: 1.3; |
| color: var(--ink); |
| padding-top: 12px; |
| border-top: 1px solid var(--rule); |
| } |
| .post h2:first-child { border-top: none; padding-top: 0; } |
| .post h3 { |
| margin: 40px 0 12px; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 15px; font-weight: 500; |
| letter-spacing: 0; |
| color: var(--ink); |
| text-transform: uppercase; |
| letter-spacing: 0.5px; |
| } |
| .post p { margin: 0 0 14px; } |
| .post p > code, .post li > code { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 0.86em; |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| padding: 1px 5px; |
| border-radius: 2px; |
| color: var(--green-dark); |
| } |
| .post pre { |
| margin: 14px 0 18px; |
| padding: 14px 16px; |
| background: var(--card); |
| border: 1px solid #ddd; |
| overflow-x: auto; |
| } |
| .post pre code { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 12px; line-height: 1.6; |
| color: var(--ink); |
| background: transparent; border: none; padding: 0; |
| } |
| .post a { |
| color: var(--green-dark); |
| text-decoration: underline; |
| text-decoration-thickness: 1px; |
| text-underline-offset: 2px; |
| } |
| .post a:hover { color: var(--green); } |
| .post strong { font-weight: 600; color: var(--ink); } |
| .post-image { |
| margin: 24px 0; |
| } |
| .post-image img { |
| display: block; |
| width: 100%; height: auto; |
| border: 1px solid var(--rule); |
| } |
| |
| |
| .widget { |
| max-width: 920px; |
| margin: 40px auto 8px; |
| } |
| .widget__head { |
| display: flex; align-items: baseline; gap: 14px; |
| margin-bottom: 6px; |
| } |
| .widget__eyebrow { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; font-weight: 500; |
| letter-spacing: 0.22em; text-transform: uppercase; |
| color: var(--green); |
| } |
| .widget__title { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 14px; font-weight: 500; |
| color: var(--ink); letter-spacing: 0; |
| } |
| .widget__caption { |
| font-family: "Inter", sans-serif; |
| font-size: 12px; color: var(--ink-soft); |
| margin: 8px 4px 14px; |
| line-height: 1.5; |
| } |
| .demo { |
| background: var(--card); border: 1px solid #ddd; |
| padding: 22px; margin: 8px 0; |
| } |
| .demo-toolbar { |
| display: flex; gap: 8px; align-items: center; flex-wrap: wrap; |
| margin-bottom: 14px; |
| font-family: "JetBrains Mono", monospace; font-size: 10px; |
| color: #666; text-transform: uppercase; letter-spacing: 1.4px; |
| } |
| .demo-toolbar .spacer { flex: 1; } |
| .demo-label { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9.5px; color: #6b7a6e; |
| text-transform: uppercase; letter-spacing: 1.6px; |
| margin: 6px 0 6px; |
| } |
| |
| .pill, button.action { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; font-weight: 400; |
| padding: 5px 11px; border: 1px solid #ccc; border-radius: 3px; |
| background: #fff; color: #555; cursor: pointer; |
| text-transform: uppercase; letter-spacing: 1.5px; |
| transition: all 0.12s; |
| } |
| .pill:hover, button.action:hover { border-color: #888; color: var(--ink); } |
| .pill.active, button.action.primary { background: var(--ink); color: #fff; border-color: var(--ink); } |
| .pill.active:hover, button.action.primary:hover { background: #000; } |
| .pill.gh { background: var(--green); color: #fff; border-color: var(--green); } |
| .pill.gh:hover { background: var(--green-dark); border-color: var(--green-dark); } |
| .pills { display: inline-flex; flex-wrap: wrap; gap: 6px; } |
| .status { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; color: #666; |
| text-transform: uppercase; letter-spacing: 1.5px; |
| display: inline-flex; align-items: center; gap: 6px; |
| margin-left: 8px; |
| } |
| .status .dot { |
| display: inline-block; width: 6px; height: 6px; border-radius: 50%; |
| background: var(--green); |
| } |
| |
| input.seq-input, textarea.seq-input { |
| width: 100%; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 13px; |
| padding: 9px 12px; |
| border: 1px solid #ccc; |
| border-radius: 3px; |
| letter-spacing: 1px; |
| text-transform: uppercase; |
| color: var(--ink); |
| background: var(--soft-cream); |
| resize: vertical; |
| } |
| textarea.seq-input { letter-spacing: 0.5px; } |
| input.seq-input:focus, textarea.seq-input:focus { |
| outline: none; |
| border-color: var(--green); |
| background: #fff; |
| } |
| |
| |
| .base, .tok { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; |
| letter-spacing: 0.5px; |
| } |
| .base { |
| display: inline-block; |
| padding: 2px 5px; |
| font-weight: 500; |
| margin: 1px; |
| color: #fff; |
| border-radius: 2px; |
| min-width: 16px; |
| text-align: center; |
| } |
| .base.A { background: var(--base-a); } |
| .base.T { background: var(--base-t); } |
| .base.C { background: var(--base-c); } |
| .base.G { background: var(--base-g); } |
| .base.dim { opacity: 0.4; } |
| .base.outline { |
| background: transparent; |
| border: 1px solid currentColor; |
| } |
| .base.outline.A { color: var(--base-a); } |
| .base.outline.T { color: var(--base-t); } |
| .base.outline.C { color: var(--base-c); } |
| .base.outline.G { color: var(--base-g); } |
| |
| .tok { |
| display: inline-flex; |
| align-items: center; |
| padding: 4px 8px; |
| margin: 2px; |
| border: 1px solid #ccc; |
| border-radius: 3px; |
| background: #fff; |
| color: var(--ink); |
| } |
| .tok.kmer { |
| background: rgba(49,127,63,0.10); |
| border-color: rgba(49,127,63,0.5); |
| color: var(--green-dark); |
| font-weight: 500; |
| } |
| .tok.bpe { |
| background: rgba(184,134,44,0.10); |
| border-color: rgba(184,134,44,0.5); |
| color: var(--amber-dark); |
| } |
| .tok.text { |
| background: #fff; |
| border-color: #ccc; |
| color: var(--ink); |
| } |
| .tok.boundary { |
| background: var(--ink); |
| color: #fff; |
| border-color: var(--ink); |
| text-transform: uppercase; |
| letter-spacing: 1px; |
| font-size: 10px; |
| } |
| .tok.dim { color: #888; background: var(--soft-cream); } |
| .tok.ok { background: var(--green); color: #fff; border-color: var(--green); } |
| .tok.bad { color: var(--red); border-color: rgba(176,0,32,0.4); background: rgba(176,0,32,0.05); } |
| .tok.selected { |
| outline: 2px solid var(--green); |
| outline-offset: 1px; |
| } |
| .token-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0; } |
| |
| |
| .count-badge { |
| display: inline-block; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; font-weight: 600; |
| background: var(--ink); color: var(--bg); |
| padding: 2px 7px; border-radius: 2px; |
| letter-spacing: 1px; |
| } |
| .count-badge.green { background: var(--green); color: #fff; } |
| .count-badge.amber { background: var(--amber); color: #fff; } |
| |
| |
| .tk-anim { margin-top: 18px; } |
| .tk-source, .tk-scheme { |
| display: grid; |
| grid-template-columns: 124px 1fr; |
| gap: 18px; |
| align-items: start; |
| padding: 8px 0; |
| } |
| .tk-scheme { padding: 10px 0; min-height: 32px; } |
| .tk-source { padding-bottom: 14px; border-bottom: 1px solid var(--rule); margin-bottom: 6px; } |
| .tk-meta { |
| display: flex; |
| flex-direction: column; |
| gap: 3px; |
| padding-top: 2px; |
| } |
| .tk-label { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9.5px; |
| font-weight: 500; |
| color: var(--ink-soft); |
| text-transform: uppercase; |
| letter-spacing: 1.6px; |
| } |
| .tk-stat { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; |
| color: var(--ink-faint); |
| letter-spacing: 0.5px; |
| font-variant-numeric: tabular-nums; |
| } |
| .tk-stat .n { |
| font-weight: 600; |
| color: var(--ink); |
| } |
| .tk-scheme[data-scheme="bpe"] .tk-stat .n { color: var(--amber-dark); } |
| .tk-scheme[data-scheme="kmer"] .tk-stat .n { color: var(--green-dark); } |
| |
| |
| .tk-source-strip { |
| display: flex; |
| flex-wrap: wrap; |
| row-gap: 2px; |
| } |
| .tk-source-strip .tk-base { |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| width: 13px; |
| height: 17px; |
| color: #fff; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; |
| font-weight: 500; |
| border-radius: 1px; |
| flex: 0 0 13px; |
| transition: opacity 0.35s ease, filter 0.35s ease; |
| } |
| .tk-source-strip .tk-base + .tk-base { margin-left: 1px; } |
| .tk-source-strip .tk-base.consumed { opacity: 0.18; filter: grayscale(0.6); } |
| .tk-base.A { background: var(--base-a); } |
| .tk-base.T { background: var(--base-t); } |
| .tk-base.C { background: var(--base-c); } |
| .tk-base.G { background: var(--base-g); } |
| |
| |
| .tk-scheme-strip { |
| display: flex; |
| flex-wrap: wrap; |
| gap: 1px 8px; |
| min-height: 20px; |
| } |
| .tk-token { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 12px; |
| font-weight: 500; |
| letter-spacing: 0.5px; |
| display: inline-flex; |
| align-items: center; |
| opacity: 0; |
| will-change: transform, opacity; |
| } |
| .tk-token.dropped { |
| opacity: 1; |
| transition: |
| transform 0.48s cubic-bezier(0.22, 1, 0.36, 1), |
| opacity 0.32s ease; |
| } |
| .tk-token .br { color: var(--ink-faint); font-weight: 400; } |
| .tk-token.tail .br { color: var(--ink-faint); } |
| .tk-token.tail { opacity: 0.55; } |
| .tk-token.tail.dropped { opacity: 0.55; } |
| |
| |
| |
| .grid-3 { |
| display: grid; |
| grid-template-columns: 1fr 1fr 1fr; |
| gap: 14px; |
| margin-top: 14px; |
| } |
| .grid-2 { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: 14px; |
| margin-top: 14px; |
| } |
| @media (max-width: 720px) { |
| .grid-3, .grid-2 { grid-template-columns: 1fr; } |
| } |
| .col-card { |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| padding: 14px; |
| } |
| .col-card .col-title { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; font-weight: 500; |
| letter-spacing: 1.6px; text-transform: uppercase; |
| color: var(--ink-soft); |
| margin-bottom: 8px; |
| } |
| .col-card .col-foot { |
| margin-top: 10px; |
| display: flex; align-items: center; gap: 8px; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; color: var(--ink-soft); |
| text-transform: uppercase; letter-spacing: 1.4px; |
| } |
| |
| |
| .bar-row { |
| display: grid; |
| grid-template-columns: 18px 1fr 64px; |
| align-items: center; |
| gap: 8px; |
| margin: 3px 0; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; |
| } |
| .bar-row .bar-label { color: var(--ink-soft); font-weight: 500; text-align: center; } |
| .bar-row .bar-track { |
| position: relative; |
| height: 14px; |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| } |
| .bar-row .bar-fill { |
| height: 100%; |
| transition: width 220ms ease, background-color 220ms ease; |
| } |
| .bar-row .bar-val { text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; } |
| .bar-row.highlight .bar-track { box-shadow: 0 0 0 2px var(--green-tint); } |
| |
| |
| .posgrid { |
| display: grid; |
| grid-template-columns: repeat(6, 1fr); |
| gap: 8px; |
| } |
| .posgrid__col { |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| border-radius: 2px; |
| padding: 8px 6px 6px; |
| } |
| .posgrid__pos { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9px; color: var(--ink-faint); |
| text-transform: uppercase; letter-spacing: 1.4px; |
| text-align: center; margin-bottom: 6px; |
| } |
| .posgrid__bars { |
| display: flex; flex-direction: column; gap: 3px; |
| } |
| .posgrid .mini-row { |
| display: grid; grid-template-columns: 12px 1fr 32px; |
| align-items: center; gap: 4px; |
| font-family: "JetBrains Mono", monospace; font-size: 10px; |
| } |
| .posgrid .mini-row .ml { color: var(--ink-soft); text-align: center; font-weight: 500; } |
| .posgrid .mini-row .mt { position: relative; height: 10px; background: #fff; border: 1px solid var(--rule); } |
| .posgrid .mini-row .mf { display: block; height: 100%; transition: width 200ms ease; } |
| .posgrid .mini-row .mv { text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; font-size: 9.5px; } |
| .posgrid__col.argmax-A { box-shadow: inset 0 0 0 1px var(--base-a); } |
| .posgrid__col.argmax-T { box-shadow: inset 0 0 0 1px var(--base-t); } |
| .posgrid__col.argmax-C { box-shadow: inset 0 0 0 1px var(--base-c); } |
| .posgrid__col.argmax-G { box-shadow: inset 0 0 0 1px var(--base-g); } |
| .posgrid__col.locked { background: #fff; } |
| .posgrid__col.frozen .posgrid__bars { opacity: 0.4; } |
| .posgrid__sel { display: flex; gap: 3px; margin-top: 8px; } |
| .cond-pick { |
| flex: 1 1 0; min-width: 0; |
| font-family: "JetBrains Mono", monospace; font-size: 10px; font-weight: 600; |
| padding: 3px 0; border: 1px solid var(--rule); border-radius: 2px; |
| background: #fff; cursor: pointer; |
| transition: background 0.12s, border-color 0.12s, color 0.12s; |
| } |
| .cond-pick:hover { border-color: #888; } |
| .cond-pick.active { color: #fff; } |
| .cond-pick.active.b-A { background: var(--base-a); border-color: var(--base-a); } |
| .cond-pick.active.b-T { background: var(--base-t); border-color: var(--base-t); } |
| .cond-pick.active.b-C { background: var(--base-c); border-color: var(--base-c); } |
| .cond-pick.active.b-G { background: var(--base-g); border-color: var(--base-g); } |
| |
| |
| .w3-itok { cursor: pointer; transition: outline-color 0.12s; } |
| .w3-itok:hover { border-color: #888; } |
| .w3-sub { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; color: var(--ink-soft); |
| margin: 2px 0 10px; line-height: 1.7; |
| } |
| .w3-sub b { color: var(--ink); font-weight: 600; } |
| .w3-sub .tok { margin: 0 2px; } |
| .w3-toprow { |
| display: grid; |
| grid-template-columns: 92px 1fr 52px; |
| gap: 12px; align-items: center; |
| margin: 4px 0; |
| font-family: "JetBrains Mono", monospace; font-size: 11px; |
| } |
| .w3-toprow .km { font-weight: 500; letter-spacing: 0.5px; } |
| .w3-toprow .bar { height: 13px; background: var(--soft-cream); border: 1px solid var(--rule); } |
| .w3-toprow .fill { height: 100%; background: var(--green); transition: width 0.35s ease; } |
| .w3-toprow .pct { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); } |
| .w3-toprow.observed .km { color: var(--ink); } |
| .w3-toprow.observed .fill { background: var(--amber); } |
| .w3-io { display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap; margin-top: 6px; } |
| .w3-io__group { display: flex; flex-direction: column; gap: 6px; } |
| .w3-io__lab { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9.5px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); |
| } |
| .w3-io__arrow { font-family: "JetBrains Mono", monospace; font-size: 16px; color: var(--ink-faint); padding-bottom: 5px; } |
| .w3-gt-tok { background: rgba(184,134,44,0.12); border-color: rgba(184,134,44,0.5) !important; } |
| .w3-gt-tok { text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 2px; } |
| .w3-chart { display: block; width: 100%; height: auto; margin-top: 6px; background: #fff; border: 1px solid #eee; } |
| .w3-legend { |
| display: flex; gap: 20px; flex-wrap: wrap; margin-top: 8px; |
| font-family: "JetBrains Mono", monospace; font-size: 10px; |
| color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; |
| } |
| .w3-legend span { display: inline-flex; align-items: center; gap: 6px; } |
| .w3-legend svg { width: 20px; height: 8px; display: inline-block; vertical-align: middle; } |
| .w3-top { display: flex; gap: 6px; margin-top: 12px; } |
| .w3-topchip { |
| flex: 1 1 0; min-width: 0; |
| display: inline-flex; flex-direction: column; align-items: center; gap: 2px; |
| font-family: "JetBrains Mono", monospace; |
| border: 1px solid var(--rule); background: var(--soft-cream); |
| border-radius: 3px; padding: 6px 4px; |
| } |
| .w3-topchip .km { font-size: 12px; font-weight: 500; letter-spacing: 0.5px; } |
| .w3-topchip.ground-truth .km { text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 2px; } |
| .w3-topchip .pct { font-size: 9px; color: var(--ink-soft); font-variant-numeric: tabular-nums; } |
| .posgrid__col.clickable { cursor: pointer; } |
| .posgrid__col.sel { outline: 2px solid var(--ink); outline-offset: 2px; } |
| .w3-allgrid { |
| display: grid; |
| grid-template-columns: repeat(128, 1fr); |
| gap: 1px; |
| margin-top: 8px; |
| } |
| .w3-cell { aspect-ratio: 1; background: #d3d0c4; transition: background 0.15s ease; } |
| .w3-cell.first { |
| outline: 2px solid var(--ink); |
| outline-offset: 1px; |
| position: relative; z-index: 2; |
| } |
| .w3-order { |
| display: inline-flex; align-items: center; gap: 8px; |
| font-family: "JetBrains Mono", monospace; font-size: 9.5px; |
| text-transform: uppercase; letter-spacing: 1.4px; color: var(--ink-faint); |
| } |
| .w3-snake { width: 42px; height: auto; color: var(--ink-soft); display: block; } |
| |
| |
| .cond-slots { display: flex; gap: 6px; } |
| .cond-slot { |
| width: 40px; height: 40px; |
| display: flex; align-items: center; justify-content: center; |
| border: 1px solid var(--rule); border-radius: 3px; background: var(--soft-cream); |
| font-family: "JetBrains Mono", monospace; font-size: 17px; font-weight: 600; |
| color: var(--ink); |
| } |
| .cond-slot.active { outline: 2px solid var(--ink); outline-offset: 1px; color: var(--ink-faint); } |
| .cond-slot.pending { color: var(--ink-faint); background: transparent; border-style: dashed; } |
| .cond-slot.A { background: rgba(26,122,64,0.13); border-color: rgba(26,122,64,0.42); color: var(--base-a); } |
| .cond-slot.T { background: rgba(176,0,32,0.09); border-color: rgba(176,0,32,0.36); color: var(--base-t); } |
| .cond-slot.C { background: rgba(44,90,160,0.11); border-color: rgba(44,90,160,0.40); color: var(--base-c); } |
| .cond-slot.G { background: rgba(184,134,44,0.14); border-color: rgba(184,134,44,0.42); color: var(--amber-dark); } |
| .cond-choices { display: flex; gap: 10px; } |
| .cond-choice { |
| flex: 1 1 0; cursor: pointer; border: 1px solid var(--rule); border-radius: 3px; |
| padding: 10px 12px; background: var(--soft-cream); |
| display: flex; flex-direction: column; gap: 7px; |
| transition: background 0.12s, border-color 0.12s; |
| } |
| .cond-choice:hover { background: #fff; border-color: #888; } |
| .cond-choice__top { display: flex; justify-content: space-between; align-items: baseline; font-family: "JetBrains Mono", monospace; } |
| .cond-choice__base { font-size: 16px; font-weight: 600; } |
| .cond-choice__pct { font-size: 11px; color: var(--ink-soft); font-variant-numeric: tabular-nums; } |
| .cond-choice__bar { height: 8px; background: #fff; border: 1px solid var(--rule); } |
| .cond-choice__fill { display: block; height: 100%; transition: width 0.25s ease; } |
| .cond-done { font-family: "JetBrains Mono", monospace; font-size: 13px; color: var(--ink); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } |
| .cond-note { |
| font-family: "Inter", sans-serif; font-size: 12px; color: var(--ink-soft); |
| background: var(--soft-cream); border-left: 2px solid var(--green); |
| padding: 9px 12px; margin-top: 14px; line-height: 1.5; |
| } |
| .cond-note .tok { margin: 0 2px; } |
| |
| |
| .fns-seq-input { |
| width: 120px; |
| text-align: center; |
| text-transform: uppercase; |
| } |
| .fns-viz { |
| font-family: "JetBrains Mono", monospace; |
| padding: 10px 0 6px; |
| } |
| .fns-truth, .fns-row { |
| display: grid; |
| grid-template-columns: 222px repeat(6, 34px) 28px; |
| align-items: center; |
| column-gap: 7px; |
| min-width: 480px; |
| } |
| .fns-truth { margin-bottom: 16px; } |
| .fns-row { margin: 12px 0; } |
| .fns-gtlabel { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; |
| font-weight: 400; |
| letter-spacing: 1.6px; |
| text-transform: uppercase; |
| color: var(--ink-faint); |
| } |
| .fns-eq { |
| font-size: 16px; |
| color: var(--ink); |
| text-align: right; |
| white-space: nowrap; |
| } |
| .fns-eq sub, .fns-eq sup { font-size: 11px; } |
| .fns-eq .sum { color: var(--ink-soft); } |
| .fns-bracket { |
| font-family: "Inter", sans-serif; |
| font-size: 34px; |
| font-weight: 200; |
| line-height: 0; |
| color: var(--ink-soft); |
| vertical-align: middle; |
| transform: scaleX(0.7); |
| display: inline-block; |
| } |
| .fns-box { |
| width: 30px; height: 30px; |
| display: inline-flex; align-items: center; justify-content: center; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 14px; font-weight: 600; |
| border-radius: 3px; border: 1px solid; |
| transition: background 0.15s, border-color 0.15s, color 0.15s; |
| } |
| .fns-box.A { background: rgba(26,122,64,0.13); border-color: rgba(26,122,64,0.42); color: var(--base-a); } |
| .fns-box.T { background: rgba(176,0,32,0.09); border-color: rgba(176,0,32,0.36); color: var(--base-t); } |
| .fns-box.C { background: rgba(44,90,160,0.11); border-color: rgba(44,90,160,0.40); color: var(--base-c); } |
| .fns-box.G { background: rgba(184,134,44,0.14); border-color: rgba(184,134,44,0.42); color: var(--amber-dark); } |
| .fns-box.wild { opacity: 0.38; } |
| .fns-loss { |
| margin-top: 20px; |
| padding-top: 16px; |
| border-top: 1px solid var(--rule); |
| font-family: "JetBrains Mono", monospace; |
| font-size: 16px; |
| color: var(--ink); |
| text-align: center; |
| } |
| .fns-loss sup, .fns-loss sub { font-size: 11px; } |
| .fns-loss .frac { display: inline-block; margin: 0 1px; } |
| .fns-loss .fns-term { margin: 0 3px; white-space: nowrap; } |
| .fns-explain { |
| margin-top: 18px; |
| padding-top: 16px; |
| border-top: 1px solid var(--rule); |
| font-family: "Inter", sans-serif; |
| font-size: 13px; |
| line-height: 1.62; |
| color: var(--ink-soft); |
| } |
| .fns-explain p { margin: 0 0 11px; } |
| .fns-explain p:last-child { margin-bottom: 0; } |
| .fns-explain strong { color: var(--ink); font-weight: 600; } |
| .fns-explain .mono { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 12px; |
| color: var(--ink); |
| } |
| .fns-explain .mono sup, .fns-explain .mono sub { font-size: 9px; } |
| |
| |
| .stat-tile { |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| padding: 14px 16px; |
| text-align: left; |
| } |
| .stat-tile__label { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; color: var(--ink-soft); |
| text-transform: uppercase; letter-spacing: 1.6px; |
| margin-bottom: 6px; |
| } |
| .stat-tile__value { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 26px; font-weight: 500; |
| color: var(--ink); |
| } |
| .stat-tile__sub { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 10px; color: var(--ink-soft); |
| margin-top: 4px; letter-spacing: 0.5px; |
| } |
| .stat-tile.green .stat-tile__value { color: var(--green-dark); } |
| .stat-tile.red .stat-tile__value { color: var(--red); } |
| |
| |
| .post-foot { |
| max-width: 760px; |
| margin: 64px auto 0; |
| padding: 24px 32px 64px; |
| border-top: 1px solid var(--rule); |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; color: var(--ink-soft); |
| text-transform: uppercase; letter-spacing: 1.4px; |
| } |
| .post-foot a { color: var(--green-dark); text-decoration: none; } |
| .post-foot a:hover { color: var(--green); } |
| |
| |
| .seq-track { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 14px; |
| letter-spacing: 0; |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| padding: 10px 12px; |
| display: flex; flex-wrap: wrap; gap: 1px; |
| user-select: none; |
| } |
| .seq-track__b { |
| display: inline-flex; align-items: center; justify-content: center; |
| width: 22px; height: 26px; |
| cursor: pointer; |
| border-radius: 2px; |
| color: #fff; |
| font-weight: 500; |
| transition: transform 0.1s ease, box-shadow 0.1s ease; |
| } |
| .seq-track__b:hover { transform: translateY(-1px); } |
| .seq-track__b.A { background: var(--base-a); } |
| .seq-track__b.T { background: var(--base-t); } |
| .seq-track__b.C { background: var(--base-c); } |
| .seq-track__b.G { background: var(--base-g); } |
| .seq-track__b.selected { |
| box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--bg); |
| } |
| |
| |
| .b-A, .b-T, .b-C, .b-G { font-weight: 500; } |
| .b-A { color: var(--base-a); } |
| .b-T { color: var(--base-t); } |
| .b-C { color: var(--base-c); } |
| .b-G { color: var(--base-g); } |
| |
| |
| .kmer-token, .raw-seq { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 12px; |
| font-weight: 500; |
| letter-spacing: 0.5px; |
| } |
| .kmer-token { |
| display: inline-flex; |
| align-items: center; |
| padding: 2px 0; |
| white-space: nowrap; |
| } |
| .kmer-token .br { color: var(--ink-faint); font-weight: 400; } |
| .kmer-token.muted { opacity: 0.45; } |
| .raw-seq { display: inline-flex; padding: 2px 0; } |
| |
| .bpe-flow { |
| display: flex; align-items: center; flex-wrap: wrap; |
| gap: 18px; |
| margin: 10px 0 8px; |
| } |
| .bpe-flow .arrow { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 16px; |
| color: var(--ink-faint); |
| } |
| |
| |
| .bpe-branches { |
| display: grid; |
| grid-template-columns: auto 96px 1fr; |
| grid-template-rows: auto 150px; |
| gap: 0; |
| margin-top: 12px; |
| } |
| .branch-source { |
| grid-column: 1; grid-row: 2; |
| align-self: center; |
| display: flex; flex-direction: column; align-items: center; gap: 6px; |
| padding-right: 8px; |
| } |
| .branch-source__hint { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9px; color: var(--ink-faint); |
| text-transform: uppercase; letter-spacing: 1.6px; |
| } |
| .branch-lines { |
| grid-column: 2; grid-row: 2; |
| width: 96px; height: 150px; |
| display: block; |
| } |
| .branch-lines path { |
| fill: none; |
| stroke: #ccc; |
| stroke-width: 1.4; |
| transition: stroke 0.15s, stroke-width 0.15s; |
| } |
| .branch-lines path.selected { stroke: var(--green); stroke-width: 2.2; } |
| .branch-header { |
| grid-column: 3; grid-row: 1; |
| display: grid; |
| grid-template-columns: 100px 60px 60px; |
| gap: 18px; |
| padding: 0 12px 10px; |
| font-family: "JetBrains Mono", monospace; |
| font-size: 9.5px; |
| font-weight: 500; |
| letter-spacing: 1.6px; |
| text-transform: uppercase; |
| color: var(--ink-soft); |
| } |
| .branch-header > span { text-align: center; } |
| .branch-header > span:first-child { text-align: left; color: var(--ink-faint); } |
| .branch-targets { |
| grid-column: 3; grid-row: 2; |
| display: grid; |
| grid-template-rows: repeat(5, 26px); |
| row-gap: 5px; |
| align-content: center; |
| justify-content: start; |
| height: 150px; |
| } |
| .cand-row { |
| display: grid; |
| grid-template-columns: 100px 60px 60px; |
| gap: 18px; |
| align-items: center; |
| padding: 2px 12px; |
| cursor: pointer; |
| border-radius: 2px; |
| transition: background 0.12s; |
| } |
| .cand-row:hover { background: rgba(0,0,0,0.03); } |
| .cand-row.selected { background: var(--green-tint); } |
| .mark { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 14px; |
| font-weight: 500; |
| text-align: center; |
| line-height: 1; |
| user-select: none; |
| } |
| .mark.ok { color: var(--green); } |
| .mark.bad { color: var(--red); } |
| |
| |
| .note { |
| font-family: "Inter", sans-serif; |
| font-size: 12px; line-height: 1.55; |
| color: var(--ink-soft); |
| background: var(--soft-cream); |
| border-left: 2px solid var(--green); |
| padding: 10px 12px; |
| margin-top: 14px; |
| } |
| .note code { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 11px; |
| background: #fff; |
| border: 1px solid var(--rule); |
| padding: 0 4px; border-radius: 2px; |
| color: var(--green-dark); |
| } |
| .formula { |
| font-family: "JetBrains Mono", monospace; |
| font-size: 12px; |
| background: var(--soft-cream); |
| border: 1px solid var(--rule); |
| padding: 10px 12px; |
| margin-top: 10px; |
| color: var(--ink); |
| overflow-x: auto; |
| } |
| .formula .hl { color: var(--green-dark); font-weight: 600; } |
| |
| |
| |
| |
| |
| body { padding: 20px 24px; background: #fff; } |
| .widget { max-width: 880px; margin: 0 auto; padding: 0; border: 0; } |
| .widget__head, .widget__caption { display: none; } |
| </style> |
| </head> |
| <body> |
| <aside class="widget" id="w2"> |
| <div class="widget__head"> |
| <span class="widget__eyebrow">§ Widget · 01</span> |
| <span class="widget__title">Prefix ambiguity, in a vocabulary that holds five plausible next tokens</span> |
| </div> |
| <p class="widget__caption"> |
| Line 1 shows how BPE segments the full sequence. Line 2 zooms into the step right after |
| <code><ACGTA></code>: the same DNA prefix can be extended by five different vocab entries, but only |
| one matches the original segmentation. Click a candidate to see how teacher forcing scores it. |
| </p> |
| <div class="demo"> |
| <div class="demo-label">Actual tokenization</div> |
| <div class="bpe-flow" id="w2-line1"></div> |
|
|
| <div class="demo-label" style="margin-top: 22px">Equivalent tokenization options</div> |
| <div class="bpe-branches"> |
| <div class="branch-source"> |
| <span class="branch-source__hint">input token</span> |
| <span id="w2-source"></span> |
| </div> |
| <svg class="branch-lines" id="w2-svg" viewBox="0 0 96 150" preserveAspectRatio="none" aria-hidden="true"> |
| |
| |
| |
| <path data-i="0" d="M 0 75 L 42 75 L 42 13 L 96 13" /> |
| <path data-i="1" d="M 0 75 L 42 75 L 42 44 L 96 44" /> |
| <path data-i="2" d="M 0 75 L 42 75 L 42 75 L 96 75" /> |
| <path data-i="3" d="M 0 75 L 42 75 L 42 106 L 96 106" /> |
| <path data-i="4" d="M 0 75 L 42 75 L 42 137 L 96 137" /> |
| </svg> |
| <div class="branch-header"> |
| <span>candidate</span> |
| <span>character level</span> |
| <span>token level</span> |
| </div> |
| <div class="branch-targets" id="w2-list"></div> |
| </div> |
|
|
| <div class="note" id="w2-note"> |
| Pick a row: BPE teacher forcing only credits <code><TCG></code> as correct, even though all five candidates |
| extend the next nine bases <span class="b-T">T</span><span class="b-C">C</span><span class="b-G">G</span><span class="b-T">T</span><span class="b-A">A</span><span class="b-T">T</span><span class="b-A">A</span><span class="b-G">G</span><span class="b-G">G</span> with no error. |
| </div> |
| </div> |
| </aside> |
| <script> |
| |
| |
| |
| |
| |
| |
| const BASES = ['A', 'T', 'C', 'G']; |
| const BASE_IDX = {A: 0, T: 1, C: 2, G: 3}; |
| const BASE_COLOR = { A: 'var(--base-a)', T: 'var(--base-t)', C: 'var(--base-c)', G: 'var(--base-g)' }; |
| |
| |
| function hash32(s) { |
| let h = 0x811c9dc5; |
| for (let i = 0; i < s.length; i++) { |
| h ^= s.charCodeAt(i); |
| h = Math.imul(h, 0x01000193); |
| } |
| return h >>> 0; |
| } |
| function rand01(seed) { |
| const h = hash32(String(seed)); |
| return (h % 1000003) / 1000003; |
| } |
| function softmax(arr) { |
| let m = -Infinity; |
| for (let i = 0; i < arr.length; i++) if (arr[i] > m) m = arr[i]; |
| const out = new Float64Array(arr.length); |
| let s = 0; |
| for (let i = 0; i < arr.length; i++) { |
| out[i] = Math.exp(arr[i] - m); |
| s += out[i]; |
| } |
| for (let i = 0; i < arr.length; i++) out[i] /= s; |
| return out; |
| } |
| function cleanDNA(s) { |
| return (s || '').toUpperCase().replace(/[^ACGT]/g, ''); |
| } |
| function escapeHTML(s) { |
| return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); |
| } |
| |
| |
| function kmerToIdx(k) { |
| let i = 0; |
| for (let p = 0; p < k.length; p++) { |
| const b = BASE_IDX[k[p]]; |
| if (b == null) return -1; |
| i = i * 4 + b; |
| } |
| return i; |
| } |
| function idxToKmer(i, k = 6) { |
| let s = ''; |
| for (let p = k - 1; p >= 0; p--) { |
| s = BASES[(i >> (2 * p)) & 3] + s; |
| } |
| return s; |
| } |
| function baseAt(i, p) { |
| |
| return (i >> (2 * (5 - p))) & 3; |
| } |
| |
| |
| function distribution4096(seed) { |
| const logits = new Float64Array(4096); |
| for (let i = 0; i < 4096; i++) { |
| const a = rand01(seed + ':a:' + i); |
| const b = rand01(seed + ':b:' + (i * 7919)); |
| const c = rand01(seed + ':c:' + (i * 65537)); |
| |
| logits[i] = (a + b + c - 1.5) * 3.2; |
| } |
| return softmax(logits); |
| } |
| function marginals6x4(probs) { |
| const m = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]; |
| for (let i = 0; i < 4096; i++) { |
| const p = probs[i]; |
| for (let pos = 0; pos < 6; pos++) { |
| m[pos][baseAt(i, pos)] += p; |
| } |
| } |
| return m; |
| } |
| function fmtPct(p) { return (p * 100).toFixed(2) + '%'; } |
| function fmt(p, d=4) { return Number(p).toFixed(d); } |
| |
| |
| function renderPosCol(parent, posIndex, dist4, mode) { |
| const max = Math.max(0.0001, ...dist4); |
| let argmax = 0; |
| for (let i = 1; i < 4; i++) if (dist4[i] > dist4[argmax]) argmax = i; |
| const col = document.createElement('div'); |
| col.className = 'posgrid__col' + (mode === 'argmax' ? ' argmax-' + BASES[argmax] : ''); |
| col.innerHTML = |
| `<div class="posgrid__pos">pos ${posIndex + 1}</div>` + |
| `<div class="posgrid__bars">` + |
| BASES.map((b, j) => { |
| const w = (dist4[j] / max) * 100; |
| const isMax = j === argmax; |
| return `<div class="mini-row"> |
| <span class="ml">${b}</span> |
| <span class="mt"><span class="mf" style="width:${w.toFixed(1)}%;background:${BASE_COLOR[b]};opacity:${isMax ? 1 : 0.55}"></span></span> |
| <span class="mv">${(dist4[j] * 100).toFixed(1)}</span> |
| </div>`; |
| }).join('') + |
| `</div>`; |
| parent.appendChild(col); |
| } |
| |
| function basesHTML(seq) { |
| return Array.from(seq).map((c) => `<span class="base ${c}">${c}</span>`).join(''); |
| } |
| |
| |
| |
| |
| |
| (function setupW2() { |
| |
| function colored(s) { |
| return Array.from(s).map((c) => 'ACGT'.includes(c) |
| ? `<span class="b-${c}">${c}</span>` |
| : c).join(''); |
| } |
| function kmerToken(s, klass = '') { |
| return `<span class="kmer-token ${klass}"><span class="br"><</span>${colored(s)}<span class="br">></span></span>`; |
| } |
| |
| |
| const SEQ = 'ACGTATCGTATAGG'; |
| const SEGMENTS = ['ACGTA', 'TCG', 'TATA', 'GG']; |
| const line1 = document.getElementById('w2-line1'); |
| line1.innerHTML = |
| `<span class="raw-seq">${colored(SEQ)}</span>` + |
| `<span class="arrow">→</span>` + |
| SEGMENTS.map((s) => kmerToken(s)).join(' '); |
| |
| |
| const CANDIDATES = [ |
| { tok: 'T', ok: false }, |
| { tok: 'TC', ok: false }, |
| { tok: 'TCG', ok: true }, |
| { tok: 'TCGT', ok: false }, |
| { tok: 'TCGTA', ok: false }, |
| ]; |
| const TRUE_CONT = 'TCGTATAGG'; |
| |
| const list = document.getElementById('w2-list'); |
| const note = document.getElementById('w2-note'); |
| const source = document.getElementById('w2-source'); |
| const svg = document.getElementById('w2-svg'); |
| let selected = 2; |
| |
| source.innerHTML = kmerToken('ACGTA'); |
| |
| function render() { |
| list.innerHTML = ''; |
| CANDIDATES.forEach((c, idx) => { |
| const row = document.createElement('div'); |
| row.className = 'cand-row' + (idx === selected ? ' selected' : ''); |
| row.innerHTML = |
| kmerToken(c.tok) + |
| `<span class="mark ok">✓</span>` + |
| `<span class="mark ${c.ok ? 'ok' : 'bad'}">${c.ok ? '✓' : '✗'}</span>`; |
| row.addEventListener('click', () => { selected = idx; render(); }); |
| list.appendChild(row); |
| }); |
| |
| |
| |
| svg.querySelectorAll('path[data-i]').forEach((p) => p.classList.remove('selected')); |
| const selPath = svg.querySelector(`path[data-i="${selected}"]`); |
| if (selPath) { |
| selPath.classList.add('selected'); |
| svg.appendChild(selPath); |
| } |
| |
| const c = CANDIDATES[selected]; |
| const matched = c.tok.length; |
| const matchSpan = Array.from(TRUE_CONT.slice(0, matched)) |
| .map((b) => `<span class="b-${b}">${b}</span>`).join(''); |
| const restSpan = Array.from(TRUE_CONT.slice(matched)) |
| .map((b) => `<span style="color:var(--ink-faint)">${b}</span>`).join(''); |
| note.innerHTML = c.ok |
| ? `<code><${c.tok}></code> matches the original BPE segmentation: this is the only candidate teacher forcing credits as correct. The other four predict ${matched - 1} or more bases correctly but still get full penalty.` |
| : `<code><${c.tok}></code> predicts the next ${matched} base${matched === 1 ? '' : 's'} of the continuation correctly (${matchSpan}${restSpan}). Teacher forcing scores it as a miss because the original BPE segmentation chose <code><TCG></code> instead.`; |
| } |
| render(); |
| })(); |
| </script> |
| </body> |
| </html> |