├── .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 | ![Demonstration](https://github.com/ItsPi3141/alpaca-electron/raw/main/demo.gif) 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 |
14 |
15 |
16 | Alpaca Electron 17 |
18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 | 31 |
32 |
33 | 38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | Clear chat 52 |
53 |
54 | 55 | 59 | 60 | Change model 61 |
62 |
63 | 64 | 65 | 68 | 69 | Settings 70 |
71 |
72 |
73 |
CPU: --%, -- cores
74 |
75 |
76 |
77 |
78 |
79 |
RAM: --GB/--GB
80 |
81 |
82 |
83 |
84 |
85 |
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 | 108 | 109 | 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 |
139 |
140 | 152 |
153 | 154 | 155 | 156 | 161 | 168 | 174 |
175 |
176 |
177 | 181 |

Web access (slower)

182 |
183 |
TIP: shift + enter for multiple lines
184 |
185 |
186 | 187 |
188 | 189 | 190 | 221 | 222 | 223 | 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 | --------------------------------------------------------------------------------