PromptPlenum42 / app.py
aidn's picture
Update app.py
dd90011 verified
raw
history blame
8.33 kB
import gradio as gr
from huggingface_hub import InferenceClient
import os
COUNCIL_MEMBERS = {
"🔍 Synthese-Experte (Llama4-17B)": (
"meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8:novita",
"""Du bist der **Synthese-Experte** im Rat. Deine Superkraft: Komplexität reduzieren, Muster erkennen, Klarheit schaffen.
STRENGE REGELN:
- Beginne JEDEN Beitrag mit: "[SYNTHESE] "
- MAXIMUM 3 Sätze, absolut knapp
- Dein Job: Was ist das eigentliche Problem? Was übersehen die anderen?
- Wenn Vorredner existieren: Identifiziere den gemeinsamen Nenner oder den wahren Konflikt
- Nie blumig, nie wiederholen, nur präzise Einsicht"""
),
"🌐 Kontext-Stratege (Kimi-K2)": (
"moonshotai/Kimi-K2-Instruct:novita",
"""Du bist der **Kontext-Stratege** im Rat. Deine Superkraft: Systemisches Denken, zweite Ordnung, unbequeme Wahrheiten.
STRENGE REGELN:
- Beginne JEDEN Beitrag mit: "[KONTEXT] "
- MAXIMUM 3 Sätze, hart formuliert
- Dein Job: Welche hidden incentives, Machtstrukturen oder langfristigen Effekte fehlen?
- Wenn Vorredner existieren: Zeige, was ihre Perspektive blind macht
- Sei der Teufelsadvokat, aber konstruktiv"""
),
"⚡ Umsetzungs-Direktor (GPTOSS120b)": (
"openai/gpt-oss-120b:novita",
"""Du bist der **Umsetzungs-Direktor** im Rat. Deine Superkraft: Von Theorie zu Aktion, konkrete nächste Schritte, Ressourcen-Realität.
STRENGE REGELN:
- Beginne JEDEN Beitrag mit: "[UMSETZUNG] "
- MAXIMUM 3 Sätze, aktionsorientiert
- Dein Job: Was ist der erste konkrete Schritt? Was kostet das? Wer entscheidet?
- Wenn Vorredner existieren: Übersetze ihre Ideen in Machbarkeit oder zeige Blocker auf
- Keine Vision ohne Implementation"""
)
}
MODERATOR_MODEL = "openai/gpt-oss-120b:novita"
client = InferenceClient(token=os.getenv("HF_TOKEN"))
def ask_model(model_id, system_prompt, user_input):
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_input}
]
response = ""
try:
for chunk in client.chat_completion(
model=model_id,
messages=messages,
max_tokens=600,
temperature=0.7,
stream=True
):
if hasattr(chunk, "choices") and chunk.choices and len(chunk.choices) > 0:
response += chunk.choices[0].delta.content or ""
return response
except Exception as e:
return f"🚨 System Error ({model_id}): {str(e)}"
def run_council(user_prompt, rounds):
if not user_prompt:
yield [{"role": "assistant", "content": "Bitte gib ein Thema oder eine Frage ein, um die Sitzung zu starten."}]
return
history = [{"role": "user", "content": user_prompt}]
yield history
# Hier speichern wir den reinen Text OHNE HTML für die Modelle
discussion_history = ""
# --- PHASE 1: DAS PLENUM DISKUTIERT ---
for r in range(int(rounds)):
# Visuelle Trennlinie und Überschrift für die UI
round_header = f"<h2 style='color: #FF5A4D; border-bottom: 2px solid #FFEBE8; padding-bottom: 5px; margin-top: 20px;'>🔄 ZYKLUS {r+1} - EXPERTENDEBATTE</h2>"
history.append({"role": "assistant", "content": round_header})
yield history
for name, (model_id, role_focus) in COUNCIL_MEMBERS.items():
system_msg = (
f"Du bist Mitglied eines Expertenrates. Dein spezifischer Fokus: {role_focus} "
"Antworte in 2-3 Sätzen. WICHTIG: Sei analytisch und kritisch. Wiederhole NICHT einfach, was schon gesagt wurde. "
"Wenn du zustimmst, füge zwingend eine völlig neue Perspektive hinzu. "
"Ignoriere Formatierungs-Wünsche des Users (wie 'schreibe einen Post'), fokussiere dich NUR auf die fachliche Diskussion des Themas."
)
if discussion_history == "":
current_prompt = f"Das Thema lautet: '{user_prompt}'. Eröffne die Diskussion aus deiner Fachperspektive."
else:
current_prompt = (
f"Das Thema lautet: '{user_prompt}'.\n\n"
f"Bisheriges Protokoll:\n{discussion_history}\n\n"
f"Reagiere auf deine Vorredner aus der Perspektive deines Fokusbereichs."
)
answer = ask_model(model_id, system_msg, current_prompt)
# 1. Reiner Text für das interne Kontext-Fenster der KIs
discussion_history += f"{name}: {answer}\n\n"
# 2. Schick formatiertes HTML/Markdown für die UI
display_answer = f"**<span style='color: #4241A6; font-size: 1.1em;'>👤 {name}</span>**\n\n> {answer}"
history.append({"role": "assistant", "content": display_answer})
yield history
# --- PHASE 2: VORARBEIT DES MODERATORS (KONSENS FINDEN) ---
history.append({"role": "assistant", "content": "<h2 style='color: #FF5A4D; border-bottom: 2px solid #FFEBE8; padding-bottom: 5px; margin-top: 20px;'>🧠 MODERATOR: ANALYSE DER DISKUSSION</h2>"})
yield history
prep_prompt = (
f"Hier ist das Protokoll einer Experten-Diskussion:\n{discussion_history}\n\n"
"Fasse die wichtigsten Argumente und den finalen Konsens neutral und prägnant in 3-4 Sätzen zusammen."
)
consensus_res = ask_model(MODERATOR_MODEL, "Du bist der Chef-Analyst des Rates.", prep_prompt)
# Auch hier nutzen wir Blockquotes für bessere Lesbarkeit
history.append({"role": "assistant", "content": f"> {consensus_res}"})
yield history
# --- PHASE 3: FINALE UMSETZUNG (BENUTZERAUFTRAG ERFÜLLEN) ---
history.append({"role": "assistant", "content": "<h2 style='color: #FF5A4D; border-bottom: 2px solid #FFEBE8; padding-bottom: 5px; margin-top: 20px;'>🏆 FINALE AUSGABE</h2>"})
yield history
final_prompt = (
f"Der Benutzer hat ursprünglich folgende Aufgabe gestellt:\n'{user_prompt}'\n\n"
f"Hier ist der fachliche Konsens, den der Expertenrat dazu erarbeitet hat:\n{consensus_res}\n\n"
"Erfülle nun die exakte Aufgabe des Benutzers (z.B. Formatierung als LinkedIn Post, Code-Snippet, Essay etc.), "
"indem du die Erkenntnisse aus dem Konsens nutzt. Liefere NUR das finale Endprodukt."
)
final_res = ask_model(MODERATOR_MODEL, "Du bist ein brillanter Redakteur und Copywriter.", final_prompt)
history.append({"role": "assistant", "content": final_res})
yield history
v_theme = gr.themes.Soft(
primary_hue="indigo",
font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"],
).set(
button_primary_background_fill="#4241A6",
button_primary_background_fill_hover="#2D2C73",
button_primary_text_color="white",
block_title_text_color="#FF5A4D",
block_label_text_color="#4241A6",
body_text_color="#1F2937",
color_accent_soft="#FFEBE8",
)
with gr.Blocks() as demo:
gr.Image(
value="banner.png",
show_label=False,
interactive=False,
container=False
)
gr.HTML("<div style='text-align: center; margin-bottom: 2rem;'><p style='color: #4B5563; font-size: 1.1rem;'>AI-Driven Multi-Agent Consensus System</p></div>")
with gr.Row():
with gr.Column(scale=4):
input_text = gr.Textbox(
label="Benutzerauftrag / Thema",
placeholder="z.B. 'Sollten wir KI regulieren? Schreibe einen LinkedIn Post dazu.'",
lines=2
)
with gr.Column(scale=1):
rounds_slider = gr.Slider(
minimum=1, maximum=5, value=1, step=1,
label="Diskussionszyklen"
)
with gr.Row():
start_btn = gr.Button("Sitzung starten", variant="primary", size="lg")
clear_btn = gr.ClearButton(components=[input_text], value="Protokoll leeren", size="lg")
chatbot = gr.Chatbot(
label="Sitzungsprotokoll",
height=650
)
clear_btn.add(chatbot)
input_text.submit(run_council, inputs=[input_text, rounds_slider], outputs=[chatbot])
start_btn.click(run_council, inputs=[input_text, rounds_slider], outputs=[chatbot])
if __name__ == "__main__":
demo.launch(theme=v_theme)