Kina.ai

Specification

Phase 1, Section 23: StoryLM-0 32-token checkpoint rollout

StoryLM-0 decode slice. Not a Phase 1 exit-criteria replacement. Not a new primitive. Uses the storylm0_forward.kina algebra at a static T = 36, Section 17 argmax, and Section 18 Gumbel-max. Tokenization stays on the host.


1. What this section commits to

Companion 47’s first generation acceptance test asks for a fixed tiny checkpoint, a prompt of token ids, 32 greedy tokens, a second seeded sample run, and the causal-leak check. Sections 20–22 stop at three generated tokens and T_max = 5. Polymorphic S and in-place writes are still unspecified. This section locks that test without those features.

The instance is a host loop around one static forward:

There is no generate keyword, no in-graph PRNG, and no write into a T_max cache.


2. Why not a primitive

gather, rank-3 / rank-4 matmul, softmax, broadcast, argmax, log, and neg are already specified. Thirty-two static-S decode clones would repeat Section 20 without a polymorphic calling convention. A fused rollout op would invent a token clock and a checkpoint ABI.

Re-forwarding the existing causal graph at a compile-time T is the functional encoding of “generate 32 tokens from a frozen tiny checkpoint.” The host mutates a NumPy id buffer; Kina functions stay pure.


3. Operands (numeric instance)

Widths match storylm0_forward.kina except the time axis: B = 1, T = 36, H = 2, Dh = 2, D = 4, V = 8. Host tensors. Prompt [1, 4, 2, 6] (same ids as the forward numeric check). Pad id 0.

Name Type Role
token_ids Tensor[I64, [1, 36], @host] prompt ++ pad / generated
token_embedding Tensor[F32, [8, 4], @host] fixture embed
causal_mask Tensor[F32, [1, 1, 36, 36], @host] additive causal mask
scale Tensor[F32, [1, 1, 1, 1], @host] 1/sqrt(Dh)
wq wk wv wo Tensor[F32, [4, 4], @host] fixture projections
lm_head Tensor[F32, [4, 8], @host] fixture vocabulary

Forward result: logits : Tensor[F32, [1, 36, 8], @host].

Row decode (one live site):

Name Type Role
row Tensor[F32, [1, 1, 8], @host] host-sliced last live logits
u Tensor[F32, [1, 1, 8], @host] host Uniform(ε, 1-ε)
temperature Tensor[F32, [1, 1], @host] T = 0.8

greedy_row is Section 17 argmax on axis 2: Tensor[I64, [1, 1], @host]. sample_row is Section 18 Gumbel-max on that row.

Weight broadcast is [D, D] → [1, D, D] and [D, V] → [1, D, V], same as Section 5. Batched [1, 36, 4] @ [1, 4, 4] is existing rank-3 matmul. Do not broadcast weights to [1, 36, 4]; T ≠ D.


4. Operational meaning

tokens = prompt ++ [pad] * 32              # length 36
for s in 0 .. 31:
    logits = storylm0_rollout(tokens, …)   # [1, 36, 8]
    row    = host slice logits[:, 3+s, :]  # [1, 1, 8]
    t      = greedy_row(row)               # or sample_row
    tokens[4 + s] = t
sequence = tokens                          # 36 class ids

The first step reads the last prompt site (index 3) and writes index 4. Later steps read the token just written. Pad ids sit only in the causal future of the live prefix, so logits[:, 0:4, :] on the initial padded buffer must match storylm0_forward on [1, 4, 2, 6].

Changing a future id must not alter earlier logit rows. Two greedy runs on the same fixture must match. Two sampled runs that reuse the same Uniform stream must match.

Weights are the Section 5 patterned recipe, stored as a host fixture. They are not trained.


5. Typing (derived)

Each line is existing gather / broadcast / matmul / reshape / transpose / softmax / argmax / log / neg / div / add typing. T = 36 is static. The token buffer’s type does not change across host steps.


6. Surface instance

storylm0_rollout.kina binds greedy_row, sample_row, and storylm0_rollout. @main calls the forward with host placeholders. The numeric check loads those fns from the same .so.

Fixture (host-owned, not a compiler ABI):

tests/compiler/fixtures/storylm0/
  manifest.json     format storylm0-checkpoint-v0
  checkpoint.npz    embed, wq, wk, wv, wo, lm_head, scale
  vocab.json        eight class names; index 0 is <pad>

No new tokens. The loop sits outside any reverseMode function. @mesh does not appear.


7. Tests


8. Out of scope


9. Open issues

  1. Prefill-T family. One cache-returning forward per prompt length is still the Section 21 stance.
  2. In-place write / polymorphic S. Still unspecified.
  3. Top-k / top-p. Need a specified sort or prefix selection.
  4. Trained fixture. Specified in Section 27. The patterned v0 fixture remains this section’s regression input.