| 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 = [ |
| 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} |
|
|
| |
| 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 = [] |
|
|
| |
| for file_path in files: |
| |
| base_name = os.path.basename(file_path) |
| safe_name = base_name.encode('ascii', 'ignore').decode('ascii') |
| |
| |
| if not safe_name.strip(". "): |
| safe_name = "upload_file.pdf" |
| |
| |
| safe_temp_path = os.path.join(tempfile.gettempdir(), f"safe_{safe_name}") |
| |
| try: |
| |
| shutil.copy2(file_path, safe_temp_path) |
| |
| |
| uploaded_file = client.files.upload( |
| file=safe_temp_path, |
| config=types.UploadFileConfig(display_name=safe_name) |
| ) |
| parts.append(uploaded_file) |
| finally: |
| |
| if os.path.exists(safe_temp_path): |
| os.remove(safe_temp_path) |
| |
| |
| history.append({"role": "user", "content": gr.FileData(path=file_path)}) |
| |
| |
| if text: |
| parts.append(text) |
| history.append({"role": "user", "content": text}) |
|
|
| if not parts: |
| yield history, state |
| return |
|
|
| |
| history.append({"role": "assistant", "content": ""}) |
| yield history, state |
|
|
| |
| 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 |
| |
| for f in client.files.list(): |
| |
| client.files.delete(name=f.name) |
| deleted_count += 1 |
| |
| |
| 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.", |
| ) |
| |
| |
| 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) |
|
|