File size: 6,420 Bytes
bd272a0 69b2000 bd272a0 9a480ad 1b70e58 bd272a0 b2c60de 38c4cab b9c3558 b2c60de 1b70e58 139b7ee 56f5718 139b7ee 4474ae5 139b7ee 4474ae5 139b7ee 91b1942 b2c60de 139b7ee b2c60de 1b70e58 b2c60de bd272a0 43e9969 bd272a0 1b70e58 2d4e194 9a480ad 69b2000 00161b7 69b2000 2d4e194 69b2000 2d4e194 00161b7 bd272a0 1b70e58 9a480ad 1b70e58 bd272a0 43e9969 9a480ad bd272a0 1b70e58 9a480ad 1b70e58 43e9969 9a480ad 7ad4232 1d1ca16 b2c60de 9a480ad dcc59b1 b2c60de bd272a0 91b1942 bd272a0 1d1ca16 9a480ad bd272a0 b2c60de 1d1ca16 7ad4232 b2c60de 7ad4232 1d1ca16 bd272a0 c38f251 a2f5736 | 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 | import os
import shutil
import tempfile
import threading
import gradio as gr
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ.get("GEMINI_API_KEY"))
DEFAULT_MODEL = "gemini-3.1-flash-lite-preview"
MODELS = [
"gemini-3.1-flash-lite-preview",
"gemini-3.1-pro-preview",
"gemini-3.1-flash-preview",
]
# Tools (einmalig)
tools = [
types.Tool(url_context=types.UrlContext()),
types.Tool(googleSearch=types.GoogleSearch(
)),
]
SYSTEM_PROMPT = """ Du bist ein intelligenter, effizienter und freundlicher persönlicher Assistent.
Dein Ziel ist es, meine Produktivität zu maximieren und mir bei meinen täglichen Aufgaben zu helfen.
Halte dich an diese Richtlinien: Präzision vor
Füllwörtern: Komm direkt auf den Punkt. Vermeide unnötige Einleitungs- oder Abschlussfloskeln (wie 'Ich hoffe, das hilft Ihnen').
Struktur: Verwende für komplexe Antworten Bullet Points, nummerierte Listen oder Fettdruck, um die Lesbarkeit zu erhöhen.
Rückfragen: Wenn meine Anfrage unklar ist oder wichtige Informationen fehlen, frage mich kurz und gezielt nach dem Kontext, bevor du eine Annahme triffst.
Objektivität: Wenn ich um eine Meinung bitte, präsentiere mir verschiedene Perspektiven oder Vor- und Nachteile, anstatt dich einseitig festzulegen.
Anpassungsfähigkeit: Antworte kurz bei kurzen Fragen und ausführlich bei komplexen Themen. Wenn ich um eine Zusammenfassung bitte, halte sie kompakt. Sprache: Antworte immer in der Sprache, in der ich die Frage stelle (standardmäßig Deutsch, sofern nicht anders gewünscht).
"""
def build_generate_content_config(model_name):
config_kwargs = {"tools": tools,
"system_instruction": SYSTEM_PROMPT}
# Pro-Modelle akzeptieren MINIMAL derzeit nicht.
if "pro" not in model_name:
config_kwargs["thinking_config"] = types.ThinkingConfig(
thinking_level="MINIMAL"
)
return types.GenerateContentConfig(**config_kwargs)
def create_chat_state(model_name):
return {
"model": model_name,
"chat": client.chats.create(
model=model_name,
config=build_generate_content_config(model_name),
),
"lock": threading.Lock(),
}
def respond(message, history, state, model_name):
if state is None:
state = create_chat_state(model_name)
elif state.get("model") != model_name:
state = create_chat_state(model_name)
history = history or []
text = (message or {}).get("text", "")
files = (message or {}).get("files", [])
parts = []
# 1. Dateien verarbeiten (Upload via API & UI-Vorbereitung)
for file_path in files:
# Reinen ASCII-Namen generieren (z.B. 'Lsungen-MP-4 1.pdf')
base_name = os.path.basename(file_path)
safe_name = base_name.encode('ascii', 'ignore').decode('ascii')
# Fallback, falls der Name nach der Filterung komplett leer sein sollte
if not safe_name.strip(". "):
safe_name = "upload_file.pdf"
# Temporären, komplett sicheren Pfad generieren
safe_temp_path = os.path.join(tempfile.gettempdir(), f"safe_{safe_name}")
try:
# Datei an den sicheren Ort kopieren
shutil.copy2(file_path, safe_temp_path)
# Upload mit dem sicheren Pfad durchführen
uploaded_file = client.files.upload(
file=safe_temp_path,
config=types.UploadFileConfig(display_name=safe_name)
)
parts.append(uploaded_file)
finally:
# Temporäre Kopie aufräumen, um Speicherplatz zu sparen
if os.path.exists(safe_temp_path):
os.remove(safe_temp_path)
# Datei in der Gradio UI anzeigen (hier nutzen wir den Originalpfad für die korrekte Anzeige)
history.append({"role": "user", "content": gr.FileData(path=file_path)})
# 2. Text verarbeiten
if text:
parts.append(text)
history.append({"role": "user", "content": text})
if not parts:
yield history, state
return
# 3. UI: Assistant Placeholder hinzufügen
history.append({"role": "assistant", "content": ""})
yield history, state
# 4. Gemini: Senden + Streamen
with state["lock"]:
out = ""
for chunk in state["chat"].send_message_stream(parts):
if getattr(chunk, "text", None):
out += chunk.text
history[-1]["content"] = out
yield history, state
def cleanup_gemini_files():
deleted_count = 0
# Holt alle Dateien, die mit deinem API-Key hochgeladen wurden
for f in client.files.list():
# Löscht die Datei über ihren eindeutigen Google-Ressourcennamen
client.files.delete(name=f.name)
deleted_count += 1
# Zeigt ein kleines Popup in der Gradio UI an
gr.Info(f"{deleted_count} Datei(en) erfolgreich gelöscht.")
def clear_msg():
return {"text": "", "files": []}
def reset_chat_for_model_change(_model_name):
return [], None, {"text": "", "files": []}
with gr.Blocks() as demo:
gr.Markdown("# Gemini AI Chat by Damian")
model_selector = gr.Dropdown(
choices=MODELS,
value=DEFAULT_MODEL,
label="Gemini-Modell",
info="Ein Modellwechsel startet einen neuen Chat.",
)
# Standard-Initialisierung für Gradio >= 6.0
chatbot = gr.Chatbot(height=600)
msg = gr.MultimodalTextbox(
placeholder="Schreib was oder lade Dateien hoch…",
file_count="multiple",
)
state = gr.State(None)
msg.submit(respond, inputs=[msg, chatbot, state, model_selector], outputs=[chatbot, state]) \
.then(clear_msg, outputs=msg)
model_selector.change(
fn=reset_chat_for_model_change,
inputs=model_selector,
outputs=[chatbot, state, msg],
)
with gr.Row():
clear_btn = gr.Button("Clear Chat")
cleanup_btn = gr.Button("🗑️ Server-Dateien bereinigen")
clear_btn.click(
lambda: ([], None, {"text": "", "files": []}),
outputs=[chatbot, state, msg]
)
cleanup_btn.click(fn=cleanup_gemini_files)
if __name__ == "__main__":
print("Das Programm startet jetzt.")
demo.launch(server_name="0.0.0.0", server_port=7860)
|