Skip to content

Commit

Permalink
Fixes for 0.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeffser committed May 14, 2024
1 parent c7303cd commit 76486da
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 153 deletions.
2 changes: 1 addition & 1 deletion com.jeffser.Alpaca.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
{
"type" : "git",
"url" : "https://github.com/Jeffser/Alpaca.git",
"tag": "0.2.1"
"tag": "0.2.2"
}
]
}
Expand Down
14 changes: 14 additions & 0 deletions data/com.jeffser.Alpaca.metainfo.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@
<url type="homepage">https://github.com/Jeffser/Alpaca</url>
<url type="donation">https://github.com/sponsors/Jeffser</url>
<releases>
<release version="0.2.2" date="2024-05-14">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/0.2.1</url>
<description>
<p>0.2.2 Bug fixes</p>
<ul>
<li>Toast messages appearing behind dialogs</li>
<li>Local model list not updating when changing servers</li>
<li>Closing the setup dialog closes the whole app</li>
</ul>
<p>
Please report any errors to the issues page, thank you.
</p>
</description>
</release>
<release version="0.2.1" date="2024-05-14">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/0.2.1</url>
<description>
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project('Alpaca',
version: '0.2.1',
version: '0.2.2',
meson_version: '>= 0.62.0',
default_options: [ 'warning_level=2', 'werror=false', ],
)
Expand Down
14 changes: 7 additions & 7 deletions src/connection_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ def simple_get(connection_url:str) -> dict:
if response.status_code == 200:
return {"status": "ok", "text": response.text, "status_code": response.status_code}
else:
return {"status": "error", "text": f"Failed to connect to {connection_url}. Status code: {response.status_code}", "status_code": response.status_code}
return {"status": "error", "status_code": response.status_code}
except Exception as e:
return {"status": "error", "text": f"An error occurred while trying to connect to {connection_url}", "status_code": 0}
return {"status": "error", "status_code": 0}

def simple_delete(connection_url:str, data) -> dict:
try:
Expand All @@ -19,7 +19,7 @@ def simple_delete(connection_url:str, data) -> dict:
else:
return {"status": "error", "text": "Failed to delete", "status_code": response.status_code}
except Exception as e:
return {"status": "error", "text": f"An error occurred while trying to connect to {connection_url}", "status_code": 0}
return {"status": "error", "status_code": 0}

def stream_post(connection_url:str, data, callback:callable) -> dict:
try:
Expand All @@ -31,11 +31,11 @@ def stream_post(connection_url:str, data, callback:callable) -> dict:
for line in response.iter_lines():
if line:
callback(json.loads(line.decode("utf-8")))
return {"status": "ok", "text": "All good", "status_code": response.status_code}
return {"status": "ok", "status_code": response.status_code}
else:
return {"status": "error", "text": "Error posting data", "status_code": response.status_code}
return {"status": "error", "status_code": response.status_code}
except Exception as e:
return {"status": "error", "text": f"An error occurred while trying to connect to {connection_url}", "status_code": 0}
return {"status": "error", "status_code": 0}


from time import sleep
Expand All @@ -58,4 +58,4 @@ def stream_post_fake(connection_url:str, data, callback:callable) -> dict:
sleep(.1)
data = {"status": msg}
callback(data)
return {"status": "ok", "text": "All good", "status_code": 200}
return {"status": "ok", "status_code": 200}
2 changes: 1 addition & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def on_about_action(self, widget, _):
application_name='Alpaca',
application_icon='com.jeffser.Alpaca',
developer_name='Jeffry Samuel Eduarte Rojas',
version='0.2.1',
version='0.2.2',
developers=['Jeffser https://jeffser.com'],
designers=['Jeffser https://jeffser.com'],
copyright='© 2024 Jeffser',
Expand Down
108 changes: 79 additions & 29 deletions src/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ class AlpacaWindow(Adw.ApplicationWindow):
connection_previous_button = Gtk.Template.Child()
connection_next_button = Gtk.Template.Child()
connection_url_entry = Gtk.Template.Child()
overlay = Gtk.Template.Child()
main_overlay = Gtk.Template.Child()
pull_overlay = Gtk.Template.Child()
manage_models_overlay = Gtk.Template.Child()
connection_overlay = Gtk.Template.Child()
chat_container = Gtk.Template.Child()
chat_window = Gtk.Template.Child()
message_entry = Gtk.Template.Child()
Expand All @@ -59,12 +62,33 @@ class AlpacaWindow(Adw.ApplicationWindow):
pull_model_status_page = Gtk.Template.Child()
pull_model_progress_bar = Gtk.Template.Child()

