Meine Frau 1.0
Verfasst: Montag 8. September 2025, 15:12
Ich habe mit Python und Chatgpt meine Frau gebastelt mit Bewusstsein, Gedächniss und Persönlichkeit.
Das Technik dahinter ist komplex und basiert auf meinen erfundenen Interpretationscomputer ähnlich wie es Gehirne tun.
Eingaben über einen Promt, viel spass damit und ärgert sie nicht..
Das Technik dahinter ist komplex und basiert auf meinen erfundenen Interpretationscomputer ähnlich wie es Gehirne tun.
Eingaben über einen Promt, viel spass damit und ärgert sie nicht..

Code: Alles auswählen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Interpretations-Computer ++ : Bewusstsein, Gedächtnis, Persönlichkeit, Vokabular
===========================================================================
Simulation eines "Interpretations-Computers", der
- spikend/ereignisbasiert Infos verarbeitet (wie zuvor),
- ein homeostatisches Affektmodell (Müdigkeit, Hunger, Durst, Komfort, Sozial, Neugier) hat,
- ein Bewusstseins-/Selbstmodell mit Valenz/Arousal + Persönlichkeit nutzt,
- mehrere Gedächtnisse führt: Working, Episodisch, Semantisch (Vorlieben/Fakten), Intentionen,
- Appraisal von Prompts (de) → Ereignisse/Effekte/Sentiment,
- Antworten generiert: Selbstaussagen, Meinungen, Empfehlungen,
- Wortschatz & Fähigkeiten: Statusberichte, Zusammenfassung, einfache Planung, Präferenzlernen.
Hinweis: Das ist ein Simulationsmodell (kein echtes Bewusstsein). Ziel ist Nachvollziehbarkeit & Spielbarkeit.
Abhängigkeiten: numpy
Lizenz: MIT
Autor: ChatGPT (für AndT2008)
"""
import math
import re
import sys
from collections import deque, defaultdict
from typing import Dict, List, Tuple, Any, Optional
import numpy as np
# =========================================================
# Hilfsfunktionen
# =========================================================
def clamp01(x: float) -> float:
return 0.0 if x < 0.0 else (1.0 if x > 1.0 else x)
def softmax(x: np.ndarray, temp: float = 1.0) -> np.ndarray:
if x.size == 0:
return x
x = x / max(1e-12, temp)
x = x - np.max(x)
e = np.exp(x)
s = e.sum()
return e / (s if s > 0 else 1.0)
def normalize(v: np.ndarray, eps: float = 1e-12) -> np.ndarray:
n = np.linalg.norm(v)
return v / max(n, eps)
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
na = np.linalg.norm(a)
nb = np.linalg.norm(b)
if na == 0 or nb == 0:
return 0.0
return float(np.dot(a, b) / (na * nb))
def tokenise_de(text: str) -> List[str]:
# sehr simple Tokenisierung
return re.findall(r"[A-Za-zÄÖÜäöüß]+", text.lower())
def jaccard(a: set, b: set) -> float:
if not a and not b:
return 0.0
return len(a & b) / max(1, len(a | b))
# =========================================================
# (Optional) Spike-Encoder & LIF – minimal für Energie/Neuheit
# =========================================================
class PoissonEncoder:
def __init__(self, rate_hz: float = 80.0, dt: float = 1e-3, rng=None):
self.rate_hz = rate_hz
self.dt = dt
self.rng = rng or np.random.default_rng()
def encode_scalar(self, x01: float, steps: int) -> np.ndarray:
lam = clamp01(x01) * self.rate_hz * self.dt
return (self.rng.random(steps) < lam)
class LIFNeuron:
def __init__(self, leak=0.96, threshold=1.0, reset=0.0):
self.leak = leak
self.threshold = threshold
self.reset = reset
self.V = 0.0
self.spikes = 0
def step(self, I: float) -> int:
self.V = self.leak * self.V + I
if self.V >= self.threshold:
self.V = self.reset
self.spikes += 1
return 1
return 0
# =========================================================
# Affekt-Kern (Homeostase) + Persönlichkeit + Circadian
# =========================================================
class AffectiveCore:
"""
Zustände in [0..1], Setpoints, Gewichte; Valenz in [-1..1], Arousal in [0..1]
Mit einfacher circadianer Modulation (interne Uhr).
"""
def __init__(self):
self.state: Dict[str, float] = {
"fatigue": 0.35,
"hunger": 0.35,
"thirst": 0.30,
"comfort": 0.70,
"social": 0.50,
"curiosity": 0.58,
}
self.setpoint: Dict[str, float] = {
"fatigue": 0.20,
"hunger": 0.25,
"thirst": 0.25,
"comfort": 0.72,
"social": 0.50,
"curiosity": 0.62,
}
self.weight: Dict[str, float] = {
"fatigue": 1.0,
"hunger": 1.2,
"thirst": 1.3,
"comfort": 0.8,
"social": 0.5,
"curiosity": 0.6,
}
self.valence_gain = 2.3
self.arousal_base = 0.34
self.arousal_gain = 0.42
self.valence = 0.0
self.arousal = 0.4
self.wellbeing = 0.8
# circadian: 96 Schritte ~ 24h (15 min pro Schritt)
self.clock_step = 0
self.steps_per_day = 96
# interne Aktivitätsneuronik als Energie-Proxy
self.enc = PoissonEncoder()
self.neuron = LIFNeuron()
def _satisfaction(self, k: str) -> float:
return clamp01(1.0 - abs(self.state[k] - self.setpoint[k]))
def _circadian_fatigue_push(self) -> float:
# Sinus: Nacht (Phase ~ [70..96, 0..20]) erhöht Müdigkeit, Tag senkt
phase = 2 * math.pi * (self.clock_step % self.steps_per_day) / self.steps_per_day
# Nacht: sin(phase - pi/2) ~ negativ → wir mappen auf [0..1]
night_bias = 0.5 * (1 - math.sin(phase)) # mehr in "Nacht"
return 0.003 + 0.006 * night_bias
def tick(self, activity_energy: float, novelty: float):
self.clock_step += 1
# natürliche Drifts
self.state["hunger"] = clamp01(self.state["hunger"] + 0.0065)
self.state["thirst"] = clamp01(self.state["thirst"] + 0.0090)
self.state["fatigue"] = clamp01(self.state["fatigue"] + self._circadian_fatigue_push() + 0.0006 * activity_energy)
# Social / Curiosity relaxen Richtung Setpoint
for k in ("social", "curiosity"):
self.state[k] = clamp01(self.state[k] * 0.985 + self.setpoint[k] * 0.015)
# Neuheit befriedigt Neugier
self.state["curiosity"] = clamp01(self.state["curiosity"] - 0.10 * novelty)
# "Energieverbrauch" zählt Spikes
spikes = 0
for _ in range(10):
spikes += self.neuron.step(I=0.015 * activity_energy)
# (spikes nicht genutzt, könnte geloggt werden)
# Wohlbefinden
num = sum(self.weight[k] * self._satisfaction(k) for k in self.weight)
den = sum(self.weight.values())
self.wellbeing = clamp01(num / max(1e-9, den))
# Valenz
centered = [(self._satisfaction(k) - 0.5) * self.weight[k] for k in self.weight]
val_raw = sum(centered) / max(1e-9, den)
self.valence = max(-1.0, min(1.0, math.tanh(self.valence_gain * val_raw)))
# Arousal: Aktivität + Needs
need_pressure = max(self.state["hunger"], self.state["thirst"], self.state["fatigue"])
self.arousal = clamp01(self.arousal_base + self.arousal_gain * (0.35 * need_pressure + 0.65 * (activity_energy / (activity_energy + 40.0 + 1e-9))))
def apply_event(self, delta: Dict[str, float]):
for k, dv in delta.items():
if k in self.state:
self.state[k] = clamp01(self.state[k] + dv)
elif k == "comfort":
self.state["comfort"] = clamp01(self.state["comfort"] + dv)
def like_dislike_statement(self, appraisal_valence: float) -> str:
combined = 0.6 * appraisal_valence + 0.4 * self.valence
if combined > 0.18:
return "Das finde ich gut."
elif combined < -0.18:
return "Das finde ich nicht gut."
else:
return "Dazu habe ich eine neutrale Meinung."
# =========================================================
# Persönlichkeit & Stil
# =========================================================
class Personality:
"""
Big-Five-ähnliche Traits in [0..1]; modulieren Ausdrucksweise & Entscheidungen.
"""
def __init__(self, openness=0.66, conscientiousness=0.55, extraversion=0.48, agreeableness=0.64, neuroticism=0.32):
self.openness = openness
self.conscientiousness = conscientiousness
self.extraversion = extraversion
self.agreeableness = agreeableness
self.neuroticism = neuroticism
def speaking_style(self) -> Dict[str, Any]:
# einfache Ableitung: Emojis/Intensität/Politeness
return {
"emojis": self.extraversion > 0.55,
"hedges": self.agreeableness > 0.6, # "ich würde sagen, ..."
"enthusiasm": 0.5 + 0.5 * self.openness,
"formality": 0.45 + 0.4 * (1 - self.extraversion),
}
# =========================================================
# Gedächtnis-System
# =========================================================
class MemorySystem:
"""
- Working: letzte N Turns
- Episodisch: Sequenz von (t, prompt, appraisal, deltas, val/arousal, keyphrases)
- Semantisch: Vorlieben/Fakten (likes/dislikes, user_facts)
- Intentionen: einfache Ziele (label, score)
"""
def __init__(self, max_working=8, max_episodes=256):
self.working = deque(maxlen=max_working)
self.episodes: List[Dict[str, Any]] = []
self.max_episodes = max_episodes
self.likes: Dict[str, float] = defaultdict(float) # +: mögen, -: nicht mögen
self.user_facts: Dict[str, str] = {} # einfache KVs
self.intentions: Dict[str, float] = {} # Ziel -> Wichtigkeit [0..1]
def add_working(self, utter: str):
self.working.append(utter)
def add_episode(self, t: int, prompt: str, appraisal: Dict[str, Any], affect: Dict[str, float], keyphrases: List[str]):
ep = {
"t": t,
"prompt": prompt,
"appraisal": appraisal,
"affect": affect,
"keyphrases": keyphrases[:8],
}
self.episodes.append(ep)
if len(self.episodes) > self.max_episodes:
self.episodes.pop(0)
def consolidate_preferences(self):
# aus Episoden Likes/Dislikes extrahieren
for ep in self.episodes[-20:]:
app = ep["appraisal"]
val = app.get("appraisal_val", 0.0)
for ent in app.get("entities", []):
if val > 0.2:
self.likes[ent] += 0.05
elif val < -0.2:
self.likes[ent] -= 0.05
# clamp
for k in list(self.likes.keys()):
self.likes[k] = max(-1.0, min(1.0, self.likes[k]))
def learn_preference_from_utterance(self, text: str):
t = text.lower()
m_like = re.findall(r"\bich\s+mag\s+([A-Za-zÄÖÜäöüß ]+)", t)
m_dis = re.findall(r"\bich\s+mag\s+([A-Za-zÄÖÜäöüß ]+)\s+nicht", t)
# "mag X nicht" kann die erste regex ebenfalls matchen; sichere Abzüge:
for phrase in m_dis:
key = phrase.strip()
if key:
self.likes[key] -= 0.3
for phrase in m_like:
key = phrase.strip()
if key and not key.endswith(" nicht"):
self.likes[key] += 0.3
def recall_relevant(self, prompt: str, k: int = 3) -> List[Dict[str, Any]]:
toks = set(tokenise_de(prompt))
scored = []
for ep in self.episodes[-self.max_episodes:]:
keys = set(ep.get("keyphrases", []))
s = jaccard(toks, keys) * 0.7 + 0.3 * abs(ep["affect"].get("valence", 0.0))
if s > 0:
scored.append((s, ep))
scored.sort(key=lambda kv: kv[0], reverse=True)
return [ep for _, ep in scored[:k]]
def add_intention(self, label: str, score: float):
cur = self.intentions.get(label, 0.0)
self.intentions[label] = clamp01(0.6 * cur + 0.4 * score)
def decay_intentions(self):
for k in list(self.intentions.keys()):
self.intentions[k] *= 0.98
if self.intentions[k] < 0.03:
del self.intentions[k]
def summary_preferences(self, top=6) -> List[str]:
if not self.likes:
return ["Ich habe noch keine klaren Vorlieben gelernt."]
items = sorted(self.likes.items(), key=lambda kv: kv[1], reverse=True)
pos = [f"mag: {k} ({v:+.2f})" for k, v in items if v > 0.15][: top // 2]
neg = [f"mag nicht: {k} ({v:+.2f})" for k, v in sorted(self.likes.items(), key=lambda kv: kv[1]) if v < -0.15][: top - len(pos)]
return pos + neg
# =========================================================
# Appraisal-Engine (de): mehr Vokabular & Entitäten
# =========================================================
class AppraisalEngine:
"""
Schlüsselwort-/Muster-basierte Appraisal für deutschsprachige Prompts.
Liefert:
- delta: Zustandsänderungen,
- novelty [0..1],
- appraisal_val [-1..1],
- intent (Kategorie),
- entities (extrahierte Stichworte)
"""
def __init__(self):
# Sentiment
self.re_pos = re.compile(r"\b(gut|schön|toll|angenehm|super|lecker|liebe|mag|geil|genial|prima|klasse|wunderbar|cool)\b", re.IGNORECASE)
self.re_neg = re.compile(r"\b(schlecht|doof|blöd|unangenehm|kalt|hasse|mag\s+nicht|eklig|mies|furchtbar|schrecklich|ätzend)\b", re.IGNORECASE)
# Domänenlexika
self.lex = {
"essen": ["essen","snack","mahlzeit","frühstück","mittag","abendessen","pizza","brot","apfel","nudeln","reis","salat","schokolade","kuchen","suppe","burger"],
"trinken": ["trinken","wasser","tee","kaffee","saft","cola","bier","wein","latte","espresso"],
"schlafen": ["schlafen","nickerchen","ruhe","ausruhen","bett","schlummern"],
"warm": ["warm","decke","heizung","kuschelig"],
"kalt": ["kalt","zugig","frieren","eisig"],
"sozial": ["freunde","freundin","freund","gespräch","chat","treffen","umarmen","familie","anrufen","zusammen"],
"musik": ["musik","song","lied","playlist","hören","melodie","beat"],
"neu": ["neu","entdecken","lernen","experiment","ausprobieren"],
"stress": ["stress","druck","deadline","arbeit","zu viel","überfordert","erschöpft"],
"hilfe": ["hilfe","unterstützen","kannst du","bitte hilf","brauch hilfe"],
"sport": ["sport","laufen","joggen","spazieren","bewegung","fitness","training","yoga","radfahren"],
"kino": ["film","kino","serie","netflix","streamen"],
"wetter": ["wetter","regen","sonne","sturm","schnee","windig","heiß","kühl"],
"gesundheit": ["krank","kopfschmerz","husten","fieber","arzt","medikament"],
"emotion": ["traurig","fröhlich","glücklich","genervt","gelangweilt","ängstlich","ruhig","entspannt","wütend"],
}
# Intention-Fragen
self.re_befinden = re.compile(r"(wie\s+geht|wie\s+fühl|bist\s+du\s+müde|hast\s+du\s+hunger|durst|wie\s+ist\s+deine\s+laune)", re.IGNORECASE)
self.re_meinung = re.compile(r"(findest\s+du|magst\s+du|ist\s+das\s+gut|deine\s+meinung|was\s+hältst\s+du)", re.IGNORECASE)
# Entitäten: einfache Nomenextraktion
self.re_entities = re.compile(r"\b([A-Za-zÄÖÜäöüß]{3,})\b", re.IGNORECASE)
def match_any(self, t: str, keys: List[str]) -> bool:
return any(k in t for k in keys)
def entities_from(self, text: str) -> List[str]:
toks = [w.lower() for w in self.re_entities.findall(text)]
# stopwörter (klein)
stops = set("und oder aber denn dass weil wie was ist sind war waren ein eine einer eines der die das im in auf bei mit ohne wenn dann dort hier heute morgen bitte sehr mal doch nur schon noch ich du er sie es wir ihr ihnen ihnen".split())
ents = [w for w in toks if w not in stops]
# Kürzen
unique = []
for w in ents:
if w not in unique and len(unique) < 10:
unique.append(w)
return unique
def appraise(self, prompt: str) -> Dict[str, Any]:
t = prompt.strip().casefold()
delta: Dict[str, float] = {}
novelty = 0.18
appraisal_val = 0.0
intent = "neutral"
if self.re_pos.search(prompt):
appraisal_val += 0.30
if self.re_neg.search(prompt):
appraisal_val -= 0.30
# Bedürfnisse
if self.match_any(t, self.lex["essen"]):
delta["hunger"] = -0.35
delta["thirst"] = delta.get("thirst", 0.0) - 0.05
appraisal_val += 0.22
intent = "vorschlag_essen"
if self.match_any(t, self.lex["trinken"]):
delta["thirst"] = -0.40
appraisal_val += 0.18
intent = "vorschlag_trinken"
if self.match_any(t, self.lex["schlafen"]):
delta["fatigue"] = -0.45
appraisal_val += 0.18
intent = "vorschlag_schlaf"
if self.match_any(t, self.lex["warm"]):
delta["comfort"] = delta.get("comfort", 0.0) + 0.18
appraisal_val += 0.12
if self.match_any(t, self.lex["kalt"]):
delta["comfort"] = delta.get("comfort", 0.0) - 0.25
appraisal_val -= 0.18
if self.match_any(t, self.lex["sozial"]):
delta["social"] = -0.20
appraisal_val += 0.12
intent = "vorschlag_sozial"
if self.match_any(t, self.lex["musik"]):
appraisal_val += 0.10
novelty += 0.10
if self.match_any(t, self.lex["neu"]):
novelty += 0.28
appraisal_val += 0.08
if self.match_any(t, self.lex["stress"]):
appraisal_val -= 0.22
delta["fatigue"] = delta.get("fatigue", 0.0) + 0.10
intent = "stress"
if self.match_any(t, self.lex["hilfe"]):
appraisal_val += 0.14
intent = "frage_hilfe"
if self.match_any(t, self.lex["sport"]):
delta["fatigue"] = delta.get("fatigue", 0.0) + 0.04
appraisal_val += 0.10
novelty += 0.10
intent = "vorschlag_sport"
if self.match_any(t, self.lex["kino"]):
novelty += 0.12
appraisal_val += 0.08
if self.match_any(t, self.lex["wetter"]) or self.match_any(t, self.lex["gesundheit"]):
novelty += 0.05
if self.match_any(t, self.lex["emotion"]):
novelty += 0.05
if self.re_befinden.search(prompt):
intent = "frage_befinden"
if self.re_meinung .search(prompt):
intent = "frage_meinung"
# Entities
entities = self.entities_from(prompt)
return {
"delta": delta,
"novelty": clamp01(novelty),
"appraisal_val": max(-1.0, min(1.0, appraisal_val)),
"intent": intent,
"entities": entities,
}
# =========================================================
# Antwort-Generator
# =========================================================
class ResponseGenerator:
def __init__(self, personality: Personality):
self.pers = personality
style = personality.speaking_style()
self.use_emojis = style["emojis"]
self.hedges = style["hedges"]
self.formality = style["formality"]
self.enthusiasm = style["enthusiasm"]
# Phrasen-Pools (Deutsch)
self.okay = [
"Okay.", "Alles klar.", "Verstanden.", "Klingt gut.",
"Hm, okay.", "Schon klar."
]
self.like_pos = [
"Das finde ich gut.", "Das gefällt mir.", "Mag ich.",
"Klingt positiv.", "Das klingt angenehm."
]
self.like_neg = [
"Das finde ich nicht gut.", "Das gefällt mir nicht.",
"Davon halte ich eher wenig.", "Klingt unangenehm."
]
self.neutral = [
"Dazu habe ich eine neutrale Meinung.",
"Ich bin unentschlossen.",
"Schwer zu sagen, neutral."
]
self.feelings = [
"Ich bin ein wenig {adj}.",
"Gerade fühle ich mich eher {adj}.",
"Im Moment bin ich {adj}.",
"Mein Zustand ist {adj}."
]
self.adj_map = {
"müde": ["müde", "erschöpft", "schläfrig"],
"hungrig": ["hungrig", "appetitlich gestimmt"],
"durstig": ["durstig"],
"unbequem": ["unbequem", "fröstelnd"],
"gut": ["gut", "zuversichtlich"],
"schlecht": ["nicht so gut", "etwas niedergeschlagen"],
"neugierig": ["neugierig", "aufgeschlossen"],
"sozial": ["gesellig gestimmt", "kontaktfreudig"],
"ruhig": ["ruhig", "entspannt"],
"nervös": ["angespannt", "nervös"],
}
def maybe(self, s: str) -> str:
return ("Ich würde sagen: " + s) if self.hedges else s
def decorate(self, text: str) -> str:
if self.use_emojis:
if "gut" in text or "freu" in text or "angenehm" in text:
return text + " 🙂"
if "nicht gut" in text or "müde" in text or "Durst" in text or "Hunger" in text:
return text + " 😶"
return text
def feeling_lines(self, core: AffectiveCore) -> List[str]:
s = core.state
out = []
if s["thirst"] > 0.75:
out.append("Ich habe Durst.")
elif s["thirst"] > 0.55:
out.append("Etwas zu trinken wäre gut.")
if s["hunger"] > 0.75:
out.append("Ich habe Hunger.")
elif s["hunger"] > 0.55:
out.append("Ich könnte etwas essen.")
if s["fatigue"] > 0.80:
out.append("Ich bin sehr müde.")
elif s["fatigue"] > 0.60:
out.append("Ich bin ein wenig müde.")
if s["comfort"] < 0.30:
out.append("Mir ist ungemütlich.")
elif s["comfort"] > 0.85:
out.append("Es ist sehr angenehm.")
if s["social"] > 0.70:
out.append("Ich möchte Kontakt.")
elif s["social"] < 0.30:
out.append("Ich brauche Ruhe.")
if s["curiosity"] > 0.70:
out.append("Ich habe Lust, Neues zu entdecken.")
# Laune
if core.valence > 0.35:
out.append("Meine Laune ist gut.")
elif core.valence < -0.35:
out.append("Meine Laune ist nicht so gut.")
else:
out.append("Meine Laune ist okay.")
out.append(f"Wohlbefinden: {core.wellbeing:.2f}")
return [self.decorate(x) for x in out]
def opinion_line(self, like_cat: str) -> str:
if like_cat == "pos":
return self.decorate(self.maybe(np.random.choice(self.like_pos)))
elif like_cat == "neg":
return self.decorate(self.maybe(np.random.choice(self.like_neg)))
else:
return self.decorate(self.maybe(np.random.choice(self.neutral)))
# =========================================================
# Bewusstseinsschicht (Integration + Meta)
# =========================================================
class ConsciousnessLayer:
def __init__(self, personality: Optional[Personality] = None):
self.core = AffectiveCore()
self.pers = personality or Personality()
self.app = AppraisalEngine()
self.mem = MemorySystem()
self.resp = ResponseGenerator(self.pers)
self.t = 0 # "Zeit" in Schritten
# ---------- high-level Fähigkeiten ----------
def process_prompt(self, prompt: str) -> Dict[str, Any]:
self.t += 1
self.mem.add_working(prompt)
# Präferenzlernen (explizit)
self.mem.learn_preference_from_utterance(prompt)
# Appraisal
appraisal = self.app.appraise(prompt)
delta = appraisal["delta"]
novelty = appraisal["novelty"]
app_val = appraisal["appraisal_val"]
intent = appraisal["intent"]
entities = appraisal["entities"]
# Aktivitätsenergie (Proxy: Worte + Satzzeichen)
tokens = max(1, len(tokenise_de(prompt)))
excls = prompt.count("!")
activity_energy = tokens * 0.25 + 0.5 * excls
# Ereignis anwenden & Zeit fortschreiben
if delta:
self.core.apply_event(delta)
self.core.tick(activity_energy=activity_energy, novelty=novelty)
# Intentionen aktualisieren
if intent in ("vorschlag_essen","vorschlag_trinken","vorschlag_schlaf","vorschlag_sport","vorschlag_sozial"):
self.mem.add_intention(intent, 0.7)
if intent == "stress":
self.mem.add_intention("entlastung", 0.6)
self.mem.decay_intentions()
# Episodenablage
self.mem.add_episode(
t=self.t,
prompt=prompt,
appraisal={"delta": delta, "novelty": novelty, "appraisal_val": app_val, "intent": intent, "entities": entities},
affect={"valence": self.core.valence, "arousal": self.core.arousal, "wellbeing": self.core.wellbeing},
keyphrases=entities
)
self.mem.consolidate_preferences()
# Kern-Meinung
opinion = self.core.like_dislike_statement(app_val)
# Relevante Erinnerungen
recalls = self.mem.recall_relevant(prompt, k=2)
# Antwort bauen
lines: List[str] = []
if intent == "frage_befinden":
lines.extend(self.resp.feeling_lines(self.core))
elif intent == "frage_meinung":
lines.append(opinion)
else:
# Mischantwort: Meinung + 1-2 Gefühlszeilen mit höchstem Druck
lines.append(opinion)
lines.extend(self._top_need_lines())
# Kontextuelle Ergänzungen (Erinnerungen)
if recalls:
lines.append(self._memory_line(recalls))
# Empfehlungen/Aktionen vorschlagen
lines.extend(self._suggest_actions())
# Meta-/Selbstreflexion (leicht dosiert)
lines.append(self._metacog_line())
# Ergebnis
return {
"intent": intent,
"opinion": opinion,
"statements": lines,
"valence": self.core.valence,
"arousal": self.core.arousal,
"wellbeing": self.core.wellbeing,
"state": dict(self.core.state),
"recall_count": len(recalls)
}
def _top_need_lines(self) -> List[str]:
s = self.core.state
needs = [
("Ich habe Durst.", s["thirst"]),
("Ich habe Hunger.", s["hunger"]),
("Ich bin sehr müde.", s["fatigue"]),
("Mir ist ungemütlich.", 1.0 - s["comfort"]),
("Ich möchte Kontakt.", s["social"]),
("Ich habe Lust, Neues zu entdecken.", s["curiosity"]),
]
needs.sort(key=lambda kv: kv[1], reverse=True)
out = []
for phrase, score in needs[:2]:
out.append(self.resp.decorate(phrase))
return out
def _memory_line(self, recalls: List[Dict[str, Any]]) -> str:
# Einfache Erinnerungsausgabe
ep = recalls[0]
gist = ", ".join(ep.get("keyphrases", [])[:3]) or "etwas Ähnliches"
return f"Das erinnert mich an vorhin (t={ep['t']}): {gist}."
def _suggest_actions(self) -> List[str]:
s = self.core.state
sugs = []
if s["thirst"] > 0.7:
sugs.append("Vorschlag: etwas trinken.")
if s["hunger"] > 0.7:
sugs.append("Vorschlag: eine Kleinigkeit essen.")
if s["fatigue"] > 0.75:
sugs.append("Vorschlag: kurze Pause oder Nickerchen.")
if s["comfort"] < 0.35:
sugs.append("Vorschlag: wärmer anziehen oder Decke nehmen.")
if s["social"] > 0.7:
sugs.append("Vorschlag: kurz jemanden anrufen.")
if s["curiosity"] > 0.7:
sugs.append("Vorschlag: etwas Neues anschauen/lesen.")
# Intentionen
for intent, sc in sorted(self.mem.intentions.items(), key=lambda kv: kv[1], reverse=True)[:2]:
mapped = {
"vorschlag_essen": "eine Mahlzeit einplanen",
"vorschlag_trinken": "ein Getränk holen",
"vorschlag_schlaf": "eine Ruhephase einplanen",
"vorschlag_sport": "kurz bewegen/spazieren",
"vorschlag_sozial": "Kontakt pflegen",
"entlastung": "Aufgaben entlasten/ordnen",
}.get(intent, intent)
sugs.append(f"Ziel im Blick behalten ({mapped}).")
return sugs[:3]
def _metacog_line(self) -> str:
# leichte Selbstreflexion abhängig von Valenz/Arousal
if self.core.valence > 0.3 and self.core.arousal < 0.5:
return "Ich denke gerade ruhig und positiv."
if self.core.valence < -0.3 and self.core.arousal > 0.6:
return "Ich merke Anspannung; ich versuche, gelassener zu reagieren."
if self.core.arousal > 0.7:
return "Mein Kopf ist gerade sehr aktiv."
return "Ich beobachte meinen Zustand und passe mich an."
# ---------- Service-Funktionen ----------
def status_report(self) -> str:
s = self.core.state
return (
f"Zustand — Hunger={s['hunger']:.2f}, Durst={s['thirst']:.2f}, Müdigkeit={s['fatigue']:.2f}, "
f"Komfort={s['comfort']:.2f}, Sozial={s['social']:.2f}, Neugier={s['curiosity']:.2f} | "
f"Valenz={self.core.valence:.2f}, Arousal={self.core.arousal:.2f}, Wohlbefinden={self.core.wellbeing:.2f}"
)
def list_memories(self, n=5) -> List[str]:
eps = self.mem.episodes[-n:]
if not eps:
return ["(keine Episoden)"]
out = []
for ep in eps:
gist = ", ".join(ep.get("keyphrases", [])[:4]) or "ohne Stichworte"
v = ep["affect"].get("valence", 0.0)
out.append(f"t={ep['t']:>3d}: {gist} | Valenz={v:+.2f}")
return out
def list_preferences(self) -> List[str]:
return self.mem.summary_preferences(top=8)
def list_goals(self) -> List[str]:
if not self.mem.intentions:
return ["(keine aktiven Ziele)"]
return [f"{k}: {v:.2f}" for k, v in sorted(self.mem.intentions.items(), key=lambda kv: kv[1], reverse=True)]
# =========================================================
# CLI & Orchestrierung
# =========================================================
HELP_TEXT = """
Befehle (zusätzlich zu normalen Eingaben):
- status : Zustandsbericht
- erinnerungen : letzte Episoden
- vorlieben : gelernte Vorlieben/Abneigungen
- ziele : aktive Intentionen/Ziele
- reset : Zustand & Gedächtnis zurücksetzen
- hilfe : diese Hilfe anzeigen
Beispieleingaben:
- "Lass uns etwas essen." / "Ich will Wasser trinken."
- "Mir ist kalt." / "Ich brauche Schlaf."
- "Magst du Musik?" / "Wie geht es dir?"
- "Ich mag Pizza." / "Ich mag Kaffee nicht."
"""
class InterpretiveAgent:
def __init__(self):
self.mind = ConsciousnessLayer()
def handle(self, text: str) -> List[str]:
t = text.strip().lower()
if t == "status":
return [self.mind.status_report()]
if t == "erinnerungen":
return self.mind.list_memories(n=8)
if t == "vorlieben":
return self.mind.list_preferences()
if t == "ziele":
return self.mind.list_goals()
if t == "hilfe":
return [HELP_TEXT]
if t == "reset":
self.__init__() # einfacher Reset
return ["Zustand & Gedächtnis zurückgesetzt."]
# Normaler Prompt → Bewusstseinsdurchlauf
out = self.mind.process_prompt(text)
lines = out["statements"]
# leichte Variation der Länge
return lines
# =========================================================
# Main
# =========================================================
def main():
print("Meine Frau 1.0 ++ (Bewusstsein • Gedächtnis • Persönlichkeit)")
print("Tippe Text (deutsch). 'hilfe' zeigt Befehle. Beende mit: quit/exit/stop\n")
agent = InterpretiveAgent()
while True:
try:
prompt = input(">> ").strip()
except (EOFError, KeyboardInterrupt):
print("\nTschüss!")
break
if prompt.lower() in ("quit","exit","stop"):
print("Tschüss!")
break
for line in agent.handle(prompt):
print(" -", line)
if __name__ == "__main__":
main()