Fixes for 0.2.2
This commit is contained in:
parent
c7303cd278
commit
76486da3d4
@ -65,7 +65,7 @@
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/Jeffser/Alpaca.git",
|
||||
"tag": "0.2.1"
|
||||
"tag": "0.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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', ],
|
||||
)
|
||||
|
@ -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:
|
||||
@ -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:
|
||||
@ -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
|
||||
@ -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}
|
||||
|
@ -48,7 +48,7 @@ class AlpacaApplication(Adw.Application):
|
||||
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',
|
||||
|
108
src/window.py
108
src/window.py
@ -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()
|
||||
@ -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(
|
||||
@ -92,6 +116,8 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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"])
|
||||
@ -99,8 +125,8 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
@ -110,18 +136,8 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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")
|
||||
@ -147,7 +163,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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({
|
||||
@ -169,8 +185,8 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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
|
||||
@ -180,20 +196,17 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
|
||||
@ -218,11 +231,12 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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):
|
||||
@ -265,9 +279,11 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
@ -284,10 +300,12 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
@ -303,7 +321,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
|
||||
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",
|
||||
@ -338,6 +356,37 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
@ -348,13 +397,14 @@ class AlpacaWindow(Adw.ApplicationWindow):
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<template class="AlpacaWindow" parent="AdwApplicationWindow">
|
||||
<property name="resizable">True</property>
|
||||
<property name="content">
|
||||
<object class="AdwToastOverlay" id="overlay">
|
||||
<object class="AdwToastOverlay" id="main_overlay">
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
@ -118,9 +118,12 @@
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<object class="AdwDialog" id="pull_model_dialog">
|
||||
<property name="can-close">false</property>
|
||||
<property name="width-request">400</property>
|
||||
<child>
|
||||
<object class="AdwToastOverlay" id="pull_overlay">
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child>
|
||||
@ -142,10 +145,15 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
<object class="AdwDialog" id="manage_models_dialog">
|
||||
<property name="can-close">true</property>
|
||||
<property name="width-request">400</property>
|
||||
<property name="height-request">600</property>
|
||||
<child>
|
||||
<object class="AdwToastOverlay" id="manage_models_overlay">
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
@ -184,10 +192,15 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
<object class="AdwDialog" id="connection_dialog">
|
||||
<property name="can-close">false</property>
|
||||
<property name="width-request">450</property>
|
||||
<property name="height-request">450</property>
|
||||
<child>
|
||||
<object class="AdwToastOverlay" id="connection_overlay">
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
@ -225,8 +238,8 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwCarousel" id="connection_carousel">
|
||||
<property name="hexpand">true</property>
|
||||
@ -290,6 +303,9 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
</template>
|
||||
<menu id="primary_menu">
|
||||
<section>
|
||||
|
Loading…
x
Reference in New Issue
Block a user