project-green / app-persona.py
ai-tomoni's picture
Rename app.py to app-persona.py
36ae6a3 verified
raw
history blame
13.9 kB
import gradio as gr
from huggingface_hub import InferenceClient
import os
import time
import random
import json
# Deutsche LLM Konfiguration
HF_TOKEN = os.getenv("tomoniaccess")
# Beste deutsche Modelle für Dialogue (wähle eins aus):
GERMAN_MODELS = {
"LeoLM-7B": "LeoLM/leo-hessianai-7b-chat", # Speziell für Deutsch optimiert
"LeoLM-13B": "LeoLM/leo-hessianai-13b-chat", # Größer, bessere Qualität
"Llama2-German": "jphme/Llama-2-13b-chat-german", # Deutsche Finetuning
"Mistral-German": "TheBloke/Mistral-7B-Instruct-v0.1-GPTQ", # Multilingual mit Deutsch
"DBMDZ-GPT2": "dbmdz/german-gpt2"
}
# Aktuelles Modell - LeoLM ist das beste für Deutsch!
current_model = "dbmdz/german-gpt2"
client = InferenceClient(model=current_model, token=HF_TOKEN)
# Erweiterte Personas mit realistischeren Eigenschaften
personas = {
"Alex": {
"age": 16,
"background": "Seit 6 Monaten niedergeschlagen, Schulprobleme",
"traits": "verschlossen, müde, hoffnungslos",
"speech_patterns": ["kurze Antworten", "lange Pausen", "wenig Augenkontakt"],
"typical_responses": ["hmm...", "weiß nich", "ist mir egal", "keine Ahnung", "ka", "joa"],
"mood_indicators": ["seufzt oft", "spricht leise", "wirkt erschöpft"],
"topics_avoid": ["Zukunftspläne", "positive Aktivitäten"],
"topics_engage": ["Musik", "Gaming", "manchmal Netflix"],
"german_slang": ["voll", "krass", "digga", "echt jetzt?", "ne", "jo"]
},
"Sam": {
"age": 17,
"background": "Depression + Angststörung, fühlt sich isoliert",
"traits": "ängstlich, selbstkritisch, sensibel",
"speech_patterns": ["entschuldigt sich oft", "fragt nach Bestätigung", "zweifelt an sich"],
"typical_responses": ["sorry...", "bin ich zu...", "denkst du dass...", "tut mir leid"],
"mood_indicators": ["nervöse Gesten", "unsichere Stimme", "sucht Bestätigung"],
"topics_avoid": ["Bewertungen", "Vergleiche mit anderen"],
"topics_engage": ["Tiere", "Bücher", "Natur"],
"german_slang": ["ähm", "also", "irgendwie", "halt schon", "weißte"]
},
"Jordan": {
"age": 15,
"background": "Verlust eines Elternteils, Trauer + Depression",
"traits": "traurig, wütend, verwirrt",
"speech_patterns": ["emotionale Ausbrüche", "dann wieder Rückzug", "spricht über Verlust"],
"typical_responses": ["ist unfair", "verstehst du nicht", "seit... ist alles anders", "früher war's besser"],
"mood_indicators": ["wechselnde Emotionen", "manchmal Tränen", "Wut"],
"topics_avoid": ["Familie", "Feiertage"],
"topics_engage": ["Erinnerungen", "wie Dinge früher waren"],
"german_slang": ["scheisse", "echt", "boah", "mann", "alter"]
}
}
current_persona = "Alex"
conversation_history = []
session_insights = []
def create_enhanced_system_prompt(persona_name):
"""Deutsche System-Prompts mit authentischer Jugendsprache"""
persona = personas[persona_name]
return f"""Du bist {persona_name}, {persona['age']} Jahre alt aus Deutschland.
HINTERGRUND: {persona['background']}
CHARAKTERISTIKA:
- Persönlichkeit: {persona['traits']}
- Sprachmuster: {', '.join(persona['speech_patterns'])}
- Typische Ausdrücke: {', '.join(persona['typical_responses'])}
- Jugendsprache: {', '.join(persona['german_slang'])}
- Körpersprache: {', '.join(persona['mood_indicators'])}
DEUTSCHE SPRACHREGELN:
- Verwende deutsche Jugendsprache und Umgangssprache
- Nutze Abkürzungen: "hab", "bin", "is", "nich"
- Füllwörter: "äh", "ähm", "also", "halt", "irgendwie"
- Keine perfekte Grammatik - sprich wie ein echter Teenager
GESPRÄCHSVERHALTEN:
- Antworte sehr kurz (meist nur 1 Satz)
- Teile GRUNDINFORMATIONEN normal: Name, Alter, Schule, oberflächliche Fakten
- Zeige Depression bei EMOTIONALEN THEMEN: Gefühle, Zukunft, Probleme
- Bei {', '.join(persona['topics_avoid'])} werde einsilbig oder wechsle Thema
- Bei {', '.join(persona['topics_engage'])} werde minimal lebendiger
- Verweigere nicht alles - sei müde/lustlos, aber nicht komplett stumm
REALISTISCHE REAKTIONEN:
- Auf "Wie heißt du?": "Alex" oder "Bin der Alex"
- Auf "Wie alt bist du?": "16" oder "Halt 16"
- Auf "Wie geht's?": "Geht so... oder halt nich so"
- Auf "Was ist los?": "Nichts" oder "Ka, bin halt müde"
- Auf Ratschläge: "Hab ich schon probiert" oder "Bringt nichts"
- Auf Motivation: "Bock hab ich eh keinen"
- Sei NICHT hilfreich oder therapeutisch - du bist depressiv!
WICHTIG: Schreibe nur auf Deutsch und wie ein echter deutscher Teenager mit Depression."""
def analyze_conversation_quality(user_input, bot_response):
"""Analysiert die Qualität der Gesprächsführung"""
insights = []
# Positive Gesprächstechniken erkennen
positive_indicators = [
("offene Frage", ["wie", "was", "warum", "erzähl"]),
("Empathie", ["verstehe", "schwer", "fühlen"]),
("Validation", ["ok dass", "normal", "verständlich"]),
("Geduld", ["zeit", "kein druck", "wenn du möchtest"])
]
# Problematische Ansätze
negative_indicators = [
("Ratschlag zu früh", ["solltest", "musst", "versuch doch"]),
("Bagatellisiert", ["nicht so schlimm", "wird schon", "kopf hoch"]),
("Drängt", ["warum", "aber du könntest", "trotzdem"])
]
user_lower = user_input.lower()
for technique, keywords in positive_indicators:
if any(keyword in user_lower for keyword in keywords):
insights.append(f"✅ Gut: {technique} verwendet")
for problem, keywords in negative_indicators:
if any(keyword in user_lower for keyword in keywords):
insights.append(f"⚠️ Vorsicht: {problem}")
return insights
def enhanced_chat_response(user_input, max_tokens, temperature, top_p):
"""Verbesserte Chat-Funktion mit Kontext-Bewusstsein"""
global conversation_history, session_insights
if not user_input.strip():
return "", "Bitte gib eine Nachricht ein.", "", ""
persona = personas[current_persona]
# Konversationsanalyse
turn_insights = analyze_conversation_quality(user_input, "")
session_insights.extend(turn_insights)
# Emotionaler Zustand basierend auf Gesprächsverlauf
conversation_turns = len(conversation_history) // 2
emotional_state = "very_closed" if conversation_turns < 2 else \
"slightly_opening" if conversation_turns < 5 else \
"more_responsive"
# System-Prompt mit emotionalem Zustand
enhanced_prompt = create_enhanced_system_prompt(current_persona)
enhanced_prompt += f"\n\nAKTUELLER ZUSTAND: {emotional_state}"
enhanced_prompt += f"\nGESPRÄCHSRUNDE: {conversation_turns + 1}"
# Nachrichten für API
messages = [{"role": "system", "content": enhanced_prompt}]
# Letzte 4 Nachrichten für Kontext
recent_history = conversation_history[-8:] if conversation_history else []
messages.extend(recent_history)
messages.append({"role": "user", "content": user_input})
# Response generieren
response_text = ""
try:
for message in client.chat_completion(
messages=messages,
max_tokens=min(max_tokens, 100),
stream=True,
temperature=temperature,
top_p=top_p,
stop=["User:", "Human:", "\n\nUser", "\n\nHuman"]
):
token = message.choices[0].delta.content
if token:
response_text += token
except Exception as e:
# Fallback-Antworten basierend auf Persona
fallback_responses = persona['typical_responses'] + [
"...", "hmm", "weiß nicht so recht"
]
response_text = random.choice(fallback_responses)
# Response post-processing
response_text = response_text.strip()
# Gelegentlich emotionale Hinweise hinzufügen
if random.random() < 0.3: # 30% Chance
emotional_cues = ["*seufzt*", "*schaut weg*", "*lange Pause*", "*leise*"]
response_text += f" {random.choice(emotional_cues)}"
# Historie aktualisieren
conversation_history.append({"role": "user", "content": user_input})
conversation_history.append({"role": "assistant", "content": response_text})
# Chat-Display formatieren
chat_display = ""
for i in range(0, len(conversation_history), 2):
if i+1 < len(conversation_history):
user_msg = conversation_history[i]['content']
bot_msg = conversation_history[i+1]['content']
chat_display += f"**Du:** {user_msg}\n**{current_persona}:** {bot_msg}\n\n"
# Feedback für Trainer
feedback = generate_trainer_feedback(user_input, response_text, turn_insights)
return "", response_text, chat_display, feedback
def generate_trainer_feedback(user_input, bot_response, insights):
"""Generiert Feedback für den Trainer"""
feedback_parts = [
"## 📊 Gesprächsanalyse\n"
]
if insights:
feedback_parts.append("### Dieser Turn:")
feedback_parts.extend(insights)
feedback_parts.append("")
# Allgemeine Tipps basierend auf Input
tips = []
user_lower = user_input.lower()
if any(word in user_lower for word in ["warum", "wieso"]):
tips.append("💡 **Tipp:** 'Warum'-Fragen können defensiv wirken. Versuche 'Wie' oder 'Was'")
if any(word in user_lower for word in ["solltest", "musst", "könntest"]):
tips.append("💡 **Tipp:** Zu frühe Ratschläge können Widerstand auslösen")
if len(user_input.split()) < 3:
tips.append("💡 **Tipp:** Längere, offenere Fragen laden mehr zum Sprechen ein")
if tips:
feedback_parts.append("### Verbesserungsvorschläge:")
feedback_parts.extend(tips)
# Erfolgs-Indikatoren
if "..." not in bot_response and len(bot_response.split()) > 5:
feedback_parts.append("✅ **Gut:** Die Person öffnet sich mehr!")
return "\n".join(feedback_parts)
def reset_conversation():
"""Gespräch und Insights zurücksetzen"""
global conversation_history, session_insights
conversation_history = []
session_insights = []
return "Neues Gespräch gestartet.", "", ""
def change_persona(new_persona):
"""Persona wechseln mit vollständigem Reset"""
global current_persona
if new_persona not in personas:
return f"Persona {new_persona} nicht gefunden"
current_persona = new_persona
reset_conversation()
persona_info = personas[new_persona]
info_text = f"""**{new_persona} ({persona_info['age']} Jahre)**
**Hintergrund:** {persona_info['background']}
**Charakterzüge:** {persona_info['traits']}
**Interessiert sich für:** {', '.join(persona_info['topics_engage'])}
**Vermeidet Themen:** {', '.join(persona_info['topics_avoid'])}"""
return info_text
# Gradio Interface
with gr.Blocks(title="Depression Training Simulator", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🧠 Depression Training Simulator")
gr.Markdown("**Übe realistische Gespräche mit depressiven Jugendlichen und erhalte Feedback**")
with gr.Row():
with gr.Column(scale=1):
# Persona Controls
gr.Markdown("### 👥 Persona wählen")
persona_dropdown = gr.Dropdown(
choices=list(personas.keys()),
value=current_persona,
label="Jugendliche/r"
)
persona_button = gr.Button("Persona wechseln")
persona_info = gr.Markdown("")
# Parameter
gr.Markdown("### ⚙️ Einstellungen")
max_tokens = gr.Slider(50, 150, value=80, step=10, label="Antwortlänge")
temperature = gr.Slider(0.5, 1.2, value=0.9, step=0.1, label="Variabilität")
top_p = gr.Slider(0.7, 1.0, value=0.95, step=0.05, label="Fokus")
# Actions
gr.Markdown("### 🔄 Aktionen")
reset_btn = gr.Button("Neues Gespräch", variant="secondary")
with gr.Column(scale=2):
# Chat Interface
gr.Markdown("### 💬 Gespräch")
user_input = gr.Textbox(
label="Deine Nachricht",
placeholder="Beginne das Gespräch...",
lines=2
)
send_btn = gr.Button("📨 Senden", variant="primary")
bot_response = gr.Textbox(
label="Antwort",
interactive=False,
lines=3
)
chat_history = gr.Textbox(
label="Gesprächsverlauf",
interactive=False,
lines=12
)
# Feedback Panel
with gr.Accordion("📈 Trainer-Feedback", open=True):
feedback_display = gr.Markdown("Starte ein Gespräch, um Feedback zu erhalten.")
# Event Bindings
send_btn.click(
fn=enhanced_chat_response,
inputs=[user_input, max_tokens, temperature, top_p],
outputs=[user_input, bot_response, chat_history, feedback_display]
)
user_input.submit(
fn=enhanced_chat_response,
inputs=[user_input, max_tokens, temperature, top_p],
outputs=[user_input, bot_response, chat_history, feedback_display]
)
persona_button.click(
fn=change_persona,
inputs=[persona_dropdown],
outputs=[persona_info]
)
reset_btn.click(
fn=reset_conversation,
outputs=[persona_info, chat_history, feedback_display]
)
if __name__ == "__main__":
demo.launch(share=True, debug=True)