Skip to content

Commit 75d6b2d

Browse files
committed
OGC update: Add error logs. Stop button prototype
1 parent 71cdbbc commit 75d6b2d

File tree

1 file changed

+99
-35
lines changed

1 file changed

+99
-35
lines changed

App/Linux/OllamaGUIChat.py

Lines changed: 99 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
import customtkinter as ctk
55
import os
66

7-
# TODO: Add `progressbar` to all jsons.
8-
# Fill README.md
9-
10-
117
APP_PATH: str = os.path.dirname(os.path.realpath(__file__))
128
THEME_PATH: str = os.path.join(APP_PATH, "theme", "custom-theme.json")
139

10+
error_log = []
11+
model_list = []
12+
1413
class GPLLicense(ctk.CTkToplevel):
1514
def __init__(self):
1615
super().__init__()
@@ -38,9 +37,19 @@ def __init__(self):
3837
""",)
3938
self.label.grid(row=0, column=0, sticky="nsew", padx=10)
4039

40+
class ErrorWindow(ctk.CTkToplevel):
41+
def __init__(self):
42+
super().__init__()
4143

42-
error_log = []
43-
model_list = []
44+
self.title("Error logs")
45+
self.geometry("600x400")
46+
47+
self.error_output = ctk.CTkTextbox(self, height=390, width=590, cursor="arrow")
48+
self.error_output.grid(row=0, column=0, padx=5, pady=5, sticky="nsew",)
49+
50+
error_lines = "\n\n".join(error_log)
51+
self.error_output.insert("1.0", error_lines)
52+
self.error_output.configure(wrap="word", state="disabled", font=("", 14))
4453

4554
class OllamaGUIChat(ctk.CTk):
4655
def __init__(self):
@@ -59,6 +68,8 @@ def __init__(self):
5968
self.messages = []
6069
self.full_reply = ""
6170
self.gpl_opened = None
71+
self.error_opened = None
72+
self.response = None
6273

6374
self.title("Ollama GUI Chat")
6475
self.geometry("800x800")
@@ -70,7 +81,6 @@ def __init__(self):
7081

7182
def setup_ui(self):
7283

73-
7484
# top panel buttons
7585
top_frame = ctk.CTkFrame(self)
7686
top_frame.grid(row=0, padx=5,pady=2, sticky="nswe")
@@ -109,7 +119,7 @@ def setup_ui(self):
109119
self.chat_font_var.set(value="14")
110120
self.chat_output = ctk.CTkTextbox(self, height=600, cursor="arrow")
111121
self.chat_output.grid(row=1, columnspan=2, padx=5, pady=(5, 2), sticky="nsew",)
112-
self.chat_output.insert("1.0", error_log)
122+
#self.chat_output.insert("1.0", error_log)
113123
self.chat_output.configure(wrap="word", state="disabled", font=("", int(self.chat_font_var.get())))
114124

115125
mid_frame = ctk.CTkFrame(self)
@@ -149,6 +159,8 @@ def setup_ui(self):
149159
self.progress_bar = ctk.CTkProgressBar(mid_frame2, mode="determinate",)
150160
self.progress_bar.configure(width=150,)
151161

162+
self.stop_button = ctk.CTkButton(mid_frame2, text="🛑", command=self.stop_response)
163+
152164
# lower panel
153165
self.input_field = ctk.CTkTextbox(self, height=100)
154166
self.input_field.grid(row=3, column=0, padx=5, pady=(5,5), sticky="nswe",)
@@ -208,7 +220,8 @@ def insert_text(self, content):
208220
self.chat_output.see("end")
209221

210222
except Exception as e:
211-
print(f"Error: {e}")
223+
error_log.append(f"Error: {e}")
224+
self.open_error_logs()
212225

213226
def on_model_change(self, *args):
214227
self.messages = []
@@ -242,6 +255,14 @@ def open_gpl(self):
242255
else:
243256
self.gpl_opened.focus()
244257

258+
def open_error_logs(self):
259+
if self.error_opened is None or not self.error_opened.winfo_exists():
260+
self.error_opened = ErrorWindow()
261+
262+
else:
263+
self.error_opened.destroy()
264+
self.error_opened = ErrorWindow()
265+
245266
def clear_chat(self):
246267
self.chat_output.configure(state="normal")
247268
self.messages = []
@@ -251,25 +272,57 @@ def clear_chat(self):
251272
def save_chat(self):
252273
file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
253274

254-
if file_path:
255-
with open(file_path, "w", encoding="utf-8") as f:
256-
for message in self.messages:
257-
f.write(f"{message['role']} : {message['content']}\n")
275+
try:
276+
if file_path:
277+
with open(file_path, "w", encoding="utf-8") as f:
278+
for message in self.messages:
279+
f.write(f"{message['role']} : {message['content']}\n")
280+
281+
except Exception as e:
282+
error_log.append(f"def save_chat: {e}")
283+
self.open_error_logs()
258284

259285
def load_chat(self):
260286
file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
261-
with open(file_path, "r", encoding="utf-8") as f:
262-
for line in f.readlines():
263-
self.messages.append({"role": "assistant", "content": line})
287+
288+
if not file_path: # if you dont want to see an error each time you cancel loading - keep this intact
289+
return
290+
291+
try:
292+
with open(file_path, "r", encoding="utf-8") as f:
293+
for line in f.readlines():
294+
self.messages.append({"role": "assistant", "content": line})
295+
296+
except Exception as e:
297+
error_log.append(f"def load_chat: {e}")
298+
self.open_error_logs()
299+
300+
def stop_response(self):
301+
last_key = len(self.messages) - 1
302+
303+
if hasattr(self, "response") and self.response:
304+
self.response.close()
305+
del self.response
306+
self.messages.pop(last_key)
307+
self.insert_text("\n\n[AI] : Chat stopped.\n\n")
308+
309+
self.hide_progress()
310+
self.send_button.configure(state="normal")
264311

265312
def show_progress(self):
266313
self.progress_bar.grid(row=2, column=3, sticky="we")
267314
self.progress_bar.start()
268315

316+
self.stop_button.grid(row=2, column=4, sticky="we", padx=5)
317+
self.stop_button.configure(height=10, width=10, corner_radius=5, border_width=2, state="normal")
318+
269319
def hide_progress(self):
270320
self.progress_bar.stop()
271321
self.progress_bar.grid_forget()
272322

323+
self.stop_button.grid_forget()
324+
self.stop_button.configure(state="disabled")
325+
273326
# checks for installed LLMs.
274327
def check_existing_models(self) -> None:
275328
try:
@@ -284,8 +337,8 @@ def check_existing_models(self) -> None:
284337
self.refresh_model_list()
285338

286339
except requests.exceptions.RequestException as e:
287-
print(f"Error while checking models: {e}")
288-
self.insert_text(f"Error while checking models: {e}\n\n")
340+
error_log.append(f"def check_existing_models: {e}")
341+
self.open_error_logs()
289342

290343
def send_message(self):
291344
question = self.input_field.get("1.0", "end").strip()
@@ -311,35 +364,46 @@ def send_message(self):
311364

312365
try:
313366
response = requests.post(url, json=payload, stream=True)
367+
self.response = response
314368

315369
if response.status_code == 200:
316370
self.insert_text("[AI] :\n")
371+
self.show_progress()
317372
#self.update()
318373

319374
# full_reply "", needed for AI to remember the context of messages.
320375
# Without this, every new message is considered as new chat or whatever.
321376
full_reply= ""
322-
for line in response.iter_lines(decode_unicode=True):
323-
if line.strip():
324-
try:
325-
data = json.loads(line)
326-
content = data.get("message", {}).get("content", "")
327-
full_reply += content
328-
self.show_progress()
329-
self.insert_text(content)
330-
self.update()
331-
332-
except json.JSONDecodeError:
333-
continue
334-
335-
self.messages.append({"role": "assistant", "content": full_reply})
336-
self.insert_text("\n\n")
377+
try:
378+
for line in response.iter_lines(decode_unicode=True):
379+
if line.strip():
380+
try:
381+
data = json.loads(line)
382+
content = data.get("message", {}).get("content", "")
383+
full_reply += content
384+
self.insert_text(content)
385+
self.update()
386+
387+
except json.JSONDecodeError:
388+
error_log.append(f"def send_message: {line}")
389+
self.open_error_logs()
390+
continue
391+
392+
self.messages.append({"role": "assistant", "content": full_reply})
393+
self.insert_text("\n\n")
394+
395+
# YES, IT WILL SCREAM AN ERROR EACH TIME YOU CANCEL THE CHAT.
396+
except Exception as e:
397+
error_log.append(f"def send_message: {e}")
398+
#self.open_error_logs() # Yes, thats why this is commented out. How would you feel if someone rips your tongue off mid-sentence?
337399

338400
else:
339-
self.insert_text(f"\nError: {response.status_code}\n{response.text}\n\n")
401+
error_log.append(f"def send_message: {response.status_code}")
402+
self.open_error_logs()
340403

341404
except requests.exceptions.RequestException as e:
342-
self.insert_text(f"\nError sending request: {e}\n\n")
405+
error_log.append(f"def send_message: {e}")
406+
self.open_error_logs()
343407

344408
self.send_button.configure(state="normal")
345409
self.hide_progress()

0 commit comments

Comments
 (0)