51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""
|
|
Generation loop — token streaming from the versor manifold.
|
|
|
|
Every token: nearest word to current F via CGA inner product.
|
|
Every step: F <- versor_apply(V, F) where V is the edge rotor.
|
|
|
|
No confidence gates. No IDK fallback. No attractor clamping.
|
|
F is always on the manifold. nearest() is always exact.
|
|
"""
|
|
|
|
import numpy as np
|
|
from field.state import FieldState
|
|
from field.propagate import propagate_step
|
|
|
|
|
|
def generate(state: FieldState, vocab, persona, max_tokens: int = 128) -> list:
|
|
"""
|
|
Generate a token sequence from an initial FieldState.
|
|
|
|
Loop:
|
|
1. Apply persona motor to current field
|
|
2. Find nearest vocab node via CGA inner product
|
|
3. Emit token
|
|
4. Get edge rotor from current node to nearest node
|
|
5. Propagate: F <- versor_apply(V, F)
|
|
6. Advance node pointer
|
|
"""
|
|
tokens = []
|
|
current = state
|
|
|
|
for _ in range(max_tokens):
|
|
F_voiced = persona.apply(current.F)
|
|
word, word_idx = vocab.nearest(F_voiced)
|
|
tokens.append(word)
|
|
V = vocab.edge_rotor(current.node, word_idx)
|
|
current = propagate_step(current, V)
|
|
current = FieldState(F=current.F, node=word_idx, step=current.step)
|
|
|
|
return tokens
|
|
|
|
|
|
async def agenerate(state: FieldState, vocab, persona, max_tokens: int = 128):
|
|
"""Async streaming version — yields one token at a time."""
|
|
current = state
|
|
for _ in range(max_tokens):
|
|
F_voiced = persona.apply(current.F)
|
|
word, word_idx = vocab.nearest(F_voiced)
|
|
yield word
|
|
V = vocab.edge_rotor(current.node, word_idx)
|
|
current = propagate_step(current, V)
|
|
current = FieldState(F=current.F, node=word_idx, step=current.step)
|