🤖 Ollama GUI Client – Desktop-App für lokale LLMs

Tkinter-GUI mit Modell-Dropdown, Prompt-Threading und Verlauf

PythonTkinterOllamaGUILLM

📊 Was die App kann

Eine schlanke Python-Desktop-GUI für Ollama – Modell-Auswahl per Dropdown, Prompt-Eingabe mit Enter-Taste, Antworten in Threads (kein UI-Freeze), Server-Status-Anzeige und Kopierfunktion.

🔽
Modell-Auswahl
Dropdown listet alle installierten Ollama-Modelle – Wechsel per Klick ohne Neustart.
🧵
Multithreading
API-Calls laufen in separatem Thread – die GUI bleibt responsiv während der Antwortgenerierung.
📋
Verlauf & Copy
Prompt-Historie in der Sidebar, Antwort per Klick in die Zwischenablage kopieren.
⚙️
Konfigurierbar
Server-URL übers Menü änderbar – unterstützt Ollama auf beliebigen Hosts im Netzwerk.

💻 Echter Code aus dem Projekt

Hauptklasse: OllamaApp mit Modell-Dropdown und Menü

import tkinter as tk
from gui.prompt_panel import PromptPanel
from gui.response_panel import ResponsePanel
from gui.history_panel import HistoryPanel
from gui.status_bar import StatusBar

class OllamaApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Ollama GUI")
        self.root.geometry("800x600")
        self.api = OllamaAPI()

        # Modell-Dropdown oben
        self.model_var = tk.StringVar(value=self.api.get_active_model())
        self.model_dropdown = tk.OptionMenu(
            self.root, self.model_var, 
            *self.api.get_models(), command=self.change_model)

        # Status-Leiste unten
        self.status_bar = StatusBar(self.root, self.api)
        # Antwort-Panel (Hauptbereich)
        self.response_panel = ResponsePanel(self.root)
        # Prompt-Eingabe
        self.prompt_panel = PromptPanel(self.root, self.api, self.response_panel)
        # Verlauf (Sidebar)
        self.history_panel = HistoryPanel(self.root, self.prompt_panel, self.response_panel)

PromptPanel – Threading damit UI nicht friert

class PromptPanel(tk.Frame):
    def __init__(self, master, api, response_panel):
        self.entry = tk.Entry(self, textvariable=self.prompt_var, width=80)
        self.entry.bind('<Return>', self.send_prompt)  # Enter = Senden

    def send_prompt(self, event=None):
        prompt = self.prompt_var.get().strip()
        if prompt:
            self.response_panel.show_loading()
            # API-Call im Thread – UI bleibt responsiv
            threading.Thread(target=self._send_prompt_thread, 
                           args=(prompt,), daemon=True).start()
            self.prompt_var.set("")

    def _send_prompt_thread(self, prompt):
        response = self.api.send_prompt(prompt)
        # Ergebnis per after() zurück in den Hauptthread
        self.response_panel.after(0, 
            lambda: self.response_panel.set_response(response))

ResponsePanel – Progressbar während Generierung

class ResponsePanel(tk.Frame):
    def __init__(self, master):
        self.text = tk.Text(self, wrap=tk.WORD, height=20)
        self.copy_button = tk.Button(self, text="Antwort kopieren",
            command=self.copy_response)

    def show_loading(self):
        self.text.delete(1.0, tk.END)
        self.text.insert(tk.END, "Antwort wird generiert ...")
        self.progress = ttk.Progressbar(self, mode="indeterminate")
        self.progress.start(10)

    def hide_loading(self):
        self.progress.stop()
        self.progress.pack_forget()

StatusBar – Server-Verbindung live prüfen

class StatusBar(tk.Frame):
    def update_status(self):
        if self.api.is_server_available():
            model = self.api.get_active_model()
            self.status_var.set(
                f"Server verbunden | Modell: {model}")
        else:
            self.status_var.set("Server nicht erreichbar!")

🎯 Business Value

🔒

100% lokal – keine Cloud

Alle Prompts und Antworten bleiben auf dem eigenen Rechner. Keine Datenübertragung an Dritte.

👥

Team-tauglich

Mehrere Clients können sich mit einem zentralen Ollama-Server verbinden – eine GPU, alle nutzen sie.