Generate num_steps tokens greedily from a tiny recurrent language model, running the decoding loop with jax.lax.scan.
The model keeps one hidden state per sequence. At step t it reads the previous token yt−1 and the previous hidden state ht−1, updates the state, scores every vocabulary entry, and picks the highest-scoring token.
ht=tanh(Eyt−1+ht−1Whh+bh),ℓt=htWout+bout yt=argvmaxℓt,v,rt=logsoftmax(ℓt)ytHere params is a dict holding the embedding table embed E of shape (V, H), whose row Ey is the vector for token y, the recurrent weights w_hh Whh of shape (H, H), the bias b_h bh of shape (H,), the output weights w_out Wout of shape (H, V) and the output bias b_out bout of shape (V,). V is the vocabulary size and H is the hidden size. The loop starts from y0 = start_tokens and h0 = h0, and steps t=1,…,T with T = num_steps. ℓt holds the V logits of step t, yt is the generated token and rt is its log probability. Every one of the B sequences in the batch runs the same rule independently.
Return a dict with two keys. tokens is an int32 JAX array of shape (B, num_steps) whose row b lists y1,…,yT for sequence b, and log_probs is a float32 JAX array of shape (B, num_steps) holding the matching rt values.
Input: params = {"embed":[[-0.3,-0.8],[1.5,0.0],[-0.8,0.2],[1.7,1.5]],"w_hh":[[-0.6,0.4],[-0.1,-0.2]],"b_h":[0.1,0.1],"w_out":[[-1.6,-0.3,3.2,-2.3],[-0.4,0.9,-0.3,-2.0]],"b_out":[0.4,-0.3,-0.3,0.2]}, start_tokens = [0], h0 = [[0.0,0.0]], num_steps = 3
Output: {"tokens":[[3,2,0]],"log_probs":[[-0.43737,-0.117443,-0.703083]]}
Explanation: The first step reads token 0 with a zero state, so the new state is tanh(E_0 + b_h) = tanh([-0.2, -0.7]), about [-0.1974, -0.6044]. Its logits are about [0.9575, -0.7847, -0.7503, 1.8627], so the first token is 3 with log probability -0.43737. Feeding token 3 and the new state back into the same step gives token 2 and then token 0.
Input: params = {"embed":[[1.7,1.4,-1.1],[-0.1,-1.1,-1.1],[0.9,-0.8,0.1],[0.7,-0.7,-0.9],[0.2,0.5,-0.9]],"w_hh":[[0.2,-0.1,0.7],[0.0,0.5,-0.5],[0.0,0.2,-1.0]],"b_h":[0.5,0.1,0.3],"w_out":[[0.9,-1.0,1.5,-1.1,2.0],[-1.4,0.1,-0.9,-3.0,0.7],[-0.3,-1.0,-1.0,2.1,-3.7]],"b_out":[0.2,0.6,0.0,0.0,-0.1]}, start_tokens = [4,0], h0 = [[0.1,0.6,0.4],[-0.3,-0.2,0.9]], num_steps = 4
Output: {"tokens":[[4,4,4,4],[4,2,2,3]],"log_probs":[[-0.05271,-0.938562,-0.089923,-0.675244],[-0.019317,-1.258601,-1.079186,-0.434214]]}
Input: params = {"embed":[[0.8,-0.5],[-0.6,-1.0],[1.7,0.6],[-0.7,0.6]],"w_hh":[[-1.5,-0.9],[1.6,-0.3]],"b_h":[-0.2,-0.4],"w_out":[[0.2,-0.5,1.7,-0.4],[-2.0,0.7,-0.3,-0.8]],"b_out":[1.1,-0.8,0.4,0.5]}, start_tokens = [2,0,3], h0 = [[0.2,-0.4],[-0.2,-0.3],[-0.6,-0.1]], num_steps = 1
Output: {"tokens":[[2],[0],[3]],"log_probs":[[-0.792978],[-0.467053],[-1.220548]]}
jax.lax.scan(step, init, xs=None, length=n) runs step n times.
Carry (hidden, token); return (new_carry, (token, logprob)) to stack outputs.
jnp.take_along_axis(logp, tok[:, None], axis=-1) picks the chosen token's value.
Accepts: object
Accepts: array
Accepts: array
Accepts: integer
Generate num_steps tokens greedily from a tiny recurrent language model, running the decoding loop with jax.lax.scan.
The model keeps one hidden state per sequence. At step t it reads the previous token yt−1 and the previous hidden state ht−1, updates the state, scores every vocabulary entry, and picks the highest-scoring token.
ht=tanh(Eyt−1+ht−1Whh+bh),ℓt=htWout+bout yt=argvmaxℓt,v,rt=logsoftmax(ℓt)ytHere params is a dict holding the embedding table embed E of shape (V, H), whose row Ey is the vector for token y, the recurrent weights w_hh Whh of shape (H, H), the bias b_h bh of shape (H,), the output weights w_out Wout of shape (H, V) and the output bias b_out bout of shape (V,). V is the vocabulary size and H is the hidden size. The loop starts from y0 = start_tokens and h0 = h0, and steps t=1,…,T with T = num_steps. ℓt holds the V logits of step t, yt is the generated token and rt is its log probability. Every one of the B sequences in the batch runs the same rule independently.
Return a dict with two keys. tokens is an int32 JAX array of shape (B, num_steps) whose row b lists y1,…,yT for sequence b, and log_probs is a float32 JAX array of shape (B, num_steps) holding the matching rt values.
Input: params = {"embed":[[-0.3,-0.8],[1.5,0.0],[-0.8,0.2],[1.7,1.5]],"w_hh":[[-0.6,0.4],[-0.1,-0.2]],"b_h":[0.1,0.1],"w_out":[[-1.6,-0.3,3.2,-2.3],[-0.4,0.9,-0.3,-2.0]],"b_out":[0.4,-0.3,-0.3,0.2]}, start_tokens = [0], h0 = [[0.0,0.0]], num_steps = 3
Output: {"tokens":[[3,2,0]],"log_probs":[[-0.43737,-0.117443,-0.703083]]}
Explanation: The first step reads token 0 with a zero state, so the new state is tanh(E_0 + b_h) = tanh([-0.2, -0.7]), about [-0.1974, -0.6044]. Its logits are about [0.9575, -0.7847, -0.7503, 1.8627], so the first token is 3 with log probability -0.43737. Feeding token 3 and the new state back into the same step gives token 2 and then token 0.
Input: params = {"embed":[[1.7,1.4,-1.1],[-0.1,-1.1,-1.1],[0.9,-0.8,0.1],[0.7,-0.7,-0.9],[0.2,0.5,-0.9]],"w_hh":[[0.2,-0.1,0.7],[0.0,0.5,-0.5],[0.0,0.2,-1.0]],"b_h":[0.5,0.1,0.3],"w_out":[[0.9,-1.0,1.5,-1.1,2.0],[-1.4,0.1,-0.9,-3.0,0.7],[-0.3,-1.0,-1.0,2.1,-3.7]],"b_out":[0.2,0.6,0.0,0.0,-0.1]}, start_tokens = [4,0], h0 = [[0.1,0.6,0.4],[-0.3,-0.2,0.9]], num_steps = 4
Output: {"tokens":[[4,4,4,4],[4,2,2,3]],"log_probs":[[-0.05271,-0.938562,-0.089923,-0.675244],[-0.019317,-1.258601,-1.079186,-0.434214]]}
Input: params = {"embed":[[0.8,-0.5],[-0.6,-1.0],[1.7,0.6],[-0.7,0.6]],"w_hh":[[-1.5,-0.9],[1.6,-0.3]],"b_h":[-0.2,-0.4],"w_out":[[0.2,-0.5,1.7,-0.4],[-2.0,0.7,-0.3,-0.8]],"b_out":[1.1,-0.8,0.4,0.5]}, start_tokens = [2,0,3], h0 = [[0.2,-0.4],[-0.2,-0.3],[-0.6,-0.1]], num_steps = 1
Output: {"tokens":[[2],[0],[3]],"log_probs":[[-0.792978],[-0.467053],[-1.220548]]}
jax.lax.scan(step, init, xs=None, length=n) runs step n times.
Carry (hidden, token); return (new_carry, (token, logprob)) to stack outputs.
jnp.take_along_axis(logp, tok[:, None], axis=-1) picks the chosen token's value.
Accepts: object
Accepts: array
Accepts: array
Accepts: integer