Add deterministic engine loop proof
This commit is contained in:
parent
3620c967b9
commit
1731ca6500
1 changed files with 32 additions and 11 deletions
|
|
@ -4,13 +4,20 @@ SessionContext — binds field, vault, vocab, and persona for one session.
|
||||||
One session = one field trajectory on the manifold.
|
One session = one field trajectory on the manifold.
|
||||||
The vault accumulates versors across turns.
|
The vault accumulates versors across turns.
|
||||||
The persona motor is fixed per session (or composable across sessions).
|
The persona motor is fixed per session (or composable across sessions).
|
||||||
|
|
||||||
|
Generation returns GenerationResult so the evolved field state is preserved.
|
||||||
|
The assistant vault entry stores the generated final_state, not the prompt
|
||||||
|
field that entered the turn.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from field.state import FieldState
|
from field.state import FieldState
|
||||||
from vault.store import VaultStore
|
from vault.store import VaultStore
|
||||||
from persona.motor import PersonaMotor
|
from persona.motor import PersonaMotor
|
||||||
from ingest.gate import inject
|
from ingest.gate import inject
|
||||||
from generate.stream import generate, agenerate
|
from generate.stream import generate
|
||||||
|
from generate.result import GenerationResult
|
||||||
|
|
||||||
|
|
||||||
class SessionContext:
|
class SessionContext:
|
||||||
|
|
@ -18,29 +25,43 @@ class SessionContext:
|
||||||
self.vocab = vocab
|
self.vocab = vocab
|
||||||
self.persona = persona or PersonaMotor.identity()
|
self.persona = persona or PersonaMotor.identity()
|
||||||
self.vault = vault or VaultStore()
|
self.vault = vault or VaultStore()
|
||||||
self.state: FieldState = None
|
self.state: FieldState | None = None
|
||||||
self.turn: int = 0
|
self.turn: int = 0
|
||||||
|
|
||||||
def ingest(self, tokens: list) -> FieldState:
|
def ingest(self, tokens: list) -> FieldState:
|
||||||
"""Inject a prompt. Sets self.state. Stores field in vault."""
|
"""Inject a prompt. Sets self.state. Stores the user field in vault."""
|
||||||
self.state = inject(tokens, self.vocab)
|
self.state = inject(tokens, self.vocab)
|
||||||
self.vault.store(self.state.F, {"turn": self.turn, "role": "user"})
|
self.vault.store(self.state.F, {"turn": self.turn, "role": "user"})
|
||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
def respond(self, max_tokens: int = 128) -> list:
|
def respond(self, max_tokens: int = 128) -> GenerationResult:
|
||||||
"""Generate a response from current state. Stores result in vault."""
|
"""
|
||||||
|
Generate a response from current state and preserve the evolved field.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
GenerationResult carrying emitted tokens and final_state.
|
||||||
|
"""
|
||||||
assert self.state is not None, "Call ingest() before respond()."
|
assert self.state is not None, "Call ingest() before respond()."
|
||||||
tokens = generate(self.state, self.vocab, self.persona, max_tokens)
|
result = generate(self.state, self.vocab, self.persona, max_tokens)
|
||||||
self.vault.store(self.state.F, {"turn": self.turn, "role": "assistant"})
|
self.state = result.final_state
|
||||||
|
self.vault.store(result.final_state.F, {"turn": self.turn, "role": "assistant"})
|
||||||
self.turn += 1
|
self.turn += 1
|
||||||
return tokens
|
return result
|
||||||
|
|
||||||
async def arespond(self, max_tokens: int = 128):
|
async def arespond(self, max_tokens: int = 128):
|
||||||
"""Async streaming response."""
|
"""
|
||||||
|
Async token-yielding response path.
|
||||||
|
|
||||||
|
The generation pass still returns a GenerationResult internally so
|
||||||
|
SessionContext can store the evolved assistant final_state after
|
||||||
|
yielding the surface tokens.
|
||||||
|
"""
|
||||||
assert self.state is not None, "Call ingest() before arespond()."
|
assert self.state is not None, "Call ingest() before arespond()."
|
||||||
async for token in agenerate(self.state, self.vocab, self.persona, max_tokens):
|
result = generate(self.state, self.vocab, self.persona, max_tokens)
|
||||||
|
for token in result.tokens:
|
||||||
yield token
|
yield token
|
||||||
self.vault.store(self.state.F, {"turn": self.turn, "role": "assistant"})
|
self.state = result.final_state
|
||||||
|
self.vault.store(result.final_state.F, {"turn": self.turn, "role": "assistant"})
|
||||||
self.turn += 1
|
self.turn += 1
|
||||||
|
|
||||||
def recall(self, query_tokens: list, top_k: int = 5) -> list:
|
def recall(self, query_tokens: list, top_k: int = 5) -> list:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue