75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
"""Synthesized-memories service (T54).
|
|
|
|
When the user jump-skips with 'anything notable happen?' prose, parse
|
|
that prose into 1-N synthesized memories per present bot. Each memory
|
|
carries source="synthesized" and reliability=0.7 (lower than direct).
|
|
Caller (T62 skip flow) writes the memories via record_turn_memory_for_present.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from chat.llm.classify import classify
|
|
from chat.llm.client import LLMClient
|
|
|
|
|
|
class SynthesizedMemory(BaseModel):
|
|
text: str
|
|
significance: int = 1 # 0..3, default 1
|
|
affinity_delta: int = 0
|
|
trust_delta: int = 0
|
|
|
|
|
|
class SynthesizedDigest(BaseModel):
|
|
memories: list[SynthesizedMemory] = Field(default_factory=list)
|
|
|
|
|
|
_SYSTEM = (
|
|
"You parse a short user-supplied prose describing 'anything notable' "
|
|
"that happened during a time skip into 1-N synthesized memories from "
|
|
"a single bot's POV. Each memory has: text (one factual sentence "
|
|
"from that bot's perspective), significance (0-3, default 1; only "
|
|
"use 2 or 3 for genuinely scene-level or relationship-altering "
|
|
"events), affinity_delta and trust_delta (-10..+10, default 0; "
|
|
"use small adjustments only when prose explicitly describes a shift). "
|
|
"Empty/whitespace prose returns an empty memories list. Output "
|
|
"strict JSON matching the schema."
|
|
)
|
|
|
|
|
|
async def synthesize_memories(
|
|
client: LLMClient,
|
|
*,
|
|
classifier_model: str,
|
|
prose: str,
|
|
bot_name: str,
|
|
bot_persona: str,
|
|
you_name: str,
|
|
timeout_s: float = 30.0,
|
|
) -> SynthesizedDigest:
|
|
"""Parse 'anything notable' prose into structured memories from a
|
|
single bot's POV. Empty/whitespace prose short-circuits to an
|
|
empty digest (no LLM call)."""
|
|
if not prose or not prose.strip():
|
|
return SynthesizedDigest()
|
|
|
|
user = (
|
|
f"Bot: {bot_name}\n"
|
|
f"Persona: {bot_persona}\n"
|
|
f"Other party: {you_name}\n\n"
|
|
f"Prose:\n{prose.strip()}"
|
|
)
|
|
return await classify(
|
|
client,
|
|
model=classifier_model,
|
|
system=_SYSTEM,
|
|
user=user,
|
|
schema=SynthesizedDigest,
|
|
default=SynthesizedDigest(),
|
|
timeout_s=timeout_s,
|
|
)
|
|
|
|
|
|
__all__ = ["SynthesizedMemory", "SynthesizedDigest", "synthesize_memories"]
|