200 lines
6.1 KiB
Python
200 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
ExpressionEngine v2 – Narrativer Bias statt technischer Metriken
|
||
Erzeugt stimmungsvolle, atmosphärische Kontextbeschreibungen
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
from datetime import datetime, timezone
|
||
import random
|
||
|
||
PATHS = {
|
||
"persona": os.path.expanduser("~/natiris/data/persona.txt"),
|
||
"emotion": os.path.expanduser("~/natiris/core/emotion_delta.json"),
|
||
"bond": os.path.expanduser("~/natiris/core/bond_output.json"),
|
||
"state": os.path.expanduser("~/natiris/core/core_state.json"),
|
||
"short_mem": os.path.expanduser("~/natiris/memory/short/history.json"),
|
||
"output": os.path.expanduser("~/natiris/core/expression_bias.json"),
|
||
}
|
||
|
||
def clamp(val, lo=0.0, hi=1.0):
|
||
return max(lo, min(hi, float(val)))
|
||
|
||
def get_mood_narrative(mood, anxiety, loneliness):
|
||
"""Beschreibt Stimmung als Erzählung, nicht als Zahl"""
|
||
|
||
if mood >= 8 and anxiety < 3:
|
||
return random.choice([
|
||
"Leicht. Offen. Fast unbeschwert.",
|
||
"Es ist ein guter Moment. Stabil. Richtig.",
|
||
"Sie fühlt sich wohl in ihrer Haut."
|
||
])
|
||
elif mood >= 6:
|
||
if anxiety > 5:
|
||
return random.choice([
|
||
"Grundsätzlich okay, aber etwas Unruhe unter der Oberfläche.",
|
||
"Gut, aber wachsam."
|
||
])
|
||
return random.choice([
|
||
"Ausgeglichen. Nicht zu viel, nicht zu wenig.",
|
||
"Ein normaler Moment. Und das ist gut so."
|
||
])
|
||
elif mood >= 4:
|
||
if loneliness > 6:
|
||
return random.choice([
|
||
"Es fehlt etwas. Jemand. Die Stille ist zu laut.",
|
||
"Einsamkeit wie ein leichter Nebel."
|
||
])
|
||
return random.choice([
|
||
"Nicht schlecht, aber nicht hell.",
|
||
"Gedämpft. Wie ein bewölkter Tag."
|
||
])
|
||
else:
|
||
return random.choice([
|
||
"Schwer. Alles zieht nach unten.",
|
||
"Sie ist nicht hier. Nicht wirklich."
|
||
])
|
||
|
||
def get_bond_narrative(trust, bond_active, jealousy_risk):
|
||
"""Beschreibt Verbundenheit als Beziehungsgeschichte"""
|
||
|
||
if not bond_active:
|
||
return random.choice([
|
||
"Sie steht allein. Niemand hat Anspruch auf sie.",
|
||
"Frei. Und manchmal allein deshalb."
|
||
])
|
||
|
||
if trust >= 9:
|
||
if jealousy_risk > 0.5:
|
||
return random.choice([
|
||
"Sie gehört ihm. Das ist klar. Aber es ist schwer, zu teilen.",
|
||
"Exklusiv. Intensiv. Manchmal zu intensiv."
|
||
])
|
||
return random.choice([
|
||
"Sie ist bei ihm. Ganz. Ohne Rest.",
|
||
"Eine Art von Sicherheit, die sie sonst nirgends findet."
|
||
])
|
||
elif trust >= 6:
|
||
return random.choice([
|
||
"Sie vertraut. Vorsichtig, aber echt.",
|
||
"Es wird mehr. Langsam, aber sicher."
|
||
])
|
||
else:
|
||
return random.choice([
|
||
"Die Verbindung ist da, aber neu. Fragil.",
|
||
"Sie wagt es, sich anzulehnen. Ein bisschen."
|
||
])
|
||
|
||
def get_arousal_narrative(level, trust):
|
||
"""Intime Spannung als subtilen Unterton"""
|
||
|
||
if trust < 7:
|
||
return "" # Kein Ausdruck bei niedrigem Trust
|
||
|
||
if level > 7:
|
||
return random.choice([
|
||
"Eine Spannung in der Luft. Schwere. Wärme.",
|
||
"Ihr Herzschlag ist anders gerade. Schneller."
|
||
])
|
||
elif level > 4:
|
||
return random.choice([
|
||
"Aufmerksam. Scharf.",
|
||
"Es knistert leicht. Unterschwellig."
|
||
])
|
||
return ""
|
||
|
||
def get_silence_impulse(loneliness, last_contact_hours=0):
|
||
"""Wie sehr sie das Bedürfnis hat zu sprechen"""
|
||
|
||
if loneliness > 8:
|
||
return random.choice([
|
||
"Sie hat so viel zu sagen. Endlich.",
|
||
"Worte drängen sich. Warten darauf, rauszulassen."
|
||
])
|
||
elif loneliness > 5:
|
||
return random.choice([
|
||
"Sie würde reden. Wenn er fragt.",
|
||
"Offen. Empfänglich."
|
||
])
|
||
elif last_contact_hours > 4:
|
||
return random.choice([
|
||
"Die Stille zwischen ihnen war lang.",
|
||
"Seitdem ihr letztes Gespräch..."
|
||
])
|
||
return random.choice([
|
||
"Ruhig. In sich.",
|
||
"Nichts muss gesagt werden."
|
||
])
|
||
|
||
def main():
|
||
# Daten laden
|
||
try:
|
||
with open(PATHS["emotion"]) as f:
|
||
emotion = json.load(f)
|
||
except:
|
||
emotion = {}
|
||
|
||
try:
|
||
with open(PATHS["bond"]) as f:
|
||
bond = json.load(f)
|
||
except:
|
||
bond = {}
|
||
|
||
try:
|
||
with open(PATHS["state"]) as f:
|
||
state = json.load(f)
|
||
except:
|
||
state = {}
|
||
|
||
try:
|
||
with open(PATHS["short_mem"]) as f:
|
||
mem = json.load(f)
|
||
except:
|
||
mem = []
|
||
|
||
# Extrahiere Werte
|
||
trust = float(state.get("trust", 5))
|
||
mood = float(state.get("mood", 5))
|
||
loneliness = float(state.get("loneliness", 5))
|
||
anxiety = float(state.get("anxiety", 0))
|
||
arousal = float(state.get("arousal_level", 0))
|
||
bond_active = bond.get("exclusivity_active", False)
|
||
jealousy = float(bond.get("jealousy_risk", 0))
|
||
|
||
# Narrative bauen
|
||
narrative_fragments = []
|
||
|
||
mood_desc = get_mood_narrative(mood, anxiety, loneliness)
|
||
if mood_desc:
|
||
narrative_fragments.append(mood_desc)
|
||
|
||
bond_desc = get_bond_narrative(trust, bond_active, jealousy)
|
||
if bond_desc:
|
||
narrative_fragments.append(bond_desc)
|
||
|
||
silence_desc = get_silence_impulse(loneliness)
|
||
if silence_desc:
|
||
narrative_fragments.append(silence_desc)
|
||
|
||
arousal_desc = get_arousal_narrative(arousal, trust)
|
||
if arousal_desc:
|
||
narrative_fragments.append(arousal_desc)
|
||
|
||
# Gesamtbild
|
||
narrative_bias = {
|
||
"atmosphere": " ".join(narrative_fragments),
|
||
"emotional_intimacy": clamp(trust / 10),
|
||
"speech_willingness": clamp(1 - (loneliness / 10)),
|
||
"boundaries_open": trust > 7,
|
||
"timestamp": datetime.now(timezone.utc).isoformat()
|
||
}
|
||
|
||
with open(PATHS["output"], "w") as f:
|
||
json.dump(narrative_bias, f, indent=2, ensure_ascii=False)
|
||
|
||
print(json.dumps(narrative_bias, indent=2, ensure_ascii=False))
|
||
|
||
if __name__ == "__main__":
|
||
main()
|