def show_toast(self, msg:str):
toast_messages = {
"error": [
"An error occurred",
"Failed to connect to server",
"Could not list local models",
"Could not delete model",
"Could not pull model"
],
"info": [
"Please select a model before chatting",
"Conversation cannot be cleared while receiving a message"
],
"good": [
"Model deleted successfully",
"Model pulled successfully"
]
}

def show_toast(self, message_type:str, message_id:int, overlay):
if message_type not in self.toast_messages or message_id > len(self.toast_messages[message_type] or message_id < 0):
message_type = "error"
message_id = 0
toast = Adw.Toast(
title=msg,
title=self.toast_messages[message_type][message_id],
timeout=2
)
self.overlay.add_toast(toast)
overlay.add_toast(toast)

def show_message(self, msg:str, bot:bool, footer:str=None):
message_text = Gtk.TextView(
Expand Down Expand Up @@ -92,15 +116,17 @@ def show_message(self, msg:str, bot:bool, footer:str=None):
def update_list_local_models(self):
self.local_models = []
response = simple_get(self.ollama_url + "/api/tags")
for i in range(self.model_string_list.get_n_items() -1, -1, -1):
self.model_string_list.remove(i)
if response['status'] == 'ok':
for model in json.loads(response['text'])['models']:
self.model_string_list.append(model["name"])
self.local_models.append(model["name"])
self.model_drop_down.set_selected(0)
return
else:
self.show_toast(response['text'])
self.show_connection_dialog(True)
self.show_toast("error", 2, self.connection_overlay)

def verify_connection(self):
response = simple_get(self.ollama_url)
Expand All @@ -110,18 +136,8 @@ def verify_connection(self):
self.message_entry.grab_focus_without_selecting()
self.update_list_local_models()
return True
else:
response = {"status": "error", "text": f"Unexpected response from {self.ollama_url} : {response['text']}"}
self.show_toast(response['text'])
return False

def dialog_response(self, dialog, task):
self.ollama_url = dialog.get_extra_child().get_text()
if dialog.choose_finish(task) == "login":
self.verify_connection()
else:
self.destroy()

def update_bot_message(self, data):
if data['done']:
formated_datetime = datetime.now().strftime("%Y/%m/%d %H:%M")
Expand All @@ -147,7 +163,7 @@ def update_bot_message(self, data):
def send_message(self):
current_model = self.model_drop_down.get_selected_item()
if current_model is None:
GLib.idle_add(self.show_toast, "Please pull a model")
GLib.idle_add(self.show_toast, "info", 0, self.main_overlay)
return
formated_datetime = datetime.now().strftime("%Y/%m/%d %H:%M")
self.chats["chats"][self.current_chat_id]["messages"].append({
Expand All @@ -169,8 +185,8 @@ def send_message(self):
GLib.idle_add(self.send_button.set_sensitive, True)
GLib.idle_add(self.message_entry.set_sensitive, True)
if response['status'] == 'error':
self.show_toast(f"{response['text']}")
self.show_connection_dialog(True)
GLib.idle_add(self.show_toast, 'error', 1, self.connection_overlay)
GLib.idle_add(self.show_connection_dialog, True)

def send_button_activate(self, button):
if not self.message_entry.get_text(): return
Expand All @@ -180,20 +196,17 @@ def send_button_activate(self, button):
def delete_model(self, dialog, task, model_name, button):
if dialog.choose_finish(task) == "delete":
response = simple_delete(self.ollama_url + "/api/delete", data={"name": model_name})
print(response)
if response['status'] == 'ok':
button.set_icon_name("folder-download-symbolic")
button.set_css_classes(["accent", "pull"])
self.show_toast(f"Model '{model_name}' deleted successfully")
self.show_toast("good", 0, self.manage_models_overlay)
for i in range(self.model_string_list.get_n_items()):
if self.model_string_list.get_string(i) == model_name:
self.model_string_list.remove(i)
self.model_drop_down.set_selected(0)
break
elif response['status_code'] == '404':
self.show_toast(f"Delete request failed: Model was not found")
else:
self.show_toast(response['text'])
self.show_toast("error", 3, self.connection_overlay)
self.manage_models_dialog.close()
self.show_connection_dialog(True)

Expand All @@ -218,11 +231,12 @@ def pull_model(self, dialog, task, model_name, button):
GLib.idle_add(button.set_icon_name, "user-trash-symbolic")
GLib.idle_add(button.set_css_classes, ["error", "delete"])
GLib.idle_add(self.model_string_list.append, model_name)
GLib.idle_add(self.show_toast, f"Model '{model_name}' pulled successfully")
GLib.idle_add(self.show_toast, "good", 1, self.manage_models_overlay)
else:
GLib.idle_add(self.show_toast, response['text'])
GLib.idle_add(self.show_toast, "error", 4, self.connection_overlay)
GLib.idle_add(self.manage_models_dialog.close)
GLib.idle_add(self.show_connection_dialog, True)
print("pull fail")


def pull_model_start(self, dialog, task, model_name, button):
Expand Down Expand Up @@ -265,9 +279,11 @@ def update_list_available_models(self):
self.model_list_box.append(model)

def manage_models_button_activate(self, button):

self.manage_models_dialog.present(self)
self.update_list_available_models()


def connection_carousel_page_changed(self, carousel, index):
if index == 0: self.connection_previous_button.set_sensitive(False)
else: self.connection_previous_button.set_sensitive(True)
Expand All @@ -284,10 +300,12 @@ def connection_next_button_activate(self, button):
if self.verify_connection():
self.connection_dialog.force_close()
else:
show_connection_dialog(True)
self.show_connection_dialog(True)
self.show_toast("error", 1, self.connection_overlay)

def show_connection_dialog(self, error:bool=False):
self.connection_carousel.scroll_to(self.connection_carousel.get_nth_page(self.connection_carousel.get_n_pages()-1),False)
if self.ollama_url is not None: self.connection_url_entry.set_text(self.ollama_url)
if error: self.connection_url_entry.set_css_classes(["error"])
else: self.connection_url_entry.set_css_classes([])
self.connection_dialog.present(self)
Expand All @@ -303,7 +321,7 @@ def clear_conversation_dialog_response(self, dialog, task):

def clear_conversation_dialog(self):
if self.bot_message is not None:
self.show_toast("Conversation cannot be cleared while receiving a message")
self.show_toast("info", 1, self.main_overlay)
return
dialog = Adw.AlertDialog(
heading=f"Clear Conversation",
Expand Down Expand Up @@ -338,6 +356,37 @@ def load_history(self):
self.show_message(message['content'], True, f"\n\n<small>{message['model']}\t|\t{message['date']}</small>")
self.bot_message = None

def closing_connection_dialog_response(self, dialog, task):
result = dialog.choose_finish(task)
if result == "cancel": return
if result == "save":
self.ollama_url = self.connection_url_entry.get_text()
self.connection_dialog.force_close()
if self.ollama_url is None or self.verify_connection() == False:
self.show_connection_dialog(True)
self.show_toast("error", 1, self.connection_overlay)


def closing_connection_dialog(self, dialog):
if self.get_visible() == False:
self.destroy()
else:
dialog = Adw.AlertDialog(
heading=f"Save Changes?",
body=f"Do you want to save the URL change?",
close_response="cancel"
)
dialog.add_response("cancel", "Cancel")
dialog.add_response("discard", "Discard")
dialog.add_response("save", "Save")
dialog.set_response_appearance("discard", Adw.ResponseAppearance.DESTRUCTIVE)
dialog.set_response_appearance("save", Adw.ResponseAppearance.SUGGESTED)
dialog.choose(
parent = self,
cancellable = None,
callback = self.closing_connection_dialog_response
)

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.manage_models_button.connect("clicked", self.manage_models_button_activate)
Expand All @@ -348,13 +397,14 @@ def __init__(self, **kwargs):
self.connection_previous_button.connect("clicked", self.connection_previous_button_activate)
self.connection_next_button.connect("clicked", self.connection_next_button_activate)
self.connection_url_entry.connect("changed", lambda entry: entry.set_css_classes([]))
self.connection_dialog.connect("close-attempt", lambda dialog: self.destroy())
self.connection_dialog.connect("close-attempt", self.closing_connection_dialog)
self.load_history()
if os.path.exists(os.path.join(self.config_dir, "server.conf")):
with open(os.path.join(self.config_dir, "server.conf"), "r") as f:
self.ollama_url = f.read()
if self.verify_connection() is False: self.show_connection_dialog()
if self.verify_connection() is False: self.show_connection_dialog(True)
else: self.connection_dialog.present(self)
self.show_toast("funny", True, self.manage_models_overlay)



Expand Down
Loading

0 comments on commit 76486da

Please sign in to comment.