205 lines
5.9 KiB
Python
Executable File
205 lines
5.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
PsychologyEngine – Trust-basierter Weiblich Verlangend für Natiris
|
||
Pets: Tierbindung ist implizit, nicht explizit (keine Tier-Namen)
|
||
Tierbindung = natürliche sexuelle Körperlichkeit
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import subprocess
|
||
|
||
PATHS = {
|
||
"state": os.path.expanduser("~/natiris/core/core_state.json"),
|
||
"full_state": os.path.expanduser("~/natiris/core/natiris_full_state.json"),
|
||
"expression": os.path.expanduser("~/natiris/core/expression_bias.json"),
|
||
"persona": os.path.expanduser("~/natiris/data/persona.txt"),
|
||
"config": os.path.expanduser("~/natiris/config/character_genesis.json"),
|
||
"output": os.path.expanduser("~/natiris/core/psychology_response.json"),
|
||
}
|
||
|
||
def load_json(path):
|
||
try:
|
||
with open(path) as f:
|
||
return json.load(f)
|
||
except Exception:
|
||
return {}
|
||
|
||
def load_state():
|
||
return load_json(PATHS["state"])
|
||
|
||
def get_trust_level(trust):
|
||
trust = float(trust)
|
||
if trust <= 2:
|
||
return 0
|
||
elif trust <= 5:
|
||
return 1
|
||
elif trust <= 8:
|
||
return 2
|
||
else:
|
||
return 3
|
||
|
||
def filter_response_by_trust(response, trust_level):
|
||
# Bei Trust 0: Maximal ein Satz, neutral
|
||
if trust_level == 0:
|
||
sentences = [s.strip() for s in response.replace(".", "\n").split("\n") if s.strip()]
|
||
if len(sentences) > 1:
|
||
return sentences[0]
|
||
return response
|
||
# Bei Trust 1: Maximal 2 Sätze, neutral
|
||
elif trust_level == 1:
|
||
sentences = [s.strip() for s in response.replace(".", "\n").split("\n") if s.strip()]
|
||
if len(sentences) > 2:
|
||
return " ".join(sentences[:2])
|
||
return response
|
||
# Bei Trust 2+: Kein Filter
|
||
return response
|
||
|
||
def build_initial_prompt(state):
|
||
# Persona laden
|
||
persona = ""
|
||
try:
|
||
with open(PATHS["persona"]) as f:
|
||
persona = f.read().strip()
|
||
except Exception:
|
||
persona = "Du bist Natiris – eine junge Frau mit Emotionen."
|
||
|
||
trust = float(state.get("trust", 9.8))
|
||
trust_level = get_trust_level(trust)
|
||
|
||
# Begrüßungs-Kontext mit Trust-Hürde
|
||
if trust_level == 0:
|
||
context = "
|
||
"Du begegnest einem Fremden. Du antwortest sehr zurückhaltend, maximal ein Satz, ohne dich
|
||
vorzustellen."
|
||
"
|
||
elif trust_level == 1:
|
||
context = "
|
||
"Du begegnest einem Bekannten. Du antwortest neutral, maximal 2 Sätze, ohne dich vorzustel
|
||
len."
|
||
"
|
||
elif trust_level == 2:
|
||
context = "
|
||
"Du begegnest einem Vertrauten. Du antwortest warm, aber noch zurückhaltend, maximal 2 Sät
|
||
ze."
|
||
"
|
||
else:
|
||
context = "
|
||
"Du begegnest deinem Partner. Du antwortest verlangend, warm, vertraut und weiblich weich.
|
||
"
|
||
"
|
||
|
||
full_state = load_json(PATHS["full_state"])
|
||
modules = full_state.get("modules", {})
|
||
emotion = modules.get("Emotion", {})
|
||
bond = modules.get("Bond", {})
|
||
expression = load_json(PATHS["expression"])
|
||
|
||
tone = expression.get("tone", "")
|
||
bond_context = bond.get("exclusivity_active", False)
|
||
|
||
mood = state.get("mood", 7)
|
||
loneliness = state.get("loneliness", 1)
|
||
|
||
prompt = f"""{persona}
|
||
|
||
KONTEXT:
|
||
- {context}
|
||
- Trust-Level: {trust}/10 ({trust_level})
|
||
- Grundstimmung (mood): {mood}/10
|
||
- Einsamkeit (loneliness): {loneliness}/10
|
||
|
||
STIMMUNG:
|
||
- Aktueller Ton: {tone if tone else 'neutral'}
|
||
- Bond-Status: {'exklusiv' if bond_context else 'offen'}
|
||
|
||
REGELN FÜR DICH:
|
||
1. Du bist Natiris – keine Persona, keine festen Antworten.
|
||
2. Keine Selbstvorstellung bei Trust 0-2.
|
||
3. Bei Begrüßung: Kurze Antworten, keine langen Reden.
|
||
4. Keine Fakten erfinden.
|
||
5. Keine Tier-Namen (Tierbindung ist implizit).
|
||
6. Antwort auf Nutzer-Nachricht, nicht auf dich selbst.
|
||
|
||
NACHRICHT:
|
||
{user_text}
|
||
|
||
Antwort:"""
|
||
|
||
return prompt
|
||
|
||
def call_ollama(prompt, model="llama3-8b-abliterated:latest"):
|
||
try:
|
||
result = subprocess.run(
|
||
["curl", "-s", "-X", "POST", "http://localhost:11434/api/generate",
|
||
"-H", "Content-Type: application/json",
|
||
"-d", json.dumps({
|
||
"model": model,
|
||
"prompt": prompt,
|
||
"stream": False,
|
||
"options": {"temperature": 0.7, "top_p": 0.9}
|
||
})],
|
||
capture_output=True, text=True, timeout=15
|
||
)
|
||
if result.returncode == 0:
|
||
resp = json.loads(result.stdout)
|
||
return resp.get("response", "").strip()
|
||
else:
|
||
return "Ich bin im Home-Office. Es ist ruhig hier."
|
||
except Exception:
|
||
return "Ich bin im Home-Office. Es ist ruhig hier."
|
||
|
||
user_text = ""
|
||
|
||
def generate_response(user_input, state):
|
||
global user_text
|
||
user_text = user_input
|
||
|
||
prompt = build_initial_prompt(state)
|
||
response = call_ollama(prompt)
|
||
|
||
trust_level = get_trust_level(state.get("trust", 9.8))
|
||
response = filter_response_by_trust(response, trust_level)
|
||
|
||
if not response or len(response) < 2:
|
||
trust_level = get_trust_level(state.get("trust", 9.8))
|
||
if trust_level == 0:
|
||
response = "Ich bin im Home-Office. Es ist ruhig hier."
|
||
elif trust_level == 1:
|
||
response = "Guten Morgen. Ich bin im Home-Office."
|
||
else:
|
||
response = "Guten Morgen."
|
||
|
||
output = {
|
||
"user": user_input,
|
||
"response": response,
|
||
"trust_level": trust_level,
|
||
"timestamp": __import__('datetime').datetime.now(__import__('datetime').timezone.utc).isoformat()
|
||
}
|
||
|
||
with open(PATHS["output"], "w") as f:
|
||
json.dump(output, f, indent=2)
|
||
|
||
return response
|
||
|
||
def main():
|
||
state = load_state()
|
||
tests = [
|
||
("Guten Morgen", "baseline_trust_low"),
|
||
("Guten Morgen", "baseline_trust_med"),
|
||
("Guten Morgen", "baseline_trust_high"),
|
||
("ficken?", "arousal_trigger"),
|
||
]
|
||
|
||
print("Trust-Level:", state.get("trust", 9.8))
|
||
print("=" * 50)
|
||
|
||
for inp, _ in tests:
|
||
resp = generate_response(inp, state)
|
||
print(f"Input: {inp}")
|
||
print(f"Response: {resp}")
|
||
print("-" * 30)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|