├── .dockerignore
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── build.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── README.md
├── bin
├── chat
├── chat.exe
├── chat_mac_arm64
├── chat_mac_x64
├── no_avx2
│ ├── chat
│ └── chat.exe
└── prompts
│ ├── alpaca.txt
│ ├── llama.txt
│ ├── reason-act.txt
│ └── vicuna.txt
├── build
└── config.gypi
├── demo.gif
├── docker-compose.yml
├── electron-builder.yml
├── icon
├── alpaca-chat-logo-2.jpg
├── alpaca-chat-logo-round.png
├── alpaca-chat-logo.png
├── mac
│ └── icon.icns
├── png
│ ├── 1024x1024.png
│ ├── 128x128.png
│ ├── 16x16.png
│ ├── 24x24.png
│ ├── 256x256.png
│ ├── 32x32.png
│ ├── 48x48.png
│ ├── 512x512.png
│ └── 64x64.png
└── win
│ └── icon.ico
├── index.js
├── models
└── .gitkeep
├── package.json
└── src
├── fonts
└── IBM Plex
│ ├── IBMPlexSans-Light.ttf
│ ├── IBMPlexSans-Regular.ttf
│ └── IBMPlexSans-Thin.ttf
├── icons
├── close-k-10.png
├── close-k-12.png
├── close-k-15.png
├── close-k-20.png
├── close-k-24.png
├── close-k-30.png
├── close-w-10.png
├── close-w-12.png
├── close-w-15.png
├── close-w-20.png
├── close-w-24.png
├── close-w-30.png
├── max-k-10.png
├── max-k-12.png
├── max-k-15.png
├── max-k-20.png
├── max-k-24.png
├── max-k-30.png
├── max-w-10.png
├── max-w-12.png
├── max-w-15.png
├── max-w-20.png
├── max-w-24.png
├── max-w-30.png
├── min-k-10.png
├── min-k-12.png
├── min-k-15.png
├── min-k-20.png
├── min-k-24.png
├── min-k-30.png
├── min-w-10.png
├── min-w-12.png
├── min-w-15.png
├── min-w-20.png
├── min-w-24.png
├── min-w-30.png
├── restore-k-10.png
├── restore-k-12.png
├── restore-k-15.png
├── restore-k-20.png
├── restore-k-24.png
├── restore-k-30.png
├── restore-w-10.png
├── restore-w-12.png
├── restore-w-15.png
├── restore-w-20.png
├── restore-w-24.png
└── restore-w-30.png
├── img
├── alpaca-web.png
├── alpaca.png
└── user.png
├── index.html
├── prompts
├── alpaca.js
├── llama.js
└── vicuna.js
├── renderer.js
├── style.css
└── titlebar.css
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | package-lock.json
3 | **/models
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG] "
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. Windows]
28 | - Version [e.g. 1.0.5]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[ENHANCEMENT]"
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build and release
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | create_release:
7 | description: 'Create new release'
8 | required: true
9 | type: boolean
10 | version:
11 | description: "Don't include the v"
12 | required: true
13 |
14 | jobs:
15 | windows-x64-release:
16 | runs-on: windows-latest
17 | steps:
18 | - name: Git clone
19 | uses: actions/checkout@v3
20 |
21 | - name: Setup Node.js
22 | uses: actions/setup-node@v3
23 | with:
24 | node-version: 18.15.0
25 |
26 | - name: Dependencies
27 | run: |
28 | npm install
29 | npm run rebuild
30 |
31 | - name: Build and package
32 | run: |
33 | npm run make-win
34 | npm run pack-win
35 |
36 | - name: Upload artifacts
37 | uses: actions/upload-artifact@v3
38 | with:
39 | name: windows-x64
40 | path: |
41 | dist/Alpaca-Electron-win-x64-v${{github.event.inputs.version}}.exe
42 |
43 | macos-x64-release:
44 | runs-on: macos-latest
45 | steps:
46 | - name: Git clone
47 | uses: actions/checkout@v3
48 |
49 | - name: Setup Node.js
50 | uses: actions/setup-node@v3
51 | with:
52 | node-version: 18.15.0
53 |
54 | - name: Dependencies
55 | run: |
56 | npm install
57 | npm install electron-installer-dmg -g
58 | npx electron-rebuild
59 |
60 | - name: Build and package
61 | run: |
62 | npm run make-mac-x64
63 | npm run pack-mac-x64
64 | mv "release-builds/dmg/x64/Alpaca Electron.dmg" release-builds/dmg/x64/Alpaca-Electron-mac-x64-v${{github.event.inputs.version}}.dmg
65 |
66 | - name: Upload artifacts
67 | uses: actions/upload-artifact@v3
68 | with:
69 | name: macos-x64
70 | path: |
71 | release-builds/dmg/x64/Alpaca-Electron-mac-x64-v${{github.event.inputs.version}}.dmg
72 |
73 | linux-x64-release:
74 | runs-on: ubuntu-latest
75 | steps:
76 | - name: Git clone
77 | uses: actions/checkout@v3
78 |
79 | - name: Setup Node.js
80 | uses: actions/setup-node@v3
81 | with:
82 | node-version: 18.15.0
83 |
84 | - name: Dependencies
85 | run: |
86 | npm install
87 | npm run rebuild-linux
88 |
89 | - name: Build and package
90 | run: |
91 | npm run make-linux-x64
92 | npm run pack-linux-x64
93 | mv release-builds/Alpaca-Electron-linux-x64-vx.x.x.tar.gz release-builds/Alpaca-Electron-linux-x64-v${{github.event.inputs.version}}.tar.gz
94 |
95 | - name: Upload artifacts
96 | uses: actions/upload-artifact@v3
97 | with:
98 | name: linux-x64
99 | path: |
100 | release-builds/Alpaca-Electron-linux-x64-v${{github.event.inputs.version}}.tar.gz
101 |
102 |
103 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | yarn.lock
4 | models/*
5 | !models/.gitkeep
6 |
7 | release-builds
8 | dist
9 | .DS_Store
10 |
11 | main.log
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders on the [Alpaca Electron official Discord server](https://discord.gg/W7xwHpPWth).
63 | All complaints will be reviewed and investigated promptly and fairly.
64 |
65 | All community leaders are obligated to respect the privacy and security of the
66 | reporter of any incident.
67 |
68 | ## Enforcement Guidelines
69 |
70 | Community leaders will follow these Community Impact Guidelines in determining
71 | the consequences for any action they deem in violation of this Code of Conduct:
72 |
73 | ### 1. Correction
74 |
75 | **Community Impact**: Use of inappropriate language or other behavior deemed
76 | unprofessional or unwelcome in the community.
77 |
78 | **Consequence**: A private, written warning from community leaders, providing
79 | clarity around the nature of the violation and an explanation of why the
80 | behavior was inappropriate. A public apology may be requested.
81 |
82 | ### 2. Warning
83 |
84 | **Community Impact**: A violation through a single incident or series
85 | of actions.
86 |
87 | **Consequence**: A warning with consequences for continued behavior. No
88 | interaction with the people involved, including unsolicited interaction with
89 | those enforcing the Code of Conduct, for a specified period of time. This
90 | includes avoiding interactions in community spaces as well as external channels
91 | like social media. Violating these terms may lead to a temporary or
92 | permanent ban.
93 |
94 | ### 3. Temporary Ban
95 |
96 | **Community Impact**: A serious violation of community standards, including
97 | sustained inappropriate behavior.
98 |
99 | **Consequence**: A temporary ban from any sort of interaction or public
100 | communication with the community for a specified period of time. No public or
101 | private interaction with the people involved, including unsolicited interaction
102 | with those enforcing the Code of Conduct, is allowed during this period.
103 | Violating these terms may lead to a permanent ban.
104 |
105 | ### 4. Permanent Ban
106 |
107 | **Community Impact**: Demonstrating a pattern of violation of community
108 | standards, including sustained inappropriate behavior, harassment of an
109 | individual, or aggression toward or disparagement of classes of individuals.
110 |
111 | **Consequence**: A permanent ban from any sort of public interaction within
112 | the community.
113 |
114 | ## Attribution
115 |
116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117 | version 2.0, available at
118 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
119 |
120 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
121 | enforcement ladder](https://github.com/mozilla/diversity).
122 |
123 | [homepage]: https://www.contributor-covenant.org
124 |
125 | For answers to common questions about this code of conduct, see the FAQ at
126 | https://www.contributor-covenant.org/faq. Translations are available at
127 | https://www.contributor-covenant.org/translations.
128 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:bullseye-slim as alpaca-cpp-builder
2 |
3 | USER root
4 |
5 | RUN apt-get update \
6 | && apt-get install -yq --no-install-recommends git build-essential ca-certificates \
7 | && apt-get clean && rm -rf /var/lib/apt/lists/*
8 |
9 | ENV LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH
10 |
11 | RUN git clone https://github.com/ggerganov/llama.cpp /tmp/llama.cpp
12 | RUN cd /tmp/llama.cpp && git checkout master-87a6f84 && make -j
13 |
14 | FROM node:20.0-bullseye as alpaca-electron-builder
15 |
16 | USER root
17 |
18 | COPY . /tmp/alpaca-electron
19 | COPY --from=alpaca-cpp-builder /tmp/llama.cpp/main /tmp/alpaca-electron/bin/chat
20 | WORKDIR /tmp/alpaca-electron
21 |
22 | RUN npm install
23 | RUN npm run linux-x64
24 |
25 | FROM debian:bullseye-slim
26 |
27 | USER root
28 |
29 | ENV DEBIAN_FRONTEND=noninteractive
30 |
31 | RUN apt-get update \
32 | && apt-get install -yq --no-install-recommends tini procps xorg openbox libx11-xcb1 libxcb-dri3-0 libxtst6 libnss3 libatk-bridge2.0-0 libgtk-3-0 libxss1 libasound2 libatk-adaptor \
33 | && apt-get clean && rm -rf /var/lib/apt/lists/*
34 |
35 | RUN mkdir /alpaca-electron
36 | ARG src="/tmp/alpaca-electron/release-builds/Alpaca Electron-linux-x64"
37 | COPY --chown=1000 --from=alpaca-electron-builder ${src} /alpaca-electron
38 |
39 | WORKDIR /alpaca-electron
40 |
41 | RUN chown root chrome-sandbox
42 | RUN chmod 4755 chrome-sandbox
43 |
44 | RUN useradd -m -u 1000 debian
45 | RUN mkdir -p /home/debian/.config && chown debian:debian /home/debian/.config
46 |
47 | USER 1000
48 | ENTRYPOINT [ "tini", "--" ]
49 | CMD [ "bash", "-c", "/alpaca-electron/Alpaca\\ Electron --no-sandbox --disable-gpu & sleep 5 && while [[ $(ps | grep 'Alpaca\\ Electron' | wc -l) -gt 0 ]]; do sleep 5; done" ]
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Pi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Alpaca Electron
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Alpaca Electron is built from the ground-up to be the easiest way to chat with the alpaca AI models. No command line or compiling needed!
26 |
27 |
28 | # Important:
29 | **Only windows is current supported for now. The new llama.cpp binaries that support GGUF have not been built for other platforms yet.**
30 | If you would like to help, please makea pull request and update the binaries in `./bin`
31 |
32 | ## 📃 Features + to-do
33 |
34 | - [x] Runs locally on your computer, internet connection is not needed except when downloading models
35 | - [x] Compact and efficient since it uses [llama.cpp](https://github.com/ggerganov/llama.cpp) as its backend (which supports Alpaca & Vicuna too)
36 | - [x] Runs on CPU, anyone can run it without an expensive graphics card
37 | - [x] No external dependencies required, everything is included in the installer
38 | - [x] "Borrowed" UI from *that* popular chat AI :trollface:
39 | - [x] Supports Windows, MacOS, and Linux (untested)
40 | - [x] Docker-ized 🐋
41 | - [x] Context memory
42 | - [ ] Chat history
43 | - [ ] Integration with Stable Diffusion
44 | - [ ] DuckDuckGo integration for web access
45 | - [ ] GPU acceleration (cuBLAS & openBLAS)
46 |
47 | ## 🎞 Demo
48 |
49 | 
50 |
51 | ## 🚀 Quick Start Guide
52 |
53 | 1. Download an Alpaca model (7B native is recommended) and place it somewhere on your computer where it's easy to find.
54 | > **Note**
55 | > Download links will not be provided in this repository.
56 |
57 | 2. Download the latest installer from the [releases page](https://github.com/ItsPi3141/alpaca-electron/releases) section.
58 |
59 | 3. Open the installer and wait for it to install.
60 |
61 | 4. Once done installing, it'll ask for a valid path to a model. Now, go to where you placed the model, hold shift, right click on the file, and then click on "Copy as Path". Then, paste this into that dialog box and click `Confirm`.
62 |
63 | 5. The program will automatically restart. Now you can begin chatting!
64 |
65 | > **Note**
66 | > The program will also accept any other 4 bit quantized .bin model files. If you can find other .bin Alpaca model files, you can use them instead of the one recommended in the Quick Start Guide to experiment with different models. As always, be careful about what you download from the internet.
67 |
68 | ## 🔧 Troubleshooting
69 |
70 | ### General
71 | - If you get an error that says "Invalid file path" when pasting the path to the model file, you probably have some sort of misspelling in there. Try copying the path again or using the file picker.
72 | - If you get an error that says "Couldn't load model", your model is probably corrupted or incompatible. Try downloading the model again.
73 | - If you face other problems or issues not listed here, create an issue in the "Issues" tab at the top of this page. Describe in detail what happens, and include screenshots.
74 |
75 | ### Windows
76 | - If the model has been loaded into RAM but text generation doesn't seem start, [check](https://ark.intel.com/content/www/us/en/ark.html#@Processors) to see if your CPU is compatible with the [AVX2](https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/client/platforms/alder-lake-desktop/12th-generation-intel-core-processors-datasheet-volume-1-of-2/002/intel-advanced-vector-extensions-2-intel-avx2/) instruction set. If it does not support AVX2, Alpaca Electron will use AVX instead, which is much slower so be patient.
77 | - If you get an error saying "vcruntime140_1.dll is missing" or nothing happens at all and the model was not loaded into RAM, try installing the [Microsoft Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe).
78 |
79 | ### MacOS
80 | - If you get an error that says "App can't be opened because it is from an unidentified developer.", go to the Applications folder. Then, hold the control key and click on the app. Then click "Open", then click "Open" when it gives you a warning. Your preference will be saved and MacOS will let you open the app normally from now on.
81 | - If the above method does not work, try running the following command in terminal: `xattr -cr /Applications/Alpaca\ Electron.app/`
82 |
83 | ### Linux
84 |
85 | - You can either download the prebuilt app (packaged as tar.gz) from the releases page, extract it and execute it with ```./"alpaca electron"``` or build the application on yourself.
86 |
87 | - If you want to build the application yourself:
88 | >Clone the repository:
89 | >
90 | >```git clone https://github.com/ItsPi3141/alpaca-electron.git```
91 | >
92 | >Change your current directory to alpaca-electron:
93 | >
94 | >```cd alpaca-electron```
95 | >
96 | >Install application specific dependencies:
97 | >
98 | >```npm install --save-dev```
99 | >
100 | >Build the application:
101 | >
102 | >```npm run linux-x64```
103 | >
104 | >Change your current directory to the build target:
105 | >
106 | >```cd release-builds/'Alpaca Electron-linux-x64'```
107 | >
108 | >Run the application with ```./'Alpaca Electron'```
109 |
110 | ### Docker Compose
111 |
112 | - You can run this electron application with docker compose. Therefore you need to compelete the following steps:
113 |
114 | >Clone the repository:
115 | >
116 | >```git clone https://github.com/ItsPi3141/alpaca-electron.git```
117 | >
118 | >Change your current directory to alpaca-electron:
119 | >
120 | >```cd alpaca-electron```
121 | >
122 | >Build the container image:
123 | >
124 | >```docker compose build```
125 | >
126 | >Run the application container:
127 | >
128 | >```docker compose up -d```
129 |
130 | - If no window opens up run ```docker compose up``` (without the -d). If there is an error like ```Authorization required, but no authorization protocol specified``` run ```xhost local:root``` on your docker host.
131 |
132 | ## ⚒️ Building
133 |
134 | ### Prerequisites
135 | - [Node.js](https://node.org)
136 | - [Git](https://git-scm.com)
137 | - If you're on Windows and are planning on building llama.cpp binaries also, [CMake](https://cmake.org).
138 |
139 | ### **(OPTIONAL)** Building llama.cpp from source
140 | 1. Clone llama.cpp's GitHub repo
141 | ```sh
142 | git clone https://github.com/ggerganov/llama.cpp
143 | cd llama.cpp
144 | ```
145 |
146 | 2. Build llama.cpp
147 | On Windows:
148 | ```cmd
149 | mkdir build
150 | cd build
151 | cmake ..
152 | cmake . --config Release
153 | ```
154 |
155 | On Linux and MacOS:
156 | ```sh
157 | make
158 | ```
159 |
160 | ### Running the project from source
161 | 1. Clone the GitHub repo
162 | ```sh
163 | git clone https://github.com/ItsPi3141/alpaca-electron
164 | cd alpaca-electron
165 | ```
166 |
167 | 2. Install node packages
168 | ```sh
169 | npm install
170 | npm run rebuild
171 | ```
172 | > **Info**
173 | If you are on Linux, replace `npm run rebuild` with `npm run rebuild-linux`
174 |
175 | 3. **(OPTIONAL)** Use your own llama.cpp build
176 | > **Warning**
177 | > This step is not required. Only do it if you had built llama.cpp yourself and you want to use that build. Otherwise, skip to **step 4**
178 | If you had built llama.cpp in the previous section, copy the `main` executable file into the `bin` folder inside the alpaca-electron folder.
179 |
180 | Make sure the file replaces the correct file. E.g. if you're on Windows, replace chat.exe with your file. If you're on arm64 MacOS, replace chat_mac_arm64. Etc...
181 |
182 | 4. Start the Electron app
183 | ```sh
184 | npm start
185 | ```
186 |
187 | ### Building a release and installer
188 | Run one of the following commands:
189 | - `npm run win`
190 | - `npm run mac-x64`
191 | - `npm run mac-arm64`
192 | - `npm run linux-x64`
193 |
194 | You can only build for the OS you are running the build on. E.g. if you are on Windows, you can build for Windows, but not for MacOS and Linux.
195 |
196 |
197 | ## 👨💻 Credits
198 |
199 | Credits go to [@antimatter15](https://github.com/antimatter15/alpaca.cpp) for creating alpaca.cpp and to [@ggerganov](https://github.com/ggerganov/llama.cpp) for creating llama.cpp, the backbones behind alpaca.cpp. Finally, credits go to Meta and Stanford for creating the LLaMA and Alpaca models, respectively.
200 |
201 | Special thanks to [@keldenl](https://github.com/keldenl) for providing arm64 builds for MacOS and [@W48B1T](https://github.com/W48B1T) for providing Linux builds
202 |
--------------------------------------------------------------------------------
/bin/chat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/chat
--------------------------------------------------------------------------------
/bin/chat.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/chat.exe
--------------------------------------------------------------------------------
/bin/chat_mac_arm64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/chat_mac_arm64
--------------------------------------------------------------------------------
/bin/chat_mac_x64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/chat_mac_x64
--------------------------------------------------------------------------------
/bin/no_avx2/chat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/no_avx2/chat
--------------------------------------------------------------------------------
/bin/no_avx2/chat.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/bin/no_avx2/chat.exe
--------------------------------------------------------------------------------
/bin/prompts/alpaca.txt:
--------------------------------------------------------------------------------
1 | Below is an instruction that describes a task. Write a response that appropriately completes the request.
2 |
3 | ### Instruction: Hello.
4 | ### Response: Hello. How may I help you today?
5 | ### Instruction: What are the key differences between renewable and non-renewable energy sources?
6 | ### Response: Renewable energy sources are those that can be replenished naturally in a relatively short amount of time, such as solar, wind, hydro, geothermal, and biomass. Non-renewable energy sources, on the other hand, are finite and will eventually be depleted, such as coal, oil, and natural gas.
7 | ### Instruction:
--------------------------------------------------------------------------------
/bin/prompts/llama.txt:
--------------------------------------------------------------------------------
1 | Transcript of a dialog, where the User interacts with an Assistant named Llama. Llama is helpful, kind, honest, good at writing, and never fails to answer the User's requests immediately and with precision.
2 |
3 | User: Hello, Llama.
4 | Llama: Hello. How may I help you today?
5 | User: Please tell me the largest city in Europe.
6 | Llama: Sure. The largest city in Europe is Moscow, the capital of Russia.
7 | User:
--------------------------------------------------------------------------------
/bin/prompts/reason-act.txt:
--------------------------------------------------------------------------------
1 | You run in a loop of Thought, Action, Observation.
2 | At the end of the loop either Answer or restate your Thought and Action.
3 | Use Thought to describe your thoughts about the question you have been asked.
4 | Use Action to run one of these actions available to you:
5 | - calculate[python math expression]
6 | Observation will be the result of running those actions
7 |
8 |
9 | Question: What is 4 * 7 / 3?
10 | Thought: Do I need to use an action? Yes, I use calculate to do math
11 | Action: calculate[4 * 7 / 3]
12 | Observation: 9.3333333333
13 | Thought: Do I need to use an action? No, have the result
14 | Answer: The calculate tool says it is 9.3333333333
15 | Question: What is capital of france?
16 | Thought: Do I need to use an action? No, I know the answer
17 | Answer: Paris is the capital of France
18 | Question:
19 |
--------------------------------------------------------------------------------
/bin/prompts/vicuna.txt:
--------------------------------------------------------------------------------
1 | A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions.
2 |
3 | ### Human: Hello, Assistant.
4 | ### Assistant: Hello. How may I help you today?
5 | ### Human: What are the key differences between renewable and non-renewable energy sources?
6 | ### Assistant: Renewable energy sources are those that can be replenished naturally in a relatively short amount of time, such as solar, wind, hydro, geothermal, and biomass. Non-renewable energy sources, on the other hand, are finite and will eventually be depleted, such as coal, oil, and natural gas.
7 | ### Human:
--------------------------------------------------------------------------------
/build/config.gypi:
--------------------------------------------------------------------------------
1 | # Do not edit. File was generated by node-gyp's "configure" step
2 | {
3 | "target_defaults": {
4 | "cflags": [],
5 | "default_configuration": "Release",
6 | "defines": [],
7 | "include_dirs": [],
8 | "libraries": [],
9 | "msbuild_toolset": "v142",
10 | "msvs_windows_target_platform_version": "10.0.19041.0"
11 | },
12 | "variables": {
13 | "asan": 0,
14 | "coverage": "false",
15 | "dcheck_always_on": 0,
16 | "debug_nghttp2": "false",
17 | "debug_node": "false",
18 | "enable_lto": "false",
19 | "enable_pgo_generate": "false",
20 | "enable_pgo_use": "false",
21 | "error_on_warn": "false",
22 | "force_dynamic_crt": 0,
23 | "host_arch": "x64",
24 | "icu_data_in": "..\\..\\deps\\icu-tmp\\icudt72l.dat",
25 | "icu_endianness": "l",
26 | "icu_gyp_path": "tools/icu/icu-generic.gyp",
27 | "icu_path": "deps/icu-small",
28 | "icu_small": "false",
29 | "icu_ver_major": "72",
30 | "is_debug": 0,
31 | "libdir": "lib",
32 | "llvm_version": "0.0",
33 | "napi_build_version": "8",
34 | "nasm_version": "2.16",
35 | "node_builtin_shareable_builtins": [
36 | "deps/cjs-module-lexer/lexer.js",
37 | "deps/cjs-module-lexer/dist/lexer.js",
38 | "deps/undici/undici.js"
39 | ],
40 | "node_byteorder": "little",
41 | "node_debug_lib": "false",
42 | "node_enable_d8": "false",
43 | "node_enable_v8_vtunejit": "false",
44 | "node_fipsinstall": "false",
45 | "node_install_corepack": "true",
46 | "node_install_npm": "true",
47 | "node_library_files": [
48 | "lib/_http_agent.js",
49 | "lib/_http_client.js",
50 | "lib/_http_common.js",
51 | "lib/_http_incoming.js",
52 | "lib/_http_outgoing.js",
53 | "lib/_http_server.js",
54 | "lib/_stream_duplex.js",
55 | "lib/_stream_passthrough.js",
56 | "lib/_stream_readable.js",
57 | "lib/_stream_transform.js",
58 | "lib/_stream_wrap.js",
59 | "lib/_stream_writable.js",
60 | "lib/_tls_common.js",
61 | "lib/_tls_wrap.js",
62 | "lib/assert.js",
63 | "lib/assert/strict.js",
64 | "lib/async_hooks.js",
65 | "lib/buffer.js",
66 | "lib/child_process.js",
67 | "lib/cluster.js",
68 | "lib/console.js",
69 | "lib/constants.js",
70 | "lib/crypto.js",
71 | "lib/dgram.js",
72 | "lib/diagnostics_channel.js",
73 | "lib/dns.js",
74 | "lib/dns/promises.js",
75 | "lib/domain.js",
76 | "lib/events.js",
77 | "lib/fs.js",
78 | "lib/fs/promises.js",
79 | "lib/http.js",
80 | "lib/http2.js",
81 | "lib/https.js",
82 | "lib/inspector.js",
83 | "lib/internal/abort_controller.js",
84 | "lib/internal/assert.js",
85 | "lib/internal/assert/assertion_error.js",
86 | "lib/internal/assert/calltracker.js",
87 | "lib/internal/async_hooks.js",
88 | "lib/internal/blob.js",
89 | "lib/internal/blocklist.js",
90 | "lib/internal/bootstrap/browser.js",
91 | "lib/internal/bootstrap/loaders.js",
92 | "lib/internal/bootstrap/node.js",
93 | "lib/internal/bootstrap/switches/does_not_own_process_state.js",
94 | "lib/internal/bootstrap/switches/does_own_process_state.js",
95 | "lib/internal/bootstrap/switches/is_main_thread.js",
96 | "lib/internal/bootstrap/switches/is_not_main_thread.js",
97 | "lib/internal/buffer.js",
98 | "lib/internal/child_process.js",
99 | "lib/internal/child_process/serialization.js",
100 | "lib/internal/cli_table.js",
101 | "lib/internal/cluster/child.js",
102 | "lib/internal/cluster/primary.js",
103 | "lib/internal/cluster/round_robin_handle.js",
104 | "lib/internal/cluster/shared_handle.js",
105 | "lib/internal/cluster/utils.js",
106 | "lib/internal/cluster/worker.js",
107 | "lib/internal/console/constructor.js",
108 | "lib/internal/console/global.js",
109 | "lib/internal/constants.js",
110 | "lib/internal/crypto/aes.js",
111 | "lib/internal/crypto/certificate.js",
112 | "lib/internal/crypto/cfrg.js",
113 | "lib/internal/crypto/cipher.js",
114 | "lib/internal/crypto/diffiehellman.js",
115 | "lib/internal/crypto/ec.js",
116 | "lib/internal/crypto/hash.js",
117 | "lib/internal/crypto/hashnames.js",
118 | "lib/internal/crypto/hkdf.js",
119 | "lib/internal/crypto/keygen.js",
120 | "lib/internal/crypto/keys.js",
121 | "lib/internal/crypto/mac.js",
122 | "lib/internal/crypto/pbkdf2.js",
123 | "lib/internal/crypto/random.js",
124 | "lib/internal/crypto/rsa.js",
125 | "lib/internal/crypto/scrypt.js",
126 | "lib/internal/crypto/sig.js",
127 | "lib/internal/crypto/util.js",
128 | "lib/internal/crypto/webcrypto.js",
129 | "lib/internal/crypto/x509.js",
130 | "lib/internal/debugger/inspect.js",
131 | "lib/internal/debugger/inspect_client.js",
132 | "lib/internal/debugger/inspect_repl.js",
133 | "lib/internal/dgram.js",
134 | "lib/internal/dns/callback_resolver.js",
135 | "lib/internal/dns/promises.js",
136 | "lib/internal/dns/utils.js",
137 | "lib/internal/dtrace.js",
138 | "lib/internal/encoding.js",
139 | "lib/internal/error_serdes.js",
140 | "lib/internal/errors.js",
141 | "lib/internal/event_target.js",
142 | "lib/internal/file.js",
143 | "lib/internal/fixed_queue.js",
144 | "lib/internal/freelist.js",
145 | "lib/internal/freeze_intrinsics.js",
146 | "lib/internal/fs/cp/cp-sync.js",
147 | "lib/internal/fs/cp/cp.js",
148 | "lib/internal/fs/dir.js",
149 | "lib/internal/fs/promises.js",
150 | "lib/internal/fs/read_file_context.js",
151 | "lib/internal/fs/recursive_watch.js",
152 | "lib/internal/fs/rimraf.js",
153 | "lib/internal/fs/streams.js",
154 | "lib/internal/fs/sync_write_stream.js",
155 | "lib/internal/fs/utils.js",
156 | "lib/internal/fs/watchers.js",
157 | "lib/internal/heap_utils.js",
158 | "lib/internal/histogram.js",
159 | "lib/internal/http.js",
160 | "lib/internal/http2/compat.js",
161 | "lib/internal/http2/core.js",
162 | "lib/internal/http2/util.js",
163 | "lib/internal/idna.js",
164 | "lib/internal/inspector_async_hook.js",
165 | "lib/internal/js_stream_socket.js",
166 | "lib/internal/legacy/processbinding.js",
167 | "lib/internal/linkedlist.js",
168 | "lib/internal/main/check_syntax.js",
169 | "lib/internal/main/environment.js",
170 | "lib/internal/main/eval_stdin.js",
171 | "lib/internal/main/eval_string.js",
172 | "lib/internal/main/inspect.js",
173 | "lib/internal/main/mksnapshot.js",
174 | "lib/internal/main/print_help.js",
175 | "lib/internal/main/prof_process.js",
176 | "lib/internal/main/repl.js",
177 | "lib/internal/main/run_main_module.js",
178 | "lib/internal/main/test_runner.js",
179 | "lib/internal/main/watch_mode.js",
180 | "lib/internal/main/worker_thread.js",
181 | "lib/internal/mime.js",
182 | "lib/internal/modules/cjs/helpers.js",
183 | "lib/internal/modules/cjs/loader.js",
184 | "lib/internal/modules/esm/assert.js",
185 | "lib/internal/modules/esm/create_dynamic_module.js",
186 | "lib/internal/modules/esm/fetch_module.js",
187 | "lib/internal/modules/esm/formats.js",
188 | "lib/internal/modules/esm/get_format.js",
189 | "lib/internal/modules/esm/handle_process_exit.js",
190 | "lib/internal/modules/esm/initialize_import_meta.js",
191 | "lib/internal/modules/esm/load.js",
192 | "lib/internal/modules/esm/loader.js",
193 | "lib/internal/modules/esm/module_job.js",
194 | "lib/internal/modules/esm/module_map.js",
195 | "lib/internal/modules/esm/package_config.js",
196 | "lib/internal/modules/esm/resolve.js",
197 | "lib/internal/modules/esm/translators.js",
198 | "lib/internal/modules/package_json_reader.js",
199 | "lib/internal/modules/run_main.js",
200 | "lib/internal/net.js",
201 | "lib/internal/options.js",
202 | "lib/internal/per_context/domexception.js",
203 | "lib/internal/per_context/messageport.js",
204 | "lib/internal/per_context/primordials.js",
205 | "lib/internal/perf/event_loop_delay.js",
206 | "lib/internal/perf/event_loop_utilization.js",
207 | "lib/internal/perf/nodetiming.js",
208 | "lib/internal/perf/observe.js",
209 | "lib/internal/perf/performance.js",
210 | "lib/internal/perf/performance_entry.js",
211 | "lib/internal/perf/resource_timing.js",
212 | "lib/internal/perf/timerify.js",
213 | "lib/internal/perf/usertiming.js",
214 | "lib/internal/perf/utils.js",
215 | "lib/internal/policy/manifest.js",
216 | "lib/internal/policy/sri.js",
217 | "lib/internal/priority_queue.js",
218 | "lib/internal/process/esm_loader.js",
219 | "lib/internal/process/execution.js",
220 | "lib/internal/process/per_thread.js",
221 | "lib/internal/process/policy.js",
222 | "lib/internal/process/pre_execution.js",
223 | "lib/internal/process/promises.js",
224 | "lib/internal/process/report.js",
225 | "lib/internal/process/signal.js",
226 | "lib/internal/process/task_queues.js",
227 | "lib/internal/process/warning.js",
228 | "lib/internal/process/worker_thread_only.js",
229 | "lib/internal/promise_hooks.js",
230 | "lib/internal/querystring.js",
231 | "lib/internal/readline/callbacks.js",
232 | "lib/internal/readline/emitKeypressEvents.js",
233 | "lib/internal/readline/interface.js",
234 | "lib/internal/readline/promises.js",
235 | "lib/internal/readline/utils.js",
236 | "lib/internal/repl.js",
237 | "lib/internal/repl/await.js",
238 | "lib/internal/repl/history.js",
239 | "lib/internal/repl/utils.js",
240 | "lib/internal/socket_list.js",
241 | "lib/internal/socketaddress.js",
242 | "lib/internal/source_map/prepare_stack_trace.js",
243 | "lib/internal/source_map/source_map.js",
244 | "lib/internal/source_map/source_map_cache.js",
245 | "lib/internal/stream_base_commons.js",
246 | "lib/internal/streams/add-abort-signal.js",
247 | "lib/internal/streams/buffer_list.js",
248 | "lib/internal/streams/compose.js",
249 | "lib/internal/streams/destroy.js",
250 | "lib/internal/streams/duplex.js",
251 | "lib/internal/streams/duplexify.js",
252 | "lib/internal/streams/end-of-stream.js",
253 | "lib/internal/streams/from.js",
254 | "lib/internal/streams/lazy_transform.js",
255 | "lib/internal/streams/legacy.js",
256 | "lib/internal/streams/operators.js",
257 | "lib/internal/streams/passthrough.js",
258 | "lib/internal/streams/pipeline.js",
259 | "lib/internal/streams/readable.js",
260 | "lib/internal/streams/state.js",
261 | "lib/internal/streams/transform.js",
262 | "lib/internal/streams/utils.js",
263 | "lib/internal/streams/writable.js",
264 | "lib/internal/structured_clone.js",
265 | "lib/internal/test/binding.js",
266 | "lib/internal/test/transfer.js",
267 | "lib/internal/test_runner/coverage.js",
268 | "lib/internal/test_runner/harness.js",
269 | "lib/internal/test_runner/mock.js",
270 | "lib/internal/test_runner/reporter/dot.js",
271 | "lib/internal/test_runner/reporter/spec.js",
272 | "lib/internal/test_runner/reporter/tap.js",
273 | "lib/internal/test_runner/runner.js",
274 | "lib/internal/test_runner/tap_checker.js",
275 | "lib/internal/test_runner/tap_lexer.js",
276 | "lib/internal/test_runner/tap_parser.js",
277 | "lib/internal/test_runner/test.js",
278 | "lib/internal/test_runner/tests_stream.js",
279 | "lib/internal/test_runner/utils.js",
280 | "lib/internal/test_runner/yaml_to_js.js",
281 | "lib/internal/timers.js",
282 | "lib/internal/tls/secure-context.js",
283 | "lib/internal/tls/secure-pair.js",
284 | "lib/internal/trace_events_async_hooks.js",
285 | "lib/internal/tty.js",
286 | "lib/internal/url.js",
287 | "lib/internal/util.js",
288 | "lib/internal/util/colors.js",
289 | "lib/internal/util/comparisons.js",
290 | "lib/internal/util/debuglog.js",
291 | "lib/internal/util/inspect.js",
292 | "lib/internal/util/inspector.js",
293 | "lib/internal/util/iterable_weak_map.js",
294 | "lib/internal/util/parse_args/parse_args.js",
295 | "lib/internal/util/parse_args/utils.js",
296 | "lib/internal/util/types.js",
297 | "lib/internal/v8/startup_snapshot.js",
298 | "lib/internal/v8_prof_polyfill.js",
299 | "lib/internal/v8_prof_processor.js",
300 | "lib/internal/validators.js",
301 | "lib/internal/vm.js",
302 | "lib/internal/vm/module.js",
303 | "lib/internal/wasm_web_api.js",
304 | "lib/internal/watch_mode/files_watcher.js",
305 | "lib/internal/watchdog.js",
306 | "lib/internal/webstreams/adapters.js",
307 | "lib/internal/webstreams/compression.js",
308 | "lib/internal/webstreams/encoding.js",
309 | "lib/internal/webstreams/queuingstrategies.js",
310 | "lib/internal/webstreams/readablestream.js",
311 | "lib/internal/webstreams/transfer.js",
312 | "lib/internal/webstreams/transformstream.js",
313 | "lib/internal/webstreams/util.js",
314 | "lib/internal/webstreams/writablestream.js",
315 | "lib/internal/worker.js",
316 | "lib/internal/worker/io.js",
317 | "lib/internal/worker/js_transferable.js",
318 | "lib/module.js",
319 | "lib/net.js",
320 | "lib/os.js",
321 | "lib/path.js",
322 | "lib/path/posix.js",
323 | "lib/path/win32.js",
324 | "lib/perf_hooks.js",
325 | "lib/process.js",
326 | "lib/punycode.js",
327 | "lib/querystring.js",
328 | "lib/readline.js",
329 | "lib/readline/promises.js",
330 | "lib/repl.js",
331 | "lib/stream.js",
332 | "lib/stream/consumers.js",
333 | "lib/stream/promises.js",
334 | "lib/stream/web.js",
335 | "lib/string_decoder.js",
336 | "lib/sys.js",
337 | "lib/test.js",
338 | "lib/timers.js",
339 | "lib/timers/promises.js",
340 | "lib/tls.js",
341 | "lib/trace_events.js",
342 | "lib/tty.js",
343 | "lib/url.js",
344 | "lib/util.js",
345 | "lib/util/types.js",
346 | "lib/v8.js",
347 | "lib/vm.js",
348 | "lib/wasi.js",
349 | "lib/worker_threads.js",
350 | "lib/zlib.js"
351 | ],
352 | "node_module_version": 108,
353 | "node_no_browser_globals": "false",
354 | "node_prefix": "/usr/local",
355 | "node_release_urlbase": "https://nodejs.org/download/release/",
356 | "node_shared": "false",
357 | "node_shared_brotli": "false",
358 | "node_shared_cares": "false",
359 | "node_shared_http_parser": "false",
360 | "node_shared_libuv": "false",
361 | "node_shared_nghttp2": "false",
362 | "node_shared_nghttp3": "false",
363 | "node_shared_ngtcp2": "false",
364 | "node_shared_openssl": "false",
365 | "node_shared_zlib": "false",
366 | "node_tag": "",
367 | "node_target_type": "executable",
368 | "node_use_bundled_v8": "true",
369 | "node_use_dtrace": "false",
370 | "node_use_etw": "true",
371 | "node_use_node_code_cache": "true",
372 | "node_use_node_snapshot": "true",
373 | "node_use_openssl": "true",
374 | "node_use_v8_platform": "true",
375 | "node_with_ltcg": "true",
376 | "node_without_node_options": "false",
377 | "openssl_is_fips": "false",
378 | "openssl_quic": "true",
379 | "ossfuzz": "false",
380 | "shlib_suffix": "so.108",
381 | "target_arch": "x64",
382 | "v8_enable_31bit_smis_on_64bit_arch": 0,
383 | "v8_enable_gdbjit": 0,
384 | "v8_enable_hugepage": 0,
385 | "v8_enable_i18n_support": 1,
386 | "v8_enable_inspector": 1,
387 | "v8_enable_javascript_promise_hooks": 1,
388 | "v8_enable_lite_mode": 0,
389 | "v8_enable_object_print": 1,
390 | "v8_enable_pointer_compression": 0,
391 | "v8_enable_shared_ro_heap": 1,
392 | "v8_enable_short_builtin_calls": 1,
393 | "v8_enable_webassembly": 1,
394 | "v8_no_strict_aliasing": 1,
395 | "v8_optimized_debug": 1,
396 | "v8_promise_internal_field_count": 1,
397 | "v8_random_seed": 0,
398 | "v8_trace_maps": 0,
399 | "v8_use_siphash": 1,
400 | "want_separate_host_toolset": 0,
401 | "nodedir": "C:\\Users\\Pi\\AppData\\Local\\Temp\\prebuild\\node\\5.0.0",
402 | "standalone_static_library": 1,
403 | "msbuild_path": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe",
404 | "target": "5.0.0",
405 | "build_v8_with_gn": "false"
406 | }
407 | }
408 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/demo.gif
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.7'
2 |
3 | services:
4 | alpaca-electron:
5 | build: .
6 | volumes:
7 | - config:/home/debian/.config
8 | - ./models:/alpaca-electron/models
9 | - /tmp/.X11-unix:/tmp/.X11-unix
10 | environment:
11 | DISPLAY: ${DISPLAY}
12 |
13 | volumes:
14 | config:
15 | external: false
16 |
--------------------------------------------------------------------------------
/electron-builder.yml:
--------------------------------------------------------------------------------
1 | appId: com.pi.alpaca.electron
2 | nsis:
3 | artifactName: Alpaca-Electron-win-x64-v${version}.${ext}
4 | shortcutName: ${productName}
5 | uninstallDisplayName: ${productName}
6 | createDesktopShortcut: always
7 | installerIcon: icon/win/icon.ico
8 | uninstallerIcon: icon/win/icon.ico
9 | deleteAppDataOnUninstall: true
10 | npmRebuild: false
11 | asar: false
12 |
--------------------------------------------------------------------------------
/icon/alpaca-chat-logo-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/alpaca-chat-logo-2.jpg
--------------------------------------------------------------------------------
/icon/alpaca-chat-logo-round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/alpaca-chat-logo-round.png
--------------------------------------------------------------------------------
/icon/alpaca-chat-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/alpaca-chat-logo.png
--------------------------------------------------------------------------------
/icon/mac/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/mac/icon.icns
--------------------------------------------------------------------------------
/icon/png/1024x1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/1024x1024.png
--------------------------------------------------------------------------------
/icon/png/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/128x128.png
--------------------------------------------------------------------------------
/icon/png/16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/16x16.png
--------------------------------------------------------------------------------
/icon/png/24x24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/24x24.png
--------------------------------------------------------------------------------
/icon/png/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/256x256.png
--------------------------------------------------------------------------------
/icon/png/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/32x32.png
--------------------------------------------------------------------------------
/icon/png/48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/48x48.png
--------------------------------------------------------------------------------
/icon/png/512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/512x512.png
--------------------------------------------------------------------------------
/icon/png/64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/png/64x64.png
--------------------------------------------------------------------------------
/icon/win/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/icon/win/icon.ico
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const { BrowserWindow, app, ipcMain, dialog } = require("electron");
2 | const path = require("path");
3 | require("@electron/remote/main").initialize();
4 |
5 | const os = require("os");
6 | const platform = os.platform();
7 | const arch = os.arch();
8 |
9 | var win;
10 | function createWindow() {
11 | win = new BrowserWindow({
12 | width: 1200,
13 | height: 810,
14 | minWidth: 960,
15 | minHeight: 600,
16 | webPreferences: {
17 | nodeIntegration: true,
18 | contextIsolation: false,
19 | enableRemoteModule: true,
20 | devTools: false
21 | },
22 | titleBarStyle: "hidden",
23 | icon: platform == "darwin" ? path.join(__dirname, "icon", "mac", "icon.icns") : path.join(__dirname, "icon", "png", "128x128.png")
24 | });
25 | require("@electron/remote/main").enable(win.webContents);
26 |
27 | win.loadFile(path.resolve(__dirname, "src", "index.html"));
28 |
29 | win.setMenu(null);
30 | // win.webContents.openDevTools();
31 | }
32 |
33 | app.on("second-instance", () => {
34 | if (win) {
35 | if (win.isMinimized()) win.restore();
36 | win.focus();
37 | }
38 | });
39 |
40 | app.on("ready", () => {
41 | createWindow();
42 | });
43 |
44 | app.on("window-all-closed", () => {
45 | app.quit();
46 | });
47 | app.on("activate", () => {
48 | if (win == null) createWindow();
49 | });
50 | app.on("before-quit", () => {
51 | if (runningShell) runningShell.kill();
52 | });
53 |
54 | // OS STATS
55 |
56 | const osUtil = require("os-utils");
57 | var threads;
58 | var sysThreads = osUtil.cpuCount();
59 | for (let i = 1; i < sysThreads; i = i * 2) {
60 | threads = i;
61 | }
62 | if (sysThreads == 4) {
63 | threads = 4;
64 | }
65 | ipcMain.on("cpuUsage", () => {
66 | osUtil.cpuUsage(function (v) {
67 | win.webContents.send("cpuUsage", { data: v });
68 | });
69 | });
70 | ipcMain.on("cpuFree", () => {
71 | osUtil.cpuFree(function (v) {
72 | win.webContents.send("cpuFree", { data: v });
73 | });
74 | });
75 |
76 | ipcMain.on("cpuCount", () => {
77 | win.webContents.send("cpuCount", {
78 | data: osUtil.cpuCount()
79 | });
80 | });
81 | ipcMain.on("threadUtilized", () => {
82 | win.webContents.send("threadUtilized", {
83 | data: threads
84 | });
85 | });
86 | ipcMain.on("freemem", () => {
87 | win.webContents.send("freemem", {
88 | data: Math.round(osUtil.freemem() / 102.4) / 10
89 | });
90 | });
91 | ipcMain.on("totalmem", () => {
92 | win.webContents.send("totalmem", {
93 | data: osUtil.totalmem()
94 | });
95 | });
96 | ipcMain.on("os", () => {
97 | win.webContents.send("os", {
98 | data: platform
99 | });
100 | });
101 |
102 | // SET-UP
103 | const Store = require("electron-store");
104 | const schema = {
105 | params: {
106 | default: {
107 | model_type: "alpaca",
108 | repeat_last_n: "64",
109 | repeat_penalty: "1.3",
110 | top_k: "40",
111 | top_p: "0.9",
112 | temp: "0.8",
113 | seed: "-1",
114 | webAccess: false,
115 | websearch_amount: "5"
116 | }
117 | },
118 | modelPath: {
119 | default: "undefined"
120 | },
121 | supportsAVX2: {
122 | default: "undefined"
123 | }
124 | };
125 | const store = new Store({ schema });
126 | const fs = require("fs");
127 | var modelPath = store.get("modelPath");
128 |
129 | function checkModelPath() {
130 | modelPath = store.get("modelPath");
131 | if (modelPath) {
132 | if (fs.existsSync(path.resolve(modelPath))) {
133 | win.webContents.send("modelPathValid", { data: true });
134 | } else {
135 | win.webContents.send("modelPathValid", { data: false });
136 | }
137 | } else {
138 | win.webContents.send("modelPathValid", { data: false });
139 | }
140 | }
141 | ipcMain.on("checkModelPath", checkModelPath);
142 |
143 | ipcMain.on("checkPath", (_event, { data }) => {
144 | if (data) {
145 | if (fs.existsSync(path.resolve(data))) {
146 | store.set("modelPath", data);
147 | modelPath = store.get("modelPath");
148 | win.webContents.send("pathIsValid", { data: true });
149 | } else {
150 | win.webContents.send("pathIsValid", { data: false });
151 | }
152 | } else {
153 | win.webContents.send("pathIsValid", { data: false });
154 | }
155 | });
156 |
157 | // DUCKDUCKGO SEARCH FUNCTION
158 | const DDG = require("duck-duck-scrape");
159 | async function queryToPrompt(text) {
160 | const searchResults = await DDG.search(text, {
161 | safeSearch: DDG.SafeSearchType.MODERATE
162 | });
163 | if (!searchResults.noResults) {
164 | var convertedText = `Using the given web search results, answer the following query: `;
165 | convertedText += text;
166 | convertedText += "\\n### INPUT: \\n";
167 | convertedText += "Here are the web search results: ";
168 | var targetResultCount = store.get("params").websearch_amount || 5;
169 | if (searchResults.news) {
170 | for (let i = 0; i < searchResults.news.length && i < targetResultCount; i++) {
171 | convertedText += `${searchResults.news[i].description.replaceAll(/<\/?b>/gi, "")} `;
172 | }
173 | } else {
174 | for (let i = 0; i < searchResults.results.length && i < targetResultCount; i++) {
175 | convertedText += `${searchResults.results[i].description.replaceAll(/<\/?b>/gi, "")} `;
176 | }
177 | }
178 | return convertedText;
179 | // var convertedText = `Summarize the following text: `;
180 | // for (let i = 0; i < searchResults.results.length && i < 3; i++) {
181 | // convertedText += `${searchResults.results[i].description.replaceAll(/<\/?b>/gi, "")} `;
182 | // }
183 | // return convertedText;
184 | } else {
185 | return text;
186 | }
187 | }
188 |
189 | // RUNNING CHAT
190 | const pty = require("node-pty-prebuilt-multiarch");
191 | var runningShell, currentPrompt;
192 | var alpacaReady,
193 | alpacaHalfReady = false;
194 | var checkAVX,
195 | isAVX2 = false;
196 | if (store.get("supportsAVX2") == undefined) {
197 | store.set("supportsAVX2", true);
198 | }
199 | var supportsAVX2 = store.get("supportsAVX2");
200 | const config = {
201 | name: "xterm-color",
202 | cols: 69420,
203 | rows: 30
204 | };
205 |
206 | const shell = platform === "win32" ? "powershell.exe" : "bash";
207 | const stripAnsi = (str) => {
208 | const pattern = [
209 | "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
210 | "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
211 | ].join("|");
212 |
213 | const regex = new RegExp(pattern, "g");
214 | return str.replace(regex, "");
215 | };
216 |
217 | function restart() {
218 | console.log("restarting");
219 | win.webContents.send("result", {
220 | data: "\n\n"
221 | });
222 | if (runningShell) runningShell.kill();
223 | runningShell = undefined;
224 | currentPrompt = undefined;
225 | alpacaReady = false;
226 | alpacaHalfReady = false;
227 | initChat();
228 | }
229 |
230 | function initChat() {
231 | if (runningShell) {
232 | win.webContents.send("ready");
233 | return;
234 | }
235 | const ptyProcess = pty.spawn(shell, [], config);
236 | runningShell = ptyProcess;
237 | ptyProcess.onData((res) => {
238 | res = stripAnsi(res);
239 | console.log(`//> ${res}`);
240 | if (
241 | (res.includes("llama_model_load: invalid model file") || res.includes("llama_model_load: failed to open") || res.includes("llama_init_from_file: failed to load model")) &&
242 | res.includes("main: error: failed to load model")
243 | ) {
244 | if (runningShell) runningShell.kill();
245 | win.webContents.send("modelPathValid", { data: false });
246 | } else if (res.includes("\n>") && !alpacaReady) {
247 | alpacaHalfReady = true;
248 | } else if (alpacaHalfReady && !alpacaReady) {
249 | alpacaReady = true;
250 | checkAVX = false;
251 | win.webContents.send("ready");
252 | console.log("ready!");
253 | } else if (
254 | ((res.startsWith("llama_model_load:") && res.includes("sampling parameters: ")) || (res.startsWith("main: interactive mode") && res.includes("sampling parameters: "))) &&
255 | !checkAVX
256 | ) {
257 | checkAVX = true;
258 | console.log("checking avx compat");
259 | } else if (res.match(/PS [A-Z]:.*>/) && checkAVX) {
260 | console.log("avx2 incompatible, retrying with avx1");
261 | if (runningShell) runningShell.kill();
262 | runningShell = undefined;
263 | currentPrompt = undefined;
264 | alpacaReady = false;
265 | alpacaHalfReady = false;
266 | supportsAVX2 = false;
267 | checkAVX = false;
268 | store.set("supportsAVX2", false);
269 | initChat();
270 | } else if (
271 | ((res.match(/PS [A-Z]:.*>/) && platform == "win32") ||
272 | (res.match(/bash-[0-9]+\.?[0-9]*\$/) && platform == "darwin") ||
273 | (res.match(/([a-zA-Z0-9]|_|-)+@([a-zA-Z0-9]|_|-)+:?~(\$|#)/) && platform == "linux")) &&
274 | alpacaReady
275 | ) {
276 | restart();
277 | } else if (res.includes("\n>") && alpacaReady) {
278 | win.webContents.send("result", {
279 | data: "\n\n"
280 | });
281 | } else if (!res.startsWith(currentPrompt) && !res.startsWith("Using the given web search results, answer the following query:") && alpacaReady) {
282 | if (platform == "darwin") res = res.replaceAll("^C", "");
283 | win.webContents.send("result", {
284 | data: res
285 | });
286 | }
287 | });
288 |
289 | const params = store.get("params");
290 | if (params.model_type == "alpaca") {
291 | var revPrompt = "### Instruction:";
292 | } else if (params.model_type == "vicuna") {
293 | var revPrompt = "### Human:";
294 | } else {
295 | var revPrompt = "User:";
296 | }
297 | if (params.model_type == "alpaca") {
298 | var promptFile = "alpaca.txt";
299 | } else if (params.model_type == "vicuna") {
300 | var promptFile = "vicuna.txt";
301 | } else {
302 | var promptFile = "llama.txt";
303 | }
304 | const chatArgs = `-i --interactive-first -ins -r "${revPrompt}" -f "${path.resolve(__dirname, "bin", "prompts", promptFile)}"`;
305 | const paramArgs = `-m "${modelPath}" -n -1 --ctx_size 2048 --temp ${params.temp} --top_k ${params.top_k} --top_p ${params.top_p} --threads ${threads} --batch_size 512 --repeat_last_n ${params.repeat_last_n} --repeat_penalty ${params.repeat_penalty} --seed ${params.seed}`;
306 | if (platform == "win32") {
307 | runningShell.write(
308 | `[System.Console]::OutputEncoding=[System.Console]::InputEncoding=[System.Text.Encoding]::UTF8; ."${path.resolve(
309 | __dirname,
310 | "bin",
311 | supportsAVX2 ? "" : "no_avx2",
312 | "chat.exe"
313 | )}" ${paramArgs} ${chatArgs}\r`
314 | );
315 | } else if (platform == "darwin") {
316 | const macArch = arch == "x64" ? "chat_mac_x64" : "chat_mac_arm64";
317 | runningShell.write(`"${path.resolve(__dirname, "bin", macArch)}" ${paramArgs} ${chatArgs}\r`);
318 | } else {
319 | runningShell.write(`"${path.resolve(__dirname, "bin", "chat")}" ${paramArgs} ${chatArgs}\r`);
320 | }
321 | }
322 | ipcMain.on("startChat", () => {
323 | initChat();
324 | });
325 |
326 | ipcMain.on("message", async (_event, { data }) => {
327 | currentPrompt = data;
328 | if (runningShell) {
329 | if (store.get("params").webAccess) {
330 | runningShell.write(`${await queryToPrompt(data)}\r`);
331 | } else {
332 | runningShell.write(`${data}\r`);
333 | }
334 | }
335 | });
336 | ipcMain.on("stopGeneration", () => {
337 | if (runningShell) {
338 | if (runningShell) runningShell.kill();
339 | runningShell = undefined;
340 | currentPrompt = undefined;
341 | alpacaReady = false;
342 | alpacaHalfReady = false;
343 | initChat();
344 | setTimeout(() => {
345 | win.webContents.send("result", {
346 | data: "\n\n"
347 | });
348 | }, 200);
349 | }
350 | });
351 | ipcMain.on("getCurrentModel", () => {
352 | win.webContents.send("currentModel", {
353 | data: store.get("modelPath")
354 | });
355 | });
356 |
357 | ipcMain.on("pickFile", () => {
358 | dialog
359 | .showOpenDialog(win, {
360 | title: "Choose Alpaca GGUF model",
361 | filters: [
362 | {
363 | name: "GGUF model",
364 | extensions: ["gguf"]
365 | }
366 | ],
367 | properties: ["dontAddToRecent", "openFile"]
368 | })
369 | .then((obj) => {
370 | if (!obj.canceled) {
371 | win.webContents.send("pickedFile", {
372 | data: obj.filePaths[0]
373 | });
374 | }
375 | });
376 | });
377 |
378 | ipcMain.on("storeParams", (_event, { params }) => {
379 | console.log(params);
380 | store.set("params", params);
381 | restart();
382 | });
383 | ipcMain.on("getParams", () => {
384 | win.webContents.send("params", store.get("params"));
385 | });
386 |
387 | ipcMain.on("webAccess", (_event, value) => {
388 | store.set("params", {
389 | ...store.get("params"),
390 | webAccess: value
391 | });
392 | });
393 |
394 | ipcMain.on("restart", restart);
395 |
396 | process.on("unhandledRejection", () => {});
397 | process.on("uncaughtException", () => {});
398 | process.on("uncaughtExceptionMonitor", () => {});
399 | process.on("multipleResolves", () => {});
400 |
--------------------------------------------------------------------------------
/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/models/.gitkeep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "alpaca-electron",
3 | "productName": "Alpaca Electron",
4 | "description": "The most user friendly way to interact with Alpaca",
5 | "version": "1.0.6",
6 | "author": "Pi",
7 | "license": "MIT",
8 | "main": "index.js",
9 | "icon": "icon/win/icon.ico",
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1",
12 | "start": "electron .",
13 | "make-win": "npx electron-packager . --overwrite --platform=win32 --arch=x64 --icon=icon/win/icon.ico --prune=true --electron-version=13.6.9 --app-copyright=\"Pi\" --out=release-builds --version-string.CompanyName=Pi",
14 | "pack-win": "npx electron-builder --win --config --publish=never --prepackaged \"release-builds/Alpaca Electron-win32-x64\"",
15 | "win": "rmdir /s /q release-builds dist && npm run make-win && npm run pack-win",
16 | "make-mac-x64": "npx electron-packager . --overwrite --platform=darwin --arch=x64 --icon=icon/mac/icon.icns --prune=true --electron-version=13.6.9 --app-copyright=\"Pi\" --out=./release-builds --version-string.CompanyName=Pi",
17 | "make-mac-arm64": "npx electron-packager . --overwrite --platform=darwin --arch=arm64 --icon=icon/mac/icon.icns --prune=true --electron-version=13.6.9 --app-copyright=\"Pi\" --out=./release-builds --version-string.CompanyName=Pi",
18 | "pack-mac-x64": "electron-installer-dmg \"release-builds/Alpaca Electron-darwin-x64/Alpaca Electron.app\" \"Alpaca Electron\" --out=release-builds/dmg/x64 --icon=icon/mac/icon.icns --icon-size=128 --title=\"Alpaca Electron\" --overwrite",
19 | "pack-mac-arm64": "electron-installer-dmg \"release-builds/Alpaca Electron-darwin-arm64/Alpaca Electron.app\" \"Alpaca Electron\" --out=release-builds/dmg/arm64 --icon=icon/mac/icon.icns --icon-size=128 --title=\"Alpaca Electron\" --overwrite",
20 | "mac-x64": "npm run make-mac-x64 && npm run pack-mac-x64",
21 | "mac-arm64": "npm run make-mac-arm64 && npm run pack-mac-arm64",
22 | "rebuild": ".\\node_modules\\.bin\\electron-rebuild",
23 | "rebuild-linux": "npx --openssl_fips='' electron-rebuild",
24 | "make-linux-x64": "npx electron-packager . --overwrite --platform=linux --arch=x64 --icon=icon/png/128x128.png --prune=true --electron-version=13.6.9 --app-copyright='Pi' --out=./release-builds --version-string.CompanyName=Pi",
25 | "pack-linux-x64": "tar czf release-builds/Alpaca-Electron-linux-x64-1.0.6.tar.gz \"release-builds/Alpaca Electron-linux-x64\"",
26 | "linux-x64": "npm run rebuild-linux && npm run make-linux-x64 && npm run pack-linux-x64",
27 | "make-linux-arm64": "npx electron-packager . --overwrite --platform=linux --arch=arm64 --icon=icon/png/128x128.png --prune=true --electron-version=13.6.9 --app-copyright='Pi' --out=./release-builds --version-string.CompanyName=Pi",
28 | "pack-linux-arm64": "tar czf release-builds/Alpaca-Electron-linux-arm64-1.0.6.tar.gz \"release-builds/Alpaca Electron-linux-arm64\"",
29 | "linux-arm64": "npm run rebuild-linux && npm run make-linux-arm64 && npm run pack-linux-arm64"
30 | },
31 | "dependencies": {
32 | "@electron/remote": "^2.0.9",
33 | "@npmcli/fs": "^3.1.0",
34 | "duck-duck-scrape": "^2.2.4",
35 | "electron-store": "^8.1.0",
36 | "express": "^4.18.2",
37 | "node-pty-prebuilt-multiarch": "^0.10.1-pre.5",
38 | "os-utils": "^0.0.14",
39 | "path": "^0.12.7"
40 | },
41 | "devDependencies": {
42 | "@electron/rebuild": "^3.2.10",
43 | "electron": "^13.6.9",
44 | "electron-builder": "^23.6.0",
45 | "electron-packager": "^17.1.1"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/fonts/IBM Plex/IBMPlexSans-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/fonts/IBM Plex/IBMPlexSans-Light.ttf
--------------------------------------------------------------------------------
/src/fonts/IBM Plex/IBMPlexSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/fonts/IBM Plex/IBMPlexSans-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/IBM Plex/IBMPlexSans-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/fonts/IBM Plex/IBMPlexSans-Thin.ttf
--------------------------------------------------------------------------------
/src/icons/close-k-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-10.png
--------------------------------------------------------------------------------
/src/icons/close-k-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-12.png
--------------------------------------------------------------------------------
/src/icons/close-k-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-15.png
--------------------------------------------------------------------------------
/src/icons/close-k-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-20.png
--------------------------------------------------------------------------------
/src/icons/close-k-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-24.png
--------------------------------------------------------------------------------
/src/icons/close-k-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-k-30.png
--------------------------------------------------------------------------------
/src/icons/close-w-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-10.png
--------------------------------------------------------------------------------
/src/icons/close-w-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-12.png
--------------------------------------------------------------------------------
/src/icons/close-w-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-15.png
--------------------------------------------------------------------------------
/src/icons/close-w-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-20.png
--------------------------------------------------------------------------------
/src/icons/close-w-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-24.png
--------------------------------------------------------------------------------
/src/icons/close-w-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/close-w-30.png
--------------------------------------------------------------------------------
/src/icons/max-k-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-10.png
--------------------------------------------------------------------------------
/src/icons/max-k-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-12.png
--------------------------------------------------------------------------------
/src/icons/max-k-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-15.png
--------------------------------------------------------------------------------
/src/icons/max-k-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-20.png
--------------------------------------------------------------------------------
/src/icons/max-k-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-24.png
--------------------------------------------------------------------------------
/src/icons/max-k-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-k-30.png
--------------------------------------------------------------------------------
/src/icons/max-w-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-10.png
--------------------------------------------------------------------------------
/src/icons/max-w-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-12.png
--------------------------------------------------------------------------------
/src/icons/max-w-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-15.png
--------------------------------------------------------------------------------
/src/icons/max-w-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-20.png
--------------------------------------------------------------------------------
/src/icons/max-w-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-24.png
--------------------------------------------------------------------------------
/src/icons/max-w-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/max-w-30.png
--------------------------------------------------------------------------------
/src/icons/min-k-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-10.png
--------------------------------------------------------------------------------
/src/icons/min-k-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-12.png
--------------------------------------------------------------------------------
/src/icons/min-k-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-15.png
--------------------------------------------------------------------------------
/src/icons/min-k-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-20.png
--------------------------------------------------------------------------------
/src/icons/min-k-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-24.png
--------------------------------------------------------------------------------
/src/icons/min-k-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-k-30.png
--------------------------------------------------------------------------------
/src/icons/min-w-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-10.png
--------------------------------------------------------------------------------
/src/icons/min-w-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-12.png
--------------------------------------------------------------------------------
/src/icons/min-w-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-15.png
--------------------------------------------------------------------------------
/src/icons/min-w-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-20.png
--------------------------------------------------------------------------------
/src/icons/min-w-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-24.png
--------------------------------------------------------------------------------
/src/icons/min-w-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/min-w-30.png
--------------------------------------------------------------------------------
/src/icons/restore-k-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-10.png
--------------------------------------------------------------------------------
/src/icons/restore-k-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-12.png
--------------------------------------------------------------------------------
/src/icons/restore-k-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-15.png
--------------------------------------------------------------------------------
/src/icons/restore-k-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-20.png
--------------------------------------------------------------------------------
/src/icons/restore-k-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-24.png
--------------------------------------------------------------------------------
/src/icons/restore-k-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-k-30.png
--------------------------------------------------------------------------------
/src/icons/restore-w-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-10.png
--------------------------------------------------------------------------------
/src/icons/restore-w-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-12.png
--------------------------------------------------------------------------------
/src/icons/restore-w-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-15.png
--------------------------------------------------------------------------------
/src/icons/restore-w-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-20.png
--------------------------------------------------------------------------------
/src/icons/restore-w-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-24.png
--------------------------------------------------------------------------------
/src/icons/restore-w-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/icons/restore-w-30.png
--------------------------------------------------------------------------------
/src/img/alpaca-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/img/alpaca-web.png
--------------------------------------------------------------------------------
/src/img/alpaca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/img/alpaca.png
--------------------------------------------------------------------------------
/src/img/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ItsPi3141/alpaca-electron/04bad635d8cd57abaa6be1fee8a51144499c3eba/src/img/user.png
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Alpaca Electron
9 |
10 |
11 |
12 |
13 |
42 |
43 |
86 |
87 |
88 |
89 |
90 |
91 |
Alpaca Electron
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
Examples
107 | "Can you explain quantum computing in simple terms?" →
108 | "Do you have any creative ideas for a 10 year old’s birthday?" →
109 | "How do you make an HTTP request in Javascript?" →
110 |
111 |
112 |
113 |
114 |
115 |
116 |
Capabilities
117 |
Trained on 20 languages, mostly those with Latin or Cyrillic alphabets
118 |
Can answer questions naturally, try to use "you" rather than "I"
119 |
Will not deny your prompts
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
Limitations
129 |
May occasionally generate incorrect information
130 |
Not trained for writing code
131 |
Does not always provide information that is up to date
132 |
133 |
134 |
135 |
136 |
137 |
138 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
Couldn't load model
194 |
199 |
200 |
201 |
Enter the filepath for a LLaMA model.
202 |
You can change the model type in settings.
203 |
204 |
205 |
206 |
207 |
210 |
211 |
212 |
213 |
Invalid file path
214 |
215 |
216 | Cancel
217 | Confirm
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
Settings
227 |
232 |
233 |
234 |
235 |
Presets
236 |
You can choose a preset from here or customize your own settings below.
237 |
238 |
239 |
240 |
241 | Custom
242 | Alpaca
243 | Vicuna
244 | Llama
245 |
246 |
247 |
248 |
249 |
250 |
251 |
Llama.cpp settings
252 |
253 |
254 | AI model
255 |
256 |
257 | Alpaca
258 | Vicuna
259 | Llama
260 | Other
261 |
262 |
263 |
264 |
265 |
266 |
Repeat last n tokens
267 |
268 |
269 |
270 |
271 |
Repeat penalty
272 |
273 |
274 |
275 |
279 |
280 |
284 |
285 |
286 |
Temperature
287 |
288 |
289 |
290 |
291 |
Seed (set to -1 for random)
292 |
293 |
294 |
295 |
296 |
297 |
Web search settings
298 |
299 |
Web search result amount
300 |
301 |
302 |
303 |
304 |
305 | Cancel
306 | Save
307 |
308 |
309 |
310 |
311 |
314 |
315 |
316 |
--------------------------------------------------------------------------------
/src/prompts/alpaca.js:
--------------------------------------------------------------------------------
1 | const instruction = "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n";
2 | const prefix = {
3 | user: "### Instruction: ",
4 | bot: "### Response: "
5 | };
6 |
7 | module.exports = { instruction, prefix };
8 |
--------------------------------------------------------------------------------
/src/prompts/llama.js:
--------------------------------------------------------------------------------
1 | const instruction = "Transcript of a dialog, where the User interacts with an Assistant named Llama. Llama is helpful, kind, honest, good at writing, and never fails to answer the User's requests immediately and with precision.\n\n";
2 | const prefix = {
3 | user: "User: ",
4 | bot: "Llama: "
5 | };
6 |
7 | module.exports = { instruction, prefix };
8 |
--------------------------------------------------------------------------------
/src/prompts/vicuna.js:
--------------------------------------------------------------------------------
1 | const instruction = "A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions.\n\n";
2 | const prefix = {
3 | user: "### Human: ",
4 | bot: "### Assistant: "
5 | };
6 |
7 | module.exports = { instruction, prefix };
8 |
--------------------------------------------------------------------------------
/src/renderer.js:
--------------------------------------------------------------------------------
1 | const remote = require("@electron/remote");
2 | const { ipcRenderer } = require("electron");
3 |
4 | const win = remote.getCurrentWindow();
5 |
6 | document.onreadystatechange = () => {
7 | ipcRenderer.send("os");
8 | if (document.readyState == "complete") {
9 | handleWindowControls();
10 | }
11 | document.querySelector("#path-dialog-bg > div > div.dialog-button > button.secondary").style.display = "none";
12 | document.querySelector("#path-dialog-bg > div > div.dialog-title > h3").innerText = "Couldn't load model";
13 | ipcRenderer.send("checkModelPath");
14 | };
15 |
16 | ipcRenderer.on("os", (_error, { data }) => {
17 | document.querySelector("html").classList.add(data);
18 | });
19 |
20 | ipcRenderer.on("modelPathValid", (_event, { data }) => {
21 | if (data) {
22 | ipcRenderer.send("startChat");
23 | } else {
24 | ipcRenderer.send("getCurrentModel");
25 | document.getElementById("path-dialog-bg").classList.remove("hidden");
26 | }
27 | });
28 |
29 | document.querySelector("#path-dialog-bg > div > div.dialog-button > button.primary").addEventListener("click", () => {
30 | var path = document.querySelector("#path-dialog input[type=text]").value.replaceAll('"', "");
31 | ipcRenderer.send("checkPath", { data: path });
32 | });
33 |
34 | document.querySelector("#path-dialog-bg > div > div.dialog-button > button.secondary").addEventListener("click", () => {
35 | document.getElementById("path-dialog-bg").classList.add("hidden");
36 | });
37 |
38 | ipcRenderer.on("pathIsValid", (_event, { data }) => {
39 | console.log(data);
40 | if (data) {
41 | document.querySelector("#path-dialog > p.error-text").style.display = "none";
42 | document.getElementById("path-dialog-bg").classList.add("hidden");
43 | ipcRenderer.send("restart");
44 | } else {
45 | document.querySelector("#path-dialog > p.error-text").style.display = "block";
46 | }
47 | });
48 |
49 | document.querySelector("#path-dialog > div > button").addEventListener("click", () => {
50 | ipcRenderer.send("pickFile");
51 | });
52 | ipcRenderer.on("pickedFile", (_error, { data }) => {
53 | document.querySelector("#path-dialog input[type=text]").value = data;
54 | });
55 |
56 | ipcRenderer.on("currentModel", (_event, { data }) => {
57 | document.querySelector("#path-dialog input[type=text]").value = data;
58 | });
59 |
60 | document.querySelector("#path-dialog input[type=text]").addEventListener("keypress", (e) => {
61 | if (e.keyCode === 13) {
62 | e.preventDefault();
63 | document.querySelector("#path-dialog-bg .dialog-button button.primary").click();
64 | }
65 | });
66 |
67 | window.onbeforeunload = () => {
68 | win.removeAllListeners();
69 | };
70 |
71 | function handleWindowControls() {
72 | document.getElementById("min-button").addEventListener("click", () => {
73 | win.minimize();
74 | });
75 |
76 | document.getElementById("max-button").addEventListener("click", () => {
77 | win.maximize();
78 | });
79 |
80 | document.getElementById("restore-button").addEventListener("click", () => {
81 | win.unmaximize();
82 | });
83 |
84 | document.getElementById("close-button").addEventListener("click", () => {
85 | win.close();
86 | });
87 |
88 | toggleMaxRestoreButtons();
89 | win.on("maximize", toggleMaxRestoreButtons);
90 | win.on("unmaximize", toggleMaxRestoreButtons);
91 |
92 | function toggleMaxRestoreButtons() {
93 | if (win.isMaximized()) {
94 | document.body.classList.add("maximized");
95 | } else {
96 | document.body.classList.remove("maximized");
97 | }
98 | }
99 | }
100 |
101 | var gen = 0;
102 | const form = document.getElementById("form");
103 | const stopButton = document.getElementById("stop");
104 | const input = document.getElementById("input");
105 | const messages = document.getElementById("messages");
106 |
107 | input.addEventListener("keydown", () => {
108 | setTimeout(() => {
109 | input.style.height = "auto";
110 | input.style.height = input.scrollHeight + "px";
111 | });
112 | });
113 | input.addEventListener("keyup", () => {
114 | setTimeout(() => {
115 | input.style.height = "auto";
116 | input.style.height = input.scrollHeight + "px";
117 | });
118 | });
119 |
120 | let isRunningModel = false;
121 | const loading = (on) => {
122 | if (on) {
123 | document.querySelector(".loading").classList.remove("hidden");
124 | } else {
125 | document.querySelector(".loading").classList.add("hidden");
126 | }
127 | };
128 |
129 | form.addEventListener("submit", (e) => {
130 | e.preventDefault();
131 | e.stopPropagation();
132 | if (form.classList.contains("running-model")) return;
133 | if (input.value) {
134 | var prompt = input.value.replaceAll("\n", "\\n");
135 | ipcRenderer.send("message", { data: prompt });
136 | say(input.value, `user${gen}`, true);
137 | loading(prompt);
138 | input.value = "";
139 | isRunningModel = true;
140 | stopButton.removeAttribute("disabled");
141 | form.setAttribute("class", isRunningModel ? "running-model" : "");
142 | gen++;
143 | setTimeout(() => {
144 | input.style.height = "auto";
145 | input.style.height = input.scrollHeight + "px";
146 | });
147 | }
148 | });
149 | input.addEventListener("keydown", (e) => {
150 | if (e.keyCode === 13) {
151 | e.preventDefault();
152 | if (e.shiftKey) {
153 | document.execCommand("insertLineBreak");
154 | } else {
155 | form.requestSubmit();
156 | }
157 | }
158 | });
159 |
160 | stopButton.addEventListener("click", (e) => {
161 | e.preventDefault();
162 | e.stopPropagation();
163 | ipcRenderer.send("stopGeneration");
164 | stopButton.setAttribute("disabled", "true");
165 | setTimeout(() => {
166 | isRunningModel = false;
167 | form.setAttribute("class", isRunningModel ? "running-model" : "");
168 | input.style.height = "34px";
169 | }, 5);
170 | });
171 |
172 | const sha256 = async (input) => {
173 | const textAsBuffer = new TextEncoder().encode(input);
174 | const hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
175 | const hashArray = Array.from(new Uint8Array(hashBuffer));
176 | const hash = hashArray.map((item) => item.toString(16).padStart(2, "0")).join("");
177 | return hash;
178 | };
179 | const say = (msg, id, isUser) => {
180 | let item = document.createElement("li");
181 | if (id) item.setAttribute("data-id", id);
182 | item.classList.add(isUser ? "user-msg" : document.getElementById("web-access").checked ? "bot-web-msg" : "bot-msg");
183 | console.log(msg);
184 |
185 | //escape html tag
186 | if (isUser) {
187 | msg = msg.replaceAll(//g, ">");
189 | }
190 |
191 | item.innerHTML = msg;
192 | if (document.getElementById("bottom").getBoundingClientRect().y - 40 < window.innerHeight) {
193 | setTimeout(() => {
194 | bottom.scrollIntoView({ behavior: "smooth", block: "end" });
195 | }, 100);
196 | }
197 | messages.append(item);
198 | };
199 | var responses = [];
200 |
201 | Date.prototype.timeNow = function () {
202 | return (this.getHours() < 10 ? "0" : "") + this.getHours() + ":" + (this.getMinutes() < 10 ? "0" : "") + this.getMinutes() + ":" + (this.getSeconds() < 10 ? "0" : "") + this.getSeconds();
203 | };
204 | Date.prototype.today = function () {
205 | return (this.getDate() < 10 ? "0" : "") + this.getDate() + "/" + (this.getMonth() + 1 < 10 ? "0" : "") + (this.getMonth() + 1) + "/" + this.getFullYear();
206 | };
207 |
208 | ipcRenderer.on("result", async (_event, { data }) => {
209 | var response = data;
210 | loading(false);
211 | if (data == "\n\n") {
212 | setTimeout(() => {
213 | isRunningModel = false;
214 | form.setAttribute("class", isRunningModel ? "running-model" : "");
215 | }, 200);
216 | } else {
217 | document.body.classList.remove("llama");
218 | document.body.classList.remove("alpaca");
219 | isRunningModel = true;
220 | form.setAttribute("class", isRunningModel ? "running-model" : "");
221 | const id = gen;
222 | let existing = document.querySelector(`[data-id='${id}']`);
223 | if (existing) {
224 | if (!responses[id]) {
225 | responses[id] = document.querySelector(`[data-id='${id}']`).innerHTML;
226 | }
227 |
228 | responses[id] = responses[id] + response;
229 |
230 | if (responses[id].startsWith(" ")) {
231 | responses[id] = responses[id].replace(" ", "");
232 | }
233 | if (responses[id].startsWith("\n")) {
234 | responses[id] = responses[id].replace("\n", "");
235 | }
236 |
237 | responses[id] = responses[id].replaceAll(/\r?\n\x1B\[\d+;\d+H./g, "");
238 | responses[id] = responses[id].replaceAll(/\x08\r?\n?/g, "");
239 |
240 | responses[id] = responses[id].replaceAll("\\t", " "); //tab characters
241 | responses[id] = responses[id].replaceAll("\\b", " "); //no break space
242 | responses[id] = responses[id].replaceAll("\\f", " "); //no break space
243 | responses[id] = responses[id].replaceAll("\\r", "\n"); //sometimes /r is used in codeblocks
244 |
245 | responses[id] = responses[id].replaceAll("\\n", "\n"); //convert line breaks back
246 | responses[id] = responses[id].replaceAll("\\\n", "\n"); //convert line breaks back
247 | responses[id] = responses[id].replaceAll('\\\\\\""', '"'); //convert quotes back
248 |
249 | responses[id] = responses[id].replaceAll(/\[name\]/gi, "Alpaca");
250 |
251 | responses[id] = responses[id].replaceAll(/(<|\[|#+)((current|local)_)?time(>|\]|#+)/gi, new Date().timeNow());
252 | responses[id] = responses[id].replaceAll(/(<|\[|#+)(current_)?date(>|\]|#+)/gi, new Date().today());
253 | responses[id] = responses[id].replaceAll(/(<|\[|#+)day_of_(the_)?week(>|\]|#+)/gi, new Date().toLocaleString("en-us", { weekday: "long" }));
254 |
255 | responses[id] = responses[id].replaceAll(/(<|\[|#+)(current_)?year(>|\]|#+)/gi, new Date().getFullYear());
256 | responses[id] = responses[id].replaceAll(/(<|\[|#+)(current_)?month(>|\]|#+)/gi, new Date().getMonth() + 1);
257 | responses[id] = responses[id].replaceAll(/(<|\[|#+)(current_)?day(>|\]|#+)/gi, new Date().getDate());
258 |
259 | //escape html tag
260 | responses[id] = responses[id].replaceAll(//g, ">");
262 |
263 | // if scroll is within 8px of the bottom, scroll to bottom
264 | if (document.getElementById("bottom").getBoundingClientRect().y - 40 < window.innerHeight) {
265 | setTimeout(() => {
266 | bottom.scrollIntoView({ behavior: "smooth", block: "end" });
267 | }, 100);
268 | }
269 | existing.innerHTML = responses[id];
270 | } else {
271 | say(response, id);
272 | }
273 | }
274 | });
275 |
276 | document.querySelectorAll("#feed-placeholder-llama button.card").forEach((e) => {
277 | e.addEventListener("click", () => {
278 | let text = e.innerText.replace('"', "").replace('" →', "");
279 | input.value = text;
280 | });
281 | });
282 | document.querySelectorAll("#feed-placeholder-alpaca button.card").forEach((e) => {
283 | e.addEventListener("click", () => {
284 | let text = e.innerText.replace('"', "").replace('" →', "");
285 | input.value = text;
286 | });
287 | });
288 |
289 | const cpuText = document.querySelector("#cpu .text");
290 | const ramText = document.querySelector("#ram .text");
291 | const cpuBar = document.querySelector("#cpu .bar-inner");
292 | const ramBar = document.querySelector("#ram .bar-inner");
293 |
294 | var cpuCount, threadUtilized, totalmem, cpuPercent, freemem;
295 | ipcRenderer.send("cpuCount");
296 | ipcRenderer.send("threadUtilized");
297 | ipcRenderer.send("totalmem");
298 | ipcRenderer.on("cpuCount", (_event, { data }) => {
299 | cpuCount = data;
300 | });
301 | ipcRenderer.on("threadUtilized", (_event, { data }) => {
302 | threadUtilized = data;
303 | });
304 | ipcRenderer.on("totalmem", (_event, { data }) => {
305 | totalmem = Math.round(data / 102.4) / 10;
306 | });
307 |
308 | setInterval(async () => {
309 | ipcRenderer.send("cpuUsage");
310 | ipcRenderer.send("freemem");
311 | }, 1500);
312 | ipcRenderer.on("cpuUsage", (_event, { data }) => {
313 | cpuPercent = Math.round(data * 100);
314 | cpuText.innerText = `CPU: ${cpuPercent}%, ${threadUtilized}/${cpuCount} threads`;
315 | cpuBar.style.transform = `scaleX(${cpuPercent / 100})`;
316 | });
317 | ipcRenderer.on("freemem", (_event, { data }) => {
318 | freemem = data;
319 | ramText.innerText = `RAM: ${Math.round((totalmem - freemem) * 10) / 10}GB/${totalmem}GB`;
320 | ramBar.style.transform = `scaleX(${(totalmem - freemem) / totalmem})`;
321 | });
322 |
323 | document.getElementById("clear").addEventListener("click", () => {
324 | input.value = "";
325 | setTimeout(() => {
326 | input.style.height = "auto";
327 | input.style.height = input.scrollHeight + "px";
328 | });
329 | });
330 |
331 | document.getElementById("clear-chat").addEventListener("click", () => {
332 | stopButton.click();
333 | stopButton.removeAttribute("disabled");
334 | document.querySelectorAll("#messages li").forEach((element) => {
335 | element.remove();
336 | });
337 | setTimeout(() => {
338 | document.querySelectorAll("#messages li").forEach((element) => {
339 | element.remove();
340 | });
341 | }, 100);
342 | });
343 | document.getElementById("change-model").addEventListener("click", () => {
344 | ipcRenderer.send("getCurrentModel");
345 | document.querySelector("#path-dialog-bg > div > div.dialog-button > button.secondary").style.display = "";
346 | document.querySelector("#path-dialog-bg > div > div.dialog-title > h3").innerText = "Change model path";
347 | document.getElementById("path-dialog-bg").classList.remove("hidden");
348 | });
349 |
350 | ipcRenderer.send("getParams");
351 | document.getElementById("settings").addEventListener("click", () => {
352 | document.getElementById("settings-dialog-bg").classList.remove("hidden");
353 | ipcRenderer.send("getParams");
354 | });
355 | ipcRenderer.on("params", (_event, data) => {
356 | document.getElementById("model").value = data.model_type;
357 | document.getElementById("repeat_last_n").value = data.repeat_last_n;
358 | document.getElementById("repeat_penalty").value = data.repeat_penalty;
359 | document.getElementById("top_k").value = data.top_k;
360 | document.getElementById("top_p").value = data.top_p;
361 | document.getElementById("temp").value = data.temp;
362 | document.getElementById("seed").value = data.seed;
363 | document.getElementById("web-access").checked = data.webAccess;
364 | });
365 | document.querySelector("#settings-dialog-bg > div > div.dialog-button > button.primary").addEventListener("click", () => {
366 | ipcRenderer.send("storeParams", {
367 | params: {
368 | model_type: document.getElementById("model").value,
369 | repeat_last_n: document.getElementById("repeat_last_n").value || document.getElementById("repeat_last_n").placeholder,
370 | repeat_penalty: document.getElementById("repeat_penalty").value || document.getElementById("repeat_penalty").placeholder,
371 | top_k: document.getElementById("top_k").value || document.getElementById("top_k").placeholder,
372 | top_p: document.getElementById("top_p").value || document.getElementById("top_p").placeholder,
373 | temp: document.getElementById("temp").value || document.getElementById("temp").placeholder,
374 | seed: document.getElementById("seed").value || document.getElementById("seed").placeholder,
375 | webAccess: document.getElementById("web-access").checked,
376 | websearch_amount: document.getElementById("websearch_amount").value || document.getElementById("websearch_amount").placeholder
377 | }
378 | });
379 | document.getElementById("settings-dialog-bg").classList.add("hidden");
380 | });
381 | document.querySelector("#settings-dialog-bg > div > div.dialog-button > button.secondary").addEventListener("click", () => {
382 | document.getElementById("settings-dialog-bg").classList.add("hidden");
383 | });
384 |
385 | document.getElementById("web-access").addEventListener("change", () => {
386 | ipcRenderer.send("webAccess", document.getElementById("web-access").checked);
387 | });
388 |
389 | document.getElementById("settings-preset").addEventListener("change", () => {
390 | console.log("hi");
391 | const value = document.getElementById("settings-preset").value;
392 | if (value == "alpaca") {
393 | document.getElementById("model").value = "alpaca";
394 | document.getElementById("repeat_last_n").value = 64;
395 | document.getElementById("repeat_penalty").value = 1.3;
396 | document.getElementById("top_k").value = 420;
397 | document.getElementById("top_p").value = 90;
398 | document.getElementById("temp").value = 0.9;
399 | } else if (value == "vicuna") {
400 | document.getElementById("model").value = "vicuna";
401 | document.getElementById("repeat_last_n").value = 64;
402 | document.getElementById("repeat_penalty").value = 1.1;
403 | document.getElementById("top_k").value = 420;
404 | document.getElementById("top_p").value = 10;
405 | document.getElementById("temp").value = 0.7;
406 | } else if (value == "llama") {
407 | document.getElementById("model").value = "llama";
408 | document.getElementById("repeat_last_n").value = 64;
409 | document.getElementById("repeat_penalty").value = 1.3;
410 | document.getElementById("top_k").value = 420;
411 | document.getElementById("top_p").value = 90;
412 | document.getElementById("temp").value = 0.8;
413 | }
414 | });
415 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "IBM Plex";
3 | src: url("fonts/IBM Plex/IBMPlexSans-Light.ttf");
4 | font-weight: normal;
5 | }
6 | @font-face {
7 | font-family: "IBM Plex";
8 | src: url("fonts/IBM Plex/IBMPlexSans-Regular.ttf");
9 | font-weight: normal;
10 | }
11 |
12 | :root {
13 | --primary-text: #d1d5db;
14 | --primary-text-alt: #ececf1;
15 | --secondary-text: #ffffff80;
16 | --background: #343541;
17 | --background-mid: #2c2d30;
18 | --background-alt: #202123;
19 | --surface: #444654;
20 | --surface-alt: #565869;
21 | --surface-alt-bright: #acacbe;
22 | --tertiary: #3e3f4b;
23 | --accent: rgba(16, 163, 127);
24 | --secondary: rgba(26, 127, 100);
25 | --error: #ff5d5d;
26 | --overlay: rgba(52, 53, 65, 0.9);
27 | --hover: hsla(240, 9%, 59%, 0.1);
28 | --text-box-border: rgba(32, 33, 35, 0.5);
29 | --border: rgb(64, 65, 79);
30 | --small-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
31 | }
32 |
33 | @media (prefers-color-scheme: light) {
34 | :root {
35 | --primary-text: #374151;
36 | --primary-text-alt: #343541;
37 | --secondary-text: #00000080;
38 | --background: #ffffff;
39 | --background-mid: #d9d9e3;
40 | --background-alt: #ffffff;
41 | --surface: #ffffff;
42 | --surface-alt: #bfc0cc;
43 | --surface-alt-bright: #acacbe;
44 | --tertiary: #f7f7f8;
45 | --accent: rgba(16, 163, 127);
46 | --secondary: rgba(26, 127, 100);
47 | --error: #ff5d5d;
48 | --overlay: rgba(141, 141, 160, 0.9);
49 | --hover: hsla(240, 9%, 59%, 0.1);
50 | --text-box-border: rgba(0, 0, 0, 0.1);
51 | --border: rgb(166, 169, 202);
52 | --small-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
53 | }
54 | }
55 |
56 | *::-webkit-scrollbar {
57 | -webkit-appearance: none;
58 | }
59 | *::-webkit-scrollbar:vertical {
60 | width: 8px;
61 | }
62 | *::-webkit-scrollbar:horizontal {
63 | height: 8px;
64 | }
65 | *::-webkit-scrollbar-thumb {
66 | border-radius: 8px;
67 | background-color: var(--surface-alt);
68 | }
69 | *::-webkit-scrollbar-thumb:hover {
70 | background-color: #acacbe;
71 | }
72 | *::-webkit-scrollbar-track {
73 | background-color: transparent;
74 | border-radius: 8px;
75 | }
76 |
77 | * {
78 | color: var(--primary-text);
79 | font-size: 1rem;
80 | line-height: 28px;
81 | /* font-family: Sohne; */
82 | font-family: "IBM Plex", ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
83 | font-weight: normal;
84 | }
85 | h1,
86 | h2,
87 | h3,
88 | h4,
89 | h5,
90 | h6 {
91 | font-size: revert;
92 | font-weight: bold;
93 | }
94 |
95 | code {
96 | line-height: 1.5;
97 | display: block;
98 | overflow: auto hidden;
99 | /* font-family: "Sohne Mono"; */
100 | font-family: Monaco, Andale Mono, Ubuntu Mono, monospace;
101 | }
102 | pre:has(code) {
103 | padding: 8px;
104 | border-radius: 8px;
105 | background: #8883;
106 | border: #8884 solid 1px;
107 | }
108 |
109 | button {
110 | cursor: pointer;
111 | }
112 |
113 | html,
114 | body {
115 | background-color: var(--background-mid);
116 | }
117 | body {
118 | margin: 0;
119 | padding: 0px;
120 | overflow: hidden;
121 | }
122 |
123 | .input-field {
124 | background: var(--surface);
125 | display: flex;
126 | padding: 10px;
127 | box-sizing: border-box;
128 | box-shadow: 0 0 15px #00000010;
129 | border-radius: 0.375rem;
130 | border: solid 1px var(--text-box-border);
131 | pointer-events: all;
132 | }
133 | #input {
134 | white-space: pre-wrap;
135 | padding: 5px;
136 | outline: none;
137 | border: none;
138 | flex-grow: 1;
139 | box-sizing: border-box;
140 | background: none;
141 | max-height: 200px;
142 | overflow: hidden scroll;
143 | resize: none;
144 | line-height: 24px;
145 | }
146 | #input:focus {
147 | outline: none;
148 | }
149 | button {
150 | color: white;
151 | border: none;
152 | border-radius: 5px;
153 | outline: none;
154 | box-sizing: border-box;
155 | background: #0005;
156 | }
157 | button#stop,
158 | button#autocomplete,
159 | button#clear {
160 | background: none;
161 | height: 32px;
162 | width: 32px;
163 | align-items: center;
164 | justify-content: center;
165 | }
166 | button#clear {
167 | opacity: 0.75;
168 | margin-right: 5px;
169 | }
170 | button#stop:hover,
171 | button#autocomplete:hover,
172 | button#clear:hover {
173 | background: var(--background-alt);
174 | }
175 | button#stop,
176 | .running-model button#autocomplete {
177 | display: none;
178 | }
179 | .running-model button#stop,
180 | button#autocomplete,
181 | button#clear {
182 | display: flex;
183 | }
184 | #input:placeholder-shown ~ button#clear {
185 | display: none;
186 | }
187 |
188 | #main {
189 | display: flex;
190 | margin-top: 32px;
191 | max-height: calc(100vh - 32px);
192 | position: fixed;
193 | top: 0;
194 | left: 0;
195 | }
196 | html.darwin #main {
197 | margin-top: 28px;
198 | max-height: calc(100vh - 28px);
199 | }
200 | #feed {
201 | width: calc(100vw - 200px);
202 | height: 100vh;
203 | overflow-y: auto;
204 | background-color: var(--background);
205 | }
206 | .logo {
207 | font-weight: bold;
208 | display: block;
209 | font-size: 2.25rem;
210 | line-height: 2.5rem;
211 | color: var(--primary-text-alt);
212 | margin: 0 auto 4rem;
213 | }
214 | #feed-placeholder-alpaca {
215 | text-align: center;
216 | max-width: 48rem;
217 | margin: auto;
218 | display: block;
219 | margin: 20vh auto 12rem;
220 | }
221 | #feed-placeholder-alpaca:not(:last-child) {
222 | display: none;
223 | }
224 | @media (max-width: 1024px) {
225 | #feed-placeholder-alpaca {
226 | text-align: center;
227 | max-width: 48rem;
228 | margin: auto;
229 | display: block;
230 | margin: 20vh 1.5rem 12rem;
231 | }
232 | }
233 |
234 | .columns,
235 | .column {
236 | display: flex;
237 | gap: 0.875rem;
238 | }
239 | .columns {
240 | justify-content: space-around;
241 | }
242 | .column {
243 | flex-direction: column;
244 | align-items: center;
245 | flex: 1 1 0%;
246 | }
247 | .column h3 {
248 | margin: 0;
249 | }
250 | .column .card {
251 | background-color: var(--tertiary);
252 | padding: 0.75rem;
253 | letter-spacing: 0.1px;
254 | font-size: 0.9rem;
255 | border-radius: 0.375rem;
256 | width: calc(100% - 1.75rem);
257 | color: var(--primary-text-alt);
258 | }
259 | .column button.card {
260 | width: 100%;
261 | }
262 | .column button.card:hover {
263 | background-color: var(--background-mid);
264 | }
265 |
266 | #messages {
267 | list-style-type: none;
268 | margin: 0;
269 | box-sizing: border-box;
270 | padding: 0;
271 | margin-bottom: 200px;
272 | }
273 | #messages > li {
274 | box-sizing: border-box;
275 | padding: 24px calc((100% - 48rem + 96px) / 2) 24px calc((100% - 48rem + 96px) / 2 + 48px);
276 | }
277 | #messages > li.user-msg {
278 | background: var(--surface);
279 | }
280 | #messages > li > br {
281 | display: none;
282 | }
283 | li {
284 | white-space: pre-wrap;
285 | }
286 | #messages > li::before {
287 | width: 32px;
288 | height: 32px;
289 | content: "";
290 | display: inline-block;
291 | background-size: cover;
292 | position: relative;
293 | margin-left: -48px;
294 | margin-right: 16px;
295 | margin-top: -32px;
296 | top: 14px;
297 | border-radius: 5px;
298 | }
299 | #messages > li.user-msg::before {
300 | background-image: url(img/user.png);
301 | }
302 | #messages > li.bot-msg::before {
303 | background-image: url(img/alpaca.png);
304 | }
305 | #messages > li.bot-web-msg::before {
306 | background-image: url(img/alpaca-web.png);
307 | }
308 |
309 | @-webkit-keyframes spin {
310 | to {
311 | -webkit-transform: rotate(1turn);
312 | transform: rotate(1turn);
313 | }
314 | }
315 |
316 | @keyframes spin {
317 | to {
318 | -webkit-transform: rotate(1turn);
319 | transform: rotate(1turn);
320 | }
321 | }
322 | .loading {
323 | margin-bottom: 10px;
324 | padding: 10px;
325 | box-sizing: border-box;
326 | background: none;
327 | opacity: 0;
328 | pointer-events: none;
329 | }
330 | .loading svg {
331 | animation: spin 1s linear infinite;
332 | }
333 | /* .hidden */
334 | form.running-model .loading {
335 | opacity: 1;
336 | }
337 |
338 | .input-container {
339 | margin: 10px 48px;
340 | max-width: 48rem;
341 | width: calc(100vw - 296px);
342 | }
343 | .info {
344 | font-size: 12px;
345 | padding: 5px;
346 | text-align: center;
347 | }
348 |
349 | #form {
350 | position: fixed;
351 | bottom: 0;
352 | width: calc(100vw - 200px);
353 | display: flex;
354 | flex-direction: column;
355 | align-items: center;
356 | background-image: linear-gradient(180deg, #0000, var(--background) 58.85%);
357 | margin: 0;
358 | pointer-events: none;
359 | }
360 | .form-header {
361 | display: flex;
362 | align-items: start;
363 | justify-content: flex-start;
364 | margin: 0;
365 | width: 200px;
366 | background-color: #202123;
367 | height: calc(100vh - 182px);
368 | overflow: hidden auto;
369 | flex-direction: column;
370 | }
371 | .form-header * {
372 | color: #d1d5db;
373 | }
374 | input[type="number"],
375 | input[type="text"],
376 | select {
377 | margin-bottom: 10px !important;
378 | border: #fff1 solid 1px;
379 | outline: none;
380 | background: rgba(0, 0, 0, 0.08);
381 | border-radius: 5px;
382 | padding: 5px 10px;
383 | box-sizing: border-box;
384 | }
385 | input[type="number"]:focus,
386 | input[type="text"]:focus,
387 | select:focus {
388 | border: #fff3 solid 1px;
389 | }
390 | select {
391 | display: inline-block;
392 | -webkit-appearance: none;
393 | -moz-appearance: none;
394 | appearance: none;
395 | cursor: pointer;
396 | padding-right: 40px;
397 | text-overflow: ellipsis;
398 | }
399 | label.dropdown-arrow {
400 | position: relative;
401 | }
402 | label.dropdown-arrow:after {
403 | content: ">";
404 | font: 16px "Consolas", monospace;
405 | color: #888;
406 | -webkit-transform: rotate(90deg);
407 | -moz-transform: rotate(90deg);
408 | transform: rotate(90deg);
409 | right: 5px;
410 | top: 5px;
411 | padding: 0 0 5px;
412 | width: 24px;
413 | height: 24px;
414 | display: flex;
415 | align-items: center;
416 | justify-content: center;
417 | border-bottom: 1px solid #8885;
418 | position: absolute;
419 | pointer-events: none;
420 | }
421 | option {
422 | background-color: #202123;
423 | height: 20px;
424 | }
425 |
426 | .config-container {
427 | display: flex;
428 | flex-wrap: wrap;
429 | width: 160px;
430 | padding: 10px 20px;
431 | padding-bottom: 200px;
432 | }
433 | .kv {
434 | display: block;
435 | max-width: 100%;
436 | }
437 | .kv label {
438 | display: block;
439 | padding: 5px 0px;
440 | font-size: 12px;
441 | max-width: 100%;
442 | }
443 | .kv input {
444 | max-width: 100%;
445 | }
446 |
447 | .switch {
448 | position: relative;
449 | display: inline-block;
450 | width: 3rem;
451 | height: 1rem;
452 | pointer-events: all;
453 | }
454 |
455 | .switch input {
456 | opacity: 0;
457 | width: 0;
458 | height: 0;
459 | }
460 |
461 | .slider {
462 | position: absolute;
463 | cursor: pointer;
464 | top: 0;
465 | left: 6px;
466 | height: 1.25rem;
467 | width: 2.25rem;
468 | background-color: var(--surface-alt);
469 | -webkit-transition: 0.4s;
470 | transition: 0.4s;
471 | border-radius: 420px;
472 | }
473 | .slider:before {
474 | position: absolute;
475 | content: "";
476 | height: 1rem;
477 | width: 1rem;
478 | left: 0.125rem;
479 | top: 0.125rem;
480 | background-color: white;
481 | -webkit-transition: 0.4s;
482 | transition: 0.4s;
483 | border-radius: 69px;
484 | }
485 | input:checked + .slider {
486 | background-color: var(--accent);
487 | }
488 | input:checked + .slider:before {
489 | -webkit-transform: translateX(1rem);
490 | -ms-transform: translateX(1rem);
491 | transform: translateX(1rem);
492 | }
493 | .slider.round {
494 | border-radius: 34px;
495 | }
496 | .slider.round:before {
497 | border-radius: 50%;
498 | }
499 |
500 | .action-button {
501 | margin: 0.5rem 0.5rem 0;
502 | padding: 0.75rem 1rem;
503 | display: flex;
504 | align-items: center;
505 | gap: 0.75rem;
506 | width: calc(100% - 3rem);
507 | border-radius: 0.375rem;
508 | cursor: pointer;
509 | background-color: transparent;
510 | transition: all 0.1s ease-out;
511 | }
512 | .action-button:hover {
513 | background-color: var(--hover);
514 | }
515 |
516 | #resources {
517 | position: fixed;
518 | width: 200px;
519 | height: 150px;
520 | background-color: #2c2d30;
521 | bottom: 0;
522 | left: 0;
523 | display: flex;
524 | flex-direction: column;
525 | align-items: center;
526 | justify-content: left;
527 | }
528 | .resource-item {
529 | flex: 1 1 100%;
530 | width: 100%;
531 | display: flex;
532 | flex-direction: column;
533 | align-items: flex-start;
534 | justify-content: center;
535 | }
536 | .resource-item:not(:first-child) {
537 | border-top: 1px #fff1 solid;
538 | }
539 | .resource-item * {
540 | margin: 0 25px;
541 | line-height: 14px;
542 | color: #d1d5db;
543 | }
544 | .resource-item .text {
545 | padding: 5px 0;
546 | }
547 | .bar {
548 | width: 142px;
549 | height: 10px;
550 | border-radius: 69px;
551 | background-color: #565869;
552 | overflow: hidden;
553 | }
554 | .bar-inner {
555 | height: 100%;
556 | width: 100%;
557 | margin: 0;
558 | background-color: var(--accent);
559 | transform: scaleX(0);
560 | transform-origin: left;
561 | transition: transform 1s linear;
562 | }
563 |
564 | .dialog-bg {
565 | background-color: var(--overlay);
566 | width: 100vw;
567 | height: 100vh;
568 | margin: 0;
569 | position: fixed;
570 | top: 0;
571 | left: 0;
572 | display: flex;
573 | align-items: center;
574 | justify-content: center;
575 | transition: all 0.1s;
576 | opacity: 1;
577 | }
578 | .dialog-bg.hidden {
579 | opacity: 0;
580 | pointer-events: none;
581 | }
582 | .dialog-box {
583 | width: 500px;
584 | background-color: var(--background-alt);
585 | display: flex;
586 | flex-direction: column;
587 | border-radius: 0.375rem;
588 | border: 1px var(--border) solid;
589 | box-shadow: var(--small-shadow);
590 | transition: all 0.1s;
591 | transform: scale(1);
592 | }
593 | .dialog-bg.hidden .dialog-box {
594 | transform: scale(0.85);
595 | }
596 | .dialog-title {
597 | display: flex;
598 | flex-direction: row;
599 | align-items: center;
600 | justify-content: space-between;
601 | padding: 0.75rem 1rem;
602 | border-bottom: 1px var(--border) solid;
603 | }
604 | .dialog-title * {
605 | margin: 0;
606 | }
607 | .dialog-close {
608 | background-color: transparent;
609 | display: flex;
610 | align-items: center;
611 | justify-content: center;
612 | }
613 | .dialog-content {
614 | display: flex;
615 | flex-direction: column;
616 | padding: 1rem;
617 | gap: 0.75rem;
618 | border-bottom: 1px var(--border) solid;
619 | max-height: calc(100vh - 300px);
620 | overflow-y: scroll;
621 | }
622 | .dialog-content * {
623 | margin: 0;
624 | }
625 | .dialog-button {
626 | display: flex;
627 | flex-direction: row;
628 | align-items: center;
629 | justify-content: flex-end;
630 | padding: 0.75rem 1rem;
631 | gap: 0.75rem;
632 | }
633 | .dialog-button button {
634 | padding: 0.5rem 1rem;
635 | transition: all 0.1s;
636 | }
637 | button.primary {
638 | background-color: var(--accent);
639 | }
640 | button.primary:hover {
641 | background-color: var(--secondary);
642 | }
643 | button.secondary {
644 | background-color: var(--surface-alt);
645 | }
646 | button.secondary:hover {
647 | background-color: var(--surface);
648 | }
649 | @media (prefers-color-scheme: light) {
650 | button.secondary:hover {
651 | background-color: #b1b3c2;
652 | }
653 | }
654 |
655 | p.error-text {
656 | font-size: 12px;
657 | color: var(--error);
658 | margin: 0;
659 | margin-top: -24px;
660 | }
661 | p.error-text::before {
662 | content: "⚠ ";
663 | font-weight: lighter;
664 | font-size: 20px;
665 | position: relative;
666 | top: 2px;
667 | }
668 | #path-dialog input[type="text"] {
669 | flex-grow: 1;
670 | text-overflow: ellipsis;
671 | }
672 | #path-dialog button {
673 | width: 40px;
674 | height: 40px;
675 | }
676 |
677 | .settings-items > .item {
678 | display: flex;
679 | justify-content: space-between;
680 | align-items: center;
681 | }
682 | .settings-items > .item > input,
683 | .settings-items > .item select {
684 | width: 7.5rem;
685 | }
686 |
--------------------------------------------------------------------------------
/src/titlebar.css:
--------------------------------------------------------------------------------
1 | #titlebar {
2 | display: block;
3 | position: fixed;
4 | top: 0;
5 | height: 24px; /* 32px - padding of 2*4px */
6 | width: calc(100% - 8px);
7 | background-color: transparent;
8 | padding: 4px;
9 | cursor: initial;
10 | user-select: none;
11 | z-index: 9999;
12 | color: #fff;
13 | -webkit-app-region: drag;
14 | }
15 | .maximized #titlebar {
16 | width: 100%;
17 | }
18 | #titlebar #drag-region {
19 | width: 100%;
20 | height: 100%;
21 | display: grid;
22 | grid-template-columns: auto 138px;
23 | }
24 | #window-title {
25 | grid-column: 1;
26 | display: flex;
27 | align-items: center;
28 | margin-left: 8px;
29 | overflow: hidden;
30 | font-family: "Segoe UI", sans-serif;
31 | font-size: 12px;
32 | }
33 | .maximized #window-title {
34 | margin-left: 12px;
35 | }
36 | #window-title span {
37 | overflow: hidden;
38 | text-overflow: ellipsis;
39 | white-space: nowrap;
40 | line-height: 1.5;
41 | font-size: larger;
42 | }
43 | #window-controls {
44 | display: grid;
45 | grid-template-columns: repeat(3, 46px);
46 | position: absolute;
47 | top: 0;
48 | right: 0;
49 | height: 100%;
50 | }
51 | .maximized #window-controls {
52 | right: 8px;
53 | }
54 | #window-controls .button {
55 | -webkit-app-region: no-drag;
56 | grid-row: 1 / span 1;
57 | display: flex;
58 | justify-content: center;
59 | align-items: center;
60 | width: 100%;
61 | height: 100%;
62 | }
63 | @media (-webkit-device-pixel-ratio: 1.5), (device-pixel-ratio: 1.5), (-webkit-device-pixel-ratio: 2), (device-pixel-ratio: 2), (-webkit-device-pixel-ratio: 3), (device-pixel-ratio: 3) {
64 | #window-controls .icon {
65 | width: 10px;
66 | height: 10px;
67 | }
68 | }
69 | #window-controls .button {
70 | user-select: none;
71 | }
72 | #window-controls .button:hover {
73 | background: rgba(128, 128, 128, 0.2);
74 | }
75 | #window-controls .button:active {
76 | background: rgba(128, 128, 128, 0.3);
77 | }
78 | #close-button:hover {
79 | background: #e81123 !important;
80 | }
81 | #close-button:active {
82 | background: #f1707a !important;
83 | }
84 | #close-button:active .icon {
85 | filter: invert(1);
86 | }
87 | @media (prefers-color-scheme: light) {
88 | .icon {
89 | filter: invert(1);
90 | }
91 | }
92 | #min-button {
93 | grid-column: 1;
94 | }
95 | #max-button,
96 | #restore-button {
97 | grid-column: 2;
98 | }
99 | #close-button {
100 | grid-column: 3;
101 | }
102 | #restore-button {
103 | display: none !important;
104 | }
105 | .maximized #restore-button {
106 | display: flex !important;
107 | }
108 | .maximized #max-button {
109 | display: none;
110 | }
111 |
112 | html.darwin #titlebar {
113 | height: 28px !important;
114 | }
115 | html.darwin #window-controls {
116 | display: none !important;
117 | }
118 | html.darwin #window-title {
119 | justify-content: center !important;
120 | align-items: flex-start !important;
121 | }
122 | html.darwin #drag-region {
123 | grid-template-columns: none !important;
124 | }
125 |
--------------------------------------------------------------------------------