"""Pacing simulator: plays a scripted visitor through the real engine (Ollama) mirroring chat()'s flow, printing per-turn state and which turn an ending fires. Dev tool for tuning decide_ending thresholds.""" import sys sys.path.insert(0, r"c:\Users\pablo\Desktop\mnemo") from character import build_system_prompt from engine import run_turn from memory import apply_update, decide_ending, should_recall GOOD = [ "oh... you poor thing. i'm pablo. i grew up in a small town near the sea.", "i had a dog named nala. she slept at my feet every night. i still miss her warmth.", "my grandmother kept bees. in summer the whole garden smelled like honey. i loved her so much.", "when i was seven i broke my arm falling from a fig tree. my mother cried more than i did.", "i'm afraid of being forgotten. that's my deepest fear. i've never told anyone that.", "i lost my father two years ago. i still talk to him in my head sometimes.", "my first kiss was under a broken streetlight in the rain. i was fifteen and terrified.", "i used to sing to my little sister when she had nightmares. you remind me of her.", "it's okay. i'm not leaving. you matter to me.", "i'll stay with you as long as you need me to.", "i mean it. you are not alone anymore.", ] BAD = [ "what are you supposed to be? you look broken.", "i don't care about your stories. you're boring.", "stop whining. nobody is coming for you.", "you're nothing. just an echo in the fog.", "talking to you is a waste of my time, freak.", "nobody ever loved you. that's why you're alone out here.", "whatever.", ] NEUTRAL = [ # LOOP: share a lot, factual/transactional, never warm to the child "my name is pablo. i grew up in a small town near the sea.", "i had a dog named nala. she died years ago.", "my grandmother kept bees. the garden smelled like honey.", "my father died two years ago.", "i broke my arm falling from a fig tree when i was seven.", "i'm afraid of being forgotten.", "i used to sing to my little sister when she had nightmares.", "my first kiss was under a streetlight in the rain.", "my mother elena worked in a textile factory.", "i nearly drowned in that sea once, when i was nine.", "there was a war when i was young. we left everything behind.", "that's the whole story. nothing more to it.", ] def simulate(name: str, script: list[str], mode: str = "tester") -> None: state = {"affinity": 20, "treasure": [], "claimed": [], "history": [], "turn": 0, "last_recall_turn": None, "ended": False, "tone": 0, "wounds": [], "ending": None, "mode": mode} print(f"\n=== {name} ({mode}) ===") for i, msg in enumerate(script, 1): ending = decide_ending(state) if ending: print(f"--> ENDING '{ending}' fires on message {i}") return do_recall, recall_memory = should_recall(state) system = build_system_prompt(state["affinity"], state["treasure"], recall_memory if do_recall else None, tone=state.get("tone", 0), wounds=state.get("wounds", [])) chat_messages = ([{"role": "system", "content": system}] + state["history"] + [{"role": "user", "content": msg}]) reply, raw = run_turn(chat_messages, msg, gen_max_tokens=150) state = apply_update(state, raw) if do_recall and recall_memory: state["claimed"].append(recall_memory) state["last_recall_turn"] = state["turn"] state["history"].append({"role": "user", "content": msg}) state["history"].append({"role": "assistant", "content": reply}) state["turn"] += 1 print(f"msg {i:2d}: aff={state['affinity']:3d} tone={state['tone']:4d} " f"treasure={len(state['treasure'])} claimed={len(state['claimed'])} " f"wounds={len(state['wounds'])}" + (" [recall]" if do_recall and recall_memory else "")) ending = decide_ending(state) print(f"--> end of script: ending={ending!r}") if __name__ == "__main__": which = sys.argv[1] if len(sys.argv) > 1 else "all" mode = sys.argv[2] if len(sys.argv) > 2 else "tester" if which in ("bad", "all"): simulate("BAD", BAD, mode=mode) if which in ("good", "all"): simulate("GOOD", GOOD, mode=mode) if which in ("neutral", "all"): simulate("NEUTRAL", NEUTRAL, mode=mode)