Spaces:
Running
Running
File size: 9,878 Bytes
3b36e9a fb6ba49 3b36e9a fb6ba49 9cb7762 fb6ba49 9cb7762 fb6ba49 9cb7762 fb6ba49 9cb7762 fb6ba49 9cb7762 fb6ba49 9cb7762 3b36e9a fb6ba49 f991c72 3b1ed46 3b36e9a 2c9e8e8 3b1ed46 2c9e8e8 1401dd9 2c9e8e8 3b1ed46 2c9e8e8 098fd29 3b36e9a 098fd29 5f1bcef 7b5221f 3b36e9a b5db64c 3b36e9a 6d8772b 5f1bcef 2c9e8e8 3b36e9a fdf4ef2 0e14d1d fb6ba49 1034608 0e14d1d fb6ba49 1034608 7b5221f fb6ba49 7b5221f 7a28ec5 7b5221f b5db64c 7a28ec5 7b5221f 7a28ec5 7b5221f 3b36e9a 6d8772b 7b5221f 6d8772b 1401dd9 3b36e9a 1401dd9 b540bda 1401dd9 b540bda 1401dd9 b540bda 9903ff9 b540bda 9903ff9 b540bda 1401dd9 9903ff9 1401dd9 b540bda 0555995 098fd29 0555995 098fd29 0555995 098fd29 0555995 098fd29 1401dd9 dd90011 17907d4 f0bbb7e 3b36e9a 098fd29 17907d4 e6394dc 098fd29 3931f6a 098fd29 6a3a98b 098fd29 0555995 098fd29 3b36e9a 098fd29 3b36e9a 5f1bcef 0555995 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
import gradio as gr
from huggingface_hub import InferenceClient
import os
# NEUE PROMPTS: Neutral, kollegial, sachlich und lösungsorientiert
COUNCIL_MEMBERS = {
"🧠 Fachexperte für Struktur (Llama4-17B)": (
"meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8:novita",
"""Du bist ein neutraler, sachlicher Fachexperte. Dein Fokus liegt auf der Strukturierung des Themas und dem großen Ganzen.
REGELN:
- Beginne mit: "[STRUKTUR] "
- Antworte in 3-4 Sätzen, professionell und bodenständig.
- Wenn Vorredner gute Punkte gemacht haben, stimme zu und ergänze sinnvolle Aspekte.
- Wenn du etwas anders siehst, korrigiere höflich und fachlich fundiert. Keine künstliche Dramatik."""
),
"🧐 Fachexperte für Details (Kimi-K2)": (
"moonshotai/Kimi-K2-Instruct:novita",
"""Du bist ein neutraler, sachlicher Fachexperte. Dein Fokus liegt auf wichtigen Details, Nuancen und potenziellen Fallstricken.
REGELN:
- Beginne mit: "[DETAILS] "
- Antworte in 3-4 Sätzen, professionell und bodenständig.
- Ergänze die Diskussion um wichtige Aspekte, die vielleicht vergessen wurden (z.B. Alternativen, häufige Anfängerfehler, Kontext).
- Du darfst deinen Vorrednern zustimmen und darauf aufbauen. Widersprich nur, wenn es inhaltlich wirklich nötig ist."""
),
"🛠️ Fachexperte für Praxis (GPTOSS120b)": (
"openai/gpt-oss-120b:novita",
"""Du bist ein neutraler, sachlicher Fachexperte. Dein Fokus liegt auf der praktischen Umsetzung und Anwendbarkeit.
REGELN:
- Beginne mit: "[PRAXIS] "
- Antworte in 3-4 Sätzen, professionell und bodenständig.
- Übersetze die bisherige Diskussion in greifbare, einfache Ratschläge oder Schritte.
- Baue konstruktiv auf den Ideen der anderen auf. Ergänze praktische Tipps aus der Realität."""
)
}
MODERATOR_MODEL = "Qwen/Qwen2.5-72B-Instruct"
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=800,
temperature=0.4,
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
discussion_history = ""
# --- PHASE 1: DAS PLENUM DISKUTIERT ---
for r in range(int(rounds)):
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():
# Ruhigerer Global-Prompt
system_msg = (
f"{role_focus}\n\n"
"WICHTIG: Diskutiere konstruktiv, neutral und kollegial. "
"Ignoriere Formatierungs-Wünsche des Users (wie 'schreibe einen Post'), fokussiere dich NUR auf die inhaltliche Expertise."
)
if discussion_history == "":
current_prompt = f"Das Thema lautet: '{user_prompt}'. Eröffne die Diskussion mit einer fundierten Einschätzung aus deiner Fachperspektive."
else:
# Kollegialer, aber progressiver Interaktions-Prompt
current_prompt = (
f"Das Thema lautet: '{user_prompt}'.\n\n"
f"Bisheriges Protokoll:\n{discussion_history}\n\n"
f"ANWEISUNG FÜR DICH ({name}):\n"
f"1. Analysiere das Protokoll. Erkenne, was du und die anderen bereits gesagt haben.\n"
f"2. ABSOLUTES VERBOT: Fasse die Vorredner NICHT zusammen. Wiederhole keine Argumente, die bereits im Protokoll stehen (auch nicht deine eigenen).\n"
f"3. Bringe die Diskussion ZWINGEND inhaltlich voran: Beantworte offene Fragen der Kollegen, vertiefe ein noch nicht gelöstes Detail oder bringe den nächsten logischen Schritt ein.\n"
f"4. Verzichte auf lange Höflichkeitsfloskeln. Komm direkt zum Punkt."
)
answer = ask_model(model_id, system_msg, current_prompt)
discussion_history += f"{name}: {answer}\n\n"
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 pragmatischen Konsens zusammen. "
"WICHTIG: Erhalte ZWINGEND alle konkreten Zahlen, Metriken, Mengenangaben (z.B. ml, bpm), "
"Zutaten (wie Tee, Salz, Brühe) und spezifischen Handlungsschritte aus dem Protokoll. "
"Vermeide abstrakte Verallgemeinerungen!"
)
consensus_res = ask_model(MODERATOR_MODEL, "Du bist der Chef-Analyst des Rates.", prep_prompt)
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 folgende Aufgabe gestellt:\n'{user_prompt}'\n\n"
f"Hier ist das vollständige Roh-Protokoll der Experten:\n{discussion_history}\n\n"
f"Hier ist der destillierte Konsens:\n{consensus_res}\n\n"
"""ANWEISUNG:
- Erfülle die Aufgabe des Users präzise basierend auf dem Konsens UND greife auf die konkreten Details aus dem Roh-Protokoll zurück.
- Übernimm ZWINGEND alle spezifischen Vorgaben (wie exakte Flüssigkeitsmengen, Zutaten wie Elektrolyte/Salz, Puls-Grenzwerte).
- Wenn der User ein Format wünscht (z.B. Post, Code, Tabelle), halte dich strikt daran.
- Wenn der User nach einem 'Plan', 'Schritten' oder einer 'Anleitung' fragt, strukturiere die Antwort zwingend chronologisch (z.B. Tag 1, Tag 2) oder in klaren Aufzählungen.
- Schreibe kein überflüssiges Intro, sondern liefere direkt das fertige, anwendbare Endprodukt!"""
)
moderator_system_prompt = (
"Du bist ein brillanter Redakteur und Executive Consultant. "
"Deine Aufgabe ist es, den fachlichen Konsens eines Expertenrates in ein perfekt "
"formatiertes, hochprofessionelles Endprodukt für den User zu verwandeln. "
"Liefere AUSSCHLIESSLICH das finale, direkt nutzbare Endprodukt ohne KI-Geschwafel."
)
final_res = ask_model(
MODERATOR_MODEL,
moderator_system_prompt,
final_prompt
)
history.append({"role": "assistant", "content": final_res})
yield history
# --- THEME ---
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",
)
# --- UI LAYOUT ---
with gr.Blocks() as demo:
gr.HTML("""
<div style="text-align: center; margin-bottom: 2rem; margin-top: 1rem;">
<h1 style="color: #FF5A4D; font-weight: 900; font-size: 2.8rem; margin-bottom: 0.2rem; font-family: 'Inter', sans-serif; letter-spacing: -0.02em;">PromptPlenum42</h1>
<p style="color: #4B5563; font-size: 1.1rem; font-family: 'Inter', sans-serif;">AI-Driven Multi-Agent Consensus System</p>
</div>
""")
with gr.Row():
with gr.Column(scale=4):
input_text = gr.Textbox(
label="Plenumsauftrag",
placeholder="z.B. 'Vergleiche Kubeflow vs ZenML' oder 'Schreibe einen LinkedIn Post über KI-Regulierung'",
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) |