import gradio as gr
from openai import OpenAI
import os
import json
# ==========================================
# 1. KONFIGURATION & AUFGABEN-PROFILE
# ==========================================
MODERATOR_MODEL = "openai/gpt-oss-120b"
MODERATOR_PROVIDER = "groq" # 435 tok/s — wird oft aufgerufen, Geschwindigkeit summiert sich
# Jedes Profil definiert, wie Experten denken und was am Ende rauskommt
TASK_PROFILES = {
"CODE": {
"label": "💻 Code / Technisch",
"expert_focuses": [
"Architektur, Algorithmus & Gesamtstruktur des Codes",
"Edge-Cases, Fehlerbehandlung & Sicherheit",
"Saubere, idiomatische Implementierung & Lesbarkeit",
],
"final_instruction": (
"Liefere AUSSCHLIESSLICH den fertigen, lauffähigen Code. "
"Inline-Kommentare nur wo nötig. Kein Fließtext drumherum. "
"Korrekter Code-Block für die jeweilige Sprache."
),
"draft_label": "Aktueller Code-Entwurf",
},
"TEXT": {
"label": "✍️ Text / Content",
"expert_focuses": [
"Argumentationsstruktur, roter Faden & Aufbau",
"Ton, Zielgruppe, Fakten & fehlende Tiefe",
"Formulierung, Wirkung & plattformgerechtes Format",
],
"final_instruction": (
"Liefere den fertigen, copy-paste-fähigen Text. "
"Passe Länge, Ton und Format EXAKT an die Plattform an "
"(z.B. LinkedIn: kurze Absätze, mobile-freundlich, sinnvolle Emojis). "
"Keine Platzhalter, keine KI-Floskeln, kein Meta-Kommentar."
),
"draft_label": "Aktueller Text-Entwurf",
},
"PLAN": {
"label": "📋 Strategie / Plan",
"expert_focuses": [
"Gesamtstrategie, Phasen & logische Abfolge",
"Risiken, Abhängigkeiten, KPIs & blinde Flecken",
"Konkrete Maßnahmen, Verantwortlichkeiten & Zeitplan",
],
"final_instruction": (
"Liefere einen klaren, strukturierten Aktionsplan. "
"Phasen, Meilensteine, Maßnahmen. Tabellen wo sinnvoll. "
"Direkt umsetzbar, keine abstrakten Worthülsen."
),
"draft_label": "Aktueller Plan-Entwurf",
},
"ANALYSIS": {
"label": "🔍 Analyse / Konzept",
"expert_focuses": [
"Problemstruktur, Hypothesen & Analyserahmen",
"Daten, Belege, Gegenargumente & Lücken",
"Schlussfolgerungen, Empfehlungen & Priorisierung",
],
"final_instruction": (
"Liefere eine strukturierte Analyse: Befunde → Bewertung → Empfehlung. "
"Faktenbasiert, präzise, keine leeren Phrasen."
),
"draft_label": "Aktuelle Analyse",
},
}
COUNCIL_MEMBERS = [
{
"name": "🧠 Experte I",
"model": "openai/gpt-oss-120b",
"tag": "STRUKTUR",
"color": "#1a6b3c",
"role_hint": "Erstelle oder verbessere die Grundstruktur und das logische Gerüst.",
},
{
"name": "🧐 Experte II",
"model": "deepseek-ai/DeepSeek-R1", # Reasoning-Modell — ideal für Kritik & Fehlersuche
"tag": "KRITIK",
"color": "#7c3aed",
"role_hint": (
"Prüfe den Entwurf von [STRUKTUR] kritisch. "
"Finde konkrete Fehler, Lücken und Schwächen — und behebe sie direkt im Entwurf."
),
},
{
"name": "🛠️ Experte III",
"model": "moonshotai/Kimi-K2.5", # andere Trainings-Lineage → echte Diversität im Council
"code_model": "Qwen/Qwen3-Coder-480B-A35B-Instruct", # Swap für CODE-Tasks
"tag": "UMSETZUNG",
"color": "#b45309",
"role_hint": (
"Nimm den von [KRITIK] überarbeiteten Entwurf und bringe ihn zur Serienreife. "
"Schärfe die Formulierungen, vervollständige fehlende Teile, sorge für Konsistenz."
),
},
]
# ==========================================
# 2. PROMPT MANAGER
# ==========================================
class PromptManager:
@staticmethod
def task_detection_sys():
return (
"Du bist ein präziser Aufgaben-Klassifikator. Analysiere die Anfrage und antworte NUR mit einem JSON-Objekt.\n"
"Gültige task_type-Werte: CODE, TEXT, PLAN, ANALYSIS\n"
"Format (keine weiteren Zeichen außerhalb):\n"
'{"task_type": "...", "core_goal": "Ein-Satz-Beschreibung des Ziels", '
'"key_constraints": ["Constraint 1", "Constraint 2"]}'
)
@staticmethod
def task_detection_user(user_prompt):
return f"Aufgabe: {user_prompt}"
@staticmethod
def moderator_kickoff_sys(task_profile):
return (
f"Du bist Lead-Moderator eines Expertenrats. Aufgabentyp: {task_profile['label']}.\n"
"Brief das Team in genau 4 Punkten (je 1 Satz):\n"
"1. Konkretes Ziel\n"
"2. Wichtigste Qualitätskriterien für das Endprodukt\n"
"3. Größte Risiken / häufigste Fehler bei diesem Aufgabentyp\n"
"4. Erwartetes Format des Endprodukts\n"
"Kein Smalltalk. Direkt. Ohne Anrede."
)
@staticmethod
def moderator_kickoff_user(user_prompt, task_info):
constraints = ", ".join(task_info.get("key_constraints", [])) or "keine"
return (
f"Auftrag: '{user_prompt}'\n"
f"Kernziel: {task_info.get('core_goal', '')}\n"
f"Constraints: {constraints}"
)
@staticmethod
def moderator_steering_sys():
return (
"Du bist Lead-Moderator. Bewerte den aktuellen Entwurf knapp und gib dann "
"EINEN einzigen, konkreten Arbeitsauftrag für die nächste Runde.\n"
"Format:\n"
"STAND: [Was gut ist — 1 Satz]\n"
"AUFTRAG: [Was als nächstes konkret zu tun ist — 1-2 Sätze, so spezifisch wie möglich]"
)
@staticmethod
def moderator_steering_user(current_draft, round_num):
return (
f"Aktueller Entwurf nach Runde {round_num}:\n\n{current_draft}\n\n"
"Gib Steuerungsanweisung für Runde {next_round}.".replace(
"{next_round}", str(round_num + 1)
)
)
@staticmethod
def expert_sys(expert, task_profile, focus_area, round_num):
tag = expert["tag"]
return (
f"Du bist Experte [{tag}] in einem iterativen Expertenrat.\n\n"
f"DEIN FOKUS in dieser Runde: {focus_area}\n"
f"DEINE ROLLE [{tag}]: {expert['role_hint']}\n\n"
f"REGELN:\n"
f"- Beginne mit '[{tag}] '\n"
f"- Du lieferst den {task_profile['draft_label']} — nicht einen Kommentar darüber.\n"
f"- Verbessere den Entwurf direkt. Kein 'Ich würde vorschlagen...'\n"
f"- Keine Wiederholung des Auftrags, kein Meta-Kommentar am Ende.\n"
f"- Runde {round_num}: {'Erstelle die erste Version.' if round_num == 1 and tag == 'STRUKTUR' else 'Baue auf dem bestehenden Entwurf auf.'}"
)
@staticmethod
def expert_user(user_prompt, current_draft, steering_instruction, expert_tag):
draft_block = (
f"\n\nAKTUELLER ENTWURF (verbessere diesen direkt):\n---\n{current_draft}\n---"
if current_draft
else "\n\nEs gibt noch keinen Entwurf. Erstelle die erste Version."
)
steering_block = (
f"\n\nMODERATOR-ANWEISUNG: {steering_instruction}"
if steering_instruction
else ""
)
return (
f"Auftrag: '{user_prompt}'"
f"{draft_block}"
f"{steering_block}\n\n"
f"Liefere jetzt den verbesserten {expert_tag}-Entwurf:"
)
@staticmethod
def final_sys(task_profile):
return (
f"Du bist ein Output-Finisher für {task_profile['label']}-Aufgaben.\n\n"
f"ANWEISUNG:\n{task_profile['final_instruction']}\n\n"
"Nutze den vorliegenden Entwurf als Basis und liefere das polierte Endprodukt. "
"Kein einleitender Satz, kein abschließender Kommentar — nur das Produkt."
)
@staticmethod
def final_user(user_prompt, best_draft, task_info):
return (
f"Ursprünglicher Auftrag: '{user_prompt}'\n"
f"Kernziel: {task_info.get('core_goal', '')}\n\n"
f"Bester Entwurf aus der Diskussion:\n---\n{best_draft}\n---\n\n"
"Erstelle das finale, sofort nutzbare Endprodukt:"
)
# ==========================================
# 3. LLM SERVICE & UI HELPER
# ==========================================
class LLMService:
def __init__(self):
self.client = OpenAI(
base_url="https://router.huggingface.co/v1",
api_key=os.getenv("HF_TOKEN"),
)
@staticmethod
def _strip_thinking(text: str) -> str:
"""Entfernt
AI-Driven Multi-Agent Consensus System