- field/state.py: FieldState is now frozen+slotted; constructor copies and
enforces float32 shape (32,); advance() updated to pass raw arrays.
np.ndarray inside frozen dataclass is ref-frozen — copy() at construction
is the explicit contract boundary.
- generate/result.py: NEW — GenerationResult frozen dataclass carrying
tokens + final_state. Async variant yields tokens and exposes final_state
on completion.
- generate/stream.py: generate() now returns GenerationResult, not list[str].
vocab.edge_rotor() call replaced with:
A = vocab.get_versor_at(current.node)
B = vocab.get_versor_at(word_idx)
V = word_transition_rotor(A, B)
agenerate() updated to yield tokens and surface final_state.
- vocab/manifold.py: added get_versor_at(idx) and get_word_at(idx) indexed
accessors. VocabManifold stores points; algebra constructs operators.
normalize_to_versor() call-site in docstring clarified: callers must call
unitize_versor() (algebra construction primitive) before add(), not
normalize_to_versor() directly.
- algebra/versor.py: unitize_versor() added as the explicit construction-time
primitive. normalize_to_versor() kept but marked internal/gate-only.
Distinction encoded in docstrings and __all__.
- persona/motor.py + ingest/gate.py: SessionContext.respond() is not yet in
the repo as a separate file; gate.py docstring updated to reflect the
three-tier normalization doctrine:
unitize_versor() — algebra construction only
inject() — gate, once per raw input
normalization — forbidden in propagate/generate/vault recall
35 lines
1.3 KiB
Python
35 lines
1.3 KiB
Python
"""
|
|
GenerationResult — the complete output of one generation pass.
|
|
|
|
Generate() must return the evolved field state, not only surface tokens.
|
|
The field state after generation is semantically different from the
|
|
field state before generation; discarding it means the vault stores
|
|
the prompt field, not the assistant response field.
|
|
|
|
Contracts:
|
|
tokens — the decoded token sequence in emission order
|
|
final_state — FieldState after the last propagation step
|
|
trajectory — optional ordered list of intermediate FieldStates;
|
|
None unless the caller explicitly requests it (expensive)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
from dataclasses import dataclass, field
|
|
from field.state import FieldState
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class GenerationResult:
|
|
tokens: tuple # decoded token sequence, immutable
|
|
final_state: FieldState
|
|
trajectory: tuple | None = None # (FieldState, ...) or None
|
|
|
|
def __post_init__(self) -> None:
|
|
# Coerce list inputs to tuple for immutability.
|
|
object.__setattr__(self, "tokens", tuple(self.tokens))
|
|
if self.trajectory is not None:
|
|
object.__setattr__(self, "trajectory", tuple(self.trajectory))
|
|
|
|
def text(self, sep: str = " ") -> str:
|
|
"""Join tokens into a string for display."""
|
|
return sep.join(self.tokens)
|