Updated code to use local ollama only.
This commit is contained in:
87
sql_ai_gui.py
Executable file → Normal file
87
sql_ai_gui.py
Executable file → Normal file
@@ -4,13 +4,11 @@ JR SQL AI GUI (Ollama) - lightweight Arch/Hyprland friendly GUI.
|
||||
|
||||
- Left: Prompt/context
|
||||
- Right: Rendered Markdown answer + raw markdown
|
||||
- Buttons: Send, Copy, Copy SQL only, Model pull, Ollama runtime update (Docker)
|
||||
- Buttons: Send, Copy, Copy SQL only, Model pull
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, List
|
||||
@@ -41,7 +39,6 @@ from PySide6.QtWidgets import (
|
||||
# -----------------------------
|
||||
DEFAULT_OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "http://127.0.0.1:11434")
|
||||
DEFAULT_MODEL = os.environ.get("OLLAMA_MODEL", "jr-sql-expert:latest")
|
||||
DEFAULT_DOCKER_CONTAINER_NAME = os.environ.get("OLLAMA_DOCKER_CONTAINER", "ollama")
|
||||
|
||||
|
||||
# -----------------------------
|
||||
@@ -51,17 +48,6 @@ def is_docker_available() -> bool:
|
||||
return shutil.which("docker") is not None
|
||||
|
||||
|
||||
def run_cmd(cmd: list[str], timeout: int = 600) -> tuple[int, str, str]:
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=timeout,
|
||||
text=True,
|
||||
)
|
||||
return proc.returncode, proc.stdout, proc.stderr
|
||||
|
||||
|
||||
def human_error(e: Exception) -> str:
|
||||
return f"{type(e).__name__}: {e}"
|
||||
|
||||
@@ -191,36 +177,6 @@ class PullModelWorker(QThread):
|
||||
self.error.emit(human_error(e))
|
||||
|
||||
|
||||
class UpdateOllamaDockerWorker(QThread):
|
||||
status = Signal(str)
|
||||
done = Signal()
|
||||
error = Signal(str)
|
||||
|
||||
def __init__(self, container_name: str):
|
||||
super().__init__()
|
||||
self.container_name = container_name
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
if not is_docker_available():
|
||||
raise RuntimeError("docker not found in PATH")
|
||||
|
||||
self.status.emit("docker pull ollama/ollama:latest …")
|
||||
code, out, err = run_cmd(["docker", "pull", "ollama/ollama:latest"], timeout=1800)
|
||||
if code != 0:
|
||||
raise RuntimeError(err.strip() or out.strip() or f"docker pull failed (code {code})")
|
||||
|
||||
self.status.emit(f"Restarting container '{self.container_name}' …")
|
||||
code, out, err = run_cmd(["docker", "restart", self.container_name], timeout=120)
|
||||
if code != 0:
|
||||
raise RuntimeError(err.strip() or out.strip() or f"docker restart failed (code {code})")
|
||||
|
||||
self.status.emit("Done.")
|
||||
self.done.emit()
|
||||
except Exception as e:
|
||||
self.error.emit(human_error(e))
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# Main Window
|
||||
# -----------------------------
|
||||
@@ -231,7 +187,6 @@ class MainWindow(QMainWindow):
|
||||
|
||||
self._gen_worker: Optional[GenerateWorker] = None
|
||||
self._pull_worker: Optional[PullModelWorker] = None
|
||||
self._update_worker: Optional[UpdateOllamaDockerWorker] = None
|
||||
|
||||
self._raw_markdown: str = ""
|
||||
self._render_timer = QTimer(self)
|
||||
@@ -324,11 +279,6 @@ class MainWindow(QMainWindow):
|
||||
self.btn_model_pull.clicked.connect(self.on_pull_model)
|
||||
right_btn_row.addWidget(self.btn_model_pull)
|
||||
|
||||
self.btn_runtime_update = QPushButton("Ollama Runtime updaten")
|
||||
self.btn_runtime_update.clicked.connect(self.on_update_runtime)
|
||||
self.btn_runtime_update.setEnabled(is_docker_available())
|
||||
right_btn_row.addWidget(self.btn_runtime_update)
|
||||
|
||||
right_l.addLayout(right_btn_row)
|
||||
|
||||
splitter.addWidget(left)
|
||||
@@ -343,7 +293,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# -------------- UI helpers --------------
|
||||
def ui_busy(self, busy: bool) -> None:
|
||||
for w in [self.btn_send, self.btn_model_pull, self.btn_refresh_models, self.btn_runtime_update, self.btn_copy_sql]:
|
||||
for w in [self.btn_send, self.btn_model_pull, self.btn_refresh_models, self.btn_copy_sql]:
|
||||
w.setEnabled(not busy)
|
||||
self.prompt.setEnabled(not busy)
|
||||
self.base_url.setEnabled(not busy)
|
||||
@@ -482,39 +432,6 @@ class MainWindow(QMainWindow):
|
||||
def _on_pull_err(self, err: str) -> None:
|
||||
self.ui_busy(False)
|
||||
self.msg_error("Model pull fehlgeschlagen", err)
|
||||
|
||||
# -------------- Update runtime (Docker) --------------
|
||||
def on_update_runtime(self) -> None:
|
||||
if not is_docker_available():
|
||||
self.msg_info("Nicht verfügbar", "docker ist nicht im PATH gefunden.")
|
||||
return
|
||||
|
||||
msg = (
|
||||
"Das führt aus:\n"
|
||||
" docker pull ollama/ollama:latest\n"
|
||||
" docker restart ollama\n\n"
|
||||
"Hinweis: Du brauchst Docker-Rechte (docker group).\n"
|
||||
"Fortfahren?"
|
||||
)
|
||||
if QMessageBox.question(self, "Ollama updaten?", msg) != QMessageBox.Yes:
|
||||
return
|
||||
|
||||
self.ui_busy(True)
|
||||
self.status.showMessage("Ollama Runtime Update …")
|
||||
|
||||
self._update_worker = UpdateOllamaDockerWorker(DEFAULT_DOCKER_CONTAINER_NAME)
|
||||
self._update_worker.status.connect(lambda s: self.status.showMessage(s))
|
||||
self._update_worker.done.connect(self._on_update_done)
|
||||
self._update_worker.error.connect(self._on_update_err)
|
||||
self._update_worker.start()
|
||||
|
||||
def _on_update_done(self) -> None:
|
||||
self.ui_busy(False)
|
||||
self.status.showMessage("Ollama Runtime Update fertig.", 5000)
|
||||
QTimer.singleShot(700, self.refresh_models)
|
||||
|
||||
def _on_update_err(self, err: str) -> None:
|
||||
self.ui_busy(False)
|
||||
self.msg_error("Ollama Runtime Update fehlgeschlagen", err)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user