89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
import logging
|
|
|
|
from langchain_core.messages import HumanMessage, SystemMessage
|
|
|
|
from llm_runtime import _format_prompt, _normalize_llm_output, llm
|
|
from memory import EntityMemory, MemoryEntry
|
|
from time_utils import WorldClock
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Entity:
|
|
def __init__(
|
|
self,
|
|
name,
|
|
traits,
|
|
stats,
|
|
voice_sample,
|
|
current_mood="Neutral",
|
|
entity_id=None,
|
|
):
|
|
self.name = name
|
|
self.traits = traits
|
|
self.stats = stats
|
|
self.current_mood = current_mood
|
|
self.memory = EntityMemory()
|
|
# TIER 1: The Short-Term Buffer (Verbatim)
|
|
self.chat_buffer = []
|
|
self.voice_sample = voice_sample
|
|
self.entity_id = entity_id
|
|
|
|
def perceive(self, entry: MemoryEntry):
|
|
self.memory.save(entry)
|
|
|
|
def reflect_and_summarize(self, world_clock: WorldClock, location: str):
|
|
"""Converts Tier 1 (Buffer) into Tier 2 (Long-term Subjective Memory)."""
|
|
if not self.chat_buffer:
|
|
return
|
|
|
|
dialogue_text = "\n".join(
|
|
[f"{m['role_name']}: {m['content']}" for m in self.chat_buffer]
|
|
)
|
|
|
|
# The Subjective Filter Prompt
|
|
summary_prompt = [
|
|
SystemMessage(
|
|
content=f"""
|
|
You are the private inner thoughts of {self.name}.
|
|
Traits: {", ".join(self.traits)}.
|
|
Mood: {self.current_mood}.
|
|
Voice Reference: {self.voice_sample}
|
|
|
|
Think about what just happened.
|
|
- No META-TALK, Do not use 'player', 'interaction', 'entity', or 'dialogue'
|
|
- BE SUBJECTIVE. If you hated the talk or loved it, then express that.
|
|
- USE YOUR VOICE. Match the style of your Voice Reference
|
|
- Focus only on facts learned or feelings toward the person"""
|
|
),
|
|
HumanMessage(
|
|
content=f"""
|
|
What just happened? Context:\n{dialogue_text}"""
|
|
),
|
|
]
|
|
|
|
logger.info("LLM prompt (reflection):\n%s", _format_prompt(summary_prompt))
|
|
summary = _normalize_llm_output(llm.invoke(summary_prompt).content)
|
|
logger.info("SYSTEM: %s reflected on the talk: '%s'", self.name, summary)
|
|
|
|
chat_entities = sorted(
|
|
{
|
|
m["role_id"]
|
|
for m in self.chat_buffer
|
|
if m.get("role_id") and m.get("role_id") != self.entity_id
|
|
}
|
|
)
|
|
reflection = MemoryEntry(
|
|
content=f"Past Conversation Summary: {summary}",
|
|
event_type="reflection",
|
|
timestamp_str=world_clock.get_time_str(),
|
|
location=location,
|
|
entities=chat_entities,
|
|
)
|
|
self.perceive(reflection)
|
|
self.chat_buffer = [] # Clear buffer after archiving
|
|
|
|
|
|
class Player(Entity):
|
|
pass
|