24 Commits
2.6.0 ... 2.6.5

Author SHA1 Message Date
jeffser
3253e67680 Update to snap 2024-10-13 17:08:42 -06:00
jeffser
e189769f3f Updated spanish 2024-10-13 17:07:33 -06:00
jeffser
f6637493db Update languages 2024-10-13 17:03:00 -06:00
jeffser
063da38597 Preparing for 2.6.5 2024-10-13 16:24:20 -06:00
jeffser
7587b03828 Added Exception as e so it can catch everything 2024-10-13 15:21:39 -06:00
jeffser
8fffb64f79 the 2024-10-13 15:07:20 -06:00
aritra saha
735eae0d0e Update bn.po (#346)
* Update bn.po

* Update bn.po
2024-10-13 14:39:45 -06:00
jeffser
8c98be6ef6 Integrated instance indicator on preferences 2024-10-13 10:27:18 -06:00
jeffser
115e22e52c Added warning if model is too large for system 2024-10-13 10:00:43 -06:00
jeffser
792a81ad03 Restore Ollama logging 2024-10-13 09:57:52 -06:00
jeffser
2ea0ff6870 Removed webiste button in creation page 2024-10-12 18:47:20 -06:00
jeffser
6242087152 Replace model selector with button if there aren't any models download 2024-10-12 17:25:34 -06:00
aritra saha
1da6e31de1 Update hi.po (#345) 2024-10-12 17:07:09 -06:00
aritra saha
cb4979ab7c Update bn.po (#344)
* Update bn.po

* Update bn.po
2024-10-12 17:06:55 -06:00
jeffser
da653c754d Added create button to details and fixed some css 2024-10-12 17:01:54 -06:00
jeffser
c4907b81fd Fixed datetime bug 2024-10-12 13:29:54 -06:00
jeffser
4c104560d5 Chaged styling 2024-10-11 22:51:51 -06:00
jeffser
2253e378ac Updated spanish 2024-10-11 22:45:20 -06:00
jeffser
ba66ac40a3 Updated translations 2024-10-11 22:44:53 -06:00
jeffser
40d0d92498 Forgot one translation 2024-10-11 22:44:22 -06:00
jeffser
4ed6cf8e18 Updated spanish 2024-10-11 22:42:49 -06:00
jeffser
3fc1c74f51 Updated translations 2024-10-11 22:41:17 -06:00
jeffser
150e8779c7 New 'model details' page 2024-10-11 22:40:31 -06:00
Jeffry Samuel
5462248565 Update README.md 2024-10-11 19:08:35 -06:00
24 changed files with 8185 additions and 7001 deletions

View File

@@ -33,7 +33,7 @@ Alpaca is an [Ollama](https://github.com/ollama/ollama) client where you can man
Normal conversation | Image recognition | Code highlighting | YouTube transcription | Model management
:------------------:|:-----------------:|:-----------------:|:---------------------:|:----------------:
![screenie1](https://jeffser.com/images/alpaca/screenie1.png) | ![screenie2](https://jeffser.com/images/alpaca/screenie2.png) | ![screenie3](https://jeffser.com/images/alpaca/screenie3.png) | ![screenie4](https://jeffser.com/images/alpaca/screenie4.png) | ![screenie5](https://jeffser.com/images/alpaca/screenie5.png)
![screenie1](https://jeffser.com/images/alpaca/screenie1.png) | ![screenie2](https://jeffser.com/images/alpaca/screenie2.png) | ![screenie3](https://jeffser.com/images/alpaca/screenie3.png) | ![screenie4](https://jeffser.com/images/alpaca/screenie5.png) | ![screenie5](https://jeffser.com/images/alpaca/screenie6.png)
## Installation

View File

@@ -82,6 +82,18 @@
<url type="contribute">https://github.com/Jeffser/Alpaca/discussions/154</url>
<url type="vcs-browser">https://github.com/Jeffser/Alpaca</url>
<releases>
<release version="2.6.5" date="2024-10-13">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/2.6.5</url>
<description>
<p>New</p>
<ul>
<li>Details page for models</li>
<li>Model selector gets replaced with 'manage models' button when there are no models downloaded</li>
<li>Added warning when model is too big for the device</li>
<li>Added AMD GPU indicator in preferences</li>
</ul>
</description>
</release>
<release version="2.6.0" date="2024-10-11">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/2.6.0</url>
<description>

View File

@@ -1,5 +1,5 @@
project('Alpaca', 'c',
version: '2.6.0',
version: '2.6.5',
meson_version: '>= 0.62.0',
default_options: [ 'warning_level=2', 'werror=false', ],
)

File diff suppressed because it is too large Load Diff

1093
po/bn.po

File diff suppressed because it is too large Load Diff

1062
po/de.po

File diff suppressed because it is too large Load Diff

1070
po/es.po

File diff suppressed because it is too large Load Diff

1062
po/fr.po

File diff suppressed because it is too large Load Diff

1062
po/he.po

File diff suppressed because it is too large Load Diff

1094
po/hi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1059
po/ru.po

File diff suppressed because it is too large Load Diff

1062
po/te.po

File diff suppressed because it is too large Load Diff

1062
po/tr.po

File diff suppressed because it is too large Load Diff

1062
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
name: alpaca
name: jeffser-alpaca
base: core24
adopt-info: alpaca
@@ -63,14 +63,15 @@ parts:
ollama:
plugin: dump
source:
- on amd64: https://github.com/ollama/ollama/releases/download/v0.3.10/ollama-linux-amd64.tgz
- on arm64: https://github.com/ollama/ollama/releases/download/v0.3.10/ollama-linux-arm64.tgz
- on amd64: https://github.com/ollama/ollama/releases/download/v0.3.12/ollama-linux-amd64.tgz
- on arm64: https://github.com/ollama/ollama/releases/download/v0.3.12/ollama-linux-arm64.tgz
# Alpaca app
alpaca:
plugin: meson
source-type: git
source: https://github.com/Jeffser/Alpaca.git
source-tag: 2.6.5
source-depth: 1
meson-parameters:
- --prefix=/snap/alpaca/current/usr

View File

@@ -33,6 +33,7 @@
<file alias="icons/scalable/status/chat-bubble-text-symbolic.svg">icons/chat-bubble-text-symbolic.svg</file>
<file alias="icons/scalable/status/execute-from-symbolic.svg">icons/execute-from-symbolic.svg</file>
<file alias="icons/scalable/status/cross-large-symbolic.svg">icons/cross-large-symbolic.svg</file>
<file alias="icons/scalable/status/info-outline-symbolic.svg">icons/info-outline-symbolic.svg</file>
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
</gresource>

View File

@@ -16,10 +16,18 @@ def log_output(pipe):
with pipe:
try:
for line in iter(pipe.readline, ''):
#print(line, end='')
print(line, end='')
f.write(line)
f.flush()
except:
if 'msg="model request too large for system"' in line:
window.show_toast(_("Model request too large for system"), window.main_overlay)
elif 'msg="amdgpu detected, but no compatible rocm library found.' in line:
window.ollama_information_label.set_label(_("AMD GPU detected but the extension is missing, Ollama will use CPU"))
window.ollama_information_label.set_css_classes(['dim-label', 'error'])
elif 'msg="amdgpu is supported"' in line:
window.ollama_information_label.set_label(_("Using AMD GPU type '{}'").format(line.split('=')[-1]))
window.ollama_information_label.set_css_classes(['dim-label', 'success'])
except Exception as e:
pass
class instance():
@@ -116,6 +124,8 @@ class instance():
self.instance = instance
if not self.idle_timer:
self.start_timer()
window.ollama_information_label.set_label(_("Integrated Ollama instance is running"))
window.ollama_information_label.set_css_classes(['dim-label', 'success'])
else:
self.remote = True
window.remote_connection_switch.set_sensitive(True)
@@ -130,6 +140,8 @@ class instance():
self.instance.terminate()
self.instance.wait()
self.instance = None
window.ollama_information_label.set_label(_("Integrated Ollama instance is not running"))
window.ollama_information_label.set_css_classes(['dim-label'])
logger.info("Stopped Alpaca's Ollama instance")
def reset(self):

View File

@@ -56,7 +56,7 @@ class model_selector_popup(Gtk.Popover):
class model_selector_row(Gtk.ListBoxRow):
__gtype_name__ = 'AlpacaModelSelectorRow'
def __init__(self, model_name:str, image_recognition:bool):
def __init__(self, model_name:str, data:dict):
super().__init__(
child = Gtk.Label(
label=window.convert_model_name(model_name, 0),
@@ -68,7 +68,8 @@ class model_selector_row(Gtk.ListBoxRow):
name=model_name,
tooltip_text=window.convert_model_name(model_name, 0)
)
self.image_recognition = image_recognition
self.data = data
self.image_recognition = 'projector_info' in self.data
class model_selector_button(Gtk.MenuButton):
__gtype_name__ = 'AlpacaModelSelectorButton'
@@ -81,11 +82,10 @@ class model_selector_button(Gtk.MenuButton):
orientation=0,
spacing=5
)
self.label = Gtk.Label(label=_('Select a Model'))
self.label = Gtk.Label()
container.append(self.label)
container.append(Gtk.Image.new_from_icon_name("down-symbolic"))
super().__init__(
tooltip_text=_('Select a Model'),
child=container,
popover=self.popover,
halign=3
@@ -104,27 +104,28 @@ class model_selector_button(Gtk.MenuButton):
self.label.set_label(window.convert_model_name(model_name, 0))
self.set_tooltip_text(window.convert_model_name(model_name, 0))
elif len(list(listbox)) == 0:
self.label.set_label(_("Select a Model"))
self.set_tooltip_text(_("Select a Model"))
window.title_stack.set_visible_child_name('no_models')
window.model_manager.verify_if_image_can_be_used()
def add_model(self, model_name:str):
vision = False
data = None
response = window.ollama_instance.request("POST", "api/show", json.dumps({"name": model_name}))
if response.status_code != 200:
logger.error(f"Status code was {response.status_code}")
return
try:
vision = 'projector_info' in json.loads(response.text)
data = json.loads(response.text)
except Exception as e:
logger.error(f"Error fetching vision info: {str(e)}")
model_row = model_selector_row(model_name, vision)
logger.error(f"Error fetching 'api - show' info: {str(e)}")
model_row = model_selector_row(model_name, data)
GLib.idle_add(self.get_popover().model_list_box.append, model_row)
GLib.idle_add(self.change_model, model_name)
GLib.idle_add(window.title_stack.set_visible_child_name, 'model_selector')
def remove_model(self, model_name:str):
self.get_popover().model_list_box.remove(next((model for model in list(self.get_popover().model_list_box) if model.get_name() == model_name), None))
self.model_changed(self.get_popover().model_list_box)
window.title_stack.set_visible_child_name('model_selector' if len(window.model_manager.get_model_list()) > 0 else 'no_models')
def clear_list(self):
self.get_popover().model_list_box.remove_all()
@@ -248,6 +249,37 @@ class pulling_model_list(Gtk.ListBox):
visible=False
)
class information_bow(Gtk.Box):
__gtype_name__ = 'AlpacaModelInformationBow'
def __init__(self, title:str, subtitle:str):
self.title = title
self.subtitle = subtitle
title_label = Gtk.Label(
label=self.title,
css_classes=['subtitle', 'caption', 'dim-label'],
hexpand=True,
margin_top=10,
margin_start=0,
margin_end=0
)
subtitle_label = Gtk.Label(
label=self.subtitle if self.subtitle else '(none)',
css_classes=['heading'],
hexpand=True,
margin_bottom=10,
margin_start=0,
margin_end=0
)
super().__init__(
spacing=5,
orientation=1,
css_classes=['card']
)
self.append(title_label)
self.append(subtitle_label)
class local_model(Gtk.ListBoxRow):
__gtype_name__ = 'AlpacaLocalModel'
@@ -275,6 +307,16 @@ class local_model(Gtk.ListBoxRow):
description_box.append(model_label)
description_box.append(tag_label)
info_button = Gtk.Button(
icon_name = "info-outline-symbolic",
vexpand = False,
valign = 3,
css_classes = ["circular"],
tooltip_text = _("Details")
)
info_button.connect('clicked', self.show_information)
delete_button = Gtk.Button(
icon_name = "user-trash-symbolic",
vexpand = False,
@@ -302,6 +344,7 @@ class local_model(Gtk.ListBoxRow):
margin_end=10
)
container_box.append(description_box)
container_box.append(info_button)
container_box.append(delete_button)
super().__init__(
@@ -309,6 +352,53 @@ class local_model(Gtk.ListBoxRow):
name=model_name
)
def show_information(self, button):
model = next((element for element in list(window.model_manager.model_selector.get_popover().model_list_box) if element.get_name() == self.get_name()), None)
model_name = model.get_child().get_label()
window.model_detail_page.set_title(' ('.join(model_name.split(' (')[:-1]))
window.model_detail_page.set_description(' ('.join(model_name.split(' (')[-1:])[:-1])
window.model_detail_create_button.set_name(model_name)
window.model_detail_create_button.set_tooltip_text(_("Create Model Based on '{}'").format(model_name))
details_flow_box = Gtk.FlowBox(
valign=1,
hexpand=True,
vexpand=False,
selection_mode=0,
max_children_per_line=2,
min_children_per_line=1,
margin_top=12,
margin_bottom=12,
margin_start=12,
margin_end=12
)
translation_strings={
'modified_at': _('Modified At'),
'parent_model': _('Parent Model'),
'format': _('Format'),
'family': _('Family'),
'parameter_size': _('Parameter Size'),
'quantization_level': _('Quantization Level')
}
if 'modified_at' in model.data and model.data['modified_at']:
details_flow_box.append(information_bow(
title=translation_strings['modified_at'],
subtitle=datetime.datetime.strptime(':'.join(model.data['modified_at'].split(':')[:2]), '%Y-%m-%dT%H:%M').strftime('%Y-%m-%d %H:%M')
))
for name, value in model.data['details'].items():
if isinstance(value, str):
details_flow_box.append(information_bow(
title=translation_strings[name] if name in translation_strings else name.replace('_', ' ').title(),
subtitle=value
))
window.model_detail_page.set_child(details_flow_box)
window.navigation_view_manage_models.push_by_tag('model_information')
class local_model_list(Gtk.ListBox):
__gtype_name__ = 'AlpacaLocalModelList'
@@ -521,7 +611,8 @@ class model_manager_container(Gtk.Box):
except Exception as e:
logger.error(e)
window.connection_error()
window.title_stack.set_visible_child_name('model_selector')
window.title_stack.set_visible_child_name('model_selector' if len(window.model_manager.get_model_list()) > 0 else 'no_models')
#window.title_stack.set_visible_child_name('model_selector')
window.chat_list_box.update_welcome_screens(len(self.get_model_list()) > 0)
#Should only be called when the app starts

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 8 0 c -4.410156 0 -8 3.589844 -8 8 s 3.589844 8 8 8 s 8 -3.589844 8 -8 s -3.589844 -8 -8 -8 z m 0 2 c 3.332031 0 6 2.667969 6 6 s -2.667969 6 -6 6 s -6 -2.667969 -6 -6 s 2.667969 -6 6 -6 z m 0 1.875 c -0.621094 0 -1.125 0.503906 -1.125 1.125 s 0.503906 1.125 1.125 1.125 s 1.125 -0.503906 1.125 -1.125 s -0.503906 -1.125 -1.125 -1.125 z m -1.523438 3.125 c -0.265624 0.011719 -0.476562 0.230469 -0.476562 0.5 c 0 0.277344 0.222656 0.5 0.5 0.5 h 0.5 v 3 h -0.5 c -0.277344 0 -0.5 0.222656 -0.5 0.5 s 0.222656 0.5 0.5 0.5 h 3 c 0.277344 0 0.5 -0.222656 0.5 -0.5 s -0.222656 -0.5 -0.5 -0.5 h -0.5 v -4 h -2.5 c -0.007812 0 -0.015625 0 -0.023438 0 z m 0 0" fill="#222222"/></svg>

After

Width:  |  Height:  |  Size: 813 B

View File

@@ -102,6 +102,9 @@ class AlpacaWindow(Adw.ApplicationWindow):
title_stack = Gtk.Template.Child()
manage_models_dialog = Gtk.Template.Child()
model_scroller = Gtk.Template.Child()
model_detail_page = Gtk.Template.Child()
model_detail_create_button = Gtk.Template.Child()
ollama_information_label = Gtk.Template.Child()
chat_list_container = Gtk.Template.Child()
chat_list_box = None
@@ -332,6 +335,10 @@ class AlpacaWindow(Adw.ApplicationWindow):
clipboard.read_text_async(None, self.cb_text_received)
clipboard.read_texture_async(None, self.cb_image_received)
@Gtk.Template.Callback()
def model_detail_create_button_clicked(self, button):
self.create_model(button.get_name(), False)
def convert_model_name(self, name:str, mode:int) -> str: # mode=0 name:tag -> Name (tag) | mode=1 Name (tag) -> name:tag
try:
if mode == 0:
@@ -351,20 +358,15 @@ class AlpacaWindow(Adw.ApplicationWindow):
modelfile_buffer.delete(modelfile_buffer.get_start_iter(), modelfile_buffer.get_end_iter())
self.create_model_system.set_text('')
if not file:
response = self.ollama_instance.request("POST", "api/show", json.dumps({"name": self.convert_model_name(model, 1)}))
if response.status_code == 200:
data = json.loads(response.text)
modelfile = []
for line in data['modelfile'].split('\n'):
if line.startswith('SYSTEM'):
self.create_model_system.set_text(line[len('SYSTEM'):].strip())
if not line.startswith('SYSTEM') and not line.startswith('FROM') and not line.startswith('#'):
modelfile.append(line)
self.create_model_name.set_text(self.convert_model_name(model, 1).split(':')[0] + "-custom")
modelfile_buffer.insert(modelfile_buffer.get_start_iter(), '\n'.join(modelfile), len('\n'.join(modelfile).encode('utf-8')))
else:
##TODO ERROR MESSAGE
return
data = next((element for element in list(self.model_manager.model_selector.get_popover().model_list_box) if element.get_name() == self.convert_model_name(model, 1)), None).data
modelfile = []
for line in data['modelfile'].split('\n'):
if line.startswith('SYSTEM'):
self.create_model_system.set_text(line[len('SYSTEM'):].strip())
if not line.startswith('SYSTEM') and not line.startswith('FROM') and not line.startswith('#'):
modelfile.append(line)
self.create_model_name.set_text(self.convert_model_name(model, 1).split(':')[0] + "-custom")
modelfile_buffer.insert(modelfile_buffer.get_start_iter(), '\n'.join(modelfile), len('\n'.join(modelfile).encode('utf-8')))
self.create_model_base.set_subtitle(self.convert_model_name(model, 1))
else:
self.create_model_name.set_text(os.path.splitext(os.path.basename(model))[0])
@@ -607,6 +609,7 @@ Generate a title following these rules:
self.chat_list_box.prepend_chat(_("New Chat"))
def generate_numbered_name(self, chat_name:str, compare_list:list) -> str:
if chat_name in compare_list:
for i in range(len(compare_list)):
@@ -829,7 +832,7 @@ Generate a title following these rules:
[element.set_sensitive(True) for element in sensitive_elements]
self.get_application().lookup_action('manage_models').set_enabled(True)
self.title_stack.set_visible_child_name('model_selector')
self.title_stack.set_visible_child_name('model_selector' if len(self.model_manager.get_model_list()) > 0 else 'no_models')
if state:
options = {

View File

@@ -6,7 +6,7 @@
<signal name="close-request" handler="closing_app"/>
<property name="resizable">True</property>
<property name="width-request">400</property>
<property name="height-request">400</property>
<property name="height-request">600</property>
<property name="default-width">1300</property>
<property name="default-height">800</property>
<property name="title">Alpaca</property>
@@ -97,6 +97,18 @@
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">no_models</property>
<property name="child">
<object class="GtkButton">
<property name="label" translatable="yes">Manage Models</property>
<property name="tooltip-text" translatable="yes">Manage Models</property>
<property name="action-name">app.manage_models</property>
</object>
</property>
</object>
</child>
</object>
</child>
<child type="end">
@@ -212,6 +224,7 @@
<signal name="paste-clipboard" handler="on_clipboard_paste"/>
<style>
<class name="message_text_view"/>
<class name="undershoot-bottom"/>
</style>
<property name="wrap-mode">word</property>
<property name="top-margin">10</property>
@@ -457,6 +470,19 @@
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="GtkLabel" id="ollama_information_label">
<property name="wrap">true</property>
<property name="label" translatable="yes">Integrated Ollama instance is not running</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
@@ -639,20 +665,48 @@
</child>
<child>
<object class="AdwNavigationPage">
<property name="title" translatable="yes">Create Model</property>
<property name="tag">model_create_page</property>
<property name="title" translatable="yes">Model Details</property>
<property name="tag">model_information</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<child type="start">
<object class="GtkButton">
<signal name="clicked" handler="link_button_handler"/>
<property name="icon-name">globe-symbolic</property>
<object class="GtkButton" id="model_detail_create_button">
<signal name="clicked" handler="model_detail_create_button_clicked"/>
<property name="icon-name">edit-copy-symbolic</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="vexpand">true</property>
<property name="hexpand">true</property>
<child>
<object class="AdwStatusPage" id="model_detail_page">
<property name="icon-name">brain-augemnted-symbolic</property>
<property name="description">text</property>
<style>
<class name="compact"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="title" translatable="yes">Create Model</property>
<property name="tag">model_create_page</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="vexpand">true</property>
@@ -726,6 +780,9 @@
<object class="GtkScrolledWindow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<style>
<class name="undershoot-bottom"/>
</style>
<child>
<object class="GtkTextView" id="create_model_modelfile">
<style>