Compare commits

...

178 Commits

Author SHA1 Message Date
Timothy Jaeryang Baek 96a004d4d8 Merge pull request #2921 from open-webui/dev
Create and publish Docker images with specific build args / build-main-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-main-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / merge-main-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-cuda-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-ollama-images (push) Blocked by required conditions
0.3.0
2024-06-09 18:11:53 -07:00
Timothy J. Baek 1fa16d73f0 doc: changelog 2024-06-09 18:02:42 -07:00
Timothy J. Baek d2cd803a57 doc: changelog 2024-06-09 18:01:40 -07:00
Timothy J. Baek e685953df7 doc: changelog 2024-06-09 17:57:16 -07:00
Timothy J. Baek d6520e7fd8 fix: document selector 2024-06-09 17:55:23 -07:00
Timothy J. Baek c54e3d5bf4 doc: changelog 2024-06-09 17:52:22 -07:00
Timothy J. Baek a71b824728 chore: format 2024-06-09 17:39:33 -07:00
Timothy J. Baek bc1a7ab567 fix: playground 2024-06-09 17:38:08 -07:00
Timothy J. Baek b565301a47 feat: knowledge integration 2024-06-09 17:34:42 -07:00
Timothy J. Baek 78272aed8d fix 2024-06-09 17:20:23 -07:00
Timothy J. Baek 3f7913b36f feat: knowledge selector 2024-06-09 17:17:35 -07:00
Timothy J. Baek e1edf9227d feat: model knowledge ui 2024-06-09 16:34:34 -07:00
Timothy J. Baek a8d709102f refac: styling 2024-06-09 16:17:10 -07:00
Timothy J. Baek 9032ab8857 refac 2024-06-09 16:05:29 -07:00
Timothy J. Baek c9137edf5a refac 2024-06-09 15:59:33 -07:00
Timothy J. Baek d11c373cf1 fix: styling 2024-06-09 15:36:25 -07:00
Timothy J. Baek 2755ef62d9 feat: threshold setting 2024-06-09 15:29:55 -07:00
Timothy J. Baek 8debb71197 feat: search query threshold 2024-06-09 15:19:36 -07:00
Timothy J. Baek 8b4867deb5 refac: styling 2024-06-09 15:12:38 -07:00
Timothy J. Baek a93645aee8 refac 2024-06-09 15:08:23 -07:00
Timothy J. Baek 28ca6fb678 refac 2024-06-09 15:04:33 -07:00
Timothy J. Baek da4586f27d refac: task models 2024-06-09 15:00:38 -07:00
Timothy J. Baek 591cd993c2 refac: search query task 2024-06-09 14:53:10 -07:00
Timothy J. Baek aa1bb4fb6d refac 2024-06-09 14:26:49 -07:00
Timothy J. Baek 5e7237b9cb refac: title generation 2024-06-09 14:25:31 -07:00
Timothy J. Baek 84defafc14 feat: unified chat completions endpoint 2024-06-09 13:17:44 -07:00
Timothy Jaeryang Baek 7b1404f490 Merge pull request #2936 from SimonOriginal/dev
Ukrainian translation update
2024-06-09 13:01:33 -07:00
Timothy Jaeryang Baek 9b38788aa2 Merge pull request #2937 from mindspawn/cuda-fix
Enable case independent environment variable testing in start.sh
2024-06-09 13:01:17 -07:00
Timothy J. Baek c44fc82ecd refac: openai 2024-06-09 12:43:54 -07:00
Timothy J. Baek 8b6f422d45 refac: styling 2024-06-09 12:15:48 -07:00
Timothy J. Baek 2eb8c3456f refac 2024-06-09 12:13:13 -07:00
Timothy J. Baek fa9835a7ad refac: styling 2024-06-09 12:08:16 -07:00
Timothy J. Baek 3db9d19ae3 refac 2024-06-09 11:57:33 -07:00
Timothy Jaeryang Baek 762db11bf4 Merge pull request #2939 from KarlLee830/translate
Add some missing i18n keys
2024-06-09 11:14:50 -07:00
Timothy J. Baek f2b9a5f5bf refac: rag 2024-06-09 03:01:25 -07:00
Timothy J. Baek 277fc3feac refac: styling 2024-06-09 02:44:50 -07:00
Timothy J. Baek 9053bfdadf refac: styling 2024-06-09 02:41:52 -07:00
Timothy J. Baek 414ab53144 refac: banners 2024-06-09 02:39:18 -07:00
Timothy J. Baek 4a7d3a076c fix: styling 2024-06-09 02:29:56 -07:00
Timothy J. Baek 8198807fc9 refac: document settings > admin settings 2024-06-09 02:28:52 -07:00
Timothy J. Baek e556c02fe9 refac: styling 2024-06-09 02:14:05 -07:00
Timothy J. Baek f7de01cbc2 refac: styling 2024-06-09 02:05:36 -07:00
Timothy J. Baek 1bc96de620 refac: styling 2024-06-09 02:01:03 -07:00
Timothy J. Baek 23489105fc refac: styling 2024-06-09 01:59:39 -07:00
Timothy Jaeryang Baek 8c95a8be3a Merge pull request #2943 from choltha/fix/temperature-params
fix: model settings temperature not passed correctly from model settings to ollama/openai api
2024-06-09 01:56:18 -07:00
Timothy J. Baek d00c8b00df refac 2024-06-09 01:55:56 -07:00
Timothy J. Baek 4bae43096b refac: settings 2024-06-09 01:54:50 -07:00
Timothy J. Baek d90e138773 refac: settings 2024-06-09 01:44:08 -07:00
Timothy J. Baek bb15eb016e fix: message input delay 2024-06-09 01:22:21 -07:00
Christoph Holthaus 97b39115a1 fix: temperature not passed correctly 2024-06-09 09:49:24 +02:00
Timothy J. Baek cc53fd8379 fix: params 2024-06-08 20:09:59 -07:00
Timothy J. Baek 5342063e24 fix: import model 2024-06-08 19:21:37 -07:00
Timothy J. Baek e274a0dc3e fix: base model verification 2024-06-08 17:21:23 -07:00
Karl Lee 9c3920a489 Update Chinese translation 2024-06-09 04:54:58 +08:00
Timothy J. Baek d1da3dde65 refac: migration 2024-06-08 13:45:33 -07:00
Karl Lee 0ccd96c950 Add some missing i18n keys 2024-06-09 04:42:22 +08:00
Timothy J. Baek 3499ec3f79 fix: tts 2024-06-08 13:18:42 -07:00
Timothy J. Baek 40ea18d54d refac: auth styling 2024-06-08 13:08:03 -07:00
Timothy Jaeryang Baek ffbc480bb4 Merge pull request #2930 from KarlLee830/translate
Update Chinese translation
2024-06-08 13:03:22 -07:00
Timothy Jaeryang Baek 9b839e5c9f Merge pull request #2927 from arkohut/tolerant-no-write-permission-for-static-dir
fix: tolerant no write permission for copy favicon to static dir
2024-06-08 13:03:08 -07:00
mindspawn 575f23cde9 Update start.sh to be case-independent when testing env vars 2024-06-08 10:59:59 -07:00
SimonOriginal 711317555c Ukrainian translation update 2024-06-08 18:08:53 +02:00
Timothy J. Baek 063e1ee46c refac: call 2024-06-08 03:27:56 -07:00
Karl Lee 0d0f8aac15 Upload Chinese tranlsation 2024-06-08 18:13:19 +08:00
Timothy J. Baek 5cbb79fa6e fix: safari audio issue 2024-06-08 02:07:19 -07:00
Timothy J. Baek 277e7aead7 refac 2024-06-08 00:52:19 -07:00
arkohut d3558fdb33 fix: tolerant no write permission for copy favicon to static dir 2024-06-08 13:56:08 +08:00
Timothy J. Baek 1271d1dccc feat: allow image from prompt {{CLIPBOARD}} 2024-06-07 22:44:10 -07:00
Timothy J. Baek 3be1cb98d3 fix: ollama embedding list 2024-06-07 22:32:45 -07:00
Timothy J. Baek c2a7e7f510 doc: readme 2024-06-07 22:17:11 -07:00
Timothy Jaeryang Baek dbde628141 Merge pull request #2923 from mindspawn/outlook-msg
Support Outlook Message File Format
2024-06-07 21:50:03 -07:00
mindspawn 2412f31ed9 Update Dockerfile to revert duplicated pip install 2024-06-07 21:47:50 -07:00
Timothy J. Baek 8df0c9e0dd doc: readme 2024-06-07 21:47:31 -07:00
mindspawn 6f9148ac4c Update main.py 2024-06-07 21:41:30 -07:00
Timothy J. Baek d7d8896e43 fix: active users 2024-06-07 21:38:09 -07:00
mindspawn d5a2a8a880 Update Dockerfile 2024-06-07 21:20:59 -07:00
mindspawn cff8534f33 Update constants.ts 2024-06-07 21:19:46 -07:00
mindspawn f69bc57fed Update requirements.txt 2024-06-07 21:18:35 -07:00
mindspawn 4ecc1c06d3 Update main.py 2024-06-07 21:18:04 -07:00
Timothy J. Baek f78e6a5fba fix: auto playback 2024-06-07 21:10:00 -07:00
Timothy J. Baek 411e6c2fe4 fix: styling 2024-06-07 21:06:26 -07:00
Timothy J. Baek 369816ace0 chore: format 2024-06-07 21:03:45 -07:00
Timothy J. Baek 06e4b87c9e refac: audio 2024-06-07 20:57:15 -07:00
Timothy J. Baek c6b74a3cf9 refac: audio 2024-06-07 20:55:50 -07:00
Timothy J. Baek 27417dd771 refac: audio 2024-06-07 20:51:53 -07:00
Timothy J. Baek 16615010f7 refac 2024-06-07 20:35:50 -07:00
Timothy J. Baek e516374d54 feat: external stt 2024-06-07 20:31:52 -07:00
Timothy J. Baek 55dc6c1b3b refac: audio 2024-06-07 20:18:48 -07:00
Timothy J. Baek da47c2dfa3 refac: active users 2024-06-07 17:35:01 -07:00
Timothy J. Baek 694d1708a3 fix: styling 2024-06-07 16:58:33 -07:00
Timothy J. Baek f9aa03bc6d feat: dark splash screen 2024-06-07 16:57:02 -07:00
Timothy J. Baek bd3e5d7bfa refac 2024-06-07 16:20:50 -07:00
Timothy J. Baek 5743df2280 refac: styling 2024-06-07 15:55:02 -07:00
Timothy J. Baek e3efe2c565 fix: safari video 2024-06-07 15:31:58 -07:00
Timothy J. Baek 32c4748749 refac 2024-06-07 15:18:45 -07:00
Timothy J. Baek f4a15f9590 chore: version bump 2024-06-07 15:16:24 -07:00
Timothy J. Baek f92ef3211b refac: permission 2024-06-07 15:12:34 -07:00
Timothy J. Baek 508e8eb4b1 refac 2024-06-07 15:08:21 -07:00
Timothy J. Baek dfc2fb65af refac: styling 2024-06-07 15:01:55 -07:00
Timothy J. Baek d7ce408d25 refac 2024-06-07 15:00:42 -07:00
Timothy J. Baek 374f647048 fix 2024-06-07 14:56:10 -07:00
Timothy J. Baek 00018085ed refac 2024-06-07 14:55:32 -07:00
Timothy J. Baek d17cdc8068 feat: video devices support 2024-06-07 14:49:36 -07:00
Timothy J. Baek e5ad76615c feat: video call 2024-06-07 14:08:04 -07:00
Timothy J. Baek 54420f5300 refac: styling 2024-06-07 01:04:51 -07:00
Timothy J. Baek f076f81e0c fix: safari compatibility issue 2024-06-07 00:57:53 -07:00
Timothy J. Baek ea80285e9c fix: disable empty string 2024-06-07 00:37:54 -07:00
Timothy J. Baek f43d255e8f refac: wip tooltip 2024-06-07 00:28:34 -07:00
Timothy J. Baek fc3a31e3d5 refac: optimisation 2024-06-07 00:27:05 -07:00
Timothy J. Baek 4e640daf83 feat: submit prompt integration 2024-06-07 00:04:47 -07:00
Timothy J. Baek 404bb3fd67 refac: call overlay 2024-06-06 23:42:31 -07:00
Timothy J. Baek eacce66a82 refac 2024-06-06 23:36:47 -07:00
Timothy J. Baek 4f19a92dc5 refac 2024-06-06 23:29:08 -07:00
Timothy J. Baek 5196b65c2e feat: call ui scaffold 2024-06-06 22:30:19 -07:00
Timothy J. Baek 340b716a90 refac: voice recording web api 2024-06-06 21:56:09 -07:00
Timothy Jaeryang Baek ff4cf16742 Merge pull request #2900 from open-webui/voice
feat: voice note
2024-06-06 21:01:41 -07:00
Timothy J. Baek 7eaf83cb7d fix: silence monitoring 2024-06-06 21:00:41 -07:00
Timothy J. Baek 4a73a01c24 refac 2024-06-06 20:44:42 -07:00
Timothy J. Baek 1a9dee50ce refac: styling 2024-06-06 20:35:18 -07:00
Timothy J. Baek f97f6601f7 feat: voice input refac 2024-06-06 20:33:23 -07:00
Timothy Jaeryang Baek 5ab5231c73 Merge pull request #2886 from KarlLee830/translate
i18n: Added missing i18n key
2024-06-06 11:18:48 -07:00
Karl Lee 046dd02a6d Added missing i18n key 2024-06-07 01:52:03 +08:00
Timothy Jaeryang Baek 72e1615fe1 Merge pull request #2873 from KarlLee830/translate
i18n: Added missing i18n keys for the pending overlay and other pages.
2024-06-06 04:10:47 -07:00
Timothy Jaeryang Baek b512501d9d Merge pull request #2870 from mindspawn/proxy-fix2
Fix proxy not being used for /api/version/updates
2024-06-06 04:06:36 -07:00
Karl Lee 36cc3c24e6 Added some missing i18n keys 2024-06-06 15:07:09 +08:00
Karl Lee 62bfcf35e5 Update translation.json 2024-06-06 14:19:36 +08:00
Karl Lee 9bec2cea12 Update translation 2024-06-06 13:58:25 +08:00
Karl Lee f4a122a4bb Added missing i18n
Added missing i18n keys and update Chinese translation.
2024-06-06 13:47:40 +08:00
Karl Lee 34aea03c02 Update Chinese translation 2024-06-06 13:29:45 +08:00
Karl Lee e7fb86190a added missing i18n keys 2024-06-06 13:12:45 +08:00
Karl Lee 194564e253 Update Chinese translation 2024-06-06 13:03:11 +08:00
Timothy J. Baek d4b10097d2 fix: sidebar 2024-06-05 18:31:15 -07:00
mindspawn 3069fa8074 Update main.py to enable http_proxy use for checking for new versions 2024-06-05 17:24:59 -07:00
Timothy J. Baek c2bbb37fc1 fix: sidebar 2024-06-05 14:20:26 -07:00
Timothy J. Baek e52568e7cb feat: upload pipeline 2024-06-05 13:57:48 -07:00
Timothy Jaeryang Baek bc4aeeeec8 Merge pull request #2866 from bartowski1182/patch-1
Update CONTRIBUTING.md to include proper first step
2024-06-05 13:26:19 -07:00
Bartowski 25ee5f6cb0 Update CONTRIBUTING.md
Update step one to be opening a discussion rather than an issue
2024-06-05 16:24:24 -04:00
Timothy Jaeryang Baek 882ad219ea Merge pull request #2862 from jannikstdl/locale-update
i18n: added missing i18n keys + german locales
2024-06-05 12:43:34 -07:00
Jannik Streidl c108d863f6 added missing i18n keys + german locales 2024-06-05 20:42:41 +02:00
Timothy Jaeryang Baek a8d80f936a Merge pull request #2857 from open-webui/dev
refac: styling
2024-06-05 10:12:23 -07:00
Timothy J. Baek 1bb7fc7c92 refac: styling 2024-06-05 10:12:01 -07:00
Timothy Jaeryang Baek dbb83f9824 Merge pull request #2856 from open-webui/dev
Create and publish Docker images with specific build args / build-main-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-main-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/amd64) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/arm64) (push) Waiting to run
Create and publish Docker images with specific build args / merge-main-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-cuda-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-ollama-images (push) Blocked by required conditions
0.2.5
2024-06-05 10:06:11 -07:00
Timothy J. Baek e1889b0c5e doc: changelog 2024-06-05 10:05:35 -07:00
Timothy J. Baek 88758af621 chore: format 2024-06-05 09:59:40 -07:00
Timothy Jaeryang Baek 43f83673e2 Merge pull request #2855 from mikal-k/norwegian-translation
Added Norwegian Bokmål translation
2024-06-05 09:57:14 -07:00
Timothy J. Baek 950073c1de feat: create modelfile from models 2024-06-05 09:52:58 -07:00
Mikal Krogstad 651c85fcc4 Added Norwegian Bokmål translation 2024-06-05 18:21:35 +02:00
Timothy J. Baek ec7c5a3f07 refac: set default model from interface settings 2024-06-05 09:14:15 -07:00
Timothy J. Baek d077b3dcdb fix: ollama version request when ollama api is disabled 2024-06-05 09:08:52 -07:00
Timothy Jaeryang Baek 1d6bbdf917 Merge pull request #2836 from Jasurbek99/main
added turkmen language
2024-06-05 08:55:32 -07:00
Timothy J. Baek f248425931 refac: styling 2024-06-05 08:48:02 -07:00
Timothy J. Baek bdf7ed7f02 fix: mobile screen 2024-06-05 08:43:23 -07:00
Timothy Jaeryang Baek 66200cfb7d Merge pull request #2828 from KarlLee830/dev
i18n: Update Chinese translation
2024-06-04 18:09:55 -07:00
Karl Lee 9174e01d6a Update Chinese translation
Update Chinese translation to match the latest version.
2024-06-05 08:03:04 +08:00
Timothy J. Baek f17df4f114 doc: readme 2024-06-04 12:32:20 -07:00
Timothy J. Baek 1948e78351 refac: rename fullscreen -> widescreen 2024-06-04 11:48:46 -07:00
Timothy J. Baek 73a98ff938 chore: format 2024-06-04 11:45:23 -07:00
Timothy J. Baek 92d056c982 fix: running models 2024-06-04 11:38:31 -07:00
Timothy J. Baek 2be9c25ba7 feat: show current running models 2024-06-04 11:13:43 -07:00
Timothy Jaeryang Baek 56fda46215 Merge pull request #2802 from KarlLee830/dev
Updated Chinese translation
2024-06-04 10:07:57 -07:00
Timothy J. Baek 1d1b945483 fix 2024-06-04 09:56:51 -07:00
Karl Lee 9aac6e05a9 Update Chinese translation
Fix a typo.
2024-06-05 00:56:14 +08:00
Timothy J. Baek 73e2912849 fix: incognito mode 2024-06-04 09:55:31 -07:00
Timothy J. Baek 7cf80289c3 fix: active users 2024-06-04 09:52:27 -07:00
Karl Lee 2fa594d5bd Update Chinese translation
Optimize more translations.
2024-06-05 00:41:56 +08:00
Karl Lee 45f1a4157b Update Chinese translation
Modify the time format to a format that native Chinese speakers are more comfortable with.
2024-06-05 00:19:21 +08:00
Karl Lee b3e4ecd2f4 Update Chinese translation
Change the date format so that the dates are aligned. Fix some incorrect translations.
2024-06-05 00:14:11 +08:00
Timothy Jaeryang Baek ab04e0dfd4 Merge pull request #2818 from Lanhild/patch-4 2024-06-04 08:25:43 -07:00
Loan J ee625a0519 Update pull_request_template.md 2024-06-04 11:02:51 -04:00
Loan J fea563cf89 Update pull_request_template.md 2024-06-04 11:01:15 -04:00
Jasurbek99 fcfdfa3dea added turkmen language 2024-06-04 15:54:47 +05:00
Timothy J. Baek 844923d0a4 refac: edit admin 2024-06-04 01:14:37 -07:00
Timothy J. Baek bbfa54a6b9 feat: active user count 2024-06-04 01:10:31 -07:00
Karl Lee e2429314f3 Update translation.json 2024-06-04 16:00:50 +08:00
Timothy J. Baek 4925a6530b fix: banner z index 2024-06-04 00:45:56 -07:00
Timothy J. Baek 85484392b2 feat: websocket 2024-06-03 23:39:52 -07:00
Karl Lee 8d9712d66e Updated Chinese translation
Updated Chinese translation for version 0.2.4.
2024-06-04 13:46:24 +08:00
Timothy J. Baek 0495f01acb feat: reset upload dir 2024-06-03 21:45:36 -07:00
130 changed files with 10478 additions and 2530 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
- [ ] **Dependencies:** Are there any new dependencies? Have you updated the dependency versions in the documentation?
- [ ] **Testing:** Have you written and run sufficient tests for validating the changes?
- [ ] **Code review:** Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards?
- [ ] **Label:** To cleary categorize this pull request, assign a relevant label to the pull request title, using one of the following:
- [ ] **Prefix:** To cleary categorize this pull request, prefix the pull request title, using one of the following:
- **BREAKING CHANGE**: Significant changes that may affect compatibility
- **build**: Changes that affect the build system or external dependencies
- **ci**: Changes to our continuous integration processes or workflows
+46
View File
@@ -5,6 +5,52 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.0] - 2024-06-09
### Added
- **📚 Knowledge Support for Models**: Attach documents directly to models from the models workspace, enhancing the information available to each model.
- **🎙️ Hands-Free Voice Call Feature**: Initiate voice calls without needing to use your hands, making interactions more seamless.
- **📹 Video Call Feature**: Enable video calls with supported vision models like Llava and GPT-4o, adding a visual dimension to your communications.
- **🎛️ Enhanced UI for Voice Recording**: Improved user interface for the voice recording feature, making it more intuitive and user-friendly.
- **🌐 External STT Support**: Now support for external Speech-To-Text services, providing more flexibility in choosing your STT provider.
- **⚙️ Unified Settings**: Consolidated settings including document settings under a new admin settings section for easier management.
- **🌑 Dark Mode Splash Screen**: A new splash screen for dark mode, ensuring a consistent and visually appealing experience for dark mode users.
- **📥 Upload Pipeline**: Directly upload pipelines from the admin settings > pipelines section, streamlining the pipeline management process.
- **🌍 Improved Language Support**: Enhanced support for Chinese and Ukrainian languages, better catering to a global user base.
### Fixed
- **🛠️ Playground Issue**: Fixed the playground not functioning properly, ensuring a smoother user experience.
- **🔥 Temperature Parameter Issue**: Corrected the issue where the temperature value '0' was not being passed correctly.
- **📝 Prompt Input Clearing**: Resolved prompt input textarea not being cleared right away, ensuring a clean slate for new inputs.
- **✨ Various UI Styling Issues**: Fixed numerous user interface styling problems for a more cohesive look.
- **👥 Active Users Display**: Fixed active users showing active sessions instead of actual users, now reflecting accurate user activity.
- **🌐 Community Platform Compatibility**: The Community Platform is back online and fully compatible with Open WebUI.
### Changed
- **📝 RAG Implementation**: Updated the RAG (Retrieval-Augmented Generation) implementation to use a system prompt for context, instead of overriding the user's prompt.
- **🔄 Settings Relocation**: Moved Models, Connections, Audio, and Images settings to the admin settings for better organization.
- **✍️ Improved Title Generation**: Enhanced the default prompt for title generation, yielding better results.
- **🔧 Backend Task Management**: Tasks like title generation and search query generation are now managed on the backend side and controlled only by the admin.
- **🔍 Editable Search Query Prompt**: You can now edit the search query generation prompt, offering more control over how queries are generated.
- **📏 Prompt Length Threshold**: Set the prompt length threshold for search query generation from the admin settings, giving more customization options.
- **📣 Settings Consolidation**: Merged the Banners admin setting with the Interface admin setting for a more streamlined settings area.
## [0.2.5] - 2024-06-05
### Added
- **👥 Active Users Indicator**: Now you can see how many people are currently active and what they are running. This helps you gauge when performance might slow down due to a high number of users.
- **🗂️ Create Ollama Modelfile**: The option to create a modelfile for Ollama has been reintroduced in the Settings > Models section, making it easier to manage your models.
- **⚙️ Default Model Setting**: Added an option to set the default model from Settings > Interface. This feature is now easily accessible, especially convenient for mobile users as it was previously hidden.
- **🌐 Enhanced Translations**: We've improved the Chinese translations and added support for Turkmen and Norwegian languages to make the interface more accessible globally.
### Fixed
- **📱 Mobile View Improvements**: The UI now uses dvh (dynamic viewport height) instead of vh (viewport height), providing a better and more responsive experience for mobile users.
## [0.2.4] - 2024-06-03
### Added
+12 -3
View File
@@ -11,7 +11,7 @@
[![Discord](https://img.shields.io/badge/Discord-Open_WebUI-blue?logo=discord&logoColor=white)](https://discord.gg/5rJgQTnV4s)
[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/tjbck)
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI designed to operate entirely offline. It supports various LLM runners, including Ollama and OpenAI-compatible APIs. For more information, be sure to check out our [Open WebUI Documentation](https://docs.openwebui.com/).
Open WebUI is an [extensible](https://github.com/open-webui/pipelines), feature-rich, and user-friendly self-hosted WebUI designed to operate entirely offline. It supports various LLM runners, including Ollama and OpenAI-compatible APIs. For more information, be sure to check out our [Open WebUI Documentation](https://docs.openwebui.com/).
![Open WebUI Demo](./demo.gif)
@@ -146,10 +146,19 @@ docker run --rm --volume /var/run/docker.sock:/var/run/docker.sock containrrr/wa
In the last part of the command, replace `open-webui` with your container name if it is different.
### Moving from Ollama WebUI to Open WebUI
Check our Migration Guide available in our [Open WebUI Documentation](https://docs.openwebui.com/migration/).
### Using the Dev Branch 🌙
> [!WARNING]
> The `:dev` branch contains the latest unstable features and changes. Use it at your own risk as it may have bugs or incomplete features.
If you want to try out the latest bleeding-edge features and are okay with occasional instability, you can use the `:dev` tag like this:
```bash
docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:dev
```
## What's Next? 🌟
Discover upcoming features on our roadmap in the [Open WebUI Documentation](https://docs.openwebui.com/roadmap/).
+207 -59
View File
@@ -17,13 +17,12 @@ from fastapi.middleware.cors import CORSMiddleware
from faster_whisper import WhisperModel
from pydantic import BaseModel
import uuid
import requests
import hashlib
from pathlib import Path
import json
from constants import ERROR_MESSAGES
from utils.utils import (
decode_token,
@@ -41,10 +40,15 @@ from config import (
WHISPER_MODEL_DIR,
WHISPER_MODEL_AUTO_UPDATE,
DEVICE_TYPE,
AUDIO_OPENAI_API_BASE_URL,
AUDIO_OPENAI_API_KEY,
AUDIO_OPENAI_API_MODEL,
AUDIO_OPENAI_API_VOICE,
AUDIO_STT_OPENAI_API_BASE_URL,
AUDIO_STT_OPENAI_API_KEY,
AUDIO_TTS_OPENAI_API_BASE_URL,
AUDIO_TTS_OPENAI_API_KEY,
AUDIO_STT_ENGINE,
AUDIO_STT_MODEL,
AUDIO_TTS_ENGINE,
AUDIO_TTS_MODEL,
AUDIO_TTS_VOICE,
AppConfig,
)
@@ -61,10 +65,17 @@ app.add_middleware(
)
app.state.config = AppConfig()
app.state.config.OPENAI_API_BASE_URL = AUDIO_OPENAI_API_BASE_URL
app.state.config.OPENAI_API_KEY = AUDIO_OPENAI_API_KEY
app.state.config.OPENAI_API_MODEL = AUDIO_OPENAI_API_MODEL
app.state.config.OPENAI_API_VOICE = AUDIO_OPENAI_API_VOICE
app.state.config.STT_OPENAI_API_BASE_URL = AUDIO_STT_OPENAI_API_BASE_URL
app.state.config.STT_OPENAI_API_KEY = AUDIO_STT_OPENAI_API_KEY
app.state.config.STT_ENGINE = AUDIO_STT_ENGINE
app.state.config.STT_MODEL = AUDIO_STT_MODEL
app.state.config.TTS_OPENAI_API_BASE_URL = AUDIO_TTS_OPENAI_API_BASE_URL
app.state.config.TTS_OPENAI_API_KEY = AUDIO_TTS_OPENAI_API_KEY
app.state.config.TTS_ENGINE = AUDIO_TTS_ENGINE
app.state.config.TTS_MODEL = AUDIO_TTS_MODEL
app.state.config.TTS_VOICE = AUDIO_TTS_VOICE
# setting device type for whisper model
whisper_device_type = DEVICE_TYPE if DEVICE_TYPE and DEVICE_TYPE == "cuda" else "cpu"
@@ -74,41 +85,101 @@ SPEECH_CACHE_DIR = Path(CACHE_DIR).joinpath("./audio/speech/")
SPEECH_CACHE_DIR.mkdir(parents=True, exist_ok=True)
class OpenAIConfigUpdateForm(BaseModel):
url: str
key: str
model: str
speaker: str
class TTSConfigForm(BaseModel):
OPENAI_API_BASE_URL: str
OPENAI_API_KEY: str
ENGINE: str
MODEL: str
VOICE: str
class STTConfigForm(BaseModel):
OPENAI_API_BASE_URL: str
OPENAI_API_KEY: str
ENGINE: str
MODEL: str
class AudioConfigUpdateForm(BaseModel):
tts: TTSConfigForm
stt: STTConfigForm
from pydub import AudioSegment
from pydub.utils import mediainfo
def is_mp4_audio(file_path):
"""Check if the given file is an MP4 audio file."""
if not os.path.isfile(file_path):
print(f"File not found: {file_path}")
return False
info = mediainfo(file_path)
if (
info.get("codec_name") == "aac"
and info.get("codec_type") == "audio"
and info.get("codec_tag_string") == "mp4a"
):
return True
return False
def convert_mp4_to_wav(file_path, output_path):
"""Convert MP4 audio file to WAV format."""
audio = AudioSegment.from_file(file_path, format="mp4")
audio.export(output_path, format="wav")
print(f"Converted {file_path} to {output_path}")
@app.get("/config")
async def get_openai_config(user=Depends(get_admin_user)):
async def get_audio_config(user=Depends(get_admin_user)):
return {
"OPENAI_API_BASE_URL": app.state.config.OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.OPENAI_API_KEY,
"OPENAI_API_MODEL": app.state.config.OPENAI_API_MODEL,
"OPENAI_API_VOICE": app.state.config.OPENAI_API_VOICE,
"tts": {
"OPENAI_API_BASE_URL": app.state.config.TTS_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.TTS_OPENAI_API_KEY,
"ENGINE": app.state.config.TTS_ENGINE,
"MODEL": app.state.config.TTS_MODEL,
"VOICE": app.state.config.TTS_VOICE,
},
"stt": {
"OPENAI_API_BASE_URL": app.state.config.STT_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.STT_OPENAI_API_KEY,
"ENGINE": app.state.config.STT_ENGINE,
"MODEL": app.state.config.STT_MODEL,
},
}
@app.post("/config/update")
async def update_openai_config(
form_data: OpenAIConfigUpdateForm, user=Depends(get_admin_user)
async def update_audio_config(
form_data: AudioConfigUpdateForm, user=Depends(get_admin_user)
):
if form_data.key == "":
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.API_KEY_NOT_FOUND)
app.state.config.TTS_OPENAI_API_BASE_URL = form_data.tts.OPENAI_API_BASE_URL
app.state.config.TTS_OPENAI_API_KEY = form_data.tts.OPENAI_API_KEY
app.state.config.TTS_ENGINE = form_data.tts.ENGINE
app.state.config.TTS_MODEL = form_data.tts.MODEL
app.state.config.TTS_VOICE = form_data.tts.VOICE
app.state.config.OPENAI_API_BASE_URL = form_data.url
app.state.config.OPENAI_API_KEY = form_data.key
app.state.config.OPENAI_API_MODEL = form_data.model
app.state.config.OPENAI_API_VOICE = form_data.speaker
app.state.config.STT_OPENAI_API_BASE_URL = form_data.stt.OPENAI_API_BASE_URL
app.state.config.STT_OPENAI_API_KEY = form_data.stt.OPENAI_API_KEY
app.state.config.STT_ENGINE = form_data.stt.ENGINE
app.state.config.STT_MODEL = form_data.stt.MODEL
return {
"status": True,
"OPENAI_API_BASE_URL": app.state.config.OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.OPENAI_API_KEY,
"OPENAI_API_MODEL": app.state.config.OPENAI_API_MODEL,
"OPENAI_API_VOICE": app.state.config.OPENAI_API_VOICE,
"tts": {
"OPENAI_API_BASE_URL": app.state.config.TTS_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.TTS_OPENAI_API_KEY,
"ENGINE": app.state.config.TTS_ENGINE,
"MODEL": app.state.config.TTS_MODEL,
"VOICE": app.state.config.TTS_VOICE,
},
"stt": {
"OPENAI_API_BASE_URL": app.state.config.STT_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.STT_OPENAI_API_KEY,
"ENGINE": app.state.config.STT_ENGINE,
"MODEL": app.state.config.STT_MODEL,
},
}
@@ -125,13 +196,21 @@ async def speech(request: Request, user=Depends(get_verified_user)):
return FileResponse(file_path)
headers = {}
headers["Authorization"] = f"Bearer {app.state.config.OPENAI_API_KEY}"
headers["Authorization"] = f"Bearer {app.state.config.TTS_OPENAI_API_KEY}"
headers["Content-Type"] = "application/json"
try:
body = body.decode("utf-8")
body = json.loads(body)
body["model"] = app.state.config.TTS_MODEL
body = json.dumps(body).encode("utf-8")
except Exception as e:
pass
r = None
try:
r = requests.post(
url=f"{app.state.config.OPENAI_API_BASE_URL}/audio/speech",
url=f"{app.state.config.TTS_OPENAI_API_BASE_URL}/audio/speech",
data=body,
headers=headers,
stream=True,
@@ -181,41 +260,110 @@ def transcribe(
)
try:
filename = file.filename
file_path = f"{UPLOAD_DIR}/{filename}"
ext = file.filename.split(".")[-1]
id = uuid.uuid4()
filename = f"{id}.{ext}"
file_dir = f"{CACHE_DIR}/audio/transcriptions"
os.makedirs(file_dir, exist_ok=True)
file_path = f"{file_dir}/{filename}"
print(filename)
contents = file.file.read()
with open(file_path, "wb") as f:
f.write(contents)
f.close()
whisper_kwargs = {
"model_size_or_path": WHISPER_MODEL,
"device": whisper_device_type,
"compute_type": "int8",
"download_root": WHISPER_MODEL_DIR,
"local_files_only": not WHISPER_MODEL_AUTO_UPDATE,
}
if app.state.config.STT_ENGINE == "":
whisper_kwargs = {
"model_size_or_path": WHISPER_MODEL,
"device": whisper_device_type,
"compute_type": "int8",
"download_root": WHISPER_MODEL_DIR,
"local_files_only": not WHISPER_MODEL_AUTO_UPDATE,
}
log.debug(f"whisper_kwargs: {whisper_kwargs}")
log.debug(f"whisper_kwargs: {whisper_kwargs}")
try:
model = WhisperModel(**whisper_kwargs)
except:
log.warning(
"WhisperModel initialization failed, attempting download with local_files_only=False"
try:
model = WhisperModel(**whisper_kwargs)
except:
log.warning(
"WhisperModel initialization failed, attempting download with local_files_only=False"
)
whisper_kwargs["local_files_only"] = False
model = WhisperModel(**whisper_kwargs)
segments, info = model.transcribe(file_path, beam_size=5)
log.info(
"Detected language '%s' with probability %f"
% (info.language, info.language_probability)
)
whisper_kwargs["local_files_only"] = False
model = WhisperModel(**whisper_kwargs)
segments, info = model.transcribe(file_path, beam_size=5)
log.info(
"Detected language '%s' with probability %f"
% (info.language, info.language_probability)
)
transcript = "".join([segment.text for segment in list(segments)])
transcript = "".join([segment.text for segment in list(segments)])
data = {"text": transcript.strip()}
return {"text": transcript.strip()}
# save the transcript to a json file
transcript_file = f"{file_dir}/{id}.json"
with open(transcript_file, "w") as f:
json.dump(data, f)
print(data)
return data
elif app.state.config.STT_ENGINE == "openai":
if is_mp4_audio(file_path):
print("is_mp4_audio")
os.rename(file_path, file_path.replace(".wav", ".mp4"))
# Convert MP4 audio file to WAV format
convert_mp4_to_wav(file_path.replace(".wav", ".mp4"), file_path)
headers = {"Authorization": f"Bearer {app.state.config.STT_OPENAI_API_KEY}"}
files = {"file": (filename, open(file_path, "rb"))}
data = {"model": "whisper-1"}
print(files, data)
r = None
try:
r = requests.post(
url=f"{app.state.config.STT_OPENAI_API_BASE_URL}/audio/transcriptions",
headers=headers,
files=files,
data=data,
)
r.raise_for_status()
data = r.json()
# save the transcript to a json file
transcript_file = f"{file_dir}/{id}.json"
with open(transcript_file, "w") as f:
json.dump(data, f)
print(data)
return data
except Exception as e:
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
res = r.json()
if "error" in res:
error_detail = f"External: {res['error']['message']}"
except:
error_detail = f"External: {e}"
raise HTTPException(
status_code=r.status_code if r != None else 500,
detail=error_detail,
)
except Exception as e:
log.exception(e)
+53 -49
View File
@@ -41,8 +41,6 @@ from utils.utils import (
get_admin_user,
)
from utils.models import get_model_id_from_custom_model_id
from config import (
SRC_LOG_LEVELS,
@@ -274,54 +272,57 @@ async def get_ollama_tags(
@app.get("/api/version")
@app.get("/api/version/{url_idx}")
async def get_ollama_versions(url_idx: Optional[int] = None):
if app.state.config.ENABLE_OLLAMA_API:
if url_idx == None:
if url_idx == None:
# returns lowest version
tasks = [
fetch_url(f"{url}/api/version")
for url in app.state.config.OLLAMA_BASE_URLS
]
responses = await asyncio.gather(*tasks)
responses = list(filter(lambda x: x is not None, responses))
# returns lowest version
tasks = [
fetch_url(f"{url}/api/version") for url in app.state.config.OLLAMA_BASE_URLS
]
responses = await asyncio.gather(*tasks)
responses = list(filter(lambda x: x is not None, responses))
if len(responses) > 0:
lowest_version = min(
responses,
key=lambda x: tuple(
map(int, re.sub(r"^v|-.*", "", x["version"]).split("."))
),
)
if len(responses) > 0:
lowest_version = min(
responses,
key=lambda x: tuple(
map(int, re.sub(r"^v|-.*", "", x["version"]).split("."))
),
)
return {"version": lowest_version["version"]}
return {"version": lowest_version["version"]}
else:
raise HTTPException(
status_code=500,
detail=ERROR_MESSAGES.OLLAMA_NOT_FOUND,
)
else:
raise HTTPException(
status_code=500,
detail=ERROR_MESSAGES.OLLAMA_NOT_FOUND,
)
url = app.state.config.OLLAMA_BASE_URLS[url_idx]
r = None
try:
r = requests.request(method="GET", url=f"{url}/api/version")
r.raise_for_status()
return r.json()
except Exception as e:
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
res = r.json()
if "error" in res:
error_detail = f"Ollama: {res['error']}"
except:
error_detail = f"Ollama: {e}"
raise HTTPException(
status_code=r.status_code if r else 500,
detail=error_detail,
)
else:
url = app.state.config.OLLAMA_BASE_URLS[url_idx]
r = None
try:
r = requests.request(method="GET", url=f"{url}/api/version")
r.raise_for_status()
return r.json()
except Exception as e:
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
res = r.json()
if "error" in res:
error_detail = f"Ollama: {res['error']}"
except:
error_detail = f"Ollama: {e}"
raise HTTPException(
status_code=r.status_code if r else 500,
detail=error_detail,
)
return {"version": False}
class ModelNameForm(BaseModel):
@@ -725,7 +726,6 @@ async def generate_chat_completion(
model_info = Models.get_model_by_id(model_id)
if model_info:
print(model_info)
if model_info.base_model_id:
payload["model"] = model_info.base_model_id
@@ -761,7 +761,7 @@ async def generate_chat_completion(
"frequency_penalty", None
)
if model_info.params.get("temperature", None):
if model_info.params.get("temperature", None) is not None:
payload["options"]["temperature"] = model_info.params.get(
"temperature", None
)
@@ -846,9 +846,14 @@ async def generate_chat_completion(
# TODO: we should update this part once Ollama supports other types
class OpenAIChatMessageContent(BaseModel):
type: str
model_config = ConfigDict(extra="allow")
class OpenAIChatMessage(BaseModel):
role: str
content: str
content: Union[str, OpenAIChatMessageContent]
model_config = ConfigDict(extra="allow")
@@ -876,7 +881,6 @@ async def generate_openai_chat_completion(
model_info = Models.get_model_by_id(model_id)
if model_info:
print(model_info)
if model_info.base_model_id:
payload["model"] = model_info.base_model_id
+136 -89
View File
@@ -345,113 +345,97 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
)
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
@app.post("/chat/completions")
@app.post("/chat/completions/{url_idx}")
async def generate_chat_completion(
form_data: dict,
url_idx: Optional[int] = None,
user=Depends(get_verified_user),
):
idx = 0
payload = {**form_data}
body = await request.body()
# TODO: Remove below after gpt-4-vision fix from Open AI
# Try to decode the body of the request from bytes to a UTF-8 string (Require add max_token to fix gpt-4-vision)
model_id = form_data.get("model")
model_info = Models.get_model_by_id(model_id)
payload = None
if model_info:
if model_info.base_model_id:
payload["model"] = model_info.base_model_id
try:
if "chat/completions" in path:
body = body.decode("utf-8")
body = json.loads(body)
model_info.params = model_info.params.model_dump()
payload = {**body}
if model_info.params:
if model_info.params.get("temperature", None) is not None:
payload["temperature"] = float(model_info.params.get("temperature"))
model_id = body.get("model")
model_info = Models.get_model_by_id(model_id)
if model_info.params.get("top_p", None):
payload["top_p"] = int(model_info.params.get("top_p", None))
if model_info:
print(model_info)
if model_info.base_model_id:
payload["model"] = model_info.base_model_id
if model_info.params.get("max_tokens", None):
payload["max_tokens"] = int(model_info.params.get("max_tokens", None))
model_info.params = model_info.params.model_dump()
if model_info.params.get("frequency_penalty", None):
payload["frequency_penalty"] = int(
model_info.params.get("frequency_penalty", None)
)
if model_info.params:
if model_info.params.get("temperature", None):
payload["temperature"] = int(
model_info.params.get("temperature")
if model_info.params.get("seed", None):
payload["seed"] = model_info.params.get("seed", None)
if model_info.params.get("stop", None):
payload["stop"] = (
[
bytes(stop, "utf-8").decode("unicode_escape")
for stop in model_info.params["stop"]
]
if model_info.params.get("stop", None)
else None
)
if model_info.params.get("system", None):
# Check if the payload already has a system message
# If not, add a system message to the payload
if payload.get("messages"):
for message in payload["messages"]:
if message.get("role") == "system":
message["content"] = (
model_info.params.get("system", None) + message["content"]
)
break
else:
payload["messages"].insert(
0,
{
"role": "system",
"content": model_info.params.get("system", None),
},
)
if model_info.params.get("top_p", None):
payload["top_p"] = int(model_info.params.get("top_p", None))
else:
pass
if model_info.params.get("max_tokens", None):
payload["max_tokens"] = int(
model_info.params.get("max_tokens", None)
)
model = app.state.MODELS[payload.get("model")]
idx = model["urlIdx"]
if model_info.params.get("frequency_penalty", None):
payload["frequency_penalty"] = int(
model_info.params.get("frequency_penalty", None)
)
if "pipeline" in model and model.get("pipeline"):
payload["user"] = {"name": user.name, "id": user.id}
if model_info.params.get("seed", None):
payload["seed"] = model_info.params.get("seed", None)
# Check if the model is "gpt-4-vision-preview" and set "max_tokens" to 4000
# This is a workaround until OpenAI fixes the issue with this model
if payload.get("model") == "gpt-4-vision-preview":
if "max_tokens" not in payload:
payload["max_tokens"] = 4000
log.debug("Modified payload:", payload)
if model_info.params.get("stop", None):
payload["stop"] = (
[
bytes(stop, "utf-8").decode("unicode_escape")
for stop in model_info.params["stop"]
]
if model_info.params.get("stop", None)
else None
)
if model_info.params.get("system", None):
# Check if the payload already has a system message
# If not, add a system message to the payload
if payload.get("messages"):
for message in payload["messages"]:
if message.get("role") == "system":
message["content"] = (
model_info.params.get("system", None)
+ message["content"]
)
break
else:
payload["messages"].insert(
0,
{
"role": "system",
"content": model_info.params.get("system", None),
},
)
else:
pass
model = app.state.MODELS[payload.get("model")]
idx = model["urlIdx"]
if "pipeline" in model and model.get("pipeline"):
payload["user"] = {"name": user.name, "id": user.id}
# Check if the model is "gpt-4-vision-preview" and set "max_tokens" to 4000
# This is a workaround until OpenAI fixes the issue with this model
if payload.get("model") == "gpt-4-vision-preview":
if "max_tokens" not in payload:
payload["max_tokens"] = 4000
log.debug("Modified payload:", payload)
# Convert the modified body back to JSON
payload = json.dumps(payload)
except json.JSONDecodeError as e:
log.error("Error loading request body into a dictionary:", e)
# Convert the modified body back to JSON
payload = json.dumps(payload)
print(payload)
url = app.state.config.OPENAI_API_BASE_URLS[idx]
key = app.state.config.OPENAI_API_KEYS[idx]
target_url = f"{url}/{path}"
print(payload)
headers = {}
headers["Authorization"] = f"Bearer {key}"
@@ -464,9 +448,72 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
try:
session = aiohttp.ClientSession(trust_env=True)
r = await session.request(
method=request.method,
url=target_url,
data=payload if payload else body,
method="POST",
url=f"{url}/chat/completions",
data=payload,
headers=headers,
)
r.raise_for_status()
# Check if response is SSE
if "text/event-stream" in r.headers.get("Content-Type", ""):
streaming = True
return StreamingResponse(
r.content,
status_code=r.status,
headers=dict(r.headers),
background=BackgroundTask(
cleanup_response, response=r, session=session
),
)
else:
response_data = await r.json()
return response_data
except Exception as e:
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
res = await r.json()
print(res)
if "error" in res:
error_detail = f"External: {res['error']['message'] if 'message' in res['error'] else res['error']}"
except:
error_detail = f"External: {e}"
raise HTTPException(status_code=r.status if r else 500, detail=error_detail)
finally:
if not streaming and session:
if r:
r.close()
await session.close()
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
idx = 0
body = await request.body()
url = app.state.config.OPENAI_API_BASE_URLS[idx]
key = app.state.config.OPENAI_API_KEYS[idx]
target_url = f"{url}/{path}"
headers = {}
headers["Authorization"] = f"Bearer {key}"
headers["Content-Type"] = "application/json"
r = None
session = None
streaming = False
try:
session = aiohttp.ClientSession(trust_env=True)
r = await session.request(
method=request.method,
url=target_url,
data=body,
headers=headers,
)
+36
View File
@@ -9,6 +9,7 @@ from fastapi import (
)
from fastapi.middleware.cors import CORSMiddleware
import os, shutil, logging, re
from datetime import datetime
from pathlib import Path
from typing import List, Union, Sequence
@@ -30,6 +31,7 @@ from langchain_community.document_loaders import (
UnstructuredExcelLoader,
UnstructuredPowerPointLoader,
YoutubeLoader,
OutlookMessageLoader,
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
@@ -879,6 +881,13 @@ def store_docs_in_vector_db(docs, collection_name, overwrite: bool = False) -> b
texts = [doc.page_content for doc in docs]
metadatas = [doc.metadata for doc in docs]
# ChromaDB does not like datetime formats
# for meta-data so convert them to string.
for metadata in metadatas:
for key, value in metadata.items():
if isinstance(value, datetime):
metadata[key] = str(value)
try:
if overwrite:
for collection in CHROMA_CLIENT.list_collections():
@@ -965,6 +974,7 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
"swift",
"vue",
"svelte",
"msg",
]
if file_ext == "pdf":
@@ -999,6 +1009,8 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
] or file_ext in ["ppt", "pptx"]:
loader = UnstructuredPowerPointLoader(file_path)
elif file_ext == "msg":
loader = OutlookMessageLoader(file_path)
elif file_ext in known_source_ext or (
file_content_type and file_content_type.find("text/") >= 0
):
@@ -1164,6 +1176,30 @@ def reset_vector_db(user=Depends(get_admin_user)):
CHROMA_CLIENT.reset()
@app.get("/reset/uploads")
def reset_upload_dir(user=Depends(get_admin_user)) -> bool:
folder = f"{UPLOAD_DIR}"
try:
# Check if the directory exists
if os.path.exists(folder):
# Iterate over all the files and directories in the specified directory
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path) # Remove the file or link
elif os.path.isdir(file_path):
shutil.rmtree(file_path) # Remove the directory
except Exception as e:
print(f"Failed to delete {file_path}. Reason: {e}")
else:
print(f"The directory {folder} does not exist")
except Exception as e:
print(f"Failed to process the directory {folder}. Reason: {e}")
return True
@app.get("/reset")
def reset(user=Depends(get_admin_user)) -> bool:
folder = f"{UPLOAD_DIR}"
+3 -44
View File
@@ -20,7 +20,7 @@ from langchain.retrievers import (
from typing import Optional
from utils.misc import get_last_user_message, add_or_update_system_message
from config import SRC_LOG_LEVELS, CHROMA_CLIENT
log = logging.getLogger(__name__)
@@ -247,31 +247,7 @@ def rag_messages(
hybrid_search,
):
log.debug(f"docs: {docs} {messages} {embedding_function} {reranking_function}")
last_user_message_idx = None
for i in range(len(messages) - 1, -1, -1):
if messages[i]["role"] == "user":
last_user_message_idx = i
break
user_message = messages[last_user_message_idx]
if isinstance(user_message["content"], list):
# Handle list content input
content_type = "list"
query = ""
for content_item in user_message["content"]:
if content_item["type"] == "text":
query = content_item["text"]
break
elif isinstance(user_message["content"], str):
# Handle text content input
content_type = "text"
query = user_message["content"]
else:
# Fallback in case the input does not match expected types
content_type = None
query = ""
query = get_last_user_message(messages)
extracted_collections = []
relevant_contexts = []
@@ -349,24 +325,7 @@ def rag_messages(
)
log.debug(f"ra_content: {ra_content}")
if content_type == "list":
new_content = []
for content_item in user_message["content"]:
if content_item["type"] == "text":
# Update the text item's content with ra_content
new_content.append({"type": "text", "text": ra_content})
else:
# Keep other types of content as they are
new_content.append(content_item)
new_user_message = {**user_message, "content": new_content}
else:
new_user_message = {
**user_message,
"content": ra_content,
}
messages[last_user_message_idx] = new_user_message
messages = add_or_update_system_message(ra_content, messages)
return messages, citations
+151
View File
@@ -0,0 +1,151 @@
import socketio
import asyncio
from apps.webui.models.users import Users
from utils.utils import decode_token
sio = socketio.AsyncServer(cors_allowed_origins=[], async_mode="asgi")
app = socketio.ASGIApp(sio, socketio_path="/ws/socket.io")
# Dictionary to maintain the user pool
SESSION_POOL = {}
USER_POOL = {}
USAGE_POOL = {}
# Timeout duration in seconds
TIMEOUT_DURATION = 3
@sio.event
async def connect(sid, environ, auth):
print("connect ", sid)
user = None
if auth and "token" in auth:
data = decode_token(auth["token"])
if data is not None and "id" in data:
user = Users.get_user_by_id(data["id"])
if user:
SESSION_POOL[sid] = user.id
if user.id in USER_POOL:
USER_POOL[user.id].append(sid)
else:
USER_POOL[user.id] = [sid]
print(f"user {user.name}({user.id}) connected with session ID {sid}")
print(len(set(USER_POOL)))
await sio.emit("user-count", {"count": len(set(USER_POOL))})
await sio.emit("usage", {"models": get_models_in_use()})
@sio.on("user-join")
async def user_join(sid, data):
print("user-join", sid, data)
auth = data["auth"] if "auth" in data else None
if auth and "token" in auth:
data = decode_token(auth["token"])
if data is not None and "id" in data:
user = Users.get_user_by_id(data["id"])
if user:
SESSION_POOL[sid] = user.id
if user.id in USER_POOL:
USER_POOL[user.id].append(sid)
else:
USER_POOL[user.id] = [sid]
print(f"user {user.name}({user.id}) connected with session ID {sid}")
print(len(set(USER_POOL)))
await sio.emit("user-count", {"count": len(set(USER_POOL))})
@sio.on("user-count")
async def user_count(sid):
print("user-count", sid)
await sio.emit("user-count", {"count": len(set(USER_POOL))})
def get_models_in_use():
# Aggregate all models in use
models_in_use = []
for model_id, data in USAGE_POOL.items():
models_in_use.append(model_id)
print(f"Models in use: {models_in_use}")
return models_in_use
@sio.on("usage")
async def usage(sid, data):
print(f'Received "usage" event from {sid}: {data}')
model_id = data["model"]
# Cancel previous callback if there is one
if model_id in USAGE_POOL:
USAGE_POOL[model_id]["callback"].cancel()
# Store the new usage data and task
if model_id in USAGE_POOL:
USAGE_POOL[model_id]["sids"].append(sid)
USAGE_POOL[model_id]["sids"] = list(set(USAGE_POOL[model_id]["sids"]))
else:
USAGE_POOL[model_id] = {"sids": [sid]}
# Schedule a task to remove the usage data after TIMEOUT_DURATION
USAGE_POOL[model_id]["callback"] = asyncio.create_task(
remove_after_timeout(sid, model_id)
)
# Broadcast the usage data to all clients
await sio.emit("usage", {"models": get_models_in_use()})
async def remove_after_timeout(sid, model_id):
try:
print("remove_after_timeout", sid, model_id)
await asyncio.sleep(TIMEOUT_DURATION)
if model_id in USAGE_POOL:
print(USAGE_POOL[model_id]["sids"])
USAGE_POOL[model_id]["sids"].remove(sid)
USAGE_POOL[model_id]["sids"] = list(set(USAGE_POOL[model_id]["sids"]))
if len(USAGE_POOL[model_id]["sids"]) == 0:
del USAGE_POOL[model_id]
print(f"Removed usage data for {model_id} due to timeout")
# Broadcast the usage data to all clients
await sio.emit("usage", {"models": get_models_in_use()})
except asyncio.CancelledError:
# Task was cancelled due to new 'usage' event
pass
@sio.event
async def disconnect(sid):
if sid in SESSION_POOL:
user_id = SESSION_POOL[sid]
del SESSION_POOL[sid]
USER_POOL[user_id].remove(sid)
if len(USER_POOL[user_id]) == 0:
del USER_POOL[user_id]
print(f"user {user_id} disconnected with session ID {sid}")
print(USER_POOL)
await sio.emit("user-count", {"count": len(USER_POOL)})
else:
print(f"Unknown session ID {sid} disconnected")
+114 -17
View File
@@ -306,7 +306,10 @@ STATIC_DIR = Path(os.getenv("STATIC_DIR", BACKEND_DIR / "static")).resolve()
frontend_favicon = FRONTEND_BUILD_DIR / "favicon.png"
if frontend_favicon.exists():
shutil.copyfile(frontend_favicon, STATIC_DIR / "favicon.png")
try:
shutil.copyfile(frontend_favicon, STATIC_DIR / "favicon.png")
except PermissionError:
logging.error(f"No write permission to {STATIC_DIR / 'favicon.png'}")
else:
logging.warning(f"Frontend favicon not found at {frontend_favicon}")
@@ -615,6 +618,66 @@ ADMIN_EMAIL = PersistentConfig(
)
####################################
# TASKS
####################################
TASK_MODEL = PersistentConfig(
"TASK_MODEL",
"task.model.default",
os.environ.get("TASK_MODEL", ""),
)
TASK_MODEL_EXTERNAL = PersistentConfig(
"TASK_MODEL_EXTERNAL",
"task.model.external",
os.environ.get("TASK_MODEL_EXTERNAL", ""),
)
TITLE_GENERATION_PROMPT_TEMPLATE = PersistentConfig(
"TITLE_GENERATION_PROMPT_TEMPLATE",
"task.title.prompt_template",
os.environ.get(
"TITLE_GENERATION_PROMPT_TEMPLATE",
"""Here is the query:
{{prompt:middletruncate:8000}}
Create a concise, 3-5 word phrase with an emoji as a title for the previous query. Suitable Emojis for the summary can be used to enhance understanding but avoid quotation marks or special formatting. RESPOND ONLY WITH THE TITLE TEXT.
Examples of titles:
📉 Stock Market Trends
🍪 Perfect Chocolate Chip Recipe
Evolution of Music Streaming
Remote Work Productivity Tips
Artificial Intelligence in Healthcare
🎮 Video Game Development Insights""",
),
)
SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE = PersistentConfig(
"SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE",
"task.search.prompt_template",
os.environ.get(
"SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE",
"""You are tasked with generating web search queries. Give me an appropriate query to answer my question for google search. Answer with only the query. Today is {{CURRENT_DATE}}.
Question:
{{prompt:end:4000}}""",
),
)
SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD = PersistentConfig(
"SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD",
"task.search.prompt_length_threshold",
os.environ.get(
"SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD",
100,
),
)
####################################
# WEBUI_SECRET_KEY
####################################
@@ -933,25 +996,59 @@ IMAGE_GENERATION_MODEL = PersistentConfig(
# Audio
####################################
AUDIO_OPENAI_API_BASE_URL = PersistentConfig(
"AUDIO_OPENAI_API_BASE_URL",
"audio.openai.api_base_url",
os.getenv("AUDIO_OPENAI_API_BASE_URL", OPENAI_API_BASE_URL),
AUDIO_STT_OPENAI_API_BASE_URL = PersistentConfig(
"AUDIO_STT_OPENAI_API_BASE_URL",
"audio.stt.openai.api_base_url",
os.getenv("AUDIO_STT_OPENAI_API_BASE_URL", OPENAI_API_BASE_URL),
)
AUDIO_OPENAI_API_KEY = PersistentConfig(
"AUDIO_OPENAI_API_KEY",
"audio.openai.api_key",
os.getenv("AUDIO_OPENAI_API_KEY", OPENAI_API_KEY),
AUDIO_STT_OPENAI_API_KEY = PersistentConfig(
"AUDIO_STT_OPENAI_API_KEY",
"audio.stt.openai.api_key",
os.getenv("AUDIO_STT_OPENAI_API_KEY", OPENAI_API_KEY),
)
AUDIO_OPENAI_API_MODEL = PersistentConfig(
"AUDIO_OPENAI_API_MODEL",
"audio.openai.api_model",
os.getenv("AUDIO_OPENAI_API_MODEL", "tts-1"),
AUDIO_STT_ENGINE = PersistentConfig(
"AUDIO_STT_ENGINE",
"audio.stt.engine",
os.getenv("AUDIO_STT_ENGINE", ""),
)
AUDIO_OPENAI_API_VOICE = PersistentConfig(
"AUDIO_OPENAI_API_VOICE",
"audio.openai.api_voice",
os.getenv("AUDIO_OPENAI_API_VOICE", "alloy"),
AUDIO_STT_MODEL = PersistentConfig(
"AUDIO_STT_MODEL",
"audio.stt.model",
os.getenv("AUDIO_STT_MODEL", "whisper-1"),
)
AUDIO_TTS_OPENAI_API_BASE_URL = PersistentConfig(
"AUDIO_TTS_OPENAI_API_BASE_URL",
"audio.tts.openai.api_base_url",
os.getenv("AUDIO_TTS_OPENAI_API_BASE_URL", OPENAI_API_BASE_URL),
)
AUDIO_TTS_OPENAI_API_KEY = PersistentConfig(
"AUDIO_TTS_OPENAI_API_KEY",
"audio.tts.openai.api_key",
os.getenv("AUDIO_TTS_OPENAI_API_KEY", OPENAI_API_KEY),
)
AUDIO_TTS_ENGINE = PersistentConfig(
"AUDIO_TTS_ENGINE",
"audio.tts.engine",
os.getenv("AUDIO_TTS_ENGINE", ""),
)
AUDIO_TTS_MODEL = PersistentConfig(
"AUDIO_TTS_MODEL",
"audio.tts.model",
os.getenv("AUDIO_TTS_MODEL", "tts-1"),
)
AUDIO_TTS_VOICE = PersistentConfig(
"AUDIO_TTS_VOICE",
"audio.tts.voice",
os.getenv("AUDIO_TTS_VOICE", "alloy"),
)
+4
View File
@@ -84,3 +84,7 @@ class ERROR_MESSAGES(str, Enum):
WEB_SEARCH_ERROR = (
lambda err="": f"{err if err else 'Oops! Something went wrong while searching the web.'}"
)
OLLAMA_API_DISABLED = (
"The Ollama API is disabled. Please enable it to use this feature."
)
+354 -86
View File
@@ -9,8 +9,11 @@ import logging
import aiohttp
import requests
import mimetypes
import shutil
import os
import asyncio
from fastapi import FastAPI, Request, Depends, status
from fastapi import FastAPI, Request, Depends, status, UploadFile, File, Form
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
from fastapi import HTTPException
@@ -20,15 +23,26 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import StreamingResponse, Response
from apps.ollama.main import app as ollama_app, get_all_models as get_ollama_models
from apps.openai.main import app as openai_app, get_all_models as get_openai_models
from apps.socket.main import app as socket_app
from apps.ollama.main import (
app as ollama_app,
OpenAIChatCompletionForm,
get_all_models as get_ollama_models,
generate_openai_chat_completion as generate_ollama_chat_completion,
)
from apps.openai.main import (
app as openai_app,
get_all_models as get_openai_models,
generate_chat_completion as generate_openai_chat_completion,
)
from apps.audio.main import app as audio_app
from apps.images.main import app as images_app
from apps.rag.main import app as rag_app
from apps.webui.main import app as webui_app
import asyncio
from pydantic import BaseModel
from typing import List, Optional
@@ -39,6 +53,8 @@ from utils.utils import (
get_current_user,
get_http_authorization_cred,
)
from utils.task import title_generation_template, search_query_generation_template
from apps.rag.utils import rag_messages
from config import (
@@ -60,8 +76,13 @@ from config import (
SRC_LOG_LEVELS,
WEBHOOK_URL,
ENABLE_ADMIN_EXPORT,
AppConfig,
WEBUI_BUILD_HASH,
TASK_MODEL,
TASK_MODEL_EXTERNAL,
TITLE_GENERATION_PROMPT_TEMPLATE,
SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE,
SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD,
AppConfig,
)
from constants import ERROR_MESSAGES
@@ -115,10 +136,19 @@ app.state.config.ENABLE_OLLAMA_API = ENABLE_OLLAMA_API
app.state.config.ENABLE_MODEL_FILTER = ENABLE_MODEL_FILTER
app.state.config.MODEL_FILTER_LIST = MODEL_FILTER_LIST
app.state.config.WEBHOOK_URL = WEBHOOK_URL
app.state.config.TASK_MODEL = TASK_MODEL
app.state.config.TASK_MODEL_EXTERNAL = TASK_MODEL_EXTERNAL
app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = TITLE_GENERATION_PROMPT_TEMPLATE
app.state.config.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE = (
SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE
)
app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD = (
SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD
)
app.state.MODELS = {}
origins = ["*"]
@@ -226,6 +256,78 @@ class RAGMiddleware(BaseHTTPMiddleware):
app.add_middleware(RAGMiddleware)
def filter_pipeline(payload, user):
user = {"id": user.id, "name": user.name, "role": user.role}
model_id = payload["model"]
filters = [
model
for model in app.state.MODELS.values()
if "pipeline" in model
and "type" in model["pipeline"]
and model["pipeline"]["type"] == "filter"
and (
model["pipeline"]["pipelines"] == ["*"]
or any(
model_id == target_model_id
for target_model_id in model["pipeline"]["pipelines"]
)
)
]
sorted_filters = sorted(filters, key=lambda x: x["pipeline"]["priority"])
model = app.state.MODELS[model_id]
if "pipeline" in model:
sorted_filters.append(model)
for filter in sorted_filters:
r = None
try:
urlIdx = filter["urlIdx"]
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
if key != "":
headers = {"Authorization": f"Bearer {key}"}
r = requests.post(
f"{url}/{filter['id']}/filter/inlet",
headers=headers,
json={
"user": user,
"body": payload,
},
)
r.raise_for_status()
payload = r.json()
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
if r is not None:
try:
res = r.json()
if "detail" in res:
return JSONResponse(
status_code=r.status_code,
content=res,
)
except:
pass
else:
pass
if "pipeline" not in app.state.MODELS[model_id]:
if "chat_id" in payload:
del payload["chat_id"]
if "title" in payload:
del payload["title"]
return payload
class PipelineMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if request.method == "POST" and (
@@ -241,85 +343,10 @@ class PipelineMiddleware(BaseHTTPMiddleware):
# Parse string to JSON
data = json.loads(body_str) if body_str else {}
model_id = data["model"]
filters = [
model
for model in app.state.MODELS.values()
if "pipeline" in model
and "type" in model["pipeline"]
and model["pipeline"]["type"] == "filter"
and (
model["pipeline"]["pipelines"] == ["*"]
or any(
model_id == target_model_id
for target_model_id in model["pipeline"]["pipelines"]
)
)
]
sorted_filters = sorted(filters, key=lambda x: x["pipeline"]["priority"])
user = None
if len(sorted_filters) > 0:
try:
user = get_current_user(
get_http_authorization_cred(
request.headers.get("Authorization")
)
)
user = {"id": user.id, "name": user.name, "role": user.role}
except:
pass
model = app.state.MODELS[model_id]
if "pipeline" in model:
sorted_filters.append(model)
for filter in sorted_filters:
r = None
try:
urlIdx = filter["urlIdx"]
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
if key != "":
headers = {"Authorization": f"Bearer {key}"}
r = requests.post(
f"{url}/{filter['id']}/filter/inlet",
headers=headers,
json={
"user": user,
"body": data,
},
)
r.raise_for_status()
data = r.json()
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
if r is not None:
try:
res = r.json()
if "detail" in res:
return JSONResponse(
status_code=r.status_code,
content=res,
)
except:
pass
else:
pass
if "pipeline" not in app.state.MODELS[model_id]:
if "chat_id" in data:
del data["chat_id"]
if "title" in data:
del data["title"]
user = get_current_user(
get_http_authorization_cred(request.headers.get("Authorization"))
)
data = filter_pipeline(data, user)
modified_body_bytes = json.dumps(data).encode("utf-8")
# Replace the request body with the modified one
@@ -376,6 +403,9 @@ async def update_embedding_function(request: Request, call_next):
return response
app.mount("/ws", socket_app)
app.mount("/ollama", ollama_app)
app.mount("/openai", openai_app)
@@ -477,6 +507,178 @@ async def get_models(user=Depends(get_verified_user)):
return {"data": models}
@app.get("/api/task/config")
async def get_task_config(user=Depends(get_verified_user)):
return {
"TASK_MODEL": app.state.config.TASK_MODEL,
"TASK_MODEL_EXTERNAL": app.state.config.TASK_MODEL_EXTERNAL,
"TITLE_GENERATION_PROMPT_TEMPLATE": app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE,
"SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE": app.state.config.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE,
"SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD": app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD,
}
class TaskConfigForm(BaseModel):
TASK_MODEL: Optional[str]
TASK_MODEL_EXTERNAL: Optional[str]
TITLE_GENERATION_PROMPT_TEMPLATE: str
SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE: str
SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD: int
@app.post("/api/task/config/update")
async def update_task_config(form_data: TaskConfigForm, user=Depends(get_admin_user)):
app.state.config.TASK_MODEL = form_data.TASK_MODEL
app.state.config.TASK_MODEL_EXTERNAL = form_data.TASK_MODEL_EXTERNAL
app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = (
form_data.TITLE_GENERATION_PROMPT_TEMPLATE
)
app.state.config.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE = (
form_data.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE
)
app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD = (
form_data.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD
)
return {
"TASK_MODEL": app.state.config.TASK_MODEL,
"TASK_MODEL_EXTERNAL": app.state.config.TASK_MODEL_EXTERNAL,
"TITLE_GENERATION_PROMPT_TEMPLATE": app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE,
"SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE": app.state.config.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE,
"SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD": app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD,
}
@app.post("/api/task/title/completions")
async def generate_title(form_data: dict, user=Depends(get_verified_user)):
print("generate_title")
model_id = form_data["model"]
if model_id not in app.state.MODELS:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Model not found",
)
# Check if the user has a custom task model
# If the user has a custom task model, use that model
if app.state.MODELS[model_id]["owned_by"] == "ollama":
if app.state.config.TASK_MODEL:
task_model_id = app.state.config.TASK_MODEL
if task_model_id in app.state.MODELS:
model_id = task_model_id
else:
if app.state.config.TASK_MODEL_EXTERNAL:
task_model_id = app.state.config.TASK_MODEL_EXTERNAL
if task_model_id in app.state.MODELS:
model_id = task_model_id
print(model_id)
model = app.state.MODELS[model_id]
template = app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE
content = title_generation_template(
template, form_data["prompt"], user.model_dump()
)
payload = {
"model": model_id,
"messages": [{"role": "user", "content": content}],
"stream": False,
"max_tokens": 50,
"chat_id": form_data.get("chat_id", None),
"title": True,
}
print(payload)
payload = filter_pipeline(payload, user)
if model["owned_by"] == "ollama":
return await generate_ollama_chat_completion(
OpenAIChatCompletionForm(**payload), user=user
)
else:
return await generate_openai_chat_completion(payload, user=user)
@app.post("/api/task/query/completions")
async def generate_search_query(form_data: dict, user=Depends(get_verified_user)):
print("generate_search_query")
if len(form_data["prompt"]) < app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Skip search query generation for short prompts (< {app.state.config.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD} characters)",
)
model_id = form_data["model"]
if model_id not in app.state.MODELS:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Model not found",
)
# Check if the user has a custom task model
# If the user has a custom task model, use that model
if app.state.MODELS[model_id]["owned_by"] == "ollama":
if app.state.config.TASK_MODEL:
task_model_id = app.state.config.TASK_MODEL
if task_model_id in app.state.MODELS:
model_id = task_model_id
else:
if app.state.config.TASK_MODEL_EXTERNAL:
task_model_id = app.state.config.TASK_MODEL_EXTERNAL
if task_model_id in app.state.MODELS:
model_id = task_model_id
print(model_id)
model = app.state.MODELS[model_id]
template = app.state.config.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE
content = search_query_generation_template(
template, form_data["prompt"], user.model_dump()
)
payload = {
"model": model_id,
"messages": [{"role": "user", "content": content}],
"stream": False,
"max_tokens": 30,
}
print(payload)
payload = filter_pipeline(payload, user)
if model["owned_by"] == "ollama":
return await generate_ollama_chat_completion(
OpenAIChatCompletionForm(**payload), user=user
)
else:
return await generate_openai_chat_completion(payload, user=user)
@app.post("/api/chat/completions")
async def generate_chat_completions(form_data: dict, user=Depends(get_verified_user)):
model_id = form_data["model"]
if model_id not in app.state.MODELS:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Model not found",
)
model = app.state.MODELS[model_id]
print(model)
if model["owned_by"] == "ollama":
return await generate_ollama_chat_completion(
OpenAIChatCompletionForm(**form_data), user=user
)
else:
return await generate_openai_chat_completion(form_data, user=user)
@app.post("/api/chat/completed")
async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
data = form_data
@@ -569,6 +771,63 @@ async def get_pipelines_list(user=Depends(get_admin_user)):
}
@app.post("/api/pipelines/upload")
async def upload_pipeline(
urlIdx: int = Form(...), file: UploadFile = File(...), user=Depends(get_admin_user)
):
print("upload_pipeline", urlIdx, file.filename)
# Check if the uploaded file is a python file
if not file.filename.endswith(".py"):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only Python (.py) files are allowed.",
)
upload_folder = f"{CACHE_DIR}/pipelines"
os.makedirs(upload_folder, exist_ok=True)
file_path = os.path.join(upload_folder, file.filename)
try:
# Save the uploaded file
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
with open(file_path, "rb") as f:
files = {"file": f}
r = requests.post(f"{url}/pipelines/upload", headers=headers, files=files)
r.raise_for_status()
data = r.json()
return {**data}
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
detail = "Pipeline not found"
if r is not None:
try:
res = r.json()
if "detail" in res:
detail = res["detail"]
except:
pass
raise HTTPException(
status_code=(r.status_code if r is not None else status.HTTP_404_NOT_FOUND),
detail=detail,
)
finally:
# Ensure the file is deleted after the upload is completed or on failure
if os.path.exists(file_path):
os.remove(file_path)
class AddPipelineForm(BaseModel):
url: str
urlIdx: int
@@ -835,6 +1094,15 @@ async def get_app_config():
"enable_community_sharing": webui_app.state.config.ENABLE_COMMUNITY_SHARING,
"enable_admin_export": ENABLE_ADMIN_EXPORT,
},
"audio": {
"tts": {
"engine": audio_app.state.config.TTS_ENGINE,
"voice": audio_app.state.config.TTS_VOICE,
},
"stt": {
"engine": audio_app.state.config.STT_ENGINE,
},
},
}
@@ -897,7 +1165,7 @@ async def get_app_changelog():
@app.get("/api/version/updates")
async def get_app_latest_release_version():
try:
async with aiohttp.ClientSession() as session:
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(
"https://api.github.com/repos/open-webui/open-webui/releases/latest"
) as response:
+4 -1
View File
@@ -56,4 +56,7 @@ PyJWT[crypto]==2.8.0
black==24.4.2
langfuse==2.33.0
youtube-transcript-api==0.6.2
pytube==15.0.0
pytube==15.0.0
extract_msg
pydub
+2 -2
View File
@@ -20,12 +20,12 @@ if test "$WEBUI_SECRET_KEY $WEBUI_JWT_SECRET_KEY" = " "; then
WEBUI_SECRET_KEY=$(cat "$KEY_FILE")
fi
if [ "$USE_OLLAMA_DOCKER" = "true" ]; then
if [[ "${USE_OLLAMA_DOCKER,,}" == "true" ]]; then
echo "USE_OLLAMA is set to true, starting ollama serve."
ollama serve &
fi
if [ "$USE_CUDA_DOCKER" = "true" ]; then
if [[ "${USE_CUDA_DOCKER,,}" == "true" ]]; then
echo "CUDA is enabled, appending LD_LIBRARY_PATH to include torch/cudnn & cublas libraries."
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/python3.11/site-packages/torch/lib:/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib"
fi
+48 -1
View File
@@ -3,7 +3,48 @@ import hashlib
import json
import re
from datetime import timedelta
from typing import Optional
from typing import Optional, List
def get_last_user_message(messages: List[dict]) -> str:
for message in reversed(messages):
if message["role"] == "user":
if isinstance(message["content"], list):
for item in message["content"]:
if item["type"] == "text":
return item["text"]
return message["content"]
return None
def get_last_assistant_message(messages: List[dict]) -> str:
for message in reversed(messages):
if message["role"] == "assistant":
if isinstance(message["content"], list):
for item in message["content"]:
if item["type"] == "text":
return item["text"]
return message["content"]
return None
def add_or_update_system_message(content: str, messages: List[dict]):
"""
Adds a new system message at the beginning of the messages list
or updates the existing system message at the beginning.
:param msg: The message to be added or appended.
:param messages: The list of message dictionaries.
:return: The updated list of message dictionaries.
"""
if messages and messages[0].get("role") == "system":
messages[0]["content"] += f"{content}\n{messages[0]['content']}"
else:
# Insert at the beginning
messages.insert(0, {"role": "system", "content": content})
return messages
def get_gravatar_url(email):
@@ -193,8 +234,14 @@ def parse_ollama_modelfile(model_text):
system_desc_match = re.search(
r'SYSTEM\s+"""(.+?)"""', model_text, re.DOTALL | re.IGNORECASE
)
system_desc_match_single = re.search(
r"SYSTEM\s+([^\n]+)", model_text, re.IGNORECASE
)
if system_desc_match:
data["params"]["system"] = system_desc_match.group(1).strip()
elif system_desc_match_single:
data["params"]["system"] = system_desc_match_single.group(1).strip()
# Parse messages
messages = []
-10
View File
@@ -1,10 +0,0 @@
from apps.webui.models.models import Models, ModelModel, ModelForm, ModelResponse
def get_model_id_from_custom_model_id(id: str):
model = Models.get_model_by_id(id)
if model:
return model.id
else:
return id
+112
View File
@@ -0,0 +1,112 @@
import re
import math
from datetime import datetime
from typing import Optional
def prompt_template(
template: str, user_name: str = None, current_location: str = None
) -> str:
# Get the current date
current_date = datetime.now()
# Format the date to YYYY-MM-DD
formatted_date = current_date.strftime("%Y-%m-%d")
# Replace {{CURRENT_DATE}} in the template with the formatted date
template = template.replace("{{CURRENT_DATE}}", formatted_date)
if user_name:
# Replace {{USER_NAME}} in the template with the user's name
template = template.replace("{{USER_NAME}}", user_name)
if current_location:
# Replace {{CURRENT_LOCATION}} in the template with the current location
template = template.replace("{{CURRENT_LOCATION}}", current_location)
return template
def title_generation_template(
template: str, prompt: str, user: Optional[dict] = None
) -> str:
def replacement_function(match):
full_match = match.group(0)
start_length = match.group(1)
end_length = match.group(2)
middle_length = match.group(3)
if full_match == "{{prompt}}":
return prompt
elif start_length is not None:
return prompt[: int(start_length)]
elif end_length is not None:
return prompt[-int(end_length) :]
elif middle_length is not None:
middle_length = int(middle_length)
if len(prompt) <= middle_length:
return prompt
start = prompt[: math.ceil(middle_length / 2)]
end = prompt[-math.floor(middle_length / 2) :]
return f"{start}...{end}"
return ""
template = re.sub(
r"{{prompt}}|{{prompt:start:(\d+)}}|{{prompt:end:(\d+)}}|{{prompt:middletruncate:(\d+)}}",
replacement_function,
template,
)
template = prompt_template(
template,
**(
{"user_name": user.get("name"), "current_location": user.get("location")}
if user
else {}
),
)
return template
def search_query_generation_template(
template: str, prompt: str, user: Optional[dict] = None
) -> str:
def replacement_function(match):
full_match = match.group(0)
start_length = match.group(1)
end_length = match.group(2)
middle_length = match.group(3)
if full_match == "{{prompt}}":
return prompt
elif start_length is not None:
return prompt[: int(start_length)]
elif end_length is not None:
return prompt[-int(end_length) :]
elif middle_length is not None:
middle_length = int(middle_length)
if len(prompt) <= middle_length:
return prompt
start = prompt[: math.ceil(middle_length / 2)]
end = prompt[-math.floor(middle_length / 2) :]
return f"{start}...{end}"
return ""
template = re.sub(
r"{{prompt}}|{{prompt:start:(\d+)}}|{{prompt:end:(\d+)}}|{{prompt:middletruncate:(\d+)}}",
replacement_function,
template,
)
template = prompt_template(
template,
**(
{"user_name": user.get("name"), "current_location": user.get("location")}
if user
else {}
),
)
return template
+1 -1
View File
@@ -41,7 +41,7 @@ Looking to contribute? Great! Here's how you can help:
We welcome pull requests. Before submitting one, please:
1. Discuss your idea or issue in the [issues section](https://github.com/open-webui/open-webui/issues).
1. Open a discussion regarding your ideas [here](https://github.com/open-webui/open-webui/discussions/new/choose).
2. Follow the project's coding standards and include tests for new features.
3. Update documentation as necessary.
4. Write clear, descriptive commit messages.
+82 -2
View File
@@ -1,12 +1,12 @@
{
"name": "open-webui",
"version": "0.2.4",
"version": "0.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "open-webui",
"version": "0.2.4",
"version": "0.3.0",
"dependencies": {
"@pyscript/core": "^0.4.32",
"@sveltejs/adapter-node": "^1.3.1",
@@ -25,6 +25,7 @@
"marked": "^9.1.0",
"mermaid": "^10.9.1",
"pyodide": "^0.26.0-alpha.4",
"socket.io-client": "^4.7.5",
"sortablejs": "^1.15.2",
"svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7",
@@ -1214,6 +1215,11 @@
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
"dev": true
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="
},
"node_modules/@sveltejs/adapter-auto": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-2.1.1.tgz",
@@ -3800,6 +3806,46 @@
"once": "^1.4.0"
}
},
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-client/node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/engine.io-parser": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/enquirer": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
@@ -7949,6 +7995,32 @@
"node": ">=8"
}
},
"node_modules/socket.io-client": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz",
"integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/sorcery": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz",
@@ -10142,6 +10214,14 @@
}
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "open-webui",
"version": "0.2.4",
"version": "0.3.0",
"private": true,
"scripts": {
"dev": "npm run pyodide:fetch && vite dev --host",
@@ -65,6 +65,7 @@
"marked": "^9.1.0",
"mermaid": "^10.9.1",
"pyodide": "^0.26.0-alpha.4",
"socket.io-client": "^4.7.5",
"sortablejs": "^1.15.2",
"svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7",
+18 -9
View File
@@ -59,15 +59,7 @@
<div
id="splash-screen"
style="
position: fixed;
z-index: 100;
background: #fff;
top: 0;
left: 0;
width: 100%;
height: 100%;
"
style="position: fixed; z-index: 100; top: 0; left: 0; width: 100%; height: 100%"
>
<style type="text/css" nonce="">
html {
@@ -93,3 +85,20 @@
</div>
</body>
</html>
<style type="text/css" nonce="">
html {
overflow-y: hidden !important;
}
#splash-screen {
background: #fff;
}
html.dark #splash-screen {
background: #000;
}
html.dark #splash-screen img {
filter: invert(1);
}
</style>
+3 -3
View File
@@ -98,7 +98,7 @@ export const synthesizeOpenAISpeech = async (
token: string = '',
speaker: string = 'alloy',
text: string = '',
model: string = 'tts-1'
model?: string
) => {
let error = null;
@@ -109,9 +109,9 @@ export const synthesizeOpenAISpeech = async (
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: model,
input: text,
voice: speaker
voice: speaker,
...(model && { model })
})
})
.then(async (res) => {
+178
View File
@@ -104,6 +104,147 @@ export const chatCompleted = async (token: string, body: ChatCompletedForm) => {
return res;
};
export const getTaskConfig = async (token: string = '') => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/task/config`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token && { authorization: `Bearer ${token}` })
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
error = err;
return null;
});
if (error) {
throw error;
}
return res;
};
export const updateTaskConfig = async (token: string, config: object) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/task/config/update`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token && { authorization: `Bearer ${token}` })
},
body: JSON.stringify(config)
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
} else {
error = err;
}
return null;
});
if (error) {
throw error;
}
return res;
};
export const generateTitle = async (
token: string = '',
model: string,
prompt: string,
chat_id?: string
) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/task/title/completions`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
model: model,
prompt: prompt,
...(chat_id && { chat_id: chat_id })
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
}
return null;
});
if (error) {
throw error;
}
return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? 'New Chat';
};
export const generateSearchQuery = async (
token: string = '',
model: string,
messages: object[],
prompt: string
) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/task/query/completions`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
model: model,
messages: messages,
prompt: prompt
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
}
return null;
});
if (error) {
throw error;
}
return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? prompt;
};
export const getPipelinesList = async (token: string = '') => {
let error = null;
@@ -133,6 +274,43 @@ export const getPipelinesList = async (token: string = '') => {
return pipelines;
};
export const uploadPipeline = async (token: string, file: File, urlIdx: string) => {
let error = null;
// Create a new FormData object to handle the file upload
const formData = new FormData();
formData.append('file', file);
formData.append('urlIdx', urlIdx);
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines/upload`, {
method: 'POST',
headers: {
...(token && { authorization: `Bearer ${token}` })
// 'Content-Type': 'multipart/form-data' is not needed as Fetch API will set it automatically
},
body: formData
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
} else {
error = err;
}
return null;
});
if (error) {
throw error;
}
return res;
};
export const downloadPipeline = async (token: string, url: string, urlIdx: string) => {
let error = null;
+21 -13
View File
@@ -369,21 +369,29 @@ export const generateChatCompletion = async (token: string = '', body: object) =
return [res, controller];
};
export const createModel = async (token: string, tagName: string, content: string) => {
export const createModel = async (
token: string,
tagName: string,
content: string,
urlIdx: string | null = null
) => {
let error = null;
const res = await fetch(`${OLLAMA_API_BASE_URL}/api/create`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
name: tagName,
modelfile: content
})
}).catch((err) => {
const res = await fetch(
`${OLLAMA_API_BASE_URL}/api/create${urlIdx !== null ? `/${urlIdx}` : ''}`,
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
name: tagName,
modelfile: content
})
}
).catch((err) => {
error = err;
return null;
});
+26
View File
@@ -359,6 +359,32 @@ export const scanDocs = async (token: string) => {
return res;
};
export const resetUploadDir = async (token: string) => {
let error = null;
const res = await fetch(`${RAG_API_BASE_URL}/reset/uploads`, {
method: 'GET',
headers: {
Accept: 'application/json',
authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
error = err.detail;
return null;
});
if (error) {
throw error;
}
return res;
};
export const resetVectorDB = async (token: string) => {
let error = null;
+390
View File
@@ -0,0 +1,390 @@
<script>
import { getContext, tick } from 'svelte';
import { toast } from 'svelte-sonner';
import Database from './Settings/Database.svelte';
import General from './Settings/General.svelte';
import Users from './Settings/Users.svelte';
import Pipelines from './Settings/Pipelines.svelte';
import Audio from './Settings/Audio.svelte';
import Images from './Settings/Images.svelte';
import Interface from './Settings/Interface.svelte';
import Models from './Settings/Models.svelte';
import Connections from './Settings/Connections.svelte';
import Documents from './Settings/Documents.svelte';
import WebSearch from './Settings/WebSearch.svelte';
import { config } from '$lib/stores';
import { getBackendConfig } from '$lib/apis';
const i18n = getContext('i18n');
let selectedTab = 'general';
</script>
<div class="flex flex-col lg:flex-row w-full h-full py-2 lg:space-x-4">
<div
class="tabs flex flex-row overflow-x-auto space-x-1 max-w-full lg:space-x-0 lg:space-y-1 lg:flex-col lg:flex-none lg:w-44 dark:text-gray-200 text-xs text-left scrollbar-none"
>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 lg:flex-none flex text-right transition {selectedTab ===
'general'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'general';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M6.955 1.45A.5.5 0 0 1 7.452 1h1.096a.5.5 0 0 1 .497.45l.17 1.699c.484.12.94.312 1.356.562l1.321-1.081a.5.5 0 0 1 .67.033l.774.775a.5.5 0 0 1 .034.67l-1.08 1.32c.25.417.44.873.561 1.357l1.699.17a.5.5 0 0 1 .45.497v1.096a.5.5 0 0 1-.45.497l-1.699.17c-.12.484-.312.94-.562 1.356l1.082 1.322a.5.5 0 0 1-.034.67l-.774.774a.5.5 0 0 1-.67.033l-1.322-1.08c-.416.25-.872.44-1.356.561l-.17 1.699a.5.5 0 0 1-.497.45H7.452a.5.5 0 0 1-.497-.45l-.17-1.699a4.973 4.973 0 0 1-1.356-.562L4.108 13.37a.5.5 0 0 1-.67-.033l-.774-.775a.5.5 0 0 1-.034-.67l1.08-1.32a4.971 4.971 0 0 1-.561-1.357l-1.699-.17A.5.5 0 0 1 1 8.548V7.452a.5.5 0 0 1 .45-.497l1.699-.17c.12-.484.312-.94.562-1.356L2.629 4.107a.5.5 0 0 1 .034-.67l.774-.774a.5.5 0 0 1 .67-.033L5.43 3.71a4.97 4.97 0 0 1 1.356-.561l.17-1.699ZM6 8c0 .538.212 1.026.558 1.385l.057.057a2 2 0 0 0 2.828-2.828l-.058-.056A2 2 0 0 0 6 8Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('General')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'users'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'users';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M8 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM3.156 11.763c.16-.629.44-1.21.813-1.72a2.5 2.5 0 0 0-2.725 1.377c-.136.287.102.58.418.58h1.449c.01-.077.025-.156.045-.237ZM12.847 11.763c.02.08.036.16.046.237h1.446c.316 0 .554-.293.417-.579a2.5 2.5 0 0 0-2.722-1.378c.374.51.653 1.09.813 1.72ZM14 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0ZM3.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM5 13c-.552 0-1.013-.455-.876-.99a4.002 4.002 0 0 1 7.753 0c.136.535-.324.99-.877.99H5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Users')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'connections'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'connections';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M1 9.5A3.5 3.5 0 0 0 4.5 13H12a3 3 0 0 0 .917-5.857 2.503 2.503 0 0 0-3.198-3.019 3.5 3.5 0 0 0-6.628 2.171A3.5 3.5 0 0 0 1 9.5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Connections')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'models'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'models';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M10 1c3.866 0 7 1.79 7 4s-3.134 4-7 4-7-1.79-7-4 3.134-4 7-4zm5.694 8.13c.464-.264.91-.583 1.306-.952V10c0 2.21-3.134 4-7 4s-7-1.79-7-4V8.178c.396.37.842.688 1.306.953C5.838 10.006 7.854 10.5 10 10.5s4.162-.494 5.694-1.37zM3 13.179V15c0 2.21 3.134 4 7 4s7-1.79 7-4v-1.822c-.396.37-.842.688-1.306.953-1.532.875-3.548 1.369-5.694 1.369s-4.162-.494-5.694-1.37A7.009 7.009 0 013 13.179z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Models')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'documents'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'documents';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4 h-4"
>
<path d="M11.625 16.5a1.875 1.875 0 1 0 0-3.75 1.875 1.875 0 0 0 0 3.75Z" />
<path
fill-rule="evenodd"
d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875Zm6 16.5c.66 0 1.277-.19 1.797-.518l1.048 1.048a.75.75 0 0 0 1.06-1.06l-1.047-1.048A3.375 3.375 0 1 0 11.625 18Z"
clip-rule="evenodd"
/>
<path
d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Documents')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'web'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'web';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Web Search')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'interface'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'interface';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M2 4.25A2.25 2.25 0 0 1 4.25 2h7.5A2.25 2.25 0 0 1 14 4.25v5.5A2.25 2.25 0 0 1 11.75 12h-1.312c.1.128.21.248.328.36a.75.75 0 0 1 .234.545v.345a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1-.75-.75v-.345a.75.75 0 0 1 .234-.545c.118-.111.228-.232.328-.36H4.25A2.25 2.25 0 0 1 2 9.75v-5.5Zm2.25-.75a.75.75 0 0 0-.75.75v4.5c0 .414.336.75.75.75h7.5a.75.75 0 0 0 .75-.75v-4.5a.75.75 0 0 0-.75-.75h-7.5Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Interface')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'audio'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'audio';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M7.557 2.066A.75.75 0 0 1 8 2.75v10.5a.75.75 0 0 1-1.248.56L3.59 11H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h1.59l3.162-2.81a.75.75 0 0 1 .805-.124ZM12.95 3.05a.75.75 0 1 0-1.06 1.06 5.5 5.5 0 0 1 0 7.78.75.75 0 1 0 1.06 1.06 7 7 0 0 0 0-9.9Z"
/>
<path
d="M10.828 5.172a.75.75 0 1 0-1.06 1.06 2.5 2.5 0 0 1 0 3.536.75.75 0 1 0 1.06 1.06 4 4 0 0 0 0-5.656Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Audio')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'images'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'images';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4Zm10.5 5.707a.5.5 0 0 0-.146-.353l-1-1a.5.5 0 0 0-.708 0L9.354 9.646a.5.5 0 0 1-.708 0L6.354 7.354a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0-.146.353V12a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5V9.707ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Images')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'pipelines'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'pipelines';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
d="M11.644 1.59a.75.75 0 0 1 .712 0l9.75 5.25a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.712 0l-9.75-5.25a.75.75 0 0 1 0-1.32l9.75-5.25Z"
/>
<path
d="m3.265 10.602 7.668 4.129a2.25 2.25 0 0 0 2.134 0l7.668-4.13 1.37.739a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.71 0l-9.75-5.25a.75.75 0 0 1 0-1.32l1.37-.738Z"
/>
<path
d="m10.933 19.231-7.668-4.13-1.37.739a.75.75 0 0 0 0 1.32l9.75 5.25c.221.12.489.12.71 0l9.75-5.25a.75.75 0 0 0 0-1.32l-1.37-.738-7.668 4.13a2.25 2.25 0 0 1-2.134-.001Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Pipelines')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'db'
? 'bg-gray-200 dark:bg-gray-800'
: ' hover:bg-gray-300 dark:hover:bg-gray-850'}"
on:click={() => {
selectedTab = 'db';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path d="M8 7c3.314 0 6-1.343 6-3s-2.686-3-6-3-6 1.343-6 3 2.686 3 6 3Z" />
<path
d="M8 8.5c1.84 0 3.579-.37 4.914-1.037A6.33 6.33 0 0 0 14 6.78V8c0 1.657-2.686 3-6 3S2 9.657 2 8V6.78c.346.273.72.5 1.087.683C4.42 8.131 6.16 8.5 8 8.5Z"
/>
<path
d="M8 12.5c1.84 0 3.579-.37 4.914-1.037.366-.183.74-.41 1.086-.684V12c0 1.657-2.686 3-6 3s-6-1.343-6-3v-1.22c.346.273.72.5 1.087.683C4.42 12.131 6.16 12.5 8 12.5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Database')}</div>
</button>
</div>
<div class="flex-1 mt-3 lg:mt-0 overflow-y-scroll">
{#if selectedTab === 'general'}
<General
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'users'}
<Users
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'connections'}
<Connections
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'models'}
<Models />
{:else if selectedTab === 'documents'}
<Documents
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'web'}
<WebSearch
saveHandler={async () => {
toast.success($i18n.t('Settings saved successfully!'));
await tick();
await config.set(await getBackendConfig());
}}
/>
{:else if selectedTab === 'interface'}
<Interface
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'audio'}
<Audio
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'images'}
<Images
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'db'}
<Database
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'pipelines'}
<Pipelines
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{/if}
</div>
</div>
@@ -0,0 +1,302 @@
<script lang="ts">
import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
import { user, settings, config } from '$lib/stores';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import Switch from '$lib/components/common/Switch.svelte';
import { getBackendConfig } from '$lib/apis';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
export let saveHandler: Function;
// Audio
let TTS_OPENAI_API_BASE_URL = '';
let TTS_OPENAI_API_KEY = '';
let TTS_ENGINE = '';
let TTS_MODEL = '';
let TTS_VOICE = '';
let STT_OPENAI_API_BASE_URL = '';
let STT_OPENAI_API_KEY = '';
let STT_ENGINE = '';
let STT_MODEL = '';
let voices = [];
let models = [];
let nonLocalVoices = false;
const getOpenAIVoices = () => {
voices = [
{ name: 'alloy' },
{ name: 'echo' },
{ name: 'fable' },
{ name: 'onyx' },
{ name: 'nova' },
{ name: 'shimmer' }
];
};
const getOpenAIModels = () => {
models = [{ name: 'tts-1' }, { name: 'tts-1-hd' }];
};
const getWebAPIVoices = () => {
const getVoicesLoop = setInterval(async () => {
voices = await speechSynthesis.getVoices();
// do your loop
if (voices.length > 0) {
clearInterval(getVoicesLoop);
}
}, 100);
};
const updateConfigHandler = async () => {
const res = await updateAudioConfig(localStorage.token, {
tts: {
OPENAI_API_BASE_URL: TTS_OPENAI_API_BASE_URL,
OPENAI_API_KEY: TTS_OPENAI_API_KEY,
ENGINE: TTS_ENGINE,
MODEL: TTS_MODEL,
VOICE: TTS_VOICE
},
stt: {
OPENAI_API_BASE_URL: STT_OPENAI_API_BASE_URL,
OPENAI_API_KEY: STT_OPENAI_API_KEY,
ENGINE: STT_ENGINE,
MODEL: STT_MODEL
}
});
if (res) {
toast.success('Audio settings updated successfully');
config.set(await getBackendConfig());
}
};
onMount(async () => {
const res = await getAudioConfig(localStorage.token);
if (res) {
console.log(res);
TTS_OPENAI_API_BASE_URL = res.tts.OPENAI_API_BASE_URL;
TTS_OPENAI_API_KEY = res.tts.OPENAI_API_KEY;
TTS_ENGINE = res.tts.ENGINE;
TTS_MODEL = res.tts.MODEL;
TTS_VOICE = res.tts.VOICE;
STT_OPENAI_API_BASE_URL = res.stt.OPENAI_API_BASE_URL;
STT_OPENAI_API_KEY = res.stt.OPENAI_API_KEY;
STT_ENGINE = res.stt.ENGINE;
STT_MODEL = res.stt.MODEL;
}
if (TTS_ENGINE === 'openai') {
getOpenAIVoices();
getOpenAIModels();
} else {
getWebAPIVoices();
}
});
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={async () => {
await updateConfigHandler();
dispatch('save');
}}
>
<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
<div class="flex flex-col gap-3">
<div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('STT Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Speech-to-Text Engine')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={STT_ENGINE}
placeholder="Select an engine"
>
<option value="">{$i18n.t('Whisper (Local)')}</option>
<option value="openai">OpenAI</option>
<option value="web">{$i18n.t('Web API')}</option>
</select>
</div>
</div>
{#if STT_ENGINE === 'openai'}
<div>
<div class="mt-1 flex gap-2 mb-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Base URL')}
bind:value={STT_OPENAI_API_BASE_URL}
required
/>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Key')}
bind:value={STT_OPENAI_API_KEY}
required
/>
</div>
</div>
<hr class=" dark:border-gray-850 my-2" />
<div>
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('STT Model')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
list="model-list"
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={STT_MODEL}
placeholder="Select a model"
/>
<datalist id="model-list">
<option value="whisper-1" />
</datalist>
</div>
</div>
</div>
{/if}
</div>
<hr class=" dark:border-gray-800" />
<div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('TTS Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Text-to-Speech Engine')}</div>
<div class="flex items-center relative">
<select
class=" dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={TTS_ENGINE}
placeholder="Select a mode"
on:change={(e) => {
if (e.target.value === 'openai') {
getOpenAIVoices();
TTS_VOICE = 'alloy';
TTS_MODEL = 'tts-1';
} else {
getWebAPIVoices();
TTS_VOICE = '';
}
}}
>
<option value="">{$i18n.t('Web API')}</option>
<option value="openai">{$i18n.t('Open AI')}</option>
</select>
</div>
</div>
{#if TTS_ENGINE === 'openai'}
<div>
<div class="mt-1 flex gap-2 mb-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Base URL')}
bind:value={TTS_OPENAI_API_BASE_URL}
required
/>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Key')}
bind:value={TTS_OPENAI_API_KEY}
required
/>
</div>
</div>
{/if}
<hr class=" dark:border-gray-850 my-2" />
{#if TTS_ENGINE === ''}
<div>
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('TTS Voice')}</div>
<div class="flex w-full">
<div class="flex-1">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={TTS_VOICE}
>
<option value="" selected={TTS_VOICE !== ''}>{$i18n.t('Default')}</option>
{#each voices as voice}
<option
value={voice.voiceURI}
class="bg-gray-100 dark:bg-gray-700"
selected={TTS_VOICE === voice.voiceURI}>{voice.name}</option
>
{/each}
</select>
</div>
</div>
</div>
{:else if TTS_ENGINE === 'openai'}
<div class=" flex gap-2">
<div class="w-full">
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('TTS Voice')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
list="voice-list"
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={TTS_VOICE}
placeholder="Select a voice"
/>
<datalist id="voice-list">
{#each voices as voice}
<option value={voice.name} />
{/each}
</datalist>
</div>
</div>
</div>
<div class="w-full">
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('TTS Model')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
list="model-list"
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={TTS_MODEL}
placeholder="Select a model"
/>
<datalist id="model-list">
{#each models as model}
<option value={model.name} />
{/each}
</datalist>
</div>
</div>
</div>
</div>
{/if}
</div>
</div>
</div>
<div class="flex justify-end text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -1,137 +0,0 @@
<script lang="ts">
import { v4 as uuidv4 } from 'uuid';
import { getContext, onMount } from 'svelte';
import { banners as _banners } from '$lib/stores';
import type { Banner } from '$lib/types';
import { getBanners, setBanners } from '$lib/apis/configs';
import type { Writable } from 'svelte/store';
import type { i18n as i18nType } from 'i18next';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Switch from '$lib/components/common/Switch.svelte';
const i18n: Writable<i18nType> = getContext('i18n');
export let saveHandler: Function;
let banners: Banner[] = [];
onMount(async () => {
banners = await getBanners(localStorage.token);
});
const updateBanners = async () => {
_banners.set(await setBanners(localStorage.token, banners));
};
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={async () => {
updateBanners();
saveHandler();
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80 h-full">
<div class=" space-y-3 pr-1.5">
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">
{$i18n.t('Banners')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (banners.length === 0 || banners.at(-1).content !== '') {
banners = [
...banners,
{
id: uuidv4(),
type: '',
title: '',
content: '',
dismissible: true,
timestamp: Math.floor(Date.now() / 1000)
}
];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<div class="flex flex-col space-y-1">
{#each banners as banner, bannerIdx}
<div class=" flex justify-between">
<div class="flex flex-row flex-1 border rounded-xl dark:border-gray-800">
<select
class="w-fit capitalize rounded-xl py-2 px-4 text-xs bg-transparent outline-none"
bind:value={banner.type}
>
{#if banner.type == ''}
<option value="" selected disabled class="text-gray-900">{$i18n.t('Type')}</option
>
{/if}
<option value="info" class="text-gray-900">{$i18n.t('Info')}</option>
<option value="warning" class="text-gray-900">{$i18n.t('Warning')}</option>
<option value="error" class="text-gray-900">{$i18n.t('Error')}</option>
<option value="success" class="text-gray-900">{$i18n.t('Success')}</option>
</select>
<input
class="pr-5 py-1.5 text-xs w-full bg-transparent outline-none"
placeholder={$i18n.t('Content')}
bind:value={banner.content}
/>
<div class="relative top-1.5 -left-2">
<Tooltip content="Dismissible" className="flex h-fit items-center">
<Switch bind:state={banner.dismissible} />
</Tooltip>
</div>
</div>
<button
class="px-2"
type="button"
on:click={() => {
banners.splice(bannerIdx, 1);
banners = banners;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div>
</div>
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
Save
</button>
</div>
</form>
@@ -23,10 +23,14 @@
import Switch from '$lib/components/common/Switch.svelte';
import Spinner from '$lib/components/common/Spinner.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { getModels as _getModels } from '$lib/apis';
const i18n = getContext('i18n');
export let getModels: Function;
const getModels = async () => {
const models = await _getModels(localStorage.token);
return models;
};
// External
let OLLAMA_BASE_URLS = [''];
@@ -158,7 +162,7 @@
dispatch('save');
}}
>
<div class="space-y-3 pr-1.5 overflow-y-scroll h-[24rem] max-h-[25rem]">
<div class="space-y-3 overflow-y-scroll scrollbar-hidden h-full">
{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null}
<div class=" space-y-3">
<div class="mt-2 space-y-2 pr-1.5">
@@ -300,7 +304,7 @@
</div>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div class="pr-1.5 space-y-2">
<div class="flex justify-between items-center text-sm">
@@ -30,7 +30,7 @@
saveHandler();
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
<div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Database')}</div>
@@ -8,7 +8,10 @@
getEmbeddingConfig,
updateEmbeddingConfig,
getRerankingConfig,
updateRerankingConfig
updateRerankingConfig,
resetUploadDir,
getRAGConfig,
updateRAGConfig
} from '$lib/apis/rag';
import { documents, models } from '$lib/stores';
@@ -24,11 +27,16 @@
let updateRerankingModelLoading = false;
let showResetConfirm = false;
let showResetUploadDirConfirm = false;
let embeddingEngine = '';
let embeddingModel = '';
let rerankingModel = '';
let chunkSize = 0;
let chunkOverlap = 0;
let pdfExtractImages = true;
let OpenAIKey = '';
let OpenAIUrl = '';
let OpenAIBatchSize = 1;
@@ -150,6 +158,14 @@
if (querySettings.hybrid) {
rerankingModelUpdateHandler();
}
const res = await updateRAGConfig(localStorage.token, {
pdf_extract_images: pdfExtractImages,
chunk: {
chunk_overlap: chunkOverlap,
chunk_size: chunkSize
}
});
};
const setEmbeddingConfig = async () => {
@@ -183,6 +199,15 @@
await setRerankingConfig();
querySettings = await getQuerySettings(localStorage.token);
const res = await getRAGConfig(localStorage.token);
if (res) {
pdfExtractImages = res.pdf_extract_images;
chunkSize = res.chunk.chunk_size;
chunkOverlap = res.chunk.chunk_overlap;
}
});
</script>
@@ -193,7 +218,7 @@
saveHandler();
}}
>
<div class=" space-y-2.5 pr-1.5 overflow-y-scroll max-h-[28rem]">
<div class=" space-y-2.5 overflow-y-scroll scrollbar-hidden h-full">
<div class="flex flex-col gap-0.5">
<div class=" mb-0.5 text-sm font-medium">{$i18n.t('General Settings')}</div>
@@ -330,7 +355,7 @@
</div>
</div>
<hr class=" dark:border-gray-700 my-1" />
<hr class=" dark:border-gray-850 my-1" />
<div class="space-y-2" />
<div>
@@ -348,10 +373,8 @@
{#if !embeddingModel}
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{/if}
{#each $models.filter((m) => m.id && !m.external) as model}
<option value={model.name} class="bg-gray-100 dark:bg-gray-700"
>{model.name + ' (' + (model.size / 1024 ** 3).toFixed(1) + ' GB)'}</option
>
{#each $models.filter((m) => m.id && m.ollama && !(m?.preset ?? false)) as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">{model.name}</option>
{/each}
</select>
</div>
@@ -496,99 +519,319 @@
{/if}
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
{#if showResetConfirm}
<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
<div class="flex items-center space-x-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z" />
<path
fill-rule="evenodd"
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM5.72 7.47a.75.75 0 0 1 1.06 0L8 8.69l1.22-1.22a.75.75 0 1 1 1.06 1.06L9.06 9.75l1.22 1.22a.75.75 0 1 1-1.06 1.06L8 10.81l-1.22 1.22a.75.75 0 0 1-1.06-1.06l1.22-1.22-1.22-1.22a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
<div class=" ">
<div class=" text-sm font-medium">{$i18n.t('Query Params')}</div>
<div class=" flex">
<div class=" flex w-full justify-between">
<div class="self-center text-xs font-medium min-w-fit">{$i18n.t('Top K')}</div>
<div class="self-center p-3">
<input
class=" w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Enter Top K')}
bind:value={querySettings.k}
autocomplete="off"
min="0"
/>
</svg>
<span>{$i18n.t('Are you sure?')}</span>
</div>
</div>
<div class="flex space-x-1.5 items-center">
{#if querySettings.hybrid === true}
<div class="flex w-full">
<div class=" self-center text-xs font-medium min-w-fit">
{$i18n.t('Minimum Score')}
</div>
<div class="self-center p-3">
<input
class=" w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
step="0.01"
placeholder={$i18n.t('Enter Score')}
bind:value={querySettings.r}
autocomplete="off"
min="0.0"
title={$i18n.t('The score should be a value between 0.0 (0%) and 1.0 (100%).')}
/>
</div>
</div>
{/if}
</div>
{#if querySettings.hybrid === true}
<div class="mt-2 mb-1 text-xs text-gray-400 dark:text-gray-500">
{$i18n.t(
'Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.'
)}
</div>
<hr class=" dark:border-gray-850 my-3" />
{/if}
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('RAG Template')}</div>
<textarea
bind:value={querySettings.template}
class="w-full rounded-lg px-4 py-3 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
rows="4"
/>
</div>
</div>
<hr class=" dark:border-gray-850" />
<div class=" ">
<div class=" text-sm font-medium">{$i18n.t('Chunk Params')}</div>
<div class=" my-2 flex gap-1.5">
<div class=" w-full justify-between">
<div class="self-center text-xs font-medium min-w-fit mb-1">{$i18n.t('Chunk Size')}</div>
<div class="self-center">
<input
class=" w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Enter Chunk Size')}
bind:value={chunkSize}
autocomplete="off"
min="0"
/>
</div>
</div>
<div class="w-full">
<div class=" self-center text-xs font-medium min-w-fit mb-1">
{$i18n.t('Chunk Overlap')}
</div>
<div class="self-center">
<input
class="w-full rounded-lg py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Enter Chunk Overlap')}
bind:value={chunkOverlap}
autocomplete="off"
min="0"
/>
</div>
</div>
</div>
<div class="my-3">
<div class="flex justify-between items-center text-xs">
<div class=" text-xs font-medium">{$i18n.t('PDF Extract Images (OCR)')}</div>
<button
class="hover:text-white transition"
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
const res = resetVectorDB(localStorage.token).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Success'));
}
showResetConfirm = false;
}}
pdfExtractImages = !pdfExtractImages;
}}>{pdfExtractImages ? $i18n.t('On') : $i18n.t('Off')}</button
>
</div>
</div>
</div>
<hr class=" dark:border-gray-850" />
<div>
{#if showResetUploadDirConfirm}
<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
<div class="flex items-center space-x-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
fill-rule="evenodd"
d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM9.75 14.25a.75.75 0 0 0 0 1.5H15a.75.75 0 0 0 0-1.5H9.75Z"
clip-rule="evenodd"
/>
<path
d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
/>
</svg>
<span>{$i18n.t('Are you sure?')}</span>
</div>
<div class="flex space-x-1.5 items-center">
<button
class="hover:text-white transition"
on:click={() => {
const res = resetUploadDir(localStorage.token).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Success'));
}
showResetUploadDirConfirm = false;
}}
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class="hover:text-white transition"
type="button"
on:click={() => {
showResetUploadDirConfirm = false;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
</div>
{:else}
<button
class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => {
showResetUploadDirConfirm = true;
}}
type="button"
>
<div class=" self-center mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
fill-rule="evenodd"
d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM9.75 14.25a.75.75 0 0 0 0 1.5H15a.75.75 0 0 0 0-1.5H9.75Z"
clip-rule="evenodd"
/>
<path
d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Reset Upload Directory')}</div>
</button>
{/if}
{#if showResetConfirm}
<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
<div class="flex items-center space-x-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class="hover:text-white transition"
on:click={() => {
showResetConfirm = false;
}}
>
<span>{$i18n.t('Are you sure?')}</span>
</div>
<div class="flex space-x-1.5 items-center">
<button
class="hover:text-white transition"
on:click={() => {
const res = resetVectorDB(localStorage.token).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Success'));
}
showResetConfirm = false;
}}
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class="hover:text-white transition"
on:click={() => {
showResetConfirm = false;
}}
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
</div>
{:else}
<button
class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => {
showResetConfirm = true;
}}
type="button"
>
<div class=" self-center mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
fill-rule="evenodd"
d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
</div>
{:else}
<button
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => {
showResetConfirm = true;
}}
>
<div class=" self-center mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Reset Vector Storage')}</div>
</button>
{/if}
</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Reset Vector Storage')}</div>
</button>
{/if}
</div>
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<button
@@ -56,7 +56,7 @@
saveHandler();
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[22rem]">
<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
{#if adminConfig !== null}
<div>
<div class=" mb-3 text-sm font-medium">{$i18n.t('General Settings')}</div>
@@ -23,8 +23,6 @@
const i18n = getContext('i18n');
export let saveSettings: Function;
let loading = false;
let imageGenerationEngine = '';
@@ -171,7 +169,7 @@
loading = false;
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[24rem]">
<div class=" space-y-3 overflow-y-scroll scrollbar-hidden">
<div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('Image Settings')}</div>
@@ -228,7 +226,7 @@
</div>
</div>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
{#if imageGenerationEngine === ''}
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('AUTOMATIC1111 Base URL')}</div>
@@ -326,7 +324,7 @@
{/if}
{#if enableImageGeneration}
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Default Model')}</div>
@@ -0,0 +1,339 @@
<script lang="ts">
import { v4 as uuidv4 } from 'uuid';
import { toast } from 'svelte-sonner';
import { getBackendConfig, getTaskConfig, updateTaskConfig } from '$lib/apis';
import { setDefaultPromptSuggestions } from '$lib/apis/configs';
import { config, models, settings, user } from '$lib/stores';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { banners as _banners } from '$lib/stores';
import type { Banner } from '$lib/types';
import { getBanners, setBanners } from '$lib/apis/configs';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Switch from '$lib/components/common/Switch.svelte';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
let taskConfig = {
TASK_MODEL: '',
TASK_MODEL_EXTERNAL: '',
TITLE_GENERATION_PROMPT_TEMPLATE: '',
SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE: '',
SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD: 0
};
let promptSuggestions = [];
let banners: Banner[] = [];
const updateInterfaceHandler = async () => {
taskConfig = await updateTaskConfig(localStorage.token, taskConfig);
promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions);
await updateBanners();
await config.set(await getBackendConfig());
};
onMount(async () => {
taskConfig = await getTaskConfig(localStorage.token);
promptSuggestions = $config?.default_prompt_suggestions;
banners = await getBanners(localStorage.token);
});
const updateBanners = async () => {
_banners.set(await setBanners(localStorage.token, banners));
};
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={() => {
updateInterfaceHandler();
dispatch('save');
}}
>
<div class=" overflow-y-scroll scrollbar-hidden h-full pr-1.5">
<div>
<div class=" mb-2.5 text-sm font-medium flex">
<div class=" mr-1">{$i18n.t('Set Task Model')}</div>
<Tooltip
content={$i18n.t(
'A task model is used when performing tasks such as generating titles for chats and web search queries'
)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
/>
</svg>
</Tooltip>
</div>
<div class="flex w-full gap-2">
<div class="flex-1">
<div class=" text-xs mb-1">{$i18n.t('Local Models')}</div>
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={taskConfig.TASK_MODEL}
placeholder={$i18n.t('Select a model')}
>
<option value="" selected>{$i18n.t('Current Model')}</option>
{#each $models.filter((m) => m.owned_by === 'ollama') as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">
{model.name}
</option>
{/each}
</select>
</div>
<div class="flex-1">
<div class=" text-xs mb-1">{$i18n.t('External Models')}</div>
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={taskConfig.TASK_MODEL_EXTERNAL}
placeholder={$i18n.t('Select a model')}
>
<option value="" selected>{$i18n.t('Current Model')}</option>
{#each $models as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">
{model.name}
</option>
{/each}
</select>
</div>
</div>
<div class="mt-3">
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Title Generation Prompt')}</div>
<textarea
bind:value={taskConfig.TITLE_GENERATION_PROMPT_TEMPLATE}
class="w-full rounded-lg py-3 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
rows="6"
/>
</div>
<div class="mt-3">
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Search Query Generation Prompt')}</div>
<textarea
bind:value={taskConfig.SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE}
class="w-full rounded-lg py-3 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
rows="6"
/>
</div>
<div class="mt-3">
<div class=" mb-2.5 text-sm font-medium">
{$i18n.t('Search Query Generation Prompt Length Threshold')}
</div>
<input
bind:value={taskConfig.SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD}
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
type="number"
/>
</div>
</div>
<hr class=" dark:border-gray-850 my-3" />
<div class=" space-y-3 {banners.length > 0 ? ' mb-3' : ''}">
<div class="flex w-full justify-between">
<div class=" self-center text-sm font-semibold">
{$i18n.t('Banners')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (banners.length === 0 || banners.at(-1).content !== '') {
banners = [
...banners,
{
id: uuidv4(),
type: '',
title: '',
content: '',
dismissible: true,
timestamp: Math.floor(Date.now() / 1000)
}
];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<div class="flex flex-col space-y-1">
{#each banners as banner, bannerIdx}
<div class=" flex justify-between">
<div class="flex flex-row flex-1 border rounded-xl dark:border-gray-800">
<select
class="w-fit capitalize rounded-xl py-2 px-4 text-xs bg-transparent outline-none"
bind:value={banner.type}
required
>
{#if banner.type == ''}
<option value="" selected disabled class="text-gray-900">{$i18n.t('Type')}</option
>
{/if}
<option value="info" class="text-gray-900">{$i18n.t('Info')}</option>
<option value="warning" class="text-gray-900">{$i18n.t('Warning')}</option>
<option value="error" class="text-gray-900">{$i18n.t('Error')}</option>
<option value="success" class="text-gray-900">{$i18n.t('Success')}</option>
</select>
<input
class="pr-5 py-1.5 text-xs w-full bg-transparent outline-none"
placeholder={$i18n.t('Content')}
bind:value={banner.content}
/>
<div class="relative top-1.5 -left-2">
<Tooltip content={$i18n.t('Dismissible')} className="flex h-fit items-center">
<Switch bind:state={banner.dismissible} />
</Tooltip>
</div>
</div>
<button
class="px-2"
type="button"
on:click={() => {
banners.splice(bannerIdx, 1);
banners = banners;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div>
</div>
{#if $user.role === 'admin'}
<div class=" space-y-3">
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">
{$i18n.t('Default Prompt Suggestions')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (promptSuggestions.length === 0 || promptSuggestions.at(-1).content !== '') {
promptSuggestions = [...promptSuggestions, { content: '', title: ['', ''] }];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<div class="grid lg:grid-cols-2 flex-col gap-1.5">
{#each promptSuggestions as prompt, promptIdx}
<div class=" flex dark:bg-gray-850 rounded-xl py-1.5">
<div class="flex flex-col flex-1 pl-1">
<div class="flex border-b dark:border-gray-800 w-full">
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-800"
placeholder={$i18n.t('Title (e.g. Tell me a fun fact)')}
bind:value={prompt.title[0]}
/>
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-800"
placeholder={$i18n.t('Subtitle (e.g. about the Roman Empire)')}
bind:value={prompt.title[1]}
/>
</div>
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-800"
placeholder={$i18n.t('Prompt (e.g. Tell me a fun fact about the Roman Empire)')}
bind:value={prompt.content}
/>
</div>
<button
class="px-3"
type="button"
on:click={() => {
promptSuggestions.splice(promptIdx, 1);
promptSuggestions = promptSuggestions;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div>
{#if promptSuggestions.length > 0}
<div class="text-xs text-left w-full mt-2">
{$i18n.t('Adjusting these settings will apply changes universally to all users.')}
</div>
{/if}
</div>
{/if}
</div>
<div class="flex justify-end text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
{$i18n.t('Save')}
</button>
</div>
</form>
File diff suppressed because it is too large Load Diff
@@ -14,7 +14,8 @@
getModels,
getPipelinesList,
downloadPipeline,
deletePipeline
deletePipeline,
uploadPipeline
} from '$lib/apis';
import Spinner from '$lib/components/common/Spinner.svelte';
@@ -24,6 +25,9 @@
export let saveHandler: Function;
let downloading = false;
let uploading = false;
let pipelineFiles;
let PIPELINES_LIST = null;
let selectedPipelinesUrlIdx = '';
@@ -126,6 +130,41 @@
downloading = false;
};
const uploadPipelineHandler = async () => {
uploading = true;
if (pipelineFiles && pipelineFiles.length !== 0) {
const file = pipelineFiles[0];
console.log(file);
const res = await uploadPipeline(localStorage.token, file, selectedPipelinesUrlIdx).catch(
(error) => {
console.log(error);
toast.error('Something went wrong :/');
return null;
}
);
if (res) {
toast.success('Pipeline downloaded successfully');
setPipelines();
models.set(await getModels(localStorage.token));
}
} else {
toast.error('No file selected');
}
pipelineFiles = null;
const pipelineUploadInputElement = document.getElementById('pipeline-upload-input');
if (pipelineUploadInputElement) {
pipelineUploadInputElement.value = null;
}
uploading = false;
};
const deletePipelineHandler = async () => {
const res = await deletePipeline(
localStorage.token,
@@ -161,7 +200,7 @@
updateHandler();
}}
>
<div class=" pr-1.5 overflow-y-scroll max-h-80 h-full">
<div class="overflow-y-scroll scrollbar-hidden h-full">
{#if PIPELINES_LIST !== null}
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">
@@ -196,6 +235,91 @@
</div>
</div>
<div class=" my-2">
<div class=" mb-2 text-sm font-medium">
{$i18n.t('Upload Pipeline')}
</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
id="pipelines-upload-input"
bind:files={pipelineFiles}
type="file"
accept=".py"
hidden
/>
<button
class="w-full text-sm font-medium py-2 bg-transparent hover:bg-gray-100 border border-dashed dark:border-gray-800 dark:hover:bg-gray-850 text-center rounded-xl"
type="button"
on:click={() => {
document.getElementById('pipelines-upload-input')?.click();
}}
>
{#if pipelineFiles}
{pipelineFiles.length > 0 ? `${pipelineFiles.length}` : ''} pipeline(s) selected.
{:else}
{$i18n.t('Click here to select a py file.')}
{/if}
</button>
</div>
<button
class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
on:click={() => {
uploadPipelineHandler();
}}
disabled={uploading}
type="button"
>
{#if uploading}
<div class="self-center">
<svg
class=" w-4 h-4"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<style>
.spinner_ajPY {
transform-origin: center;
animation: spinner_AtaB 0.75s infinite linear;
}
@keyframes spinner_AtaB {
100% {
transform: rotate(360deg);
}
}
</style>
<path
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
opacity=".25"
/>
<path
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
class="spinner_ajPY"
/>
</svg>
</div>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="size-4"
>
<path
d="M7.25 10.25a.75.75 0 0 0 1.5 0V4.56l2.22 2.22a.75.75 0 1 0 1.06-1.06l-3.5-3.5a.75.75 0 0 0-1.06 0l-3.5 3.5a.75.75 0 0 0 1.06 1.06l2.22-2.22v5.69Z"
/>
<path
d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
/>
</svg>
{/if}
</button>
</div>
</div>
<div class=" my-2">
<div class=" mb-2 text-sm font-medium">
{$i18n.t('Install from Github URL')}
@@ -384,6 +508,8 @@
</div>
</div>
{/if}
{:else}
<div>Pipelines Not Detected</div>
{/if}
{:else}
<div class="flex justify-center h-full">
@@ -48,7 +48,7 @@
await config.set(await getBackendConfig());
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div class=" space-y-3 overflow-y-scroll max-h-full">
<div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('User Permissions')}</div>
@@ -94,7 +94,7 @@
</div>
</div>
<hr class=" dark:border-gray-700 my-2" />
<hr class=" dark:border-gray-850 my-2" />
<div class="mt-2 space-y-3">
<div>
@@ -0,0 +1,285 @@
<script lang="ts">
import { getRAGConfig, updateRAGConfig } from '$lib/apis/rag';
import Switch from '$lib/components/common/Switch.svelte';
import { documents, models } from '$lib/stores';
import { onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let saveHandler: Function;
let webConfig = null;
let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper'];
let youtubeLanguage = 'en';
let youtubeTranslation = null;
const submitHandler = async () => {
const res = await updateRAGConfig(localStorage.token, {
web: webConfig,
youtube: {
language: youtubeLanguage.split(',').map((lang) => lang.trim()),
translation: youtubeTranslation
}
});
};
onMount(async () => {
const res = await getRAGConfig(localStorage.token);
if (res) {
webConfig = res.web;
youtubeLanguage = res.youtube.language.join(',');
youtubeTranslation = res.youtube.translation;
}
});
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={async () => {
await submitHandler();
saveHandler();
}}
>
<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
{#if webConfig}
<div>
<div class=" mb-1 text-sm font-medium">
{$i18n.t('Web Search')}
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Enable Web Search')}
</div>
<Switch bind:state={webConfig.search.enabled} />
</div>
</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Web Search Engine')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={webConfig.search.engine}
placeholder={$i18n.t('Select a engine')}
required
>
<option disabled selected value="">{$i18n.t('Select a engine')}</option>
{#each webSearchEngines as engine}
<option value={engine}>{engine}</option>
{/each}
</select>
</div>
</div>
{#if webConfig.search.engine !== ''}
<div class="mt-1.5">
{#if webConfig.search.engine === 'searxng'}
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Searxng Query URL')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Searxng Query URL')}
bind:value={webConfig.search.searxng_query_url}
autocomplete="off"
/>
</div>
</div>
</div>
{:else if webConfig.search.engine === 'google_pse'}
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Google PSE API Key')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Google PSE API Key')}
bind:value={webConfig.search.google_pse_api_key}
autocomplete="off"
/>
</div>
</div>
</div>
<div class="mt-1.5">
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Google PSE Engine Id')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Google PSE Engine Id')}
bind:value={webConfig.search.google_pse_engine_id}
autocomplete="off"
/>
</div>
</div>
</div>
{:else if webConfig.search.engine === 'brave'}
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Brave Search API Key')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Brave Search API Key')}
bind:value={webConfig.search.brave_search_api_key}
autocomplete="off"
/>
</div>
</div>
</div>
{:else if webConfig.search.engine === 'serpstack'}
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Serpstack API Key')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Serpstack API Key')}
bind:value={webConfig.search.serpstack_api_key}
autocomplete="off"
/>
</div>
</div>
</div>
{:else if webConfig.search.engine === 'serper'}
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Serper API Key')}
</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Serper API Key')}
bind:value={webConfig.search.serper_api_key}
autocomplete="off"
/>
</div>
</div>
</div>
{/if}
</div>
{/if}
{#if webConfig.search.enabled}
<div class="mt-2 flex gap-2 mb-1">
<div class="w-full">
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Search Result Count')}
</div>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Search Result Count')}
bind:value={webConfig.search.result_count}
required
/>
</div>
<div class="w-full">
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Concurrent Requests')}
</div>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Concurrent Requests')}
bind:value={webConfig.search.concurrent_requests}
required
/>
</div>
</div>
{/if}
</div>
<hr class=" dark:border-gray-850 my-2" />
<div>
<div class=" mb-1 text-sm font-medium">
{$i18n.t('Web Loader Settings')}
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Bypass SSL verification for Websites')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
webConfig.ssl_verification = !webConfig.ssl_verification;
submitHandler();
}}
type="button"
>
{#if webConfig.ssl_verification === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
<div class=" mt-2 mb-1 text-sm font-medium">
{$i18n.t('Youtube Loader Settings')}
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" w-20 text-xs font-medium self-center">{$i18n.t('Language')}</div>
<div class=" flex-1 self-center">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter language codes')}
bind:value={youtubeLanguage}
autocomplete="off"
/>
</div>
</div>
</div>
</div>
{/if}
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -39,181 +39,5 @@
</svg>
</button>
</div>
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
<div
class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'general'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'general';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M6.955 1.45A.5.5 0 0 1 7.452 1h1.096a.5.5 0 0 1 .497.45l.17 1.699c.484.12.94.312 1.356.562l1.321-1.081a.5.5 0 0 1 .67.033l.774.775a.5.5 0 0 1 .034.67l-1.08 1.32c.25.417.44.873.561 1.357l1.699.17a.5.5 0 0 1 .45.497v1.096a.5.5 0 0 1-.45.497l-1.699.17c-.12.484-.312.94-.562 1.356l1.082 1.322a.5.5 0 0 1-.034.67l-.774.774a.5.5 0 0 1-.67.033l-1.322-1.08c-.416.25-.872.44-1.356.561l-.17 1.699a.5.5 0 0 1-.497.45H7.452a.5.5 0 0 1-.497-.45l-.17-1.699a4.973 4.973 0 0 1-1.356-.562L4.108 13.37a.5.5 0 0 1-.67-.033l-.774-.775a.5.5 0 0 1-.034-.67l1.08-1.32a4.971 4.971 0 0 1-.561-1.357l-1.699-.17A.5.5 0 0 1 1 8.548V7.452a.5.5 0 0 1 .45-.497l1.699-.17c.12-.484.312-.94.562-1.356L2.629 4.107a.5.5 0 0 1 .034-.67l.774-.774a.5.5 0 0 1 .67-.033L5.43 3.71a4.97 4.97 0 0 1 1.356-.561l.17-1.699ZM6 8c0 .538.212 1.026.558 1.385l.057.057a2 2 0 0 0 2.828-2.828l-.058-.056A2 2 0 0 0 6 8Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('General')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'users'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'users';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M8 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM3.156 11.763c.16-.629.44-1.21.813-1.72a2.5 2.5 0 0 0-2.725 1.377c-.136.287.102.58.418.58h1.449c.01-.077.025-.156.045-.237ZM12.847 11.763c.02.08.036.16.046.237h1.446c.316 0 .554-.293.417-.579a2.5 2.5 0 0 0-2.722-1.378c.374.51.653 1.09.813 1.72ZM14 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0ZM3.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM5 13c-.552 0-1.013-.455-.876-.99a4.002 4.002 0 0 1 7.753 0c.136.535-.324.99-.877.99H5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Users')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'db'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'db';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path d="M8 7c3.314 0 6-1.343 6-3s-2.686-3-6-3-6 1.343-6 3 2.686 3 6 3Z" />
<path
d="M8 8.5c1.84 0 3.579-.37 4.914-1.037A6.33 6.33 0 0 0 14 6.78V8c0 1.657-2.686 3-6 3S2 9.657 2 8V6.78c.346.273.72.5 1.087.683C4.42 8.131 6.16 8.5 8 8.5Z"
/>
<path
d="M8 12.5c1.84 0 3.579-.37 4.914-1.037.366-.183.74-.41 1.086-.684V12c0 1.657-2.686 3-6 3s-6-1.343-6-3v-1.22c.346.273.72.5 1.087.683C4.42 12.131 6.16 12.5 8 12.5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Database')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'banners'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'banners';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
d="M5.85 3.5a.75.75 0 0 0-1.117-1 9.719 9.719 0 0 0-2.348 4.876.75.75 0 0 0 1.479.248A8.219 8.219 0 0 1 5.85 3.5ZM19.267 2.5a.75.75 0 1 0-1.118 1 8.22 8.22 0 0 1 1.987 4.124.75.75 0 0 0 1.48-.248A9.72 9.72 0 0 0 19.266 2.5Z"
/>
<path
fill-rule="evenodd"
d="M12 2.25A6.75 6.75 0 0 0 5.25 9v.75a8.217 8.217 0 0 1-2.119 5.52.75.75 0 0 0 .298 1.206c1.544.57 3.16.99 4.831 1.243a3.75 3.75 0 1 0 7.48 0 24.583 24.583 0 0 0 4.83-1.244.75.75 0 0 0 .298-1.205 8.217 8.217 0 0 1-2.118-5.52V9A6.75 6.75 0 0 0 12 2.25ZM9.75 18c0-.034 0-.067.002-.1a25.05 25.05 0 0 0 4.496 0l.002.1a2.25 2.25 0 1 1-4.5 0Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Banners')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'pipelines'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'pipelines';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
d="M11.644 1.59a.75.75 0 0 1 .712 0l9.75 5.25a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.712 0l-9.75-5.25a.75.75 0 0 1 0-1.32l9.75-5.25Z"
/>
<path
d="m3.265 10.602 7.668 4.129a2.25 2.25 0 0 0 2.134 0l7.668-4.13 1.37.739a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.71 0l-9.75-5.25a.75.75 0 0 1 0-1.32l1.37-.738Z"
/>
<path
d="m10.933 19.231-7.668-4.13-1.37.739a.75.75 0 0 0 0 1.32l9.75 5.25c.221.12.489.12.71 0l9.75-5.25a.75.75 0 0 0 0-1.32l-1.37-.738-7.668 4.13a2.25 2.25 0 0 1-2.134-.001Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Pipelines')}</div>
</button>
</div>
<div class="flex-1 md:min-h-[380px]">
{#if selectedTab === 'general'}
<General
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'users'}
<Users
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'db'}
<Database
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'banners'}
<Banners
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'pipelines'}
<Pipelines
saveHandler={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{/if}
</div>
</div>
</div>
</Modal>
+133 -125
View File
@@ -7,6 +7,10 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import type { Writable } from 'svelte/store';
import type { i18n as i18nType } from 'i18next';
import { OLLAMA_API_BASE_URL, OPENAI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import {
chatId,
chats,
@@ -18,7 +22,9 @@
tags as _tags,
WEBUI_NAME,
banners,
user
user,
socket,
showCallOverlay
} from '$lib/stores';
import {
convertMessagesToHistory,
@@ -38,24 +44,19 @@
getTagsById,
updateChatById
} from '$lib/apis/chats';
import {
generateOpenAIChatCompletion,
generateSearchQuery,
generateTitle
} from '$lib/apis/openai';
import { generateOpenAIChatCompletion } from '$lib/apis/openai';
import { runWebSearch } from '$lib/apis/rag';
import { createOpenAITextStream } from '$lib/apis/streaming';
import { queryMemory } from '$lib/apis/memories';
import { getUserSettings } from '$lib/apis/users';
import { chatCompleted, generateTitle, generateSearchQuery } from '$lib/apis';
import Banner from '../common/Banner.svelte';
import MessageInput from '$lib/components/chat/MessageInput.svelte';
import Messages from '$lib/components/chat/Messages.svelte';
import Navbar from '$lib/components/layout/Navbar.svelte';
import { OLLAMA_API_BASE_URL, OPENAI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { createOpenAITextStream } from '$lib/apis/streaming';
import { queryMemory } from '$lib/apis/memories';
import type { Writable } from 'svelte/store';
import type { i18n as i18nType } from 'i18next';
import { runWebSearch } from '$lib/apis/rag';
import Banner from '../common/Banner.svelte';
import { getUserSettings } from '$lib/apis/users';
import { chatCompleted } from '$lib/apis';
import CallOverlay from './MessageInput/CallOverlay.svelte';
import { error } from '@sveltejs/kit';
const i18n: Writable<i18nType> = getContext('i18n');
@@ -280,11 +281,22 @@
}
};
const getChatEventEmitter = async (modelId: string, chatId: string = '') => {
return setInterval(() => {
$socket?.emit('usage', {
action: 'chat',
model: modelId,
chat_id: chatId
});
}, 1000);
};
//////////////////////////
// Ollama functions
// Chat functions
//////////////////////////
const submitPrompt = async (userPrompt, _user = null) => {
let _responses = [];
console.log('submitPrompt', $chatId);
selectedModels = selectedModels.map((modelId) =>
@@ -307,8 +319,15 @@
)
);
} else {
// Reset chat message textarea height
document.getElementById('chat-textarea').style.height = '';
// Reset chat input textarea
const chatTextAreaElement = document.getElementById('chat-textarea');
if (chatTextAreaElement) {
chatTextAreaElement.value = '';
chatTextAreaElement.style.height = '';
}
prompt = '';
// Create user message
let userMessageId = uuidv4();
@@ -360,17 +379,17 @@
await tick();
}
// Reset chat input textarea
prompt = '';
document.getElementById('chat-textarea').style.height = '';
files = [];
// Send prompt
await sendPrompt(userPrompt, userMessageId);
_responses = await sendPrompt(userPrompt, userMessageId);
}
return _responses;
};
const sendPrompt = async (prompt, parentId, modelId = null) => {
let _responses = [];
const _chatId = JSON.parse(JSON.stringify($chatId));
await Promise.all(
@@ -451,15 +470,24 @@
}
responseMessage.userContext = userContext;
const chatEventEmitter = await getChatEventEmitter(model.id, _chatId);
if (webSearchEnabled) {
await getWebSearchResults(model.id, parentId, responseMessageId);
}
let _response = null;
if (model?.owned_by === 'openai') {
await sendPromptOpenAI(model, prompt, responseMessageId, _chatId);
_response = await sendPromptOpenAI(model, prompt, responseMessageId, _chatId);
} else if (model) {
await sendPromptOllama(model, prompt, responseMessageId, _chatId);
_response = await sendPromptOllama(model, prompt, responseMessageId, _chatId);
}
_responses.push(_response);
console.log('chatEventEmitter', chatEventEmitter);
if (chatEventEmitter) clearInterval(chatEventEmitter);
} else {
toast.error($i18n.t(`Model {{modelId}} not found`, { modelId }));
}
@@ -467,6 +495,8 @@
);
await chats.set(await getChatList(localStorage.token));
return _responses;
};
const getWebSearchResults = async (model: string, parentId: string, responseId: string) => {
@@ -480,20 +510,22 @@
messages = messages;
const prompt = history.messages[parentId].content;
let searchQuery = prompt;
if (prompt.length > 100) {
searchQuery = await generateChatSearchQuery(model, prompt);
if (!searchQuery) {
toast.warning($i18n.t('No search query generated'));
responseMessage.status = {
...responseMessage.status,
done: true,
error: true,
description: 'No search query generated'
};
messages = messages;
return;
let searchQuery = await generateSearchQuery(localStorage.token, model, messages, prompt).catch(
(error) => {
console.log(error);
return prompt;
}
);
if (!searchQuery) {
toast.warning($i18n.t('No search query generated'));
responseMessage.status = {
...responseMessage.status,
done: true,
error: true,
description: 'No search query generated'
};
messages = messages;
}
responseMessage.status = {
@@ -541,7 +573,8 @@
};
const sendPromptOllama = async (model, userPrompt, responseMessageId, _chatId) => {
model = model.id;
let _response = null;
const responseMessage = history.messages[responseMessageId];
// Wait until history/message have been updated
@@ -599,17 +632,29 @@
}
});
const docs = messages
.filter((message) => message?.files ?? null)
.map((message) =>
message.files.filter((item) =>
['doc', 'collection', 'web_search_results'].includes(item.type)
let docs = [];
if (model.info.meta.knowledge) {
docs = model.info.meta.knowledge;
}
docs = [
...docs,
...messages
.filter((message) => message?.files ?? null)
.map((message) =>
message.files.filter((item) =>
['doc', 'collection', 'web_search_results'].includes(item.type)
)
)
)
.flat(1);
.flat(1)
].filter(
(item, index, array) =>
array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index
);
const [res, controller] = await generateChatCompletion(localStorage.token, {
model: model,
model: model.id,
messages: messagesBody,
options: {
...($settings.params ?? {}),
@@ -647,9 +692,10 @@
controller.abort('User: Stop Response');
} else {
const messages = createMessagesList(responseMessageId);
await chatCompletedHandler(model, messages);
await chatCompletedHandler(model.id, messages);
}
_response = responseMessage.content;
break;
}
@@ -707,7 +753,7 @@
selectedModelfile.title.charAt(0).toUpperCase() +
selectedModelfile.title.slice(1)
}`
: `${model}`,
: `${model.id}`,
{
body: responseMessage.content,
icon: selectedModelfile?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`
@@ -719,7 +765,7 @@
copyToClipboard(responseMessage.content);
}
if ($settings.responseAutoPlayback) {
if ($settings.responseAutoPlayback && !$showCallOverlay) {
await tick();
document.getElementById(`speak-button-${responseMessage.id}`)?.click();
}
@@ -786,21 +832,34 @@
const _title = await generateChatTitle(userPrompt);
await setChatTitle(_chatId, _title);
}
return _response;
};
const sendPromptOpenAI = async (model, userPrompt, responseMessageId, _chatId) => {
let _response = null;
const responseMessage = history.messages[responseMessageId];
const docs = messages
.filter((message) => message?.files ?? null)
.map((message) =>
message.files.filter((item) =>
['doc', 'collection', 'web_search_results'].includes(item.type)
)
)
.flat(1);
let docs = [];
console.log(docs);
if (model.info.meta.knowledge) {
docs = model.info.meta.knowledge;
}
docs = [
...docs,
...messages
.filter((message) => message?.files ?? null)
.map((message) =>
message.files.filter((item) =>
['doc', 'collection', 'web_search_results'].includes(item.type)
)
)
.flat(1)
].filter(
(item, index, array) =>
array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index
);
scrollToBottom();
@@ -905,6 +964,8 @@
await chatCompletedHandler(model.id, messages);
}
_response = responseMessage.content;
break;
}
@@ -930,7 +991,7 @@
}
if ($settings.notificationEnabled && !document.hasFocus()) {
const notification = new Notification(`OpenAI ${model}`, {
const notification = new Notification(`${model.id}`, {
body: responseMessage.content,
icon: `${WEBUI_BASE_URL}/static/favicon.png`
});
@@ -940,8 +1001,9 @@
copyToClipboard(responseMessage.content);
}
if ($settings.responseAutoPlayback) {
if ($settings.responseAutoPlayback && !$showCallOverlay) {
await tick();
document.getElementById(`speak-button-${responseMessage.id}`)?.click();
}
@@ -980,6 +1042,8 @@
const _title = await generateChatTitle(userPrompt);
await setChatTitle(_chatId, _title);
}
return _response;
};
const handleOpenAIError = async (error, res: Response | null, model, responseMessage) => {
@@ -1075,28 +1139,15 @@
const generateChatTitle = async (userPrompt) => {
if ($settings?.title?.auto ?? true) {
const model = $models.find((model) => model.id === selectedModels[0]);
const titleModelId =
model?.owned_by === 'openai' ?? false
? $settings?.title?.modelExternal ?? selectedModels[0]
: $settings?.title?.model ?? selectedModels[0];
const titleModel = $models.find((model) => model.id === titleModelId);
console.log(titleModel);
const title = await generateTitle(
localStorage.token,
$settings?.title?.prompt ??
$i18n.t(
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':"
) + ' {{prompt}}',
titleModelId,
selectedModels[0],
userPrompt,
$chatId,
titleModel?.owned_by === 'openai' ?? false
? `${OPENAI_API_BASE_URL}`
: `${OLLAMA_API_BASE_URL}/v1`
);
$chatId
).catch((error) => {
console.error(error);
return 'New Chat';
});
return title;
} else {
@@ -1104,29 +1155,6 @@
}
};
const generateChatSearchQuery = async (modelId: string, prompt: string) => {
const model = $models.find((model) => model.id === modelId);
const taskModelId =
model?.owned_by === 'openai' ?? false
? $settings?.title?.modelExternal ?? modelId
: $settings?.title?.model ?? modelId;
const taskModel = $models.find((model) => model.id === taskModelId);
const previousMessages = messages
.filter((message) => message.role === 'user')
.map((message) => message.content);
return await generateSearchQuery(
localStorage.token,
taskModelId,
previousMessages,
prompt,
taskModel?.owned_by === 'openai' ?? false
? `${OPENAI_API_BASE_URL}`
: `${OLLAMA_API_BASE_URL}/v1`
);
};
const setChatTitle = async (_chatId, _title) => {
if (_chatId === $chatId) {
title = _title;
@@ -1143,28 +1171,6 @@
return [];
});
};
const addTag = async (tagName) => {
const res = await addTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
chat = await updateChatById(localStorage.token, $chatId, {
tags: tags
});
_tags.set(await getAllChatTags(localStorage.token));
};
const deleteTag = async (tagName) => {
const res = await deleteTagById(localStorage.token, $chatId, tagName);
tags = await getTags();
chat = await updateChatById(localStorage.token, $chatId, {
tags: tags
});
_tags.set(await getAllChatTags(localStorage.token));
};
</script>
<svelte:head>
@@ -1175,9 +1181,11 @@
</title>
</svelte:head>
<CallOverlay {submitPrompt} bind:files />
{#if !chatIdProp || (loaded && chatIdProp)}
<div
class="min-h-screen max-h-screen {$showSidebar
class="h-screen max-h-[100dvh] {$showSidebar
? 'md:max-w-[calc(100%-260px)]'
: ''} w-full max-w-full flex flex-col"
>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,693 @@
<script lang="ts">
import { config, settings, showCallOverlay } from '$lib/stores';
import { onMount, tick, getContext } from 'svelte';
import { blobToFile, calculateSHA256, extractSentences, findWordIndices } from '$lib/utils';
import { synthesizeOpenAISpeech, transcribeAudio } from '$lib/apis/audio';
import { toast } from 'svelte-sonner';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import VideoInputMenu from './CallOverlay/VideoInputMenu.svelte';
import { get } from 'svelte/store';
const i18n = getContext('i18n');
export let submitPrompt: Function;
export let files;
let loading = false;
let confirmed = false;
let camera = false;
let cameraStream = null;
let assistantSpeaking = false;
let assistantAudio = {};
let assistantAudioIdx = null;
let rmsLevel = 0;
let hasStartedSpeaking = false;
let currentUtterance = null;
let mediaRecorder;
let audioChunks = [];
const MIN_DECIBELS = -45;
const VISUALIZER_BUFFER_LENGTH = 300;
// Function to calculate the RMS level from time domain data
const calculateRMS = (data: Uint8Array) => {
let sumSquares = 0;
for (let i = 0; i < data.length; i++) {
const normalizedValue = (data[i] - 128) / 128; // Normalize the data
sumSquares += normalizedValue * normalizedValue;
}
return Math.sqrt(sumSquares / data.length);
};
const normalizeRMS = (rms) => {
rms = rms * 10;
const exp = 1.5; // Adjust exponent value; values greater than 1 expand larger numbers more and compress smaller numbers more
const scaledRMS = Math.pow(rms, exp);
// Scale between 0.01 (1%) and 1.0 (100%)
return Math.min(1.0, Math.max(0.01, scaledRMS));
};
const analyseAudio = (stream) => {
const audioContext = new AudioContext();
const audioStreamSource = audioContext.createMediaStreamSource(stream);
const analyser = audioContext.createAnalyser();
analyser.minDecibels = MIN_DECIBELS;
audioStreamSource.connect(analyser);
const bufferLength = analyser.frequencyBinCount;
const domainData = new Uint8Array(bufferLength);
const timeDomainData = new Uint8Array(analyser.fftSize);
let lastSoundTime = Date.now();
hasStartedSpeaking = false;
const detectSound = () => {
const processFrame = () => {
if (!mediaRecorder || !$showCallOverlay) {
if (mediaRecorder) {
mediaRecorder.stop();
}
return;
}
analyser.getByteTimeDomainData(timeDomainData);
analyser.getByteFrequencyData(domainData);
// Calculate RMS level from time domain data
rmsLevel = calculateRMS(timeDomainData);
// Check if initial speech/noise has started
const hasSound = domainData.some((value) => value > 0);
if (hasSound) {
stopAllAudio();
hasStartedSpeaking = true;
lastSoundTime = Date.now();
}
// Start silence detection only after initial speech/noise has been detected
if (hasStartedSpeaking) {
if (Date.now() - lastSoundTime > 2000) {
confirmed = true;
if (mediaRecorder) {
mediaRecorder.stop();
}
}
}
window.requestAnimationFrame(processFrame);
};
window.requestAnimationFrame(processFrame);
};
detectSound();
};
const stopAllAudio = () => {
if (currentUtterance) {
speechSynthesis.cancel();
currentUtterance = null;
}
if (assistantAudio[assistantAudioIdx]) {
assistantAudio[assistantAudioIdx].pause();
assistantAudio[assistantAudioIdx].currentTime = 0;
}
const audioElement = document.getElementById('audioElement');
audioElement.pause();
audioElement.currentTime = 0;
assistantSpeaking = false;
};
const playAudio = (idx) => {
if ($showCallOverlay) {
return new Promise((res) => {
assistantAudioIdx = idx;
const audioElement = document.getElementById('audioElement');
const audio = assistantAudio[idx];
audioElement.src = audio.src; // Assume `assistantAudio` has objects with a `src` property
audioElement.muted = true;
audioElement
.play()
.then(() => {
audioElement.muted = false;
})
.catch((error) => {
toast.error(error);
});
audioElement.onended = async (e) => {
await new Promise((r) => setTimeout(r, 300));
if (Object.keys(assistantAudio).length - 1 === idx) {
assistantSpeaking = false;
}
res(e);
};
});
} else {
return Promise.resolve();
}
};
const getOpenAISpeech = async (text) => {
const res = await synthesizeOpenAISpeech(
localStorage.token,
$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
text
).catch((error) => {
toast.error(error);
assistantSpeaking = false;
return null;
});
if (res) {
const blob = await res.blob();
const blobUrl = URL.createObjectURL(blob);
const audio = new Audio(blobUrl);
assistantAudio = audio;
}
};
const transcribeHandler = async (audioBlob) => {
// Create a blob from the audio chunks
await tick();
const file = blobToFile(audioBlob, 'recording.wav');
const res = await transcribeAudio(localStorage.token, file).catch((error) => {
toast.error(error);
return null;
});
if (res) {
console.log(res.text);
if (res.text !== '') {
const _responses = await submitPrompt(res.text);
console.log(_responses);
if (_responses.at(0)) {
const content = _responses[0];
if (content) {
assistantSpeakingHandler(content);
}
}
}
}
};
const assistantSpeakingHandler = async (content) => {
assistantSpeaking = true;
if (($config.audio.tts.engine ?? '') == '') {
let voices = [];
const getVoicesLoop = setInterval(async () => {
voices = await speechSynthesis.getVoices();
if (voices.length > 0) {
clearInterval(getVoicesLoop);
const voice =
voices
?.filter(
(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
)
?.at(0) ?? undefined;
currentUtterance = new SpeechSynthesisUtterance(content);
if (voice) {
currentUtterance.voice = voice;
}
speechSynthesis.speak(currentUtterance);
}
}, 100);
} else if ($config.audio.tts.engine === 'openai') {
console.log('openai');
const sentences = extractSentences(content).reduce((mergedTexts, currentText) => {
const lastIndex = mergedTexts.length - 1;
if (lastIndex >= 0) {
const previousText = mergedTexts[lastIndex];
const wordCount = previousText.split(/\s+/).length;
if (wordCount < 2) {
mergedTexts[lastIndex] = previousText + ' ' + currentText;
} else {
mergedTexts.push(currentText);
}
} else {
mergedTexts.push(currentText);
}
return mergedTexts;
}, []);
console.log(sentences);
let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
for (const [idx, sentence] of sentences.entries()) {
const res = await synthesizeOpenAISpeech(
localStorage.token,
$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
sentence
).catch((error) => {
toast.error(error);
assistantSpeaking = false;
return null;
});
if (res) {
const blob = await res.blob();
const blobUrl = URL.createObjectURL(blob);
const audio = new Audio(blobUrl);
assistantAudio[idx] = audio;
lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
}
}
}
};
const stopRecordingCallback = async () => {
if ($showCallOverlay) {
if (confirmed) {
loading = true;
if (cameraStream) {
const imageUrl = takeScreenshot();
files = [
{
type: 'image',
url: imageUrl
}
];
}
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
await transcribeHandler(audioBlob);
confirmed = false;
loading = false;
}
audioChunks = [];
mediaRecorder = false;
startRecording();
} else {
audioChunks = [];
mediaRecorder = false;
}
};
const startRecording = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.onstart = () => {
console.log('Recording started');
audioChunks = [];
analyseAudio(stream);
};
mediaRecorder.ondataavailable = (event) => {
if (hasStartedSpeaking) {
audioChunks.push(event.data);
}
};
mediaRecorder.onstop = async () => {
console.log('Recording stopped');
await stopRecordingCallback();
};
mediaRecorder.start();
};
let videoInputDevices = [];
let selectedVideoInputDeviceId = null;
const getVideoInputDevices = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
videoInputDevices = devices.filter((device) => device.kind === 'videoinput');
if (!!navigator.mediaDevices.getDisplayMedia) {
videoInputDevices = [
...videoInputDevices,
{
deviceId: 'screen',
label: 'Screen Share'
}
];
}
console.log(videoInputDevices);
if (selectedVideoInputDeviceId === null && videoInputDevices.length > 0) {
selectedVideoInputDeviceId = videoInputDevices[0].deviceId;
}
};
const startCamera = async () => {
await getVideoInputDevices();
if (cameraStream === null) {
camera = true;
await tick();
try {
await startVideoStream();
} catch (err) {
console.error('Error accessing webcam: ', err);
}
}
};
const startVideoStream = async () => {
const video = document.getElementById('camera-feed');
if (video) {
if (selectedVideoInputDeviceId === 'screen') {
cameraStream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: 'always'
},
audio: false
});
} else {
cameraStream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: selectedVideoInputDeviceId ? { exact: selectedVideoInputDeviceId } : undefined
}
});
}
if (cameraStream) {
await getVideoInputDevices();
video.srcObject = cameraStream;
await video.play();
}
}
};
const stopVideoStream = async () => {
if (cameraStream) {
const tracks = cameraStream.getTracks();
tracks.forEach((track) => track.stop());
}
cameraStream = null;
};
const takeScreenshot = () => {
const video = document.getElementById('camera-feed');
const canvas = document.getElementById('camera-canvas');
if (!canvas) {
return;
}
const context = canvas.getContext('2d');
// Make the canvas match the video dimensions
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// Draw the image from the video onto the canvas
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
// Convert the canvas to a data base64 URL and console log it
const dataURL = canvas.toDataURL('image/png');
console.log(dataURL);
return dataURL;
};
const stopCamera = async () => {
await stopVideoStream();
camera = false;
};
$: if ($showCallOverlay) {
startRecording();
} else {
stopCamera();
}
</script>
{#if $showCallOverlay}
<audio id="audioElement" src="" style="display: none;" />
<div class=" absolute w-full h-screen max-h-[100dvh] flex z-[999] overflow-hidden">
<div
class="absolute w-full h-screen max-h-[100dvh] bg-white text-gray-700 dark:bg-black dark:text-gray-300 flex justify-center"
>
<div class="max-w-lg w-full h-screen max-h-[100dvh] flex flex-col justify-between p-3 md:p-6">
{#if camera}
<div class="flex justify-center items-center w-full min-h-20">
{#if loading}
<svg
class="size-12 text-gray-900 dark:text-gray-400"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_qM83 {
animation: spinner_8HQG 1.05s infinite;
}
.spinner_oXPr {
animation-delay: 0.1s;
}
.spinner_ZTLf {
animation-delay: 0.2s;
}
@keyframes spinner_8HQG {
0%,
57.14% {
animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1);
transform: translate(0);
}
28.57% {
animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33);
transform: translateY(-6px);
}
100% {
transform: translate(0);
}
}
</style><circle class="spinner_qM83" cx="4" cy="12" r="3" /><circle
class="spinner_qM83 spinner_oXPr"
cx="12"
cy="12"
r="3"
/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="3" /></svg
>
{:else}
<div
class=" {rmsLevel * 100 > 4
? ' size-[4.5rem]'
: rmsLevel * 100 > 2
? ' size-16'
: rmsLevel * 100 > 1
? 'size-14'
: 'size-12'} transition-all bg-black dark:bg-white rounded-full"
/>
{/if}
<!-- navbar -->
</div>
{/if}
<div class="flex justify-center items-center flex-1 h-full w-full max-h-full">
{#if !camera}
{#if loading}
<svg
class="size-44 text-gray-900 dark:text-gray-400"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_qM83 {
animation: spinner_8HQG 1.05s infinite;
}
.spinner_oXPr {
animation-delay: 0.1s;
}
.spinner_ZTLf {
animation-delay: 0.2s;
}
@keyframes spinner_8HQG {
0%,
57.14% {
animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1);
transform: translate(0);
}
28.57% {
animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33);
transform: translateY(-6px);
}
100% {
transform: translate(0);
}
}
</style><circle class="spinner_qM83" cx="4" cy="12" r="3" /><circle
class="spinner_qM83 spinner_oXPr"
cx="12"
cy="12"
r="3"
/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="3" /></svg
>
{:else}
<div
class=" {rmsLevel * 100 > 4
? ' size-52'
: rmsLevel * 100 > 2
? 'size-48'
: rmsLevel * 100 > 1
? 'size-[11.5rem]'
: 'size-44'} transition-all bg-black dark:bg-white rounded-full"
/>
{/if}
{:else}
<div
class="relative flex video-container w-full max-h-full pt-2 pb-4 md:py-6 px-2 h-full"
>
<video
id="camera-feed"
autoplay
class="rounded-2xl h-full min-w-full object-cover object-center"
playsinline
/>
<canvas id="camera-canvas" style="display:none;" />
<div class=" absolute top-4 md:top-8 left-4">
<button
type="button"
class="p-1.5 text-white cursor-pointer backdrop-blur-xl bg-black/10 rounded-full"
on:click={() => {
stopCamera();
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="size-6"
>
<path
d="M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z"
/>
</svg>
</button>
</div>
</div>
{/if}
</div>
<div class="flex justify-between items-center pb-2 w-full">
<div>
{#if camera}
<VideoInputMenu
devices={videoInputDevices}
on:change={async (e) => {
console.log(e.detail);
selectedVideoInputDeviceId = e.detail;
await stopVideoStream();
await startVideoStream();
}}
>
<button class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900" type="button">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="size-5"
>
<path
fill-rule="evenodd"
d="M15.312 11.424a5.5 5.5 0 0 1-9.201 2.466l-.312-.311h2.433a.75.75 0 0 0 0-1.5H3.989a.75.75 0 0 0-.75.75v4.242a.75.75 0 0 0 1.5 0v-2.43l.31.31a7 7 0 0 0 11.712-3.138.75.75 0 0 0-1.449-.39Zm1.23-3.723a.75.75 0 0 0 .219-.53V2.929a.75.75 0 0 0-1.5 0V5.36l-.31-.31A7 7 0 0 0 3.239 8.188a.75.75 0 1 0 1.448.389A5.5 5.5 0 0 1 13.89 6.11l.311.31h-2.432a.75.75 0 0 0 0 1.5h4.243a.75.75 0 0 0 .53-.219Z"
clip-rule="evenodd"
/>
</svg>
</button>
</VideoInputMenu>
{:else}
<Tooltip content={$i18n.t('Camera')}>
<button
class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"
type="button"
on:click={() => {
startCamera();
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6.827 6.175A2.31 2.31 0 0 1 5.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 0 0-1.134-.175 2.31 2.31 0 0 1-1.64-1.055l-.822-1.316a2.192 2.192 0 0 0-1.736-1.039 48.774 48.774 0 0 0-5.232 0 2.192 2.192 0 0 0-1.736 1.039l-.821 1.316Z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.5 12.75a4.5 4.5 0 1 1-9 0 4.5 4.5 0 0 1 9 0ZM18.75 10.5h.008v.008h-.008V10.5Z"
/>
</svg>
</button>
</Tooltip>
{/if}
</div>
<div>
<button type="button">
<div class=" line-clamp-1 text-sm font-medium">
{#if loading}
{$i18n.t('Thinking...')}
{:else}
{$i18n.t('Listening...')}
{/if}
</div>
</button>
</div>
<div>
<button
class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"
on:click={async () => {
showCallOverlay.set(false);
}}
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="size-5"
>
<path
d="M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"
/>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
{/if}
@@ -0,0 +1,51 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import { getContext, createEventDispatcher } from 'svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
import Dropdown from '$lib/components/common/Dropdown.svelte';
export let onClose: Function = () => {};
export let devices: any;
let show = false;
</script>
<Dropdown
bind:show
on:change={(e) => {
if (e.detail === false) {
onClose();
}
}}
>
<slot />
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[180px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-[9999] bg-white dark:bg-gray-900 dark:text-white shadow-sm"
sideOffset={6}
side="top"
align="start"
transition={flyAndScale}
>
{#each devices as device}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
on:click={() => {
dispatch('change', device.deviceId);
}}
>
<div class="flex items-center">
<div class=" line-clamp-1">
{device?.label ?? 'Camera'}
</div>
</div>
</DropdownMenu.Item>
{/each}
</DropdownMenu.Content>
</div>
</Dropdown>
@@ -101,7 +101,7 @@
</script>
{#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="pl-1 pr-12 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="flex w-full px-2">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-xl text-center">
<div class=" text-lg font-semibold mt-2">#</div>
@@ -133,7 +133,7 @@
{#if prompt.charAt(0) === '@'}
{#if filteredModels.length > 0}
<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="pl-1 pr-12 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="flex w-full px-2">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-xl text-center">
<div class=" text-lg font-semibold mt-2">@</div>
@@ -6,6 +6,7 @@
const i18n = getContext('i18n');
export let files;
export let prompt = '';
let selectedCommandIdx = 0;
let filteredPromptCommands = [];
@@ -35,6 +36,32 @@
return '{{CLIPBOARD}}';
});
console.log(clipboardText);
const clipboardItems = await navigator.clipboard.read();
let imageUrl = null;
for (const item of clipboardItems) {
// Check for known image types
for (const type of item.types) {
if (type.startsWith('image/')) {
const blob = await item.getType(type);
imageUrl = URL.createObjectURL(blob);
console.log(`Image URL (${type}): ${imageUrl}`);
}
}
}
if (imageUrl) {
files = [
...files,
{
type: 'image',
url: imageUrl
}
];
}
text = command.content.replaceAll('{{CLIPBOARD}}', clipboardText);
}
@@ -61,7 +88,7 @@
</script>
{#if filteredPromptCommands.length > 0}
<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="pl-1 pr-12 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div class="flex w-full px-2">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-xl text-center">
<div class=" text-lg font-semibold mt-2">/</div>
@@ -0,0 +1,458 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { createEventDispatcher, tick, getContext } from 'svelte';
import { config, settings } from '$lib/stores';
import { blobToFile, calculateSHA256, findWordIndices } from '$lib/utils';
import { transcribeAudio } from '$lib/apis/audio';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
export let recording = false;
let loading = false;
let confirmed = false;
let durationSeconds = 0;
let durationCounter = null;
let transcription = '';
const startDurationCounter = () => {
durationCounter = setInterval(() => {
durationSeconds++;
}, 1000);
};
const stopDurationCounter = () => {
clearInterval(durationCounter);
durationSeconds = 0;
};
$: if (recording) {
startRecording();
} else {
stopRecording();
}
const formatSeconds = (seconds) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
const formattedSeconds = remainingSeconds < 10 ? `0${remainingSeconds}` : remainingSeconds;
return `${minutes}:${formattedSeconds}`;
};
let speechRecognition;
let mediaRecorder;
let audioChunks = [];
const MIN_DECIBELS = -45;
const VISUALIZER_BUFFER_LENGTH = 300;
let visualizerData = Array(VISUALIZER_BUFFER_LENGTH).fill(0);
// Function to calculate the RMS level from time domain data
const calculateRMS = (data: Uint8Array) => {
let sumSquares = 0;
for (let i = 0; i < data.length; i++) {
const normalizedValue = (data[i] - 128) / 128; // Normalize the data
sumSquares += normalizedValue * normalizedValue;
}
return Math.sqrt(sumSquares / data.length);
};
const normalizeRMS = (rms) => {
rms = rms * 10;
const exp = 1.5; // Adjust exponent value; values greater than 1 expand larger numbers more and compress smaller numbers more
const scaledRMS = Math.pow(rms, exp);
// Scale between 0.01 (1%) and 1.0 (100%)
return Math.min(1.0, Math.max(0.01, scaledRMS));
};
const analyseAudio = (stream) => {
const audioContext = new AudioContext();
const audioStreamSource = audioContext.createMediaStreamSource(stream);
const analyser = audioContext.createAnalyser();
analyser.minDecibels = MIN_DECIBELS;
audioStreamSource.connect(analyser);
const bufferLength = analyser.frequencyBinCount;
const domainData = new Uint8Array(bufferLength);
const timeDomainData = new Uint8Array(analyser.fftSize);
let lastSoundTime = Date.now();
const detectSound = () => {
const processFrame = () => {
if (!recording || loading) return;
if (recording && !loading) {
analyser.getByteTimeDomainData(timeDomainData);
analyser.getByteFrequencyData(domainData);
// Calculate RMS level from time domain data
const rmsLevel = calculateRMS(timeDomainData);
// Push the calculated decibel level to visualizerData
visualizerData.push(normalizeRMS(rmsLevel));
// Ensure visualizerData array stays within the buffer length
if (visualizerData.length >= VISUALIZER_BUFFER_LENGTH) {
visualizerData.shift();
}
visualizerData = visualizerData;
// if (domainData.some((value) => value > 0)) {
// lastSoundTime = Date.now();
// }
// if (recording && Date.now() - lastSoundTime > 3000) {
// if ($settings?.speechAutoSend ?? false) {
// confirmRecording();
// }
// }
}
window.requestAnimationFrame(processFrame);
};
window.requestAnimationFrame(processFrame);
};
detectSound();
};
const transcribeHandler = async (audioBlob) => {
// Create a blob from the audio chunks
await tick();
const file = blobToFile(audioBlob, 'recording.wav');
const res = await transcribeAudio(localStorage.token, file).catch((error) => {
toast.error(error);
return null;
});
if (res) {
console.log(res.text);
dispatch('confirm', res.text);
}
};
const saveRecording = (blob) => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = 'recording.wav';
a.click();
window.URL.revokeObjectURL(url);
};
const startRecording = async () => {
startDurationCounter();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.onstart = () => {
console.log('Recording started');
audioChunks = [];
analyseAudio(stream);
};
mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data);
mediaRecorder.onstop = async () => {
console.log('Recording stopped');
if (($settings?.audio?.stt?.engine ?? '') === 'web') {
audioChunks = [];
} else {
if (confirmed) {
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
await transcribeHandler(audioBlob);
confirmed = false;
loading = false;
}
audioChunks = [];
recording = false;
}
};
mediaRecorder.start();
if ($config.audio.stt.engine === 'web' || ($settings?.audio?.stt?.engine ?? '') === 'web') {
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) {
// Create a SpeechRecognition object
speechRecognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
// Set continuous to true for continuous recognition
speechRecognition.continuous = true;
// Set the timeout for turning off the recognition after inactivity (in milliseconds)
const inactivityTimeout = 2000; // 3 seconds
let timeoutId;
// Start recognition
speechRecognition.start();
// Event triggered when speech is recognized
speechRecognition.onresult = async (event) => {
// Clear the inactivity timeout
clearTimeout(timeoutId);
// Handle recognized speech
console.log(event);
const transcript = event.results[Object.keys(event.results).length - 1][0].transcript;
transcription = `${transcription}${transcript}`;
await tick();
document.getElementById('chat-textarea')?.focus();
// Restart the inactivity timeout
timeoutId = setTimeout(() => {
console.log('Speech recognition turned off due to inactivity.');
speechRecognition.stop();
}, inactivityTimeout);
};
// Event triggered when recognition is ended
speechRecognition.onend = function () {
// Restart recognition after it ends
console.log('recognition ended');
confirmRecording();
dispatch('confirm', transcription);
confirmed = false;
loading = false;
};
// Event triggered when an error occurs
speechRecognition.onerror = function (event) {
console.log(event);
toast.error($i18n.t(`Speech recognition error: {{error}}`, { error: event.error }));
dispatch('cancel');
stopRecording();
};
}
}
};
const stopRecording = async () => {
if (recording && mediaRecorder) {
await mediaRecorder.stop();
}
stopDurationCounter();
audioChunks = [];
};
const confirmRecording = async () => {
loading = true;
confirmed = true;
if (recording && mediaRecorder) {
await mediaRecorder.stop();
}
clearInterval(durationCounter);
};
</script>
<div
class="{loading
? ' bg-gray-100/50 dark:bg-gray-850/50'
: 'bg-indigo-300/10 dark:bg-indigo-500/10 '} rounded-full flex p-2.5"
>
<div class="flex items-center mr-1">
<button
type="button"
class="p-1.5
{loading
? ' bg-gray-200 dark:bg-gray-700/50'
: 'bg-indigo-400/20 text-indigo-600 dark:text-indigo-300 '}
rounded-full"
on:click={async () => {
dispatch('cancel');
stopRecording();
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="3"
stroke="currentColor"
class="size-4"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</button>
</div>
<div
class="flex flex-1 self-center items-center justify-between ml-2 mx-1 overflow-hidden h-6"
dir="rtl"
>
<div class="flex-1 flex items-center gap-0.5 h-6">
{#each visualizerData.slice().reverse() as rms}
<div
class="w-[2px]
{loading
? ' bg-gray-500 dark:bg-gray-400 '
: 'bg-indigo-500 dark:bg-indigo-400 '}
inline-block h-full"
style="height: {Math.min(100, Math.max(14, rms * 100))}%;"
/>
{/each}
</div>
</div>
<div class=" mx-1.5 pr-1 flex justify-center items-center">
<div
class="text-sm
{loading ? ' text-gray-500 dark:text-gray-400 ' : ' text-indigo-400 '}
font-medium flex-1 mx-auto text-center"
>
{formatSeconds(durationSeconds)}
</div>
</div>
<div class="flex items-center mr-1">
{#if loading}
<div class=" text-gray-500 rounded-full cursor-not-allowed">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
><style>
.spinner_OSmW {
transform-origin: center;
animation: spinner_T6mA 0.75s step-end infinite;
}
@keyframes spinner_T6mA {
8.3% {
transform: rotate(30deg);
}
16.6% {
transform: rotate(60deg);
}
25% {
transform: rotate(90deg);
}
33.3% {
transform: rotate(120deg);
}
41.6% {
transform: rotate(150deg);
}
50% {
transform: rotate(180deg);
}
58.3% {
transform: rotate(210deg);
}
66.6% {
transform: rotate(240deg);
}
75% {
transform: rotate(270deg);
}
83.3% {
transform: rotate(300deg);
}
91.6% {
transform: rotate(330deg);
}
100% {
transform: rotate(360deg);
}
}
</style><g class="spinner_OSmW"
><rect x="11" y="1" width="2" height="5" opacity=".14" /><rect
x="11"
y="1"
width="2"
height="5"
transform="rotate(30 12 12)"
opacity=".29"
/><rect
x="11"
y="1"
width="2"
height="5"
transform="rotate(60 12 12)"
opacity=".43"
/><rect
x="11"
y="1"
width="2"
height="5"
transform="rotate(90 12 12)"
opacity=".57"
/><rect
x="11"
y="1"
width="2"
height="5"
transform="rotate(120 12 12)"
opacity=".71"
/><rect
x="11"
y="1"
width="2"
height="5"
transform="rotate(150 12 12)"
opacity=".86"
/><rect x="11" y="1" width="2" height="5" transform="rotate(180 12 12)" /></g
></svg
>
</div>
{:else}
<button
type="button"
class="p-1.5 bg-indigo-500 text-white dark:bg-indigo-500 dark:text-blue-950 rounded-full"
on:click={async () => {
await confirmRecording();
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2.5"
stroke="currentColor"
class="size-4"
>
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
</button>
{/if}
</div>
</div>
<style>
.visualizer {
display: flex;
height: 100%;
}
.visualizer-bar {
width: 2px;
background-color: #4a5aba; /* or whatever color you need */
}
</style>
+1 -1
View File
@@ -286,7 +286,7 @@
{#each messages as message, messageIdx}
<div class=" w-full {messageIdx === messages.length - 1 ? ' pb-12' : ''}">
<div
class="flex flex-col justify-between px-5 mb-3 {$settings?.fullScreenMode ?? null
class="flex flex-col justify-between px-5 mb-3 {$settings?.widescreenMode ?? null
? 'max-w-full'
: 'max-w-5xl'} mx-auto rounded-lg group"
>
@@ -109,7 +109,7 @@
class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
currentMessageId
].model === model
? 'border-gray-100 dark:border-gray-700 border-[1.5px]'
? 'border-gray-100 dark:border-gray-850 border-[1.5px]'
: 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl"
on:click={() => {
currentMessageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id;
@@ -213,7 +213,7 @@
} else {
speaking = true;
if ($settings?.audio?.TTSEngine === 'openai') {
if ($config.audio.tts.engine === 'openai') {
loadingSpeech = true;
const sentences = extractSentences(message.content).reduce((mergedTexts, currentText) => {
@@ -244,9 +244,8 @@
for (const [idx, sentence] of sentences.entries()) {
const res = await synthesizeOpenAISpeech(
localStorage.token,
$settings?.audio?.speaker,
sentence,
$settings?.audio?.model
$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
sentence
).catch((error) => {
toast.error(error);
@@ -273,17 +272,29 @@
clearInterval(getVoicesLoop);
const voice =
voices?.filter((v) => v.name === $settings?.audio?.speaker)?.at(0) ?? undefined;
voices
?.filter(
(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
)
?.at(0) ?? undefined;
console.log(voice);
const speak = new SpeechSynthesisUtterance(message.content);
console.log(speak);
speak.onend = () => {
speaking = null;
if ($settings.conversationMode) {
document.getElementById('voice-input-button')?.click();
}
};
speak.voice = voice;
if (voice) {
speak.voice = voice;
}
speechSynthesis.speak(speak);
}
}, 100);
@@ -757,7 +768,7 @@
</Tooltip>
{#if $config?.features.enable_image_generation && !readOnly}
<Tooltip content="Generate Image" placement="bottom">
<Tooltip content={$i18n.t('Generate Image')} placement="bottom">
<button
class="{isLastMessage
? 'visible'
@@ -219,7 +219,7 @@
<DropdownMenu.Content
class=" z-40 {$mobile
? `w-full`
: `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/50 outline-none "
: `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-850/50 outline-none "
transition={flyAndScale}
side={$mobile ? 'bottom' : 'bottom-start'}
sideOffset={4}
@@ -265,7 +265,7 @@
</div>
{/if}
<div class="flex items-center gap-2">
<div class="flex items-center">
<div class="flex items-center min-w-fit">
<div class="line-clamp-1">
{item.label}
</div>
@@ -92,7 +92,7 @@
</div>
{#if ollamaVersion}
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Ollama Version')}</div>
@@ -104,7 +104,7 @@
</div>
{/if}
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div class="flex space-x-1">
<a href="https://discord.gg/5rJgQTnV4s" target="_blank">
@@ -234,7 +234,7 @@
<UpdatePassword />
</div>
<hr class=" dark:border-gray-700 my-4" />
<hr class=" dark:border-gray-850 my-4" />
<div class="flex justify-between items-center text-sm">
<div class=" font-medium">{$i18n.t('API keys')}</div>
@@ -556,7 +556,7 @@
type="number"
class=" bg-transparent text-center w-14"
min="-1"
step="10"
step="1"
/>
</div>
</div>
+40 -203
View File
@@ -1,6 +1,5 @@
<script lang="ts">
import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
import { user, settings } from '$lib/stores';
import { user, settings, config } from '$lib/stores';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import Switch from '$lib/components/common/Switch.svelte';
@@ -11,26 +10,15 @@
export let saveSettings: Function;
// Audio
let OpenAIUrl = '';
let OpenAIKey = '';
let OpenAISpeaker = '';
let STTEngines = ['', 'openai'];
let STTEngine = '';
let conversationMode = false;
let speechAutoSend = false;
let responseAutoPlayback = false;
let nonLocalVoices = false;
let TTSEngines = ['', 'openai'];
let TTSEngine = '';
let STTEngine = '';
let voices = [];
let speaker = '';
let models = [];
let model = '';
let voice = '';
const getOpenAIVoices = () => {
voices = [
@@ -43,10 +31,6 @@
];
};
const getOpenAIVoicesModel = () => {
models = [{ name: 'tts-1' }, { name: 'tts-1-hd' }];
};
const getWebAPIVoices = () => {
const getVoicesLoop = setInterval(async () => {
voices = await speechSynthesis.getVoices();
@@ -58,21 +42,6 @@
}, 100);
};
const toggleConversationMode = async () => {
conversationMode = !conversationMode;
if (conversationMode) {
responseAutoPlayback = true;
speechAutoSend = true;
}
saveSettings({
conversationMode: conversationMode,
responseAutoPlayback: responseAutoPlayback,
speechAutoSend: speechAutoSend
});
};
const toggleResponseAutoPlayback = async () => {
responseAutoPlayback = !responseAutoPlayback;
saveSettings({ responseAutoPlayback: responseAutoPlayback });
@@ -83,76 +52,35 @@
saveSettings({ speechAutoSend: speechAutoSend });
};
const updateConfigHandler = async () => {
if (TTSEngine === 'openai') {
const res = await updateAudioConfig(localStorage.token, {
url: OpenAIUrl,
key: OpenAIKey,
model: model,
speaker: OpenAISpeaker
});
if (res) {
OpenAIUrl = res.OPENAI_API_BASE_URL;
OpenAIKey = res.OPENAI_API_KEY;
model = res.OPENAI_API_MODEL;
OpenAISpeaker = res.OPENAI_API_VOICE;
}
}
};
onMount(async () => {
conversationMode = $settings.conversationMode ?? false;
speechAutoSend = $settings.speechAutoSend ?? false;
responseAutoPlayback = $settings.responseAutoPlayback ?? false;
STTEngine = $settings?.audio?.STTEngine ?? '';
TTSEngine = $settings?.audio?.TTSEngine ?? '';
nonLocalVoices = $settings.audio?.nonLocalVoices ?? false;
speaker = $settings?.audio?.speaker ?? '';
model = $settings?.audio?.model ?? '';
STTEngine = $settings?.audio?.stt?.engine ?? '';
voice = $settings?.audio?.tts?.voice ?? $config.audio.tts.voice ?? '';
nonLocalVoices = $settings.audio?.tts?.nonLocalVoices ?? false;
if (TTSEngine === 'openai') {
if ($config.audio.tts.engine === 'openai') {
getOpenAIVoices();
getOpenAIVoicesModel();
} else {
getWebAPIVoices();
}
if ($user.role === 'admin') {
const res = await getAudioConfig(localStorage.token);
if (res) {
OpenAIUrl = res.OPENAI_API_BASE_URL;
OpenAIKey = res.OPENAI_API_KEY;
model = res.OPENAI_API_MODEL;
OpenAISpeaker = res.OPENAI_API_VOICE;
if (TTSEngine === 'openai') {
speaker = OpenAISpeaker;
}
}
}
});
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={async () => {
if ($user.role === 'admin') {
await updateConfigHandler();
}
saveSettings({
audio: {
STTEngine: STTEngine !== '' ? STTEngine : undefined,
TTSEngine: TTSEngine !== '' ? TTSEngine : undefined,
speaker:
(TTSEngine === 'openai' ? OpenAISpeaker : speaker) !== ''
? TTSEngine === 'openai'
? OpenAISpeaker
: speaker
: undefined,
model: model !== '' ? model : undefined,
nonLocalVoices: nonLocalVoices
stt: {
engine: STTEngine !== '' ? STTEngine : undefined
},
tts: {
voice: voice !== '' ? voice : undefined,
nonLocalVoices: $config.audio.tts.engine === '' ? nonLocalVoices : undefined
}
}
});
dispatch('save');
@@ -162,53 +90,25 @@
<div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('STT Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Speech-to-Text Engine')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={STTEngine}
placeholder="Select a mode"
on:change={(e) => {
if (e.target.value !== '') {
navigator.mediaDevices.getUserMedia({ audio: true }).catch(function (err) {
toast.error(
$i18n.t(`Permission denied when accessing microphone: {{error}}`, {
error: err
})
);
STTEngine = '';
});
}
}}
>
<option value="">{$i18n.t('Default (Web API)')}</option>
<option value="whisper-local">{$i18n.t('Whisper (Local)')}</option>
</select>
{#if $config.audio.stt.engine !== 'web'}
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Speech-to-Text Engine')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={STTEngine}
placeholder="Select an engine"
>
<option value="">{$i18n.t('Default')}</option>
<option value="web">{$i18n.t('Web API')}</option>
</select>
</div>
</div>
</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Conversation Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
toggleConversationMode();
}}
type="button"
>
{#if conversationMode === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
{/if}
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Auto-send input after 3 sec.')}
{$i18n.t('Instant Auto-Send After Voice Transcription')}
</div>
<button
@@ -230,50 +130,6 @@
<div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('TTS Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Text-to-Speech Engine')}</div>
<div class="flex items-center relative">
<select
class=" dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={TTSEngine}
placeholder="Select a mode"
on:change={(e) => {
if (e.target.value === 'openai') {
getOpenAIVoices();
OpenAISpeaker = 'alloy';
model = 'tts-1';
} else {
getWebAPIVoices();
speaker = '';
}
}}
>
<option value="">{$i18n.t('Default (Web API)')}</option>
<option value="openai">{$i18n.t('Open AI')}</option>
</select>
</div>
</div>
{#if $user.role === 'admin'}
{#if TTSEngine === 'openai'}
<div class="mt-1 flex gap-2 mb-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Base URL')}
bind:value={OpenAIUrl}
required
/>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('API Key')}
bind:value={OpenAIKey}
required
/>
</div>
{/if}
{/if}
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Auto-playback response')}</div>
@@ -293,30 +149,30 @@
</div>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
{#if TTSEngine === ''}
{#if $config.audio.tts.engine === ''}
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
<div class="flex w-full">
<div class="flex-1">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={speaker}
bind:value={voice}
>
<option value="" selected={speaker !== ''}>{$i18n.t('Default')}</option>
{#each voices.filter((v) => nonLocalVoices || v.localService === true) as voice}
<option value="" selected={voice !== ''}>{$i18n.t('Default')}</option>
{#each voices.filter((v) => nonLocalVoices || v.localService === true) as _voice}
<option
value={voice.name}
value={_voice.name}
class="bg-gray-100 dark:bg-gray-700"
selected={speaker === voice.name}>{voice.name}</option
selected={voice === _voice.name}>{_voice.name}</option
>
{/each}
</select>
</div>
</div>
<div class="flex items-center justify-between mb-1">
<div class="text-sm">
<div class="flex items-center justify-between my-1.5">
<div class="text-xs">
{$i18n.t('Allow non-local voices')}
</div>
@@ -325,7 +181,7 @@
</div>
</div>
</div>
{:else if TTSEngine === 'openai'}
{:else if $config.audio.tts.engine === 'openai'}
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
<div class="flex w-full">
@@ -333,7 +189,7 @@
<input
list="voice-list"
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={OpenAISpeaker}
bind:value={voice}
placeholder="Select a voice"
/>
@@ -345,25 +201,6 @@
</div>
</div>
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Model')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
list="model-list"
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={model}
placeholder="Select a model"
/>
<datalist id="model-list">
{#each models as model}
<option value={model.name} />
{/each}
</datalist>
</div>
</div>
</div>
{/if}
</div>
@@ -161,7 +161,7 @@
</div>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div class="flex flex-col">
<input
@@ -218,7 +218,7 @@
</button>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div class="flex flex-col">
{#if showArchiveConfirm}
@@ -203,7 +203,7 @@
</div>
</div>
<hr class=" dark:border-gray-700 my-3" />
<hr class=" dark:border-gray-850 my-3" />
<div>
<div class=" my-2.5 text-sm font-medium">{$i18n.t('System Prompt')}</div>
@@ -228,7 +228,7 @@
{#if showAdvanced}
<AdvancedParams bind:params />
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div class=" py-1 w-full justify-between">
<div class="flex w-full justify-between">
+30 -184
View File
@@ -14,14 +14,11 @@
// Addons
let titleAutoGenerate = true;
let responseAutoCopy = false;
let titleAutoGenerateModel = '';
let titleAutoGenerateModelExternal = '';
let fullScreenMode = false;
let titleGenerationPrompt = '';
let widescreenMode = false;
let splitLargeChunks = false;
// Interface
let promptSuggestions = [];
let defaultModelId = '';
let showUsername = false;
let chatBubble = true;
let chatDirection: 'LTR' | 'RTL' = 'LTR';
@@ -31,9 +28,9 @@
saveSettings({ splitLargeChunks: splitLargeChunks });
};
const toggleFullScreenMode = async () => {
fullScreenMode = !fullScreenMode;
saveSettings({ fullScreenMode: fullScreenMode });
const togglewidescreenMode = async () => {
widescreenMode = !widescreenMode;
saveSettings({ widescreenMode: widescreenMode });
};
const toggleChatBubble = async () => {
@@ -84,39 +81,21 @@
};
const updateInterfaceHandler = async () => {
if ($user.role === 'admin') {
promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions);
await config.set(await getBackendConfig());
}
saveSettings({
title: {
...$settings.title,
model: titleAutoGenerateModel !== '' ? titleAutoGenerateModel : undefined,
modelExternal:
titleAutoGenerateModelExternal !== '' ? titleAutoGenerateModelExternal : undefined,
prompt: titleGenerationPrompt ? titleGenerationPrompt : undefined
}
models: [defaultModelId]
});
};
onMount(async () => {
if ($user.role === 'admin') {
promptSuggestions = $config?.default_prompt_suggestions;
}
titleAutoGenerate = $settings?.title?.auto ?? true;
titleAutoGenerateModel = $settings?.title?.model ?? '';
titleAutoGenerateModelExternal = $settings?.title?.modelExternal ?? '';
titleGenerationPrompt =
$settings?.title?.prompt ??
`Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title': {{prompt}}`;
responseAutoCopy = $settings.responseAutoCopy ?? false;
showUsername = $settings.showUsername ?? false;
chatBubble = $settings.chatBubble ?? true;
fullScreenMode = $settings.fullScreenMode ?? false;
widescreenMode = $settings.widescreenMode ?? false;
splitLargeChunks = $settings.splitLargeChunks ?? false;
chatDirection = $settings.chatDirection ?? 'LTR';
defaultModelId = ($settings?.models ?? ['']).at(0);
});
</script>
@@ -195,16 +174,16 @@
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Full Screen Mode')}</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Widescreen Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
toggleFullScreenMode();
togglewidescreenMode();
}}
type="button"
>
{#if fullScreenMode === true}
{#if widescreenMode === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
@@ -278,161 +257,28 @@
</div>
</div>
<hr class=" dark:border-gray-700" />
<hr class=" dark:border-gray-850" />
<div>
<div class=" mb-2.5 text-sm font-medium flex">
<div class=" mr-1">{$i18n.t('Set Task Model')}</div>
<Tooltip
content={$i18n.t(
'A task model is used when performing tasks such as generating titles for chats and web search queries'
)}
<div class=" space-y-1 mb-3">
<div class="mb-2">
<div class="flex justify-between items-center text-xs">
<div class=" text-xs font-medium">{$i18n.t('Default Model')}</div>
</div>
</div>
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={defaultModelId}
placeholder="Select a model"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
/>
</svg>
</Tooltip>
</div>
<div class="flex w-full gap-2 pr-2">
<div class="flex-1">
<div class=" text-xs mb-1">Local Models</div>
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={titleAutoGenerateModel}
placeholder={$i18n.t('Select a model')}
>
<option value="" selected>{$i18n.t('Current Model')}</option>
{#each $models.filter((m) => m.owned_by === 'ollama') as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">
{model.name}
</option>
{/each}
</select>
</div>
<div class="flex-1">
<div class=" text-xs mb-1">External Models</div>
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={titleAutoGenerateModelExternal}
placeholder={$i18n.t('Select a model')}
>
<option value="" selected>{$i18n.t('Current Model')}</option>
{#each $models as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">
{model.name}
</option>
{/each}
</select>
</div>
</div>
<div class="mt-3 mr-2">
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Title Generation Prompt')}</div>
<textarea
bind:value={titleGenerationPrompt}
class="w-full rounded-lg p-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
rows="3"
/>
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{#each $models.filter((model) => model.id) as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">{model.name}</option>
{/each}
</select>
</div>
</div>
{#if $user.role === 'admin'}
<hr class=" dark:border-gray-700" />
<div class=" space-y-3 pr-1.5">
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">
{$i18n.t('Default Prompt Suggestions')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (promptSuggestions.length === 0 || promptSuggestions.at(-1).content !== '') {
promptSuggestions = [...promptSuggestions, { content: '', title: ['', ''] }];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<div class="flex flex-col space-y-1">
{#each promptSuggestions as prompt, promptIdx}
<div class=" flex border dark:border-gray-600 rounded-lg">
<div class="flex flex-col flex-1">
<div class="flex border-b dark:border-gray-600 w-full">
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
placeholder={$i18n.t('Title (e.g. Tell me a fun fact)')}
bind:value={prompt.title[0]}
/>
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
placeholder={$i18n.t('Subtitle (e.g. about the Roman Empire)')}
bind:value={prompt.title[1]}
/>
</div>
<input
class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
placeholder={$i18n.t('Prompt (e.g. Tell me a fun fact about the Roman Empire)')}
bind:value={prompt.content}
/>
</div>
<button
class="px-2"
type="button"
on:click={() => {
promptSuggestions.splice(promptIdx, 1);
promptSuggestions = promptSuggestions;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div>
{#if promptSuggestions.length > 0}
<div class="text-xs text-left w-full mt-2">
{$i18n.t('Adjusting these settings will apply changes universally to all users.')}
</div>
{/if}
</div>
{/if}
</div>
<div class="flex justify-end text-sm font-medium">
+158 -3
View File
@@ -43,6 +43,13 @@
let modelTransferring = false;
let modelTag = '';
let createModelLoading = false;
let createModelTag = '';
let createModelContent = '';
let createModelDigest = '';
let createModelPullProgress = null;
let digest = '';
let pullProgress = null;
@@ -434,6 +441,83 @@
}
};
const createModelHandler = async () => {
createModelLoading = true;
const res = await createModel(
localStorage.token,
createModelTag,
createModelContent,
selectedOllamaUrlIdx
).catch((error) => {
toast.error(error);
return null;
});
if (res && res.ok) {
const reader = res.body
.pipeThrough(new TextDecoderStream())
.pipeThrough(splitStream('\n'))
.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
try {
let lines = value.split('\n');
for (const line of lines) {
if (line !== '') {
console.log(line);
let data = JSON.parse(line);
console.log(data);
if (data.error) {
throw data.error;
}
if (data.detail) {
throw data.detail;
}
if (data.status) {
if (
!data.digest &&
!data.status.includes('writing') &&
!data.status.includes('sha256')
) {
toast.success(data.status);
} else {
if (data.digest) {
createModelDigest = data.digest;
if (data.completed) {
createModelPullProgress =
Math.round((data.completed / data.total) * 1000) / 10;
} else {
createModelPullProgress = 100;
}
}
}
}
}
}
} catch (error) {
console.log(error);
toast.error(error);
}
}
}
models.set(await getModels());
createModelLoading = false;
createModelTag = '';
createModelContent = '';
createModelDigest = '';
createModelPullProgress = null;
};
onMount(async () => {
const ollamaConfig = await getOllamaConfig(localStorage.token);
@@ -457,13 +541,13 @@
]);
} else {
ollamaEnabled = false;
toast.error('Ollama API is disabled');
toast.error($i18n.t('Ollama API is disabled'));
}
});
</script>
<div class="flex flex-col h-full justify-between text-sm">
<div class=" space-y-3 pr-1.5 overflow-y-scroll h-[24rem]">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[27rem]">
{#if ollamaEnabled}
{#if ollamaVersion !== null}
<div class="space-y-2 pr-1.5">
@@ -695,6 +779,77 @@
</div>
</div>
<div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Create a model')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2 flex flex-col gap-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Enter model tag (e.g. {{modelTag}})', {
modelTag: 'my-modelfile'
})}
bind:value={createModelTag}
disabled={createModelLoading}
/>
<textarea
bind:value={createModelContent}
class="w-full rounded-lg py-2 px-4 text-sm bg-gray-100 dark:text-gray-100 dark:bg-gray-850 outline-none resize-none scrollbar-hidden"
rows="6"
placeholder={`TEMPLATE """{{ .System }}\nUSER: {{ .Prompt }}\nASSISTANT: """\nPARAMETER num_ctx 4096\nPARAMETER stop "</s>"\nPARAMETER stop "USER:"\nPARAMETER stop "ASSISTANT:"`}
disabled={createModelLoading}
/>
</div>
<div class="flex self-start">
<button
class="px-2.5 py-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition disabled:cursor-not-allowed"
on:click={() => {
createModelHandler();
}}
disabled={createModelLoading}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="size-4"
>
<path
d="M7.25 10.25a.75.75 0 0 0 1.5 0V4.56l2.22 2.22a.75.75 0 1 0 1.06-1.06l-3.5-3.5a.75.75 0 0 0-1.06 0l-3.5 3.5a.75.75 0 0 0 1.06 1.06l2.22-2.22v5.69Z"
/>
<path
d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
/>
</svg>
</button>
</div>
</div>
{#if createModelDigest !== ''}
<div class="flex flex-col mt-1">
<div class="font-medium mb-1">{createModelTag}</div>
<div class="">
<div class="flex flex-row justify-between space-x-4 pr-2">
<div class=" flex-1">
<div
class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full"
style="width: {Math.max(15, createModelPullProgress ?? 0)}%"
>
{createModelPullProgress ?? 0}%
</div>
</div>
</div>
{#if createModelDigest}
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
{createModelDigest}
</div>
{/if}
</div>
</div>
{/if}
</div>
<div class="pt-1">
<div class="flex justify-between items-center text-xs">
<div class=" text-sm font-medium">{$i18n.t('Experimental')}</div>
@@ -908,7 +1063,7 @@
</div>
{/if}
{:else if ollamaEnabled === false}
<div>Ollama API is disabled</div>
<div>{$i18n.t('Ollama API is disabled')}</div>
{:else}
<div class="flex h-full justify-center">
<div class="my-auto">
@@ -35,7 +35,9 @@
<div>
<div class="flex items-center justify-between mb-1">
<Tooltip
content="This is an experimental feature, it may not function as expected and is subject to change at any time."
content={$i18n.t(
'This is an experimental feature, it may not function as expected and is subject to change at any time.'
)}
>
<div class="text-sm font-medium">
{$i18n.t('Memory')}
@@ -57,8 +59,9 @@
<div class="text-xs text-gray-600 dark:text-gray-400">
<div>
You can personalize your interactions with LLMs by adding memories through the 'Manage'
button below, making them more helpful and tailored to you.
{$i18n.t(
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you."
)}
</div>
<!-- <div class="mt-3">
@@ -79,7 +82,7 @@
showManageModal = true;
}}
>
Manage
{$i18n.t('Manage')}
</button>
</div>
</div>
@@ -75,7 +75,7 @@
/>
<div class="text-xs text-gray-500">
ⓘ Refer to yourself as "User" (e.g., "User is learning Spanish")
{$i18n.t('Refer to yourself as "User" (e.g., "User is learning Spanish")')}
</div>
</div>
@@ -136,7 +136,7 @@
class=" px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-300 dark:outline-gray-800 rounded-3xl"
on:click={() => {
showAddMemoryModal = true;
}}>Add memory</button
}}>{$i18n.t('Add Memory')}</button
>
<button
class=" px-3.5 py-1.5 font-medium text-red-500 hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-red-300 dark:outline-red-800 rounded-3xl"
@@ -150,7 +150,7 @@
toast.success('Memory cleared successfully');
memories = [];
}
}}>Clear memory</button
}}>{$i18n.t('Clear memory')}</button
>
</div>
</div>
+10 -79
View File
@@ -8,16 +8,14 @@
import Modal from '../common/Modal.svelte';
import Account from './Settings/Account.svelte';
import About from './Settings/About.svelte';
import Models from './Settings/Models.svelte';
import General from './Settings/General.svelte';
import Interface from './Settings/Interface.svelte';
import Audio from './Settings/Audio.svelte';
import Chats from './Settings/Chats.svelte';
import Connections from './Settings/Connections.svelte';
import Images from './Settings/Images.svelte';
import User from '../icons/User.svelte';
import Personalization from './Settings/Personalization.svelte';
import { updateUserSettings } from '$lib/apis/users';
import { goto } from '$app/navigation';
const i18n = getContext('i18n');
@@ -90,55 +88,32 @@
<div class=" self-center">{$i18n.t('General')}</div>
</button>
{#if $user?.role === 'admin'}
{#if $user.role === 'admin'}
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'connections'
'admin'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'connections';
on:click={async () => {
await goto('/admin/settings');
show = false;
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M1 9.5A3.5 3.5 0 0 0 4.5 13H12a3 3 0 0 0 .917-5.857 2.503 2.503 0 0 0-3.198-3.019 3.5 3.5 0 0 0-6.628 2.171A3.5 3.5 0 0 0 1 9.5Z"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Connections')}</div>
</button>
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'models'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'models';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
class="size-4"
>
<path
fill-rule="evenodd"
d="M10 1c3.866 0 7 1.79 7 4s-3.134 4-7 4-7-1.79-7-4 3.134-4 7-4zm5.694 8.13c.464-.264.91-.583 1.306-.952V10c0 2.21-3.134 4-7 4s-7-1.79-7-4V8.178c.396.37.842.688 1.306.953C5.838 10.006 7.854 10.5 10 10.5s4.162-.494 5.694-1.37zM3 13.179V15c0 2.21 3.134 4 7 4s7-1.79 7-4v-1.822c-.396.37-.842.688-1.306.953-1.532.875-3.548 1.369-5.694 1.369s-4.162-.494-5.694-1.37A7.009 7.009 0 013 13.179z"
d="M4.5 3.75a3 3 0 0 0-3 3v10.5a3 3 0 0 0 3 3h15a3 3 0 0 0 3-3V6.75a3 3 0 0 0-3-3h-15Zm4.125 3a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5Zm-3.873 8.703a4.126 4.126 0 0 1 7.746 0 .75.75 0 0 1-.351.92 7.47 7.47 0 0 1-3.522.877 7.47 7.47 0 0 1-3.522-.877.75.75 0 0 1-.351-.92ZM15 8.25a.75.75 0 0 0 0 1.5h3.75a.75.75 0 0 0 0-1.5H15ZM14.25 12a.75.75 0 0 1 .75-.75h3.75a.75.75 0 0 1 0 1.5H15a.75.75 0 0 1-.75-.75Zm.75 2.25a.75.75 0 0 0 0 1.5h3.75a.75.75 0 0 0 0-1.5H15Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Models')}</div>
<div class=" self-center">{$i18n.t('Admin Settings')}</div>
</button>
{/if}
@@ -210,34 +185,6 @@
<div class=" self-center">{$i18n.t('Audio')}</div>
</button>
{#if $user.role === 'admin'}
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'images'
? 'bg-gray-200 dark:bg-gray-700'
: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'images';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4Zm10.5 5.707a.5.5 0 0 0-.146-.353l-1-1a.5.5 0 0 0-.708 0L9.354 9.646a.5.5 0 0 1-.708 0L6.354 7.354a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0-.146.353V12a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5V9.707ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center">{$i18n.t('Images')}</div>
</button>
{/if}
<button
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'chats'
@@ -325,15 +272,6 @@
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'models'}
<Models {getModels} />
{:else if selectedTab === 'connections'}
<Connections
{getModels}
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'interface'}
<Interface
{saveSettings}
@@ -355,13 +293,6 @@
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'images'}
<Images
{saveSettings}
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'chats'}
<Chats {saveSettings} />
{:else if selectedTab === 'account'}
+1 -1
View File
@@ -39,7 +39,7 @@
{#if !dismissed}
{#if mounted}
<div
class=" top-0 left-0 right-0 p-2 mx-4 px-3 flex justify-center items-center relative rounded-xl border border-gray-50 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-40"
class=" top-0 left-0 right-0 p-2 mx-4 px-3 flex justify-center items-center relative rounded-xl border border-gray-50 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-30"
transition:fade={{ delay: 100, duration: 300 }}
>
<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
+1 -1
View File
@@ -48,7 +48,7 @@
<ChevronDown className="absolute end-2 top-1/2 -translate-y-[45%] size-3.5" strokeWidth="2.5" />
</Select.Trigger>
<Select.Content
class="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/50 outline-none"
class="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-850/50 outline-none"
transition={flyAndScale}
sideOffset={4}
>
+4
View File
@@ -21,6 +21,10 @@
touch: touch
});
}
} else if (tooltipInstance && content === '') {
if (tooltipInstance) {
tooltipInstance.destroy();
}
}
onDestroy(() => {
@@ -95,7 +95,7 @@
)}
</div>
<hr class=" dark:border-gray-700 my-3" />
<hr class=" dark:border-gray-850 my-3" />
{/if}
<div>
@@ -68,10 +68,10 @@
<select
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={webConfig.search.engine}
placeholder="Select a engine"
placeholder={$i18n.t('Select a engine')}
required
>
<option disabled selected value="">Select a engine</option>
<option disabled selected value="">{$i18n.t('Select a engine')}</option>
{#each webSearchEngines as engine}
<option value={engine}>{engine}</option>
{/each}
+20
View File
@@ -0,0 +1,20 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '0';
</script>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path
fill-rule="evenodd"
d="M12 5a7 7 0 0 0-7 7v1.17c.313-.11.65-.17 1-.17h2a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H6a3 3 0 0 1-3-3v-6a9 9 0 0 1 18 0v6a3 3 0 0 1-3 3h-2a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h2c.35 0 .687.06 1 .17V12a7 7 0 0 0-7-7Z"
clip-rule="evenodd"
/>
</svg>
+1 -1
View File
@@ -67,7 +67,7 @@
<div class="self-start flex flex-none items-center text-gray-600 dark:text-gray-400">
<!-- <div class="md:hidden flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" /> -->
{#if shareEnabled}
{#if shareEnabled && chat && chat.id}
<Menu
{chat}
{shareEnabled}
@@ -138,7 +138,6 @@
</svg>
<div class="flex items-center">{$i18n.t('Share')}</div>
</DropdownMenu.Item>
<!-- <DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer"
on:click={() => {
@@ -21,17 +21,20 @@
<div class="m-auto pb-10 flex flex-col justify-center">
<div class="max-w-md">
<div class="text-center dark:text-white text-2xl font-medium z-50">
Account Activation Pending<br /> Contact Admin for WebUI Access
{$i18n.t('Account Activation Pending')}<br />
{$i18n.t('Contact Admin for WebUI Access')}
</div>
<div class=" mt-4 text-center text-sm dark:text-gray-200 w-full">
Your account status is currently pending activation.<br /> To access the WebUI, please reach
out to the administrator. Admins can manage user statuses from the Admin Panel.
{$i18n.t('Your account status is currently pending activation.')}<br />
{$i18n.t(
'To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.'
)}
</div>
{#if adminDetails}
<div class="mt-4 text-sm font-medium text-center">
<div>Admin: {adminDetails.name} ({adminDetails.email})</div>
<div>{$i18n.t('Admin')}: {adminDetails.name} ({adminDetails.email})</div>
</div>
{/if}
+4
View File
@@ -325,6 +325,10 @@
on:click={() => {
selectedChatId = null;
chatId.set('');
if ($mobile) {
showSidebar.set(false);
}
}}
draggable="false"
>
@@ -1,12 +1,13 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { createEventDispatcher, getContext } from 'svelte';
import { createEventDispatcher, getContext, onMount } from 'svelte';
import { flyAndScale } from '$lib/utils/transitions';
import { goto } from '$app/navigation';
import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
import { showSettings } from '$lib/stores';
import { showSettings, activeUserCount, USAGE_POOL } from '$lib/stores';
import { fade, slide } from 'svelte/transition';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
@@ -107,7 +108,7 @@
</button>
{/if}
<hr class=" dark:border-gray-800 my-2 p-0" />
<hr class=" dark:border-gray-800 my-1.5 p-0" />
<button
class="flex rounded-md py-2 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition"
@@ -139,6 +140,36 @@
<div class=" self-center font-medium">{$i18n.t('Sign Out')}</div>
</button>
{#if $activeUserCount}
<hr class=" dark:border-gray-800 my-1.5 p-0" />
<Tooltip
content={$USAGE_POOL && $USAGE_POOL.length > 0
? `${$i18n.t('Running')}: ${$USAGE_POOL.join(', ')} ✨`
: ''}
>
<div class="flex rounded-md py-1.5 px-3 text-xs gap-2.5 items-center">
<div class=" flex items-center">
<span class="relative flex size-2">
<span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
/>
<span class="relative inline-flex rounded-full size-2 bg-green-500" />
</span>
</div>
<div class=" ">
<span class=" font-medium">
{$i18n.t('Active Users')}:
</span>
<span class=" font-semibold">
{$activeUserCount}
</span>
</div>
</div>
</Tooltip>
{/if}
<!-- <DropdownMenu.Item class="flex items-center px-3 py-2 text-sm font-medium">
<div class="flex items-center">Profile</div>
</DropdownMenu.Item> -->
+9 -34
View File
@@ -4,7 +4,7 @@
const { saveAs } = fileSaver;
import { onMount, getContext } from 'svelte';
import { WEBUI_NAME, documents } from '$lib/stores';
import { WEBUI_NAME, documents, showSidebar } from '$lib/stores';
import { createNewDoc, deleteDocByName, getDocs } from '$lib/apis/documents';
import { SUPPORTED_FILE_TYPE, SUPPORTED_FILE_EXTENSIONS } from '$lib/constants';
@@ -15,7 +15,6 @@
import EditDocModal from '$lib/components/documents/EditDocModal.svelte';
import AddFilesPlaceholder from '$lib/components/AddFilesPlaceholder.svelte';
import SettingsModal from '$lib/components/documents/SettingsModal.svelte';
import AddDocModal from '$lib/components/documents/AddDocModal.svelte';
const i18n = getContext('i18n');
@@ -158,12 +157,14 @@
{#if dragged}
<div
class="fixed w-full h-full flex z-50 touch-none pointer-events-none"
class="fixed {$showSidebar
? 'left-0 md:left-[260px] md:w-[calc(100%-260px)]'
: 'left-0'} w-full h-full flex z-50 touch-none pointer-events-none"
id="dropzone"
role="region"
aria-label="Drag and Drop Container"
>
<div class="absolute rounded-xl w-full h-full backdrop-blur bg-gray-800/40 flex justify-center">
<div class="absolute w-full h-full backdrop-blur bg-gray-800/40 flex justify-center">
<div class="m-auto pt-64 flex flex-col justify-center">
<div class="max-w-md">
<AddFilesPlaceholder>
@@ -183,39 +184,9 @@
<AddDocModal bind:show={showAddDocModal} />
<SettingsModal bind:show={showSettingsModal} />
<div class="mb-3">
<div class="flex justify-between items-center">
<div class=" text-lg font-semibold self-center">{$i18n.t('Documents')}</div>
<div>
<button
class="flex items-center space-x-1 px-3 py-1.5 rounded-xl bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 transition"
type="button"
on:click={() => {
showSettingsModal = !showSettingsModal;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M6.955 1.45A.5.5 0 0 1 7.452 1h1.096a.5.5 0 0 1 .497.45l.17 1.699c.484.12.94.312 1.356.562l1.321-1.081a.5.5 0 0 1 .67.033l.774.775a.5.5 0 0 1 .034.67l-1.08 1.32c.25.417.44.873.561 1.357l1.699.17a.5.5 0 0 1 .45.497v1.096a.5.5 0 0 1-.45.497l-1.699.17c-.12.484-.312.94-.562 1.356l1.082 1.322a.5.5 0 0 1-.034.67l-.774.774a.5.5 0 0 1-.67.033l-1.322-1.08c-.416.25-.872.44-1.356.561l-.17 1.699a.5.5 0 0 1-.497.45H7.452a.5.5 0 0 1-.497-.45l-.17-1.699a4.973 4.973 0 0 1-1.356-.562L4.108 13.37a.5.5 0 0 1-.67-.033l-.774-.775a.5.5 0 0 1-.034-.67l1.08-1.32a4.971 4.971 0 0 1-.561-1.357l-1.699-.17A.5.5 0 0 1 1 8.548V7.452a.5.5 0 0 1 .45-.497l1.699-.17c.12-.484.312-.94.562-1.356L2.629 4.107a.5.5 0 0 1 .034-.67l.774-.774a.5.5 0 0 1 .67-.033L5.43 3.71a4.97 4.97 0 0 1 1.356-.561l.17-1.699ZM6 8c0 .538.212 1.026.558 1.385l.057.057a2 2 0 0 0 2.828-2.828l-.058-.056A2 2 0 0 0 6 8Z"
clip-rule="evenodd"
/>
</svg>
<div class=" text-xs">{$i18n.t('Document Settings')}</div>
</button>
</div>
</div>
<div class=" text-gray-500 text-xs mt-1">
{$i18n.t("Use '#' in the prompt input to load and select your documents.")}
</div>
</div>
@@ -520,6 +491,10 @@
{/each}
</div>
<div class=" text-gray-500 text-xs mt-1">
{$i18n.t("Use '#' in the prompt input to load and select your documents.")}
</div>
<div class=" flex justify-end w-full mb-2">
<div class="flex space-x-2">
<input
+13 -10
View File
@@ -71,16 +71,19 @@
const url = 'https://openwebui.com';
const tab = await window.open(`${url}/models/create`, '_blank');
window.addEventListener(
'message',
(event) => {
if (event.origin !== url) return;
if (event.data === 'loaded') {
tab.postMessage(JSON.stringify(model), '*');
}
},
false
);
// Define the event handler function
const messageHandler = (event) => {
if (event.origin !== url) return;
if (event.data === 'loaded') {
tab.postMessage(JSON.stringify(model), '*');
// Remove the event listener after handling the message
window.removeEventListener('message', messageHandler);
}
};
window.addEventListener('message', messageHandler, false);
};
const hideModelHandler = async (model) => {
@@ -0,0 +1,106 @@
<script lang="ts">
import { getContext } from 'svelte';
import Selector from './Knowledge/Selector.svelte';
export let knowledge = [];
const i18n = getContext('i18n');
</script>
<div>
<div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Knowledge')}</div>
</div>
<div class=" text-xs dark:text-gray-500">
To add documents here, upload them to the "Documents" workspace first.
</div>
<div class="flex flex-col">
{#if knowledge.length > 0}
<div class=" flex items-center gap-2 mt-2">
{#each knowledge as file, fileIdx}
<div class=" relative group">
<div
class="h-16 w-[15rem] flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none"
>
<div class="p-2.5 bg-red-400 text-white rounded-lg">
{#if (file?.type ?? 'doc') === 'doc'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-6"
>
<path
fill-rule="evenodd"
d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z"
clip-rule="evenodd"
/>
<path
d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z"
/>
</svg>
{:else if file.type === 'collection'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-6"
>
<path
d="M7.5 3.375c0-1.036.84-1.875 1.875-1.875h.375a3.75 3.75 0 0 1 3.75 3.75v1.875C13.5 8.161 14.34 9 15.375 9h1.875A3.75 3.75 0 0 1 21 12.75v3.375C21 17.16 20.16 18 19.125 18h-9.75A1.875 1.875 0 0 1 7.5 16.125V3.375Z"
/>
<path
d="M15 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 17.25 7.5h-1.875A.375.375 0 0 1 15 7.125V5.25ZM4.875 6H6v10.125A3.375 3.375 0 0 0 9.375 19.5H16.5v1.125c0 1.035-.84 1.875-1.875 1.875h-9.75A1.875 1.875 0 0 1 3 20.625V7.875C3 6.839 3.84 6 4.875 6Z"
/>
</svg>
{/if}
</div>
<div class="flex flex-col justify-center -space-y-0.5">
<div class=" dark:text-gray-100 text-sm font-medium line-clamp-1">
{file?.title ?? `#${file.name}`}
</div>
<div class=" text-gray-500 text-sm">{$i18n.t(file?.type ?? 'Document')}</div>
</div>
</div>
<div class=" absolute -top-1 -right-1">
<button
class=" bg-gray-400 text-white border border-white rounded-full group-hover:visible invisible transition"
type="button"
on:click={() => {
knowledge.splice(fileIdx, 1);
knowledge = knowledge;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
</div>
{/each}
</div>
{/if}
<div class="flex flex-wrap text-sm font-medium gap-1.5 mt-2">
<Selector bind:knowledge>
<button
class=" px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-300 dark:outline-gray-800 rounded-3xl"
type="button">Select Documents</button
>
</Selector>
</div>
<!-- {knowledge} -->
</div>
</div>
@@ -0,0 +1,138 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { documents } from '$lib/stores';
import { flyAndScale } from '$lib/utils/transitions';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let onClose: Function = () => {};
export let knowledge = [];
let items = [];
onMount(() => {
let collections = [
...($documents.length > 0
? [
{
name: 'All Documents',
type: 'collection',
title: $i18n.t('All Documents'),
collection_names: $documents.map((doc) => doc.collection_name)
}
]
: []),
...$documents
.reduce((a, e, i, arr) => {
return [...new Set([...a, ...(e?.content?.tags ?? []).map((tag) => tag.name)])];
}, [])
.map((tag) => ({
name: tag,
type: 'collection',
collection_names: $documents
.filter((doc) => (doc?.content?.tags ?? []).map((tag) => tag.name).includes(tag))
.map((doc) => doc.collection_name)
}))
];
items = [...collections, ...$documents];
});
</script>
<Dropdown
on:change={(e) => {
if (e.detail === false) {
onClose();
}
}}
>
<slot />
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[300px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg"
sideOffset={8}
side="bottom"
align="start"
transition={flyAndScale}
>
<div class="max-h-[10rem] overflow-y-scroll">
{#if items.length === 0}
<div class="text-center text-sm text-gray-500 dark:text-gray-400">
{$i18n.t('No documents found')}
</div>
{:else}
{#each items as item}
<DropdownMenu.Item
class="flex gap-2.5 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
on:click={() => {
if (!knowledge.find((k) => k.name === item.name)) {
knowledge = [
...knowledge,
{
...item,
type: item?.type ?? 'doc'
}
];
}
}}
>
<div class="flex self-start">
{#if (item?.type ?? 'doc') === 'doc'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4"
>
<path
fill-rule="evenodd"
d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z"
clip-rule="evenodd"
/>
<path
d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z"
/>
</svg>
{:else if item.type === 'collection'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-4"
>
<path
d="M7.5 3.375c0-1.036.84-1.875 1.875-1.875h.375a3.75 3.75 0 0 1 3.75 3.75v1.875C13.5 8.161 14.34 9 15.375 9h1.875A3.75 3.75 0 0 1 21 12.75v3.375C21 17.16 20.16 18 19.125 18h-9.75A1.875 1.875 0 0 1 7.5 16.125V3.375Z"
/>
<path
d="M15 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 17.25 7.5h-1.875A.375.375 0 0 1 15 7.125V5.25ZM4.875 6H6v10.125A3.375 3.375 0 0 0 9.375 19.5H16.5v1.125c0 1.035-.84 1.875-1.875 1.875h-9.75A1.875 1.875 0 0 1 3 20.625V7.875C3 6.839 3.84 6 4.875 6Z"
/>
</svg>
{/if}
</div>
<div class="flex items-center">
<div class="flex flex-col">
<div
class=" w-fit text-xs font-black px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
>
{item?.type ?? 'Document'}
</div>
<div class="line-clamp-1 font-medium pr-0.5">
{item.name}
</div>
</div>
</div>
</DropdownMenu.Item>
{/each}
{/if}
</div>
</DropdownMenu.Content>
</div>
</Dropdown>
+8 -18
View File
@@ -80,8 +80,6 @@
if (stopResponseFlag) {
controller.abort('User: Stop Response');
}
currentRequestId = null;
break;
}
@@ -97,11 +95,7 @@
let data = JSON.parse(line.replace(/^data: /, ''));
console.log(data);
if ('request_id' in data) {
currentRequestId = data.request_id;
} else {
text += data.choices[0].delta.content ?? '';
}
text += data.choices[0].delta.content ?? '';
}
}
}
@@ -178,21 +172,17 @@
let data = JSON.parse(line.replace(/^data: /, ''));
console.log(data);
if ('request_id' in data) {
currentRequestId = data.request_id;
if (responseMessage.content == '' && data.choices[0].delta.content == '\n') {
continue;
} else {
if (responseMessage.content == '' && data.choices[0].delta.content == '\n') {
continue;
} else {
textareaElement.style.height = textareaElement.scrollHeight + 'px';
textareaElement.style.height = textareaElement.scrollHeight + 'px';
responseMessage.content += data.choices[0].delta.content ?? '';
messages = messages;
responseMessage.content += data.choices[0].delta.content ?? '';
messages = messages;
textareaElement.style.height = textareaElement.scrollHeight + 'px';
textareaElement.style.height = textareaElement.scrollHeight + 'px';
await tick();
}
await tick();
}
}
}
+4 -2
View File
@@ -2,8 +2,9 @@ import { browser, dev } from '$app/environment';
// import { version } from '../../package.json';
export const APP_NAME = 'Open WebUI';
export const WEBUI_BASE_URL = browser ? (dev ? `http://${location.hostname}:8080` : ``) : ``;
export const WEBUI_HOSTNAME = browser ? (dev ? `${location.hostname}:8080` : ``) : '';
export const WEBUI_BASE_URL = browser ? (dev ? `http://${WEBUI_HOSTNAME}` : ``) : ``;
export const WEBUI_API_BASE_URL = `${WEBUI_BASE_URL}/api/v1`;
export const OLLAMA_API_BASE_URL = `${WEBUI_BASE_URL}/ollama`;
@@ -88,7 +89,8 @@ export const SUPPORTED_FILE_EXTENSIONS = [
'xls',
'xlsx',
'pptx',
'ppt'
'ppt',
'msg'
];
// Source: https://kit.svelte.dev/docs/modules#$env-static-public
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "مستخدم",
"About": "عن",
"Account": "الحساب",
"Account Activation Pending": "",
"Accurate information": "معلومات دقيقة",
"Active Users": "",
"Add": "أضف",
"Add a model id": "إضافة معرف نموذج",
"Add a short description about what this model does": "أضف وصفا موجزا حول ما يفعله هذا النموذج",
@@ -28,6 +30,7 @@
"Add User": "اضافة مستخدم",
"Adjusting these settings will apply changes universally to all users.": "سيؤدي ضبط هذه الإعدادات إلى تطبيق التغييرات بشكل عام على كافة المستخدمين",
"admin": "المشرف",
"Admin": "",
"Admin Panel": "لوحة التحكم",
"Admin Settings": "اعدادات المشرف",
"Advanced Parameters": "التعليمات المتقدمة",
@@ -58,7 +61,6 @@
"Audio": "صوتي",
"August": "أغسطس",
"Auto-playback response": "استجابة التشغيل التلقائي",
"Auto-send input after 3 sec.": "إرسال تلقائي للإدخال بعد 3 ثواني.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 الرابط الرئيسي",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 الرابط مطلوب",
"available!": "متاح",
@@ -70,6 +72,9 @@
"Being lazy": "كون كسول",
"Brave Search API Key": "مفتاح واجهة برمجة تطبيقات البحث الشجاع",
"Bypass SSL verification for Websites": "تجاوز التحقق من SSL للموقع",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "اللغاء",
"Capabilities": "قدرات",
"Change Password": "تغير الباسورد",
@@ -87,10 +92,12 @@
"Chunk Params": "Chunk المتغيرات",
"Chunk Size": "Chunk حجم",
"Citation": "اقتباس",
"Clear memory": "",
"Click here for help.": "أضغط هنا للمساعدة",
"Click here to": "أضغط هنا الانتقال",
"Click here to select": "أضغط هنا للاختيار",
"Click here to select a csv file.": "أضغط هنا للاختيار ملف csv",
"Click here to select a py file.": "",
"Click here to select documents.": "انقر هنا لاختيار المستندات",
"click here.": "أضغط هنا",
"Click on the user role button to change a user's role.": "أضغط على أسم الصلاحيات لتغيرها للمستخدم",
@@ -104,17 +111,16 @@
"Concurrent Requests": "الطلبات المتزامنة",
"Confirm Password": "تأكيد كلمة المرور",
"Connections": "اتصالات",
"Contact Admin for WebUI Access": "",
"Content": "الاتصال",
"Context Length": "طول السياق",
"Continue Response": "متابعة الرد",
"Conversation Mode": "وضع المحادثة",
"Copied shared chat URL to clipboard!": "تم نسخ عنوان URL للدردشة المشتركة إلى الحافظة",
"Copy": "نسخ",
"Copy last code block": "انسخ كتلة التعليمات البرمجية الأخيرة",
"Copy last response": "انسخ الرد الأخير",
"Copy Link": "أنسخ الرابط",
"Copying to clipboard was successful!": "تم النسخ إلى الحافظة بنجاح",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "قم بإنشاء عبارة موجزة مكونة من 3-5 كلمات كرأس للاستعلام التالي، مع الالتزام الصارم بالحد الأقصى لعدد الكلمات الذي يتراوح بين 3-5 كلمات وتجنب استخدام الكلمة 'عنوان':",
"Create a model": "إنشاء نموذج",
"Create Account": "إنشاء حساب",
"Create new key": "عمل مفتاح جديد",
@@ -126,12 +132,12 @@
"Custom": "مخصص",
"Customize models for a specific purpose": "تخصيص النماذج لغرض معين",
"Dark": "مظلم",
"Dashboard": "",
"Database": "قاعدة البيانات",
"December": "ديسمبر",
"Default": "الإفتراضي",
"Default (Automatic1111)": "(Automatic1111) الإفتراضي",
"Default (SentenceTransformers)": "(SentenceTransformers) الإفتراضي",
"Default (Web API)": "(Web API) الإفتراضي",
"Default Model": "النموذج الافتراضي",
"Default model updated": "الإفتراضي تحديث الموديل",
"Default Prompt Suggestions": "الإفتراضي Prompt الاقتراحات",
@@ -152,6 +158,7 @@
"Discover a prompt": "اكتشاف موجه",
"Discover, download, and explore custom prompts": "اكتشاف وتنزيل واستكشاف المطالبات المخصصة",
"Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج",
"Dismissible": "",
"Display the username instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة",
"Document": "المستند",
"Document Settings": "أعدادات المستند",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "تصدير وثائق الخرائط",
"Export Models": "نماذج التصدير",
"Export Prompts": "مطالبات التصدير",
"External Models": "",
"Failed to create API Key.": "فشل في إنشاء مفتاح API.",
"Failed to read clipboard contents": "فشل في قراءة محتويات الحافظة",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "اتبعت التعليمات على أكمل وجه",
"Format your variables using square brackets like this:": "قم بتنسيق المتغيرات الخاصة بك باستخدام الأقواس المربعة مثل هذا:",
"Frequency Penalty": "عقوبة التردد",
"Full Screen Mode": "وضع ملء الشاشة",
"General": "عام",
"General Settings": "الاعدادات العامة",
"Generate Image": "",
"Generating search query": "إنشاء استعلام بحث",
"Generation Info": "معلومات الجيل",
"Good Response": "استجابة جيدة",
@@ -252,6 +260,7 @@
"Info": "معلومات",
"Input commands": "إدخال الأوامر",
"Install from Github URL": "التثبيت من عنوان URL لجيثب",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "واجهه المستخدم",
"Invalid Tag": "تاق غير صالحة",
"January": "يناير",
@@ -264,14 +273,17 @@
"JWT Token": "JWT Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "اختصارات لوحة المفاتيح",
"Knowledge": "",
"Language": "اللغة",
"Last Active": "آخر نشاط",
"Light": "فاتح",
"Listening...": "جاري الاستماع",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "يمكن أن تصدر بعض الأخطاء. لذلك يجب التحقق من المعلومات المهمة",
"Local Models": "",
"LTR": "من جهة اليسار إلى اليمين",
"Made by OpenWebUI Community": "OpenWebUI تم إنشاؤه بواسطة مجتمع ",
"Make sure to enclose them with": "تأكد من إرفاقها",
"Manage": "",
"Manage Models": "إدارة النماذج",
"Manage Ollama Models": "Ollama إدارة موديلات ",
"Manage Pipelines": "إدارة خطوط الأنابيب",
@@ -307,6 +319,7 @@
"Name your model": "قم بتسمية النموذج الخاص بك",
"New Chat": "دردشة جديدة",
"New Password": "كلمة المرور الجديدة",
"No documents found": "",
"No results found": "لا توجد نتايج",
"No search query generated": "لم يتم إنشاء استعلام بحث",
"No source available": "لا يوجد مصدر متاح",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "أولاما API",
"Ollama API disabled": "أولاما API معطلة",
"Ollama API is disabled": "",
"Ollama Version": "Ollama الاصدار",
"On": "تشغيل",
"Only": "فقط",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF ملف (.pdf)",
"PDF Extract Images (OCR)": "PDF أستخرج الصور (OCR)",
"pending": "قيد الانتظار",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ",
"Personalization": "التخصيص",
"Pipelines": "خطوط الانابيب",
@@ -367,6 +383,7 @@
"Read Aloud": "أقراء لي",
"Record voice": "سجل صوت",
"Redirecting you to OpenWebUI Community": "OpenWebUI إعادة توجيهك إلى مجتمع ",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "رفض عندما لا ينبغي أن يكون",
"Regenerate": "تجديد",
"Release Notes": "ملاحظات الإصدار",
@@ -378,12 +395,14 @@
"Reranking Model": "إعادة تقييم النموذج",
"Reranking model disabled": "تم تعطيل نموذج إعادة الترتيب",
"Reranking model set to \"{{reranking_model}}\"": "تم ضبط نموذج إعادة الترتيب على \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "إعادة تعيين تخزين المتجهات",
"Response AutoCopy to Clipboard": "النسخ التلقائي للاستجابة إلى الحافظة",
"Role": "منصب",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "من اليمين إلى اليسار",
"Running": "",
"Save": "حفظ",
"Save & Create": "حفظ وإنشاء",
"Save & Update": "حفظ وتحديث",
@@ -397,6 +416,8 @@
"Search Documents": "البحث المستندات",
"Search Models": "نماذج البحث",
"Search Prompts": "أبحث حث",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "عدد نتائج البحث",
"Searched {{count}} sites_zero": "تم البحث في {{count}} sites_zero",
"Searched {{count}} sites_one": "تم البحث في {{count}} sites_one",
@@ -410,12 +431,14 @@
"See what's new": "ما الجديد",
"Seed": "Seed",
"Select a base model": "حدد نموذجا أساسيا",
"Select a engine": "",
"Select a mode": "أختار موديل",
"Select a model": "أختار الموديل",
"Select a pipeline": "حدد مسارا",
"Select a pipeline url": "حدد عنوان URL لخط الأنابيب",
"Select an Ollama instance": "أختار سيرفر ",
"Select model": " أختار موديل",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "النموذج (النماذج) المحددة لا تدعم مدخلات الصور",
"Send": "تم",
"Send a Message": "يُرجى إدخال طلبك هنا",
@@ -428,7 +451,6 @@
"Set Default Model": "تفعيد الموديل الافتراضي",
"Set embedding model (e.g. {{model}})": "ضبط نموذج المتجهات (على سبيل المثال: {{model}})",
"Set Image Size": "حجم الصورة",
"Set Model": "ضبط النموذج",
"Set reranking model (e.g. {{model}})": "ضبط نموذج إعادة الترتيب (على سبيل المثال: {{model}})",
"Set Steps": "ضبط الخطوات",
"Set Task Model": "تعيين نموذج المهمة",
@@ -452,8 +474,8 @@
"Source": "المصدر",
"Speech recognition error: {{error}}": "{{error}} خطأ في التعرف على الكلام",
"Speech-to-Text Engine": "محرك تحويل الكلام إلى نص",
"SpeechRecognition API is not supported in this browser.": "API SpeechRecognition غير مدعومة في هذا المتصفح.",
"Stop Sequence": "وقف التسلسل",
"STT Model": "",
"STT Settings": "STT اعدادات",
"Submit": "إرسال",
"Subtitle (e.g. about the Roman Empire)": "(e.g. about the Roman Empire) الترجمة",
@@ -472,7 +494,9 @@
"Thanks for your feedback!": "شكرا لملاحظاتك!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "يجب أن تكون النتيجة قيمة تتراوح بين 0.0 (0%) و1.0 (100%).",
"Theme": "الثيم",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "وهذا يضمن حفظ محادثاتك القيمة بشكل آمن في قاعدة بياناتك الخلفية. شكرًا لك!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "لا تتم مزامنة هذا الإعداد عبر المتصفحات أو الأجهزة.",
"Thorough explanation": "شرح شامل",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ملاحضة: قم بتحديث عدة فتحات متغيرة على التوالي عن طريق الضغط على مفتاح tab في مدخلات الدردشة بعد كل استبدال.",
@@ -484,6 +508,7 @@
"to": "الى",
"To access the available model names for downloading,": "للوصول إلى أسماء الموديلات المتاحة للتنزيل،",
"To access the GGUF models available for downloading,": "للوصول إلى الموديلات GGUF المتاحة للتنزيل،",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "الى كتابة المحادثه",
"Today": "اليوم",
"Toggle settings": "فتح وأغلاق الاعدادات",
@@ -491,7 +516,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "هل تواجه مشكلة في الوصول",
"TTS Model": "",
"TTS Settings": "TTS اعدادات",
"TTS Voice": "",
"Type": "نوع",
"Type Hugging Face Resolve (Download) URL": "اكتب عنوان URL لحل مشكلة الوجه (تنزيل).",
"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}خطاء أوه! حدثت مشكلة في الاتصال بـ ",
@@ -500,6 +527,7 @@
"Update password": "تحديث كلمة المرور",
"Upload a GGUF model": "GGUF رفع موديل نوع",
"Upload Files": "تحميل الملفات",
"Upload Pipeline": "",
"Upload Progress": "جاري التحميل",
"URL Mode": "رابط الموديل",
"Use '#' in the prompt input to load and select your documents.": "أستخدم '#' في المحادثة لربطهامن المستندات",
@@ -518,6 +546,7 @@
"Warning": "تحذير",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "تحذير: إذا قمت بتحديث أو تغيير نموذج التضمين الخاص بك، فستحتاج إلى إعادة استيراد كافة المستندات.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Web تحميل اعدادات",
"Web Params": "Web تحميل اعدادات",
"Web Search": "بحث الويب",
@@ -528,17 +557,20 @@
"WebUI will make requests to": "سوف يقوم WebUI بتقديم طلبات ل",
"Whats New in": "ما هو الجديد",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "عند إيقاف تشغيل السجل، لن تظهر الدردشات الجديدة على هذا المتصفح في سجلك على أي من أجهزتك.",
"Whisper (Local)": "Whisper (Local)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "مساحة العمل",
"Write a prompt suggestion (e.g. Who are you?)": "اكتب اقتراحًا سريعًا (على سبيل المثال، من أنت؟)",
"Write a summary in 50 words that summarizes [topic or keyword].": "اكتب ملخصًا في 50 كلمة يلخص [الموضوع أو الكلمة الرئيسية]",
"Yesterday": "أمس",
"You": "انت",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "لا يمكنك استنساخ نموذج أساسي",
"You have no archived conversations.": "لا تملك محادثات محفوظه",
"You have shared this chat": "تم مشاركة هذه المحادثة",
"You're a helpful assistant.": "مساعدك المفيد هنا",
"You're now logged in.": "لقد قمت الآن بتسجيل الدخول.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Youtube تحميل اعدادات"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "потребител",
"About": "Относно",
"Account": "Акаунт",
"Account Activation Pending": "",
"Accurate information": "Точни информация",
"Active Users": "",
"Add": "Добавяне",
"Add a model id": "Добавяне на ИД на модел",
"Add a short description about what this model does": "Добавете кратко описание за това какво прави този модел",
@@ -28,6 +30,7 @@
"Add User": "Добавяне на потребител",
"Adjusting these settings will apply changes universally to all users.": "При промяна на тези настройки промените се прилагат за всички потребители.",
"admin": "админ",
"Admin": "",
"Admin Panel": "Панел на Администратор",
"Admin Settings": "Настройки на Администратор",
"Advanced Parameters": "Разширени Параметри",
@@ -58,7 +61,6 @@
"Audio": "Аудио",
"August": "Август",
"Auto-playback response": "Аувтоматично възпроизвеждане на Отговора",
"Auto-send input after 3 sec.": "Аувтоматично изпращане на входа след 3 сек.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Базов URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Базов URL е задължителен.",
"available!": "наличен!",
@@ -70,6 +72,9 @@
"Being lazy": "Да бъдеш мързелив",
"Brave Search API Key": "Смел ключ за API за търсене",
"Bypass SSL verification for Websites": "Изключване на SSL проверката за сайтове",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Отказ",
"Capabilities": "Възможности",
"Change Password": "Промяна на Парола",
@@ -87,10 +92,12 @@
"Chunk Params": "Chunk Params",
"Chunk Size": "Chunk Size",
"Citation": "Цитат",
"Clear memory": "",
"Click here for help.": "Натиснете тук за помощ.",
"Click here to": "Натиснете тук за",
"Click here to select": "Натиснете тук, за да изберете",
"Click here to select a csv file.": "Натиснете тук, за да изберете csv файл.",
"Click here to select a py file.": "",
"Click here to select documents.": "Натиснете тук, за да изберете документи.",
"click here.": "натиснете тук.",
"Click on the user role button to change a user's role.": "Натиснете върху бутона за промяна на ролята на потребителя.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Едновременни искания",
"Confirm Password": "Потвърди Парола",
"Connections": "Връзки",
"Contact Admin for WebUI Access": "",
"Content": "Съдържание",
"Context Length": "Дължина на Контекста",
"Continue Response": "Продължи отговора",
"Conversation Mode": "Режим на Чат",
"Copied shared chat URL to clipboard!": "Копирана е връзката за чат!",
"Copy": "Копирай",
"Copy last code block": "Копиране на последен код блок",
"Copy last response": "Копиране на последен отговор",
"Copy Link": "Копиране на връзка",
"Copying to clipboard was successful!": "Копирането в клипборда беше успешно!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Създайте кратка фраза от 3-5 думи като заглавие за следващото запитване, като стриктно спазвате ограничението от 3-5 думи и избягвате използването на думата 'заглавие':",
"Create a model": "Създаване на модел",
"Create Account": "Създаване на Акаунт",
"Create new key": "Създаване на нов ключ",
@@ -126,12 +132,12 @@
"Custom": "Персонализиран",
"Customize models for a specific purpose": "Персонализиране на модели за конкретна цел",
"Dark": "Тъмен",
"Dashboard": "",
"Database": "База данни",
"December": "Декември",
"Default": "По подразбиране",
"Default (Automatic1111)": "По подразбиране (Automatic1111)",
"Default (SentenceTransformers)": "По подразбиране (SentenceTransformers)",
"Default (Web API)": "По подразбиране (Web API)",
"Default Model": "Модел по подразбиране",
"Default model updated": "Моделът по подразбиране е обновен",
"Default Prompt Suggestions": "Промпт Предложения по подразбиране",
@@ -152,6 +158,7 @@
"Discover a prompt": "Откриване на промпт",
"Discover, download, and explore custom prompts": "Откриване, сваляне и преглед на персонализирани промптове",
"Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели",
"Dismissible": "",
"Display the username instead of You in the Chat": "Показване на потребителското име вместо Вие в чата",
"Document": "Документ",
"Document Settings": "Документ Настройки",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Експортване на документен мапинг",
"Export Models": "Експортиране на модели",
"Export Prompts": "Експортване на промптове",
"External Models": "",
"Failed to create API Key.": "Неуспешно създаване на API ключ.",
"Failed to read clipboard contents": "Грешка при четене на съдържанието от клипборда",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Следвайте инструкциите перфектно",
"Format your variables using square brackets like this:": "Форматирайте вашите променливи, като използвате квадратни скоби, както следва:",
"Frequency Penalty": "Наказание за честота",
"Full Screen Mode": "На Цял екран",
"General": "Основни",
"General Settings": "Основни Настройки",
"Generate Image": "",
"Generating search query": "Генериране на заявка за търсене",
"Generation Info": "Информация за Генерация",
"Good Response": "Добра отговор",
@@ -252,6 +260,7 @@
"Info": "Информация",
"Input commands": "Въведете команди",
"Install from Github URL": "Инсталиране от URL адреса на Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Интерфейс",
"Invalid Tag": "Невалиден тег",
"January": "Януари",
@@ -264,14 +273,17 @@
"JWT Token": "JWT Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "Клавиши за бърз достъп",
"Knowledge": "",
"Language": "Език",
"Last Active": "Последни активни",
"Light": "Светъл",
"Listening...": "Слушам...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLMs могат да правят грешки. Проверете важните данни.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Направено от OpenWebUI общността",
"Make sure to enclose them with": "Уверете се, че са заключени с",
"Manage": "",
"Manage Models": "Управление на Моделите",
"Manage Ollama Models": "Управление на Ollama Моделите",
"Manage Pipelines": "Управление на тръбопроводи",
@@ -307,6 +319,7 @@
"Name your model": "Дайте име на вашия модел",
"New Chat": "Нов чат",
"New Password": "Нова парола",
"No documents found": "",
"No results found": "Няма намерени резултати",
"No search query generated": "Не е генерирана заявка за търсене",
"No source available": "Няма наличен източник",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API деактивиран",
"Ollama API is disabled": "",
"Ollama Version": "Ollama Версия",
"On": "Вкл.",
"Only": "Само",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF документ (.pdf)",
"PDF Extract Images (OCR)": "PDF Extract Images (OCR)",
"pending": "в очакване",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
"Personalization": "Персонализация",
"Pipelines": "Тръбопроводи",
@@ -367,6 +383,7 @@
"Read Aloud": "Прочети на Голос",
"Record voice": "Записване на глас",
"Redirecting you to OpenWebUI Community": "Пренасочване към OpenWebUI общността",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Отказано, когато не трябва да бъде",
"Regenerate": "Регенериране",
"Release Notes": "Бележки по изданието",
@@ -378,12 +395,14 @@
"Reranking Model": "Reranking Model",
"Reranking model disabled": "Reranking model disabled",
"Reranking model set to \"{{reranking_model}}\"": "Reranking model set to \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Ресет Vector Storage",
"Response AutoCopy to Clipboard": "Аувтоматично копиране на отговор в клипборда",
"Role": "Роля",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "Запис",
"Save & Create": "Запис & Създаване",
"Save & Update": "Запис & Актуализиране",
@@ -397,6 +416,8 @@
"Search Documents": "Търси Документи",
"Search Models": "Търсене на модели",
"Search Prompts": "Търси Промптове",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Брой резултати от търсенето",
"Searched {{count}} sites_one": "Търси се в {{count}} sites_one",
"Searched {{count}} sites_other": "Търси се в {{count}} sites_other",
@@ -406,12 +427,14 @@
"See what's new": "Виж какво е новото",
"Seed": "Seed",
"Select a base model": "Изберете базов модел",
"Select a engine": "",
"Select a mode": "Изберете режим",
"Select a model": "Изберете модел",
"Select a pipeline": "Изберете тръбопровод",
"Select a pipeline url": "Избор на URL адрес на канал",
"Select an Ollama instance": "Изберете Ollama инстанция",
"Select model": "Изберете модел",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Избраният(те) модел(и) не поддържа въвеждане на изображения",
"Send": "Изпрати",
"Send a Message": "Изпращане на Съобщение",
@@ -424,7 +447,6 @@
"Set Default Model": "Задай Модел По Подразбиране",
"Set embedding model (e.g. {{model}})": "Задай embedding model (e.g. {{model}})",
"Set Image Size": "Задай Размер на Изображението",
"Set Model": "Задай Модел",
"Set reranking model (e.g. {{model}})": "Задай reranking model (e.g. {{model}})",
"Set Steps": "Задай Стъпки",
"Set Task Model": "Задаване на модел на задача",
@@ -448,8 +470,8 @@
"Source": "Източник",
"Speech recognition error: {{error}}": "Speech recognition error: {{error}}",
"Speech-to-Text Engine": "Speech-to-Text Engine",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition API is not supported in this browser.",
"Stop Sequence": "Stop Sequence",
"STT Model": "",
"STT Settings": "STT Настройки",
"Submit": "Изпращане",
"Subtitle (e.g. about the Roman Empire)": "Подтитул (напр. за Римска империя)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "Благодарим ви за вашия отзив!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "The score should be a value between 0.0 (0%) and 1.0 (100%).",
"Theme": "Тема",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Това гарантира, че ценните ви разговори се запазват сигурно във вашата бекенд база данни. Благодарим ви!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Тази настройка не се синхронизира между браузъри или устройства.",
"Thorough explanation": "Това е подробно описание.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Съвет: Актуализирайте няколко слота за променливи последователно, като натискате клавиша Tab в чат входа след всяка подмяна.",
@@ -480,6 +504,7 @@
"to": "в",
"To access the available model names for downloading,": "За да получите достъп до наличните имена на модели за изтегляне,",
"To access the GGUF models available for downloading,": "За да получите достъп до GGUF моделите, налични за изтегляне,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "към чат входа.",
"Today": "днес",
"Toggle settings": "Toggle settings",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Проблеми с достъпът до Ollama?",
"TTS Model": "",
"TTS Settings": "TTS Настройки",
"TTS Voice": "",
"Type": "Вид",
"Type Hugging Face Resolve (Download) URL": "Въведете Hugging Face Resolve (Download) URL",
"Uh-oh! There was an issue connecting to {{provider}}.": "О, не! Възникна проблем при свързването с {{provider}}.",
@@ -496,6 +523,7 @@
"Update password": "Обновяване на парола",
"Upload a GGUF model": "Качване на GGUF модел",
"Upload Files": "Качване на файлове",
"Upload Pipeline": "",
"Upload Progress": "Прогрес на качването",
"URL Mode": "URL Mode",
"Use '#' in the prompt input to load and select your documents.": "Използвайте '#' във промпта за да заредите и изберете вашите документи.",
@@ -514,6 +542,7 @@
"Warning": "Предупреждение",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Предупреждение: Ако актуализирате или промените вашия модел за вграждане, трябва да повторите импортирането на всички документи.",
"Web": "Уеб",
"Web API": "",
"Web Loader Settings": "Настройки за зареждане на уеб",
"Web Params": "Параметри за уеб",
"Web Search": "Търсене в уеб",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI ще направи заявки към",
"Whats New in": "Какво е новото в",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Когато историята е изключена, нови чатове в този браузър ще не се показват в историята на никои от вашия профил.",
"Whisper (Local)": "Whisper (Локален)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Работно пространство",
"Write a prompt suggestion (e.g. Who are you?)": "Напиши предложение за промпт (напр. Кой сте вие?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Напиши описание в 50 знака, което описва [тема или ключова дума].",
"Yesterday": "вчера",
"You": "вие",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Не можете да клонирате базов модел",
"You have no archived conversations.": "Нямате архивирани разговори.",
"You have shared this chat": "Вие сте споделели този чат",
"You're a helpful assistant.": "Вие сте полезен асистент.",
"You're now logged in.": "Сега, вие влязохте в системата.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Youtube Loader Settings"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "একজন ব্যাবহারকারী",
"About": "সম্পর্কে",
"Account": "একাউন্ট",
"Account Activation Pending": "",
"Accurate information": "সঠিক তথ্য",
"Active Users": "",
"Add": "যোগ করুন",
"Add a model id": "একটি মডেল ID যোগ করুন",
"Add a short description about what this model does": "এই মডেলটি কী করে সে সম্পর্কে একটি সংক্ষিপ্ত বিবরণ যুক্ত করুন",
@@ -28,6 +30,7 @@
"Add User": "ইউজার যোগ করুন",
"Adjusting these settings will apply changes universally to all users.": "এই সেটিংগুলো পরিবর্তন করলে তা সব ইউজারের উপরেই প্রয়োগ করা হবে",
"admin": "এডমিন",
"Admin": "",
"Admin Panel": "এডমিন প্যানেল",
"Admin Settings": "এডমিন সেটিংস",
"Advanced Parameters": "এডভান্সড প্যারামিটার্স",
@@ -58,7 +61,6 @@
"Audio": "অডিও",
"August": "আগস্ট",
"Auto-playback response": "রেসপন্স অটো-প্লেব্যাক",
"Auto-send input after 3 sec.": "৩ সেকেন্ড পর ইনপুট সংয়ক্রিয়ভাবে পাঠান",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 বেজ ইউআরএল",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 বেজ ইউআরএল আবশ্যক",
"available!": "উপলব্ধ!",
@@ -70,6 +72,9 @@
"Being lazy": "অলস হওয়া",
"Brave Search API Key": "সাহসী অনুসন্ধান API কী",
"Bypass SSL verification for Websites": "ওয়েবসাইটের জন্য SSL যাচাই বাতিল করুন",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "বাতিল",
"Capabilities": "সক্ষমতা",
"Change Password": "পাসওয়ার্ড পরিবর্তন করুন",
@@ -87,10 +92,12 @@
"Chunk Params": "চাঙ্ক প্যারামিটার্স",
"Chunk Size": "চাঙ্ক সাইজ",
"Citation": "উদ্ধৃতি",
"Clear memory": "",
"Click here for help.": "সাহায্যের জন্য এখানে ক্লিক করুন",
"Click here to": "এখানে ক্লিক করুন",
"Click here to select": "নির্বাচন করার জন্য এখানে ক্লিক করুন",
"Click here to select a csv file.": "একটি csv ফাইল নির্বাচন করার জন্য এখানে ক্লিক করুন",
"Click here to select a py file.": "",
"Click here to select documents.": "ডকুমেন্টগুলো নির্বাচন করার জন্য এখানে ক্লিক করুন",
"click here.": "এখানে ক্লিক করুন",
"Click on the user role button to change a user's role.": "ইউজারের পদবি পরিবর্তন করার জন্য ইউজারের পদবি বাটনে ক্লিক করুন",
@@ -104,17 +111,16 @@
"Concurrent Requests": "সমকালীন অনুরোধ",
"Confirm Password": "পাসওয়ার্ড নিশ্চিত করুন",
"Connections": "কানেকশনগুলো",
"Contact Admin for WebUI Access": "",
"Content": "বিষয়বস্তু",
"Context Length": "কনটেক্সটের দৈর্ঘ্য",
"Continue Response": "যাচাই করুন",
"Conversation Mode": "কথোপকথন মোড",
"Copied shared chat URL to clipboard!": "শেয়ারকৃত কথা-ব্যবহারের URL ক্লিপবোর্ডে কপি করা হয়েছে!",
"Copy": "অনুলিপি",
"Copy last code block": "সর্বশেষ কোড ব্লক কপি করুন",
"Copy last response": "সর্বশেষ রেসপন্স কপি করুন",
"Copy Link": "লিংক কপি করুন",
"Copying to clipboard was successful!": "ক্লিপবোর্ডে কপি করা সফল হয়েছে",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "'title' শব্দটি ব্যবহার না করে নিম্মোক্ত অনুসন্ধানের জন্য সংক্ষেপে সর্বোচ্চ ৩-৫ শব্দের একটি হেডার তৈরি করুন",
"Create a model": "একটি মডেল তৈরি করুন",
"Create Account": "একাউন্ট তৈরি করুন",
"Create new key": "একটি নতুন কী তৈরি করুন",
@@ -126,12 +132,12 @@
"Custom": "কাস্টম",
"Customize models for a specific purpose": "একটি নির্দিষ্ট উদ্দেশ্যে মডেল কাস্টমাইজ করুন",
"Dark": "ডার্ক",
"Dashboard": "",
"Database": "ডেটাবেজ",
"December": "ডেসেম্বর",
"Default": "ডিফল্ট",
"Default (Automatic1111)": "ডিফল্ট (Automatic1111)",
"Default (SentenceTransformers)": "ডিফল্ট (SentenceTransformers)",
"Default (Web API)": "ডিফল্ট (Web API)",
"Default Model": "ডিফল্ট মডেল",
"Default model updated": "ডিফল্ট মডেল আপডেট হয়েছে",
"Default Prompt Suggestions": "ডিফল্ট প্রম্পট সাজেশন",
@@ -152,6 +158,7 @@
"Discover a prompt": "একটি প্রম্পট খুঁজে বের করুন",
"Discover, download, and explore custom prompts": "কাস্টম প্রম্পটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
"Discover, download, and explore model presets": "মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
"Dismissible": "",
"Display the username instead of You in the Chat": "চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান",
"Document": "ডকুমেন্ট",
"Document Settings": "ডকুমেন্ট সেটিংসমূহ",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "ডকুমেন্টসমূহ ম্যাপিং এক্সপোর্ট করুন",
"Export Models": "রপ্তানি মডেল",
"Export Prompts": "প্রম্পটগুলো একপোর্ট করুন",
"External Models": "",
"Failed to create API Key.": "API Key তৈরি করা যায়নি।",
"Failed to read clipboard contents": "ক্লিপবোর্ডের বিষয়বস্তু পড়া সম্ভব হয়নি",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "নির্দেশাবলী নিখুঁতভাবে অনুসরণ করা হয়েছে",
"Format your variables using square brackets like this:": "আপনার ভেরিয়বলগুলো এভাবে স্কয়ার ব্রাকেটের মাধ্যমে সাজান",
"Frequency Penalty": "ফ্রিকোয়েন্সি পেনাল্টি",
"Full Screen Mode": "ফুলস্ক্রিন মোড",
"General": "সাধারণ",
"General Settings": "সাধারণ সেটিংসমূহ",
"Generate Image": "",
"Generating search query": "অনুসন্ধান ক্যোয়ারী তৈরি করা হচ্ছে",
"Generation Info": "জেনারেশন ইনফো",
"Good Response": "ভালো সাড়া",
@@ -252,6 +260,7 @@
"Info": "তথ্য",
"Input commands": "ইনপুট কমান্ডস",
"Install from Github URL": "Github URL থেকে ইনস্টল করুন",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "ইন্টারফেস",
"Invalid Tag": "অবৈধ ট্যাগ",
"January": "জানুয়ারী",
@@ -264,14 +273,17 @@
"JWT Token": "JWT টোকেন",
"Keep Alive": "সচল রাখুন",
"Keyboard shortcuts": "কিবোর্ড শর্টকাটসমূহ",
"Knowledge": "",
"Language": "ভাষা",
"Last Active": "সর্বশেষ সক্রিয়",
"Light": "লাইট",
"Listening...": "শুনছে...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLM ভুল করতে পারে। গুরুত্বপূর্ণ তথ্য যাচাই করে নিন।",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "OpenWebUI কমিউনিটিকর্তৃক নির্মিত",
"Make sure to enclose them with": "এটা দিয়ে বন্ধনী দিতে ভুলবেন না",
"Manage": "",
"Manage Models": "মডেলসমূহ ব্যবস্থাপনা করুন",
"Manage Ollama Models": "Ollama মডেলসূহ ব্যবস্থাপনা করুন",
"Manage Pipelines": "পাইপলাইন পরিচালনা করুন",
@@ -307,6 +319,7 @@
"Name your model": "আপনার মডেলের নাম দিন",
"New Chat": "নতুন চ্যাট",
"New Password": "নতুন পাসওয়ার্ড",
"No documents found": "",
"No results found": "কোন ফলাফল পাওয়া যায়নি",
"No search query generated": "কোনও অনুসন্ধান ক্যোয়ারী উত্পন্ন হয়নি",
"No source available": "কোন উৎস পাওয়া যায়নি",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API নিষ্ক্রিয় করা হয়েছে",
"Ollama API is disabled": "",
"Ollama Version": "Ollama ভার্সন",
"On": "চালু",
"Only": "শুধুমাত্র",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF ডকুমেন্ট (.pdf)",
"PDF Extract Images (OCR)": "পিডিএফ এর ছবি থেকে লেখা বের করুন (OCR)",
"pending": "অপেক্ষমান",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "মাইক্রোফোন ব্যবহারের অনুমতি পাওয়া যায়নি: {{error}}",
"Personalization": "ডিজিটাল বাংলা",
"Pipelines": "পাইপলাইন",
@@ -367,6 +383,7 @@
"Read Aloud": "পড়াশোনা করুন",
"Record voice": "ভয়েস রেকর্ড করুন",
"Redirecting you to OpenWebUI Community": "আপনাকে OpenWebUI কমিউনিটিতে পাঠানো হচ্ছে",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "যদি উপযুক্ত নয়, তবে রেজিগেনেট করা হচ্ছে",
"Regenerate": "রেজিগেনেট করুন",
"Release Notes": "রিলিজ নোটসমূহ",
@@ -378,12 +395,14 @@
"Reranking Model": "রির্যাক্টিং মডেল",
"Reranking model disabled": "রির্যাক্টিং মডেল নিষ্ক্রিয় করা",
"Reranking model set to \"{{reranking_model}}\"": "রির ্যাঙ্কিং মডেল \"{{reranking_model}}\" -এ সেট করা আছে",
"Reset Upload Directory": "",
"Reset Vector Storage": "ভেক্টর স্টোরেজ রিসেট করুন",
"Response AutoCopy to Clipboard": "রেসপন্সগুলো স্বয়ংক্রিভাবে ক্লিপবোর্ডে কপি হবে",
"Role": "পদবি",
"Rosé Pine": "রোজ পাইন",
"Rosé Pine Dawn": "ভোরের রোজ পাইন",
"RTL": "RTL",
"Running": "",
"Save": "সংরক্ষণ",
"Save & Create": "সংরক্ষণ এবং তৈরি করুন",
"Save & Update": "সংরক্ষণ এবং আপডেট করুন",
@@ -397,6 +416,8 @@
"Search Documents": "ডকুমেন্টসমূহ অনুসন্ধান করুন",
"Search Models": "অনুসন্ধান মডেল",
"Search Prompts": "প্রম্পটসমূহ অনুসন্ধান করুন",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "অনুসন্ধানের ফলাফল গণনা",
"Searched {{count}} sites_one": "{{কাউন্ট}} অনুসন্ধান করা হয়েছে sites_one",
"Searched {{count}} sites_other": "{{কাউন্ট}} অনুসন্ধান করা হয়েছে sites_other",
@@ -406,12 +427,14 @@
"See what's new": "নতুন কী আছে দেখুন",
"Seed": "সীড",
"Select a base model": "একটি বেস মডেল নির্বাচন করুন",
"Select a engine": "",
"Select a mode": "একটি মডেল নির্বাচন করুন",
"Select a model": "একটি মডেল নির্বাচন করুন",
"Select a pipeline": "একটি পাইপলাইন নির্বাচন করুন",
"Select a pipeline url": "একটি পাইপলাইন URL নির্বাচন করুন",
"Select an Ollama instance": "একটি Ollama ইন্সট্যান্স নির্বাচন করুন",
"Select model": "মডেল নির্বাচন করুন",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "নির্বাচিত মডেল(গুলি) চিত্র ইনপুট সমর্থন করে না",
"Send": "পাঠান",
"Send a Message": "একটি মেসেজ পাঠান",
@@ -424,7 +447,6 @@
"Set Default Model": "ডিফল্ট মডেল নির্ধারণ করুন",
"Set embedding model (e.g. {{model}})": "ইমেম্বিং মডেল নির্ধারণ করুন (উদাহরণ {{model}})",
"Set Image Size": "ছবির সাইজ নির্ধারণ করুন",
"Set Model": "মডেল নির্ধারণ করুন",
"Set reranking model (e.g. {{model}})": "রি-র্যাংকিং মডেল নির্ধারণ করুন (উদাহরণ {{model}})",
"Set Steps": "পরবর্তী ধাপসমূহ",
"Set Task Model": "টাস্ক মডেল সেট করুন",
@@ -448,8 +470,8 @@
"Source": "উৎস",
"Speech recognition error: {{error}}": "স্পিচ রিকগনিশনে সমস্যা: {{error}}",
"Speech-to-Text Engine": "স্পিচ-টু-টেক্সট ইঞ্জিন",
"SpeechRecognition API is not supported in this browser.": "এই ব্রাউজার স্পিচরিকগনিশন এপিআই সাপোর্ট করে না।",
"Stop Sequence": "সিকোয়েন্স থামান",
"STT Model": "",
"STT Settings": "STT সেটিংস",
"Submit": "সাবমিট",
"Subtitle (e.g. about the Roman Empire)": "সাবটাইটল (রোমান ইম্পার্টের সম্পর্কে)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "আপনার মতামত ধন্যবাদ!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "স্কোর একটি 0.0 (0%) এবং 1.0 (100%) এর মধ্যে একটি মান হওয়া উচিত।",
"Theme": "থিম",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "এটা নিশ্চিত করে যে, আপনার গুরুত্বপূর্ণ আলোচনা নিরাপদে আপনার ব্যাকএন্ড ডেটাবেজে সংরক্ষিত আছে। ধন্যবাদ!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "এই সেটিং অন্যন্য ব্রাউজার বা ডিভাইসের সাথে সিঙ্ক্রোনাইজ নয় না।",
"Thorough explanation": "পুঙ্খানুপুঙ্খ ব্যাখ্যা",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "পরামর্শ: একাধিক ভেরিয়েবল স্লট একের পর এক রিপ্লেস করার জন্য চ্যাট ইনপুটে কিবোর্ডের Tab বাটন ব্যবহার করুন।",
@@ -480,6 +504,7 @@
"to": "প্রতি",
"To access the available model names for downloading,": "ডাউনলোডের জন্য এভেইলএবল মডেলের নামগুলো এক্সেস করতে,",
"To access the GGUF models available for downloading,": "ডাউলোডের জন্য এভেইলএবল GGUF মডেলগুলো এক্সেস করতে,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "চ্যাট ইনপুটে",
"Today": "আজ",
"Toggle settings": "সেটিংস টোগল",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Ollama এক্সেস করতে সমস্যা হচ্ছে?",
"TTS Model": "",
"TTS Settings": "TTS সেটিংসমূহ",
"TTS Voice": "",
"Type": "টাইপ",
"Type Hugging Face Resolve (Download) URL": "Hugging Face থেকে ডাউনলোড করার ইউআরএল টাইপ করুন",
"Uh-oh! There was an issue connecting to {{provider}}.": "ওহ-হো! {{provider}} এর সাথে কানেকশনে সমস্যা হয়েছে।",
@@ -496,6 +523,7 @@
"Update password": "পাসওয়ার্ড আপডেট করুন",
"Upload a GGUF model": "একটি GGUF মডেল আপলোড করুন",
"Upload Files": "ফাইল আপলোড করুন",
"Upload Pipeline": "",
"Upload Progress": "আপলোড হচ্ছে",
"URL Mode": "ইউআরএল মোড",
"Use '#' in the prompt input to load and select your documents.": "আপনার ডকুমেন্টসমূহ নির্বাচন করার জন্য আপনার প্রম্পট ইনপুটে '# ব্যবহার করুন।",
@@ -514,6 +542,7 @@
"Warning": "সতর্কীকরণ",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "সতর্কীকরণ: আপনি যদি আপনার এম্বেডিং মডেল আপডেট বা পরিবর্তন করেন, তাহলে আপনাকে সমস্ত নথি পুনরায় আমদানি করতে হবে।.",
"Web": "ওয়েব",
"Web API": "",
"Web Loader Settings": "ওয়েব লোডার সেটিংস",
"Web Params": "ওয়েব প্যারামিটারসমূহ",
"Web Search": "ওয়েব অনুসন্ধান",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI যেখানে রিকোয়েস্ট পাঠাবে",
"Whats New in": "এতে নতুন কী",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "যদি হিস্টোরি বন্ধ থাকে তাহলে এই ব্রাউজারের নতুন চ্যাটগুলো আপনার কোন ডিভাইসের হিস্টোরিতেই দেখা যাবে না।",
"Whisper (Local)": "Whisper (লোকাল)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "ওয়ার্কস্পেস",
"Write a prompt suggestion (e.g. Who are you?)": "একটি প্রম্পট সাজেশন লিখুন (যেমন Who are you?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "৫০ শব্দের মধ্যে [topic or keyword] এর একটি সারসংক্ষেপ লিখুন।",
"Yesterday": "আগামী",
"You": "আপনি",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "আপনি একটি বেস মডেল ক্লোন করতে পারবেন না",
"You have no archived conversations.": "আপনার কোনও আর্কাইভ করা কথোপকথন নেই।",
"You have shared this chat": "আপনি এই চ্যাটটি শেয়ার করেছেন",
"You're a helpful assistant.": "আপনি একজন উপকারী এসিস্ট্যান্ট",
"You're now logged in.": "আপনি এখন লগইন করা অবস্থায় আছেন",
"Your account status is currently pending activation.": "",
"Youtube": "YouTube",
"Youtube Loader Settings": "YouTube লোডার সেটিংস"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "un usuari",
"About": "Sobre",
"Account": "Compte",
"Account Activation Pending": "",
"Accurate information": "Informació precisa",
"Active Users": "",
"Add": "Afegir",
"Add a model id": "Afegir un identificador de model",
"Add a short description about what this model does": "Afegiu una breu descripció sobre què fa aquest model",
@@ -28,6 +30,7 @@
"Add User": "Afegir Usuari",
"Adjusting these settings will apply changes universally to all users.": "Ajustar aquests paràmetres aplicarà canvis de manera universal a tots els usuaris.",
"admin": "administrador",
"Admin": "",
"Admin Panel": "Panell d'Administració",
"Admin Settings": "Configuració d'Administració",
"Advanced Parameters": "Paràmetres Avançats",
@@ -58,7 +61,6 @@
"Audio": "Àudio",
"August": "Agost",
"Auto-playback response": "Resposta de reproducció automàtica",
"Auto-send input after 3 sec.": "Enviar entrada automàticament després de 3 segons",
"AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "Es requereix l'URL Base AUTOMATIC1111.",
"available!": "disponible!",
@@ -70,6 +72,9 @@
"Being lazy": "Ser l'estupidez",
"Brave Search API Key": "Clau API Brave Search",
"Bypass SSL verification for Websites": "Desactivar la verificació SSL per a l'accés a l'Internet",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Cancel·la",
"Capabilities": "Capacitats",
"Change Password": "Canvia la Contrasenya",
@@ -87,10 +92,12 @@
"Chunk Params": "Paràmetres de Blocs",
"Chunk Size": "Mida del Bloc",
"Citation": "Citació",
"Clear memory": "",
"Click here for help.": "Fes clic aquí per ajuda.",
"Click here to": "Fes clic aquí per",
"Click here to select": "Fes clic aquí per seleccionar",
"Click here to select a csv file.": "Fes clic aquí per seleccionar un fitxer csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "Fes clic aquí per seleccionar documents.",
"click here.": "fes clic aquí.",
"Click on the user role button to change a user's role.": "Fes clic al botó de rol d'usuari per canviar el rol d'un usuari.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Sol·licituds simultànies",
"Confirm Password": "Confirma la Contrasenya",
"Connections": "Connexions",
"Contact Admin for WebUI Access": "",
"Content": "Contingut",
"Context Length": "Longitud del Context",
"Continue Response": "Continua la Resposta",
"Conversation Mode": "Mode de Conversa",
"Copied shared chat URL to clipboard!": "S'ha copiat l'URL compartida al porta-retalls!",
"Copy": "Copiar",
"Copy last code block": "Copia l'últim bloc de codi",
"Copy last response": "Copia l'última resposta",
"Copy Link": "Copiar l'enllaç",
"Copying to clipboard was successful!": "La còpia al porta-retalls ha estat exitosa!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Crea una frase concisa de 3-5 paraules com a capçalera per a la següent consulta, seguint estrictament el límit de 3-5 paraules i evitant l'ús de la paraula 'títol':",
"Create a model": "Crear un model",
"Create Account": "Crea un Compte",
"Create new key": "Crea una nova clau",
@@ -126,12 +132,12 @@
"Custom": "Personalitzat",
"Customize models for a specific purpose": "Personalitzar models per a un propòsit específic",
"Dark": "Fosc",
"Dashboard": "",
"Database": "Base de Dades",
"December": "Desembre",
"Default": "Per defecte",
"Default (Automatic1111)": "Per defecte (Automatic1111)",
"Default (SentenceTransformers)": "Per defecte (SentenceTransformers)",
"Default (Web API)": "Per defecte (Web API)",
"Default Model": "Model per defecte",
"Default model updated": "Model per defecte actualitzat",
"Default Prompt Suggestions": "Suggeriments de Prompt Per Defecte",
@@ -152,6 +158,7 @@
"Discover a prompt": "Descobreix un prompt",
"Discover, download, and explore custom prompts": "Descobreix, descarrega i explora prompts personalitzats",
"Discover, download, and explore model presets": "Descobreix, descarrega i explora presets de models",
"Dismissible": "",
"Display the username instead of You in the Chat": "Mostra el nom d'usuari en lloc de 'Tu' al Xat",
"Document": "Document",
"Document Settings": "Configuració de Documents",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Exporta el Mapatge de Documents",
"Export Models": "Models d'exportació",
"Export Prompts": "Exporta Prompts",
"External Models": "",
"Failed to create API Key.": "No s'ha pogut crear la clau d'API.",
"Failed to read clipboard contents": "No s'ha pogut llegir el contingut del porta-retalls",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Siguiu les instruccions perfeicte",
"Format your variables using square brackets like this:": "Formata les teves variables utilitzant claudàtors així:",
"Frequency Penalty": "Pena de freqüència",
"Full Screen Mode": "Mode de Pantalla Completa",
"General": "General",
"General Settings": "Configuració General",
"Generate Image": "",
"Generating search query": "Generació de consultes de cerca",
"Generation Info": "Informació de Generació",
"Good Response": "Resposta bona",
@@ -252,6 +260,7 @@
"Info": "Informació",
"Input commands": "Entra ordres",
"Install from Github URL": "Instal·leu des de l'URL de Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interfície",
"Invalid Tag": "Etiqueta Inválida",
"January": "Gener",
@@ -264,14 +273,17 @@
"JWT Token": "Token JWT",
"Keep Alive": "Mantén Actiu",
"Keyboard shortcuts": "Dreceres de Teclat",
"Knowledge": "",
"Language": "Idioma",
"Last Active": "Últim Actiu",
"Light": "Clar",
"Listening...": "Escoltant...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Els LLMs poden cometre errors. Verifica la informació important.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Creat per la Comunitat OpenWebUI",
"Make sure to enclose them with": "Assegura't d'envoltar-los amb",
"Manage": "",
"Manage Models": "Gestiona Models",
"Manage Ollama Models": "Gestiona Models Ollama",
"Manage Pipelines": "Gestionar canonades",
@@ -307,6 +319,7 @@
"Name your model": "Posa un nom al model",
"New Chat": "Xat Nou",
"New Password": "Nova Contrasenya",
"No documents found": "",
"No results found": "No s'han trobat resultats",
"No search query generated": "No es genera cap consulta de cerca",
"No source available": "Sense font disponible",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "API d'Ollama",
"Ollama API disabled": "L'API d'Ollama desactivada",
"Ollama API is disabled": "",
"Ollama Version": "Versió d'Ollama",
"On": "Activat",
"Only": "Només",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "Document PDF (.pdf)",
"PDF Extract Images (OCR)": "Extreu Imatges de PDF (OCR)",
"pending": "pendent",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
"Personalization": "Personalització",
"Pipelines": "Canonades",
@@ -367,6 +383,7 @@
"Read Aloud": "Llegiu al voltant",
"Record voice": "Enregistra veu",
"Redirecting you to OpenWebUI Community": "Redirigint-te a la Comunitat OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Refusat quan no hauria d'haver-ho",
"Regenerate": "Regenerar",
"Release Notes": "Notes de la Versió",
@@ -378,12 +395,14 @@
"Reranking Model": "Model de Reranking desactivat",
"Reranking model disabled": "Model de Reranking desactivat",
"Reranking model set to \"{{reranking_model}}\"": "Model de Reranking establert a \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Reinicia l'Emmagatzematge de Vectors",
"Response AutoCopy to Clipboard": "Resposta AutoCopiar al Portapapers",
"Role": "Rol",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Albada Rosé Pine",
"RTL": "RTL",
"Running": "",
"Save": "Guarda",
"Save & Create": "Guarda i Crea",
"Save & Update": "Guarda i Actualitza",
@@ -397,6 +416,8 @@
"Search Documents": "Cerca Documents",
"Search Models": "Models de cerca",
"Search Prompts": "Cerca Prompts",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Recompte de resultats de cerca",
"Searched {{count}} sites_one": "Cercat {{count}} sites_one",
"Searched {{count}} sites_many": "Cercat {{recompte}} sites_many",
@@ -407,12 +428,14 @@
"See what's new": "Veure novetats",
"Seed": "Llavor",
"Select a base model": "Seleccionar un model base",
"Select a engine": "",
"Select a mode": "Selecciona un mode",
"Select a model": "Selecciona un model",
"Select a pipeline": "Seleccioneu una canonada",
"Select a pipeline url": "Seleccionar un URL de canonada",
"Select an Ollama instance": "Selecciona una instància d'Ollama",
"Select model": "Selecciona un model",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Els models seleccionats no admeten l'entrada d'imatges",
"Send": "Envia",
"Send a Message": "Envia un Missatge",
@@ -425,7 +448,6 @@
"Set Default Model": "Estableix Model Predeterminat",
"Set embedding model (e.g. {{model}})": "Estableix el model d'emboscada (p.ex. {{model}})",
"Set Image Size": "Estableix Mida de la Imatge",
"Set Model": "Estableix Model",
"Set reranking model (e.g. {{model}})": "Estableix el model de reranking (p.ex. {{model}})",
"Set Steps": "Estableix Passos",
"Set Task Model": "Defineix el model de tasca",
@@ -449,8 +471,8 @@
"Source": "Font",
"Speech recognition error: {{error}}": "Error de reconeixement de veu: {{error}}",
"Speech-to-Text Engine": "Motor de Veu a Text",
"SpeechRecognition API is not supported in this browser.": "L'API de Reconèixer Veu no és compatible amb aquest navegador.",
"Stop Sequence": "Atura Seqüència",
"STT Model": "",
"STT Settings": "Configuracions STT",
"Submit": "Envia",
"Subtitle (e.g. about the Roman Empire)": "Subtítol (per exemple, sobre l'Imperi Romà)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "Gràcies pel teu comentari!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "El puntuatge ha de ser un valor entre 0.0 (0%) i 1.0 (100%).",
"Theme": "Tema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Això assegura que les teves converses valuoses queden segurament guardades a la teva base de dades backend. Gràcies!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Aquesta configuració no es sincronitza entre navegadors ni dispositius.",
"Thorough explanation": "Explacació exhaustiva",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza diversos espais de variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.",
@@ -481,6 +505,7 @@
"to": "a",
"To access the available model names for downloading,": "Per accedir als noms dels models disponibles per descarregar,",
"To access the GGUF models available for downloading,": "Per accedir als models GGUF disponibles per descarregar,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "a l'entrada del xat.",
"Today": "Avui",
"Toggle settings": "Commuta configuracions",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemes accedint a Ollama?",
"TTS Model": "",
"TTS Settings": "Configuracions TTS",
"TTS Voice": "",
"Type": "Tipus",
"Type Hugging Face Resolve (Download) URL": "Escriu URL de Resolució (Descàrrega) de Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uf! Hi va haver un problema connectant-se a {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Actualitza contrasenya",
"Upload a GGUF model": "Puja un model GGUF",
"Upload Files": "Pujar fitxers",
"Upload Pipeline": "",
"Upload Progress": "Progrés de Càrrega",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilitza '#' a l'entrada del prompt per carregar i seleccionar els teus documents.",
@@ -515,6 +543,7 @@
"Warning": "Advertiment",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avís: Si actualitzeu o canvieu el model d'incrustació, haureu de tornar a importar tots els documents.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Configuració del carregador web",
"Web Params": "Paràmetres web",
"Web Search": "Cercador web",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI farà peticions a",
"Whats New in": "Què hi ha de Nou en",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quan l'historial està desactivat, els nous xats en aquest navegador no apareixeran en el teu historial en cap dels teus dispositius.",
"Whisper (Local)": "Whisper (Local)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Treball",
"Write a prompt suggestion (e.g. Who are you?)": "Escriu una suggerència de prompt (p. ex. Qui ets tu?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Escriu un resum en 50 paraules que resumeixi [tema o paraula clau].",
"Yesterday": "Ayer",
"You": "Tu",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "No es pot clonar un model base",
"You have no archived conversations.": "No tens converses arxivades.",
"You have shared this chat": "Has compartit aquest xat",
"You're a helpful assistant.": "Ets un assistent útil.",
"You're now logged in.": "Ara estàs connectat.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Configuració del carregador de Youtube"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "usa ka user",
"About": "Mahitungod sa",
"Account": "Account",
"Account Activation Pending": "",
"Accurate information": "",
"Active Users": "",
"Add": "",
"Add a model id": "",
"Add a short description about what this model does": "",
@@ -28,6 +30,7 @@
"Add User": "",
"Adjusting these settings will apply changes universally to all users.": "Ang pag-adjust niini nga mga setting magamit ang mga pagbag-o sa tanan nga tiggamit.",
"admin": "Administrator",
"Admin": "",
"Admin Panel": "Admin Panel",
"Admin Settings": "Mga setting sa administratibo",
"Advanced Parameters": "advanced settings",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "",
"Auto-playback response": "Autoplay nga tubag",
"Auto-send input after 3 sec.": "Awtomatikong ipadala ang entry pagkahuman sa 3 segundos.",
"AUTOMATIC1111 Base URL": "Base URL AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "Ang AUTOMATIC1111 base URL gikinahanglan.",
"available!": "magamit!",
@@ -70,6 +72,9 @@
"Being lazy": "",
"Brave Search API Key": "",
"Bypass SSL verification for Websites": "",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Pagkanselar",
"Capabilities": "",
"Change Password": "Usba ang password",
@@ -87,10 +92,12 @@
"Chunk Params": "Mga Setting sa Block",
"Chunk Size": "Gidak-on sa block",
"Citation": "Mga kinutlo",
"Clear memory": "",
"Click here for help.": "I-klik dinhi alang sa tabang.",
"Click here to": "",
"Click here to select": "I-klik dinhi aron makapili",
"Click here to select a csv file.": "",
"Click here to select a py file.": "",
"Click here to select documents.": "Pag-klik dinhi aron mapili ang mga dokumento.",
"click here.": "I-klik dinhi.",
"Click on the user role button to change a user's role.": "I-klik ang User Role button aron usbon ang role sa user.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "",
"Confirm Password": "Kumpirma ang password",
"Connections": "Mga koneksyon",
"Contact Admin for WebUI Access": "",
"Content": "Kontento",
"Context Length": "Ang gitas-on sa konteksto",
"Continue Response": "",
"Conversation Mode": "Talk mode",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy last code block": "Kopyaha ang katapusang bloke sa code",
"Copy last response": "Kopyaha ang kataposang tubag",
"Copy Link": "",
"Copying to clipboard was successful!": "Ang pagkopya sa clipboard malampuson!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Paghimo og mugbo nga 3-5 ka pulong nga sentence isip usa ka ulohan alang sa mosunod nga pangutana, hugot nga pagsunod sa 3-5 ka pulong nga limitasyon ug paglikay sa paggamit sa pulong nga 'titulo':",
"Create a model": "",
"Create Account": "Paghimo og account",
"Create new key": "",
@@ -126,12 +132,12 @@
"Custom": "Custom",
"Customize models for a specific purpose": "",
"Dark": "Ngitngit",
"Dashboard": "",
"Database": "Database",
"December": "",
"Default": "Pinaagi sa default",
"Default (Automatic1111)": "Default (Awtomatiko1111)",
"Default (SentenceTransformers)": "",
"Default (Web API)": "Default (Web API)",
"Default Model": "",
"Default model updated": "Gi-update nga default template",
"Default Prompt Suggestions": "Default nga prompt nga mga sugyot",
@@ -152,6 +158,7 @@
"Discover a prompt": "Pagkaplag usa ka prompt",
"Discover, download, and explore custom prompts": "Pagdiskubre, pag-download ug pagsuhid sa mga naandan nga pag-aghat",
"Discover, download, and explore model presets": "Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template",
"Dismissible": "",
"Display the username instead of You in the Chat": "Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan",
"Document": "Dokumento",
"Document Settings": "Mga Setting sa Dokumento",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "I-export ang pagmapa sa dokumento",
"Export Models": "",
"Export Prompts": "Export prompts",
"External Models": "",
"Failed to create API Key.": "",
"Failed to read clipboard contents": "Napakyas sa pagbasa sa sulod sa clipboard",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "",
"Format your variables using square brackets like this:": "I-format ang imong mga variable gamit ang square brackets sama niini:",
"Frequency Penalty": "",
"Full Screen Mode": "Full screen mode",
"General": "Heneral",
"General Settings": "kinatibuk-ang mga setting",
"Generate Image": "",
"Generating search query": "",
"Generation Info": "",
"Good Response": "",
@@ -252,6 +260,7 @@
"Info": "",
"Input commands": "Pagsulod sa input commands",
"Install from Github URL": "",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interface",
"Invalid Tag": "",
"January": "",
@@ -264,14 +273,17 @@
"JWT Token": "JWT token",
"Keep Alive": "Padayon nga aktibo",
"Keyboard shortcuts": "Mga shortcut sa keyboard",
"Knowledge": "",
"Language": "Pinulongan",
"Last Active": "",
"Light": "Kahayag",
"Listening...": "Paminaw...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Ang mga LLM mahimong masayop. ",
"Local Models": "",
"LTR": "",
"Made by OpenWebUI Community": "Gihimo sa komunidad sa OpenWebUI",
"Make sure to enclose them with": "Siguruha nga palibutan sila",
"Manage": "",
"Manage Models": "Pagdumala sa mga templates",
"Manage Ollama Models": "Pagdumala sa mga modelo sa Ollama",
"Manage Pipelines": "",
@@ -307,6 +319,7 @@
"Name your model": "",
"New Chat": "Bag-ong diskusyon",
"New Password": "Bag-ong Password",
"No documents found": "",
"No results found": "",
"No search query generated": "",
"No source available": "Walay tinubdan nga anaa",
@@ -323,6 +336,7 @@
"Ollama": "",
"Ollama API": "",
"Ollama API disabled": "",
"Ollama API is disabled": "",
"Ollama Version": "Ollama nga bersyon",
"On": "Gipaandar",
"Only": "Lamang",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "PDF Image Extraction (OCR)",
"pending": "gipugngan",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Gidili ang pagtugot sa dihang nag-access sa mikropono: {{error}}",
"Personalization": "",
"Pipelines": "",
@@ -367,6 +383,7 @@
"Read Aloud": "",
"Record voice": "Irekord ang tingog",
"Redirecting you to OpenWebUI Community": "Gi-redirect ka sa komunidad sa OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "",
"Regenerate": "",
"Release Notes": "Release Notes",
@@ -378,12 +395,14 @@
"Reranking Model": "",
"Reranking model disabled": "",
"Reranking model set to \"{{reranking_model}}\"": "",
"Reset Upload Directory": "",
"Reset Vector Storage": "I-reset ang pagtipig sa vector",
"Response AutoCopy to Clipboard": "Awtomatikong kopya sa tubag sa clipboard",
"Role": "Papel",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Aube Pine Rosé",
"RTL": "",
"Running": "",
"Save": "Tipigi",
"Save & Create": "I-save ug Paghimo",
"Save & Update": "I-save ug I-update",
@@ -397,6 +416,8 @@
"Search Documents": "Pangitaa ang mga dokumento",
"Search Models": "",
"Search Prompts": "Pangitaa ang mga prompt",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "",
"Searched {{count}} sites_one": "",
"Searched {{count}} sites_other": "",
@@ -406,12 +427,14 @@
"See what's new": "Tan-awa unsay bag-o",
"Seed": "Binhi",
"Select a base model": "",
"Select a engine": "",
"Select a mode": "Pagpili og mode",
"Select a model": "Pagpili og modelo",
"Select a pipeline": "",
"Select a pipeline url": "",
"Select an Ollama instance": "Pagpili usa ka pananglitan sa Ollama",
"Select model": "Pagpili og modelo",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "",
"Send": "",
"Send a Message": "Magpadala ug mensahe",
@@ -424,7 +447,6 @@
"Set Default Model": "Ibutang ang default template",
"Set embedding model (e.g. {{model}})": "",
"Set Image Size": "Ibutang ang gidak-on sa hulagway",
"Set Model": "I-configure ang template",
"Set reranking model (e.g. {{model}})": "",
"Set Steps": "Ipasabot ang mga lakang",
"Set Task Model": "",
@@ -448,8 +470,8 @@
"Source": "Tinubdan",
"Speech recognition error: {{error}}": "Sayop sa pag-ila sa tingog: {{error}}",
"Speech-to-Text Engine": "Engine sa pag-ila sa tingog",
"SpeechRecognition API is not supported in this browser.": "Ang SpeechRecognition API wala gisuportahan niini nga browser.",
"Stop Sequence": "Pagkasunod-sunod sa pagsira",
"STT Model": "",
"STT Settings": "Mga setting sa STT",
"Submit": "Isumite",
"Subtitle (e.g. about the Roman Empire)": "",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "",
"Theme": "Tema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Kini nagsiguro nga ang imong bililhon nga mga panag-istoryahanay luwas nga natipig sa imong backend database. ",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Kini nga setting wala mag-sync tali sa mga browser o device.",
"Thorough explanation": "",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Sugyot: Pag-update sa daghang variable nga lokasyon nga sunud-sunod pinaagi sa pagpindot sa tab key sa chat entry pagkahuman sa matag puli.",
@@ -480,6 +504,7 @@
"to": "adunay",
"To access the available model names for downloading,": "Aron ma-access ang mga ngalan sa modelo nga ma-download,",
"To access the GGUF models available for downloading,": "Aron ma-access ang mga modelo sa GGUF nga magamit alang sa pag-download,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "sa entrada sa iring.",
"Today": "",
"Toggle settings": "I-toggle ang mga setting",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Ibabaw nga P",
"Trouble accessing Ollama?": "Adunay mga problema sa pag-access sa Ollama?",
"TTS Model": "",
"TTS Settings": "Mga Setting sa TTS",
"TTS Voice": "",
"Type": "",
"Type Hugging Face Resolve (Download) URL": "Pagsulod sa resolusyon (pag-download) URL Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! {{provider}}.",
@@ -496,6 +523,7 @@
"Update password": "I-update ang password",
"Upload a GGUF model": "Pag-upload ug modelo sa GGUF",
"Upload Files": "",
"Upload Pipeline": "",
"Upload Progress": "Pag-uswag sa Pag-upload",
"URL Mode": "URL mode",
"Use '#' in the prompt input to load and select your documents.": "Gamita ang '#' sa dali nga pagsulod aron makarga ug mapili ang imong mga dokumento.",
@@ -514,6 +542,7 @@
"Warning": "",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "",
"Web Params": "",
"Web Search": "",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "Ang WebUI maghimo mga hangyo sa",
"Whats New in": "Unsay bag-o sa",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Kung ang kasaysayan gipalong, ang mga bag-ong chat sa kini nga browser dili makita sa imong kasaysayan sa bisan unsang mga aparato.",
"Whisper (Local)": "Whisper (Lokal)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "",
"Write a prompt suggestion (e.g. Who are you?)": "Pagsulat og gisugyot nga prompt (eg. Kinsa ka?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Pagsulat og 50 ka pulong nga summary nga nagsumaryo [topic o keyword].",
"Yesterday": "",
"You": "",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "",
"You have no archived conversations.": "",
"You have shared this chat": "",
"You're a helpful assistant.": "Usa ka ka mapuslanon nga katabang",
"You're now logged in.": "Konektado ka na karon.",
"Your account status is currently pending activation.": "",
"Youtube": "",
"Youtube Loader Settings": ""
}
+56 -24
View File
@@ -12,7 +12,9 @@
"a user": "ein Benutzer",
"About": "Über",
"Account": "Account",
"Account Activation Pending": "",
"Accurate information": "Genaue Information",
"Active Users": "Aktive Benutzer",
"Add": "Hinzufügen",
"Add a model id": "Hinzufügen einer Modell-ID",
"Add a short description about what this model does": "Fügen Sie eine kurze Beschreibung hinzu, was dieses Modell tut",
@@ -28,6 +30,7 @@
"Add User": "User hinzufügen",
"Adjusting these settings will apply changes universally to all users.": "Das Anpassen dieser Einstellungen wirkt sich universell auf alle Benutzer aus.",
"admin": "Administrator",
"Admin": "",
"Admin Panel": "Admin Panel",
"Admin Settings": "Admin Einstellungen",
"Advanced Parameters": "Erweiterte Parameter",
@@ -37,7 +40,7 @@
"All Users": "Alle Benutzer",
"Allow": "Erlauben",
"Allow Chat Deletion": "Chat Löschung erlauben",
"Allow non-local voices": "",
"Allow non-local voices": "Nicht-lokale Stimmen erlauben",
"alphanumeric characters and hyphens": "alphanumerische Zeichen und Bindestriche",
"Already have an account?": "Hast du vielleicht schon ein Account?",
"an assistant": "ein Assistent",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "August",
"Auto-playback response": "Automatische Wiedergabe der Antwort",
"Auto-send input after 3 sec.": "Automatisches Senden der Eingabe nach 3 Sek",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Basis URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Basis URL wird benötigt",
"available!": "verfügbar!",
@@ -70,6 +72,9 @@
"Being lazy": "Faul sein",
"Brave Search API Key": "API-Schlüssel für die Brave-Suche",
"Bypass SSL verification for Websites": "Bypass SSL-Verifizierung für Websites",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Abbrechen",
"Capabilities": "Fähigkeiten",
"Change Password": "Passwort ändern",
@@ -87,10 +92,12 @@
"Chunk Params": "Chunk Parameter",
"Chunk Size": "Chunk Size",
"Citation": "Zitate",
"Clear memory": "Memory löschen",
"Click here for help.": "Klicke hier für Hilfe.",
"Click here to": "Klicke hier, um",
"Click here to select": "Klicke hier um auszuwählen",
"Click here to select a csv file.": "Klicke hier um eine CSV-Datei auszuwählen.",
"Click here to select a py file.": "",
"Click here to select documents.": "Klicke hier um Dokumente auszuwählen",
"click here.": "hier klicken.",
"Click on the user role button to change a user's role.": "Klicke auf die Benutzerrollenschaltfläche, um die Rolle eines Benutzers zu ändern.",
@@ -104,18 +111,17 @@
"Concurrent Requests": "Gleichzeitige Anforderungen",
"Confirm Password": "Passwort bestätigen",
"Connections": "Verbindungen",
"Content": "Inhalt",
"Contact Admin for WebUI Access": "",
"Content": "Info",
"Context Length": "Context Length",
"Continue Response": "Antwort fortsetzen",
"Conversation Mode": "Konversationsmodus",
"Copied shared chat URL to clipboard!": "Geteilte Chat-URL in die Zwischenablage kopiert!",
"Copy": "Kopieren",
"Copy last code block": "Letzten Codeblock kopieren",
"Copy last response": "Letzte Antwort kopieren",
"Copy Link": "Link kopieren",
"Copying to clipboard was successful!": "Das Kopieren in die Zwischenablage war erfolgreich!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Erstelle einen prägnanten Satz mit 3-5 Wörtern als Überschrift für die folgende Abfrage. Halte dich dabei strikt an die 3-5-Wort-Grenze und vermeide die Verwendung des Wortes Titel:",
"Create a model": "Erstellen eines Modells",
"Create a model": "Ein Modell erstellen",
"Create Account": "Konto erstellen",
"Create new key": "Neuen Schlüssel erstellen",
"Create new secret key": "Neuen API Schlüssel erstellen",
@@ -126,12 +132,12 @@
"Custom": "Benutzerdefiniert",
"Customize models for a specific purpose": "Modelle für einen bestimmten Zweck anpassen",
"Dark": "Dunkel",
"Dashboard": "",
"Database": "Datenbank",
"December": "Dezember",
"Default": "Standard",
"Default (Automatic1111)": "Standard (Automatic1111)",
"Default (SentenceTransformers)": "Standard (SentenceTransformers)",
"Default (Web API)": "Standard (Web-API)",
"Default Model": "Standardmodell",
"Default model updated": "Standardmodell aktualisiert",
"Default Prompt Suggestions": "Standard-Prompt-Vorschläge",
@@ -152,10 +158,11 @@
"Discover a prompt": "Einen Prompt entdecken",
"Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden",
"Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden",
"Dismissible": "ausblendbar",
"Display the username instead of You in the Chat": "Den Benutzernamen anstelle von 'du' im Chat anzeigen",
"Document": "Dokument",
"Document Settings": "Dokumenteinstellungen",
"Documentation": "",
"Documentation": "Dokumentation",
"Documents": "Dokumente",
"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Deine Daten bleiben sicher auf Deinen lokal gehosteten Server.",
"Don't Allow": "Nicht erlauben",
@@ -170,7 +177,7 @@
"Edit Doc": "Dokument bearbeiten",
"Edit User": "Benutzer bearbeiten",
"Email": "E-Mail",
"Embedding Batch Size": "",
"Embedding Batch Size": "Embedding Batch Größe",
"Embedding Model": "Embedding-Modell",
"Embedding Model Engine": "Embedding-Modell-Engine",
"Embedding model set to \"{{embedding_model}}\"": "Embedding-Modell auf \"{{embedding_model}}\" gesetzt",
@@ -199,35 +206,36 @@
"Enter Top K": "Gib Top K ein",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Gib die URL ein (z.B. http://127.0.0.1:7860/)",
"Enter URL (e.g. http://localhost:11434)": "Gib die URL ein (z.B. http://localhost:11434)",
"Enter Your Email": "Gib deine E-Mail-Adresse ein",
"Enter Your Full Name": "Gib deinen vollständigen Namen ein",
"Enter Your Password": "Gib dein Passwort ein",
"Enter Your Email": "E-Mail-Adresse",
"Enter Your Full Name": "Name",
"Enter Your Password": "Passwort",
"Enter Your Role": "Gebe deine Rolle ein",
"Error": "Fehler",
"Experimental": "Experimentell",
"Export": "Exportieren",
"Export All Chats (All Users)": "Alle Chats exportieren (alle Benutzer)",
"Export chat (.json)": "",
"Export chat (.json)": "Chat exportieren (.json)",
"Export Chats": "Chats exportieren",
"Export Documents Mapping": "Dokumentenmapping exportieren",
"Export Models": "Modelle exportieren",
"Export Prompts": "Prompts exportieren",
"External Models": "",
"Failed to create API Key.": "API Key erstellen fehlgeschlagen",
"Failed to read clipboard contents": "Fehler beim Lesen des Zwischenablageninhalts",
"Failed to update settings": "",
"Failed to update settings": "Fehler beim Aktualisieren der Einstellungen",
"February": "Februar",
"Feel free to add specific details": "Ergänze Details.",
"File Mode": "File Modus",
"File not found.": "Datei nicht gefunden.",
"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint spoofing erkannt: Initialen können nicht als Avatar verwendet werden. Es wird auf das Standardprofilbild zurückgegriffen.",
"Fluidly stream large external response chunks": "Streamen Sie große externe Antwortblöcke flüssig",
"Fluidly stream large external response chunks": "Große externe Antwortblöcke flüssig streamen",
"Focus chat input": "Chat-Eingabe fokussieren",
"Followed instructions perfectly": "Anweisungen perfekt befolgt",
"Format your variables using square brackets like this:": "Formatiere deine Variablen mit eckigen Klammern wie folgt:",
"Frequency Penalty": "Frequenz-Strafe",
"Full Screen Mode": "Vollbildmodus",
"General": "Allgemein",
"General Settings": "Allgemeine Einstellungen",
"Generate Image": "",
"Generating search query": "Suchanfrage generieren",
"Generation Info": "Generierungsinformationen",
"Good Response": "Gute Antwort",
@@ -252,6 +260,7 @@
"Info": "Info",
"Input commands": "Eingabebefehle",
"Install from Github URL": "Installieren Sie von der Github-URL",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Benutzeroberfläche",
"Invalid Tag": "Ungültiger Tag",
"January": "Januar",
@@ -264,14 +273,17 @@
"JWT Token": "JWT-Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "Tastenkürzel",
"Knowledge": "",
"Language": "Sprache",
"Last Active": "Zuletzt aktiv",
"Light": "Hell",
"Listening...": "Hören...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLMs können Fehler machen. Überprüfe wichtige Informationen.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Von der OpenWebUI-Community",
"Make sure to enclose them with": "Formatiere deine Variablen mit:",
"Manage": "Verwalten",
"Manage Models": "Modelle verwalten",
"Manage Ollama Models": "Ollama-Modelle verwalten",
"Manage Pipelines": "Verwalten von Pipelines",
@@ -307,6 +319,7 @@
"Name your model": "Benennen Sie Ihr Modell",
"New Chat": "Neuer Chat",
"New Password": "Neues Passwort",
"No documents found": "",
"No results found": "Keine Ergebnisse gefunden",
"No search query generated": "Keine Suchanfrage generiert",
"No source available": "Keine Quelle verfügbar.",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama-API",
"Ollama API disabled": "Ollama-API deaktiviert",
"Ollama API is disabled": "",
"Ollama Version": "Ollama-Version",
"On": "Ein",
"Only": "Nur",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF-Dokument (.pdf)",
"PDF Extract Images (OCR)": "Text von Bildern aus PDFs extrahieren (OCR)",
"pending": "ausstehend",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Zugriff auf das Mikrofon verweigert: {{error}}",
"Personalization": "Personalisierung",
"Pipelines": "Pipelines",
@@ -362,11 +378,12 @@
"Prompts": "Prompts",
"Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" von Ollama.com herunterladen",
"Pull a model from Ollama.com": "Ein Modell von Ollama.com abrufen",
"Query Params": "Query Parameter",
"RAG Template": "RAG-Vorlage",
"Query Params": "Abfrage Parameter",
"RAG Template": "RAG-Template",
"Read Aloud": "Vorlesen",
"Record voice": "Stimme aufnehmen",
"Redirecting you to OpenWebUI Community": "Du wirst zur OpenWebUI-Community weitergeleitet",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Abgelehnt, obwohl es nicht hätte sein sollen.",
"Regenerate": "Neu generieren",
"Release Notes": "Versionshinweise",
@@ -378,12 +395,14 @@
"Reranking Model": "Reranking Modell",
"Reranking model disabled": "Rranking Modell deaktiviert",
"Reranking model set to \"{{reranking_model}}\"": "Reranking Modell auf \"{{reranking_model}}\" gesetzt",
"Reset Upload Directory": "Uploadverzeichnis löschen",
"Reset Vector Storage": "Vektorspeicher zurücksetzen",
"Response AutoCopy to Clipboard": "Antwort automatisch in die Zwischenablage kopieren",
"Role": "Rolle",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "Läuft",
"Save": "Speichern",
"Save & Create": "Speichern und erstellen",
"Save & Update": "Speichern und aktualisieren",
@@ -397,6 +416,8 @@
"Search Documents": "Dokumente suchen",
"Search Models": "Modelle suchen",
"Search Prompts": "Prompts suchen",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Anzahl der Suchergebnisse",
"Searched {{count}} sites_one": "Gesucht {{count}} sites_one",
"Searched {{count}} sites_other": "Gesucht {{count}} sites_other",
@@ -406,12 +427,14 @@
"See what's new": "Was gibt's Neues",
"Seed": "Seed",
"Select a base model": "Wählen Sie ein Basismodell",
"Select a engine": "Wähle eine Engine",
"Select a mode": "Einen Modus auswählen",
"Select a model": "Ein Modell auswählen",
"Select a pipeline": "Wählen Sie eine Pipeline aus",
"Select a pipeline url": "Auswählen einer Pipeline-URL",
"Select an Ollama instance": "Eine Ollama Instanz auswählen",
"Select model": "Modell auswählen",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Ausgewählte Modelle unterstützen keine Bildeingaben",
"Send": "Senden",
"Send a Message": "Eine Nachricht senden",
@@ -424,20 +447,19 @@
"Set Default Model": "Standardmodell festlegen",
"Set embedding model (e.g. {{model}})": "Eingabemodell festlegen (z.B. {{model}})",
"Set Image Size": "Bildgröße festlegen",
"Set Model": "Modell festlegen",
"Set reranking model (e.g. {{model}})": "Rerankingmodell festlegen (z.B. {{model}})",
"Set Steps": "Schritte festlegen",
"Set Task Model": "Aufgabenmodell festlegen",
"Set Voice": "Stimme festlegen",
"Settings": "Einstellungen",
"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
"Settings updated successfully": "",
"Settings updated successfully": "Settings updated successfully",
"Share": "Teilen",
"Share Chat": "Chat teilen",
"Share to OpenWebUI Community": "Mit OpenWebUI Community teilen",
"short-summary": "kurze-zusammenfassung",
"Show": "Anzeigen",
"Show Admin Details in Account Pending Overlay": "",
"Show Admin Details in Account Pending Overlay": "Admin-Details im Account-Pending-Overlay anzeigen",
"Show shortcuts": "Verknüpfungen anzeigen",
"Showcased creativity": "Kreativität zur Schau gestellt",
"sidebar": "Seitenleiste",
@@ -448,8 +470,8 @@
"Source": "Quellen",
"Speech recognition error: {{error}}": "Spracherkennungsfehler: {{error}}",
"Speech-to-Text Engine": "Sprache-zu-Text-Engine",
"SpeechRecognition API is not supported in this browser.": "Die Spracherkennungs-API wird in diesem Browser nicht unterstützt.",
"Stop Sequence": "Stop Sequence",
"STT Model": "",
"STT Settings": "STT-Einstellungen",
"Submit": "Senden",
"Subtitle (e.g. about the Roman Empire)": "Untertitel (z.B. über das Römische Reich)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "Danke für dein Feedback",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Der Score sollte ein Wert zwischen 0,0 (0 %) und 1,0 (100 %) sein.",
"Theme": "Design",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dadurch werden deine wertvollen Unterhaltungen sicher in der Backend-Datenbank gespeichert. Vielen Dank!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Diese Einstellung wird nicht zwischen Browsern oder Geräten synchronisiert.",
"Thorough explanation": "Genaue Erklärung",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tipp: Aktualisiere mehrere Variablen nacheinander, indem du nach jeder Aktualisierung die Tabulatortaste im Chat-Eingabefeld drückst.",
@@ -480,6 +504,7 @@
"to": "für",
"To access the available model names for downloading,": "Um auf die verfügbaren Modellnamen zum Herunterladen zuzugreifen,",
"To access the GGUF models available for downloading,": "Um auf die verfügbaren GGUF Modelle zum Herunterladen zuzugreifen",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "to chat input.",
"Today": "Heute",
"Toggle settings": "Einstellungen umschalten",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Probleme beim Zugriff auf Ollama?",
"TTS Model": "",
"TTS Settings": "TTS-Einstellungen",
"TTS Voice": "",
"Type": "Art",
"Type Hugging Face Resolve (Download) URL": "Gib die Hugging Face Resolve (Download) URL ein",
"Uh-oh! There was an issue connecting to {{provider}}.": "Ups! Es gab ein Problem bei der Verbindung mit {{provider}}.",
@@ -496,6 +523,7 @@
"Update password": "Passwort aktualisieren",
"Upload a GGUF model": "GGUF Model hochladen",
"Upload Files": "Dateien hochladen",
"Upload Pipeline": "",
"Upload Progress": "Upload Progress",
"URL Mode": "URL Modus",
"Use '#' in the prompt input to load and select your documents.": "Verwende '#' in der Prompt-Eingabe, um deine Dokumente zu laden und auszuwählen.",
@@ -514,6 +542,7 @@
"Warning": "Warnung",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warnung: Wenn du dein Einbettungsmodell aktualisierst oder änderst, musst du alle Dokumente erneut importieren.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Web Loader Einstellungen",
"Web Params": "Web Parameter",
"Web Search": "Websuche",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "Wenn aktiviert sendet WebUI externe Anfragen an",
"Whats New in": "Was gibt's Neues in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Wenn die Historie ausgeschaltet ist, werden neue Chats nicht in deiner Historie auf deine Geräte angezeigt.",
"Whisper (Local)": "Whisper (Lokal)",
"Whisper (Local)": "",
"Widescreen Mode": "Widescreen Modus",
"Workspace": "Arbeitsbereich",
"Write a prompt suggestion (e.g. Who are you?)": "Gebe einen Prompt-Vorschlag ein (z.B. Wer bist du?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Schreibe eine kurze Zusammenfassung in 50 Wörtern, die [Thema oder Schlüsselwort] zusammenfasst.",
"Yesterday": "Gestern",
"You": "Du",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Du kannst deine Interaktionen mit LLMs personalisieren, indem du Erinnerungen durch den 'Verwalten'-Button unten hinzufügst, um sie hilfreicher und auf dich zugeschnitten zu machen.",
"You cannot clone a base model": "Sie können ein Basismodell nicht klonen",
"You have no archived conversations.": "Du hast keine archivierten Unterhaltungen.",
"You have shared this chat": "Du hast diesen Chat",
"You're a helpful assistant.": "Du bist ein hilfreicher Assistent.",
"You're now logged in.": "Du bist nun eingeloggt.",
"Your account status is currently pending activation.": "",
"Youtube": "YouTube",
"Youtube Loader Settings": "YouTube-Ladeeinstellungen"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "such user",
"About": "Much About",
"Account": "Account",
"Account Activation Pending": "",
"Accurate information": "",
"Active Users": "",
"Add": "",
"Add a model id": "",
"Add a short description about what this model does": "",
@@ -28,6 +30,7 @@
"Add User": "",
"Adjusting these settings will apply changes universally to all users.": "Adjusting these settings will apply changes to all users. Such universal, very wow.",
"admin": "admin",
"Admin": "",
"Admin Panel": "Admin Panel",
"Admin Settings": "Admin Settings",
"Advanced Parameters": "Advanced Parameters",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "",
"Auto-playback response": "Auto-playback response",
"Auto-send input after 3 sec.": "Auto-send after 3 sec.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Base URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Base URL is required.",
"available!": "available! So excite!",
@@ -70,6 +72,9 @@
"Being lazy": "",
"Brave Search API Key": "",
"Bypass SSL verification for Websites": "",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Cancel",
"Capabilities": "",
"Change Password": "Change Password",
@@ -87,10 +92,12 @@
"Chunk Params": "Chunk Params",
"Chunk Size": "Chunk Size",
"Citation": "",
"Clear memory": "",
"Click here for help.": "Click for help. Much assist.",
"Click here to": "",
"Click here to select": "Click to select",
"Click here to select a csv file.": "",
"Click here to select a py file.": "",
"Click here to select documents.": "Click to select documents",
"click here.": "click here. Such click.",
"Click on the user role button to change a user's role.": "Click user role button to change role.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "",
"Confirm Password": "Confirm Password",
"Connections": "Connections",
"Contact Admin for WebUI Access": "",
"Content": "Content",
"Context Length": "Context Length",
"Continue Response": "",
"Conversation Mode": "Conversation Mode",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy last code block": "Copy last code block",
"Copy last response": "Copy last response",
"Copy Link": "",
"Copying to clipboard was successful!": "Copying to clipboard was success! Very success!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Create short phrase, 3-5 word, as header for query, much strict, avoid 'title':",
"Create a model": "",
"Create Account": "Create Account",
"Create new key": "",
@@ -126,12 +132,12 @@
"Custom": "Custom",
"Customize models for a specific purpose": "",
"Dark": "Dark",
"Dashboard": "",
"Database": "Database",
"December": "",
"Default": "Default",
"Default (Automatic1111)": "Default (Automatic1111)",
"Default (SentenceTransformers)": "",
"Default (Web API)": "Default (Web API)",
"Default Model": "",
"Default model updated": "Default model much updated",
"Default Prompt Suggestions": "Default Prompt Suggestions",
@@ -152,6 +158,7 @@
"Discover a prompt": "Discover a prompt",
"Discover, download, and explore custom prompts": "Discover, download, and explore custom prompts",
"Discover, download, and explore model presets": "Discover, download, and explore model presets",
"Dismissible": "",
"Display the username instead of You in the Chat": "Display username instead of You in Chat",
"Document": "Document",
"Document Settings": "Document Settings",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Export Mappings of Dogos",
"Export Models": "",
"Export Prompts": "Export Promptos",
"External Models": "",
"Failed to create API Key.": "",
"Failed to read clipboard contents": "Failed to read clipboard borks",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "",
"Format your variables using square brackets like this:": "Format variables using square brackets like wow:",
"Frequency Penalty": "",
"Full Screen Mode": "Much Full Bark Mode",
"General": "Woweral",
"General Settings": "General Doge Settings",
"Generate Image": "",
"Generating search query": "",
"Generation Info": "",
"Good Response": "",
@@ -252,6 +260,7 @@
"Info": "",
"Input commands": "Input commands",
"Install from Github URL": "",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interface",
"Invalid Tag": "",
"January": "",
@@ -264,14 +273,17 @@
"JWT Token": "JWT Borken",
"Keep Alive": "Keep Wow",
"Keyboard shortcuts": "Keyboard Barkcuts",
"Knowledge": "",
"Language": "Doge Speak",
"Last Active": "",
"Light": "Light",
"Listening...": "Listening...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLMs can make borks. Verify important info.",
"Local Models": "",
"LTR": "",
"Made by OpenWebUI Community": "Made by OpenWebUI Community",
"Make sure to enclose them with": "Make sure to enclose them with",
"Manage": "",
"Manage Models": "Manage Wowdels",
"Manage Ollama Models": "Manage Ollama Wowdels",
"Manage Pipelines": "",
@@ -307,6 +319,7 @@
"Name your model": "",
"New Chat": "New Bark",
"New Password": "New Barkword",
"No documents found": "",
"No results found": "",
"No search query generated": "",
"No source available": "No source available",
@@ -323,6 +336,7 @@
"Ollama": "",
"Ollama API": "",
"Ollama API disabled": "",
"Ollama API is disabled": "",
"Ollama Version": "Ollama Version",
"On": "On",
"Only": "Only",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "PDF Extract Wowmages (OCR)",
"pending": "pending",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
"Personalization": "Personalization",
"Pipelines": "",
@@ -367,6 +383,7 @@
"Read Aloud": "",
"Record voice": "Record Bark",
"Redirecting you to OpenWebUI Community": "Redirecting you to OpenWebUI Community",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "",
"Regenerate": "",
"Release Notes": "Release Borks",
@@ -378,12 +395,14 @@
"Reranking Model": "",
"Reranking model disabled": "",
"Reranking model set to \"{{reranking_model}}\"": "",
"Reset Upload Directory": "",
"Reset Vector Storage": "Reset Vector Storage",
"Response AutoCopy to Clipboard": "Copy Bark Auto Bark",
"Role": "Role",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "",
"Running": "",
"Save": "Save much wow",
"Save & Create": "Save & Create much create",
"Save & Update": "Save & Update much update",
@@ -397,6 +416,8 @@
"Search Documents": "Search Documents much find",
"Search Models": "",
"Search Prompts": "Search Prompts much wow",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "",
"Searched {{count}} sites_one": "",
"Searched {{count}} sites_other": "",
@@ -406,12 +427,14 @@
"See what's new": "See what's new so amaze",
"Seed": "Seed very plant",
"Select a base model": "",
"Select a engine": "",
"Select a mode": "Select a mode very choose",
"Select a model": "Select a model much choice",
"Select a pipeline": "",
"Select a pipeline url": "",
"Select an Ollama instance": "Select an Ollama instance very choose",
"Select model": "Select model much choice",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "",
"Send": "",
"Send a Message": "Send a Message much message",
@@ -424,7 +447,6 @@
"Set Default Model": "Set Default Model much model",
"Set embedding model (e.g. {{model}})": "",
"Set Image Size": "Set Image Size very size",
"Set Model": "Set Model so speak",
"Set reranking model (e.g. {{model}})": "",
"Set Steps": "Set Steps so many steps",
"Set Task Model": "",
@@ -448,8 +470,8 @@
"Source": "Source",
"Speech recognition error: {{error}}": "Speech recognition error: {{error}} so error",
"Speech-to-Text Engine": "Speech-to-Text Engine much speak",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition API is not supported in this browser. Much sad.",
"Stop Sequence": "Stop Sequence much stop",
"STT Model": "",
"STT Settings": "STT Settings very settings",
"Submit": "Submit much submit",
"Subtitle (e.g. about the Roman Empire)": "",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "",
"Theme": "Theme much theme",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "This ensures that your valuable conversations are securely saved to your backend database. Thank you! Much secure!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "This setting does not sync across browsers or devices. Very not sync.",
"Thorough explanation": "",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement. Much tip!",
@@ -480,6 +504,7 @@
"to": "to very to",
"To access the available model names for downloading,": "To access the available model names for downloading, much access",
"To access the GGUF models available for downloading,": "To access the GGUF models available for downloading, much access",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "to chat input. Very chat.",
"Today": "",
"Toggle settings": "Toggle settings much toggle",
@@ -487,7 +512,9 @@
"Top K": "Top K very top",
"Top P": "Top P very top",
"Trouble accessing Ollama?": "Trouble accessing Ollama? Much trouble?",
"TTS Model": "",
"TTS Settings": "TTS Settings much settings",
"TTS Voice": "",
"Type": "",
"Type Hugging Face Resolve (Download) URL": "Type Hugging Face Resolve (Download) URL much download",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! There was an issue connecting to {{provider}}. Much uh-oh!",
@@ -496,6 +523,7 @@
"Update password": "Update password much change",
"Upload a GGUF model": "Upload a GGUF model very upload",
"Upload Files": "",
"Upload Pipeline": "",
"Upload Progress": "Upload Progress much progress",
"URL Mode": "URL Mode much mode",
"Use '#' in the prompt input to load and select your documents.": "Use '#' in the prompt input to load and select your documents. Much use.",
@@ -514,6 +542,7 @@
"Warning": "",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
"Web": "Web very web",
"Web API": "",
"Web Loader Settings": "",
"Web Params": "",
"Web Search": "",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI will make requests to much request",
"Whats New in": "Whats New in much new",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "When history is turned off, new chats on this browser won't appear in your history on any of your devices. Much history.",
"Whisper (Local)": "Whisper (Local) much whisper",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "",
"Write a prompt suggestion (e.g. Who are you?)": "Write a prompt suggestion (e.g. Who are you?) much suggest",
"Write a summary in 50 words that summarizes [topic or keyword].": "Write a summary in 50 words that summarizes [topic or keyword]. Much summarize.",
"Yesterday": "",
"You": "",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "",
"You have no archived conversations.": "",
"You have shared this chat": "",
"You're a helpful assistant.": "You're a helpful assistant. Much helpful.",
"You're now logged in.": "You're now logged in. Much logged.",
"Your account status is currently pending activation.": "",
"Youtube": "",
"Youtube Loader Settings": ""
}
+39 -7
View File
@@ -12,7 +12,9 @@
"a user": "",
"About": "",
"Account": "",
"Account Activation Pending": "",
"Accurate information": "",
"Active Users": "",
"Add": "",
"Add a model id": "",
"Add a short description about what this model does": "",
@@ -28,6 +30,7 @@
"Add User": "",
"Adjusting these settings will apply changes universally to all users.": "",
"admin": "",
"Admin": "",
"Admin Panel": "",
"Admin Settings": "",
"Advanced Parameters": "",
@@ -58,7 +61,6 @@
"Audio": "",
"August": "",
"Auto-playback response": "",
"Auto-send input after 3 sec.": "",
"AUTOMATIC1111 Base URL": "",
"AUTOMATIC1111 Base URL is required.": "",
"available!": "",
@@ -70,6 +72,9 @@
"Being lazy": "",
"Brave Search API Key": "",
"Bypass SSL verification for Websites": "",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "",
"Capabilities": "",
"Change Password": "",
@@ -87,10 +92,12 @@
"Chunk Params": "",
"Chunk Size": "",
"Citation": "",
"Clear memory": "",
"Click here for help.": "",
"Click here to": "",
"Click here to select": "",
"Click here to select a csv file.": "",
"Click here to select a py file.": "",
"Click here to select documents.": "",
"click here.": "",
"Click on the user role button to change a user's role.": "",
@@ -104,17 +111,16 @@
"Concurrent Requests": "",
"Confirm Password": "",
"Connections": "",
"Contact Admin for WebUI Access": "",
"Content": "",
"Context Length": "",
"Continue Response": "",
"Conversation Mode": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy last code block": "",
"Copy last response": "",
"Copy Link": "",
"Copying to clipboard was successful!": "",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "",
"Create a model": "",
"Create Account": "",
"Create new key": "",
@@ -126,12 +132,12 @@
"Custom": "",
"Customize models for a specific purpose": "",
"Dark": "",
"Dashboard": "",
"Database": "",
"December": "",
"Default": "",
"Default (Automatic1111)": "",
"Default (SentenceTransformers)": "",
"Default (Web API)": "",
"Default Model": "",
"Default model updated": "",
"Default Prompt Suggestions": "",
@@ -152,6 +158,7 @@
"Discover a prompt": "",
"Discover, download, and explore custom prompts": "",
"Discover, download, and explore model presets": "",
"Dismissible": "",
"Display the username instead of You in the Chat": "",
"Document": "",
"Document Settings": "",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "",
"Export Models": "",
"Export Prompts": "",
"External Models": "",
"Failed to create API Key.": "",
"Failed to read clipboard contents": "",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "",
"Format your variables using square brackets like this:": "",
"Frequency Penalty": "",
"Full Screen Mode": "",
"General": "",
"General Settings": "",
"Generate Image": "",
"Generating search query": "",
"Generation Info": "",
"Good Response": "",
@@ -252,6 +260,7 @@
"Info": "",
"Input commands": "",
"Install from Github URL": "",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "",
"Invalid Tag": "",
"January": "",
@@ -264,14 +273,17 @@
"JWT Token": "",
"Keep Alive": "",
"Keyboard shortcuts": "",
"Knowledge": "",
"Language": "",
"Last Active": "",
"Light": "",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "",
"Local Models": "",
"LTR": "",
"Made by OpenWebUI Community": "",
"Make sure to enclose them with": "",
"Manage": "",
"Manage Models": "",
"Manage Ollama Models": "",
"Manage Pipelines": "",
@@ -307,6 +319,7 @@
"Name your model": "",
"New Chat": "",
"New Password": "",
"No documents found": "",
"No results found": "",
"No search query generated": "",
"No source available": "",
@@ -323,6 +336,7 @@
"Ollama": "",
"Ollama API": "",
"Ollama API disabled": "",
"Ollama API is disabled": "",
"Ollama Version": "",
"On": "",
"Only": "",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "",
"pending": "",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "",
"Personalization": "",
"Pipelines": "",
@@ -367,6 +383,7 @@
"Read Aloud": "",
"Record voice": "",
"Redirecting you to OpenWebUI Community": "",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "",
"Regenerate": "",
"Release Notes": "",
@@ -378,12 +395,14 @@
"Reranking Model": "",
"Reranking model disabled": "",
"Reranking model set to \"{{reranking_model}}\"": "",
"Reset Upload Directory": "",
"Reset Vector Storage": "",
"Response AutoCopy to Clipboard": "",
"Role": "",
"Rosé Pine": "",
"Rosé Pine Dawn": "",
"RTL": "",
"Running": "",
"Save": "",
"Save & Create": "",
"Save & Update": "",
@@ -397,6 +416,8 @@
"Search Documents": "",
"Search Models": "",
"Search Prompts": "",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "",
"Searched {{count}} sites_one": "",
"Searched {{count}} sites_other": "",
@@ -406,12 +427,14 @@
"See what's new": "",
"Seed": "",
"Select a base model": "",
"Select a engine": "",
"Select a mode": "",
"Select a model": "",
"Select a pipeline": "",
"Select a pipeline url": "",
"Select an Ollama instance": "",
"Select model": "",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "",
"Send": "",
"Send a Message": "",
@@ -424,7 +447,6 @@
"Set Default Model": "",
"Set embedding model (e.g. {{model}})": "",
"Set Image Size": "",
"Set Model": "",
"Set reranking model (e.g. {{model}})": "",
"Set Steps": "",
"Set Task Model": "",
@@ -448,8 +470,8 @@
"Source": "",
"Speech recognition error: {{error}}": "",
"Speech-to-Text Engine": "",
"SpeechRecognition API is not supported in this browser.": "",
"Stop Sequence": "",
"STT Model": "",
"STT Settings": "",
"Submit": "",
"Subtitle (e.g. about the Roman Empire)": "",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "",
"Theme": "",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "",
"Thorough explanation": "",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "",
@@ -480,6 +504,7 @@
"to": "",
"To access the available model names for downloading,": "",
"To access the GGUF models available for downloading,": "",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "",
"Today": "",
"Toggle settings": "",
@@ -487,7 +512,9 @@
"Top K": "",
"Top P": "",
"Trouble accessing Ollama?": "",
"TTS Model": "",
"TTS Settings": "",
"TTS Voice": "",
"Type": "",
"Type Hugging Face Resolve (Download) URL": "",
"Uh-oh! There was an issue connecting to {{provider}}.": "",
@@ -496,6 +523,7 @@
"Update password": "",
"Upload a GGUF model": "",
"Upload Files": "",
"Upload Pipeline": "",
"Upload Progress": "",
"URL Mode": "",
"Use '#' in the prompt input to load and select your documents.": "",
@@ -514,6 +542,7 @@
"Warning": "",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
"Web": "",
"Web API": "",
"Web Loader Settings": "",
"Web Params": "",
"Web Search": "",
@@ -525,16 +554,19 @@
"Whats New in": "",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "",
"Write a prompt suggestion (e.g. Who are you?)": "",
"Write a summary in 50 words that summarizes [topic or keyword].": "",
"Yesterday": "",
"You": "",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "",
"You have no archived conversations.": "",
"You have shared this chat": "",
"You're a helpful assistant.": "",
"You're now logged in.": "",
"Your account status is currently pending activation.": "",
"Youtube": "",
"Youtube Loader Settings": ""
}
+39 -7
View File
@@ -12,7 +12,9 @@
"a user": "",
"About": "",
"Account": "",
"Account Activation Pending": "",
"Accurate information": "",
"Active Users": "",
"Add": "",
"Add a model id": "",
"Add a short description about what this model does": "",
@@ -28,6 +30,7 @@
"Add User": "",
"Adjusting these settings will apply changes universally to all users.": "",
"admin": "",
"Admin": "",
"Admin Panel": "",
"Admin Settings": "",
"Advanced Parameters": "",
@@ -58,7 +61,6 @@
"Audio": "",
"August": "",
"Auto-playback response": "",
"Auto-send input after 3 sec.": "",
"AUTOMATIC1111 Base URL": "",
"AUTOMATIC1111 Base URL is required.": "",
"available!": "",
@@ -70,6 +72,9 @@
"Being lazy": "",
"Brave Search API Key": "",
"Bypass SSL verification for Websites": "",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "",
"Capabilities": "",
"Change Password": "",
@@ -87,10 +92,12 @@
"Chunk Params": "",
"Chunk Size": "",
"Citation": "",
"Clear memory": "",
"Click here for help.": "",
"Click here to": "",
"Click here to select": "",
"Click here to select a csv file.": "",
"Click here to select a py file.": "",
"Click here to select documents.": "",
"click here.": "",
"Click on the user role button to change a user's role.": "",
@@ -104,17 +111,16 @@
"Concurrent Requests": "",
"Confirm Password": "",
"Connections": "",
"Contact Admin for WebUI Access": "",
"Content": "",
"Context Length": "",
"Continue Response": "",
"Conversation Mode": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy last code block": "",
"Copy last response": "",
"Copy Link": "",
"Copying to clipboard was successful!": "",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "",
"Create a model": "",
"Create Account": "",
"Create new key": "",
@@ -126,12 +132,12 @@
"Custom": "",
"Customize models for a specific purpose": "",
"Dark": "",
"Dashboard": "",
"Database": "",
"December": "",
"Default": "",
"Default (Automatic1111)": "",
"Default (SentenceTransformers)": "",
"Default (Web API)": "",
"Default Model": "",
"Default model updated": "",
"Default Prompt Suggestions": "",
@@ -152,6 +158,7 @@
"Discover a prompt": "",
"Discover, download, and explore custom prompts": "",
"Discover, download, and explore model presets": "",
"Dismissible": "",
"Display the username instead of You in the Chat": "",
"Document": "",
"Document Settings": "",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "",
"Export Models": "",
"Export Prompts": "",
"External Models": "",
"Failed to create API Key.": "",
"Failed to read clipboard contents": "",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "",
"Format your variables using square brackets like this:": "",
"Frequency Penalty": "",
"Full Screen Mode": "",
"General": "",
"General Settings": "",
"Generate Image": "",
"Generating search query": "",
"Generation Info": "",
"Good Response": "",
@@ -252,6 +260,7 @@
"Info": "",
"Input commands": "",
"Install from Github URL": "",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "",
"Invalid Tag": "",
"January": "",
@@ -264,14 +273,17 @@
"JWT Token": "",
"Keep Alive": "",
"Keyboard shortcuts": "",
"Knowledge": "",
"Language": "",
"Last Active": "",
"Light": "",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "",
"Local Models": "",
"LTR": "",
"Made by OpenWebUI Community": "",
"Make sure to enclose them with": "",
"Manage": "",
"Manage Models": "",
"Manage Ollama Models": "",
"Manage Pipelines": "",
@@ -307,6 +319,7 @@
"Name your model": "",
"New Chat": "",
"New Password": "",
"No documents found": "",
"No results found": "",
"No search query generated": "",
"No source available": "",
@@ -323,6 +336,7 @@
"Ollama": "",
"Ollama API": "",
"Ollama API disabled": "",
"Ollama API is disabled": "",
"Ollama Version": "",
"On": "",
"Only": "",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "",
"pending": "",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "",
"Personalization": "",
"Pipelines": "",
@@ -367,6 +383,7 @@
"Read Aloud": "",
"Record voice": "",
"Redirecting you to OpenWebUI Community": "",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "",
"Regenerate": "",
"Release Notes": "",
@@ -378,12 +395,14 @@
"Reranking Model": "",
"Reranking model disabled": "",
"Reranking model set to \"{{reranking_model}}\"": "",
"Reset Upload Directory": "",
"Reset Vector Storage": "",
"Response AutoCopy to Clipboard": "",
"Role": "",
"Rosé Pine": "",
"Rosé Pine Dawn": "",
"RTL": "",
"Running": "",
"Save": "",
"Save & Create": "",
"Save & Update": "",
@@ -397,6 +416,8 @@
"Search Documents": "",
"Search Models": "",
"Search Prompts": "",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "",
"Searched {{count}} sites_one": "",
"Searched {{count}} sites_other": "",
@@ -406,12 +427,14 @@
"See what's new": "",
"Seed": "",
"Select a base model": "",
"Select a engine": "",
"Select a mode": "",
"Select a model": "",
"Select a pipeline": "",
"Select a pipeline url": "",
"Select an Ollama instance": "",
"Select model": "",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "",
"Send": "",
"Send a Message": "",
@@ -424,7 +447,6 @@
"Set Default Model": "",
"Set embedding model (e.g. {{model}})": "",
"Set Image Size": "",
"Set Model": "",
"Set reranking model (e.g. {{model}})": "",
"Set Steps": "",
"Set Task Model": "",
@@ -448,8 +470,8 @@
"Source": "",
"Speech recognition error: {{error}}": "",
"Speech-to-Text Engine": "",
"SpeechRecognition API is not supported in this browser.": "",
"Stop Sequence": "",
"STT Model": "",
"STT Settings": "",
"Submit": "",
"Subtitle (e.g. about the Roman Empire)": "",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "",
"Theme": "",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "",
"Thorough explanation": "",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "",
@@ -480,6 +504,7 @@
"to": "",
"To access the available model names for downloading,": "",
"To access the GGUF models available for downloading,": "",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "",
"Today": "",
"Toggle settings": "",
@@ -487,7 +512,9 @@
"Top K": "",
"Top P": "",
"Trouble accessing Ollama?": "",
"TTS Model": "",
"TTS Settings": "",
"TTS Voice": "",
"Type": "",
"Type Hugging Face Resolve (Download) URL": "",
"Uh-oh! There was an issue connecting to {{provider}}.": "",
@@ -496,6 +523,7 @@
"Update password": "",
"Upload a GGUF model": "",
"Upload Files": "",
"Upload Pipeline": "",
"Upload Progress": "",
"URL Mode": "",
"Use '#' in the prompt input to load and select your documents.": "",
@@ -514,6 +542,7 @@
"Warning": "",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
"Web": "",
"Web API": "",
"Web Loader Settings": "",
"Web Params": "",
"Web Search": "",
@@ -525,16 +554,19 @@
"Whats New in": "",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "",
"Write a prompt suggestion (e.g. Who are you?)": "",
"Write a summary in 50 words that summarizes [topic or keyword].": "",
"Yesterday": "",
"You": "",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "",
"You have no archived conversations.": "",
"You have shared this chat": "",
"You're a helpful assistant.": "",
"You're now logged in.": "",
"Your account status is currently pending activation.": "",
"Youtube": "",
"Youtube Loader Settings": ""
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "un usuario",
"About": "Sobre nosotros",
"Account": "Cuenta",
"Account Activation Pending": "",
"Accurate information": "Información precisa",
"Active Users": "",
"Add": "Agregar",
"Add a model id": "Adición de un identificador de modelo",
"Add a short description about what this model does": "Agregue una breve descripción sobre lo que hace este modelo",
@@ -28,6 +30,7 @@
"Add User": "Agregar Usuario",
"Adjusting these settings will apply changes universally to all users.": "Ajustar estas opciones aplicará los cambios universalmente a todos los usuarios.",
"admin": "admin",
"Admin": "",
"Admin Panel": "Panel de Administración",
"Admin Settings": "Configuración de Administrador",
"Advanced Parameters": "Parámetros Avanzados",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "Agosto",
"Auto-playback response": "Respuesta de reproducción automática",
"Auto-send input after 3 sec.": "Envía la información entrada automáticamente luego de 3 segundos.",
"AUTOMATIC1111 Base URL": "Dirección URL de AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "La dirección URL de AUTOMATIC1111 es requerida.",
"available!": "¡disponible!",
@@ -70,6 +72,9 @@
"Being lazy": "Ser perezoso",
"Brave Search API Key": "Clave de API de Brave Search",
"Bypass SSL verification for Websites": "Desactivar la verificación SSL para sitios web",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Cancelar",
"Capabilities": "Capacidades",
"Change Password": "Cambia la Contraseña",
@@ -87,10 +92,12 @@
"Chunk Params": "Parámetros de fragmentos",
"Chunk Size": "Tamaño de fragmentos",
"Citation": "Cita",
"Clear memory": "",
"Click here for help.": "Presiona aquí para obtener ayuda.",
"Click here to": "Presiona aquí para",
"Click here to select": "Presiona aquí para seleccionar",
"Click here to select a csv file.": "Presiona aquí para seleccionar un archivo csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "Presiona aquí para seleccionar documentos",
"click here.": "Presiona aquí.",
"Click on the user role button to change a user's role.": "Presiona en el botón de roles del usuario para cambiar su rol.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Solicitudes simultáneas",
"Confirm Password": "Confirmar Contraseña",
"Connections": "Conexiones",
"Contact Admin for WebUI Access": "",
"Content": "Contenido",
"Context Length": "Longitud del contexto",
"Continue Response": "Continuar Respuesta",
"Conversation Mode": "Modo de Conversación",
"Copied shared chat URL to clipboard!": "¡URL de chat compartido copiado al portapapeles!",
"Copy": "Copiar",
"Copy last code block": "Copia el último bloque de código",
"Copy last response": "Copia la última respuesta",
"Copy Link": "Copiar enlace",
"Copying to clipboard was successful!": "¡La copia al portapapeles se ha realizado correctamente!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Cree una frase concisa de 3 a 5 palabras como encabezado para la siguiente consulta, respetando estrictamente el límite de 3 a 5 palabras y evitando el uso de la palabra 'título':",
"Create a model": "Crear un modelo",
"Create Account": "Crear una cuenta",
"Create new key": "Crear una nueva clave",
@@ -126,12 +132,12 @@
"Custom": "Personalizado",
"Customize models for a specific purpose": "Personalizar modelos para un propósito específico",
"Dark": "Oscuro",
"Dashboard": "",
"Database": "Base de datos",
"December": "Diciembre",
"Default": "Por defecto",
"Default (Automatic1111)": "Por defecto (Automatic1111)",
"Default (SentenceTransformers)": "Por defecto (SentenceTransformers)",
"Default (Web API)": "Por defecto (Web API)",
"Default Model": "Modelo predeterminado",
"Default model updated": "El modelo por defecto ha sido actualizado",
"Default Prompt Suggestions": "Sugerencias de mensajes por defecto",
@@ -152,6 +158,7 @@
"Discover a prompt": "Descubre un Prompt",
"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
"Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos",
"Dismissible": "",
"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
"Document": "Documento",
"Document Settings": "Configuración del Documento",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Exportar el mapeo de documentos",
"Export Models": "Modelos de exportación",
"Export Prompts": "Exportar Prompts",
"External Models": "",
"Failed to create API Key.": "No se pudo crear la clave API.",
"Failed to read clipboard contents": "No se pudo leer el contenido del portapapeles",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Siguió las instrucciones perfectamente",
"Format your variables using square brackets like this:": "Formatea tus variables usando corchetes de la siguiente manera:",
"Frequency Penalty": "Penalización de frecuencia",
"Full Screen Mode": "Modo de Pantalla Completa",
"General": "General",
"General Settings": "Opciones Generales",
"Generate Image": "",
"Generating search query": "Generación de consultas de búsqueda",
"Generation Info": "Información de Generación",
"Good Response": "Buena Respuesta",
@@ -252,6 +260,7 @@
"Info": "Información",
"Input commands": "Ingresar comandos",
"Install from Github URL": "Instalar desde la URL de Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interfaz",
"Invalid Tag": "Etiqueta Inválida",
"January": "Enero",
@@ -264,14 +273,17 @@
"JWT Token": "Token JWT",
"Keep Alive": "Mantener Vivo",
"Keyboard shortcuts": "Atajos de teclado",
"Knowledge": "",
"Language": "Lenguaje",
"Last Active": "Última Actividad",
"Light": "Claro",
"Listening...": "Escuchando...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Los LLM pueden cometer errores. Verifica la información importante.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Hecho por la comunidad de OpenWebUI",
"Make sure to enclose them with": "Asegúrese de adjuntarlos con",
"Manage": "",
"Manage Models": "Administrar Modelos",
"Manage Ollama Models": "Administrar Modelos Ollama",
"Manage Pipelines": "Administrar canalizaciones",
@@ -307,6 +319,7 @@
"Name your model": "Asigne un nombre a su modelo",
"New Chat": "Nuevo Chat",
"New Password": "Nueva Contraseña",
"No documents found": "",
"No results found": "No se han encontrado resultados",
"No search query generated": "No se ha generado ninguna consulta de búsqueda",
"No source available": "No hay fuente disponible",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "API de Ollama deshabilitada",
"Ollama API is disabled": "",
"Ollama Version": "Versión de Ollama",
"On": "Activado",
"Only": "Solamente",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF document (.pdf)",
"PDF Extract Images (OCR)": "Extraer imágenes de PDF (OCR)",
"pending": "pendiente",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permiso denegado al acceder al micrófono: {{error}}",
"Personalization": "Personalización",
"Pipelines": "Tuberías",
@@ -367,6 +383,7 @@
"Read Aloud": "Leer al oído",
"Record voice": "Grabar voz",
"Redirecting you to OpenWebUI Community": "Redireccionándote a la comunidad OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Rechazado cuando no debería",
"Regenerate": "Regenerar",
"Release Notes": "Notas de la versión",
@@ -378,12 +395,14 @@
"Reranking Model": "Modelo de reranking",
"Reranking model disabled": "Modelo de reranking deshabilitado",
"Reranking model set to \"{{reranking_model}}\"": "Modelo de reranking establecido en \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Restablecer almacenamiento vectorial",
"Response AutoCopy to Clipboard": "Copiar respuesta automáticamente al portapapeles",
"Role": "Rol",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "Guardar",
"Save & Create": "Guardar y Crear",
"Save & Update": "Guardar y Actualizar",
@@ -397,6 +416,8 @@
"Search Documents": "Buscar Documentos",
"Search Models": "Modelos de búsqueda",
"Search Prompts": "Buscar Prompts",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Recuento de resultados de búsqueda",
"Searched {{count}} sites_one": "Buscado {{count}} sites_one",
"Searched {{count}} sites_many": "Buscado {{count}} sites_many",
@@ -407,12 +428,14 @@
"See what's new": "Ver las novedades",
"Seed": "Seed",
"Select a base model": "Seleccionar un modelo base",
"Select a engine": "",
"Select a mode": "Selecciona un modo",
"Select a model": "Selecciona un modelo",
"Select a pipeline": "Selección de una canalización",
"Select a pipeline url": "Selección de una dirección URL de canalización",
"Select an Ollama instance": "Seleccione una instancia de Ollama",
"Select model": "Selecciona un modelo",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Los modelos seleccionados no admiten entradas de imagen",
"Send": "Enviar",
"Send a Message": "Enviar un Mensaje",
@@ -425,7 +448,6 @@
"Set Default Model": "Establecer modelo predeterminado",
"Set embedding model (e.g. {{model}})": "Establecer modelo de embedding (ej. {{model}})",
"Set Image Size": "Establecer tamaño de imagen",
"Set Model": "Establecer el modelo",
"Set reranking model (e.g. {{model}})": "Establecer modelo de reranking (ej. {{model}})",
"Set Steps": "Establecer Pasos",
"Set Task Model": "Establecer modelo de tarea",
@@ -449,8 +471,8 @@
"Source": "Fuente",
"Speech recognition error: {{error}}": "Error de reconocimiento de voz: {{error}}",
"Speech-to-Text Engine": "Motor de voz a texto",
"SpeechRecognition API is not supported in this browser.": "La API SpeechRecognition no es compatible con este navegador.",
"Stop Sequence": "Detener secuencia",
"STT Model": "",
"STT Settings": "Configuraciones de STT",
"Submit": "Enviar",
"Subtitle (e.g. about the Roman Empire)": "Subtítulo (por ejemplo, sobre el Imperio Romano)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "¡Gracias por tu retroalimentación!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "El puntaje debe ser un valor entre 0.0 (0%) y 1.0 (100%).",
"Theme": "Tema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Esto garantiza que sus valiosas conversaciones se guarden de forma segura en su base de datos en el backend. ¡Gracias!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Esta configuración no se sincroniza entre navegadores o dispositivos.",
"Thorough explanation": "Explicación exhaustiva",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consejo: Actualice múltiples variables consecutivamente presionando la tecla tab en la entrada del chat después de cada reemplazo.",
@@ -481,6 +505,7 @@
"to": "para",
"To access the available model names for downloading,": "Para acceder a los nombres de modelos disponibles para descargar,",
"To access the GGUF models available for downloading,": "Para acceder a los modelos GGUF disponibles para descargar,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "a la entrada del chat.",
"Today": "Hoy",
"Toggle settings": "Alternar configuración",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "¿Problemas para acceder a Ollama?",
"TTS Model": "",
"TTS Settings": "Configuración de TTS",
"TTS Voice": "",
"Type": "Tipo",
"Type Hugging Face Resolve (Download) URL": "Escriba la URL (Descarga) de Hugging Face Resolve",
"Uh-oh! There was an issue connecting to {{provider}}.": "¡Uh oh! Hubo un problema al conectarse a {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Actualizar contraseña",
"Upload a GGUF model": "Subir un modelo GGUF",
"Upload Files": "Subir archivos",
"Upload Pipeline": "",
"Upload Progress": "Progreso de carga",
"URL Mode": "Modo de URL",
"Use '#' in the prompt input to load and select your documents.": "Utilice '#' en el prompt para cargar y seleccionar sus documentos.",
@@ -515,6 +543,7 @@
"Warning": "Advertencia",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Advertencia: Si actualiza o cambia su modelo de inserción, necesitará volver a importar todos los documentos.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Web Loader Settings",
"Web Params": "Web Params",
"Web Search": "Búsqueda en la Web",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI realizará solicitudes a",
"Whats New in": "Novedades en",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Cuando el historial está desactivado, los nuevos chats en este navegador no aparecerán en el historial de ninguno de sus dispositivos..",
"Whisper (Local)": "Whisper (Local)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Espacio de trabajo",
"Write a prompt suggestion (e.g. Who are you?)": "Escribe una sugerencia para un prompt (por ejemplo, ¿quién eres?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Escribe un resumen en 50 palabras que resuma [tema o palabra clave].",
"Yesterday": "Ayer",
"You": "Usted",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "No se puede clonar un modelo base",
"You have no archived conversations.": "No tiene conversaciones archivadas.",
"You have shared this chat": "Usted ha compartido esta conversación",
"You're a helpful assistant.": "Usted es un asistente útil.",
"You're now logged in.": "Usted ahora está conectado.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Configuración del cargador de Youtube"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "یک کاربر",
"About": "درباره",
"Account": "حساب کاربری",
"Account Activation Pending": "",
"Accurate information": "اطلاعات دقیق",
"Active Users": "",
"Add": "اضافه کردن",
"Add a model id": "افزودن شناسه مدل",
"Add a short description about what this model does": "اضافه کردن توضیحات کوتاه در مورد انچه که این مدل انجام می دهد",
@@ -28,6 +30,7 @@
"Add User": "اضافه کردن کاربر",
"Adjusting these settings will apply changes universally to all users.": "با تنظیم این تنظیمات، تغییرات به طور کلی برای همه کاربران اعمال می شود.",
"admin": "مدیر",
"Admin": "",
"Admin Panel": "پنل مدیریت",
"Admin Settings": "تنظیمات مدیریت",
"Advanced Parameters": "پارامترهای پیشرفته",
@@ -58,7 +61,6 @@
"Audio": "صدا",
"August": "آگوست",
"Auto-playback response": "پخش خودکار پاسخ ",
"Auto-send input after 3 sec.": "به طور خودکار ورودی را پس از 3 ثانیه ارسال کن.",
"AUTOMATIC1111 Base URL": "پایه URL AUTOMATIC1111 ",
"AUTOMATIC1111 Base URL is required.": "به URL پایه AUTOMATIC1111 مورد نیاز است.",
"available!": "در دسترس!",
@@ -70,6 +72,9 @@
"Being lazy": "حالت سازنده",
"Brave Search API Key": "کلید API جستجوی شجاع",
"Bypass SSL verification for Websites": "عبور از تأیید SSL برای وب سایت ها",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "لغو",
"Capabilities": "قابلیت",
"Change Password": "تغییر رمز عبور",
@@ -87,10 +92,12 @@
"Chunk Params": "پارامترهای تکه",
"Chunk Size": "اندازه تکه",
"Citation": "استناد",
"Clear memory": "",
"Click here for help.": "برای کمک اینجا را کلیک کنید.",
"Click here to": "برای کمک اینجا را کلیک کنید.",
"Click here to select": "برای انتخاب اینجا کلیک کنید",
"Click here to select a csv file.": "برای انتخاب یک فایل csv اینجا را کلیک کنید.",
"Click here to select a py file.": "",
"Click here to select documents.": "برای انتخاب اسناد اینجا را کلیک کنید.",
"click here.": "اینجا کلیک کنید.",
"Click on the user role button to change a user's role.": "برای تغییر نقش کاربر، روی دکمه نقش کاربر کلیک کنید.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "درخواست های همزمان",
"Confirm Password": "تایید رمز عبور",
"Connections": "ارتباطات",
"Contact Admin for WebUI Access": "",
"Content": "محتوا",
"Context Length": "طول زمینه",
"Continue Response": "ادامه پاسخ",
"Conversation Mode": "حالت مکالمه",
"Copied shared chat URL to clipboard!": "URL چت به کلیپ بورد کپی شد!",
"Copy": "کپی",
"Copy last code block": "کپی آخرین بلوک کد",
"Copy last response": "کپی آخرین پاسخ",
"Copy Link": "کپی لینک",
"Copying to clipboard was successful!": "کپی کردن در کلیپ بورد با موفقیت انجام شد!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "یک عبارت مختصر و ۳ تا ۵ کلمه ای را به عنوان سرفصل برای پرس و جو زیر ایجاد کنید، به شدت محدودیت ۳-۵ کلمه را رعایت کنید و از استفاده از کلمه 'عنوان' خودداری کنید:",
"Create a model": "ایجاد یک مدل",
"Create Account": "ساخت حساب کاربری",
"Create new key": "ساخت کلید جدید",
@@ -126,12 +132,12 @@
"Custom": "دلخواه",
"Customize models for a specific purpose": "سفارشی کردن مدل ها برای یک هدف خاص",
"Dark": "تیره",
"Dashboard": "",
"Database": "پایگاه داده",
"December": "دسامبر",
"Default": "پیشفرض",
"Default (Automatic1111)": "پیشفرض (Automatic1111)",
"Default (SentenceTransformers)": "پیشفرض (SentenceTransformers)",
"Default (Web API)": "پیشفرض (Web API)",
"Default Model": "مدل پیشفرض",
"Default model updated": "مدل پیشفرض به\u200cروزرسانی شد",
"Default Prompt Suggestions": "پیشنهادات پرامپت پیش فرض",
@@ -152,6 +158,7 @@
"Discover a prompt": "یک اعلان را کشف کنید",
"Discover, download, and explore custom prompts": "پرامپت\u200cهای سفارشی را کشف، دانلود و کاوش کنید",
"Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید",
"Dismissible": "",
"Display the username instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت",
"Document": "سند",
"Document Settings": "تنظیمات سند",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "اکسپورت از نگاشت اسناد",
"Export Models": "مدل های صادرات",
"Export Prompts": "اکسپورت از پرامپت\u200cها",
"External Models": "",
"Failed to create API Key.": "ایجاد کلید API با خطا مواجه شد.",
"Failed to read clipboard contents": "خواندن محتوای کلیپ بورد ناموفق بود",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "دستورالعمل ها را کاملا دنبال کرد",
"Format your variables using square brackets like this:": "متغیرهای خود را با استفاده از براکت مربع به شکل زیر قالب بندی کنید:",
"Frequency Penalty": "مجازات فرکانس",
"Full Screen Mode": "حالت تمام صفحه",
"General": "عمومی",
"General Settings": "تنظیمات عمومی",
"Generate Image": "",
"Generating search query": "در حال تولید پرسوجوی جستجو",
"Generation Info": "اطلاعات تولید",
"Good Response": "پاسخ خوب",
@@ -252,6 +260,7 @@
"Info": "اطلاعات",
"Input commands": "ورودی دستورات",
"Install from Github URL": "نصب از ادرس Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "رابط",
"Invalid Tag": "تگ نامعتبر",
"January": "ژانویه",
@@ -264,14 +273,17 @@
"JWT Token": "JWT توکن",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "میانبرهای صفحه کلید",
"Knowledge": "",
"Language": "زبان",
"Last Active": "آخرین فعال",
"Light": "روشن",
"Listening...": "در حال گوش دادن...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "مدل\u200cهای زبانی بزرگ می\u200cتوانند اشتباه کنند. اطلاعات مهم را راستی\u200cآزمایی کنید.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "ساخته شده توسط OpenWebUI Community",
"Make sure to enclose them with": "مطمئن شوید که آنها را با این محصور کنید:",
"Manage": "",
"Manage Models": "مدیریت مدل\u200cها",
"Manage Ollama Models": "مدیریت مدل\u200cهای اولاما",
"Manage Pipelines": "مدیریت خطوط لوله",
@@ -307,6 +319,7 @@
"Name your model": "نام مدل خود را",
"New Chat": "گپ جدید",
"New Password": "رمز عبور جدید",
"No documents found": "",
"No results found": "نتیجه\u200cای یافت نشد",
"No search query generated": "پرسوجوی جستجویی ایجاد نشده است",
"No source available": "منبعی در دسترس نیست",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "API Ollama غیرفعال شد",
"Ollama API is disabled": "",
"Ollama Version": "نسخه اولاما",
"On": "روشن",
"Only": "فقط",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF سند (.pdf)",
"PDF Extract Images (OCR)": "استخراج تصاویر از PDF (OCR)",
"pending": "در انتظار",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "هنگام دسترسی به میکروفون، اجازه داده نشد: {{error}}",
"Personalization": "شخصی سازی",
"Pipelines": "خط لوله",
@@ -367,6 +383,7 @@
"Read Aloud": "خواندن به صورت صوتی",
"Record voice": "ضبط صدا",
"Redirecting you to OpenWebUI Community": "در حال هدایت به OpenWebUI Community",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "رد شده زمانی که باید نباشد",
"Regenerate": "ری\u200cسازی",
"Release Notes": "یادداشت\u200cهای انتشار",
@@ -378,12 +395,14 @@
"Reranking Model": "مدل ری\u200cشناسی مجدد غیرفعال است",
"Reranking model disabled": "مدل ری\u200cشناسی مجدد غیرفعال است",
"Reranking model set to \"{{reranking_model}}\"": "مدل ری\u200cشناسی مجدد به \"{{reranking_model}}\" تنظیم شده است",
"Reset Upload Directory": "",
"Reset Vector Storage": "بازنشانی ذخیره سازی برداری",
"Response AutoCopy to Clipboard": "کپی خودکار پاسخ به کلیپ بورد",
"Role": "نقش",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "ذخیره",
"Save & Create": "ذخیره و ایجاد",
"Save & Update": "ذخیره و به\u200cروزرسانی",
@@ -397,6 +416,8 @@
"Search Documents": "جستجوی اسناد",
"Search Models": "مدل های جستجو",
"Search Prompts": "جستجوی پرامپت\u200cها",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "تعداد نتایج جستجو",
"Searched {{count}} sites_one": "جستجو {{count}} sites_one",
"Searched {{count}} sites_other": "جستجو {{count}} sites_other",
@@ -406,12 +427,14 @@
"See what's new": "ببینید موارد جدید چه بوده",
"Seed": "Seed",
"Select a base model": "انتخاب یک مدل پایه",
"Select a engine": "",
"Select a mode": "یک حالت انتخاب کنید",
"Select a model": "انتخاب یک مدل",
"Select a pipeline": "انتخاب یک خط لوله",
"Select a pipeline url": "یک ادرس خط لوله را انتخاب کنید",
"Select an Ollama instance": "انتخاب یک نمونه از اولاما",
"Select model": "انتخاب یک مدل",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "مدل) های (انتخاب شده ورودیهای تصویر را پشتیبانی نمیکند",
"Send": "ارسال",
"Send a Message": "ارسال یک پیام",
@@ -424,7 +447,6 @@
"Set Default Model": "تنظیم مدل پیش فرض",
"Set embedding model (e.g. {{model}})": "تنظیم مدل پیچشی (برای مثال {{model}})",
"Set Image Size": "تنظیم اندازه تصویر",
"Set Model": "تنظیم مدل",
"Set reranking model (e.g. {{model}})": "تنظیم مدل ری\u200cراینگ (برای مثال {{model}})",
"Set Steps": "تنظیم گام\u200cها",
"Set Task Model": "تنظیم مدل تکلیف",
@@ -448,8 +470,8 @@
"Source": "منبع",
"Speech recognition error: {{error}}": "خطای تشخیص گفتار: {{error}}",
"Speech-to-Text Engine": "موتور گفتار به متن",
"SpeechRecognition API is not supported in this browser.": "API تشخیص گفتار در این مرورگر پشتیبانی نمی شود.",
"Stop Sequence": "توالی توقف",
"STT Model": "",
"STT Settings": "STT تنظیمات",
"Submit": "ارسال",
"Subtitle (e.g. about the Roman Empire)": "زیرنویس (برای مثال: درباره رمانی)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "با تشکر از بازخورد شما!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "امتیاز باید یک مقدار بین 0.0 (0%) و 1.0 (100%) باشد.",
"Theme": "قالب",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "این تضمین می کند که مکالمات ارزشمند شما به طور ایمن در پایگاه داده بکند ذخیره می شود. تشکر!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "این تنظیم در مرورگرها یا دستگاه\u200cها همگام\u200cسازی نمی\u200cشود.",
"Thorough explanation": "توضیح کامل",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "با فشردن کلید Tab در ورودی چت پس از هر بار تعویض، چندین متغیر را به صورت متوالی به روزرسانی کنید.",
@@ -480,6 +504,7 @@
"to": "به",
"To access the available model names for downloading,": "برای دسترسی به نام مدل های موجود برای دانلود،",
"To access the GGUF models available for downloading,": "برای دسترسی به مدل\u200cهای GGUF موجود برای دانلود،",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "در ورودی گپ.",
"Today": "امروز",
"Toggle settings": "نمایش/عدم نمایش تنظیمات",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "در دسترسی به اولاما مشکل دارید؟",
"TTS Model": "",
"TTS Settings": "تنظیمات TTS",
"TTS Voice": "",
"Type": "نوع",
"Type Hugging Face Resolve (Download) URL": "مقدار URL دانلود (Resolve) Hugging Face را وارد کنید",
"Uh-oh! There was an issue connecting to {{provider}}.": "اوه اوه! مشکلی در اتصال به {{provider}} وجود داشت.",
@@ -496,6 +523,7 @@
"Update password": "به روزرسانی رمزعبور",
"Upload a GGUF model": "آپلود یک مدل GGUF",
"Upload Files": "بارگذاری پروندهها",
"Upload Pipeline": "",
"Upload Progress": "پیشرفت آپلود",
"URL Mode": "حالت URL",
"Use '#' in the prompt input to load and select your documents.": "در پرامپت از '#' برای لود و انتخاب اسناد خود استفاده کنید.",
@@ -514,6 +542,7 @@
"Warning": "هشدار",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "هشدار: اگر شما به روز کنید یا تغییر دهید مدل شما، باید تمام سند ها را مجددا وارد کنید.",
"Web": "وب",
"Web API": "",
"Web Loader Settings": "تنظیمات لودر وب",
"Web Params": "پارامترهای وب",
"Web Search": "جستجوی وب",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI درخواست\u200cها را ارسال خواهد کرد به",
"Whats New in": "موارد جدید در",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "وقتی سابقه خاموش است، چت\u200cهای جدید در این مرورگر در سابقه شما در هیچ یک از دستگاه\u200cهایتان ظاهر نمی\u200cشوند.",
"Whisper (Local)": "ویسپر (محلی)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "محیط کار",
"Write a prompt suggestion (e.g. Who are you?)": "یک پیشنهاد پرامپت بنویسید (مثلاً شما کی هستید؟)",
"Write a summary in 50 words that summarizes [topic or keyword].": "خلاصه ای در 50 کلمه بنویسید که [موضوع یا کلمه کلیدی] را خلاصه کند.",
"Yesterday": "دیروز",
"You": "شما",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "شما نمیتوانید یک مدل پایه را کلون کنید",
"You have no archived conversations.": "شما هیچ گفتگوی ذخیره شده ندارید.",
"You have shared this chat": "شما این گفتگو را به اشتراک گذاشته اید",
"You're a helpful assistant.": "تو یک دستیار سودمند هستی.",
"You're now logged in.": "شما اکنون وارد شده\u200cاید.",
"Your account status is currently pending activation.": "",
"Youtube": "یوتیوب",
"Youtube Loader Settings": "تنظیمات لودر یوتیوب"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "käyttäjä",
"About": "Tietoja",
"Account": "Tili",
"Account Activation Pending": "",
"Accurate information": "Tarkkaa tietoa",
"Active Users": "",
"Add": "Lisää",
"Add a model id": "Mallitunnuksen lisääminen",
"Add a short description about what this model does": "Lisää lyhyt kuvaus siitä, mitä tämä malli tekee",
@@ -28,6 +30,7 @@
"Add User": "Lisää käyttäjä",
"Adjusting these settings will apply changes universally to all users.": "Näiden asetusten säätäminen vaikuttaa kaikkiin käyttäjiin.",
"admin": "hallinta",
"Admin": "",
"Admin Panel": "Hallintapaneeli",
"Admin Settings": "Hallinta-asetukset",
"Advanced Parameters": "Edistyneet parametrit",
@@ -58,7 +61,6 @@
"Audio": "Ääni",
"August": "elokuu",
"Auto-playback response": "Soita vastaus automaattisesti",
"Auto-send input after 3 sec.": "Lähetä syöte automaattisesti 3 sekunnin kuluttua",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111-perus-URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111-perus-URL vaaditaan.",
"available!": "saatavilla!",
@@ -70,6 +72,9 @@
"Being lazy": "Oli laiska",
"Brave Search API Key": "Brave Search API -avain",
"Bypass SSL verification for Websites": "Ohita SSL-varmennus verkkosivustoille",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Peruuta",
"Capabilities": "Ominaisuuksia",
"Change Password": "Vaihda salasana",
@@ -87,10 +92,12 @@
"Chunk Params": "Osien parametrit",
"Chunk Size": "Osien koko",
"Citation": "Sitaatti",
"Clear memory": "",
"Click here for help.": "Klikkaa tästä saadaksesi apua.",
"Click here to": "Klikkaa tästä",
"Click here to select": "Klikkaa tästä valitaksesi",
"Click here to select a csv file.": "Klikkaa tästä valitaksesi CSV-tiedosto.",
"Click here to select a py file.": "",
"Click here to select documents.": "Klikkaa tästä valitaksesi asiakirjoja.",
"click here.": "klikkaa tästä.",
"Click on the user role button to change a user's role.": "Klikkaa käyttäjän roolipainiketta vaihtaaksesi käyttäjän roolia.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Samanaikaiset pyynnöt",
"Confirm Password": "Vahvista salasana",
"Connections": "Yhteydet",
"Contact Admin for WebUI Access": "",
"Content": "Sisältö",
"Context Length": "Kontekstin pituus",
"Continue Response": "Jatka vastausta",
"Conversation Mode": "Keskustelutila",
"Copied shared chat URL to clipboard!": "Jaettu keskustelulinkki kopioitu leikepöydälle!",
"Copy": "Kopioi",
"Copy last code block": "Kopioi viimeisin koodilohko",
"Copy last response": "Kopioi viimeisin vastaus",
"Copy Link": "Kopioi linkki",
"Copying to clipboard was successful!": "Kopioiminen leikepöydälle onnistui!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Luo tiivis, 3-5 sanan lause otsikoksi seuraavalle kyselylle, noudattaen tiukasti 3-5 sanan rajoitusta ja välttäen sanan 'otsikko' käyttöä:",
"Create a model": "Mallin luominen",
"Create Account": "Luo tili",
"Create new key": "Luo uusi avain",
@@ -126,12 +132,12 @@
"Custom": "Mukautettu",
"Customize models for a specific purpose": "Mallien mukauttaminen tiettyyn tarkoitukseen",
"Dark": "Tumma",
"Dashboard": "",
"Database": "Tietokanta",
"December": "joulukuu",
"Default": "Oletus",
"Default (Automatic1111)": "Oletus (AUTOMATIC1111)",
"Default (SentenceTransformers)": "Oletus (SentenceTransformers)",
"Default (Web API)": "Oletus (web-API)",
"Default Model": "Oletusmalli",
"Default model updated": "Oletusmalli päivitetty",
"Default Prompt Suggestions": "Oletuskehotteiden ehdotukset",
@@ -152,6 +158,7 @@
"Discover a prompt": "Löydä kehote",
"Discover, download, and explore custom prompts": "Löydä ja lataa mukautettuja kehotteita",
"Discover, download, and explore model presets": "Löydä ja lataa mallien esiasetuksia",
"Dismissible": "",
"Display the username instead of You in the Chat": "Näytä käyttäjänimi keskustelussa",
"Document": "Asiakirja",
"Document Settings": "Asiakirja-asetukset",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Vie asiakirjakartoitus",
"Export Models": "Vie malleja",
"Export Prompts": "Vie kehotteet",
"External Models": "",
"Failed to create API Key.": "API-avaimen luonti epäonnistui.",
"Failed to read clipboard contents": "Leikepöydän sisällön lukeminen epäonnistui",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Noudatti ohjeita täydellisesti",
"Format your variables using square brackets like this:": "Muotoile muuttujat hakasulkeilla näin:",
"Frequency Penalty": "Taajuussakko",
"Full Screen Mode": "Koko näytön tila",
"General": "Yleinen",
"General Settings": "Yleisasetukset",
"Generate Image": "",
"Generating search query": "Hakukyselyn luominen",
"Generation Info": "Generointitiedot",
"Good Response": "Hyvä vastaus",
@@ -252,6 +260,7 @@
"Info": "Info",
"Input commands": "Syötä komennot",
"Install from Github URL": "Asenna Githubin URL-osoitteesta",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Käyttöliittymä",
"Invalid Tag": "Virheellinen tagi",
"January": "tammikuu",
@@ -264,14 +273,17 @@
"JWT Token": "JWT-token",
"Keep Alive": "Pysy aktiivisena",
"Keyboard shortcuts": "Pikanäppäimet",
"Knowledge": "",
"Language": "Kieli",
"Last Active": "Viimeksi aktiivinen",
"Light": "Vaalea",
"Listening...": "Kuunnellaan...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Kielimallit voivat tehdä virheitä. Varmista tärkeät tiedot.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Tehnyt OpenWebUI-yhteisö",
"Make sure to enclose them with": "Varmista, että suljet ne",
"Manage": "",
"Manage Models": "Hallitse malleja",
"Manage Ollama Models": "Hallitse Ollama-malleja",
"Manage Pipelines": "Hallitse putkia",
@@ -307,6 +319,7 @@
"Name your model": "Mallin nimeäminen",
"New Chat": "Uusi keskustelu",
"New Password": "Uusi salasana",
"No documents found": "",
"No results found": "Ei tuloksia",
"No search query generated": "Hakukyselyä ei luotu",
"No source available": "Ei lähdettä saatavilla",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API poistettu käytöstä",
"Ollama API is disabled": "",
"Ollama Version": "Ollama-versio",
"On": "Päällä",
"Only": "Vain",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF-tiedosto (.pdf)",
"PDF Extract Images (OCR)": "PDF-tiedoston kuvien erottelu (OCR)",
"pending": "odottaa",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Mikrofonin käyttöoikeus evätty: {{error}}",
"Personalization": "Henkilökohtaisuus",
"Pipelines": "Putkistot",
@@ -367,6 +383,7 @@
"Read Aloud": "Lue ääneen",
"Record voice": "Nauhoita ääni",
"Redirecting you to OpenWebUI Community": "Ohjataan sinut OpenWebUI-yhteisöön",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Kieltäytyi, vaikka ei olisi pitänyt",
"Regenerate": "Uudelleenluo",
"Release Notes": "Julkaisutiedot",
@@ -378,12 +395,14 @@
"Reranking Model": "Uudelleenpisteytysmalli",
"Reranking model disabled": "Uudelleenpisteytysmalli poistettu käytöstä",
"Reranking model set to \"{{reranking_model}}\"": "\"{{reranking_model}}\" valittu uudelleenpisteytysmalliksi",
"Reset Upload Directory": "",
"Reset Vector Storage": "Tyhjennä vektorivarasto",
"Response AutoCopy to Clipboard": "Vastauksen automaattikopiointi leikepöydälle",
"Role": "Rooli",
"Rosé Pine": "Rosee-mänty",
"Rosé Pine Dawn": "Aamuinen Rosee-mänty",
"RTL": "RTL",
"Running": "",
"Save": "Tallenna",
"Save & Create": "Tallenna ja luo",
"Save & Update": "Tallenna ja päivitä",
@@ -397,6 +416,8 @@
"Search Documents": "Hae asiakirjoja",
"Search Models": "Hae malleja",
"Search Prompts": "Hae kehotteita",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Hakutulosten määrä",
"Searched {{count}} sites_one": "Haettu {{count}} sites_one",
"Searched {{count}} sites_other": "Haku {{count}} sites_other",
@@ -406,12 +427,14 @@
"See what's new": "Katso, mitä uutta",
"Seed": "Siemen",
"Select a base model": "Valitse perusmalli",
"Select a engine": "",
"Select a mode": "Valitse tila",
"Select a model": "Valitse malli",
"Select a pipeline": "Valitse putki",
"Select a pipeline url": "Valitse putken URL-osoite",
"Select an Ollama instance": "Valitse Ollama-instanssi",
"Select model": "Valitse malli",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Valitut mallit eivät tue kuvasyötteitä",
"Send": "Lähetä",
"Send a Message": "Lähetä viesti",
@@ -424,7 +447,6 @@
"Set Default Model": "Aseta oletusmalli",
"Set embedding model (e.g. {{model}})": "Aseta upotusmalli (esim. {{model}})",
"Set Image Size": "Aseta kuvan koko",
"Set Model": "Aseta malli",
"Set reranking model (e.g. {{model}})": "Aseta uudelleenpisteytysmalli (esim. {{model}})",
"Set Steps": "Aseta askelmäärä",
"Set Task Model": "Aseta tehtävämalli",
@@ -448,8 +470,8 @@
"Source": "Lähde",
"Speech recognition error: {{error}}": "Puheentunnistusvirhe: {{error}}",
"Speech-to-Text Engine": "Puheentunnistusmoottori",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition-rajapinta ei ole tuettu tässä selaimessa.",
"Stop Sequence": "Lopetussekvenssi",
"STT Model": "",
"STT Settings": "Puheentunnistusasetukset",
"Submit": "Lähetä",
"Subtitle (e.g. about the Roman Empire)": "Alaotsikko (esim. Rooman valtakunnasta)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "Kiitos palautteestasi!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Pisteytyksen tulee olla arvo välillä 0.0 (0%) ja 1.0 (100%).",
"Theme": "Teema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Tämä varmistaa, että arvokkaat keskustelusi tallennetaan turvallisesti backend-tietokantaasi. Kiitos!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Tämä asetus ei synkronoidu selainten tai laitteiden välillä.",
"Thorough explanation": "Perusteellinen selitys",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Vinkki: Päivitä useita muuttujapaikkoja peräkkäin painamalla tabulaattoria keskustelusyötteessä jokaisen korvauksen jälkeen.",
@@ -480,6 +504,7 @@
"to": "->",
"To access the available model names for downloading,": "Päästäksesi käsiksi ladattavissa oleviin mallinimiin,",
"To access the GGUF models available for downloading,": "Päästäksesi käsiksi ladattavissa oleviin GGUF-malleihin,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "keskustelusyötteeseen.",
"Today": "Tänään",
"Toggle settings": "Kytke asetukset",
@@ -487,7 +512,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Ongelmia Ollama-yhteydessä?",
"TTS Model": "",
"TTS Settings": "Puheentuottamisasetukset",
"TTS Voice": "",
"Type": "Tyyppi",
"Type Hugging Face Resolve (Download) URL": "Kirjoita Hugging Face -resolve-osoite",
"Uh-oh! There was an issue connecting to {{provider}}.": "Voi ei! Yhteysongelma {{provider}}:n kanssa.",
@@ -496,6 +523,7 @@
"Update password": "Päivitä salasana",
"Upload a GGUF model": "Lataa GGUF-malli",
"Upload Files": "Lataa tiedostoja",
"Upload Pipeline": "",
"Upload Progress": "Latauksen eteneminen",
"URL Mode": "URL-tila",
"Use '#' in the prompt input to load and select your documents.": "Käytä '#' syötteessä ladataksesi ja valitaksesi asiakirjoja.",
@@ -514,6 +542,7 @@
"Warning": "Varoitus",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Varoitus: Jos päivität tai vaihdat upotusmallia, sinun on tuotava kaikki asiakirjat uudelleen.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Web Loader asetukset",
"Web Params": "Web-parametrit",
"Web Search": "Web-haku",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI tekee pyyntöjä",
"Whats New in": "Mitä uutta",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Kun historia on pois päältä, uudet keskustelut tässä selaimessa eivät näy historiassasi millään laitteellasi.",
"Whisper (Local)": "Whisper (paikallinen)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Työtilat",
"Write a prompt suggestion (e.g. Who are you?)": "Kirjoita ehdotettu kehote (esim. Kuka olet?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Kirjoita 50 sanan yhteenveto, joka tiivistää [aihe tai avainsana].",
"Yesterday": "Eilen",
"You": "Sinä",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Perusmallia ei voi kloonata",
"You have no archived conversations.": "Sinulla ei ole arkistoituja keskusteluja.",
"You have shared this chat": "Olet jakanut tämän keskustelun",
"You're a helpful assistant.": "Olet avulias apulainen.",
"You're now logged in.": "Olet nyt kirjautunut sisään.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Youtube Loader-asetukset"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "un utilisateur",
"About": "À propos",
"Account": "Compte",
"Account Activation Pending": "",
"Accurate information": "Information précise",
"Active Users": "",
"Add": "Ajouter",
"Add a model id": "Ajouter un id de modèle",
"Add a short description about what this model does": "Ajoutez une brève description de ce que fait ce modèle",
@@ -28,6 +30,7 @@
"Add User": "Ajouter un utilisateur",
"Adjusting these settings will apply changes universally to all users.": "L'ajustement de ces paramètres appliquera les changements à tous les utilisateurs.",
"admin": "Administrateur",
"Admin": "",
"Admin Panel": "Panneau d'administration",
"Admin Settings": "Paramètres d'administration",
"Advanced Parameters": "Paramètres avancés",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "Août",
"Auto-playback response": "Réponse en lecture automatique",
"Auto-send input after 3 sec.": "Envoyer automatiquement l'entrée après 3 sec.",
"AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL de base AUTOMATIC1111 est requise.",
"available!": "disponible !",
@@ -70,6 +72,9 @@
"Being lazy": "En manque de temps",
"Brave Search API Key": "Clé dAPI de recherche brave",
"Bypass SSL verification for Websites": "Parcourir la vérification SSL pour les sites Web",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Annuler",
"Capabilities": "Capacités",
"Change Password": "Changer le mot de passe",
@@ -87,10 +92,12 @@
"Chunk Params": "Paramètres de bloc",
"Chunk Size": "Taille de bloc",
"Citation": "Citations",
"Clear memory": "",
"Click here for help.": "Cliquez ici pour de l'aide.",
"Click here to": "Cliquez ici pour",
"Click here to select": "Cliquez ici pour sélectionner",
"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "Cliquez ici pour sélectionner des documents.",
"click here.": "cliquez ici.",
"Click on the user role button to change a user's role.": "Cliquez sur le bouton de rôle d'utilisateur pour changer le rôle d'un utilisateur.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Demandes simultanées",
"Confirm Password": "Confirmer le mot de passe",
"Connections": "Connexions",
"Contact Admin for WebUI Access": "",
"Content": "Contenu",
"Context Length": "Longueur du contexte",
"Continue Response": "Continuer la réponse",
"Conversation Mode": "Mode de conversation",
"Copied shared chat URL to clipboard!": "URL de chat partagé copié dans le presse-papier !",
"Copy": "Copier",
"Copy last code block": "Copier le dernier bloc de code",
"Copy last response": "Copier la dernière réponse",
"Copy Link": "Copier le lien",
"Copying to clipboard was successful!": "La copie dans le presse-papiers a réussi !",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Créez une phrase concise de 3 à 5 mots comme en-tête pour la requête suivante, en respectant strictement la limite de 3 à 5 mots et en évitant l'utilisation du mot 'titre' :",
"Create a model": "Créer un modèle",
"Create Account": "Créer un compte",
"Create new key": "Créer une nouvelle clé",
@@ -126,12 +132,12 @@
"Custom": "Personnalisé",
"Customize models for a specific purpose": "Personnaliser les modèles dans un but spécifique",
"Dark": "Sombre",
"Dashboard": "",
"Database": "Base de données",
"December": "Décembre",
"Default": "Par défaut",
"Default (Automatic1111)": "Par défaut (Automatic1111)",
"Default (SentenceTransformers)": "Par défaut (SentenceTransformers)",
"Default (Web API)": "Par défaut (API Web)",
"Default Model": "Modèle par défaut",
"Default model updated": "Modèle par défaut mis à jour",
"Default Prompt Suggestions": "Suggestions de prompt par défaut",
@@ -152,6 +158,7 @@
"Discover a prompt": "Découvrir un prompt",
"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
"Dismissible": "",
"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans la Discussion",
"Document": "Document",
"Document Settings": "Paramètres du document",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Exporter le mappage des documents",
"Export Models": "Modèles dexportation",
"Export Prompts": "Exporter les prompts",
"External Models": "",
"Failed to create API Key.": "Impossible de créer la clé API.",
"Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Suivi des instructions parfaitement",
"Format your variables using square brackets like this:": "Formatez vos variables en utilisant des crochets comme ceci :",
"Frequency Penalty": "Pénalité de fréquence",
"Full Screen Mode": "Mode plein écran",
"General": "Général",
"General Settings": "Paramètres généraux",
"Generate Image": "",
"Generating search query": "Génération dune requête de recherche",
"Generation Info": "Informations de génération",
"Good Response": "Bonne réponse",
@@ -252,6 +260,7 @@
"Info": "Linfo",
"Input commands": "Entrez des commandes d'entrée",
"Install from Github URL": "Installer à partir de lURL Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interface",
"Invalid Tag": "Tag invalide",
"January": "Janvier",
@@ -264,14 +273,17 @@
"JWT Token": "Jeton JWT",
"Keep Alive": "Garder actif",
"Keyboard shortcuts": "Raccourcis clavier",
"Knowledge": "",
"Language": "Langue",
"Last Active": "Dernière activité",
"Light": "Lumière",
"Listening...": "Écoute...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Les LLMs peuvent faire des erreurs. Vérifiez les informations importantes.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
"Make sure to enclose them with": "Assurez-vous de les entourer avec",
"Manage": "",
"Manage Models": "Gérer les modèles",
"Manage Ollama Models": "Gérer les modèles Ollama",
"Manage Pipelines": "Gérer les pipelines",
@@ -307,6 +319,7 @@
"Name your model": "Nommez votre modèle",
"New Chat": "Nouvelle discussion",
"New Password": "Nouveau mot de passe",
"No documents found": "",
"No results found": "Aucun résultat trouvé",
"No search query generated": "Aucune requête de recherche générée",
"No source available": "Aucune source disponible",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "API Ollama désactivée",
"Ollama API is disabled": "",
"Ollama Version": "Version Ollama",
"On": "Activé",
"Only": "Seulement",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "Document PDF (.pdf)",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
"Personalization": "Personnalisation",
"Pipelines": "Pipelines",
@@ -367,6 +383,7 @@
"Read Aloud": "Lire à l'échelle",
"Record voice": "Enregistrer la voix",
"Redirecting you to OpenWebUI Community": "Vous redirige vers la communauté OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Refusé quand il ne devrait pas l'être",
"Regenerate": "Régénérer",
"Release Notes": "Notes de version",
@@ -378,12 +395,14 @@
"Reranking Model": "Modèle de reranking",
"Reranking model disabled": "Modèle de reranking désactivé",
"Reranking model set to \"{{reranking_model}}\"": "Modèle de reranking défini sur \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Réinitialiser le stockage vectoriel",
"Response AutoCopy to Clipboard": "Copie automatique de la réponse vers le presse-papiers",
"Role": "Rôle",
"Rosé Pine": "Pin Rosé",
"Rosé Pine Dawn": "Aube Pin Rosé",
"RTL": "RTL",
"Running": "",
"Save": "Enregistrer",
"Save & Create": "Enregistrer & Créer",
"Save & Update": "Enregistrer & Mettre à jour",
@@ -397,6 +416,8 @@
"Search Documents": "Rechercher des documents",
"Search Models": "Modèles de recherche",
"Search Prompts": "Rechercher des prompts",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Nombre de résultats de la recherche",
"Searched {{count}} sites_one": "Recherche dans {{count}} sites_one",
"Searched {{count}} sites_many": "Recherche dans {{count}} sites_many",
@@ -407,12 +428,14 @@
"See what's new": "Voir les nouveautés",
"Seed": "Graine",
"Select a base model": "Sélectionner un modèle de base",
"Select a engine": "",
"Select a mode": "Sélectionnez un mode",
"Select a model": "Sélectionnez un modèle",
"Select a pipeline": "Sélectionner un pipeline",
"Select a pipeline url": "Sélectionnez une URL de pipeline",
"Select an Ollama instance": "Sélectionner une instance Ollama",
"Select model": "Sélectionnez un modèle",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Les modèles sélectionnés ne prennent pas en charge les entrées dimage",
"Send": "Envoyer",
"Send a Message": "Envoyer un message",
@@ -425,7 +448,6 @@
"Set Default Model": "Définir le modèle par défaut",
"Set embedding model (e.g. {{model}})": "Définir le modèle d'embedding (par exemple {{model}})",
"Set Image Size": "Définir la taille de l'image",
"Set Model": "Configurer le modèle",
"Set reranking model (e.g. {{model}})": "Définir le modèle de reranking (par exemple {{model}})",
"Set Steps": "Définir les étapes",
"Set Task Model": "Définir le modèle de tâche",
@@ -449,8 +471,8 @@
"Source": "Source",
"Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}",
"Speech-to-Text Engine": "Moteur reconnaissance vocale",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition n'est pas prise en charge dans ce navigateur.",
"Stop Sequence": "Séquence d'arrêt",
"STT Model": "",
"STT Settings": "Paramètres de STT",
"Submit": "Soumettre",
"Subtitle (e.g. about the Roman Empire)": "Sous-titre (par exemple, sur l'empire romain)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "Merci pour votre feedback!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Le score doit être une valeur entre 0.0 (0%) et 1.0 (100%).",
"Theme": "Thème",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cela garantit que vos précieuses conversations sont enregistrées en toute sécurité dans votre base de données backend. Merci !",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Ce réglage ne se synchronise pas entre les navigateurs ou les appareils.",
"Thorough explanation": "Explication approfondie",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Astuce : Mettez à jour plusieurs emplacements de variables consécutivement en appuyant sur la touche tabulation dans l'entrée de chat après chaque remplacement.",
@@ -481,6 +505,7 @@
"to": "à",
"To access the available model names for downloading,": "Pour accéder aux noms de modèles disponibles pour le téléchargement,",
"To access the GGUF models available for downloading,": "Pour accéder aux modèles GGUF disponibles pour le téléchargement,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "à l'entrée du chat.",
"Today": "Aujourd'hui",
"Toggle settings": "Basculer les paramètres",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Des problèmes pour accéder à Ollama ?",
"TTS Model": "",
"TTS Settings": "Paramètres TTS",
"TTS Voice": "",
"Type": "Type",
"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de résolution (téléchargement) Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Mettre à jour le mot de passe",
"Upload a GGUF model": "Téléverser un modèle GGUF",
"Upload Files": "Télécharger des fichiers",
"Upload Pipeline": "",
"Upload Progress": "Progression du Téléversement",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilisez '#' dans l'entrée de prompt pour charger et sélectionner vos documents.",
@@ -515,6 +543,7 @@
"Warning": "Avertissement",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Attention : Si vous mettez à jour ou changez votre modèle d'intégration, vous devrez réimporter tous les documents.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Paramètres du chargeur Web",
"Web Params": "Paramètres Web",
"Web Search": "Recherche sur le Web",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI effectuera des demandes à",
"Whats New in": "Quoi de neuf dans",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Lorsque l'historique est désactivé, les nouvelles discussions sur ce navigateur n'apparaîtront pas dans votre historique sur aucun de vos appareils.",
"Whisper (Local)": "Whisper (Local)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Espace de travail",
"Write a prompt suggestion (e.g. Who are you?)": "Rédigez une suggestion de prompt (p. ex. Qui êtes-vous ?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Rédigez un résumé en 50 mots qui résume [sujet ou mot-clé].",
"Yesterday": "hier",
"You": "Vous",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Vous ne pouvez pas cloner un modèle de base",
"You have no archived conversations.": "Vous n'avez aucune conversation archivée.",
"You have shared this chat": "Vous avez partagé cette conversation",
"You're a helpful assistant.": "Vous êtes un assistant utile",
"You're now logged in.": "Vous êtes maintenant connecté.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Paramètres du chargeur Youtube"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "un utilisateur",
"About": "À Propos",
"Account": "Compte",
"Account Activation Pending": "",
"Accurate information": "Information précise",
"Active Users": "",
"Add": "Ajouter",
"Add a model id": "Ajouter un identifiant modèle",
"Add a short description about what this model does": "Ajouter une courte description de ce que fait ce modèle",
@@ -28,6 +30,7 @@
"Add User": "Ajouter un Utilisateur",
"Adjusting these settings will apply changes universally to all users.": "L'ajustement de ces paramètres appliquera les changements à tous les utilisateurs.",
"admin": "admin",
"Admin": "",
"Admin Panel": "Panneau d'Administration",
"Admin Settings": "Paramètres d'Administration",
"Advanced Parameters": "Paramètres Avancés",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "Août",
"Auto-playback response": "Réponse en lecture automatique",
"Auto-send input after 3 sec.": "Envoyer automatiquement l'entrée après 3 sec.",
"AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL de base AUTOMATIC1111 est requise.",
"available!": "disponible !",
@@ -70,6 +72,9 @@
"Being lazy": "Est paresseux",
"Brave Search API Key": "Clé API Brave Search",
"Bypass SSL verification for Websites": "Contourner la vérification SSL pour les sites Web.",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Annuler",
"Capabilities": "Capacités",
"Change Password": "Changer le mot de passe",
@@ -87,10 +92,12 @@
"Chunk Params": "Paramètres de bloc",
"Chunk Size": "Taille de bloc",
"Citation": "Citation",
"Clear memory": "",
"Click here for help.": "Cliquez ici pour de l'aide.",
"Click here to": "Cliquez ici pour",
"Click here to select": "Cliquez ici pour sélectionner",
"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "Cliquez ici pour sélectionner des documents.",
"click here.": "cliquez ici.",
"Click on the user role button to change a user's role.": "Cliquez sur le bouton de rôle d'utilisateur pour changer le rôle d'un utilisateur.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Demandes simultanées",
"Confirm Password": "Confirmer le mot de passe",
"Connections": "Connexions",
"Contact Admin for WebUI Access": "",
"Content": "Contenu",
"Context Length": "Longueur du contexte",
"Continue Response": "Continuer la Réponse",
"Conversation Mode": "Mode de conversation",
"Copied shared chat URL to clipboard!": "URL du chat copié dans le presse-papiers !",
"Copy": "Copier",
"Copy last code block": "Copier le dernier bloc de code",
"Copy last response": "Copier la dernière réponse",
"Copy Link": "Copier le Lien",
"Copying to clipboard was successful!": "La copie dans le presse-papiers a réussi !",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Créez une phrase concise de 3-5 mots comme en-tête pour la requête suivante, en respectant strictement la limite de 3-5 mots et en évitant l'utilisation du mot 'titre' :",
"Create a model": "Créer un modèle",
"Create Account": "Créer un compte",
"Create new key": "Créer une nouvelle clé",
@@ -126,12 +132,12 @@
"Custom": "Personnalisé",
"Customize models for a specific purpose": "Personnaliser les modèles pour un objectif spécifique",
"Dark": "Sombre",
"Dashboard": "",
"Database": "Base de données",
"December": "Décembre",
"Default": "Par défaut",
"Default (Automatic1111)": "Par défaut (Automatic1111)",
"Default (SentenceTransformers)": "Par défaut (SentenceTransformers)",
"Default (Web API)": "Par défaut (API Web)",
"Default Model": "Modèle par défaut",
"Default model updated": "Modèle par défaut mis à jour",
"Default Prompt Suggestions": "Suggestions de prompt par défaut",
@@ -152,6 +158,7 @@
"Discover a prompt": "Découvrir un prompt",
"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
"Dismissible": "",
"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans le Chat",
"Document": "Document",
"Document Settings": "Paramètres du document",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Exporter la Correspondance des Documents",
"Export Models": "Exporter les Modèles",
"Export Prompts": "Exporter les Prompts",
"External Models": "",
"Failed to create API Key.": "Échec de la création de la clé d'API.",
"Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "A suivi les instructions parfaitement",
"Format your variables using square brackets like this:": "Formatez vos variables en utilisant des crochets comme ceci :",
"Frequency Penalty": "Pénalité de fréquence",
"Full Screen Mode": "Mode plein écran",
"General": "Général",
"General Settings": "Paramètres Généraux",
"Generate Image": "",
"Generating search query": "Génération dune requête de recherche",
"Generation Info": "Informations de la Génération",
"Good Response": "Bonne Réponse",
@@ -252,6 +260,7 @@
"Info": "Info",
"Input commands": "Entrez les commandes d'entrée",
"Install from Github URL": "Installer à partir de lURL Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interface",
"Invalid Tag": "Tag Invalide",
"January": "Janvier",
@@ -264,14 +273,17 @@
"JWT Token": "Jeton JWT",
"Keep Alive": "Rester en vie",
"Keyboard shortcuts": "Raccourcis clavier",
"Knowledge": "",
"Language": "Langue",
"Last Active": "Dernier Activité",
"Light": "Clair",
"Listening...": "Écoute...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Les LLMs peuvent faire des erreurs. Vérifiez les informations importantes.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
"Make sure to enclose them with": "Assurez-vous de les entourer avec",
"Manage": "",
"Manage Models": "Gérer les modèles",
"Manage Ollama Models": "Gérer les modèles Ollama",
"Manage Pipelines": "Gérer les pipelines",
@@ -307,6 +319,7 @@
"Name your model": "Nommez votre modèle",
"New Chat": "Nouveau chat",
"New Password": "Nouveau mot de passe",
"No documents found": "",
"No results found": "Aucun résultat",
"No search query generated": "Aucune requête de recherche générée",
"No source available": "Aucune source disponible",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "API Ollama",
"Ollama API disabled": "API Ollama désactivée",
"Ollama API is disabled": "",
"Ollama Version": "Version Ollama",
"On": "Activé",
"Only": "Seulement",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "Document PDF (.pdf)",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
"Personalization": "Personnalisation",
"Pipelines": "Pipelines",
@@ -367,6 +383,7 @@
"Read Aloud": "Lire à Voix Haute",
"Record voice": "Enregistrer la voix",
"Redirecting you to OpenWebUI Community": "Redirection vers la communauté OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Refuse quand il ne devrait pas",
"Regenerate": "Regénérer",
"Release Notes": "Notes de Version",
@@ -378,12 +395,14 @@
"Reranking Model": "Modèle de Reclassement",
"Reranking model disabled": "Modèle de Reclassement Désactivé",
"Reranking model set to \"{{reranking_model}}\"": "Modèle de reclassement défini sur \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Réinitialiser le Stockage de Vecteur",
"Response AutoCopy to Clipboard": "Copie Automatique de la Réponse dans le Presse-papiers",
"Role": "Rôle",
"Rosé Pine": "Pin Rosé",
"Rosé Pine Dawn": "Aube Pin Rosé",
"RTL": "RTL",
"Running": "",
"Save": "Enregistrer",
"Save & Create": "Enregistrer & Créer",
"Save & Update": "Enregistrer & Mettre à jour",
@@ -397,6 +416,8 @@
"Search Documents": "Rechercher des Documents",
"Search Models": "Rechercher des modèles",
"Search Prompts": "Rechercher des Prompts",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Nombre de résultats de recherche",
"Searched {{count}} sites_one": "Recherché {{count}} sites_one",
"Searched {{count}} sites_many": "Recherché {{count}} sites_many",
@@ -407,12 +428,14 @@
"See what's new": "Voir les nouveautés",
"Seed": "Graine",
"Select a base model": "Sélectionner un modèle de base",
"Select a engine": "",
"Select a mode": "Sélectionner un mode",
"Select a model": "Sélectionner un modèle",
"Select a pipeline": "Sélectionner un pipeline",
"Select a pipeline url": "Sélectionnez une URL de pipeline",
"Select an Ollama instance": "Sélectionner une instance Ollama",
"Select model": "Sélectionner un modèle",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Modèle(s) séléctionés ne supportent pas les entrées images",
"Send": "Envoyer",
"Send a Message": "Envoyer un message",
@@ -425,7 +448,6 @@
"Set Default Model": "Définir le Modèle par Défaut",
"Set embedding model (e.g. {{model}})": "Définir le modèle d'embedding (p. ex. {{model}})",
"Set Image Size": "Définir la Taille de l'Image",
"Set Model": "Définir le Modèle",
"Set reranking model (e.g. {{model}})": "Définir le modèle de reclassement (p. ex. {{model}})",
"Set Steps": "Définir les Étapes",
"Set Task Model": "Définir le modèle de tâche",
@@ -449,8 +471,8 @@
"Source": "Source",
"Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}",
"Speech-to-Text Engine": "Moteur de Reconnaissance Vocale",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition n'est pas prise en charge dans ce navigateur.",
"Stop Sequence": "Séquence d'Arrêt",
"STT Model": "",
"STT Settings": "Paramètres STT",
"Submit": "Envoyer",
"Subtitle (e.g. about the Roman Empire)": "Sous-Titres (p. ex. à propos de l'Empire Romain)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "Merci pour votre avis !",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Le score devrait avoir une valeur entre 0.0 (0%) et 1.0 (100%).",
"Theme": "Thème",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cela garantit que vos précieuses conversations sont en sécurité dans votre base de données. Merci !",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Ce paramètre ne se synchronise pas entre les navigateurs ou les appareils.",
"Thorough explanation": "Explication détaillée",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Conseil : Mettez à jour plusieurs emplacements de variables consécutivement en appuyant sur la touche tab dans l'entrée de chat après chaque remplacement",
@@ -481,6 +505,7 @@
"to": "à",
"To access the available model names for downloading,": "Pour accéder aux noms de modèles disponibles pour le téléchargement,",
"To access the GGUF models available for downloading,": "Pour accéder aux modèles GGUF disponibles pour le téléchargement,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "à l'entrée du chat.",
"Today": "Aujourd'hui",
"Toggle settings": "Basculer les paramètres",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problèmes d'accès à Ollama ?",
"TTS Model": "",
"TTS Settings": "Paramètres TTS",
"TTS Voice": "",
"Type": "Type",
"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de Résolution (Téléchargement) Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Mettre à Jour le Mot de Passe",
"Upload a GGUF model": "Téléverser un modèle GGUF",
"Upload Files": "Télécharger des fichiers",
"Upload Pipeline": "",
"Upload Progress": "Progression du Téléversement",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilisez '#' dans l'entrée du prompt pour charger et sélectionner vos documents.",
@@ -515,6 +543,7 @@
"Warning": "Avertissement",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avertissement : Si vous mettez à jour ou modifier votre modèle d'embedding, vous devrez réimporter tous les documents.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Paramètres du Chargeur Web",
"Web Params": "Paramètres Web",
"Web Search": "Recherche sur le Web",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI effectuera des demandes à",
"Whats New in": "Quoi de neuf dans",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Lorsque l'historique est désactivé, les nouveaux chats sur ce navigateur n'apparaîtront pas dans votre historique sur aucun de vos appareils.",
"Whisper (Local)": "Whisper (Local)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Espace de Travail",
"Write a prompt suggestion (e.g. Who are you?)": "Écrivez une suggestion de prompt (e.x. Qui est-tu ?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Ecrivez un résumé en 50 mots qui résume [sujet ou mot-clé]",
"Yesterday": "Hier",
"You": "Vous",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Vous ne pouvez pas cloner un modèle de base",
"You have no archived conversations.": "Vous n'avez pas de conversations archivées",
"You have shared this chat": "Vous avez partagé ce chat",
"You're a helpful assistant.": "Vous êtes un assistant utile.",
"You're now logged in.": "Vous êtes maintenant connecté.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Paramètres du Chargeur YouTube"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "משתמש",
"About": "אודות",
"Account": "חשבון",
"Account Activation Pending": "",
"Accurate information": "מידע מדויק",
"Active Users": "",
"Add": "הוסף",
"Add a model id": "הוספת מזהה דגם",
"Add a short description about what this model does": "הוסף תיאור קצר אודות אופן הפעולה של מודל זה",
@@ -28,6 +30,7 @@
"Add User": "הוסף משתמש",
"Adjusting these settings will apply changes universally to all users.": "התאמת הגדרות אלו תחול על כל המשתמשים.",
"admin": "מנהל",
"Admin": "",
"Admin Panel": "לוח בקרה למנהל",
"Admin Settings": "הגדרות מנהל",
"Advanced Parameters": "פרמטרים מתקדמים",
@@ -58,7 +61,6 @@
"Audio": "אודיו",
"August": "אוגוסט",
"Auto-playback response": "תגובת השמעה אוטומטית",
"Auto-send input after 3 sec.": "שליחת קלט אוטומטית אחרי 3 שניות",
"AUTOMATIC1111 Base URL": "כתובת URL בסיסית של AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "נדרשת כתובת URL בסיסית של AUTOMATIC1111",
"available!": "זמין!",
@@ -70,6 +72,9 @@
"Being lazy": "להיות עצלן",
"Brave Search API Key": "מפתח API של חיפוש אמיץ",
"Bypass SSL verification for Websites": "עקוף אימות SSL עבור אתרים",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "בטל",
"Capabilities": "יכולות",
"Change Password": "שנה סיסמה",
@@ -87,10 +92,12 @@
"Chunk Params": "פרמטרי נתונים",
"Chunk Size": "גודל נתונים",
"Citation": "ציטוט",
"Clear memory": "",
"Click here for help.": "לחץ כאן לעזרה.",
"Click here to": "לחץ כאן כדי",
"Click here to select": "לחץ כאן לבחירה",
"Click here to select a csv file.": "לחץ כאן לבחירת קובץ csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "לחץ כאן לבחירת מסמכים.",
"click here.": "לחץ כאן.",
"Click on the user role button to change a user's role.": "לחץ על כפתור תפקיד המשתמש כדי לשנות את תפקיד המשתמש.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "בקשות בו-זמניות",
"Confirm Password": "אשר סיסמה",
"Connections": "חיבורים",
"Contact Admin for WebUI Access": "",
"Content": "תוכן",
"Context Length": "אורך הקשר",
"Continue Response": "המשך תגובה",
"Conversation Mode": "מצב שיחה",
"Copied shared chat URL to clipboard!": "העתקת כתובת URL של צ'אט משותף ללוח!",
"Copy": "העתק",
"Copy last code block": "העתק את בלוק הקוד האחרון",
"Copy last response": "העתק את התגובה האחרונה",
"Copy Link": "העתק קישור",
"Copying to clipboard was successful!": "ההעתקה ללוח הייתה מוצלחת!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "צור ביטוי תמציתי של 3-5 מילים ככותרת לשאילתה הבאה, תוך שמירה מדויקת על מגבלת 3-5 המילים והימנעות משימוש במילה 'כותרת':",
"Create a model": "יצירת מודל",
"Create Account": "צור חשבון",
"Create new key": "צור מפתח חדש",
@@ -126,12 +132,12 @@
"Custom": "מותאם אישית",
"Customize models for a specific purpose": "התאמה אישית של מודלים למטרה ספציפית",
"Dark": "כהה",
"Dashboard": "",
"Database": "מסד נתונים",
"December": "דצמבר",
"Default": "ברירת מחדל",
"Default (Automatic1111)": "ברירת מחדל (Automatic1111)",
"Default (SentenceTransformers)": "ברירת מחדל (SentenceTransformers)",
"Default (Web API)": "ברירת מחדל (Web API)",
"Default Model": "מודל ברירת מחדל",
"Default model updated": "המודל המוגדר כברירת מחדל עודכן",
"Default Prompt Suggestions": "הצעות ברירת מחדל לפקודות",
@@ -152,6 +158,7 @@
"Discover a prompt": "גלה פקודה",
"Discover, download, and explore custom prompts": "גלה, הורד, וחקור פקודות מותאמות אישית",
"Discover, download, and explore model presets": "גלה, הורד, וחקור הגדרות מודל מוגדרות מראש",
"Dismissible": "",
"Display the username instead of You in the Chat": "הצג את שם המשתמש במקום 'אתה' בצ'אט",
"Document": "מסמך",
"Document Settings": "הגדרות מסמך",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "ייצוא מיפוי מסמכים",
"Export Models": "ייצוא מודלים",
"Export Prompts": "ייצוא פקודות",
"External Models": "",
"Failed to create API Key.": "יצירת מפתח API נכשלה.",
"Failed to read clipboard contents": "קריאת תוכן הלוח נכשלה",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "עקב אחר ההוראות במושלמות",
"Format your variables using square brackets like this:": "עצב את המשתנים שלך באמצעות סוגריים מרובעים כך:",
"Frequency Penalty": "עונש תדירות",
"Full Screen Mode": "מצב מסך מלא",
"General": "כללי",
"General Settings": "הגדרות כלליות",
"Generate Image": "",
"Generating search query": "יצירת שאילתת חיפוש",
"Generation Info": "מידע על היצירה",
"Good Response": "תגובה טובה",
@@ -252,6 +260,7 @@
"Info": "מידע",
"Input commands": "פקודות קלט",
"Install from Github URL": "התקן מכתובת URL של Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "ממשק",
"Invalid Tag": "תג לא חוקי",
"January": "ינואר",
@@ -264,14 +273,17 @@
"JWT Token": "אסימון JWT",
"Keep Alive": "השאר פעיל",
"Keyboard shortcuts": "קיצורי מקלדת",
"Knowledge": "",
"Language": "שפה",
"Last Active": "פעיל לאחרונה",
"Light": "בהיר",
"Listening...": "מאזין...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "מודלים בשפה טבעית יכולים לטעות. אמת מידע חשוב.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "נוצר על ידי קהילת OpenWebUI",
"Make sure to enclose them with": "ודא להקיף אותם עם",
"Manage": "",
"Manage Models": "נהל מודלים",
"Manage Ollama Models": "נהל מודלים של Ollama",
"Manage Pipelines": "ניהול צינורות",
@@ -307,6 +319,7 @@
"Name your model": "תן שם לדגם שלך",
"New Chat": "צ'אט חדש",
"New Password": "סיסמה חדשה",
"No documents found": "",
"No results found": "לא נמצאו תוצאות",
"No search query generated": "לא נוצרה שאילתת חיפוש",
"No source available": "אין מקור זמין",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API מושבת",
"Ollama API is disabled": "",
"Ollama Version": "גרסת Ollama",
"On": "פועל",
"Only": "רק",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "מסמך PDF (.pdf)",
"PDF Extract Images (OCR)": "חילוץ תמונות מ-PDF (OCR)",
"pending": "ממתין",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "ההרשאה נדחתה בעת גישה למיקרופון: {{error}}",
"Personalization": "תאור",
"Pipelines": "צינורות",
@@ -367,6 +383,7 @@
"Read Aloud": "קרא בקול",
"Record voice": "הקלט קול",
"Redirecting you to OpenWebUI Community": "מפנה אותך לקהילת OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "נדחה כאשר לא היה צריך",
"Regenerate": "הפק מחדש",
"Release Notes": "הערות שחרור",
@@ -378,12 +395,14 @@
"Reranking Model": "מודל דירוג מחדש",
"Reranking model disabled": "מודל דירוג מחדש מושבת",
"Reranking model set to \"{{reranking_model}}\"": "מודל דירוג מחדש הוגדר ל-\"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "איפוס אחסון וקטורים",
"Response AutoCopy to Clipboard": "העתקה אוטומטית של תגובה ללוח",
"Role": "תפקיד",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "שמור",
"Save & Create": "שמור וצור",
"Save & Update": "שמור ועדכן",
@@ -397,6 +416,8 @@
"Search Documents": "חפש מסמכים",
"Search Models": "חיפוש מודלים",
"Search Prompts": "חפש פקודות",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "ספירת תוצאות חיפוש",
"Searched {{count}} sites_one": "חיפש {{count}} sites_one",
"Searched {{count}} sites_two": "חיפש {{count}} sites_two",
@@ -407,12 +428,14 @@
"See what's new": "ראה מה חדש",
"Seed": "זרע",
"Select a base model": "בחירת מודל בסיס",
"Select a engine": "",
"Select a mode": "בחר מצב",
"Select a model": "בחר מודל",
"Select a pipeline": "בחר קו צינור",
"Select a pipeline url": "בחר כתובת URL של קו צינור",
"Select an Ollama instance": "בחר מופע של Ollama",
"Select model": "בחר מודל",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "דגמים נבחרים אינם תומכים בקלט תמונה",
"Send": "שלח",
"Send a Message": "שלח הודעה",
@@ -425,7 +448,6 @@
"Set Default Model": "הגדר מודל ברירת מחדל",
"Set embedding model (e.g. {{model}})": "הגדר מודל הטמעה (למשל {{model}})",
"Set Image Size": "הגדר גודל תמונה",
"Set Model": "הגדר מודל",
"Set reranking model (e.g. {{model}})": "הגדר מודל דירוג מחדש (למשל {{model}})",
"Set Steps": "הגדר שלבים",
"Set Task Model": "הגדרת מודל משימה",
@@ -449,8 +471,8 @@
"Source": "מקור",
"Speech recognition error: {{error}}": "שגיאת תחקור שמע: {{error}}",
"Speech-to-Text Engine": "מנוע תחקור שמע",
"SpeechRecognition API is not supported in this browser.": "מנוע תחקור שמע אינו נתמך בדפדפן זה.",
"Stop Sequence": "סידור עצירה",
"STT Model": "",
"STT Settings": "הגדרות חקירה של TTS",
"Submit": "שלח",
"Subtitle (e.g. about the Roman Empire)": "תחקור (לדוגמה: על מעמד הרומי)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "תודה על המשוב שלך!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "ציון צריך להיות ערך בין 0.0 (0%) ל-1.0 (100%)",
"Theme": "נושא",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "פעולה זו מבטיחה שהשיחות בעלות הערך שלך יישמרו באופן מאובטח במסד הנתונים העורפי שלך. תודה!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "הגדרה זו אינה מסתנכרנת בין דפדפנים או מכשירים.",
"Thorough explanation": "תיאור מפורט",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "טיפ: עדכן חריצים משתנים מרובים ברציפות על-ידי לחיצה על מקש Tab בקלט הצ'אט לאחר כל החלפה.",
@@ -481,6 +505,7 @@
"to": "ל",
"To access the available model names for downloading,": "כדי לגשת לשמות הדגמים הזמינים להורדה,",
"To access the GGUF models available for downloading,": "כדי לגשת לדגמי GGUF הזמינים להורדה,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "לקלטת שיחה.",
"Today": "היום",
"Toggle settings": "החלפת מצב של הגדרות",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "קשה לגשת לOllama?",
"TTS Model": "",
"TTS Settings": "הגדרות TTS",
"TTS Voice": "",
"Type": "סוג",
"Type Hugging Face Resolve (Download) URL": "הקלד כתובת URL של פתרון פנים מחבק (הורד)",
"Uh-oh! There was an issue connecting to {{provider}}.": "או-הו! אירעה בעיה בהתחברות ל- {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "עדכן סיסמה",
"Upload a GGUF model": "העלה מודל GGUF",
"Upload Files": "העלאת קבצים",
"Upload Pipeline": "",
"Upload Progress": "תקדמות העלאה",
"URL Mode": "מצב URL",
"Use '#' in the prompt input to load and select your documents.": "השתמש ב- '#' בקלט הבקשה כדי לטעון ולבחור את המסמכים שלך.",
@@ -515,6 +543,7 @@
"Warning": "אזהרה",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "אזהרה: אם תעדכן או תשנה את מודל ההטבעה שלך, יהיה עליך לייבא מחדש את כל המסמכים.",
"Web": "רשת",
"Web API": "",
"Web Loader Settings": "הגדרות טעינת אתר",
"Web Params": "פרמטרים Web",
"Web Search": "חיפוש באינטרנט",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI יבקש לבקש",
"Whats New in": "מה חדש ב",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "כאשר ההיסטוריה מושבתת, צ'אטים חדשים בדפדפן זה לא יופיעו בהיסטוריה שלך באף אחד מהמכשירים שלך.",
"Whisper (Local)": "ושפה (מקומית)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "סביבה",
"Write a prompt suggestion (e.g. Who are you?)": "כתוב הצעה מהירה (למשל, מי אתה?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "כתוב סיכום ב-50 מילים שמסכם [נושא או מילת מפתח].",
"Yesterday": "אתמול",
"You": "אתה",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "לא ניתן לשכפל מודל בסיס",
"You have no archived conversations.": "אין לך שיחות בארכיון.",
"You have shared this chat": "שיתפת את השיחה הזו",
"You're a helpful assistant.": "אתה עוזר מועיל.",
"You're now logged in.": "כעת אתה מחובר.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "הגדרות Youtube Loader"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "एक उपयोगकर्ता",
"About": "हमारे बारे में",
"Account": "खाता",
"Account Activation Pending": "",
"Accurate information": "सटीक जानकारी",
"Active Users": "",
"Add": "जोड़ें",
"Add a model id": "मॉडल आईडी जोड़ना",
"Add a short description about what this model does": "इस मॉडल के बारे में एक संक्षिप्त विवरण जोड़ें",
@@ -28,6 +30,7 @@
"Add User": "उपयोगकर्ता जोड़ें",
"Adjusting these settings will apply changes universally to all users.": "इन सेटिंग्स को समायोजित करने से परिवर्तन सभी उपयोगकर्ताओं पर सार्वभौमिक रूप से लागू होंगे।",
"admin": "व्यवस्थापक",
"Admin": "",
"Admin Panel": "व्यवस्थापक पैनल",
"Admin Settings": "व्यवस्थापक सेटिंग्स",
"Advanced Parameters": "उन्नत पैरामीटर",
@@ -58,7 +61,6 @@
"Audio": "ऑडियो",
"August": "अगस्त",
"Auto-playback response": "ऑटो-प्लेबैक प्रतिक्रिया",
"Auto-send input after 3 sec.": "3 सेकंड के बाद स्वचालित रूप से इनपुट भेजें।",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 बेस यूआरएल",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 का बेस यूआरएल आवश्यक है।",
"available!": "उपलब्ध!",
@@ -70,6 +72,9 @@
"Being lazy": "आलसी होना",
"Brave Search API Key": "Brave सर्च एपीआई कुंजी",
"Bypass SSL verification for Websites": "वेबसाइटों के लिए SSL सुनिश्चिती को छोड़ें",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "रद्द करें",
"Capabilities": "क्षमताओं",
"Change Password": "पासवर्ड बदलें",
@@ -87,10 +92,12 @@
"Chunk Params": "चंक पैरामीटर्स",
"Chunk Size": "चंक आकार",
"Citation": "उद्धरण",
"Clear memory": "",
"Click here for help.": "सहायता के लिए यहां क्लिक करें।",
"Click here to": "यहां क्लिक करें",
"Click here to select": "चयन करने के लिए यहां क्लिक करें।",
"Click here to select a csv file.": "सीएसवी फ़ाइल का चयन करने के लिए यहां क्लिक करें।",
"Click here to select a py file.": "",
"Click here to select documents.": "दस्तावेज़ चुनने के लिए यहां क्लिक करें।",
"click here.": "यहाँ क्लिक करें।",
"Click on the user role button to change a user's role.": "उपयोगकर्ता की भूमिका बदलने के लिए उपयोगकर्ता भूमिका बटन पर क्लिक करें।",
@@ -104,17 +111,16 @@
"Concurrent Requests": "समवर्ती अनुरोध",
"Confirm Password": "पासवर्ड की पुष्टि कीजिये",
"Connections": "सम्बन्ध",
"Contact Admin for WebUI Access": "",
"Content": "सामग्री",
"Context Length": "प्रसंग की लंबाई",
"Continue Response": "प्रतिक्रिया जारी रखें",
"Conversation Mode": "बातचीत का मॉड",
"Copied shared chat URL to clipboard!": "साझा चैट URL को क्लिपबोर्ड पर कॉपी किया गया!",
"Copy": "कॉपी",
"Copy last code block": "अंतिम कोड ब्लॉक कॉपी करें",
"Copy last response": "अंतिम प्रतिक्रिया कॉपी करें",
"Copy Link": "लिंक को कॉपी करें",
"Copying to clipboard was successful!": "क्लिपबोर्ड पर कॉपी बनाना सफल रहा!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "निम्नलिखित क्वेरी के लिए हेडर के रूप में एक संक्षिप्त, 3-5 शब्द वाक्यांश बनाएं, 3-5 शब्द सीमा का सख्ती से पालन करें और 'शीर्षक' शब्द के उपयोग से बचें:",
"Create a model": "एक मॉडल बनाएं",
"Create Account": "खाता बनाएं",
"Create new key": "नया क्रिप्टोग्राफिक क्षेत्र बनाएं",
@@ -126,12 +132,12 @@
"Custom": "कस्टम संस्करण",
"Customize models for a specific purpose": "एक विशिष्ट उद्देश्य के लिए मॉडल अनुकूलित करें",
"Dark": "डार्क",
"Dashboard": "",
"Database": "डेटाबेस",
"December": "डिसेंबर",
"Default": "डिफ़ॉल्ट",
"Default (Automatic1111)": "डिफ़ॉल्ट (Automatic1111)",
"Default (SentenceTransformers)": "डिफ़ॉल्ट (SentenceTransformers)",
"Default (Web API)": "डिफ़ॉल्ट (Web API)",
"Default Model": "डिफ़ॉल्ट मॉडल",
"Default model updated": "डिफ़ॉल्ट मॉडल अपडेट किया गया",
"Default Prompt Suggestions": "डिफ़ॉल्ट प्रॉम्प्ट सुझाव",
@@ -152,6 +158,7 @@
"Discover a prompt": "प्रॉम्प्ट खोजें",
"Discover, download, and explore custom prompts": "कस्टम प्रॉम्प्ट को खोजें, डाउनलोड करें और एक्सप्लोर करें",
"Discover, download, and explore model presets": "मॉडल प्रीसेट खोजें, डाउनलोड करें और एक्सप्लोर करें",
"Dismissible": "",
"Display the username instead of You in the Chat": "चैट में 'आप' के स्थान पर उपयोगकर्ता नाम प्रदर्शित करें",
"Document": "दस्तावेज़",
"Document Settings": "दस्तावेज़ सेटिंग्स",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "निर्यात दस्तावेज़ मैपिंग",
"Export Models": "निर्यात मॉडल",
"Export Prompts": "प्रॉम्प्ट निर्यात करें",
"External Models": "",
"Failed to create API Key.": "एपीआई कुंजी बनाने में विफल.",
"Failed to read clipboard contents": "क्लिपबोर्ड सामग्री पढ़ने में विफल",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "निर्देशों का पूर्णतः पालन किया",
"Format your variables using square brackets like this:": "वर्गाकार कोष्ठकों का उपयोग करके अपने चरों को इस प्रकार प्रारूपित करें :",
"Frequency Penalty": "फ्रीक्वेंसी पेनल्टी",
"Full Screen Mode": "पूर्ण स्क्रीन मोड",
"General": "सामान्य",
"General Settings": "सामान्य सेटिंग्स",
"Generate Image": "",
"Generating search query": "खोज क्वेरी जनरेट करना",
"Generation Info": "जनरेशन की जानकारी",
"Good Response": "अच्छी प्रतिक्रिया",
@@ -252,6 +260,7 @@
"Info": "सूचना-विषयक",
"Input commands": "इनपुट क命",
"Install from Github URL": "Github URL से इंस्टॉल करें",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "इंटरफेस",
"Invalid Tag": "अवैध टैग",
"January": "जनवरी",
@@ -264,14 +273,17 @@
"JWT Token": "जट टोकन",
"Keep Alive": "क्रियाशील रहो",
"Keyboard shortcuts": "कीबोर्ड शॉर्टकट",
"Knowledge": "",
"Language": "भाषा",
"Last Active": "पिछली बार सक्रिय",
"Light": "सुन",
"Listening...": "सुन रहा हूँ...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "एलएलएम गलतियाँ कर सकते हैं। महत्वपूर्ण जानकारी सत्यापित करें.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "OpenWebUI समुदाय द्वारा निर्मित",
"Make sure to enclose them with": "उन्हें संलग्न करना सुनिश्चित करें",
"Manage": "",
"Manage Models": "मॉडल प्रबंधित करें",
"Manage Ollama Models": "Ollama मॉडल प्रबंधित करें",
"Manage Pipelines": "पाइपलाइनों का प्रबंधन करें",
@@ -307,6 +319,7 @@
"Name your model": "अपने मॉडल को नाम दें",
"New Chat": "नई चैट",
"New Password": "नया पासवर्ड",
"No documents found": "",
"No results found": "कोई परिणाम नहीं मिला",
"No search query generated": "कोई खोज क्वेरी जनरेट नहीं हुई",
"No source available": "कोई स्रोत उपलब्ध नहीं है",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "ओलामा एपीआई",
"Ollama API disabled": "ओलामा एपीआई अक्षम",
"Ollama API is disabled": "",
"Ollama Version": "Ollama Version",
"On": "चालू",
"Only": "केवल",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF दस्तावेज़ (.pdf)",
"PDF Extract Images (OCR)": "PDF छवियाँ निकालें (OCR)",
"pending": "लंबित",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "माइक्रोफ़ोन तक पहुँचने पर अनुमति अस्वीकृत: {{error}}",
"Personalization": "पेरसनलाइज़मेंट",
"Pipelines": "पाइपलाइनों",
@@ -367,6 +383,7 @@
"Read Aloud": "जोर से पढ़ें",
"Record voice": "आवाज रिकॉर्ड करना",
"Redirecting you to OpenWebUI Community": "आपको OpenWebUI समुदाय पर पुनर्निर्देशित किया जा रहा है",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "जब ऐसा नहीं होना चाहिए था तो मना कर दिया",
"Regenerate": "पुनः जेनरेट",
"Release Notes": "रिलीज नोट्स",
@@ -378,12 +395,14 @@
"Reranking Model": "रीरैकिंग मोड",
"Reranking model disabled": "पुनर्रैंकिंग मॉडल अक्षम किया गया",
"Reranking model set to \"{{reranking_model}}\"": "रीरैंकिंग मॉडल को \"{{reranking_model}}\" पर \u200b\u200bसेट किया गया",
"Reset Upload Directory": "",
"Reset Vector Storage": "वेक्टर संग्रहण रीसेट करें",
"Response AutoCopy to Clipboard": "क्लिपबोर्ड पर प्रतिक्रिया ऑटोकॉपी",
"Role": "भूमिका",
"Rosé Pine": "रोसे पिन",
"Rosé Pine Dawn": "रोसे पिन डेन",
"RTL": "RTL",
"Running": "",
"Save": "सहेजें",
"Save & Create": "सहेजें और बनाएं",
"Save & Update": "सहेजें और अपडेट करें",
@@ -397,6 +416,8 @@
"Search Documents": "दस्तावेज़ खोजें",
"Search Models": "मॉडल खोजें",
"Search Prompts": "प्रॉम्प्ट खोजें",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "खोज परिणामों की संख्या",
"Searched {{count}} sites_one": "{{count}} sites_one खोजा गया",
"Searched {{count}} sites_other": "{{count}} sites_other खोजा गया",
@@ -406,12 +427,14 @@
"See what's new": "देखें, क्या नया है",
"Seed": "सीड्\u200c",
"Select a base model": "एक आधार मॉडल का चयन करें",
"Select a engine": "",
"Select a mode": "एक मोड चुनें",
"Select a model": "एक मॉडल चुनें",
"Select a pipeline": "एक पाइपलाइन का चयन करें",
"Select a pipeline url": "एक पाइपलाइन url चुनें",
"Select an Ollama instance": "एक Ollama Instance चुनें",
"Select model": "मॉडल चुनें",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "चयनित मॉडल छवि इनपुट का समर्थन नहीं करते हैं",
"Send": "भेज",
"Send a Message": "एक संदेश भेजो",
@@ -424,7 +447,6 @@
"Set Default Model": "डिफ़ॉल्ट मॉडल सेट करें",
"Set embedding model (e.g. {{model}})": "ईम्बेडिंग मॉडल सेट करें (उदाहरण: {{model}})",
"Set Image Size": "छवि का आकार सेट करें",
"Set Model": "मॉडल सेट करें",
"Set reranking model (e.g. {{model}})": "रीकरण मॉडल सेट करें (उदाहरण: {{model}})",
"Set Steps": "चरण निर्धारित करें",
"Set Task Model": "कार्य मॉडल सेट करें",
@@ -448,8 +470,8 @@
"Source": "स्रोत",
"Speech recognition error: {{error}}": "वाक् पहचान त्रुटि: {{error}}",
"Speech-to-Text Engine": "वाक्-से-पाठ इंजन",
"SpeechRecognition API is not supported in this browser.": "इस ब्राउज़र में SpeechRecognition API समर्थित नहीं है",
"Stop Sequence": "अनुक्रम रोकें",
"STT Model": "",
"STT Settings": "STT सेटिंग्स ",
"Submit": "सबमिट करें",
"Subtitle (e.g. about the Roman Empire)": "उपशीर्षक (जैसे रोमन साम्राज्य के बारे में)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "आपकी प्रतिक्रिया के लिए धन्यवाद!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "स्कोर का मान 0.0 (0%) और 1.0 (100%) के बीच होना चाहिए।",
"Theme": "थीम",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "यह सुनिश्चित करता है कि आपकी मूल्यवान बातचीत आपके बैकएंड डेटाबेस में सुरक्षित रूप से सहेजी गई है। धन्यवाद!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "यह सेटिंग सभी ब्राउज़रों या डिवाइसों में समन्वयित नहीं होती है",
"Thorough explanation": "विस्तृत व्याख्या",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "टिप: प्रत्येक प्रतिस्थापन के बाद चैट इनपुट में टैब कुंजी दबाकर लगातार कई वैरिएबल स्लॉट अपडेट करें।",
@@ -480,6 +504,7 @@
"to": "तक",
"To access the available model names for downloading,": "डाउनलोड करने के लिए उपलब्ध मॉडल नामों तक पहुंचने के लिए,",
"To access the GGUF models available for downloading,": "डाउनलोडिंग के लिए उपलब्ध GGUF मॉडल तक पहुँचने के लिए,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "इनपुट चैट करने के लिए.",
"Today": "आज",
"Toggle settings": "सेटिंग्स टॉगल करें",
@@ -487,7 +512,9 @@
"Top K": "शीर्ष K",
"Top P": "शीर्ष P",
"Trouble accessing Ollama?": "Ollama तक पहुँचने में परेशानी हो रही है?",
"TTS Model": "",
"TTS Settings": "TTS सेटिंग्स",
"TTS Voice": "",
"Type": "प्रकार",
"Type Hugging Face Resolve (Download) URL": "हगिंग फेस रिज़ॉल्व (डाउनलोड) यूआरएल टाइप करें",
"Uh-oh! There was an issue connecting to {{provider}}.": "उह ओह! {{provider}} से कनेक्ट करने में एक समस्या थी।",
@@ -496,6 +523,7 @@
"Update password": "पासवर्ड अपडेट करें",
"Upload a GGUF model": "GGUF मॉडल अपलोड करें",
"Upload Files": "फ़ाइलें अपलोड करें",
"Upload Pipeline": "",
"Upload Progress": "प्रगति अपलोड करें",
"URL Mode": "URL मोड",
"Use '#' in the prompt input to load and select your documents.": "अपने दस्तावेज़ों को लोड करने और चुनने के लिए शीघ्र इनपुट में '#' का उपयोग करें।",
@@ -514,6 +542,7 @@
"Warning": "चेतावनी",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "चेतावनी: यदि आप अपने एम्बेडिंग मॉडल को अपडेट या बदलते हैं, तो आपको सभी दस्तावेज़ों को फिर से आयात करने की आवश्यकता होगी।",
"Web": "वेब",
"Web API": "",
"Web Loader Settings": "वेब लोडर सेटिंग्स",
"Web Params": "वेब पैरामीटर",
"Web Search": "वेब खोज",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI अनुरोध करेगा",
"Whats New in": "इसमें नया क्या है",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "जब इतिहास बंद हो जाता है, तो इस ब्राउज़र पर नई चैट आपके किसी भी डिवाइस पर इतिहास में दिखाई नहीं देंगी।",
"Whisper (Local)": "Whisper (स्थानीय)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "वर्कस्पेस",
"Write a prompt suggestion (e.g. Who are you?)": "एक त्वरित सुझाव लिखें (जैसे कि आप कौन हैं?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "50 शब्दों में एक सारांश लिखें जो [विषय या कीवर्ड] का सारांश प्रस्तुत करता हो।",
"Yesterday": "कल",
"You": "आप",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "आप बेस मॉडल का क्लोन नहीं बना सकते",
"You have no archived conversations.": "आपको कोई अंकित चैट नहीं है।",
"You have shared this chat": "आपने इस चैट को शेयर किया है",
"You're a helpful assistant.": "आप एक सहायक सहायक हैं",
"You're now logged in.": "अब आप लॉग इन हो गए हैं",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "यूट्यूब लोडर सेटिंग्स"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "korisnik",
"About": "O aplikaciji",
"Account": "Račun",
"Account Activation Pending": "",
"Accurate information": "Točne informacije",
"Active Users": "",
"Add": "Dodaj",
"Add a model id": "Dodavanje ID-a modela",
"Add a short description about what this model does": "Dodajte kratak opis funkcija ovog modela",
@@ -28,6 +30,7 @@
"Add User": "Dodaj korisnika",
"Adjusting these settings will apply changes universally to all users.": "Podešavanje će se primijeniti univerzalno na sve korisnike.",
"admin": "administrator",
"Admin": "",
"Admin Panel": "Administratorska ploča",
"Admin Settings": "Administratorske postavke",
"Advanced Parameters": "Napredni parametri",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "Kolovoz",
"Auto-playback response": "Automatska reprodukcija odgovora",
"Auto-send input after 3 sec.": "Automatsko slanje unosa nakon 3 sek.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 osnovni URL",
"AUTOMATIC1111 Base URL is required.": "Potreban je AUTOMATIC1111 osnovni URL.",
"available!": "dostupno!",
@@ -70,6 +72,9 @@
"Being lazy": "Biti lijen",
"Brave Search API Key": "Ključ API-ja za hrabro pretraživanje",
"Bypass SSL verification for Websites": "Zaobiđi SSL provjeru za web stranice",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Otkaži",
"Capabilities": "Mogućnosti",
"Change Password": "Promijeni lozinku",
@@ -87,10 +92,12 @@
"Chunk Params": "Parametri dijelova",
"Chunk Size": "Veličina dijela",
"Citation": "Citiranje",
"Clear memory": "",
"Click here for help.": "Kliknite ovdje za pomoć.",
"Click here to": "Kliknite ovdje za",
"Click here to select": "Kliknite ovdje za odabir",
"Click here to select a csv file.": "Kliknite ovdje da odaberete csv datoteku.",
"Click here to select a py file.": "",
"Click here to select documents.": "Kliknite ovdje da odaberete dokumente.",
"click here.": "kliknite ovdje.",
"Click on the user role button to change a user's role.": "Kliknite na gumb uloge korisnika za promjenu uloge korisnika.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Istodobni zahtjevi",
"Confirm Password": "Potvrdite lozinku",
"Connections": "Povezivanja",
"Contact Admin for WebUI Access": "",
"Content": "Sadržaj",
"Context Length": "Dužina konteksta",
"Continue Response": "Nastavi odgovor",
"Conversation Mode": "Način razgovora",
"Copied shared chat URL to clipboard!": "URL dijeljenog razgovora kopiran u međuspremnik!",
"Copy": "Kopiraj",
"Copy last code block": "Kopiraj zadnji blok koda",
"Copy last response": "Kopiraj zadnji odgovor",
"Copy Link": "Kopiraj vezu",
"Copying to clipboard was successful!": "Kopiranje u međuspremnik je uspješno!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Stvorite sažetu frazu od 3-5 riječi kao naslov za sljedeći upit, strogo se pridržavajući ograničenja od 3-5 riječi i izbjegavajući upotrebu riječi 'naslov':",
"Create a model": "Stvaranje modela",
"Create Account": "Stvori račun",
"Create new key": "Stvori novi ključ",
@@ -126,12 +132,12 @@
"Custom": "Prilagođeno",
"Customize models for a specific purpose": "Prilagodba modela za određenu svrhu",
"Dark": "Tamno",
"Dashboard": "",
"Database": "Baza podataka",
"December": "Prosinac",
"Default": "Zadano",
"Default (Automatic1111)": "Zadano (Automatic1111)",
"Default (SentenceTransformers)": "Zadano (SentenceTransformers)",
"Default (Web API)": "Zadano (Web API)",
"Default Model": "Zadani model",
"Default model updated": "Zadani model ažuriran",
"Default Prompt Suggestions": "Zadani prijedlozi prompta",
@@ -152,6 +158,7 @@
"Discover a prompt": "Otkrijte prompt",
"Discover, download, and explore custom prompts": "Otkrijte, preuzmite i istražite prilagođene prompte",
"Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele",
"Dismissible": "",
"Display the username instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru",
"Document": "Dokument",
"Document Settings": "Postavke dokumenta",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Izvoz mapiranja dokumenata",
"Export Models": "Izvezi modele",
"Export Prompts": "Izvoz prompta",
"External Models": "",
"Failed to create API Key.": "Neuspješno stvaranje API ključa.",
"Failed to read clipboard contents": "Neuspješno čitanje sadržaja međuspremnika",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Savršeno slijedio upute",
"Format your variables using square brackets like this:": "Formatirajte svoje varijable pomoću uglatih zagrada ovako:",
"Frequency Penalty": "Kazna za učestalost",
"Full Screen Mode": "Način cijelog zaslona",
"General": "Općenito",
"General Settings": "Opće postavke",
"Generate Image": "",
"Generating search query": "Generiranje upita za pretraživanje",
"Generation Info": "Informacije o generaciji",
"Good Response": "Dobar odgovor",
@@ -252,6 +260,7 @@
"Info": "Informacije",
"Input commands": "Unos naredbi",
"Install from Github URL": "Instaliraj s Github URL-a",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Sučelje",
"Invalid Tag": "Nevažeća oznaka",
"January": "Siječanj",
@@ -264,14 +273,17 @@
"JWT Token": "JWT token",
"Keep Alive": "Održavanje živim",
"Keyboard shortcuts": "Tipkovnički prečaci",
"Knowledge": "",
"Language": "Jezik",
"Last Active": "Zadnja aktivnost",
"Light": "Svijetlo",
"Listening...": "Slušam...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLM-ovi mogu pogriješiti. Provjerite važne informacije.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Izradio OpenWebUI Community",
"Make sure to enclose them with": "Provjerite da ih zatvorite s",
"Manage": "",
"Manage Models": "Upravljanje modelima",
"Manage Ollama Models": "Upravljanje Ollama modelima",
"Manage Pipelines": "Upravljanje cjevovodima",
@@ -307,6 +319,7 @@
"Name your model": "Dodijelite naziv modelu",
"New Chat": "Novi razgovor",
"New Password": "Nova lozinka",
"No documents found": "",
"No results found": "Nema rezultata",
"No search query generated": "Nije generiran upit za pretraživanje",
"No source available": "Nema dostupnog izvora",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API je onemogućen",
"Ollama API is disabled": "",
"Ollama Version": "Ollama verzija",
"On": "Uključeno",
"Only": "Samo",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF dokument (.pdf)",
"PDF Extract Images (OCR)": "PDF izdvajanje slika (OCR)",
"pending": "u tijeku",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Pristup mikrofonu odbijen: {{error}}",
"Personalization": "Prilagodba",
"Pipelines": "Cjevovodima",
@@ -367,6 +383,7 @@
"Read Aloud": "Čitaj naglas",
"Record voice": "Snimanje glasa",
"Redirecting you to OpenWebUI Community": "Preusmjeravanje na OpenWebUI zajednicu",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Odbijen kada nije trebao biti",
"Regenerate": "Regeneriraj",
"Release Notes": "Bilješke o izdanju",
@@ -378,12 +395,14 @@
"Reranking Model": "Model za ponovno rangiranje",
"Reranking model disabled": "Model za ponovno rangiranje onemogućen",
"Reranking model set to \"{{reranking_model}}\"": "Model za ponovno rangiranje postavljen na \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Resetiraj pohranu vektora",
"Response AutoCopy to Clipboard": "Automatsko kopiranje odgovora u međuspremnik",
"Role": "Uloga",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "Spremi",
"Save & Create": "Spremi i stvori",
"Save & Update": "Spremi i ažuriraj",
@@ -397,6 +416,8 @@
"Search Documents": "Pretraga dokumenata",
"Search Models": "Modeli pretraživanja",
"Search Prompts": "Pretraga prompta",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Broj rezultata pretraživanja",
"Searched {{count}} sites_one": "Pretraženo {{count}} sites_one",
"Searched {{count}} sites_few": "Pretraženo {{count}} sites_few",
@@ -407,12 +428,14 @@
"See what's new": "Pogledajte što je novo",
"Seed": "Sjeme",
"Select a base model": "Odabir osnovnog modela",
"Select a engine": "",
"Select a mode": "Odaberite način",
"Select a model": "Odaberite model",
"Select a pipeline": "Odabir kanala",
"Select a pipeline url": "Odabir URL-a kanala",
"Select an Ollama instance": "Odaberite Ollama instancu",
"Select model": "Odaberite model",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "Odabrani modeli ne podržavaju unose slika",
"Send": "Pošalji",
"Send a Message": "Pošaljite poruku",
@@ -425,7 +448,6 @@
"Set Default Model": "Postavi zadani model",
"Set embedding model (e.g. {{model}})": "Postavi model za embedding (npr. {{model}})",
"Set Image Size": "Postavi veličinu slike",
"Set Model": "Postavi model",
"Set reranking model (e.g. {{model}})": "Postavi model za ponovno rangiranje (npr. {{model}})",
"Set Steps": "Postavi korake",
"Set Task Model": "Postavi model zadatka",
@@ -449,8 +471,8 @@
"Source": "Izvor",
"Speech recognition error: {{error}}": "Pogreška prepoznavanja govora: {{error}}",
"Speech-to-Text Engine": "Stroj za prepoznavanje govora",
"SpeechRecognition API is not supported in this browser.": "API za prepoznavanje govora nije podržan u ovom pregledniku.",
"Stop Sequence": "Zaustavi sekvencu",
"STT Model": "",
"STT Settings": "STT postavke",
"Submit": "Pošalji",
"Subtitle (e.g. about the Roman Empire)": "Podnaslov (npr. o Rimskom carstvu)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "Hvala na povratnim informacijama!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Ocjena treba biti vrijednost između 0,0 (0%) i 1,0 (100%).",
"Theme": "Tema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Ovo osigurava da su vaši vrijedni razgovori sigurno spremljeni u bazu podataka. Hvala vam!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Ova postavka se ne sinkronizira između preglednika ili uređaja.",
"Thorough explanation": "Detaljno objašnjenje",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Savjet: Ažurirajte više mjesta za varijable uzastopno pritiskom na tipku tab u unosu razgovora nakon svake zamjene.",
@@ -481,6 +505,7 @@
"to": "do",
"To access the available model names for downloading,": "Za pristup dostupnim nazivima modela za preuzimanje,",
"To access the GGUF models available for downloading,": "Za pristup GGUF modelima dostupnim za preuzimanje,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "u unos razgovora.",
"Today": "Danas",
"Toggle settings": "Prebaci postavke",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemi s pristupom Ollama?",
"TTS Model": "",
"TTS Settings": "TTS postavke",
"TTS Voice": "",
"Type": "Tip",
"Type Hugging Face Resolve (Download) URL": "Upišite Hugging Face Resolve (Download) URL",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Pojavio se problem s povezivanjem na {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Ažuriraj lozinku",
"Upload a GGUF model": "Učitaj GGUF model",
"Upload Files": "Prenesi datoteke",
"Upload Pipeline": "",
"Upload Progress": "Napredak učitavanja",
"URL Mode": "URL način",
"Use '#' in the prompt input to load and select your documents.": "Koristite '#' u unosu prompta za učitavanje i odabir vaših dokumenata.",
@@ -515,6 +543,7 @@
"Warning": "Upozorenje",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Upozorenje: Ako ažurirate ili promijenite svoj model za umetanje, morat ćete ponovno uvesti sve dokumente.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Postavke web učitavanja",
"Web Params": "Web parametri",
"Web Search": "Web-pretraživanje",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI će slati zahtjeve na",
"Whats New in": "Što je novo u",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Kada je povijest isključena, novi razgovori na ovom pregledniku neće se pojaviti u vašoj povijesti na bilo kojem od vaših uređaja.",
"Whisper (Local)": "Whisper (lokalno)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Radna ploča",
"Write a prompt suggestion (e.g. Who are you?)": "Napišite prijedlog prompta (npr. Tko si ti?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Napišite sažetak u 50 riječi koji sažima [temu ili ključnu riječ].",
"Yesterday": "Jučer",
"You": "Vi",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Ne možete klonirati osnovni model",
"You have no archived conversations.": "Nemate arhiviranih razgovora.",
"You have shared this chat": "Podijelili ste ovaj razgovor",
"You're a helpful assistant.": "Vi ste korisni asistent.",
"You're now logged in.": "Sada ste prijavljeni.",
"Your account status is currently pending activation.": "",
"Youtube": "YouTube",
"Youtube Loader Settings": "YouTube postavke učitavanja"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "un utente",
"About": "Informazioni",
"Account": "Account",
"Account Activation Pending": "",
"Accurate information": "Informazioni accurate",
"Active Users": "",
"Add": "Aggiungi",
"Add a model id": "Aggiungere un ID modello",
"Add a short description about what this model does": "Aggiungi una breve descrizione di ciò che fa questo modello",
@@ -28,6 +30,7 @@
"Add User": "Aggiungi utente",
"Adjusting these settings will apply changes universally to all users.": "La modifica di queste impostazioni applicherà le modifiche universalmente a tutti gli utenti.",
"admin": "amministratore",
"Admin": "",
"Admin Panel": "Pannello di amministrazione",
"Admin Settings": "Impostazioni amministratore",
"Advanced Parameters": "Parametri avanzati",
@@ -58,7 +61,6 @@
"Audio": "Audio",
"August": "Agosto",
"Auto-playback response": "Riproduzione automatica della risposta",
"Auto-send input after 3 sec.": "Invio automatico dell'input dopo 3 secondi.",
"AUTOMATIC1111 Base URL": "URL base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL base AUTOMATIC1111 è obbligatorio.",
"available!": "disponibile!",
@@ -70,6 +72,9 @@
"Being lazy": "Essere pigri",
"Brave Search API Key": "Chiave API di ricerca Brave",
"Bypass SSL verification for Websites": "Aggira la verifica SSL per i siti web",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "Annulla",
"Capabilities": "Funzionalità",
"Change Password": "Cambia password",
@@ -87,10 +92,12 @@
"Chunk Params": "Parametri chunk",
"Chunk Size": "Dimensione chunk",
"Citation": "Citazione",
"Clear memory": "",
"Click here for help.": "Clicca qui per aiuto.",
"Click here to": "Clicca qui per",
"Click here to select": "Clicca qui per selezionare",
"Click here to select a csv file.": "Clicca qui per selezionare un file csv.",
"Click here to select a py file.": "",
"Click here to select documents.": "Clicca qui per selezionare i documenti.",
"click here.": "clicca qui.",
"Click on the user role button to change a user's role.": "Clicca sul pulsante del ruolo utente per modificare il ruolo di un utente.",
@@ -104,17 +111,16 @@
"Concurrent Requests": "Richieste simultanee",
"Confirm Password": "Conferma password",
"Connections": "Connessioni",
"Contact Admin for WebUI Access": "",
"Content": "Contenuto",
"Context Length": "Lunghezza contesto",
"Continue Response": "Continua risposta",
"Conversation Mode": "Modalità conversazione",
"Copied shared chat URL to clipboard!": "URL della chat condivisa copiato negli appunti!",
"Copy": "Copia",
"Copy last code block": "Copia ultimo blocco di codice",
"Copy last response": "Copia ultima risposta",
"Copy Link": "Copia link",
"Copying to clipboard was successful!": "Copia negli appunti riuscita!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Crea una frase concisa di 3-5 parole come intestazione per la seguente query, aderendo rigorosamente al limite di 3-5 parole ed evitando l'uso della parola 'titolo':",
"Create a model": "Creare un modello",
"Create Account": "Crea account",
"Create new key": "Crea nuova chiave",
@@ -126,12 +132,12 @@
"Custom": "Personalizzato",
"Customize models for a specific purpose": "Personalizza i modelli per uno scopo specifico",
"Dark": "Scuro",
"Dashboard": "",
"Database": "Database",
"December": "Dicembre",
"Default": "Predefinito",
"Default (Automatic1111)": "Predefinito (Automatic1111)",
"Default (SentenceTransformers)": "Predefinito (SentenceTransformers)",
"Default (Web API)": "Predefinito (API Web)",
"Default Model": "Modello di default",
"Default model updated": "Modello predefinito aggiornato",
"Default Prompt Suggestions": "Suggerimenti prompt predefiniti",
@@ -152,6 +158,7 @@
"Discover a prompt": "Scopri un prompt",
"Discover, download, and explore custom prompts": "Scopri, scarica ed esplora prompt personalizzati",
"Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset del modello",
"Dismissible": "",
"Display the username instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat",
"Document": "Documento",
"Document Settings": "Impostazioni documento",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "Esporta mappatura documenti",
"Export Models": "Esporta modelli",
"Export Prompts": "Esporta prompt",
"External Models": "",
"Failed to create API Key.": "Impossibile creare la chiave API.",
"Failed to read clipboard contents": "Impossibile leggere il contenuto degli appunti",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "Ha seguito le istruzioni alla perfezione",
"Format your variables using square brackets like this:": "Formatta le tue variabili usando parentesi quadre come questa:",
"Frequency Penalty": "Penalità di frequenza",
"Full Screen Mode": "Modalità a schermo intero",
"General": "Generale",
"General Settings": "Impostazioni generali",
"Generate Image": "",
"Generating search query": "Generazione di query di ricerca",
"Generation Info": "Informazioni generazione",
"Good Response": "Buona risposta",
@@ -252,6 +260,7 @@
"Info": "Informazioni",
"Input commands": "Comandi di input",
"Install from Github URL": "Eseguire l'installazione dall'URL di Github",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "Interfaccia",
"Invalid Tag": "Tag non valido",
"January": "Gennaio",
@@ -264,14 +273,17 @@
"JWT Token": "Token JWT",
"Keep Alive": "Mantieni attivo",
"Keyboard shortcuts": "Scorciatoie da tastiera",
"Knowledge": "",
"Language": "Lingua",
"Last Active": "Ultima attività",
"Light": "Chiaro",
"Listening...": "Ascolto...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "Gli LLM possono commettere errori. Verifica le informazioni importanti.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "Realizzato dalla comunità OpenWebUI",
"Make sure to enclose them with": "Assicurati di racchiuderli con",
"Manage": "",
"Manage Models": "Gestisci modelli",
"Manage Ollama Models": "Gestisci modelli Ollama",
"Manage Pipelines": "Gestire le pipeline",
@@ -307,6 +319,7 @@
"Name your model": "Assegna un nome al tuo modello",
"New Chat": "Nuova chat",
"New Password": "Nuova password",
"No documents found": "",
"No results found": "Nessun risultato trovato",
"No search query generated": "Nessuna query di ricerca generata",
"No source available": "Nessuna fonte disponibile",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "API Ollama disabilitata",
"Ollama API is disabled": "",
"Ollama Version": "Versione Ollama",
"On": "Attivato",
"Only": "Solo",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "Documento PDF (.pdf)",
"PDF Extract Images (OCR)": "Estrazione immagini PDF (OCR)",
"pending": "in sospeso",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "Autorizzazione negata durante l'accesso al microfono: {{error}}",
"Personalization": "Personalizzazione",
"Pipelines": "Condutture",
@@ -367,6 +383,7 @@
"Read Aloud": "Leggi ad alta voce",
"Record voice": "Registra voce",
"Redirecting you to OpenWebUI Community": "Reindirizzamento alla comunità OpenWebUI",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "Rifiutato quando non avrebbe dovuto",
"Regenerate": "Rigenera",
"Release Notes": "Note di rilascio",
@@ -378,12 +395,14 @@
"Reranking Model": "Modello di riclassificazione",
"Reranking model disabled": "Modello di riclassificazione disabilitato",
"Reranking model set to \"{{reranking_model}}\"": "Modello di riclassificazione impostato su \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "Reimposta archivio vettoriale",
"Response AutoCopy to Clipboard": "Copia automatica della risposta negli appunti",
"Role": "Ruolo",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "Salva",
"Save & Create": "Salva e crea",
"Save & Update": "Salva e aggiorna",
@@ -397,6 +416,8 @@
"Search Documents": "Cerca documenti",
"Search Models": "Cerca modelli",
"Search Prompts": "Cerca prompt",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "Conteggio dei risultati della ricerca",
"Searched {{count}} sites_one": "Ricercato {{count}} sites_one",
"Searched {{count}} sites_many": "Ricercato {{count}} sites_many",
@@ -407,12 +428,14 @@
"See what's new": "Guarda le novità",
"Seed": "Seme",
"Select a base model": "Selezionare un modello di base",
"Select a engine": "",
"Select a mode": "Seleziona una modalità",
"Select a model": "Seleziona un modello",
"Select a pipeline": "Selezionare una tubazione",
"Select a pipeline url": "Selezionare l'URL di una pipeline",
"Select an Ollama instance": "Seleziona un'istanza Ollama",
"Select model": "Seleziona modello",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "I modelli selezionati non supportano l'input di immagini",
"Send": "Invia",
"Send a Message": "Invia un messaggio",
@@ -425,7 +448,6 @@
"Set Default Model": "Imposta modello predefinito",
"Set embedding model (e.g. {{model}})": "Imposta modello di embedding (ad esempio {{model}})",
"Set Image Size": "Imposta dimensione immagine",
"Set Model": "Imposta modello",
"Set reranking model (e.g. {{model}})": "Imposta modello di riclassificazione (ad esempio {{model}})",
"Set Steps": "Imposta passaggi",
"Set Task Model": "Imposta modello di attività",
@@ -449,8 +471,8 @@
"Source": "Fonte",
"Speech recognition error: {{error}}": "Errore di riconoscimento vocale: {{error}}",
"Speech-to-Text Engine": "Motore da voce a testo",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition non è supportata in questo browser.",
"Stop Sequence": "Sequenza di arresto",
"STT Model": "",
"STT Settings": "Impostazioni STT",
"Submit": "Invia",
"Subtitle (e.g. about the Roman Empire)": "Sottotitolo (ad esempio sull'Impero Romano)",
@@ -469,7 +491,9 @@
"Thanks for your feedback!": "Grazie per il tuo feedback!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Il punteggio dovrebbe essere un valore compreso tra 0.0 (0%) e 1.0 (100%).",
"Theme": "Tema",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Ciò garantisce che le tue preziose conversazioni siano salvate in modo sicuro nel tuo database backend. Grazie!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "Questa impostazione non si sincronizza tra browser o dispositivi.",
"Thorough explanation": "Spiegazione dettagliata",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Suggerimento: aggiorna più slot di variabili consecutivamente premendo il tasto tab nell'input della chat dopo ogni sostituzione.",
@@ -481,6 +505,7 @@
"to": "a",
"To access the available model names for downloading,": "Per accedere ai nomi dei modelli disponibili per il download,",
"To access the GGUF models available for downloading,": "Per accedere ai modelli GGUF disponibili per il download,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "all'input della chat.",
"Today": "Oggi",
"Toggle settings": "Attiva/disattiva impostazioni",
@@ -488,7 +513,9 @@
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemi di accesso a Ollama?",
"TTS Model": "",
"TTS Settings": "Impostazioni TTS",
"TTS Voice": "",
"Type": "Digitare",
"Type Hugging Face Resolve (Download) URL": "Digita l'URL di Hugging Face Resolve (Download)",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Si è verificato un problema durante la connessione a {{provider}}.",
@@ -497,6 +524,7 @@
"Update password": "Aggiorna password",
"Upload a GGUF model": "Carica un modello GGUF",
"Upload Files": "Carica file",
"Upload Pipeline": "",
"Upload Progress": "Avanzamento caricamento",
"URL Mode": "Modalità URL",
"Use '#' in the prompt input to load and select your documents.": "Usa '#' nell'input del prompt per caricare e selezionare i tuoi documenti.",
@@ -515,6 +543,7 @@
"Warning": "Avvertimento",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Attenzione: se aggiorni o cambi il tuo modello di embedding, dovrai reimportare tutti i documenti.",
"Web": "Web",
"Web API": "",
"Web Loader Settings": "Impostazioni del caricatore Web",
"Web Params": "Parametri Web",
"Web Search": "Ricerca sul Web",
@@ -525,17 +554,20 @@
"WebUI will make requests to": "WebUI effettuerà richieste a",
"Whats New in": "Novità in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando la cronologia è disattivata, le nuove chat su questo browser non verranno visualizzate nella cronologia su nessuno dei tuoi dispositivi.",
"Whisper (Local)": "Whisper (locale)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "Area di lavoro",
"Write a prompt suggestion (e.g. Who are you?)": "Scrivi un suggerimento per il prompt (ad esempio Chi sei?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Scrivi un riassunto in 50 parole che riassume [argomento o parola chiave].",
"Yesterday": "Ieri",
"You": "Tu",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "Non è possibile clonare un modello di base",
"You have no archived conversations.": "Non hai conversazioni archiviate.",
"You have shared this chat": "Hai condiviso questa chat",
"You're a helpful assistant.": "Sei un assistente utile.",
"You're now logged in.": "Ora hai effettuato l'accesso.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Impostazioni del caricatore Youtube"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "ユーザー",
"About": "概要",
"Account": "アカウント",
"Account Activation Pending": "",
"Accurate information": "情報の正確性",
"Active Users": "",
"Add": "追加",
"Add a model id": "モデル ID を追加する",
"Add a short description about what this model does": "このモデルの機能に関する簡単な説明を追加します",
@@ -28,6 +30,7 @@
"Add User": "ユーザーを追加",
"Adjusting these settings will apply changes universally to all users.": "これらの設定を調整すると、すべてのユーザーに普遍的に変更が適用されます。",
"admin": "管理者",
"Admin": "",
"Admin Panel": "管理者パネル",
"Admin Settings": "管理者設定",
"Advanced Parameters": "詳細パラメーター",
@@ -58,7 +61,6 @@
"Audio": "オーディオ",
"August": "8月",
"Auto-playback response": "応答の自動再生",
"Auto-send input after 3 sec.": "3 秒後に自動的に出力を送信",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 ベース URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 ベース URL が必要です。",
"available!": "利用可能!",
@@ -70,6 +72,9 @@
"Being lazy": "怠惰な",
"Brave Search API Key": "Brave Search APIキー",
"Bypass SSL verification for Websites": "SSL 検証をバイパスする",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "キャンセル",
"Capabilities": "資格",
"Change Password": "パスワードを変更",
@@ -87,10 +92,12 @@
"Chunk Params": "チャンクパラメーター",
"Chunk Size": "チャンクサイズ",
"Citation": "引用文",
"Clear memory": "",
"Click here for help.": "ヘルプについてはここをクリックしてください。",
"Click here to": "ここをクリックして",
"Click here to select": "選択するにはここをクリックしてください",
"Click here to select a csv file.": "CSVファイルを選択するにはここをクリックしてください。",
"Click here to select a py file.": "",
"Click here to select documents.": "ドキュメントを選択するにはここをクリックしてください。",
"click here.": "ここをクリックしてください。",
"Click on the user role button to change a user's role.": "ユーザーの役割を変更するには、ユーザー役割ボタンをクリックしてください。",
@@ -104,17 +111,16 @@
"Concurrent Requests": "コンカレント要求",
"Confirm Password": "パスワードを確認",
"Connections": "接続",
"Contact Admin for WebUI Access": "",
"Content": "コンテンツ",
"Context Length": "コンテキストの長さ",
"Continue Response": "続きの応答",
"Conversation Mode": "会話モード",
"Copied shared chat URL to clipboard!": "共有チャットURLをクリップボードにコピーしました!",
"Copy": "コピー",
"Copy last code block": "最後のコードブロックをコピー",
"Copy last response": "最後の応答をコピー",
"Copy Link": "リンクをコピー",
"Copying to clipboard was successful!": "クリップボードへのコピーが成功しました!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "次のクエリの見出しとして、3〜5語の簡潔なフレーズを作成してください。3〜5語の制限を厳守し、「タイトル」という単語の使用を避けてください。",
"Create a model": "モデルを作成する",
"Create Account": "アカウントを作成",
"Create new key": "新しいキーを作成",
@@ -126,12 +132,12 @@
"Custom": "カスタム",
"Customize models for a specific purpose": "特定の目的に合わせてモデルをカスタマイズする",
"Dark": "ダーク",
"Dashboard": "",
"Database": "データベース",
"December": "12月",
"Default": "デフォルト",
"Default (Automatic1111)": "デフォルト (Automatic1111)",
"Default (SentenceTransformers)": "デフォルト (SentenceTransformers)",
"Default (Web API)": "デフォルト (Web API)",
"Default Model": "デフォルトモデル",
"Default model updated": "デフォルトモデルが更新されました",
"Default Prompt Suggestions": "デフォルトのプロンプトの提案",
@@ -152,6 +158,7 @@
"Discover a prompt": "プロンプトを見つける",
"Discover, download, and explore custom prompts": "カスタムプロンプトを見つけて、ダウンロードして、探索",
"Discover, download, and explore model presets": "モデルプリセットを見つけて、ダウンロードして、探索",
"Dismissible": "",
"Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示",
"Document": "ドキュメント",
"Document Settings": "ドキュメント設定",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "ドキュメントマッピングをエクスポート",
"Export Models": "モデルのエクスポート",
"Export Prompts": "プロンプトをエクスポート",
"External Models": "",
"Failed to create API Key.": "APIキーの作成に失敗しました。",
"Failed to read clipboard contents": "クリップボードの内容を読み取れませんでした",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "完全に指示に従った",
"Format your variables using square brackets like this:": "次のように角括弧を使用して変数をフォーマットします。",
"Frequency Penalty": "周波数ペナルティ",
"Full Screen Mode": "フルスクリーンモード",
"General": "一般",
"General Settings": "一般設定",
"Generate Image": "",
"Generating search query": "検索クエリの生成",
"Generation Info": "生成情報",
"Good Response": "良い応答",
@@ -252,6 +260,7 @@
"Info": "情報",
"Input commands": "入力コマンド",
"Install from Github URL": "Github URLからインストール",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "インターフェース",
"Invalid Tag": "無効なタグ",
"January": "1月",
@@ -264,14 +273,17 @@
"JWT Token": "JWT トークン",
"Keep Alive": "キープアライブ",
"Keyboard shortcuts": "キーボードショートカット",
"Knowledge": "",
"Language": "言語",
"Last Active": "最終アクティブ",
"Light": "ライト",
"Listening...": "聞いています...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "LLM は間違いを犯す可能性があります。重要な情報を検証してください。",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "OpenWebUI コミュニティによって作成",
"Make sure to enclose them with": "必ず次で囲んでください",
"Manage": "",
"Manage Models": "モデルを管理",
"Manage Ollama Models": "Ollama モデルを管理",
"Manage Pipelines": "パイプラインの管理",
@@ -307,6 +319,7 @@
"Name your model": "モデルに名前を付ける",
"New Chat": "新しいチャット",
"New Password": "新しいパスワード",
"No documents found": "",
"No results found": "結果が見つかりません",
"No search query generated": "検索クエリは生成されません",
"No source available": "使用可能なソースがありません",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API が無効になっています",
"Ollama API is disabled": "",
"Ollama Version": "Ollama バージョン",
"On": "オン",
"Only": "のみ",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF ドキュメント (.pdf)",
"PDF Extract Images (OCR)": "PDF 画像抽出 (OCR)",
"pending": "保留中",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "マイクへのアクセス時に権限が拒否されました: {{error}}",
"Personalization": "個人化",
"Pipelines": "パイプライン",
@@ -367,6 +383,7 @@
"Read Aloud": "読み上げ",
"Record voice": "音声を録音",
"Redirecting you to OpenWebUI Community": "OpenWebUI コミュニティにリダイレクトしています",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "許可されないのに許可されました",
"Regenerate": "再生成",
"Release Notes": "リリースノート",
@@ -378,12 +395,14 @@
"Reranking Model": "モデルの再ランキング",
"Reranking model disabled": "再ランキングモデルが無効です",
"Reranking model set to \"{{reranking_model}}\"": "再ランキングモデルを \"{{reranking_model}}\" に設定しました",
"Reset Upload Directory": "",
"Reset Vector Storage": "ベクトルストレージをリセット",
"Response AutoCopy to Clipboard": "クリップボードへの応答の自動コピー",
"Role": "役割",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Running": "",
"Save": "保存",
"Save & Create": "保存して作成",
"Save & Update": "保存して更新",
@@ -397,6 +416,8 @@
"Search Documents": "ドキュメントを検索",
"Search Models": "モデル検索",
"Search Prompts": "プロンプトを検索",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "検索結果数",
"Searched {{count}} sites_other": "{{count}} sites_other検索",
"Searching the web for '{{searchQuery}}'": "ウェブで '{{searchQuery}}' を検索する",
@@ -405,12 +426,14 @@
"See what's new": "新機能を見る",
"Seed": "シード",
"Select a base model": "基本モデルの選択",
"Select a engine": "",
"Select a mode": "モードを選択",
"Select a model": "モデルを選択",
"Select a pipeline": "パイプラインの選択",
"Select a pipeline url": "パイプラインの URL を選択する",
"Select an Ollama instance": "Ollama インスタンスを選択",
"Select model": "モデルを選択",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "一部のモデルは画像入力をサポートしていません",
"Send": "送信",
"Send a Message": "メッセージを送信",
@@ -423,7 +446,6 @@
"Set Default Model": "デフォルトモデルを設定",
"Set embedding model (e.g. {{model}})": "埋め込みモデルを設定します(例:{{model}}",
"Set Image Size": "画像サイズを設定",
"Set Model": "モデルを設定",
"Set reranking model (e.g. {{model}})": "モデルを設定します(例:{{model}}",
"Set Steps": "ステップを設定",
"Set Task Model": "タスクモデルの設定",
@@ -447,8 +469,8 @@
"Source": "ソース",
"Speech recognition error: {{error}}": "音声認識エラー: {{error}}",
"Speech-to-Text Engine": "音声テキスト変換エンジン",
"SpeechRecognition API is not supported in this browser.": "このブラウザでは SpeechRecognition API がサポートされていません。",
"Stop Sequence": "ストップシーケンス",
"STT Model": "",
"STT Settings": "STT 設定",
"Submit": "送信",
"Subtitle (e.g. about the Roman Empire)": "タイトル (例: ロマ帝国)",
@@ -467,7 +489,9 @@
"Thanks for your feedback!": "ご意見ありがとうございます!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "スコアは0.0(0%)から1.0(100%)の間の値にしてください。",
"Theme": "テーマ",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "これは、貴重な会話がバックエンドデータベースに安全に保存されることを保証します。ありがとうございます!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "この設定は、ブラウザやデバイス間で同期されません。",
"Thorough explanation": "詳細な説明",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ヒント: 各置換後にチャット入力で Tab キーを押すことで、複数の変数スロットを連続して更新できます。",
@@ -479,6 +503,7 @@
"to": "まで",
"To access the available model names for downloading,": "ダウンロード可能なモデル名にアクセスするには、",
"To access the GGUF models available for downloading,": "ダウンロード可能な GGUF モデルにアクセスするには、",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "チャット入力へ。",
"Today": "今日",
"Toggle settings": "設定を切り替え",
@@ -486,7 +511,9 @@
"Top K": "トップ K",
"Top P": "トップ P",
"Trouble accessing Ollama?": "Ollama へのアクセスに問題がありますか?",
"TTS Model": "",
"TTS Settings": "TTS 設定",
"TTS Voice": "",
"Type": "種類",
"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (ダウンロード) URL を入力してください",
"Uh-oh! There was an issue connecting to {{provider}}.": "おっと! {{provider}} への接続に問題が発生しました。",
@@ -495,6 +522,7 @@
"Update password": "パスワードを更新",
"Upload a GGUF model": "GGUF モデルをアップロード",
"Upload Files": "ファイルのアップロード",
"Upload Pipeline": "",
"Upload Progress": "アップロードの進行状況",
"URL Mode": "URL モード",
"Use '#' in the prompt input to load and select your documents.": "プロンプト入力で '#' を使用して、ドキュメントを読み込んで選択します。",
@@ -513,6 +541,7 @@
"Warning": "警告",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告: 埋め込みモデルを更新または変更した場合は、すべてのドキュメントを再インポートする必要があります。",
"Web": "ウェブ",
"Web API": "",
"Web Loader Settings": "Web 読み込み設定",
"Web Params": "Web パラメータ",
"Web Search": "ウェブ検索",
@@ -523,17 +552,20 @@
"WebUI will make requests to": "WebUI は次に対してリクエストを行います",
"Whats New in": "新機能",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "履歴が無効になっている場合、このブラウザでの新しいチャットは、どのデバイスの履歴にも表示されません。",
"Whisper (Local)": "Whisper (ローカル)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "ワークスペース",
"Write a prompt suggestion (e.g. Who are you?)": "プロンプトの提案を書いてください (例: あなたは誰ですか?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "[トピックまたはキーワード] を要約する 50 語の概要を書いてください。",
"Yesterday": "昨日",
"You": "あなた",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "基本モデルのクローンを作成できない",
"You have no archived conversations.": "これまでにアーカイブされた会話はありません。",
"You have shared this chat": "このチャットを共有しました",
"You're a helpful assistant.": "あなたは役に立つアシスタントです。",
"You're now logged in.": "ログインしました。",
"Your account status is currently pending activation.": "",
"Youtube": "YouTube",
"Youtube Loader Settings": "Youtubeローダー設定"
}
+41 -9
View File
@@ -12,7 +12,9 @@
"a user": "მომხმარებელი",
"About": "შესახებ",
"Account": "ანგარიში",
"Account Activation Pending": "",
"Accurate information": "დიდი ინფორმაცია",
"Active Users": "",
"Add": "დამატება",
"Add a model id": "დაამატეთ მოდელის ID",
"Add a short description about what this model does": "დაამატეთ მოკლე აღწერა იმის შესახებ, თუ რას აკეთებს ეს მოდელი",
@@ -28,6 +30,7 @@
"Add User": "მომხმარებლის დამატება",
"Adjusting these settings will apply changes universally to all users.": "ამ პარამეტრების რეგულირება ცვლილებებს უნივერსალურად გამოიყენებს ყველა მომხმარებლისთვის",
"admin": "ადმინისტრატორი",
"Admin": "",
"Admin Panel": "ადმინ პანელი",
"Admin Settings": "ადმინისტრატორის ხელსაწყოები",
"Advanced Parameters": "დამატებითი პარამეტრები",
@@ -58,7 +61,6 @@
"Audio": "ხმოვანი",
"August": "აგვისტო",
"Auto-playback response": "ავტომატური დაკვრის პასუხი",
"Auto-send input after 3 sec.": "შეყვანის ავტომატური გაგზავნა 3 წამის შემდეგ ",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 საბაზისო მისამართი",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 საბაზისო მისამართი აუცილებელია",
"available!": "ხელმისაწვდომია!",
@@ -70,6 +72,9 @@
"Being lazy": "ჩაიტყვევა",
"Brave Search API Key": "Brave Search API გასაღები",
"Bypass SSL verification for Websites": "SSL-ის ვერიფიკაციის გააუქმება ვებსაიტებზე",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Cancel": "გაუქმება",
"Capabilities": "შესაძლებლობები",
"Change Password": "პაროლის შეცვლა",
@@ -87,10 +92,12 @@
"Chunk Params": "გადახურვის პარამეტრები",
"Chunk Size": "გადახურვის ზომა",
"Citation": "ციტატა",
"Clear memory": "",
"Click here for help.": "დახმარებისთვის, დააკლიკე აქ",
"Click here to": "დააკლიკე აქ",
"Click here to select": "ასარჩევად, დააკლიკე აქ",
"Click here to select a csv file.": "ასარჩევად, დააკლიკე აქ",
"Click here to select a py file.": "",
"Click here to select documents.": "დოკუმენტების ასარჩევად, დააკლიკე აქ",
"click here.": "დააკლიკე აქ",
"Click on the user role button to change a user's role.": "დააკლიკეთ მომხმარებლის როლის ღილაკს რომ შეცვალოთ მომხმარების როლი",
@@ -104,17 +111,16 @@
"Concurrent Requests": "თანმხლები მოთხოვნები",
"Confirm Password": "პაროლის დამოწმება",
"Connections": "კავშირები",
"Contact Admin for WebUI Access": "",
"Content": "კონტენტი",
"Context Length": "კონტექსტის სიგრძე",
"Continue Response": "პასუხის გაგრძელება",
"Conversation Mode": "საუბრი რეჟიმი",
"Copied shared chat URL to clipboard!": "ყავს ჩათის URL-ი კლიპბორდში!",
"Copy": "კოპირება",
"Copy last code block": "ბოლო ბლოკის კოპირება",
"Copy last response": "ბოლო პასუხის კოპირება",
"Copy Link": "კოპირება",
"Copying to clipboard was successful!": "კლავიატურაზე კოპირება წარმატებით დასრულდა",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "შექმენით მოკლე, 3-5 სიტყვიანი ფრაზა, როგორც სათაური თქვენი შემდეგი შეკითხვისთვის, მკაცრად დაიცავით 3-5 სიტყვის ლიმიტი და მოერიდეთ გამოიყენოთ სიტყვა „სათაური“.",
"Create a model": "შექმენით მოდელი",
"Create Account": "ანგარიშის შექმნა",
"Create new key": "პირადი ღირებულბრის შექმნა",
@@ -126,12 +132,12 @@
"Custom": "საკუთარი",
"Customize models for a specific purpose": "მოდელების მორგება კონკრეტული მიზნისთვის",
"Dark": "მუქი",
"Dashboard": "",
"Database": "მონაცემთა ბაზა",
"December": "დეკემბერი",
"Default": "დეფოლტი",
"Default (Automatic1111)": "დეფოლტ (Automatic1111)",
"Default (SentenceTransformers)": "დეფოლტ (SentenceTransformers)",
"Default (Web API)": "დეფოლტ (Web API)",
"Default Model": "ნაგულისხმები მოდელი",
"Default model updated": "დეფოლტ მოდელი განახლებულია",
"Default Prompt Suggestions": "დეფოლტ პრომპტი პირველი პირველი",
@@ -152,6 +158,7 @@
"Discover a prompt": "აღმოაჩინეთ მოთხოვნა",
"Discover, download, and explore custom prompts": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მორგებული მოთხოვნები",
"Discover, download, and explore model presets": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მოდელის წინასწარ პარამეტრები",
"Dismissible": "",
"Display the username instead of You in the Chat": "ჩატში აჩვენე მომხმარებლის სახელი თქვენს ნაცვლად",
"Document": "დოკუმენტი",
"Document Settings": "დოკუმენტის პარამეტრები",
@@ -212,6 +219,7 @@
"Export Documents Mapping": "დოკუმენტების კავშირის ექსპორტი",
"Export Models": "ექსპორტის მოდელები",
"Export Prompts": "მოთხოვნების ექსპორტი",
"External Models": "",
"Failed to create API Key.": "API ღილაკის შექმნა ვერ მოხერხდა.",
"Failed to read clipboard contents": "ბუფერში შიგთავსის წაკითხვა ვერ მოხერხდა",
"Failed to update settings": "",
@@ -225,9 +233,9 @@
"Followed instructions perfectly": "ყველა ინსტრუქცია უზრუნველყოფა",
"Format your variables using square brackets like this:": "დააფორმატეთ თქვენი ცვლადები კვადრატული ფრჩხილების გამოყენებით:",
"Frequency Penalty": "სიხშირის ჯარიმა",
"Full Screen Mode": "Სრული ეკრანის რეჟიმი",
"General": "ზოგადი",
"General Settings": "ზოგადი პარამეტრები",
"Generate Image": "",
"Generating search query": "საძიებო მოთხოვნის გენერირება",
"Generation Info": "გენერაციის ინფორმაცია",
"Good Response": "დიდი პასუხი",
@@ -252,6 +260,7 @@
"Info": "ინფორმაცია",
"Input commands": "შეყვანით ბრძანებებს",
"Install from Github URL": "დააინსტალირეთ Github URL- დან",
"Instant Auto-Send After Voice Transcription": "",
"Interface": "ინტერფეისი",
"Invalid Tag": "არასწორი ტეგი",
"January": "იანვარი",
@@ -264,14 +273,17 @@
"JWT Token": "JWT ტოკენი",
"Keep Alive": "აქტიურად დატოვება",
"Keyboard shortcuts": "კლავიატურის მალსახმობები",
"Knowledge": "",
"Language": "ენა",
"Last Active": "ბოლო აქტიური",
"Light": "მსუბუქი",
"Listening...": "გისმენ...",
"Listening...": "",
"LLMs can make mistakes. Verify important information.": "შესაძლოა LLM-ებმა შეცდომები დაუშვან. გადაამოწმეთ მნიშვნელოვანი ინფორმაცია.",
"Local Models": "",
"LTR": "LTR",
"Made by OpenWebUI Community": "დამზადებულია OpenWebUI საზოგადოების მიერ",
"Make sure to enclose them with": "დარწმუნდით, რომ დაურთეთ ისინი",
"Manage": "",
"Manage Models": "მოდელების მართვა",
"Manage Ollama Models": "Ollama მოდელების მართვა",
"Manage Pipelines": "მილსადენების მართვა",
@@ -307,6 +319,7 @@
"Name your model": "დაასახელეთ თქვენი მოდელი",
"New Chat": "ახალი მიმოწერა",
"New Password": "ახალი პაროლი",
"No documents found": "",
"No results found": "ჩვენ ვერ პოულობით ნაპოვნი ჩაწერები",
"No search query generated": "ძიების მოთხოვნა არ არის გენერირებული",
"No source available": "წყარო არ არის ხელმისაწვდომი",
@@ -323,6 +336,7 @@
"Ollama": "Ollama",
"Ollama API": "Ollama API",
"Ollama API disabled": "Ollama API გამორთულია",
"Ollama API is disabled": "",
"Ollama Version": "Ollama ვერსია",
"On": "ჩართვა",
"Only": "მხოლოდ",
@@ -345,6 +359,8 @@
"PDF document (.pdf)": "PDF დოკუმენტი (.pdf)",
"PDF Extract Images (OCR)": "PDF იდან ამოღებული სურათები (OCR)",
"pending": "ლოდინის რეჟიმშია",
"Permission denied when accessing media devices": "",
"Permission denied when accessing microphone": "",
"Permission denied when accessing microphone: {{error}}": "ნებართვა უარყოფილია მიკროფონზე წვდომისას: {{error}}",
"Personalization": "პერსონალიზაცია",
"Pipelines": "მილსადენები",
@@ -367,6 +383,7 @@
"Read Aloud": "ხმის ჩაწერა",
"Record voice": "ხმის ჩაწერა",
"Redirecting you to OpenWebUI Community": "გადამისამართდებით OpenWebUI საზოგადოებაში",
"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
"Refused when it shouldn't have": "უარა, როგორც უნდა იყოს",
"Regenerate": "ხელახლა გენერირება",
"Release Notes": "Გამოშვების შენიშვნები",
@@ -378,12 +395,14 @@
"Reranking Model": "რექვექტირება",
"Reranking model disabled": "რექვექტირება არაა ჩართული",
"Reranking model set to \"{{reranking_model}}\"": "Reranking model set to \"{{reranking_model}}\"",
"Reset Upload Directory": "",
"Reset Vector Storage": "ვექტორული მეხსიერების გადატვირთვა",
"Response AutoCopy to Clipboard": "პასუხის ავტომატური კოპირება ბუფერში",
"Role": "როლი",
"Rosé Pine": "ვარდისფერი ფიჭვის ხე",
"Rosé Pine Dawn": "ვარდისფერი ფიჭვის გარიჟრაჟი",
"RTL": "RTL",
"Running": "",
"Save": "შენახვა",
"Save & Create": "დამახსოვრება და შექმნა",
"Save & Update": "დამახსოვრება და განახლება",
@@ -397,6 +416,8 @@
"Search Documents": "დოკუმენტების ძიება",
"Search Models": "საძიებო მოდელები",
"Search Prompts": "მოთხოვნების ძიება",
"Search Query Generation Prompt": "",
"Search Query Generation Prompt Length Threshold": "",
"Search Result Count": "ძიების შედეგების რაოდენობა",
"Searched {{count}} sites_one": "Searched {{count}} sites_one",
"Searched {{count}} sites_other": "Searched {{count}} sites_other",
@@ -406,12 +427,14 @@
"See what's new": "სიახლეების ნახვა",
"Seed": "სიდი",
"Select a base model": "აირჩიეთ ბაზის მოდელი",
"Select a engine": "",
"Select a mode": "რეჟიმის არჩევა",
"Select a model": "მოდელის არჩევა",
"Select a pipeline": "აირჩიეთ მილსადენი",
"Select a pipeline url": "აირჩიეთ მილსადენის url",
"Select an Ollama instance": "Ollama ინსტანსის არჩევა",
"Select model": "მოდელის არჩევა",
"Select only one model to call": "",
"Selected model(s) do not support image inputs": "შერჩეული მოდელი (ებ) ი არ უჭერს მხარს გამოსახულების შეყვანას",
"Send": "გაგზავნა",
"Send a Message": "შეტყობინების გაგზავნა",
@@ -424,7 +447,6 @@
"Set Default Model": "დეფოლტ მოდელის დაყენება",
"Set embedding model (e.g. {{model}})": "ჩვენება მოდელის დაყენება (მაგ. {{model}})",
"Set Image Size": "სურათის ზომის დაყენება",
"Set Model": "მოდელის დაყენება",
"Set reranking model (e.g. {{model}})": "რეტარირება მოდელის დაყენება (მაგ. {{model}})",
"Set Steps": "ნაბიჯების დაყენება",
"Set Task Model": "დააყენეთ სამუშაო მოდელი",
@@ -448,8 +470,8 @@
"Source": "წყარო",
"Speech recognition error: {{error}}": "მეტყველების ამოცნობის შეცდომა: {{error}}",
"Speech-to-Text Engine": "ხმოვან-ტექსტური ძრავი",
"SpeechRecognition API is not supported in this browser.": "მეტყველების ამოცნობის API არ არის მხარდაჭერილი ამ ბრაუზერში.",
"Stop Sequence": "შეჩერების თანმიმდევრობა",
"STT Model": "",
"STT Settings": "მეტყველების ამოცნობის პარამეტრები",
"Submit": "გაგზავნა",
"Subtitle (e.g. about the Roman Empire)": "სუბტიტრები (მაგ. რომის იმპერიის შესახებ)",
@@ -468,7 +490,9 @@
"Thanks for your feedback!": "მადლობა გამოხმაურებისთვის!",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "ქულა 0.0 (0%) და 1.0 (100%) ჩაშენებული უნდა იყოს.",
"Theme": "თემა",
"Thinking...": "",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "ეს უზრუნველყოფს, რომ თქვენი ძვირფასი საუბრები უსაფრთხოდ შეინახება თქვენს backend მონაცემთა ბაზაში. Გმადლობთ!",
"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
"This setting does not sync across browsers or devices.": "ეს პარამეტრი არ სინქრონიზდება ბრაუზერებსა და მოწყობილობებში",
"Thorough explanation": "ვრცლად აღწერა",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "რჩევა: განაახლეთ რამდენიმე ცვლადი სლოტი თანმიმდევრულად, ყოველი ჩანაცვლების შემდეგ ჩატის ღილაკზე დაჭერით.",
@@ -480,6 +504,7 @@
"to": "ში",
"To access the available model names for downloading,": "ჩამოტვირთვისთვის ხელმისაწვდომი მოდელების სახელებზე წვდომისთვის",
"To access the GGUF models available for downloading,": "ჩასატვირთად ხელმისაწვდომი GGUF მოდელებზე წვდომისთვის",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
"to chat input.": "ჩატში",
"Today": "დღეს",
"Toggle settings": "პარამეტრების გადართვა",
@@ -487,7 +512,9 @@
"Top K": "ტოპ K",
"Top P": "ტოპ P",
"Trouble accessing Ollama?": "Ollama-ს ვერ უკავშირდები?",
"TTS Model": "",
"TTS Settings": "TTS პარამეტრები",
"TTS Voice": "",
"Type": "ტიპი",
"Type Hugging Face Resolve (Download) URL": "სცადე გადმოწერო Hugging Face Resolve URL",
"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}-თან დაკავშირების პრობლემა წარმოიშვა.",
@@ -496,6 +523,7 @@
"Update password": "პაროლის განახლება",
"Upload a GGUF model": "GGUF მოდელის ატვირთვა",
"Upload Files": "ატვირთეთ ფაილები",
"Upload Pipeline": "",
"Upload Progress": "პროგრესის ატვირთვა",
"URL Mode": "URL რეჟიმი",
"Use '#' in the prompt input to load and select your documents.": "პრომტში გამოიყენე '#' რომელიც გაიტანს დოკუმენტებს",
@@ -514,6 +542,7 @@
"Warning": "გაფრთხილება",
"Warning: If you update or change your embedding model, you will need to re-import all documents.": "გაფრთხილება: თუ განაახლებთ ან შეცვლით ჩანერგვის მოდელს, მოგიწევთ ყველა დოკუმენტის ხელახლა იმპორტი.",
"Web": "ვები",
"Web API": "",
"Web Loader Settings": "ვების ჩატარების პარამეტრები",
"Web Params": "ვების პარამეტრები",
"Web Search": "ვებ ძებნა",
@@ -524,17 +553,20 @@
"WebUI will make requests to": "WebUI გამოგიგზავნით მოთხოვნებს",
"Whats New in": "რა არის ახალი",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "როდესაც ისტორია გამორთულია, ახალი ჩეთები ამ ბრაუზერში არ გამოჩნდება თქვენს ისტორიაში არცერთ მოწყობილობაზე.",
"Whisper (Local)": "ჩურჩული (ადგილობრივი)",
"Whisper (Local)": "",
"Widescreen Mode": "",
"Workspace": "ვულერი",
"Write a prompt suggestion (e.g. Who are you?)": "დაწერეთ მოკლე წინადადება (მაგ. ვინ ხარ?",
"Write a summary in 50 words that summarizes [topic or keyword].": "დაწერეთ რეზიუმე 50 სიტყვით, რომელიც აჯამებს [თემას ან საკვანძო სიტყვას].",
"Yesterday": "აღდგენა",
"You": "ჩემი",
"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
"You cannot clone a base model": "თქვენ არ შეგიძლიათ ბაზის მოდელის კლონირება",
"You have no archived conversations.": "არ ხართ არქივირებული განხილვები.",
"You have shared this chat": "ამ ჩატის გააგზავნა",
"You're a helpful assistant.": "თქვენ სასარგებლო ასისტენტი ხართ.",
"You're now logged in.": "თქვენ შესული ხართ.",
"Your account status is currently pending activation.": "",
"Youtube": "Youtube",
"Youtube Loader Settings": "Youtube Loader Settings"
}

Some files were not shown because too many files have changed in this diff Show More