25 Commits
2.0.2 ... 2.0.3

Author SHA1 Message Date
jeffser
991c01cba0 Update release notes 2024-09-18 10:42:55 -06:00
jeffser
3e6a2b040f Update spanish 2024-09-18 10:39:35 -06:00
jeffser
22138933f7 Updated languages 2024-09-18 10:32:26 -06:00
jeffser
3d1a3a9ece New release notes 2024-09-18 10:31:43 -06:00
jeffser
0d5350b24d Updated runtime to Gnome.Platform 47 2024-09-18 10:28:22 -06:00
jeffser
4fb83ed441 Made sidebar resize a little 2024-09-17 22:36:51 -06:00
jeffser
e8cfc9a9ee Update welcome dialog 2024-09-17 21:27:19 -06:00
jeffser
13a076bd9f Instant launch 2024-09-17 21:14:58 -06:00
jeffser
63296219cf Merge branch 'main' of github.com-jeffser:Jeffser/Alpaca 2024-09-17 19:46:34 -06:00
jeffser
1ee36b113a Fixed stop button 2024-09-17 19:46:28 -06:00
Jeffry Samuel
dce91739e7 Update com.jeffser.Alpaca.metainfo.xml.in 2024-09-17 19:04:55 -06:00
jeffser
dd29077499 Preparing for 2.0.3 2024-09-17 19:03:48 -06:00
jeffser
e398d55211 Merge branch 'main' of github.com-jeffser:Jeffser/Alpaca 2024-09-17 18:59:31 -06:00
jeffser
cbdfe43896 Fixed image verifier 2024-09-17 18:59:21 -06:00
Jeffry Samuel
25eb1526d3 Update README.md 2024-09-16 22:10:28 -06:00
jeffser
318f15925f Fixed spinner 2024-09-16 18:30:48 -06:00
jeffser
95912e0211 Merge branch 'main' of github.com-jeffser:Jeffser/Alpaca 2024-09-16 10:38:04 -06:00
jeffser
f96b652605 Changed appearance of delete / stop buttons 2024-09-16 10:37:58 -06:00
Jeffry Samuel
24b1ff2e1b Update README.md 2024-09-16 10:34:52 -06:00
jeffser
7e79f715b1 Added hebrew to updater 2024-09-16 10:34:26 -06:00
jeffser
a061feeb71 Changed order 2024-09-16 10:33:39 -06:00
jeffser
12790b5ae1 Stop existing instance before starting new one fallback 2024-09-16 10:31:28 -06:00
Yosef Or Boczko
2e2626fa99 Added Hebrew Translation (#307) 2024-09-16 10:24:00 -06:00
hideo aoyama
3962315a6e first working version (#305) 2024-09-16 10:20:50 -06:00
jeffser
08c0074ae5 Experimental Snap package 2024-09-12 11:40:23 -06:00
29 changed files with 9738 additions and 6248 deletions

View File

@@ -8,9 +8,6 @@ Alpaca is an [Ollama](https://github.com/ollama/ollama) client where you can man
--- ---
> [!NOTE]
> Please checkout [this discussion](https://github.com/Jeffser/Alpaca/discussions/292), I want to start developing a new app alongside Alpaca but I need some suggestions, thanks!
> [!WARNING] > [!WARNING]
> This project is not affiliated at all with Ollama, I'm not responsible for any damages to your device or software caused by running code given by any AI models. > This project is not affiliated at all with Ollama, I'm not responsible for any damages to your device or software caused by running code given by any AI models.
@@ -71,6 +68,7 @@ Language | Contributors
🇹🇷 Turkish | [YusaBecerikli](https://github.com/YusaBecerikli) 🇹🇷 Turkish | [YusaBecerikli](https://github.com/YusaBecerikli)
🇺🇦 Ukrainian | [Simon](https://github.com/OriginalSimon) 🇺🇦 Ukrainian | [Simon](https://github.com/OriginalSimon)
🇩🇪 German | [Marcel Margenberg](https://github.com/MehrzweckMandala) 🇩🇪 German | [Marcel Margenberg](https://github.com/MehrzweckMandala)
🇮🇱 Hebrew | [Yosef Or Boczko](https://github.com/yoseforb)
Want to add a language? Visit [this discussion](https://github.com/Jeffser/Alpaca/discussions/153) to get started! Want to add a language? Visit [this discussion](https://github.com/Jeffser/Alpaca/discussions/153) to get started!

View File

@@ -1,7 +1,7 @@
{ {
"id" : "com.jeffser.Alpaca", "id" : "com.jeffser.Alpaca",
"runtime" : "org.gnome.Platform", "runtime" : "org.gnome.Platform",
"runtime-version" : "46", "runtime-version" : "47",
"sdk" : "org.gnome.Sdk", "sdk" : "org.gnome.Sdk",
"command" : "alpaca", "command" : "alpaca",
"finish-args" : [ "finish-args" : [

View File

@@ -78,6 +78,23 @@
<url type="contribute">https://github.com/Jeffser/Alpaca/discussions/154</url> <url type="contribute">https://github.com/Jeffser/Alpaca/discussions/154</url>
<url type="vcs-browser">https://github.com/Jeffser/Alpaca</url> <url type="vcs-browser">https://github.com/Jeffser/Alpaca</url>
<releases> <releases>
<release version="2.0.3" date="2024-09-18">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/2.0.3</url>
<description>
<p>Fixes</p>
<ul>
<li>Fixed spinner not hiding if the back end fails</li>
<li>Fixed image recognition with local images</li>
<li>Changed appearance of delete / stop model buttons</li>
<li>Fixed stop button crashing the app</li>
</ul>
<p>New</p>
<ul>
<li>Made sidebar resize a little when the window is smaller</li>
<li>Instant launch</li>
</ul>
</description>
</release>
<release version="2.0.2" date="2024-09-11"> <release version="2.0.2" date="2024-09-11">
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/2.0.2</url> <url type="details">https://github.com/Jeffser/Alpaca/releases/tag/2.0.2</url>
<description> <description>

View File

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

View File

@@ -9,3 +9,4 @@ hi
tr tr
uk uk
de de
he

File diff suppressed because it is too large Load Diff

1117
po/bn.po

File diff suppressed because it is too large Load Diff

980
po/de.po

File diff suppressed because it is too large Load Diff

974
po/es.po

File diff suppressed because it is too large Load Diff

973
po/fr.po

File diff suppressed because it is too large Load Diff

2731
po/he.po Normal file

File diff suppressed because it is too large Load Diff

1124
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

1132
po/ru.po

File diff suppressed because it is too large Load Diff

973
po/tr.po

File diff suppressed because it is too large Load Diff

998
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

9
snap/gui/alpaca.desktop Normal file
View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=alpaca
Exec=alpaca
Icon=${SNAP}/meta/gui/com.jeffser.Alpaca.svg
Terminal=false
Type=Application
Categories=Utility;Development;Chat;
Keywords=ai;ollama;llm
X-Purism-FormFactor=Workstation;Mobile;

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="128px"
viewBox="0 0 128 128"
width="128px"
version="1.1"
id="svg26"
sodipodi:docname="com.jeffser.Alpaca.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs26" />
<sodipodi:namedview
id="namedview26"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="6.65625"
inkscape:cx="64"
inkscape:cy="64"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg26" />
<linearGradient
id="a"
gradientUnits="userSpaceOnUse"
x1="48"
x2="48"
y1="88"
y2="48">
<stop
offset="0"
stop-color="#b6d1f2"
id="stop1" />
<stop
offset="1"
stop-color="#e9eef4"
id="stop2" />
</linearGradient>
<path
d="m 2 66 h 24 v 12 h -24 z m 0 0"
fill="#99c1f1"
id="path2" />
<path
d="m 12.324219 56 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 1.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -1.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#99c1f1"
id="path3" />
<g
fill="#5e5c64"
id="g7">
<path
d="m 82 101 h 8 v 23 h -8 z m 0 0"
id="path4" />
<path
d="m 100 101 h 8 v 23 h -8 z m 0 0"
id="path5" />
<path
d="m 20 101 h 8 v 23 h -8 z m 0 0"
id="path6" />
<path
d="m 38 101 h 8 v 23 h -8 z m 0 0"
id="path7" />
</g>
<path
d="m 40.324219 80 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#6b9bd2"
id="path8" />
<path
d="m 102.324219 80 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#6b9bd2"
id="path9" />
<path
d="m 40.324219 76 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#82adde"
id="path10" />
<path
d="m 102.324219 76 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#82adde"
id="path11" />
<path
d="m 22.324219 80 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#99c1f1"
id="path12" />
<path
d="m 84.324219 80 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#99c1f1"
id="path13" />
<path
d="m 28 58 h 72 c 8.835938 0 16 7.164062 16 16 v 18 c 0 8.835938 -7.164062 16 -16 16 h -72 c -8.835938 0 -16 -7.164062 -16 -16 v -18 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0"
fill="#99c1f1"
id="path14" />
<path
d="m 22.324219 76 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#b6d1f2"
id="path15" />
<path
d="m 84.324219 76 h 3.351562 c 5.703125 0 10.324219 4.621094 10.324219 10.324219 v 17.351562 c 0 5.703125 -4.621094 10.324219 -10.324219 10.324219 h -3.351562 c -5.703125 0 -10.324219 -4.621094 -10.324219 -10.324219 v -17.351562 c 0 -5.703125 4.621094 -10.324219 10.324219 -10.324219 z m 0 0"
fill="#b6d1f2"
id="path16" />
<path
d="m 111 16 c -2.859375 0 -5.5 -1.523438 -6.929688 -4 c -1.425781 -2.476562 -1.425781 -5.523438 0 -8 c 1.429688 -2.476562 4.070313 -4 6.929688 -4"
fill="#bbd6f6"
id="path17" />
<path
d="m 103 8 h 8 v 16 h -8 z m 0 0"
fill="#99c1f1"
id="path18" />
<path
d="m 96 8 h 18 c 2.210938 0 4 1.789062 4 4 v 6 c 0 2.210938 -1.789062 4 -4 4 h -18 c -2.207031 0 -4 -1.789062 -4 -4 v -6 c 0 -2.210938 1.792969 -4 4 -4 z m 0 0"
fill="#e9eef4"
id="path19" />
<path
d="m 100 16 c -2.859375 0 -5.5 -1.523438 -6.929688 -4 c -1.425781 -2.476562 -1.425781 -5.523438 0 -8 c 1.429688 -2.476562 4.070313 -4 6.929688 -4"
fill="#e9eef4"
id="path20" />
<path
d="m 92 16 v 21.675781 c 0 5.71875 -4.605469 10.324219 -10.324219 10.324219 h -53.675781 c -8.863281 0 -16 7.136719 -16 16 v 24 c 0 8.863281 7.136719 16 16 16 h 72 c 8.863281 0 16 -7.136719 16 -16 v -72 z m 0 0"
fill="url(#a)"
id="path21" />
<path
d="m 92 8 h 13 v 16 h -13 z m 0 0"
fill="#e9eef4"
id="path22" />
<path
d="m 104 14 h 22 v 6 c -11.335938 0.6875 -11.078125 8.476562 -17 8 h -5 z m 0 0"
fill="#5e5c64"
id="path23" />
<path
d="m 118 14 c 0 1.378906 -1.117188 2.5 -2.5 2.5 c -1.378906 0 -2.5 -1.121094 -2.5 -2.5 s 1.121094 -2.5 2.5 -2.5 c 1.382812 0 2.5 1.121094 2.5 2.5 z m 0 0"
fill="#e9eef4"
id="path24" />
<path
d="m 113 14 c 0 1.378906 -1.121094 2.5 -2.5 2.5 c -1.382812 0 -2.5 -1.121094 -2.5 -2.5 s 1.117188 -2.5 2.5 -2.5 c 1.378906 0 2.5 1.121094 2.5 2.5 z m 0 0"
fill="#e9eef4"
id="path25" />
<path
d="m 108 14 c 0 1.378906 -1.117188 2.5 -2.5 2.5 c -1.378906 0 -2.5 -1.121094 -2.5 -2.5 s 1.121094 -2.5 2.5 -2.5 c 1.382812 0 2.5 1.121094 2.5 2.5 z m 0 0"
fill="#e9eef4"
id="path26" />
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

111
snap/snapcraft.yaml Normal file
View File

@@ -0,0 +1,111 @@
name: alpaca
base: core24
adopt-info: alpaca
summary: An Ollama client made with GTK4 and Adwaita
description: |
Alpaca is an Ollama client where you can manage and chat with multiple models,
Alpaca provides an easy and begginer friendly way of interacting with local AI,
everything is open source and powered by Ollama.
platforms:
amd64:
confinement: strict
grade: stable
compression: lzo
slots:
dbus-alpaca:
interface: dbus
bus: session
name: com.jeffser.Alpaca
apps:
alpaca:
command: usr/bin/alpaca
desktop: meta/gui/alpaca.desktop
common-id: com.jeffser.Alpaca
extensions:
- gnome
plugs:
- network
- network-bind
- desktop
- desktop-legacy
- wayland
- opengl
- home
- removable-media
slots:
- dbus-alpaca
ollama:
command: bin/ollama
plugs:
- home
- removable-media
- network
- network-bind
- opengl
ollama-daemon:
command: bin/ollama serve
daemon: simple
install-mode: enable
restart-condition: on-failure
plugs:
- home
- removable-media
- network
- network-bind
- opengl
parts:
# Python dependencies
python-deps:
plugin: python
source: .
python-packages:
- requests==2.31.0
- pillow==10.3.0
- pypdf==4.2.0
- pytube==15.0.0
- html2text==2024.2.26
# Ollama plugin
ollama:
plugin: dump
source: https://github.com/ollama/ollama/releases/download/v0.3.10/ollama-linux-amd64.tgz
# Alpaca app
alpaca:
plugin: meson
source-type: git
source: https://github.com/Jeffser/Alpaca.git
source-tag: '2.0.2'
source-depth: 1
meson-parameters:
- --prefix=/snap/alpaca/current/usr
build-packages:
- meson
- ninja-build
- pkg-config
- libcairo2-dev
- libgtk-3-dev
- libglib2.0-dev
- gettext
- desktop-file-utils
- appstream
override-pull: |
craftctl default
craftctl set version=$(git describe --tags --abbrev=0)
override-build: |
craftctl default
sed -i '1c#!/usr/bin/env python3' $CRAFT_PART_INSTALL/snap/alpaca/current/usr/bin/alpaca
stage-packages:
- libnuma1
parse-info:
- usr/share/metainfo/com.jeffser.Alpaca.metainfo.xml
organize:
snap/alpaca/current/usr: usr
after: [python-deps]

View File

@@ -92,6 +92,7 @@ class instance():
self.idle_timer.start() self.idle_timer.start()
def start(self): def start(self):
self.stop()
if shutil.which('ollama'): if shutil.which('ollama'):
if not os.path.isdir(os.path.join(cache_dir, 'tmp/ollama')): if not os.path.isdir(os.path.join(cache_dir, 'tmp/ollama')):
os.mkdir(os.path.join(cache_dir, 'tmp/ollama')) os.mkdir(os.path.join(cache_dir, 'tmp/ollama'))

View File

@@ -121,7 +121,7 @@ class chat(Gtk.ScrolledWindow):
tooltip_text=_("Open Model Manager"), tooltip_text=_("Open Model Manager"),
css_classes=["suggested-action", "pill"] css_classes=["suggested-action", "pill"]
) )
button.connect('clicked', lambda *_ : window.manage_models_dialog.present(window)) button.set_action_name('app.manage_models')
button_container.append(button) button_container.append(button)
self.welcome_screen = Adw.StatusPage( self.welcome_screen = Adw.StatusPage(

View File

@@ -345,6 +345,9 @@ class action_buttons(Gtk.Box):
def regenerate_message(self): def regenerate_message(self):
chat = self.get_parent().get_parent().get_parent().get_parent().get_parent() chat = self.get_parent().get_parent().get_parent().get_parent().get_parent()
message_element = self.get_parent() message_element = self.get_parent()
if message_element.spinner:
message_element.container.remove(message_element.spinner)
message_element.spinner = None
if not chat.busy: if not chat.busy:
message_element.set_text() message_element.set_text()
if message_element.footer: if message_element.footer:
@@ -425,6 +428,8 @@ class message(Gtk.Overlay):
if not self.action_buttons: if not self.action_buttons:
self.action_buttons = action_buttons(self.bot) self.action_buttons = action_buttons(self.bot)
self.add_overlay(self.action_buttons) self.add_overlay(self.action_buttons)
if not self.text:
self.action_buttons.set_visible(False)
def update_message(self, data:dict): def update_message(self, data:dict):
chat = self.get_parent().get_parent().get_parent().get_parent() chat = self.get_parent().get_parent().get_parent().get_parent()
@@ -452,6 +457,12 @@ class message(Gtk.Overlay):
window.show_notification(chat.get_name(), self.text[:200] + (self.text[200:] and '...'), Gio.ThemedIcon.new("chat-message-new-symbolic")) window.show_notification(chat.get_name(), self.text[:200] + (self.text[200:] and '...'), Gio.ThemedIcon.new("chat-message-new-symbolic"))
window.save_history(chat) window.save_history(chat)
else: else:
if self.spinner:
GLib.idle_add(self.container.remove, self.spinner)
self.spinner = None
chat_tab = window.chat_list_box.get_tab_by_name(chat.get_name())
if chat_tab.spinner:
GLib.idle_add(chat_tab.spinner.set_visible, False)
sys.exit() sys.exit()
def set_text(self, text:str=None): def set_text(self, text:str=None):
@@ -538,6 +549,9 @@ class message(Gtk.Overlay):
text_b = text_block(self.bot) text_b = text_block(self.bot)
text_b.set_visible(False) text_b.set_visible(False)
self.content_children.append(text_b) self.content_children.append(text_b)
if self.spinner:
self.container.remove(self.spinner)
self.spinner = None
self.spinner = Gtk.Spinner(spinning=True, margin_top=12, margin_bottom=12, hexpand=True) self.spinner = Gtk.Spinner(spinning=True, margin_top=12, margin_bottom=12, hexpand=True)
self.container.append(self.spinner) self.container.append(self.spinner)
self.container.append(text_b) self.container.append(text_b)

View File

@@ -69,7 +69,8 @@ class model_selector_button(Gtk.MenuButton):
super().__init__( super().__init__(
tooltip_text=_('Select a Model'), tooltip_text=_('Select a Model'),
child=container, child=container,
popover=self.popover popover=self.popover,
halign=3
) )
def change_model(self, model_name:str): def change_model(self, model_name:str):
@@ -158,7 +159,7 @@ class pulling_model(Gtk.ListBoxRow):
icon_name = "media-playback-stop-symbolic", icon_name = "media-playback-stop-symbolic",
vexpand = False, vexpand = False,
valign = 3, valign = 3,
css_classes = ["destructive-action", "circular"], css_classes = ["error", "circular"],
tooltip_text = _("Stop Pulling '{}'").format(window.convert_model_name(model_name, 0)) tooltip_text = _("Stop Pulling '{}'").format(window.convert_model_name(model_name, 0))
) )
stop_button.connect('clicked', lambda *_: dialogs.stop_pull_model(window, self)) stop_button.connect('clicked', lambda *_: dialogs.stop_pull_model(window, self))
@@ -237,7 +238,7 @@ class local_model(Gtk.ListBoxRow):
icon_name = "user-trash-symbolic", icon_name = "user-trash-symbolic",
vexpand = False, vexpand = False,
valign = 3, valign = 3,
css_classes = ["destructive-action", "circular"], css_classes = ["error", "circular"],
tooltip_text = _("Remove '{}'").format(window.convert_model_name(model_name, 0)) tooltip_text = _("Remove '{}'").format(window.convert_model_name(model_name, 0))
) )
delete_button.connect('clicked', lambda *_, model_name=model_name: dialogs.delete_model(window, model_name)) delete_button.connect('clicked', lambda *_, model_name=model_name: dialogs.delete_model(window, model_name))
@@ -421,7 +422,7 @@ class model_manager_container(Gtk.Box):
self.available_list = available_model_list() self.available_list = available_model_list()
self.append(self.available_list) self.append(self.available_list)
self.model_selector = model_selector_button() self.model_selector = model_selector_button()
window.header_bar.set_title_widget(self.model_selector) window.title_stack.add_named(self.model_selector, 'model_selector')
def add_local_model(self, model_name:str): def add_local_model(self, model_name:str):
self.local_list.add_model(model_name) self.local_list.add_model(model_name)
@@ -470,6 +471,8 @@ class model_manager_container(Gtk.Box):
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
window.connection_error() window.connection_error()
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 #Should only be called when the app starts
def update_available_list(self): def update_available_list(self):

View File

@@ -318,7 +318,7 @@ def attach_file_response(self, file_dialog, result):
file_type = next(key for key, value in file_types.items() if extension in value) file_type = next(key for key, value in file_types.items() if extension in value)
if not file_type: if not file_type:
return return
if file_type == 'image' and not self.verify_if_image_can_be_used(): if file_type == 'image' and not self.model_manager.verify_if_image_can_be_used():
self.show_toast(_("Image recognition is only available on specific models"), self.main_overlay) self.show_toast(_("Image recognition is only available on specific models"), self.main_overlay)
return return
self.attach_file(file.get_path(), file_type) self.attach_file(file.get_path(), file_type)

View File

@@ -51,7 +51,6 @@ class AlpacaWindow(Adw.ApplicationWindow):
#Variables #Variables
attachments = {} attachments = {}
header_bar = Gtk.Template.Child()
#Override elements #Override elements
overrides_group = Gtk.Template.Child() overrides_group = Gtk.Template.Child()
@@ -95,9 +94,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
model_searchbar = Gtk.Template.Child() model_searchbar = Gtk.Template.Child()
no_results_page = Gtk.Template.Child() no_results_page = Gtk.Template.Child()
model_link_button = Gtk.Template.Child() model_link_button = Gtk.Template.Child()
launch_dialog = Gtk.Template.Child() title_stack = Gtk.Template.Child()
launch_status = Gtk.Template.Child()
launch_level_bar = Gtk.Template.Child()
manage_models_dialog = Gtk.Template.Child() manage_models_dialog = Gtk.Template.Child()
model_scroller = Gtk.Template.Child() model_scroller = Gtk.Template.Child()
@@ -206,10 +203,6 @@ class AlpacaWindow(Adw.ApplicationWindow):
self.welcome_carousel.scroll_to(self.welcome_carousel.get_nth_page(self.welcome_carousel.get_position()+1), True) self.welcome_carousel.scroll_to(self.welcome_carousel.get_nth_page(self.welcome_carousel.get_position()+1), True)
else: else:
self.welcome_dialog.force_close() self.welcome_dialog.force_close()
if shutil.which('ollama'):
threading.Thread(target=self.prepare_alpaca, args=(11435, '', False, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True, True)).start()
else:
threading.Thread(target=self.prepare_alpaca, args=(11435, 'http://0.0.0.0:11434', True, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True, False)).start()
self.powersaver_warning_switch.set_active(True) self.powersaver_warning_switch.set_active(True)
@Gtk.Template.Callback() @Gtk.Template.Callback()
@@ -554,12 +547,16 @@ Generate a title following these rules:
if self.regenerate_button: if self.regenerate_button:
GLib.idle_add(self.chat_list_box.get_current_chat().remove, self.regenerate_button) GLib.idle_add(self.chat_list_box.get_current_chat().remove, self.regenerate_button)
try: try:
response = self.ollama_instance.request("POST", "api/chat", json.dumps(data), lambda data, message_element=message_element: GLib.idle_add(message_element.update_message, data)) response = self.ollama_instance.request("POST", "api/chat", json.dumps(data), lambda data, message_element=message_element: message_element.update_message(data))
if response.status_code != 200: if response.status_code != 200:
raise Exception('Network Error') raise Exception('Network Error')
except Exception as e: except Exception as e:
self.chat_list_box.get_tab_by_name(chat.get_name()).spinner.set_visible(False)
chat.busy = False chat.busy = False
GLib.idle_add(message_element.add_action_buttons) GLib.idle_add(message_element.add_action_buttons)
if message_element.spinner:
GLib.idle_add(message_element.container.remove, message_element.spinner)
message_element.spinner = None
GLib.idle_add(chat.show_regenerate_button, message_element) GLib.idle_add(chat.show_regenerate_button, message_element)
GLib.idle_add(self.connection_error) GLib.idle_add(self.connection_error)
@@ -790,19 +787,11 @@ Generate a title following these rules:
def power_saver_toggled(self, monitor): def power_saver_toggled(self, monitor):
self.banner.set_revealed(monitor.get_power_saver_enabled() and self.powersaver_warning_switch.get_active()) self.banner.set_revealed(monitor.get_power_saver_enabled() and self.powersaver_warning_switch.get_active())
def prepare_alpaca(self, local_port:int, remote_url:str, remote:bool, tweaks:dict, overrides:dict, bearer_token:str, idle_timer_delay:int, save:bool, show_launch_dialog:bool): def prepare_alpaca(self, local_port:int, remote_url:str, remote:bool, tweaks:dict, overrides:dict, bearer_token:str, idle_timer_delay:int, save:bool):
#Show launch dialog
if show_launch_dialog:
GLib.idle_add(self.launch_dialog.present, self)
#Instance #Instance
self.launch_level_bar.set_value(0)
self.launch_status.set_description(_('Loading instance'))
self.ollama_instance = connection_handler.instance(local_port, remote_url, remote, tweaks, overrides, bearer_token, idle_timer_delay) self.ollama_instance = connection_handler.instance(local_port, remote_url, remote, tweaks, overrides, bearer_token, idle_timer_delay)
#User Preferences #User Preferences
self.launch_level_bar.set_value(1)
self.launch_status.set_description(_('Applying user preferences'))
for element in list(list(list(list(self.tweaks_group)[0])[1])[0]): for element in list(list(list(list(self.tweaks_group)[0])[1])[0]):
if element.get_name() in self.ollama_instance.tweaks: if element.get_name() in self.ollama_instance.tweaks:
element.set_value(self.ollama_instance.tweaks[element.get_name()]) element.set_value(self.ollama_instance.tweaks[element.get_name()])
@@ -821,26 +810,20 @@ Generate a title following these rules:
#Model Manager #Model Manager
self.model_manager = model_widget.model_manager_container() self.model_manager = model_widget.model_manager_container()
self.model_scroller.set_child(self.model_manager) self.model_scroller.set_child(self.model_manager)
self.launch_level_bar.set_value(2)
self.launch_status.set_description(_('Updating list of local models'))
self.model_manager.update_local_list()
self.launch_level_bar.set_value(3)
self.launch_status.set_description(_('Updating list of available models'))
self.model_manager.update_available_list()
#Chat History #Chat History
self.launch_level_bar.set_value(4) self.load_history()
self.launch_status.set_description(_('Loading chats'))
GLib.idle_add(self.load_history) #Model Manager P.2
self.launch_level_bar.set_value(5) self.model_manager.update_available_list()
self.model_manager.update_local_list()
self.get_application().lookup_action("manage_models").set_enabled(True)
#Save preferences #Save preferences
if save: if save:
self.save_server_config() self.save_server_config()
time.sleep(.5) #This is to prevent errors with gtk creating the launch dialog and closing it too quickly self.send_button.set_sensitive(True)
#Close launch dialog
GLib.idle_add(self.launch_dialog.force_close)
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
@@ -886,6 +869,7 @@ Generate a title following these rules:
for action_name, data in universal_actions.items(): for action_name, data in universal_actions.items():
self.get_application().create_action(action_name, data[0], data[1] if len(data) > 1 else None) self.get_application().create_action(action_name, data[0], data[1] if len(data) > 1 else None)
self.get_application().lookup_action("manage_models").set_enabled(False)
self.file_preview_remove_button.connect('clicked', lambda button : dialogs.remove_attached_file(self, button.get_name())) self.file_preview_remove_button.connect('clicked', lambda button : dialogs.remove_attached_file(self, button.get_name()))
self.attachment_button.connect("clicked", lambda button, file_filter=self.file_filter_attachments: dialogs.attach_file(self, file_filter)) self.attachment_button.connect("clicked", lambda button, file_filter=self.file_filter_attachments: dialogs.attach_file(self, file_filter))
@@ -902,12 +886,16 @@ Generate a title following these rules:
if 'powersaver_warning' not in data: if 'powersaver_warning' not in data:
data['powersaver_warning'] = True data['powersaver_warning'] = True
self.powersaver_warning_switch.set_active(data['powersaver_warning']) self.powersaver_warning_switch.set_active(data['powersaver_warning'])
threading.Thread(target=self.prepare_alpaca, args=(data['local_port'], data['remote_url'], data['run_remote'], data['model_tweaks'], data['ollama_overrides'], data['remote_bearer_token'], round(data['idle_timer']), False, True)).start() threading.Thread(target=self.prepare_alpaca, args=(data['local_port'], data['remote_url'], data['run_remote'], data['model_tweaks'], data['ollama_overrides'], data['remote_bearer_token'], round(data['idle_timer']), False)).start()
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
threading.Thread(target=self.prepare_alpaca, args=(11435, '', False, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True, True)).start() threading.Thread(target=self.prepare_alpaca, args=(11435, '', False, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True)).start()
self.powersaver_warning_switch.set_active(True) self.powersaver_warning_switch.set_active(True)
else: else:
if shutil.which('ollama'):
threading.Thread(target=self.prepare_alpaca, args=(11435, '', False, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True)).start()
else:
threading.Thread(target=self.prepare_alpaca, args=(11435, 'http://0.0.0.0:11434', True, {'temperature': 0.7, 'seed': 0, 'keep_alive': 5}, {}, '', 0, True)).start()
self.welcome_dialog.present(self) self.welcome_dialog.present(self)
if self.powersaver_warning_switch.get_active(): if self.powersaver_warning_switch.get_active():

View File

@@ -19,7 +19,7 @@
<property name="content"> <property name="content">
<object class="AdwOverlaySplitView" id="split_view_overlay"> <object class="AdwOverlaySplitView" id="split_view_overlay">
<property name="show-sidebar" bind-source="show_sidebar_button" bind-property="active" bind-flags="sync-create"/> <property name="show-sidebar" bind-source="show_sidebar_button" bind-property="active" bind-flags="sync-create"/>
<property name="sidebar-width-fraction">0.4</property> <property name="sidebar-width-fraction">0.3</property>
<property name="sidebar"> <property name="sidebar">
<object class="AdwToolbarView"> <object class="AdwToolbarView">
<child type="top"> <child type="top">
@@ -55,7 +55,7 @@
<child> <child>
<object class="AdwToolbarView"> <object class="AdwToolbarView">
<child type="top"> <child type="top">
<object class="AdwHeaderBar" id="header_bar"> <object class="AdwHeaderBar">
<child type="start"> <child type="start">
<object class="GtkToggleButton" id="show_sidebar_button"> <object class="GtkToggleButton" id="show_sidebar_button">
<property name="icon-name">sidebar-show-symbolic</property> <property name="icon-name">sidebar-show-symbolic</property>
@@ -63,6 +63,33 @@
<property name="active" bind-source="split_view_overlay" bind-property="show-sidebar" bind-flags="sync-create"/> <property name="active" bind-source="split_view_overlay" bind-property="show-sidebar" bind-flags="sync-create"/>
</object> </object>
</child> </child>
<child type="title">
<object class="GtkStack" id="title_stack">
<property name="transition_duration">100</property>
<property name="transition_type">1</property>
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">0</property>
<property name="spacing">10</property>
<child>
<object class="GtkSpinner">
<property name="spinning">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Loading Instance</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<child type="end"> <child type="end">
<object class="GtkMenuButton" id="secondary_menu_button"> <object class="GtkMenuButton" id="secondary_menu_button">
<property name="primary">False</property> <property name="primary">False</property>
@@ -178,6 +205,7 @@
<property name="vexpand">false</property> <property name="vexpand">false</property>
<property name="valign">3</property> <property name="valign">3</property>
<property name="tooltip-text" translatable="yes">Send Message</property> <property name="tooltip-text" translatable="yes">Send Message</property>
<property name="sensitive">false</property>
<style> <style>
<class name="accent"/> <class name="accent"/>
<class name="circular"/> <class name="circular"/>
@@ -420,27 +448,6 @@
</child> </child>
</object> </object>
<object class="AdwDialog" id="launch_dialog">
<accessibility>
<property name="label" translatable="yes">Loading Alpaca dialog</property>
</accessibility>
<property name="width-request">400</property>
<property name="can-close">false</property>
<child>
<object class="AdwStatusPage" id="launch_status">
<property name="icon_name">com.jeffser.Alpaca</property>
<property name="title" translatable="yes">Loading Alpaca...</property>
<property name="child">
<object class="GtkLevelBar" id="launch_level_bar">
<property name="mode">1</property>
<property name="min-value">0</property>
<property name="max-value">5</property>
</object>
</property>
</object>
</child>
</object>
<object class="AdwDialog" id="manage_models_dialog"> <object class="AdwDialog" id="manage_models_dialog">
<accessibility> <accessibility>
<property name="label" translatable="yes">Manage models dialog</property> <property name="label" translatable="yes">Manage models dialog</property>

View File

@@ -24,3 +24,5 @@ echo "Updating Ukrainian"
msgmerge --no-fuzzy-matching -U po/uk.po po/alpaca.pot msgmerge --no-fuzzy-matching -U po/uk.po po/alpaca.pot
echo "Updating German" echo "Updating German"
msgmerge --no-fuzzy-matching -U po/de.po po/alpaca.pot msgmerge --no-fuzzy-matching -U po/de.po po/alpaca.pot
echo "Updating Hebrew"
msgmerge --no-fuzzy-matching -U po/he.po po/alpaca.pot