Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e2b55a249 | ||
|
|
0fbb94cd72 | ||
|
|
004b3f8574 | ||
|
|
7d1931dd17 | ||
|
|
8b7f41afa7 | ||
|
|
4bc0832865 | ||
|
|
a66c6d5f40 | ||
|
|
33b7cae24d | ||
|
|
47f5c88ef2 | ||
|
|
ffe382aee2 | ||
|
|
919f71ee78 | ||
|
|
404d4476ae | ||
|
|
f2b243cd5f | ||
|
|
c2fae41355 | ||
|
|
8fda2cde9e | ||
|
|
930380cdce | ||
|
|
5b788ffe15 | ||
|
|
521c2bdde5 | ||
|
|
eee73b1218 | ||
|
|
87d6da26c9 | ||
|
|
2029cd5cd2 | ||
|
|
36be752ee6 | ||
|
|
5b3586789f | ||
|
|
6ce670e643 | ||
|
|
dd70e8139c | ||
|
|
3ac0936d1a | ||
|
|
1477bacf6a | ||
|
|
d339a18901 | ||
|
|
f9460416d9 | ||
|
|
a9112cf3da | ||
|
|
c873b49700 | ||
|
|
3c553e37d8 | ||
|
|
0c47fbb1f7 | ||
|
|
476138ef53 | ||
|
|
385ca4f0fa | ||
|
|
46fd642789 | ||
|
|
e48249c7c9 | ||
|
|
9e8535e97e | ||
|
|
a794c63a5a | ||
|
|
f3610a46a2 | ||
|
|
20fd2cf6e3 | ||
|
|
7bf345d09d | ||
|
|
17e9560449 | ||
|
|
c02e6a565e | ||
|
|
7fbc9b9bde | ||
|
|
416e97d488 | ||
|
|
753060d9f3 | ||
|
|
972c53000c | ||
|
|
2b948a49a0 | ||
|
|
7999548738 | ||
|
|
d4d13b793f | ||
|
|
210b6f0d89 | ||
|
|
7f5894b274 | ||
|
|
2dc24ab945 | ||
|
|
2f153c9974 | ||
|
|
fa22647acd | ||
|
|
dd5d82fe7a | ||
|
|
98b179aeb5 | ||
|
|
e1f1c005a0 | ||
|
|
6e226c5a4f | ||
|
|
7440fa5a37 | ||
|
|
4fe204605a | ||
|
|
4446b42b82 | ||
|
|
4b6cd17d0a | ||
|
|
1a6e74271c | ||
|
|
6ba3719031 | ||
|
|
dd95e3df7e | ||
|
|
69fd7853c8 | ||
|
|
c01c478ffe | ||
|
|
f8be1da83a | ||
|
|
3a7625486e | ||
|
|
fdc3b6c573 | ||
|
|
76939ed51f | ||
|
|
b9cf761f4a | ||
|
|
4c515ba541 | ||
|
|
d7c3595bf1 | ||
|
|
1fbd6a0824 | ||
|
|
ccb59c7f02 | ||
|
|
04bef3e82a | ||
|
|
17105b98ed | ||
|
|
4bff1515a9 | ||
|
|
0a75893346 | ||
|
|
2ed92467f9 | ||
|
|
634ac122d9 | ||
|
|
44640b7e53 | ||
|
|
47e7b22a7e | ||
|
|
918928d4bb | ||
|
|
69fc172779 | ||
|
|
d84dabbe4d | ||
|
|
23114210c4 | ||
|
|
ea80e5a223 | ||
|
|
6087f31d41 | ||
|
|
30ee292a32 | ||
|
|
705a9319f5 | ||
|
|
c789d9d87c | ||
|
|
a7681b5505 | ||
|
|
9e74d8af0b | ||
|
|
b52061f849 | ||
|
|
01b875c283 | ||
|
|
4cc3b78321 | ||
|
|
6205db87e6 | ||
|
|
518633b153 | ||
|
|
988ee7b7e7 | ||
|
|
cdadde60ce | ||
|
|
4bb01d86d9 | ||
|
|
4cac43520f | ||
|
|
d6dddd16f1 | ||
|
|
c0da054635 | ||
|
|
2b4d94ca55 | ||
|
|
e8e564738a | ||
|
|
d48fbd8b62 | ||
|
|
c1f80f209e | ||
|
|
ed6b32c827 | ||
|
|
fc436fd352 | ||
|
|
ee6fdb1ca1 | ||
|
|
988db30355 | ||
|
|
ea98ee5e99 | ||
|
|
b8d1d43822 | ||
|
|
0d017c6d14 | ||
|
|
2825e9a003 | ||
|
|
6e9ddfcbf2 | ||
|
|
378689be39 | ||
|
|
31858fad12 | ||
|
|
60351d629d | ||
|
|
715a97159a | ||
|
|
b48ce28b35 | ||
|
|
7ab0448cd3 | ||
|
|
5f6642fa63 | ||
|
|
5a0d1ed408 | ||
|
|
131e8fb6be | ||
|
|
1c7fb8ef93 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -6,7 +6,7 @@ labels: bug
|
|||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
<!--Please be aware that GNOME Code of Conduct applies to Alpaca, https://conduct.gnome.org/-->
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -6,7 +6,7 @@ labels: enhancement
|
|||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
<!--Please be aware that GNOME Code of Conduct applies to Alpaca, https://conduct.gnome.org/-->
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
|||||||
18
.github/workflows/flatpak-builder.yml
vendored
Normal file
18
.github/workflows/flatpak-builder.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# .github/workflows/flatpak-build.yml
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
name: Flatpak Build
|
||||||
|
jobs:
|
||||||
|
flatpak:
|
||||||
|
name: "Flatpak"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: bilelmoussaoui/flatpak-github-actions:gnome-46
|
||||||
|
options: --privileged
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||||
|
with:
|
||||||
|
bundle: Alpaca.flatpak
|
||||||
|
manifest-path: com.jeffser.Alpaca.json
|
||||||
|
cache-key: flatpak-builder-${{ github.sha }}
|
||||||
24
.github/workflows/pylint.yml
vendored
Normal file
24
.github/workflows/pylint.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: Pylint
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.11"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v3
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install pylint
|
||||||
|
- name: Analysing the code with pylint
|
||||||
|
run: |
|
||||||
|
pylint --rcfile=.pylintrc $(git ls-files '*.py' | grep -v 'src/available_models_descriptions.py')
|
||||||
14
.pylintrc
Normal file
14
.pylintrc
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[MASTER]
|
||||||
|
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
disable=undefined-variable, line-too-long, missing-function-docstring, consider-using-f-string, import-error
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
max-line-length=200
|
||||||
|
|
||||||
|
# Reasons for removing some checks:
|
||||||
|
# undefined-variable: _() is used by the translator on build time but it is not defined on the scripts
|
||||||
|
# line-too-long: I... I'm too lazy to make the lines shorter, maybe later
|
||||||
|
# missing-function-docstring I'm not adding a docstring to all the functions, most are self explanatory
|
||||||
|
# consider-using-f-string I can't use f-string because of the translator
|
||||||
|
# import-error The linter doesn't have access to all the libraries that the project itself does
|
||||||
34
Alpaca.doap
Normal file
34
Alpaca.doap
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||||
|
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||||
|
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||||
|
xmlns="http://usefulinc.com/ns/doap#">
|
||||||
|
|
||||||
|
<name xml:lang="en">Alpaca</name>
|
||||||
|
<shortdesc xml:lang="en">An Ollama client made with GTK4 and Adwaita</shortdesc>
|
||||||
|
<homepage rdf:resource="https://jeffser.com/alpaca" />
|
||||||
|
<bug-database rdf:resource="https://github.com/Jeffser/Alpaca/issues"/>
|
||||||
|
<programming-language>Python</programming-language>
|
||||||
|
|
||||||
|
<platform>GTK 4</platform>
|
||||||
|
<platform>Libadwaita</platform>
|
||||||
|
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Jeffry Samuel</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:jeffrysamuer@gmail.com"/>
|
||||||
|
<foaf:account>
|
||||||
|
<foaf:OnlineAccount>
|
||||||
|
<foaf:accountServiceHomepage rdf:resource="https://github.com"/>
|
||||||
|
<foaf:accountName>jeffser</foaf:accountName>
|
||||||
|
</foaf:OnlineAccount>
|
||||||
|
</foaf:account>
|
||||||
|
<foaf:account>
|
||||||
|
<foaf:OnlineAccount>
|
||||||
|
<foaf:accountServiceHomepage rdf:resource="https://gitlab.gnome.org"/>
|
||||||
|
<foaf:accountName>jeffser</foaf:accountName>
|
||||||
|
</foaf:OnlineAccount>
|
||||||
|
</foaf:account>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
</Project>
|
||||||
55
README.md
55
README.md
@@ -11,7 +11,11 @@ Alpaca is an [Ollama](https://github.com/ollama/ollama) client where you can man
|
|||||||
> [!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.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Please be aware that [GNOME Code of Conduct](https://conduct.gnome.org) applies to Alpaca before interacting with this repository.
|
||||||
|
|
||||||
## Features!
|
## Features!
|
||||||
|
|
||||||
- Talk to multiple models in the same conversation
|
- Talk to multiple models in the same conversation
|
||||||
- Pull and delete models from the app
|
- Pull and delete models from the app
|
||||||
- Image recognition
|
- Image recognition
|
||||||
@@ -21,47 +25,38 @@ Alpaca is an [Ollama](https://github.com/ollama/ollama) client where you can man
|
|||||||
- Notifications
|
- Notifications
|
||||||
- Import / Export chats
|
- Import / Export chats
|
||||||
- Delete / Edit messages
|
- Delete / Edit messages
|
||||||
|
- Regenerate messages
|
||||||
- YouTube recognition (Ask questions about a YouTube video using the transcript)
|
- YouTube recognition (Ask questions about a YouTube video using the transcript)
|
||||||
- Website recognition (Ask questions about a certain website by parsing the url)
|
- Website recognition (Ask questions about a certain website by parsing the url)
|
||||||
|
|
||||||
## Screenies
|
## Screenies
|
||||||
Chatting with a model | Image recognition | Code highlighting
|
|
||||||
:--------------------:|:-----------------:|:----------------------:
|
|
||||||
 |  | 
|
|
||||||
|
|
||||||
## Preview
|
Normal conversation | Image recognition | Code highlighting | YouTube transcription | Model management
|
||||||
1. Clone repo using Gnome Builder
|
:------------------:|:-----------------:|:-----------------:|:---------------------:|:----------------:
|
||||||
2. Press the `run` button
|
 |  |  |  | 
|
||||||
|
|
||||||
## Instalation
|
## Translators
|
||||||
1. Go to the `releases` page
|
|
||||||
2. Download the latest flatpak package
|
|
||||||
3. Open it
|
|
||||||
|
|
||||||
## Ollama session tips
|
Language | Contributors
|
||||||
|
:----------------------|:-----------
|
||||||
### Change the port of the integrated Ollama instance
|
🇷🇺 Russian | [Alex K](https://github.com/alexkdeveloper)
|
||||||
Go to `~/.var/app/com.jeffser.Alpaca/config/server.json` and change the `"local_port"` value, by default it is `11435`.
|
🇪🇸 Spanish | [Jeffry Samuel](https://github.com/jeffser)
|
||||||
|
🇫🇷 French | [Louis Chauvet-Villaret](https://github.com/loulou64490) , [Théo FORTIN](https://github.com/topiga)
|
||||||
### Backup all the chats
|
🇧🇷 Brazilian Portuguese | [Daimar Stein](https://github.com/not-a-dev-stein)
|
||||||
The chat data is located in `~/.var/app/com.jeffser.Alpaca/data/chats` you can copy that directory wherever you want to.
|
🇳🇴 Norwegian | [CounterFlow64](https://github.com/CounterFlow64)
|
||||||
|
🇮🇳 Bengali | [Aritra Saha](https://github.com/olumolu)
|
||||||
### Force showing the welcome dialog
|
🇨🇳 Simplified Chinese | [Yuehao Sui](https://github.com/8ar10der) , [Aleksana](https://github.com/Aleksanaa)
|
||||||
To do that you just need to delete the file `~/.var/app/com.jeffser.Alpaca/config/server.json`, this won't affect your saved chats or models.
|
🇮🇳 Hindi | [Aritra Saha](https://github.com/olumolu)
|
||||||
|
|
||||||
### Add/Change environment variables for Ollama
|
|
||||||
You can change anything except `$HOME` and `$OLLAMA_HOST`, to do this go to `~/.var/app/com.jeffser.Alpaca/config/server.json` and change `ollama_overrides` accordingly, some overrides are available to change on the GUI.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
- [not-a-dev-stein](https://github.com/not-a-dev-stein) for their help with requesting a new icon, bug reports and the translation to Brazilian Portuguese
|
|
||||||
|
- [not-a-dev-stein](https://github.com/not-a-dev-stein) for their help with requesting a new icon and bug reports
|
||||||
- [TylerLaBree](https://github.com/TylerLaBree) for their requests and ideas
|
- [TylerLaBree](https://github.com/TylerLaBree) for their requests and ideas
|
||||||
- [Alexkdeveloper](https://github.com/alexkdeveloper) for their help translating the app to Russian
|
|
||||||
- [Imbev](https://github.com/imbev) for their reports and suggestions
|
- [Imbev](https://github.com/imbev) for their reports and suggestions
|
||||||
- [Nokse](https://github.com/Nokse22) for their contributions to the UI and table rendering
|
- [Nokse](https://github.com/Nokse22) for their contributions to the UI and table rendering
|
||||||
- [Louis Chauvet-Villaret](https://github.com/loulou64490) for their suggestions and help translating the app to French
|
- [Louis Chauvet-Villaret](https://github.com/loulou64490) for their suggestions
|
||||||
- [CounterFlow64](https://github.com/CounterFlow64) for their help translating the app to Norwegian
|
- [Aleksana](https://github.com/Aleksanaa) for her help with better handling of directories
|
||||||
|
- Sponsors for giving me enough money to be able to take a ride to my campus every time I need to <3
|
||||||
## About forks
|
- Everyone that has shared kind words of encouragement!
|
||||||
If you want to fork this... I mean, I think it would be better if you start from scratch, my code isn't well documented at all, but if you really want to, please give me some credit, that's all I ask for... And maybe a donation (joke)
|
|
||||||
|
|||||||
@@ -122,16 +122,16 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"url": "https://github.com/ollama/ollama/releases/download/v0.3.0/ollama-linux-amd64",
|
"url": "https://github.com/ollama/ollama/releases/download/v0.3.3/ollama-linux-amd64",
|
||||||
"sha256": "b8817c34882c7ac138565836ac1995a2c61261a79315a13a0aebbfe5435da855",
|
"sha256": "2b2a4ee4c86fa5b09503e95616bd1b3ee95238b1b3bf12488b9c27c66b84061a",
|
||||||
"only-arches": [
|
"only-arches": [
|
||||||
"x86_64"
|
"x86_64"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"url": "https://github.com/ollama/ollama/releases/download/v0.3.0/ollama-linux-arm64",
|
"url": "https://github.com/ollama/ollama/releases/download/v0.3.3/ollama-linux-arm64",
|
||||||
"sha256": "64be908749212052146f1008dd3867359c776ac1766e8d86291886f53d294d4d",
|
"sha256": "28fddbea0c161bc539fd08a3dc78d51413cfe8da97386cb39420f4f30667e22c",
|
||||||
"only-arches": [
|
"only-arches": [
|
||||||
"aarch64"
|
"aarch64"
|
||||||
]
|
]
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
"sources" : [
|
"sources" : [
|
||||||
{
|
{
|
||||||
"type" : "git",
|
"type" : "git",
|
||||||
"url" : "file:///home/tentri/Documents/Alpaca",
|
"url": "https://github.com/Jeffser/Alpaca.git",
|
||||||
"branch" : "main"
|
"branch" : "main"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -70,9 +70,7 @@
|
|||||||
<caption>Multiple models being downloaded</caption>
|
<caption>Multiple models being downloaded</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<content_rating type="oars-1.1">
|
<content_rating type="oars-1.1" />
|
||||||
<content_attribute id="money-purchasing">mild</content_attribute>
|
|
||||||
</content_rating>
|
|
||||||
<url type="bugtracker">https://github.com/Jeffser/Alpaca/issues</url>
|
<url type="bugtracker">https://github.com/Jeffser/Alpaca/issues</url>
|
||||||
<url type="homepage">https://jeffser.com/alpaca/</url>
|
<url type="homepage">https://jeffser.com/alpaca/</url>
|
||||||
<url type="donation">https://github.com/sponsors/Jeffser</url>
|
<url type="donation">https://github.com/sponsors/Jeffser</url>
|
||||||
@@ -80,6 +78,59 @@
|
|||||||
<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="1.1.0" date="2024-08-10">
|
||||||
|
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/1.1.0</url>
|
||||||
|
<description>
|
||||||
|
<p>New</p>
|
||||||
|
<ul>
|
||||||
|
<li>Model manager opens faster</li>
|
||||||
|
<li>Delete chat option in secondary menu</li>
|
||||||
|
<li>New model selector popup</li>
|
||||||
|
<li>Standard shortcuts</li>
|
||||||
|
<li>Model manager is navigable with keyboard</li>
|
||||||
|
<li>Changed sidebar collapsing behavior</li>
|
||||||
|
<li>Focus indicators on messages</li>
|
||||||
|
<li>Welcome screen</li>
|
||||||
|
<li>Give message entry focus at launch</li>
|
||||||
|
<li>Generally better code</li>
|
||||||
|
</ul>
|
||||||
|
<p>Fixes</p>
|
||||||
|
<ul>
|
||||||
|
<li>Better width for dialogs</li>
|
||||||
|
<li>Better compatibility with screen readers</li>
|
||||||
|
<li>Fixed message regenerator</li>
|
||||||
|
<li>Removed 'Featured models' from welcome dialog</li>
|
||||||
|
<li>Added default buttons to dialogs</li>
|
||||||
|
<li>Fixed import / export of chats</li>
|
||||||
|
<li>Changed Python2 title to Python on code blocks</li>
|
||||||
|
<li>Prevent regeneration of title when the user changed it to a custom title</li>
|
||||||
|
<li>Show date on stopped messages</li>
|
||||||
|
<li>Fix clear chat error</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
<release version="1.0.6" date="2024-08-04">
|
||||||
|
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/1.0.6</url>
|
||||||
|
<description>
|
||||||
|
<p>New</p>
|
||||||
|
<ul>
|
||||||
|
<li>Changed shortcuts to standards</li>
|
||||||
|
<li>Moved 'Manage Models' button to primary menu</li>
|
||||||
|
<li>Stable support for GGUF model files</li>
|
||||||
|
<li>General optimizations</li>
|
||||||
|
</ul>
|
||||||
|
<p>Fixes</p>
|
||||||
|
<ul>
|
||||||
|
<li>Better handling of enter key (important for Japanese input)</li>
|
||||||
|
<li>Removed sponsor dialog</li>
|
||||||
|
<li>Added sponsor link in about dialog</li>
|
||||||
|
<li>Changed window and elements dimensions</li>
|
||||||
|
<li>Selected model changes when entering model manager</li>
|
||||||
|
<li>Better image tooltips</li>
|
||||||
|
<li>GGUF Support</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="1.0.5" date="2024-08-02">
|
<release version="1.0.5" date="2024-08-02">
|
||||||
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/1.0.5</url>
|
<url type="details">https://github.com/Jeffser/Alpaca/releases/tag/1.0.5</url>
|
||||||
<description>
|
<description>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
project('Alpaca', 'c',
|
project('Alpaca', 'c',
|
||||||
version: '1.0.5',
|
version: '1.1.0',
|
||||||
meson_version: '>= 0.62.0',
|
meson_version: '>= 0.62.0',
|
||||||
default_options: [ 'warning_level=2', 'werror=false', ],
|
default_options: [ 'warning_level=2', 'werror=false', ],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ pt_BR
|
|||||||
fr
|
fr
|
||||||
nb_NO
|
nb_NO
|
||||||
bn
|
bn
|
||||||
zh_CN
|
zh_CN
|
||||||
|
hi
|
||||||
|
|||||||
1084
po/alpaca.pot
1084
po/alpaca.pot
File diff suppressed because it is too large
Load Diff
1133
po/nb_NO.po
1133
po/nb_NO.po
File diff suppressed because it is too large
Load Diff
1108
po/pt_BR.po
1108
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1179
po/zh_CN.po
1179
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@
|
|||||||
<file alias="icons/scalable/status/edit-symbolic.svg">icons/edit-symbolic.svg</file>
|
<file alias="icons/scalable/status/edit-symbolic.svg">icons/edit-symbolic.svg</file>
|
||||||
<file alias="icons/scalable/status/image-missing-symbolic.svg">icons/image-missing-symbolic.svg</file>
|
<file alias="icons/scalable/status/image-missing-symbolic.svg">icons/image-missing-symbolic.svg</file>
|
||||||
<file alias="icons/scalable/status/update-symbolic.svg">icons/update-symbolic.svg</file>
|
<file alias="icons/scalable/status/update-symbolic.svg">icons/update-symbolic.svg</file>
|
||||||
|
<file alias="icons/scalable/status/down-symbolic.svg">icons/down-symbolic.svg</file>
|
||||||
<file preprocess="xml-stripblanks">window.ui</file>
|
<file preprocess="xml-stripblanks">window.ui</file>
|
||||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
# connection_handler.py
|
# connection_handler.py
|
||||||
import json, requests
|
"""
|
||||||
|
Handles requests to remote and integrated instances of Ollama
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
#OK=200 response.status_code
|
#OK=200 response.status_code
|
||||||
url = None
|
URL = None
|
||||||
bearer_token = None
|
BEARER_TOKEN = None
|
||||||
|
|
||||||
def get_headers(include_json:bool) -> dict:
|
def get_headers(include_json:bool) -> dict:
|
||||||
headers = {}
|
headers = {}
|
||||||
if include_json:
|
if include_json:
|
||||||
headers["Content-Type"] = "application/json"
|
headers["Content-Type"] = "application/json"
|
||||||
if bearer_token:
|
if BEARER_TOKEN:
|
||||||
headers["Authorization"] = "Bearer {}".format(bearer_token)
|
headers["Authorization"] = "Bearer {}".format(BEARER_TOKEN)
|
||||||
return headers if len(headers.keys()) > 0 else None
|
return headers if len(headers.keys()) > 0 else None
|
||||||
|
|
||||||
def simple_get(connection_url:str) -> dict:
|
def simple_get(connection_url:str) -> dict:
|
||||||
|
|||||||
101
src/dialogs.py
101
src/dialogs.py
@@ -1,11 +1,15 @@
|
|||||||
# dialogs.py
|
# dialogs.py
|
||||||
|
"""
|
||||||
from gi.repository import Adw, Gtk, Gdk, GLib, GtkSource, Gio, GdkPixbuf
|
Handles UI dialogs
|
||||||
|
"""
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
from pytube import YouTube
|
from pytube import YouTube
|
||||||
from html2text import html2text
|
from html2text import html2text
|
||||||
|
from gi.repository import Adw, Gtk
|
||||||
from . import connection_handler
|
from . import connection_handler
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
# CLEAR CHAT | WORKS
|
# CLEAR CHAT | WORKS
|
||||||
|
|
||||||
def clear_chat_response(self, dialog, task):
|
def clear_chat_response(self, dialog, task):
|
||||||
@@ -24,6 +28,7 @@ def clear_chat(self):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("clear", _("Clear"))
|
dialog.add_response("clear", _("Clear"))
|
||||||
dialog.set_response_appearance("clear", Adw.ResponseAppearance.DESTRUCTIVE)
|
dialog.set_response_appearance("clear", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||||
|
dialog.set_default_response("clear")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -45,6 +50,7 @@ def delete_chat(self, chat_name):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("delete", _("Delete"))
|
dialog.add_response("delete", _("Delete"))
|
||||||
dialog.set_response_appearance("delete", Adw.ResponseAppearance.DESTRUCTIVE)
|
dialog.set_response_appearance("delete", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||||
|
dialog.set_default_response("delete")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -54,9 +60,11 @@ def delete_chat(self, chat_name):
|
|||||||
# RENAME CHAT | WORKS
|
# RENAME CHAT | WORKS
|
||||||
|
|
||||||
def rename_chat_response(self, dialog, task, old_chat_name, entry, label_element):
|
def rename_chat_response(self, dialog, task, old_chat_name, entry, label_element):
|
||||||
if not entry: return
|
if not entry:
|
||||||
|
return
|
||||||
new_chat_name = entry.get_text()
|
new_chat_name = entry.get_text()
|
||||||
if old_chat_name == new_chat_name: return
|
if old_chat_name == new_chat_name:
|
||||||
|
return
|
||||||
if new_chat_name and (task is None or dialog.choose_finish(task) == "rename"):
|
if new_chat_name and (task is None or dialog.choose_finish(task) == "rename"):
|
||||||
self.rename_chat(old_chat_name, new_chat_name, label_element)
|
self.rename_chat(old_chat_name, new_chat_name, label_element)
|
||||||
|
|
||||||
@@ -68,10 +76,10 @@ def rename_chat(self, chat_name, label_element):
|
|||||||
extra_child=entry,
|
extra_child=entry,
|
||||||
close_response="cancel"
|
close_response="cancel"
|
||||||
)
|
)
|
||||||
entry.connect("activate", lambda dialog, old_chat_name=chat_name, entry=entry, label_element=label_element: rename_chat_response(self, dialog, None, old_chat_name, entry, label_element))
|
|
||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("rename", _("Rename"))
|
dialog.add_response("rename", _("Rename"))
|
||||||
dialog.set_response_appearance("rename", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("rename", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("rename")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -82,7 +90,8 @@ def rename_chat(self, chat_name, label_element):
|
|||||||
|
|
||||||
def new_chat_response(self, dialog, task, entry):
|
def new_chat_response(self, dialog, task, entry):
|
||||||
chat_name = _("New Chat")
|
chat_name = _("New Chat")
|
||||||
if entry is not None and entry.get_text() != "": chat_name = entry.get_text()
|
if entry is not None and entry.get_text() != "":
|
||||||
|
chat_name = entry.get_text()
|
||||||
if chat_name and (task is None or dialog.choose_finish(task) == "create"):
|
if chat_name and (task is None or dialog.choose_finish(task) == "create"):
|
||||||
self.new_chat(chat_name)
|
self.new_chat(chat_name)
|
||||||
|
|
||||||
@@ -95,10 +104,10 @@ def new_chat(self):
|
|||||||
extra_child=entry,
|
extra_child=entry,
|
||||||
close_response="cancel"
|
close_response="cancel"
|
||||||
)
|
)
|
||||||
entry.connect("activate", lambda dialog, entry: new_chat_response(self, dialog, None, entry))
|
|
||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("create", _("Create"))
|
dialog.add_response("create", _("Create"))
|
||||||
dialog.set_response_appearance("create", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("create", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("create")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -121,6 +130,7 @@ def stop_pull_model(self, model_name):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("stop", _("Stop"))
|
dialog.add_response("stop", _("Stop"))
|
||||||
dialog.set_response_appearance("stop", Adw.ResponseAppearance.DESTRUCTIVE)
|
dialog.set_response_appearance("stop", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||||
|
dialog.set_default_response("stop")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self.manage_models_dialog,
|
parent = self.manage_models_dialog,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -142,6 +152,7 @@ def delete_model(self, model_name):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("delete", _("Delete"))
|
dialog.add_response("delete", _("Delete"))
|
||||||
dialog.set_response_appearance("delete", Adw.ResponseAppearance.DESTRUCTIVE)
|
dialog.set_response_appearance("delete", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||||
|
dialog.set_default_response("delete")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self.manage_models_dialog,
|
parent = self.manage_models_dialog,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -164,6 +175,7 @@ def remove_attached_file(self, name):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("remove", _("Remove"))
|
dialog.add_response("remove", _("Remove"))
|
||||||
dialog.set_response_appearance("remove", Adw.ResponseAppearance.DESTRUCTIVE)
|
dialog.set_response_appearance("remove", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||||
|
dialog.set_default_response("remove")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -203,11 +215,11 @@ def reconnect_remote(self, current_url, current_bearer_token):
|
|||||||
body=_("The remote instance has disconnected"),
|
body=_("The remote instance has disconnected"),
|
||||||
extra_child=container
|
extra_child=container
|
||||||
)
|
)
|
||||||
#entry.connect("activate", lambda entry, dialog: reconnect_remote_response(self, dialog, None, entry))
|
|
||||||
dialog.add_response("close", _("Close Alpaca"))
|
dialog.add_response("close", _("Close Alpaca"))
|
||||||
dialog.add_response("local", _("Use local instance"))
|
dialog.add_response("local", _("Use local instance"))
|
||||||
dialog.add_response("remote", _("Connect"))
|
dialog.add_response("remote", _("Connect"))
|
||||||
dialog.set_response_appearance("remote", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("remote", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("remote")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -236,6 +248,7 @@ def create_model_from_existing(self):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("accept", _("Accept"))
|
dialog.add_response("accept", _("Accept"))
|
||||||
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("accept")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -243,15 +256,15 @@ def create_model_from_existing(self):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def create_model_from_file_response(self, file_dialog, result):
|
def create_model_from_file_response(self, file_dialog, result):
|
||||||
try: file = file_dialog.open_finish(result)
|
|
||||||
except:
|
|
||||||
self.logger.error(e)
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
self.create_model(file.get_path(), True)
|
file = file_dialog.open_finish(result)
|
||||||
|
try:
|
||||||
|
self.create_model(file.get_path(), True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
self.show_toast(_("An error occurred while creating the model"), self.main_overlay)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(e)
|
logger.error(e)
|
||||||
self.show_toast(_("An error occurred while creating the model"), self.main_overlay)
|
|
||||||
|
|
||||||
def create_model_from_file(self):
|
def create_model_from_file(self):
|
||||||
file_dialog = Gtk.FileDialog(default_filter=self.file_filter_gguf)
|
file_dialog = Gtk.FileDialog(default_filter=self.file_filter_gguf)
|
||||||
@@ -264,7 +277,7 @@ def create_model_from_name_response(self, dialog, task, entry):
|
|||||||
|
|
||||||
def create_model_from_name(self):
|
def create_model_from_name(self):
|
||||||
entry = Gtk.Entry()
|
entry = Gtk.Entry()
|
||||||
entry.get_delegate().connect("insert-text", self.check_alphanumeric)
|
entry.get_delegate().connect("insert-text", lambda *_ : self.check_alphanumeric(*_, ['-', '.', ':', '_', '/']))
|
||||||
dialog = Adw.AlertDialog(
|
dialog = Adw.AlertDialog(
|
||||||
heading=_("Pull Model"),
|
heading=_("Pull Model"),
|
||||||
body=_("Input the name of the model in this format\nname:tag"),
|
body=_("Input the name of the model in this format\nname:tag"),
|
||||||
@@ -273,6 +286,7 @@ def create_model_from_name(self):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("accept", _("Accept"))
|
dialog.add_response("accept", _("Accept"))
|
||||||
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("accept")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -286,24 +300,24 @@ def attach_file_response(self, file_dialog, result):
|
|||||||
"image": ["png", "jpeg", "jpg", "webp", "gif"],
|
"image": ["png", "jpeg", "jpg", "webp", "gif"],
|
||||||
"pdf": ["pdf"]
|
"pdf": ["pdf"]
|
||||||
}
|
}
|
||||||
try: file = file_dialog.open_finish(result)
|
try:
|
||||||
except:
|
file = file_dialog.open_finish(result)
|
||||||
self.logger.error(e)
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
return
|
return
|
||||||
extension = file.get_path().split(".")[-1]
|
extension = file.get_path().split(".")[-1]
|
||||||
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: return
|
if not file_type:
|
||||||
|
return
|
||||||
if file_type == 'image' and not self.verify_if_image_can_be_used():
|
if file_type == 'image' and not self.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)
|
||||||
|
|
||||||
|
def attach_file(self, file_filter):
|
||||||
def attach_file(self, filter):
|
file_dialog = Gtk.FileDialog(default_filter=file_filter)
|
||||||
file_dialog = Gtk.FileDialog(default_filter=filter)
|
|
||||||
file_dialog.open(self, None, lambda file_dialog, result: attach_file_response(self, file_dialog, result))
|
file_dialog.open(self, None, lambda file_dialog, result: attach_file_response(self, file_dialog, result))
|
||||||
|
|
||||||
|
|
||||||
# YouTube caption | WORKS
|
# YouTube caption | WORKS
|
||||||
|
|
||||||
def youtube_caption_response(self, dialog, task, video_url, caption_drop_down):
|
def youtube_caption_response(self, dialog, task, video_url, caption_drop_down):
|
||||||
@@ -321,7 +335,7 @@ def youtube_caption_response(self, dialog, task, video_url, caption_drop_down):
|
|||||||
if not os.path.exists(os.path.join(self.cache_dir, 'tmp/youtube')):
|
if not os.path.exists(os.path.join(self.cache_dir, 'tmp/youtube')):
|
||||||
os.makedirs(os.path.join(self.cache_dir, 'tmp/youtube'))
|
os.makedirs(os.path.join(self.cache_dir, 'tmp/youtube'))
|
||||||
file_path = os.path.join(os.path.join(self.cache_dir, 'tmp/youtube'), f'{yt.title} ({selected_caption.split(" | ")[0]})')
|
file_path = os.path.join(os.path.join(self.cache_dir, 'tmp/youtube'), f'{yt.title} ({selected_caption.split(" | ")[0]})')
|
||||||
with open(file_path, 'w+') as f:
|
with open(file_path, 'w+', encoding="utf-8") as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
self.attach_file(file_path, 'youtube')
|
self.attach_file(file_path, 'youtube')
|
||||||
|
|
||||||
@@ -333,7 +347,8 @@ def youtube_caption(self, video_url):
|
|||||||
self.show_toast(_("This video does not have any transcriptions"), self.main_overlay)
|
self.show_toast(_("This video does not have any transcriptions"), self.main_overlay)
|
||||||
return
|
return
|
||||||
caption_list = Gtk.StringList()
|
caption_list = Gtk.StringList()
|
||||||
for caption in captions: caption_list.append("{} | {}".format(caption.name, caption.code))
|
for caption in captions:
|
||||||
|
caption_list.append("{} | {}".format(caption.name, caption.code))
|
||||||
caption_drop_down = Gtk.DropDown(
|
caption_drop_down = Gtk.DropDown(
|
||||||
enable_search=True,
|
enable_search=True,
|
||||||
model=caption_list
|
model=caption_list
|
||||||
@@ -347,6 +362,7 @@ def youtube_caption(self, video_url):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("accept", _("Accept"))
|
dialog.add_response("accept", _("Accept"))
|
||||||
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("accept")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
@@ -369,7 +385,7 @@ def attach_website_response(self, dialog, task, url):
|
|||||||
os.makedirs('/tmp/alpaca/websites/')
|
os.makedirs('/tmp/alpaca/websites/')
|
||||||
md_name = self.generate_numbered_name('website.md', os.listdir('/tmp/alpaca/websites'))
|
md_name = self.generate_numbered_name('website.md', os.listdir('/tmp/alpaca/websites'))
|
||||||
file_path = os.path.join('/tmp/alpaca/websites/', md_name)
|
file_path = os.path.join('/tmp/alpaca/websites/', md_name)
|
||||||
with open(file_path, 'w+') as f:
|
with open(file_path, 'w+', encoding="utf-8") as f:
|
||||||
f.write('{}\n\n{}'.format(url, md))
|
f.write('{}\n\n{}'.format(url, md))
|
||||||
self.attach_file(file_path, 'website')
|
self.attach_file(file_path, 'website')
|
||||||
else:
|
else:
|
||||||
@@ -385,38 +401,9 @@ def attach_website(self, url):
|
|||||||
dialog.add_response("cancel", _("Cancel"))
|
dialog.add_response("cancel", _("Cancel"))
|
||||||
dialog.add_response("accept", _("Accept"))
|
dialog.add_response("accept", _("Accept"))
|
||||||
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
|
||||||
|
dialog.set_default_response("accept")
|
||||||
dialog.choose(
|
dialog.choose(
|
||||||
parent = self,
|
parent = self,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
callback = lambda dialog, task, url=url: attach_website_response(self, dialog, task, url)
|
callback = lambda dialog, task, url=url: attach_website_response(self, dialog, task, url)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Begging for money :3
|
|
||||||
|
|
||||||
def support_response(self, dialog, task):
|
|
||||||
res = dialog.choose_finish(task)
|
|
||||||
if res == 'later': return
|
|
||||||
elif res == 'support':
|
|
||||||
self.show_toast(_("Thank you!"), self.main_overlay)
|
|
||||||
os.system('xdg-open https://github.com/sponsors/Jeffser')
|
|
||||||
elif res == 'nope':
|
|
||||||
self.show_toast(_("Visit Alpaca's website if you change your mind!"), self.main_overlay)
|
|
||||||
self.show_support = False
|
|
||||||
self.save_server_config()
|
|
||||||
|
|
||||||
def support(self):
|
|
||||||
dialog = Adw.AlertDialog(
|
|
||||||
heading=_("Support"),
|
|
||||||
body=_("Are you enjoying Alpaca? Consider sponsoring the project!"),
|
|
||||||
close_response="nope"
|
|
||||||
)
|
|
||||||
dialog.add_response("nope", _("Don't show again"))
|
|
||||||
dialog.set_response_appearance("nope", Adw.ResponseAppearance.DESTRUCTIVE)
|
|
||||||
dialog.add_response("later", _("Later"))
|
|
||||||
dialog.add_response("support", _("Support"))
|
|
||||||
dialog.set_response_appearance("support", Adw.ResponseAppearance.SUGGESTED)
|
|
||||||
dialog.choose(
|
|
||||||
parent = self,
|
|
||||||
cancellable = None,
|
|
||||||
callback = lambda dialog, task: support_response(self, dialog, task)
|
|
||||||
)
|
|
||||||
|
|||||||
2
src/icons/down-symbolic.svg
Normal file
2
src/icons/down-symbolic.svg
Normal 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 2.292969 6.707031 l 5 5 c 0.390625 0.390625 1.023437 0.390625 1.414062 0 l 5 -5 c 0.390625 -0.390625 0.390625 -1.023437 0 -1.414062 s -1.023437 -0.390625 -1.414062 0 l -4.292969 4.292969 l -4.292969 -4.292969 c -0.390625 -0.390625 -1.023437 -0.390625 -1.414062 0 s -0.390625 1.023437 0 1.414062 z m 0 0" fill="#222222" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 484 B |
25
src/internal.py
Normal file
25
src/internal.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# internal.py
|
||||||
|
"""
|
||||||
|
Handles paths, they can be different if the app is running as a Flatpak
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
APP_ID = "com.jeffser.Alpaca"
|
||||||
|
|
||||||
|
IN_FLATPAK = bool(os.getenv("FLATPAK_ID"))
|
||||||
|
|
||||||
|
def get_xdg_home(env, default):
|
||||||
|
if IN_FLATPAK:
|
||||||
|
return os.getenv(env)
|
||||||
|
base = os.getenv(env) or os.path.expanduser(default)
|
||||||
|
path = os.path.join(base, APP_ID)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
data_dir = get_xdg_home("XDG_DATA_HOME", "~/.local/share")
|
||||||
|
config_dir = get_xdg_home("XDG_CONFIG_HOME", "~/.config")
|
||||||
|
cache_dir = get_xdg_home("XDG_CACHE_HOME", "~/.cache")
|
||||||
|
|
||||||
|
source_dir = os.path.abspath(os.path.dirname(__file__))
|
||||||
@@ -1,29 +1,35 @@
|
|||||||
# local_instance.py
|
# local_instance.py
|
||||||
import subprocess, os, threading
|
"""
|
||||||
|
Handles running, stopping and resetting the integrated Ollama instance
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
from .internal import data_dir, cache_dir
|
||||||
|
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
instance = None
|
instance = None
|
||||||
port = 11435
|
port = 11435
|
||||||
data_dir = os.getenv("XDG_DATA_HOME")
|
|
||||||
overrides = {}
|
overrides = {}
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
if not os.path.isdir(os.path.join(os.getenv("XDG_CACHE_HOME"), 'tmp/ollama')):
|
if not os.path.isdir(os.path.join(cache_dir, 'tmp/ollama')):
|
||||||
os.mkdir(os.path.join(os.getenv("XDG_CACHE_HOME"), 'tmp/ollama'))
|
os.mkdir(os.path.join(cache_dir, 'tmp/ollama'))
|
||||||
global instance, overrides
|
global instance
|
||||||
params = overrides.copy()
|
params = overrides.copy()
|
||||||
params["OLLAMA_HOST"] = f"127.0.0.1:{port}" # You can't change this directly sorry :3
|
params["OLLAMA_HOST"] = f"127.0.0.1:{port}" # You can't change this directly sorry :3
|
||||||
params["HOME"] = data_dir
|
params["HOME"] = data_dir
|
||||||
params["TMPDIR"] = os.path.join(os.getenv("XDG_CACHE_HOME"), 'tmp/ollama')
|
params["TMPDIR"] = os.path.join(cache_dir, 'tmp/ollama')
|
||||||
instance = subprocess.Popen(["/app/bin/ollama", "serve"], env={**os.environ, **params}, stderr=subprocess.PIPE, text=True)
|
instance = subprocess.Popen(["ollama", "serve"], env={**os.environ, **params}, stderr=subprocess.PIPE, text=True)
|
||||||
logger.info("Starting Alpaca's Ollama instance...")
|
logger.info("Starting Alpaca's Ollama instance...")
|
||||||
logger.debug(params)
|
logger.debug(params)
|
||||||
sleep(1)
|
sleep(1)
|
||||||
logger.info("Started Alpaca's Ollama instance")
|
logger.info("Started Alpaca's Ollama instance")
|
||||||
|
v_str = subprocess.check_output("ollama -v", shell=True).decode('utf-8')
|
||||||
|
logger.info('Ollama version: {}'.format(v_str.split('client version is ')[1].strip()))
|
||||||
|
|
||||||
def stop():
|
def stop():
|
||||||
logger.info("Stopping Alpaca's Ollama instance")
|
logger.info("Stopping Alpaca's Ollama instance")
|
||||||
@@ -39,4 +45,3 @@ def reset():
|
|||||||
stop()
|
stop()
|
||||||
sleep(1)
|
sleep(1)
|
||||||
start()
|
start()
|
||||||
|
|
||||||
|
|||||||
52
src/main.py
52
src/main.py
@@ -16,21 +16,36 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
"""
|
||||||
|
Main script run at launch, handles actions, about dialog and the app itself (not the window)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '4.0')
|
||||||
|
gi.require_version('Adw', '1')
|
||||||
|
from gi.repository import Gtk, Gio, Adw, GLib
|
||||||
|
|
||||||
|
from .window import AlpacaWindow
|
||||||
|
from .internal import cache_dir, data_dir
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
import gi
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
gi.require_version('Gtk', '4.0')
|
|
||||||
gi.require_version('Adw', '1')
|
|
||||||
|
|
||||||
from gi.repository import Gtk, Gio, Adw, GLib
|
|
||||||
from .window import AlpacaWindow
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
translators = [
|
||||||
|
'Alex K (Russian) https://github.com/alexkdeveloper',
|
||||||
|
'Jeffry Samuel (Spanish) https://github.com/jeffser',
|
||||||
|
'Louis Chauvet-Villaret (French) https://github.com/loulou64490',
|
||||||
|
'Théo FORTIN (French) https://github.com/topiga',
|
||||||
|
'Daimar Stein (Brazilian Portuguese) https://github.com/not-a-dev-stein',
|
||||||
|
'CounterFlow64 (Norwegian) https://github.com/CounterFlow64',
|
||||||
|
'Aritra Saha (Bengali) https://github.com/olumolu',
|
||||||
|
'Yuehao Sui (Simplified Chinese) https://github.com/8ar10der',
|
||||||
|
'Aleksana (Simplified Chinese) https://github.com/Aleksanaa',
|
||||||
|
'Aritra Saha (Hindi) https://github.com/olumolu'
|
||||||
|
]
|
||||||
|
|
||||||
class AlpacaApplication(Adw.Application):
|
class AlpacaApplication(Adw.Application):
|
||||||
"""The main application singleton class."""
|
"""The main application singleton class."""
|
||||||
@@ -38,8 +53,8 @@ class AlpacaApplication(Adw.Application):
|
|||||||
def __init__(self, version):
|
def __init__(self, version):
|
||||||
super().__init__(application_id='com.jeffser.Alpaca',
|
super().__init__(application_id='com.jeffser.Alpaca',
|
||||||
flags=Gio.ApplicationFlags.DEFAULT_FLAGS)
|
flags=Gio.ApplicationFlags.DEFAULT_FLAGS)
|
||||||
self.create_action('quit', lambda *_: self.quit(), ['<primary>q'])
|
self.create_action('quit', lambda *_: self.quit(), ['<primary>w', '<primary>q'])
|
||||||
self.create_action('preferences', lambda *_: AlpacaWindow.show_preferences_dialog(self.props.active_window), ['<primary>p'])
|
self.create_action('preferences', lambda *_: AlpacaWindow.show_preferences_dialog(self.props.active_window), ['<primary>comma'])
|
||||||
self.create_action('about', self.on_about_action)
|
self.create_action('about', self.on_about_action)
|
||||||
self.version = version
|
self.version = version
|
||||||
|
|
||||||
@@ -58,12 +73,13 @@ class AlpacaApplication(Adw.Application):
|
|||||||
support_url="https://github.com/Jeffser/Alpaca/discussions/155",
|
support_url="https://github.com/Jeffser/Alpaca/discussions/155",
|
||||||
developers=['Jeffser https://jeffser.com'],
|
developers=['Jeffser https://jeffser.com'],
|
||||||
designers=['Jeffser https://jeffser.com', 'Tobias Bernard (App Icon) https://tobiasbernard.com/'],
|
designers=['Jeffser https://jeffser.com', 'Tobias Bernard (App Icon) https://tobiasbernard.com/'],
|
||||||
translator_credits='Alex K (Russian) https://github.com/alexkdeveloper\nJeffser (Spanish) https://jeffser.com\nDaimar Stein (Brazilian Portuguese) https://github.com/not-a-dev-stein\nLouis Chauvet-Villaret (French) https://github.com/loulou64490\nCounterFlow64 (Norwegian) https://github.com/CounterFlow64\nAritra Saha (Bengali) https://github.com/olumolu\nYuehao Sui (Simplified Chinese) https://github.com/8ar10der',
|
translator_credits='\n'.join(translators),
|
||||||
copyright='© 2024 Jeffser\n© 2024 Ollama',
|
copyright='© 2024 Jeffser\n© 2024 Ollama',
|
||||||
issue_url='https://github.com/Jeffser/Alpaca/issues',
|
issue_url='https://github.com/Jeffser/Alpaca/issues',
|
||||||
license_type=3,
|
license_type=3,
|
||||||
website="https://jeffser.com/alpaca",
|
website="https://jeffser.com/alpaca",
|
||||||
debug_info=open(os.path.join(os.getenv("XDG_DATA_HOME"), 'tmp.log'), 'r').read())
|
debug_info=open(os.path.join(data_dir, 'tmp.log'), 'r').read())
|
||||||
|
about.add_link("Become a Sponsor", "https://github.com/sponsors/Jeffser")
|
||||||
about.present(parent=self.props.active_window)
|
about.present(parent=self.props.active_window)
|
||||||
|
|
||||||
def create_action(self, name, callback, shortcuts=None):
|
def create_action(self, name, callback, shortcuts=None):
|
||||||
@@ -75,16 +91,16 @@ class AlpacaApplication(Adw.Application):
|
|||||||
|
|
||||||
|
|
||||||
def main(version):
|
def main(version):
|
||||||
if os.path.isfile(os.path.join(os.getenv("XDG_DATA_HOME"), 'tmp.log')):
|
if os.path.isfile(os.path.join(data_dir, 'tmp.log')):
|
||||||
os.remove(os.path.join(os.getenv("XDG_DATA_HOME"), 'tmp.log'))
|
os.remove(os.path.join(data_dir, 'tmp.log'))
|
||||||
if os.path.isdir(os.path.join(os.getenv("XDG_CACHE_HOME"), 'tmp')):
|
if os.path.isdir(os.path.join(cache_dir, 'tmp')):
|
||||||
os.system('rm -rf ' + os.path.join(os.getenv("XDG_CACHE_HOME"), "tmp/*"))
|
os.system('rm -rf ' + os.path.join(cache_dir, "tmp/*"))
|
||||||
else:
|
else:
|
||||||
os.mkdir(os.path.join(os.getenv("XDG_CACHE_HOME"), 'tmp'))
|
os.mkdir(os.path.join(cache_dir, 'tmp'))
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format="%(levelname)s\t[%(filename)s | %(funcName)s] %(message)s",
|
format="%(levelname)s\t[%(filename)s | %(funcName)s] %(message)s",
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
handlers=[logging.FileHandler(filename=os.path.join(os.getenv("XDG_DATA_HOME"), 'tmp.log')), logging.StreamHandler(stream=sys.stdout)]
|
handlers=[logging.FileHandler(filename=os.path.join(data_dir, 'tmp.log')), logging.StreamHandler(stream=sys.stdout)]
|
||||||
)
|
)
|
||||||
app = AlpacaApplication(version)
|
app = AlpacaApplication(version)
|
||||||
logger.info(f"Alpaca version: {app.version}")
|
logger.info(f"Alpaca version: {app.version}")
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ alpaca_sources = [
|
|||||||
'local_instance.py',
|
'local_instance.py',
|
||||||
'available_models.json',
|
'available_models.json',
|
||||||
'available_models_descriptions.py',
|
'available_models_descriptions.py',
|
||||||
'table_widget.py'
|
'table_widget.py',
|
||||||
|
'internal.py'
|
||||||
]
|
]
|
||||||
|
|
||||||
install_data(alpaca_sources, install_dir: moduledir)
|
install_data(alpaca_sources, install_dir: moduledir)
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
.message_input_scroll_window > * {
|
|
||||||
box-shadow: none;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.message_text_view, .modelfile_textview {
|
.message_text_view, .modelfile_textview {
|
||||||
background-color: rgba(0,0,0,0);
|
background-color: rgba(0,0,0,0);
|
||||||
}
|
}
|
||||||
@@ -12,3 +8,19 @@
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
.model_list_box {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.manage_models_button {
|
||||||
|
padding: 6px 8px 6px 8px;
|
||||||
|
}
|
||||||
|
.model_list_box > * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.user_message, .response_message {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.user_message:focus, .response_message:focus, .editing_message_textview:focus, .code_block:focus {
|
||||||
|
box-shadow: 0 0 1px 2px mix(@accent_color, @window_bg_color, 0.5);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
#table_widget.py
|
||||||
|
"""
|
||||||
|
Handles the table widget shown in chat responses
|
||||||
|
"""
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
from gi.repository import Adw
|
gi.require_version('Gtk', '4.0')
|
||||||
from gi.repository import Gtk, GObject, Gio
|
from gi.repository import Gtk, GObject, Gio
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|||||||
736
src/window.py
736
src/window.py
File diff suppressed because it is too large
Load Diff
329
src/window.ui
329
src/window.ui
@@ -5,32 +5,21 @@
|
|||||||
<template class="AlpacaWindow" parent="AdwApplicationWindow">
|
<template class="AlpacaWindow" parent="AdwApplicationWindow">
|
||||||
<signal name="close-request" handler="closing_app"/>
|
<signal name="close-request" handler="closing_app"/>
|
||||||
<property name="resizable">True</property>
|
<property name="resizable">True</property>
|
||||||
<property name="width-request">360</property>
|
<property name="width-request">400</property>
|
||||||
<property name="height-request">400</property>
|
<property name="height-request">400</property>
|
||||||
<property name="default-width">1300</property>
|
<property name="default-width">1300</property>
|
||||||
<property name="default-height">800</property>
|
<property name="default-height">800</property>
|
||||||
<property name="title">Alpaca</property>
|
<property name="title">Alpaca</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwBreakpoint">
|
<object class="AdwBreakpoint">
|
||||||
<condition>max-width: 800sp</condition>
|
<condition>max-width: 690sp</condition>
|
||||||
<setter object="split_view_overlay" property="collapsed">true</setter>
|
<setter object="split_view_overlay" property="collapsed">true</setter>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="AdwBreakpoint">
|
|
||||||
<condition>max-width: 500sp</condition>
|
|
||||||
<setter object="split_view_overlay" property="collapsed">true</setter>
|
|
||||||
<setter object="welcome_dialog" property="width-request">360</setter>
|
|
||||||
<setter object="manage_models_dialog" property="width-request">360</setter>
|
|
||||||
<setter object="preferences_dialog" property="width-request">360</setter>
|
|
||||||
<setter object="file_preview_dialog" property="width-request">360</setter>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<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">
|
<property name="sidebar">
|
||||||
<object class="AdwToolbarView">
|
<object class="AdwToolbarView">
|
||||||
<child type="top">
|
<child type="top">
|
||||||
@@ -87,28 +76,79 @@
|
|||||||
<property name="orientation">0</property>
|
<property name="orientation">0</property>
|
||||||
<property name="spacing">12</property>
|
<property name="spacing">12</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkDropDown" id="model_drop_down">
|
<object class="GtkMenuButton" id="model_selector_button">
|
||||||
<signal name="notify" handler="verify_if_image_can_be_used"/>
|
<property name="tooltip-text" translatable="yes">Select Model</property>
|
||||||
<property name="width-request">175</property>
|
<property name="child">
|
||||||
<property name="enable-search">true</property>
|
<object class="GtkBox">
|
||||||
<property name="tooltip-text">Select Model</property>
|
<property name="spacing">10</property>
|
||||||
<property name="model">
|
<child>
|
||||||
<object class="GtkStringList" id="model_string_list">
|
<object class="GtkLabel">
|
||||||
<items>
|
<property name="label" translatable="yes">Select a Model</property>
|
||||||
</items>
|
<property name="ellipsize">2</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="icon-name">down-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</property>
|
</property>
|
||||||
</object>
|
<property name="halign">1</property>
|
||||||
</child>
|
<style>
|
||||||
<child>
|
<class name="raised"/>
|
||||||
<object class="GtkButton" id="manage_models_button">
|
</style>
|
||||||
<signal name="clicked" handler="manage_models_button_activate"/>
|
<property name="popover">
|
||||||
<property name="tooltip-text" translatable="yes">Manage Models</property>
|
<object class="GtkPopover" id="model_popover">
|
||||||
<child>
|
<property name="has-arrow">false</property>
|
||||||
<object class="AdwButtonContent">
|
<child>
|
||||||
<property name="icon-name">brain-augemnted-symbolic</property>
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">1</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton">
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="yes">Manage Models</property>
|
||||||
|
<property name="justify">left</property>
|
||||||
|
<property name="halign">1</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
<property name="hexpand">true</property>
|
||||||
|
<property name="tooltip-text" translatable="yes">Manage Models</property>
|
||||||
|
<property name="action-name">app.manage_models</property>
|
||||||
|
<signal name="clicked" handler="close_model_popup"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
<class name="manage_models_button"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSeparator"/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="max-content-height">300</property>
|
||||||
|
<property name="propagate-natural-width">true</property>
|
||||||
|
<property name="propagate-natural-height">true</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox" id="model_list_box">
|
||||||
|
<property name="hexpand">true</property>
|
||||||
|
<style>
|
||||||
|
<class name="navigation-sidebar"/>
|
||||||
|
<class name="model_list_box"/>
|
||||||
|
</style>
|
||||||
|
<signal name="row-selected" handler="change_model"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -227,6 +267,10 @@
|
|||||||
<property name="top-margin">10</property>
|
<property name="top-margin">10</property>
|
||||||
<property name="bottom-margin">10</property>
|
<property name="bottom-margin">10</property>
|
||||||
<property name="hexpand">true</property>
|
<property name="hexpand">true</property>
|
||||||
|
<property name="input-hints">spellcheck</property>
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">Message text box</property>
|
||||||
|
</accessibility>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -454,6 +498,9 @@
|
|||||||
</object>
|
</object>
|
||||||
|
|
||||||
<object class="AdwDialog" id="manage_models_dialog">
|
<object class="AdwDialog" id="manage_models_dialog">
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">Manage models dialog</property>
|
||||||
|
</accessibility>
|
||||||
<property name="can-close">true</property>
|
<property name="can-close">true</property>
|
||||||
<property name="width-request">400</property>
|
<property name="width-request">400</property>
|
||||||
<property name="height-request">600</property>
|
<property name="height-request">600</property>
|
||||||
@@ -488,12 +535,18 @@
|
|||||||
</child>
|
</child>
|
||||||
<child type="top">
|
<child type="top">
|
||||||
<object class="GtkSearchBar" id="model_searchbar">
|
<object class="GtkSearchBar" id="model_searchbar">
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">Model search bar</property>
|
||||||
|
</accessibility>
|
||||||
<property name="key-capture-widget">AlpacaWindow</property>
|
<property name="key-capture-widget">AlpacaWindow</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkSearchEntry" id="searchentry">
|
<object class="GtkSearchEntry" id="searchentry">
|
||||||
<signal name="search-changed" handler="model_search_changed"/>
|
<signal name="search-changed" handler="model_search_changed"/>
|
||||||
<property name="search-delay">100</property>
|
<property name="search-delay">100</property>
|
||||||
<property name="placeholder-text" translatable="yes">Search models</property>
|
<property name="placeholder-text" translatable="yes">Search models</property>
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">Search models</property>
|
||||||
|
</accessibility>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -529,7 +582,7 @@
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkListBox" id="available_model_list_box">
|
<object class="GtkListBox" id="available_model_list_box">
|
||||||
<property name="selection-mode">single</property>
|
<property name="selection-mode">none</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="boxed-list"/>
|
<class name="boxed-list"/>
|
||||||
</style>
|
</style>
|
||||||
@@ -592,7 +645,7 @@
|
|||||||
<child>
|
<child>
|
||||||
<object class="GtkListBox" id="model_tag_list_box">
|
<object class="GtkListBox" id="model_tag_list_box">
|
||||||
<property name="valign">1</property>
|
<property name="valign">1</property>
|
||||||
<property name="selection-mode">single</property>
|
<property name="selection-mode">none</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="boxed-list"/>
|
<class name="boxed-list"/>
|
||||||
</style>
|
</style>
|
||||||
@@ -750,9 +803,12 @@
|
|||||||
</object>
|
</object>
|
||||||
|
|
||||||
<object class="AdwDialog" id="file_preview_dialog">
|
<object class="AdwDialog" id="file_preview_dialog">
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">File preview dialog</property>
|
||||||
|
</accessibility>
|
||||||
<property name="can-close">true</property>
|
<property name="can-close">true</property>
|
||||||
<property name="width-request">450</property>
|
<property name="width-request">400</property>
|
||||||
<property name="height-request">450</property>
|
<property name="height-request">600</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwToolbarView">
|
<object class="AdwToolbarView">
|
||||||
<child type="top">
|
<child type="top">
|
||||||
@@ -817,8 +873,8 @@
|
|||||||
|
|
||||||
<object class="AdwDialog" id="welcome_dialog">
|
<object class="AdwDialog" id="welcome_dialog">
|
||||||
<property name="can-close">false</property>
|
<property name="can-close">false</property>
|
||||||
<property name="width-request">450</property>
|
<property name="width-request">400</property>
|
||||||
<property name="height-request">450</property>
|
<property name="height-request">600</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwToolbarView">
|
<object class="AdwToolbarView">
|
||||||
<child type="bottom">
|
<child type="bottom">
|
||||||
@@ -897,141 +953,6 @@
|
|||||||
<property name="description" translatable="yes">Alpaca and its developers are not liable for any damages to devices or software resulting from the execution of code generated by an AI model. Please exercise caution and review the code carefully before running it.</property>
|
<property name="description" translatable="yes">Alpaca and its developers are not liable for any damages to devices or software resulting from the execution of code generated by an AI model. Please exercise caution and review the code carefully before running it.</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="AdwStatusPage">
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="vexpand">true</property>
|
|
||||||
<property name="margin-top">12</property>
|
|
||||||
<property name="margin-bottom">12</property>
|
|
||||||
<property name="margin-start">12</property>
|
|
||||||
<property name="margin-end">12</property>
|
|
||||||
<property name="title" translatable="yes">Featured Models</property>
|
|
||||||
<property name="description" translatable="yes">Alpaca works locally on your device, to start chatting you'll need an AI model, you can either pull models from this list or the 'Manage Models' menu later.
|
|
||||||
|
|
||||||
By downloading any model you accept their license agreement available on the model's website.
|
|
||||||
</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkListBox">
|
|
||||||
<property name="selection-mode">none</property>
|
|
||||||
<style>
|
|
||||||
<class name="boxed-list"/>
|
|
||||||
</style>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title" translatable="no">Llama3</property>
|
|
||||||
<property name="subtitle" translatable="yes">Built by Meta</property>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="link_button_handler"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">globe-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="name">https://ollama.com/library/llama3</property>
|
|
||||||
<property name="tooltip-text">https://ollama.com/library/llama3</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="pull_featured_model"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">folder-download-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="tooltip-text">Pull 'Llama3 (latest)'</property>
|
|
||||||
<style>
|
|
||||||
<class name="accent"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title" translatable="no">Gemma2</property>
|
|
||||||
<property name="subtitle" translatable="yes">Built by Google DeepMind</property>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="link_button_handler"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">globe-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="name">https://ollama.com/library/gemma2</property>
|
|
||||||
<property name="tooltip-text">https://ollama.com/library/gemma2</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="pull_featured_model"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">folder-download-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="tooltip-text">Pull 'Gemma2 (latest)'</property>
|
|
||||||
<style>
|
|
||||||
<class name="accent"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title" translatable="no">Phi3</property>
|
|
||||||
<property name="subtitle" translatable="yes">Built by Microsoft</property>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="link_button_handler"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">globe-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="name">https://ollama.com/library/phi3</property>
|
|
||||||
<property name="tooltip-text">https://ollama.com/library/phi3</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="pull_featured_model"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">folder-download-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="tooltip-text">Pull 'Phi3 (latest)'</property>
|
|
||||||
<style>
|
|
||||||
<class name="accent"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title" translatable="no">Llava</property>
|
|
||||||
<property name="subtitle" translatable="yes">Multimodal AI with image recognition</property>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="link_button_handler"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">globe-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="name">https://ollama.com/library/llava</property>
|
|
||||||
<property name="tooltip-text">https://ollama.com/library/llava</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child type="suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<signal name="clicked" handler="pull_featured_model"/>
|
|
||||||
<property name="vexpand">false</property>
|
|
||||||
<property name="icon-name">folder-download-symbolic</property>
|
|
||||||
<property name="valign">3</property>
|
|
||||||
<property name="tooltip-text">Pull 'Llava (latest)'</property>
|
|
||||||
<style>
|
|
||||||
<class name="accent"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -1045,6 +966,10 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
<attribute name="label" translatable="yes">Import Chat</attribute>
|
<attribute name="label" translatable="yes">Import Chat</attribute>
|
||||||
<attribute name="action">app.import_chat</attribute>
|
<attribute name="action">app.import_chat</attribute>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Manage Models</attribute>
|
||||||
|
<attribute name="action">app.manage_models</attribute>
|
||||||
|
</item>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
@@ -1062,25 +987,29 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="secondary_menu">
|
<menu id="secondary_menu">
|
||||||
<item>
|
<section>
|
||||||
<attribute name="label" translatable="yes">Rename Chat</attribute>
|
<item>
|
||||||
<attribute name="action">app.rename_current_chat</attribute>
|
<attribute name="label" translatable="yes">Rename Chat</attribute>
|
||||||
</item>
|
<attribute name="action">app.rename_current_chat</attribute>
|
||||||
<item>
|
</item>
|
||||||
<attribute name="label" translatable="yes">Export Chat</attribute>
|
<item>
|
||||||
<attribute name="action">app.export_current_chat</attribute>
|
<attribute name="label" translatable="yes">Export Chat</attribute>
|
||||||
</item>
|
<attribute name="action">app.export_current_chat</attribute>
|
||||||
<item>
|
</item>
|
||||||
<attribute name="label" translatable="yes">Clear Chat</attribute>
|
<item>
|
||||||
<attribute name="action">app.clear</attribute>
|
<attribute name="label" translatable="yes">Clear Chat</attribute>
|
||||||
</item>
|
<attribute name="action">app.clear</attribute>
|
||||||
</menu>
|
</item>
|
||||||
<menu id="chat_right_click_menu">
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">Delete Chat</attribute>
|
<attribute name="label" translatable="yes">Delete Chat</attribute>
|
||||||
<attribute name="action">app.delete_chat</attribute>
|
<attribute name="action">app.delete_current_chat</attribute>
|
||||||
</item>
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
|
<menu id="chat_right_click_menu">
|
||||||
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">Rename Chat</attribute>
|
<attribute name="label" translatable="yes">Rename Chat</attribute>
|
||||||
<attribute name="action">app.rename_chat</attribute>
|
<attribute name="action">app.rename_chat</attribute>
|
||||||
@@ -1090,6 +1019,12 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
<attribute name="action">app.export_chat</attribute>
|
<attribute name="action">app.export_chat</attribute>
|
||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete Chat</attribute>
|
||||||
|
<attribute name="action">app.delete_chat</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="create_model_menu">
|
<menu id="create_model_menu">
|
||||||
<section>
|
<section>
|
||||||
@@ -1147,7 +1082,7 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
<property name="title" translatable="yes">General</property>
|
<property name="title" translatable="yes">General</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkShortcutsShortcut">
|
<object class="GtkShortcutsShortcut">
|
||||||
<property name="accelerator"><ctrl>Q</property>
|
<property name="accelerator"><ctrl>W</property>
|
||||||
<property name="title" translatable="yes">Close application</property>
|
<property name="title" translatable="yes">Close application</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
@@ -1165,7 +1100,7 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkShortcutsShortcut">
|
<object class="GtkShortcutsShortcut">
|
||||||
<property name="accelerator"><ctrl>P</property>
|
<property name="accelerator"><ctrl>comma</property>
|
||||||
<property name="title" translatable="yes">Preferences</property>
|
<property name="title" translatable="yes">Preferences</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
@@ -1181,6 +1116,18 @@ By downloading any model you accept their license agreement available on the mod
|
|||||||
<property name="title" translatable="yes">Show shortcuts window</property>
|
<property name="title" translatable="yes">Show shortcuts window</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkShortcutsShortcut">
|
||||||
|
<property name="accelerator"><ctrl>M</property>
|
||||||
|
<property name="title" translatable="yes">Manage models</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkShortcutsShortcut">
|
||||||
|
<property name="accelerator">F9</property>
|
||||||
|
<property name="title" translatable="yes">Toggle sidebar</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Moves the descriptions of models to src/available_models_descriptions.py
|
||||||
|
so they can be translated
|
||||||
|
"""
|
||||||
import json
|
import json
|
||||||
with open('src/available_models.json', 'r') as f:
|
|
||||||
data = json.load(f)
|
if __name__ == "__main__":
|
||||||
results = 'descriptions = {\n'
|
with open('src/available_models.json', 'r', encoding="utf-8") as f:
|
||||||
for key, value in data.items():
|
data = json.load(f)
|
||||||
results += f" '{key}': _(\"{value['description']}\"),\n"
|
RESULTS = 'descriptions = {\n'
|
||||||
results += '}'
|
for key, value in data.items():
|
||||||
with open('src/available_models_descriptions.py', 'w+') as f:
|
RESULTS += f" '{key}': _(\"{value['description']}\"),\n"
|
||||||
f.write(results)
|
RESULTS += '}'
|
||||||
|
with open('src/available_models_descriptions.py', 'w+', encoding="utf-8") as f:
|
||||||
|
f.write(RESULTS)
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ msgmerge --no-fuzzy-matching -U po/nb_NO.po po/alpaca.pot
|
|||||||
echo "Updating Bengali"
|
echo "Updating Bengali"
|
||||||
msgmerge --no-fuzzy-matching -U po/bn.po po/alpaca.pot
|
msgmerge --no-fuzzy-matching -U po/bn.po po/alpaca.pot
|
||||||
echo "Updating Simplified Chinese"
|
echo "Updating Simplified Chinese"
|
||||||
msgmerge --no-fuzzy-matching -U po/zh_CN.po po/alpaca.pot
|
msgmerge --no-fuzzy-matching -U po/zh_CN.po po/alpaca.pot
|
||||||
|
echo "Updating Hindi"
|
||||||
|
msgmerge --no-fuzzy-matching -U po/hi.po po/alpaca.pot
|
||||||
|
|||||||
Reference in New Issue
Block a user