Spaces:
Runtime error
Runtime error
| 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) |