Compare commits

...

2399 Commits

Author SHA1 Message Date
Timothy Jaeryang Baek
82cda6e522 Merge pull request #5699 from open-webui/dev
0.3.29
2024-09-25 15:46:39 +02:00
Timothy J. Baek
119a7f1933 doc: changelog 2024-09-25 15:45:36 +02:00
Timothy J. Baek
6c4445d545 fix: filter outlet issue 2024-09-25 13:44:06 +02:00
Timothy J. Baek
92b1acd6fb fix: RESET_CONFIG_ON_START not working 2024-09-25 01:06:11 +02:00
Timothy J. Baek
1767b64135 fix: 'call' url search param not working 2024-09-25 01:02:48 +02:00
Timothy Jaeryang Baek
e030f261d1 Merge pull request #5675 from sp301415/dev
fix: Fix KaTeX Rendering (Followup)
2024-09-24 20:58:22 +02:00
Hwang In Tak
d501ece247 fix: Fix KaTeX corner cases 2024-09-25 02:15:53 +09:00
Timothy Jaeryang Baek
534e4c90ca Merge pull request #5674 from open-webui/dev
0.3.28
2024-09-24 18:52:23 +02:00
Timothy J. Baek
40f2c3521b doc: changelog 2024-09-24 18:50:47 +02:00
Timothy J. Baek
07b1327708 fix 2024-09-24 18:32:14 +02:00
Timothy J. Baek
525095b3de fix: websearch not working issue
#5672
2024-09-24 18:25:21 +02:00
Timothy Jaeryang Baek
f84513e856 Merge pull request #5673 from open-webui/dev
refac: readme
2024-09-24 18:19:09 +02:00
Timothy J. Baek
bf423b8577 refac: readme 2024-09-24 18:18:32 +02:00
Timothy Jaeryang Baek
ba20c71963 Merge pull request #5661 from open-webui/dev
0.3.27
2024-09-24 18:13:08 +02:00
Timothy J. Baek
7bbc57f225 doc: changelog 2024-09-24 18:12:47 +02:00
Timothy J. Baek
e703e172e2 chore: format 2024-09-24 18:10:14 +02:00
Timothy Jaeryang Baek
3ff52fd1ad Merge pull request #5655 from sp301415/dev
fix: Fix KaTeX Rendering
2024-09-24 17:44:08 +02:00
Timothy J. Baek
e19406cdd7 fix 2024-09-24 17:43:43 +02:00
Hwang In Tak
30e65b33f6 fix: Add comments 2024-09-25 00:41:08 +09:00
Hwang In Tak
3f1255b39e fix: Change inline and block delimiters 2024-09-25 00:10:49 +09:00
Timothy J. Baek
71743b25fe chore: format 2024-09-24 16:42:42 +02:00
Timothy Jaeryang Baek
c7e93b32c5 Merge pull request #5660 from open-webui/pypi-release
fix: open-webui serve
2024-09-24 16:36:37 +02:00
Timothy J. Baek
3cee507687 fix: dev2 2024-09-24 16:19:24 +02:00
Timothy J. Baek
ff651ddc36 fix: dev1 2024-09-24 16:07:49 +02:00
Timothy Jaeryang Baek
c0738cef26 Merge pull request #5659 from open-webui/dev
0.3.26
2024-09-24 15:41:42 +02:00
Timothy J. Baek
a44e9a8dda refac 2024-09-24 15:41:23 +02:00
Timothy J. Baek
38b9a63fa5 refac 2024-09-24 15:40:37 +02:00
Timothy J. Baek
2d60e42258 doc: changelog 2024-09-24 15:40:01 +02:00
Timothy Jaeryang Baek
60ac69eb27 Merge pull request #5656 from OriginalSimon/dev
i18n: Update Ukrainian translation
2024-09-24 15:33:15 +02:00
Timothy J. Baek
504d910557 fix: no running event loop issue 2024-09-24 15:31:55 +02:00
Hwang In Tak
e48d66f918 fix: Remove unnecessary logging 2024-09-24 22:11:05 +09:00
Hwang In Tak
0bfbace9aa fix: Simplify regex 2024-09-24 22:00:01 +09:00
Timothy Jaeryang Baek
019cf8199f Merge pull request #5657 from open-webui/dev
0.3.25
2024-09-24 14:07:23 +02:00
Timothy J. Baek
c5f85eed92 doc: changelog 2024-09-24 14:07:13 +02:00
Timothy J. Baek
21719ccdf1 chore: format 2024-09-24 14:05:44 +02:00
Timothy J. Baek
299b3d72cf fix: rate responses 2024-09-24 14:02:41 +02:00
Timothy J. Baek
85e9e231ed fix: image generation 2024-09-24 13:54:34 +02:00
Simon
f382a78e31 Update translation.json 2024-09-24 13:47:51 +02:00
Hwang In Tak
377cc427b6 fix: Remove unnecessary logging 2024-09-24 20:40:50 +09:00
Timothy Jaeryang Baek
7ec72679f0 Merge pull request #5599 from open-webui/dev
0.3.24
2024-09-24 13:32:00 +02:00
Timothy J. Baek
31b311c3c9 refac
Co-Authored-By: MicroDev <70126934+microdev1@users.noreply.github.com>
2024-09-24 13:28:00 +02:00
Timothy J. Baek
e24ab4c6d2 doc: changelog 2024-09-24 13:23:34 +02:00
Timothy J. Baek
6739983cf1 refac: deprecate interface "stream response" settings for advanced params 2024-09-24 12:49:35 +02:00
Timothy J. Baek
ff00815b61 chore: format 2024-09-24 12:41:44 +02:00
Timothy J. Baek
8f6a927be3 enh: update info toast 2024-09-24 12:40:13 +02:00
Timothy J. Baek
f6add92702 chore: format 2024-09-24 11:35:51 +02:00
Timothy Jaeryang Baek
deedfdceae Merge pull request #5632 from jannikstdl/dev
enh: open PDF citations on the associated page
2024-09-24 11:27:53 +02:00
Timothy J. Baek
e268ee5675 enh: audio/x-m4a support 2024-09-24 11:00:47 +02:00
Timothy J. Baek
33d8d818bd fix 2024-09-24 10:54:49 +02:00
Timothy Jaeryang Baek
9a81a37008 Merge pull request #5645 from kivvi3412/main
[feat] Set whether to stream individually for the model
2024-09-24 10:52:00 +02:00
Timothy Jaeryang Baek
8e620b0c2c Merge pull request #5649 from EtiennePerot/temp-file-close
fix: close temporary file after creating it
2024-09-24 10:49:38 +02:00
Hwang In Tak
214546399a fix: fix katex rendering 2024-09-24 16:58:15 +09:00
Etienne Perot
fdd27aa321 fix: close temporary file after creating it.
This fixes "The process cannot access the file
because it is being used by another process"
errors on Windows.

The file is still automatically deleted by the
`os.unlink` call later in the function.

Updates #5606
Fixes #5642
2024-09-23 23:22:47 -07:00
kivvi
4ebff2c5ce Merge remote-tracking branch 'origin/main' 2024-09-24 12:29:36 +08:00
kivvi
8266d343bf Merge remote-tracking branch 'origin/main' 2024-09-24 12:29:11 +08:00
kivvi
36ddb19023 Merge remote-tracking branch 'origin/main' 2024-09-24 12:17:40 +08:00
kivvi
ebc410d8d4 Merge remote-tracking branch 'origin/main' 2024-09-24 12:17:33 +08:00
kivvi
1772db4712 Merge remote-tracking branch 'origin/main' 2024-09-24 12:14:58 +08:00
kivvi
40d7d7d6dd Set whether to stream responses for this model individually, overriding the global setting 2024-09-24 12:14:51 +08:00
kivvi
0d01ea5f2f Set whether to stream responses for this model individually, overriding the global setting 2024-09-24 11:51:47 +08:00
Timothy J. Baek
822c47c171 fix 2024-09-24 01:35:34 +02:00
Timothy J. Baek
fdf02c4e86 fix 2024-09-24 01:12:49 +02:00
Timothy J. Baek
398bc96b1a refac 2024-09-24 01:05:46 +02:00
Timothy J. Baek
ad82eae6a9 feat: create new message pair on cmd+shift+enter 2024-09-24 00:57:28 +02:00
Timothy J. Baek
d7b64ff447 enh: infinite scroll messages 2024-09-24 00:27:22 +02:00
Timothy J. Baek
93cb2be35d refac 2024-09-23 23:55:18 +02:00
Timothy J. Baek
8f1b9bdf8a refac 2024-09-23 23:52:45 +02:00
Jannik S.
f69956bda8 fix: only append link with page attribute if metatada.page is available 2024-09-23 23:43:50 +02:00
Timothy J. Baek
e06667ead8 refac 2024-09-23 23:39:33 +02:00
Timothy Jaeryang Baek
35f64cc53f Merge pull request #5640 from open-webui/messages-render-optimisation
refac: messages render optimisation
2024-09-23 23:27:08 +02:00
Timothy J. Baek
12f95555fc fix 2024-09-23 23:23:08 +02:00
Timothy J. Baek
84c1810b6e refac 2024-09-23 23:20:27 +02:00
Timothy J. Baek
ba39f9bf56 refac 2024-09-23 17:40:24 +02:00
Jannik Streidl
8eb82265d0 Remove animation import - unsure if animations are desired 2024-09-23 15:50:46 +02:00
Jannik Streidl
ac277e8e9e enh: CitationsModal 2024-09-23 15:48:12 +02:00
Timothy J. Baek
b1521cacad refac: WIP 2024-09-23 14:24:50 +02:00
Timothy J. Baek
5978e7c9a6 refac: wip 2024-09-23 01:36:46 +02:00
Timothy J. Baek
fd5e8b4fcf refac: deprecate messages for history 2024-09-23 00:55:13 +02:00
Timothy Jaeryang Baek
291b6dd744 Merge pull request #5613 from cevheri/dev
Turkish Language Support has been updated
2024-09-22 20:33:29 +02:00
Timothy J. Baek
73ff524a8f refac 2024-09-22 20:31:53 +02:00
cevheri
c2b5bf2130 Turkish Language Support has been fixed. 2024-09-22 21:20:43 +03:00
Timothy J. Baek
8532f9da03 fix: many model chat save as copy issue 2024-09-22 20:16:45 +02:00
Timothy Jaeryang Baek
2cfe6830df Merge pull request #5595 from sebdanielsson/dev
feat: Add more variables to prompts
2024-09-22 16:47:51 +02:00
Timothy J. Baek
44355a4bdc enh: 'model' url search param added 2024-09-22 14:52:30 +02:00
Timothy J. Baek
47a858393b fix: hide mobile sidebar after menu button click 2024-09-22 14:50:24 +02:00
Timothy J. Baek
d3e80f515d enh: hide pinned chats when searching 2024-09-22 14:49:53 +02:00
Timothy Jaeryang Baek
c5b93ca631 Merge pull request #5601 from JamesClarke7283/extend-num-predict-param
fix: Extend num predict param
2024-09-22 14:28:00 +02:00
Timothy J. Baek
3335eee1b9 refac: do not set max for input 2024-09-22 14:27:52 +02:00
Sebastian
29175405a6 Add weekday, timezone, language variables to system prompts 2024-09-22 12:24:05 +02:00
Sebastian
d53062a9b0 Add more variables to prompts 2024-09-22 11:49:18 +02:00
James Clarke
96ef15362a Increased max_tokens (num_predict) to 131072, fixes #5600 2024-09-22 05:43:04 +01:00
Timothy J. Baek
d6d6098378 refac 2024-09-22 02:57:51 +02:00
Timothy J. Baek
620e629edc refac 2024-09-22 02:57:38 +02:00
Timothy J. Baek
c292fd89f9 refac 2024-09-22 02:55:45 +02:00
Timothy J. Baek
c346130774 feat: overview favourite response 2024-09-22 02:53:38 +02:00
Timothy J. Baek
768717aaf9 refac 2024-09-22 02:35:25 +02:00
Timothy J. Baek
d055e1f888 refac 2024-09-22 02:14:59 +02:00
Timothy J. Baek
5f84145a2d enh: socket full redis support 2024-09-22 02:12:55 +02:00
Timothy J. Baek
47a9395a22 refac: styling 2024-09-22 01:42:18 +02:00
Timothy J. Baek
8dbac0f7e3 enh: show model hash and modified ts 2024-09-21 22:12:41 +02:00
Timothy Jaeryang Baek
6b463164f4 Merge pull request #5584 from open-webui/dev
fix: node tooltip xss issue
2024-09-21 21:44:25 +02:00
Timothy J. Baek
5f15e9ee68 fix: node tooltip xss issue
Co-Authored-By: Valentino Stillhardt <4715129+Fusseldieb@users.noreply.github.com>
2024-09-21 21:43:54 +02:00
Timothy Jaeryang Baek
54d63ece6f Merge pull request #5583 from open-webui/dev
refac
2024-09-21 21:35:54 +02:00
Timothy J. Baek
e35883ca9c fix: openai payload issue 2024-09-21 21:35:00 +02:00
Timothy Jaeryang Baek
19e49e43cb Merge pull request #5578 from aleixdorca/dev
i18n: Update catalan translation.json
2024-09-21 17:37:41 +02:00
Aleix Dorca
e429b5548c Update catalan translation.json 2024-09-21 17:27:32 +02:00
Timothy J. Baek
839dacc4a4 refac 2024-09-21 15:53:29 +02:00
Timothy J. Baek
4225591a26 fix 2024-09-21 15:48:52 +02:00
Timothy J. Baek
b4adffc3af fix 2024-09-21 15:48:16 +02:00
Timothy J. Baek
8fc178ae91 refac: chat controls size 2024-09-21 15:46:39 +02:00
Timothy J. Baek
580ad46036 refac: speedRate -> playbackRate 2024-09-21 15:42:39 +02:00
Timothy Jaeryang Baek
f47dffe6e1 Merge pull request #5576 from open-webui/dev
fix: WEBUI_AUTH=False not working issue
2024-09-21 15:35:55 +02:00
Timothy J. Baek
00f6b4bf09 refac 2024-09-21 15:35:35 +02:00
Timothy J. Baek
9126ceac08 fix: WEBUI_AUTH=False not working issue 2024-09-21 15:33:34 +02:00
Timothy Jaeryang Baek
ff8a2da751 Merge pull request #5565 from open-webui/dev
0.3.23
2024-09-21 04:55:29 +02:00
Timothy J. Baek
2f028b45fe refac 2024-09-21 04:53:44 +02:00
Timothy J. Baek
d3ef9d980b refac 2024-09-21 04:36:18 +02:00
Timothy J. Baek
cb81dfe4ba fix: voice recording not stopping 2024-09-21 04:27:18 +02:00
Timothy J. Baek
426de76690 refac 2024-09-21 04:24:38 +02:00
Timothy J. Baek
16a767e04e doc: changelog 2024-09-21 04:14:10 +02:00
Timothy J. Baek
2adaf9ba3d refac 2024-09-21 04:10:24 +02:00
Timothy J. Baek
f381850bb2 refac 2024-09-21 04:04:34 +02:00
Timothy Jaeryang Baek
273787fe78 Merge pull request #5541 from kivvi3412/fix-title-generate
[fix] Fix title generate
2024-09-21 03:58:28 +02:00
Timothy J. Baek
70d16c3904 refac: styling 2024-09-21 03:55:17 +02:00
Timothy J. Baek
ee6b1376c3 fix: rag duplicate collection issue 2024-09-21 03:53:53 +02:00
Timothy J. Baek
aed8e2156f refac 2024-09-21 03:44:44 +02:00
Timothy J. Baek
5d848ad130 refac 2024-09-21 03:39:30 +02:00
Timothy J. Baek
98928f6bd7 enh: save chat controls width 2024-09-21 03:37:28 +02:00
Timothy J. Baek
692f04d457 enh: width adjustable chat controls 2024-09-21 03:33:06 +02:00
kivvi
e1ea0c23eb Fixed the issue of being unable to generate titles 2024-09-21 09:06:28 +08:00
Timothy J. Baek
657d443a3e fix 2024-09-21 02:24:30 +02:00
Timothy J. Baek
95985e7bbb refac 2024-09-21 02:03:58 +02:00
Timothy J. Baek
3a0a1aca11 refac: task ollama stream support 2024-09-21 01:07:57 +02:00
Timothy J. Baek
41926172d3 fix/refac: use ollama /api/chat endpoint for tasks 2024-09-21 00:30:13 +02:00
Timothy J. Baek
585b9eb84a refac 2024-09-20 23:48:03 +02:00
Timothy J. Baek
ffd7d74f77 enh: websocket redis support 2024-09-20 23:43:22 +02:00
Timothy Jaeryang Baek
578d52b89d Merge pull request #5562 from open-webui/dev
fix: chat download as plain text issue
2024-09-20 23:19:51 +02:00
Timothy J. Baek
e599d5db3c fix: chat download as plain text issue 2024-09-20 23:19:20 +02:00
Timothy Jaeryang Baek
79b5430a9e Merge pull request #5546 from itaybar/bugfix/downgrade_authlib
downgrade authlib to 1.3.1
2024-09-20 17:41:19 +02:00
Timothy J. Baek
9b05fe3c54 Update pyproject.toml 2024-09-20 17:40:30 +02:00
Timothy Jaeryang Baek
5fe2795db8 Merge pull request #5556 from open-webui/dev
refac
2024-09-20 15:44:31 +02:00
Timothy J. Baek
732f730213 refac: click to focus on mesage node 2024-09-20 15:43:18 +02:00
Timothy Jaeryang Baek
c89bb01db9 Merge pull request #5554 from KarlLee830/translate
i18n: Update Chinese translation
2024-09-20 15:34:58 +02:00
Karl Lee
1cbbf75807 i18n: Update Chinese translation 2024-09-20 21:06:10 +08:00
itaybar
bd81fc8bff downgrade authlib to 1.3.1 2024-09-20 15:13:03 +03:00
Timothy Jaeryang Baek
d4df552076 Merge pull request #5537 from open-webui/dev
refac
2024-09-20 03:18:40 +02:00
Timothy J. Baek
b7ad82757d refac 2024-09-20 03:18:14 +02:00
Timothy J. Baek
d12b6cda4e refac: openai image async gen 2024-09-20 03:16:08 +02:00
Timothy Jaeryang Baek
83855b713b Merge pull request #5362 from open-webui/dev
0.3.22
2024-09-20 00:25:27 +02:00
Timothy J. Baek
bd09b6dbad doc: changelog 2024-09-20 00:25:09 +02:00
Timothy J. Baek
eb9ad47ef8 refac: temp tools & functions files 2024-09-20 00:12:52 +02:00
Timothy J. Baek
5b46a252ff doc: changelog 2024-09-20 00:00:45 +02:00
Timothy J. Baek
39c57c0e94 refac 2024-09-19 22:40:06 +02:00
Timothy J. Baek
619dbbe9f5 refac 2024-09-19 22:21:35 +02:00
Timothy J. Baek
9be73ea94a refac 2024-09-19 22:17:32 +02:00
Timothy J. Baek
4e43663448 refac 2024-09-19 22:12:54 +02:00
Timothy J. Baek
cd117f5b67 refac 2024-09-19 21:51:45 +02:00
Timothy J. Baek
2dad9b9432 refac 2024-09-19 20:56:13 +02:00
Timothy J. Baek
b0bc36f2af fix 2024-09-19 18:47:02 +02:00
Timothy J. Baek
1688f5ecaf refac 2024-09-19 18:42:01 +02:00
Timothy J. Baek
cba2d31175 refac 2024-09-19 18:40:23 +02:00
Timothy J. Baek
a2b77fd072 refac 2024-09-19 18:08:52 +02:00
Timothy J. Baek
9b83e57372 refac 2024-09-19 17:46:11 +02:00
Timothy J. Baek
687cae9b79 refac 2024-09-19 17:31:59 +02:00
Timothy J. Baek
f8fffdd288 refac: max_tokens -> max_completion_tokens 2024-09-19 17:19:31 +02:00
Timothy J. Baek
60d6279055 chore: format 2024-09-19 17:09:05 +02:00
Timothy J. Baek
7b330d1490 refac 2024-09-19 17:05:49 +02:00
Timothy J. Baek
7078af635c refac 2024-09-19 17:02:59 +02:00
Timothy J. Baek
e1b57d80a4 chore: format 2024-09-19 16:57:34 +02:00
Timothy J. Baek
8426874426 fix 2024-09-19 16:54:34 +02:00
Timothy J. Baek
70dd790afc refac: default rag params 2024-09-19 16:44:33 +02:00
Timothy J. Baek
e99cba53fe enh: stream=false support 2024-09-19 16:25:59 +02:00
Timothy J. Baek
628d7ae72d refac 2024-09-19 16:20:07 +02:00
Timothy J. Baek
ff737a9e25 enh: openai error message handling 2024-09-19 16:20:00 +02:00
Timothy J. Baek
5c16631ec5 refac 2024-09-19 15:35:01 +02:00
Timothy Jaeryang Baek
d52eaf19d6 Merge pull request #5511 from EtiennePerot/import-file
fix: restore `__file__` variable for imported toolkits and functions
2024-09-19 15:29:34 +02:00
Timothy J. Baek
27dd6ef14e refac 2024-09-19 05:15:06 +02:00
Timothy J. Baek
ed75f72358 refac 2024-09-19 03:53:07 +02:00
Timothy J. Baek
276d629a14 fix: message delete 2024-09-19 03:49:35 +02:00
Timothy J. Baek
aedd77b81d refac 2024-09-19 03:27:54 +02:00
Timothy J. Baek
1053863175 chore: format 2024-09-19 03:24:39 +02:00
Timothy J. Baek
f448341211 chore: format 2024-09-19 03:24:34 +02:00
Timothy Jaeryang Baek
9fc6b999d0 Merge pull request #5509 from open-webui/dev-playback-controls
feat: playback controls
2024-09-19 03:23:16 +02:00
Timothy J. Baek
ff2fff857a refac: styling 2024-09-19 03:22:55 +02:00
Timothy Jaeryang Baek
dd4cf102cc Merge pull request #5313 from zabirauf/u/zabirauf/speech-speed
feat: Added speech playback speed control for Call mode
2024-09-19 02:44:27 +02:00
Timothy Jaeryang Baek
5d3a89dd25 Merge pull request #5496 from pawel-ochman/azure-tts
Integrate Azure Speech service for TTS
2024-09-19 02:42:45 +02:00
Timothy J. Baek
b4f1a0b5a6 refac 2024-09-19 02:42:24 +02:00
Timothy J. Baek
afa42dd2e4 refac 2024-09-19 02:40:54 +02:00
Timothy J. Baek
be44af4680 enh: focus on current message 2024-09-19 01:25:46 +02:00
Timothy J. Baek
e6b6f42139 refac: display error content on node 2024-09-18 16:46:13 +02:00
Pawel Ochman
4d9677e808 Update configuration page, expose all Azure settings through ENV variables 2024-09-18 14:13:42 +01:00
Pawel Ochman
eacb69074e remove dependency and migrate to raw rest calls 2024-09-18 12:24:55 +01:00
Etienne Perot
6477bf37fe fix: restore __file__ variable for imported toolkits and functions
Commit cf86ba7786 changed the way toolkits
and functions were imported to use `exec`, whereas they previously were
written to files and `import`ed. The use of `exec` means that
module-global variables such as `__file__` are no longer defined.

This breaks https://github.com/EtiennePerot/open-webui-code-execution
(code execution tool for Open WebUI), as the module needs to re-execute
its own code in a subprocess in order to properly sandbox itself. This
is done using `__file__` in order to know where the module's code is
located.

This PR creates a temporary in-memory file that contains the imported
toolkit or function's code and exists only during the import process.
Then it injects the path to this in-memory file as the `__file__`
variable in the `exec` context. This restores the ability for the
toolkit or function being imported to rely on `__file__`.
2024-09-18 01:08:30 -07:00
Timothy J. Baek
1743d3c6c1 fix 2024-09-18 03:47:04 +02:00
Timothy J. Baek
e723b2a4c6 refac 2024-09-18 03:19:32 +02:00
Timothy J. Baek
67f704c98d enh: scroll to message from overview 2024-09-18 03:13:37 +02:00
Timothy J. Baek
8d92093570 enh: node show content as tooltip 2024-09-18 02:55:25 +02:00
Timothy J. Baek
1ccac9111b refac: only animate active edges 2024-09-18 02:42:19 +02:00
Timothy J. Baek
98984166f9 refac: styling 2024-09-18 02:11:25 +02:00
Timothy J. Baek
d1bf18eeb0 fix 2024-09-18 01:57:27 +02:00
Timothy J. Baek
2018a6c000 fix: styling 2024-09-18 01:53:08 +02:00
Timothy J. Baek
56152230f8 refac 2024-09-18 01:39:22 +02:00
Timothy J. Baek
7e8cf5504a refac: styling 2024-09-18 01:35:22 +02:00
Timothy J. Baek
3c03d5069d refac: styling 2024-09-18 01:31:49 +02:00
Timothy J. Baek
705508a674 refac: allow chat menu in mobile 2024-09-18 01:30:09 +02:00
Timothy J. Baek
771482c6e6 refac 2024-09-18 01:25:28 +02:00
Timothy J. Baek
d25ccfba5f refac: styling 2024-09-18 01:21:32 +02:00
Timothy J. Baek
614c219010 enh: prepend image filename with prompt 2024-09-18 01:04:20 +02:00
Timothy J. Baek
63b3076d64 refac 2024-09-18 00:52:06 +02:00
Timothy J. Baek
8e3ad45ce4 enh: model move to top 2024-09-18 00:49:27 +02:00
Timothy J. Baek
984e0c533e refac 2024-09-18 00:18:47 +02:00
Timothy J. Baek
5065291f72 feat: save as new response message 2024-09-17 23:36:48 +02:00
Timothy J. Baek
8c273ba58a refac 2024-09-17 23:23:38 +02:00
Timothy J. Baek
7a9c0946a4 refac 2024-09-17 23:13:51 +02:00
Timothy J. Baek
7e0a26ef4e refac 2024-09-17 23:07:04 +02:00
Timothy J. Baek
65b7c9898b fix 2024-09-17 23:02:41 +02:00
Timothy J. Baek
67f95ddfdc refac 2024-09-17 22:58:06 +02:00
Timothy J. Baek
d1dbb9a3be feat: chat overview 2024-09-17 22:05:19 +02:00
Timothy J. Baek
bb087a5989 enh: chat copy button 2024-09-17 21:32:39 +02:00
Timothy Jaeryang Baek
a0d24105fc Merge pull request #5473 from aleixdorca/dev
i18n: Update Catalan Translation
2024-09-17 17:18:40 +02:00
Timothy Jaeryang Baek
a5c9160b7d Merge pull request #5466 from phil-ogb/add-security-response-headers
feat: security response headers
2024-09-17 17:18:28 +02:00
Aleix Dorca
0e2cdbe9fb Minor typo 2024-09-17 16:49:05 +02:00
Aleix Dorca
3c55a46484 i18n: Update Catalan translation.json 2024-09-17 16:46:52 +02:00
Pawel Ochman
d6b68f405e added azure speech service support 2024-09-17 09:13:10 +01:00
Pawel Ochman
351bbdb36c Added Azure speach service option (UI) 2024-09-17 08:47:30 +01:00
Phil Ogbonna
896baf021b update comment block 2024-09-16 22:02:55 -03:00
Phil Ogbonna
499e5e4f60 feat: security response headers 2024-09-16 21:53:30 -03:00
Timothy J. Baek
3ad003bccb fix 2024-09-16 16:42:18 +02:00
Timothy J. Baek
af92184c93 chore: colbert-ai requirement 2024-09-16 16:19:40 +02:00
Timothy J. Baek
06debb322b refac: colbert cuda support 2024-09-16 12:42:48 +02:00
Timothy J. Baek
b7f0759485 refac 2024-09-16 12:36:43 +02:00
Timothy J. Baek
bc6f23f82f fix 2024-09-16 12:33:55 +02:00
Timothy J. Baek
cb9e76c7f9 refac: default rag template 2024-09-16 12:01:04 +02:00
Timothy J. Baek
b38986a0aa enh: colbert rerank support 2024-09-16 11:46:39 +02:00
Timothy J. Baek
db0c576f48 refac 2024-09-16 07:14:17 +02:00
Timothy Jaeryang Baek
40d7e5089d Merge pull request #5436 from khanh-alice/fix-transparent-icons
fix: model transparent icons
2024-09-16 07:05:17 +02:00
Timothy Jaeryang Baek
9b8d42c670 Merge pull request #5440 from cheahjs/feat/capabilities-help
feat: add help text for capabilities
2024-09-16 05:17:32 +02:00
Jun Siang Cheah
bed3b71860 feat: add help text for capabilities 2024-09-15 14:14:09 +01:00
Khanh Le
253791b92c save model icon as png 2024-09-15 16:43:42 +07:00
Timothy J. Baek
5dd6ae6ec4 chore: npm 2024-09-14 23:30:56 +01:00
Timothy J. Baek
902f30c123 enh: table view allow overflow 2024-09-14 23:23:52 +01:00
Timothy J. Baek
fa8d7bd9c6 enh: allow new lines in default prompts 2024-09-14 23:17:58 +01:00
Timothy J. Baek
d0df2cbe53 fix: disable "enable new sign ups" not working issue 2024-09-14 23:13:52 +01:00
Timothy Jaeryang Baek
27baa00afb Merge pull request #5419 from cheahjs/fix/remove-doc-support
fix: remove unsupported .doc file ingest
2024-09-14 22:52:40 +01:00
Timothy J. Baek
869063c743 refac: better reranking model error handling 2024-09-14 20:58:42 +01:00
Timothy Jaeryang Baek
2f9f568dd9 Merge pull request #5400 from thiswillbeyourgithub/fix_fallback_cuda
fix: if cuda is not available fallback to cpu
2024-09-14 20:57:14 +01:00
Timothy Jaeryang Baek
937ce5f797 Merge pull request #5411 from KarlLee830/translate
i18n: Update Chinese translation
2024-09-14 20:56:13 +01:00
Timothy Jaeryang Baek
1b612209a3 Merge pull request #5429 from OriginalSimon/dev
i18n: Update Ukrainian translation
2024-09-14 20:56:03 +01:00
Simon
d00d3341af Update translation.json 2024-09-14 20:32:04 +02:00
Jun Siang Cheah
3199e26500 fix: remove unsupported .doc file ingest 2024-09-14 12:44:51 +01:00
Karl Lee
bc06e7a282 i18n: Update Chinese translation 2024-09-14 10:10:15 +08:00
Timothy Jaeryang Baek
1eec9e2b59 Merge pull request #5407 from Peter-De-Ath/citations-page-no
feat: add page no to citations
2024-09-13 21:55:45 +01:00
Peter De-Ath
d46f652f7e enh: show page number in citation if known 2024-09-13 21:05:28 +01:00
Timothy Jaeryang Baek
d75d638b9a Merge pull request #5406 from open-webui/main
refac
2024-09-13 19:26:51 +01:00
Timothy J. Baek
b64c9d966a refac 2024-09-13 14:26:32 -04:00
Timothy Jaeryang Baek
8a928e5356 Merge pull request #5405 from open-webui/main
refac: filter non chat completions models
2024-09-13 19:23:02 +01:00
Timothy J. Baek
adf958559b refac: filter non chat completions models 2024-09-13 14:20:27 -04:00
thiswillbeyourgithub
82b35492af pep8 2024-09-13 17:18:44 +02:00
thiswillbeyourgithub
a7ea07036e fix: if cuda is not available fallback to cpu 2024-09-13 17:12:00 +02:00
Timothy Jaeryang Baek
c1d3481c41 Merge pull request #5399 from open-webui/main
fix: allow o1
2024-09-13 15:01:48 +01:00
Timothy J. Baek
bc0baa35e6 fix: allow o1 2024-09-13 09:59:41 -04:00
Timothy J. Baek
f549cb1f87 fix 2024-09-13 01:30:30 -04:00
Timothy J. Baek
823093eea6 fix: hybrid search 2024-09-13 01:21:47 -04:00
Timothy J. Baek
939bfd153e refac 2024-09-13 01:18:20 -04:00
Timothy J. Baek
b943b7d337 refac 2024-09-13 01:08:02 -04:00
Timothy J. Baek
a1f3ece528 refac 2024-09-13 01:07:03 -04:00
Timothy J. Baek
8a4b3e6bc9 refac: allow multiple [context] in prompt 2024-09-13 01:06:51 -04:00
Timothy J. Baek
a9c497612b refac: rm assert 2024-09-13 00:56:50 -04:00
Timothy J. Baek
7df997c992 chore: format 2024-09-13 00:49:23 -04:00
Timothy J. Baek
bebc0d2073 chore: format 2024-09-13 00:48:54 -04:00
Timothy Jaeryang Baek
857fc3ce99 Merge pull request #5276 from sebdanielsson/add-theme-color
fix: Set theme colors to fix white top bar for PWA
2024-09-13 05:43:25 +01:00
Timothy J. Baek
47e9c12fc2 refac 2024-09-13 00:41:20 -04:00
Timothy Jaeryang Baek
5970dadead Merge pull request #5256 from Bazsalanszky/main
feat: More options for AUTOMATIC1111
2024-09-13 05:40:09 +01:00
Timothy Jaeryang Baek
7dc4cb30b2 Merge pull request #5378 from thiswillbeyourgithub/fix_RAG_and_web
fix: RAG and Web Search + RAG enhancements
2024-09-13 05:38:53 +01:00
Timothy Jaeryang Baek
fb122e67d0 Merge pull request #5382 from Peter-De-Ath/hotfix/chroma-metadata-s
fix: change metadata to metadatas
2024-09-12 22:30:08 +01:00
Peter De-Ath
ca9874757f fix: change metadata to metadatas 2024-09-12 20:14:14 +01:00
thiswillbeyourgithub
65d5545cf0 added a few type hints 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
e872f5dc78 log: added a debug log if detecting a potential prompt injection attack 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
b4ad64586a fix: add check that the context for RAG is not empty if the threshold is 0 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
9661fee554 fix: handle case where [query] happens in the RAG context 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
adf26789b8 logs: crash if rag_template would be wrong 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
209e246e6f fix: much improved RAG template 2024-09-12 17:22:22 +02:00
thiswillbeyourgithub
ed2a1e7db9 enh: use non hybrid search as fallback if hybrid search failed 2024-09-12 17:22:22 +02:00
Timothy J. Baek
143ac08c35 refac 2024-09-12 10:56:16 -04:00
thiswillbeyourgithub
53f03f6556 fix: log exception when issues of collection querying 2024-09-12 16:51:37 +02:00
Timothy J. Baek
62f1933e3c refac: audio input (audio/ogg support) 2024-09-12 09:18:20 -04:00
Timothy J. Baek
0b30dc357c refac: remove prints 2024-09-12 09:13:21 -04:00
Timothy J. Baek
d5b595a842 fix: ol numbering 2024-09-12 09:11:45 -04:00
Balazs Toldi
d05ba042c0 Make the optional AUTOMATIC1111 values nullable
This commit makes the optional AUTOMATIC1111 options default to None, and if the value is removed, it resets to None.

Signed-off-by: Balazs Toldi <balazs@toldi.eu>
2024-09-12 14:00:24 +02:00
Timothy J. Baek
eed2d735a1 refac 2024-09-12 02:06:02 -04:00
Timothy Jaeryang Baek
675403d26d Merge pull request #5364 from open-webui/multiple-vector-dbs
refac: vector db clients
2024-09-12 07:00:55 +01:00
Timothy J. Baek
8be6e16513 refac: vector db clients 2024-09-12 02:00:31 -04:00
Timothy Jaeryang Baek
c7fc17da69 Merge pull request #5312 from open-webui/multiple-vector-dbs
feat: various vector db support
2024-09-12 06:53:47 +01:00
Timothy J. Baek
4775fe43d8 feat: milvus support 2024-09-12 01:52:19 -04:00
Sebastian
2a04dd0f9b Set theme colors to fix white top bar for PWA 2024-09-11 01:46:39 +02:00
Timothy Jaeryang Baek
61ee4bd629 Merge pull request #5319 from Liuzhch1/fix-openai_timeout
fix: get OpenAI models only if OpenAI API Enabled; timeout for querying OpenAI models
2024-09-10 23:03:20 +01:00
Timothy Jaeryang Baek
dbd661a417 Merge pull request #5318 from moblangeois/french-translation
i18n: Update French (fr-FR) translation
2024-09-10 23:02:34 +01:00
Liuzhch1
26700ac4ac fix: get OpenAI models only if OpenAI Enabled;timeout for query OpenAI models 2024-09-10 19:22:05 +08:00
Morgan Blangeois
b0defe5524 i18n: Update French (fr-FR) translation 2024-09-10 12:54:47 +02:00
Zohaib Rauf
91cd8c7608 Undid a unnecessary change 2024-09-09 21:59:13 -07:00
Zohaib Rauf
62b01c5f8e Cleaned up 2024-09-09 21:57:53 -07:00
Zohaib Rauf
b33ab6c5fd Updated to use Dropdown menu which is being used elsewhere in app 2024-09-09 21:33:48 -07:00
Timothy J. Baek
0886b3a0a4 refac: comments 2024-09-10 04:46:40 +01:00
Timothy J. Baek
522afbb0a0 refac 2024-09-10 04:37:06 +01:00
Timothy Jaeryang Baek
d5f13dd9e0 Merge pull request #5311 from open-webui/dev
dev
2024-09-10 02:30:02 +01:00
Timothy Jaeryang Baek
3d6d8c91dd Merge branch 'multiple-vector-dbs' into dev 2024-09-10 02:29:55 +01:00
Timothy J. Baek
4354f270ce refac 2024-09-10 02:27:50 +01:00
Timothy J. Baek
28087ccf40 refac 2024-09-10 01:37:36 +01:00
Timothy J. Baek
eb0e683b47 refac 2024-09-10 01:34:27 +01:00
Timothy Jaeryang Baek
1023ff8454 Merge pull request #5270 from cheahjs/fix/websocket-take-2
fix: socket.io connections failing when websockets are not available
2024-09-09 23:19:05 +01:00
Jun Siang Cheah
9401f6c821 fix: workaround socketio upstream bug when websockets are not available 2024-09-09 23:17:34 +01:00
Jun Siang Cheah
827c419251 feat: add ENABLE_WEBSOCKET_SUPPORT to force socket.io to ignore websocket upgrades 2024-09-09 23:17:17 +01:00
Timothy Jaeryang Baek
82db64a700 Merge pull request #5279 from afritzler/enh/kustomization
feat: Improve `kustomization` usage
2024-09-09 23:04:29 +01:00
Timothy J. Baek
f1fae805a2 fix: separate /embed and /embedding ollama endpoint 2024-09-09 23:02:26 +01:00
Timothy Jaeryang Baek
272e2386dd Merge pull request #5300 from FINNSEEFLY/task/adjust-ru-localization
i18n: Update ru-RU localization
2024-09-09 22:59:44 +01:00
FINNSEEFLY
67e1c0a10b Adjust ru-RU localization 2024-09-09 22:49:55 +03:00
Zohaib Rauf
f88a86f9b0 Fixed build error 2024-09-08 22:57:33 -07:00
Timothy J. Baek
601982f52b fix: lengthy chat title delete ui issue 2024-09-09 04:52:12 +01:00
Timothy Jaeryang Baek
fc839011f6 Merge pull request #5275 from sebdanielsson/safe-area
fix: Add padding to compensate for iPhone nav bar
2024-09-09 04:42:45 +01:00
Timothy Jaeryang Baek
b407f24950 Merge pull request #5277 from msurma/dev
fix: incorrect casting of top_p and frequency_penalty
2024-09-09 04:36:22 +01:00
Timothy Jaeryang Baek
d15f57cfff Merge pull request #5266 from KarlLee830/translate
i18n: Update Chinese translation
2024-09-09 04:34:47 +01:00
Andreas Fritzler
82fbfd69a5 Improve kustomization usage
Ensure that the `manifest/base` folder can be used as a standalone
kustomization resource.

Add a new subfolder `manifest/gpu` which uses `manifest/base` with
additional GPU related patches.
2024-09-08 20:43:00 +02:00
Michał Surmaczewski
8e6ea49e0e fix: incorrect casting of top_p and frequency_penalty 2024-09-08 17:52:58 +02:00
Sebastian
83a3e53d8d Add padding to compensate for iPhone nav bar 2024-09-08 17:52:10 +02:00
Jun Siang Cheah
698976add0 feat: add ENABLE_WEBSOCKET_SUPPORT to force socket.io to ignore websocket upgrades 2024-09-08 12:00:36 +01:00
Karl Lee
cc1d3c48e0 i18n: Update Chinese translation 2024-09-08 16:51:14 +08:00
Timothy Jaeryang Baek
e510c8b11f Merge pull request #5263 from open-webui/dev
refac
2024-09-08 01:52:27 +01:00
Timothy J. Baek
666086a806 refac 2024-09-08 01:17:02 +01:00
Timothy J. Baek
9bdbe88bda refac: default search query prompt 2024-09-08 01:04:57 +01:00
Timothy Jaeryang Baek
50db51ebe0 Merge pull request #5262 from open-webui/dev
0.3.21
2024-09-08 00:59:40 +01:00
Timothy J. Baek
0beaab51ae doc: changelog 2024-09-08 00:57:59 +01:00
Timothy Jaeryang Baek
0e30b0f9b4 Merge pull request #5010 from jannikstdl/show-total-docs
feat: show total number of documents
2024-09-08 00:52:45 +01:00
Timothy J. Baek
214722d39e enh: search query generation prompt 2024-09-08 00:51:12 +01:00
Balazs Toldi
7f6dae41f0 More options for AUTOMATIC1111
This commit adds 3 new options to the AUTOMATIC1111 settings:
- CFG Scale
- Sampler
- Scheduler

These options allow users to configure these parameters directly through the admin settings, without needing to modify the source code, which was previously required to change the default values in  AUTOMATIC1111.

Signed-off-by: Balazs Toldi <balazs@toldi.eu>
2024-09-07 17:21:17 +02:00
Jannik S.
9aa8eff44e styling 2024-09-07 15:08:25 +02:00
Timothy Jaeryang Baek
2544f7eaf0 Merge pull request #5249 from open-webui/dev
refac: default search generation prompt
2024-09-07 06:42:12 +02:00
Timothy J. Baek
1a6ce1d5d9 refac: default search generation prompt 2024-09-07 05:41:55 +01:00
Timothy Jaeryang Baek
98eaec22d4 Merge pull request #5248 from open-webui/dev
fix
2024-09-07 06:20:35 +02:00
Timothy J. Baek
2e40719f4e fix 2024-09-07 05:18:52 +01:00
Timothy Jaeryang Baek
71a2bd2fea Merge pull request #5247 from open-webui/dev
refac: enable /api/embed
2024-09-07 06:13:02 +02:00
Timothy J. Baek
1c20db775c refac: enable /api/embed 2024-09-07 05:12:46 +01:00
Timothy Jaeryang Baek
e2ef36b582 Merge pull request #5238 from open-webui/dev
0.3.20
2024-09-07 06:08:23 +02:00
Timothy J. Baek
90a064972c fix 2024-09-07 05:07:37 +01:00
Timothy J. Baek
f4a0b845be doc: wording 2024-09-07 05:06:32 +01:00
Timothy J. Baek
1f22aa99d8 doc: changelog 2024-09-07 05:05:54 +01:00
Timothy J. Baek
4c9ea084d5 chore: format 2024-09-07 05:03:26 +01:00
Timothy J. Baek
a3094bcd1b fix: all response messages re-rendering on new message 2024-09-07 04:54:48 +01:00
Timothy J. Baek
5c8fb4b3d5 refac: web search 2024-09-07 04:50:29 +01:00
Timothy J. Baek
ff46fe2b4a refac 2024-09-07 03:09:57 +01:00
Timothy J. Baek
8d6a424604 fix: markdown proper spacing 2024-09-07 02:56:58 +01:00
Timothy J. Baek
8dfbdbd883 fix: mic kept alive after call issue 2024-09-07 01:28:07 +01:00
Timothy J. Baek
f533c9750b fix: close chat controls after call ends 2024-09-07 01:12:43 +01:00
Timothy J. Baek
2f841f9f5a fix: enable inline link image rendering 2024-09-06 23:40:35 +02:00
Timothy J. Baek
02d5bca44d fix: tools & function not installing requirements 2024-09-06 18:35:43 +02:00
Timothy J. Baek
14eda1bf5b fix: pdf download FONTS_DIR issue 2024-09-06 15:52:23 +02:00
Timothy Jaeryang Baek
2d4cdc5be9 Merge pull request #5209 from aleixdorca/dev
i18n: Update Catalan translation.json
2024-09-06 14:52:55 +02:00
Aleix Dorca
d038e831dc i18n: Update Catalan translation.json 2024-09-06 07:20:21 +02:00
Timothy J. Baek
9fe62fc80d refac 2024-09-06 05:30:16 +02:00
Timothy J. Baek
bfb12a7851 refac 2024-09-06 04:59:20 +02:00
Timothy Jaeryang Baek
4617f3a4e2 Merge pull request #5200 from open-webui/dev
fix
2024-09-05 21:01:12 +02:00
Timothy J. Baek
97e331632c fix: call overlay issue 2024-09-05 21:00:53 +02:00
Timothy J. Baek
4cf777ab5a refac: styling 2024-09-05 20:52:27 +02:00
Timothy Jaeryang Baek
05c0423d6e Merge pull request #5197 from open-webui/dev
0.3.19
2024-09-05 20:47:33 +02:00
Timothy J. Baek
377efc8a0c doc: changelog 2024-09-05 20:46:32 +02:00
Timothy J. Baek
b35bbaade2 fix: extract_frontmatter issue 2024-09-05 20:35:58 +02:00
Timothy J. Baek
c9107fa87f refac 2024-09-05 19:11:27 +02:00
Timothy J. Baek
0c1fab09ff refac 2024-09-05 18:55:31 +02:00
Timothy J. Baek
8b67959695 refac: styling 2024-09-05 18:44:52 +02:00
Timothy J. Baek
21e81d78d9 refac 2024-09-05 17:25:24 +02:00
Timothy J. Baek
31623ff330 refac: styling 2024-09-05 17:23:59 +02:00
Timothy J. Baek
7edfffdcc5 refac: styling 2024-09-05 17:11:55 +02:00
Timothy Jaeryang Baek
3b868be77b Merge pull request #5185 from open-webui/main
refac: styling
2024-09-05 17:04:10 +02:00
Timothy J. Baek
c3271e84ef refac: styling 2024-09-05 17:03:09 +02:00
Timothy Jaeryang Baek
1cac9fce46 Merge pull request #5182 from open-webui/main
dev
2024-09-05 16:26:15 +02:00
Timothy J. Baek
d0869bbfbc fix: migrations 2024-09-05 16:23:19 +02:00
Timothy J. Baek
ca4beb413b refac: styling 2024-09-05 16:21:34 +02:00
Timothy Jaeryang Baek
7b31ef60fb Merge pull request #5161 from KarlLee830/translate
i18n: Update Chinese translation
2024-09-05 16:15:46 +02:00
Timothy Jaeryang Baek
73576dfcaf Merge pull request #5180 from open-webui/main
dev
2024-09-05 16:14:11 +02:00
Timothy J. Baek
8a411decac fix 2024-09-05 16:13:40 +02:00
Timothy Jaeryang Baek
fa786c8e05 Merge pull request #5160 from vikrantrathore/main
fix: avoid overriding DATA_DIR and prevent errors when directories are the same
2024-09-05 16:11:42 +02:00
Timothy J. Baek
85fc35492d refac 2024-09-05 16:11:07 +02:00
Karl Lee
1c94f4dd71 i18n: Update Chinese translation 2024-09-05 15:28:13 +08:00
vikrantrathore
74169b0320 fix: avoid overriding DATA_DIR and prevent errors when directories are the same
Previously, the `DATA_DIR` environment variable was always overridden by defaulting to `OPEN_WEBUI_DIR / "data"`, which ignored user-defined `DATA_DIR` values. Additionally, when `DATA_DIR` and `NEW_DATA_DIR` were the same, the script attempted to copy files into themselves, leading to errors or redundant operations.

This commit ensures that:
1. The `DATA_DIR` environment variable is respected and not overridden.
2. Copy operations between `DATA_DIR` and `NEW_DATA_DIR` are only performed if the directories are different, preventing errors when they point to the same location.

These changes resolve potential file copy errors and preserve user configurations.
2024-09-05 14:17:58 +08:00
Timothy Jaeryang Baek
83574ccf6c Merge pull request #5159 from drupol/let-customize-pip-install
feat: add `OVERRIDE_PIP_INSTALL` env. variable
2024-09-04 23:01:01 +02:00
Timothy J. Baek
a0be3822bf refac 2024-09-04 23:00:01 +02:00
Pol Dellaiera
004700c125 feat: add OVERRIDE_PIP_INSTALL environment variable 2024-09-04 22:44:59 +02:00
Timothy Jaeryang Baek
19ee110b7d Merge pull request #5158 from pascallim/fix/start_scripts
fix scripts to point to correct path
2024-09-04 20:29:58 +02:00
Pascal Lim
998616c0fd fix scripts to point to correct path 2024-09-04 20:27:30 +02:00
Timothy Jaeryang Baek
9204498420 Merge pull request #5157 from open-webui/dev
0.3.18
2024-09-04 20:09:58 +02:00
Timothy J. Baek
b1957e5cfe doc: changelog 2024-09-04 20:08:14 +02:00
Timothy J. Baek
92a88df484 refac 2024-09-04 20:00:47 +02:00
Timothy J. Baek
f2f713023d refac 2024-09-04 19:57:41 +02:00
Timothy J. Baek
cf86ba7786 refac: tools & functions 2024-09-04 19:55:20 +02:00
Timothy J. Baek
94502d6494 fix: styling 2024-09-04 19:55:10 +02:00
Timothy Jaeryang Baek
5e3f9ec757 Merge pull request #5156 from open-webui/dev
fix
2024-09-04 19:04:03 +02:00
Timothy J. Baek
d6fc0ccf65 fix 2024-09-04 19:03:51 +02:00
Timothy Jaeryang Baek
a988c53949 Merge pull request #5155 from open-webui/dev
fix: tools & functions import
2024-09-04 19:00:52 +02:00
Timothy J. Baek
3afd66d50f fix: tools & functions import 2024-09-04 18:59:50 +02:00
Timothy Jaeryang Baek
a9801147b8 Merge pull request #5051 from open-webui/dev
0.3.17
2024-09-04 18:40:16 +02:00
Timothy J. Baek
f3d488fb0c doc: changelog 2024-09-04 18:37:09 +02:00
Timothy J. Baek
28e3701187 Update release-pypi.yml 2024-09-04 18:00:38 +02:00
Timothy J. Baek
8f6369374d refac: error handling 2024-09-04 17:52:59 +02:00
Timothy J. Baek
e5cfa6501b dev6 2024-09-04 17:47:51 +02:00
Timothy J. Baek
175ffc5c66 dev5 2024-09-04 17:33:39 +02:00
Timothy J. Baek
c0441ab2b8 dev4 2024-09-04 17:14:24 +02:00
Timothy J. Baek
6d1bd3ab66 dev4 2024-09-04 17:02:10 +02:00
Timothy J. Baek
1779e6fecc chore: format 2024-09-04 16:58:28 +02:00
Timothy J. Baek
03d5a670f6 refac: mv backend files to /open_webui dir 2024-09-04 16:54:48 +02:00
Timothy J. Baek
76806a998f fix: automatic1111 model update issue 2024-09-04 15:25:31 +02:00
Timothy J. Baek
9bcbf5e9b3 Update config.py 2024-09-03 21:46:40 +02:00
Timothy J. Baek
6bbb755997 feat: import/export config 2024-09-03 21:16:07 +02:00
Timothy Jaeryang Baek
aec7cd572c Merge pull request #5127 from open-webui/dependabot/pip/pip-5bab50f10f
build(deps): bump the pip group across 2 directories with 1 update
2024-09-03 20:17:04 +02:00
dependabot[bot]
856759d350 build(deps): bump the pip group across 2 directories with 1 update
Bumps the pip group with 1 update in the / directory: [flask-cors](https://github.com/corydolphin/flask-cors).
Bumps the pip group with 1 update in the /backend directory: [flask-cors](https://github.com/corydolphin/flask-cors).


Updates `flask-cors` from 4.0.1 to 5.0.0
- [Release notes](https://github.com/corydolphin/flask-cors/releases)
- [Changelog](https://github.com/corydolphin/flask-cors/blob/main/CHANGELOG.md)
- [Commits](https://github.com/corydolphin/flask-cors/compare/4.0.1...5.0.0)

Updates `flask-cors` from 4.0.1 to 5.0.0
- [Release notes](https://github.com/corydolphin/flask-cors/releases)
- [Changelog](https://github.com/corydolphin/flask-cors/blob/main/CHANGELOG.md)
- [Commits](https://github.com/corydolphin/flask-cors/compare/4.0.1...5.0.0)

---
updated-dependencies:
- dependency-name: flask-cors
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: flask-cors
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-03 15:32:52 +00:00
Timothy J. Baek
5f92f7e41f enh: prevent trailing / from comfyui base url
Co-Authored-By: qwertyoriuop <41389168+qwertyoriuop@users.noreply.github.com>
2024-09-03 16:19:34 +02:00
Timothy J. Baek
890824ced4 fix: advanced params not being applied to ollama 2024-09-03 15:43:26 +02:00
Timothy J. Baek
2cd1207e73 fix: mermaid error on rating 2024-09-03 15:39:09 +02:00
Timothy J. Baek
1803c7adeb refac 2024-09-03 15:24:58 +02:00
Timothy J. Baek
fa8bb51b81 refac 2024-09-03 15:23:38 +02:00
Timothy J. Baek
9bea1950dc feat: web search url search param 2024-09-03 15:15:46 +02:00
Timothy Jaeryang Baek
df0bb4b4b0 Merge pull request #5070 from open-webui/dependabot/pip/backend/dev/authlib-1.3.2
build(deps): bump authlib from 1.3.1 to 1.3.2 in /backend
2024-09-03 14:51:30 +02:00
Timothy Jaeryang Baek
fdfa96ba51 Merge pull request #5069 from open-webui/dependabot/pip/backend/dev/duckduckgo-search-approx-eq-6.2.11
build(deps): update duckduckgo-search requirement from ~=6.2.1 to ~=6.2.11 in /backend
2024-09-03 14:51:24 +02:00
Timothy Jaeryang Baek
ff94a8e57f Merge pull request #5068 from open-webui/dependabot/pip/backend/dev/aiohttp-3.10.5
build(deps): bump aiohttp from 3.10.2 to 3.10.5 in /backend
2024-09-03 14:51:17 +02:00
Timothy Jaeryang Baek
41369aefdf Merge pull request #5067 from open-webui/dependabot/pip/backend/dev/langchain-0.2.15
build(deps): bump langchain from 0.2.14 to 0.2.15 in /backend
2024-09-03 14:51:11 +02:00
Timothy Jaeryang Baek
d5ad5c5422 Merge pull request #5066 from open-webui/dependabot/pip/backend/dev/unstructured-0.15.9
build(deps): bump unstructured from 0.15.7 to 0.15.9 in /backend
2024-09-03 14:51:03 +02:00
Timothy Jaeryang Baek
1357237a3e Merge pull request #5076 from cheahjs/fix/websocket-error-object
fix: chat errors when websocket unavailable
2024-09-03 14:50:50 +02:00
Jun Siang Cheah
4946f08671 fix: force socket.io to try websockets first, and explicit fallback to polling 2024-09-01 12:59:49 +01:00
dependabot[bot]
665c851f66 build(deps): bump authlib from 1.3.1 to 1.3.2 in /backend
Bumps [authlib](https://github.com/lepture/authlib) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/lepture/authlib/releases)
- [Changelog](https://github.com/lepture/authlib/blob/master/docs/changelog.rst)
- [Commits](https://github.com/lepture/authlib/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: authlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 02:56:51 +00:00
dependabot[bot]
115503098e build(deps): update duckduckgo-search requirement in /backend
Updates the requirements on [duckduckgo-search](https://github.com/deedy5/duckduckgo_search) to permit the latest version.
- [Release notes](https://github.com/deedy5/duckduckgo_search/releases)
- [Commits](https://github.com/deedy5/duckduckgo_search/compare/v6.2.1...v6.2.11)

---
updated-dependencies:
- dependency-name: duckduckgo-search
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 02:56:47 +00:00
dependabot[bot]
b7cda48a03 build(deps): bump aiohttp from 3.10.2 to 3.10.5 in /backend
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.2 to 3.10.5.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.2...v3.10.5)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 02:56:42 +00:00
dependabot[bot]
7780640938 build(deps): bump langchain from 0.2.14 to 0.2.15 in /backend
Bumps [langchain](https://github.com/langchain-ai/langchain) from 0.2.14 to 0.2.15.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain==0.2.14...langchain==0.2.15)

---
updated-dependencies:
- dependency-name: langchain
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 02:56:33 +00:00
dependabot[bot]
92488c254d build(deps): bump unstructured from 0.15.7 to 0.15.9 in /backend
Bumps [unstructured](https://github.com/Unstructured-IO/unstructured) from 0.15.7 to 0.15.9.
- [Release notes](https://github.com/Unstructured-IO/unstructured/releases)
- [Changelog](https://github.com/Unstructured-IO/unstructured/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Unstructured-IO/unstructured/compare/0.15.7...0.15.9)

---
updated-dependencies:
- dependency-name: unstructured
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 02:56:28 +00:00
Timothy Jaeryang Baek
bccc6e08cc Merge pull request #4957 from pascallim/fix/imports
fix: sort and fix backend imports
2024-08-31 20:09:04 +02:00
Timothy Jaeryang Baek
a8c15e1b54 Merge pull request #5060 from cheahjs/fix/missing-chat-completion-response-headers
fix: return proxied response headers during chat completion
2024-08-31 20:08:22 +02:00
Jun Siang Cheah
953beb369c fix: return proxied response headers during chat completion 2024-08-31 15:15:21 +01:00
Pascal Lim
9232e03102 fix imports 2024-08-30 22:29:45 +02:00
Pascal Lim
c386d0b1a5 sort and fix backend imports 2024-08-30 22:26:22 +02:00
Timothy J. Baek
08efabc696 refac 2024-08-30 10:56:31 -07:00
Timothy Jaeryang Baek
560b9228fd Merge pull request #4973 from sebdanielsson/ally-aria-labels
A11y: Add missing aria labels for buttons
2024-08-30 19:43:35 +02:00
Timothy Jaeryang Baek
d3bcfd4d5f Merge pull request #4974 from SearchApi/add-search-api
feat: Add support for SearchApi as alternative to WebSearch
2024-08-30 19:42:36 +02:00
Timothy Jaeryang Baek
3b21547c83 Merge pull request #4971 from sebdanielsson/lighthouse-seo-score
Lighthouse seo score and error fixes
2024-08-30 19:39:29 +02:00
Timothy Jaeryang Baek
62c475f6b4 Merge pull request #4976 from aleixdorca/dev
i18n: Update Catalan Translation
2024-08-30 19:38:58 +02:00
Timothy Jaeryang Baek
5367d5ec3b Merge pull request #5030 from Peter-De-Ath/fix-comfy-ui-403
fix: add useragent default headers comfyui
2024-08-30 19:38:50 +02:00
Timothy Jaeryang Baek
01a5569ee9 Merge pull request #5037 from KarlLee830/translate
i18n: Update Chinese translation
2024-08-30 19:37:35 +02:00
Timothy Jaeryang Baek
f75908ebe3 Merge pull request #4975 from sebdanielsson/automatic-theme-update
fix: Update color theme on system change
2024-08-30 19:37:24 +02:00
Timothy Jaeryang Baek
928326103c Merge pull request #4970 from daniel-code/feat/support-literal-type-in-tools
feat: support Literal type in Tools
2024-08-30 19:34:19 +02:00
Timothy Jaeryang Baek
8a11f12ffd Merge pull request #4945 from OriginalSimon/dev
i18n: Update Ukrainian translation
2024-08-30 19:34:03 +02:00
Karl Lee
a6b5bf8df2 i18n: Update Chinese translation 2024-08-30 18:23:27 +08:00
Peter De-Ath
a26f4306a4 fix: add useragent default headers comfyui 2024-08-29 23:38:37 +01:00
Jannik Streidl
0ead3ed37a feat: show total number of documents 2024-08-29 16:30:34 +02:00
Su YR
45363a2abb fix: type_ == "literal" 2024-08-29 15:55:12 +08:00
Aleix Dorca
a7b6d5507f i18n: Update Catalan translation.json 2024-08-28 13:06:52 +02:00
Aleix Dorca
2706b8c59c i18n: Update Catalan translation.json 2024-08-28 13:05:19 +02:00
Sebastian
fd1612935d Update color theme on system change 2024-08-28 12:43:43 +02:00
Rajendra Kadam
7e1923fcfe Add searchapi as an alternative web search
Add config changes for SearchApi api key and engine

Add searchapi results json in testdata
2024-08-28 15:26:33 +05:30
Sebastian
22117e06b5 A11y: Buttons do not have an accessible name 2024-08-28 10:13:02 +02:00
Sebastian
718d69b148 Add meta description 2024-08-28 10:10:22 +02:00
Sebastian
30e03cbac4 Add robots.txt to fix validation error 2024-08-28 10:10:22 +02:00
Su YR
0525dd2bb5 feat: support Literal type in Tools 2024-08-28 15:16:56 +08:00
Timothy Jaeryang Baek
6589450bd6 Merge pull request #4954 from open-webui/main
dev
2024-08-27 22:45:44 +02:00
Timothy Jaeryang Baek
f4df49e600 Merge pull request #4953 from open-webui/dev
fix: support list in json schema to pydantic
2024-08-27 22:45:28 +02:00
Timothy Jaeryang Baek
bc6d06b49e Merge pull request #4952 from Peter-De-Ath/support-list-json-schema-pydantic
fix: support list in json schema pydantic
2024-08-27 22:43:49 +02:00
Peter De-Ath
025f0f390e refac: support list in json schema to pydantic 2024-08-27 21:42:22 +01:00
Timothy J. Baek
0c0a860538 revert: docker build workflow 2024-08-27 22:40:23 +02:00
Simon
8994728d8b Update translation.json 2024-08-27 19:09:42 +02:00
Timothy Jaeryang Baek
693dc3107a Merge pull request #4811 from open-webui/dev
0.3.16
2024-08-27 18:49:04 +02:00
Timothy J. Baek
63c0772135 Update uv.lock 2024-08-27 18:48:56 +02:00
Timothy J. Baek
fb9b7275ad doc: changelog 2024-08-27 18:45:35 +02:00
Timothy J. Baek
7a024fbe1e refac 2024-08-27 18:18:40 +02:00
Timothy Jaeryang Baek
9dade91ef5 Merge pull request #4917 from Yanyutin753/upload_files_limit
🤖 Limit the size and number of uploaded files
2024-08-27 17:09:52 +02:00
Timothy J. Baek
35fa278b37 chore: format 2024-08-27 17:07:47 +02:00
Timothy J. Baek
6a21a77ee9 refac 2024-08-27 17:05:24 +02:00
Timothy J. Baek
628310b12b refac 2024-08-27 15:58:02 +02:00
Timothy J. Baek
ef28330c1a refac: do NOT change default behaviour in a PR 2024-08-27 15:56:47 +02:00
Timothy J. Baek
69c4687a53 refac 2024-08-27 15:53:29 +02:00
Timothy J. Baek
09cba5b87a refac: rm sub standard code 2024-08-27 15:51:40 +02:00
Timothy J. Baek
600409682e refac: do not change default behaviour 2024-08-27 15:30:57 +02:00
Timothy J. Baek
689b05a73d enh: add content-type: application/x-ndjson to ollama /api/chat 2024-08-27 14:06:58 +02:00
Timothy J. Baek
062649e483 refac: endpoints regarding db operations 2024-08-27 14:01:00 +02:00
Timothy Jaeryang Baek
bbeed7cd85 Merge pull request #4938 from KarlLee830/translate
i18n: Update Chinese translation
2024-08-27 13:30:42 +02:00
Karl Lee
6c49a15e20 i18n: Update Chinese translation 2024-08-27 19:12:47 +08:00
Timothy Jaeryang Baek
18a6b00083 Merge pull request #4929 from jannikstdl/improve-rag-status
fix: reset status on error + styling
2024-08-27 13:08:46 +02:00
Timothy Jaeryang Baek
7c841c9f63 Merge pull request #4924 from Peter-De-Ath/fix-duplicate-system-prompt
fix: stop system prompt being duplicated
2024-08-27 13:07:26 +02:00
Jannik Streidl
97d73d3d33 fix: reset status on error + styling 2024-08-27 11:24:05 +02:00
Peter De-Ath
b2e682e263 fix: stop system prompt being duplicated 2024-08-26 21:25:57 +01:00
Clivia
29cbdbcadd 💄Fix format 2024-08-26 23:59:53 +08:00
Clivia
ebca735f5e 💄Fix format 2024-08-26 23:53:51 +08:00
Clivia
775478534a 👀 Fix Common users cannot upload files
💄Fix format

💄Fix format i18

 Feat paste upload files and make restrictions

 Feat paste upload files and make restrictions
2024-08-26 23:36:13 +08:00
Clivia
b01d72ade3 💄Fix format
💄Fix format
2024-08-26 23:36:13 +08:00
Clivia
b6da4baa97 💄 Limit the size and number of uploaded files
💄 Limit the size and number of uploaded files
2024-08-26 23:36:13 +08:00
Timothy J. Baek
7fa9f381e1 chore: format 2024-08-26 15:38:42 +02:00
Timothy J. Baek
a9673c793a fix 2024-08-26 15:37:11 +02:00
Timothy Jaeryang Baek
b148865ee8 Merge pull request #4886 from kiosion/dev
feat: Add control for how message content is split for TTS generation requests
2024-08-26 15:02:30 +02:00
Timothy J. Baek
f4f7adb377 refac 2024-08-26 15:01:29 +02:00
Timothy J. Baek
b96239fb0b enh: block api user with model filter 2024-08-26 14:24:56 +02:00
Timothy J. Baek
7fc049a513 enh: codespan click to copy content 2024-08-26 14:17:33 +02:00
Timothy J. Baek
faeabfb3d4 fix: include __files__ param to pipe function 2024-08-26 12:36:04 +02:00
Timothy J. Baek
de6b5a7bbe refac 2024-08-26 12:27:00 +02:00
Timothy J. Baek
efd4b03f78 enh: repopulate tools & functions from db if non existent 2024-08-26 12:18:12 +02:00
Timothy J. Baek
e98a20fce9 fix: .md processing issue 2024-08-26 12:08:55 +02:00
Timothy J. Baek
5a0e1c5f75 refac: disable signups when ENABLE_LOGIN_FORM is set to false 2024-08-26 11:54:55 +02:00
Timothy Jaeryang Baek
c224f1105e Merge pull request #4859 from 0xThresh/main
Enhancement: Update Docker image metadata
2024-08-26 11:38:16 +02:00
Timothy Jaeryang Baek
95185aaaec Merge pull request #4904 from que-nguyen/dev
Fix and update Vietnamese translations for better accuracy.
2024-08-26 11:35:01 +02:00
Que Nguyen
cb7ee6212e Fix and update Vietnamese translations for better accuracy. 2024-08-26 14:14:00 +07:00
kiosion
d78c35c9ba refac: Tidy Chat.svelte 2024-08-25 20:27:50 -04:00
kiosion
73998a70cc i18n: Add new strings for en, fr locales 2024-08-25 20:03:58 -04:00
kiosion
3967c34261 feat: Add control for how message content is split for TTS generation reqs 2024-08-25 20:03:21 -04:00
kiosion
f30428754f fix: Safely retrieve settings from LocalStorage 2024-08-25 20:00:57 -04:00
James W.
56c9552ab3 Reset package.json to correct version 2024-08-25 14:46:21 -07:00
James W.
e414ba2d8c Merge pull request #28 from 0xThresh/dev
Test updating version with all images
2024-08-25 15:34:37 -06:00
0xThresh.eth
b1355e16bc Test updating version with all images 2024-08-25 15:33:08 -06:00
James W.
882b76cefa Merge pull request #27 from 0xThresh/dev
Add image updates to cuda and ollama image jobs
2024-08-25 15:28:51 -06:00
0xThresh.eth
63d82dbece Add image updates to cuda and ollama image jobs 2024-08-25 15:28:09 -06:00
Timothy J. Baek
f568389235 refac 2024-08-25 18:42:27 +02:00
Timothy Jaeryang Baek
814473878f Merge pull request #4899 from open-webui/config-db-migration
feat: config.json db migration
2024-08-25 17:59:01 +02:00
Timothy J. Baek
a44bae2d3a fix 2024-08-25 17:54:51 +02:00
Timothy J. Baek
fd0370d801 fix 2024-08-25 16:57:01 +02:00
Timothy J. Baek
58cf1be20c feat: config.json db migration 2024-08-25 16:52:36 +02:00
Timothy Jaeryang Baek
072945c40b Merge pull request #4867 from El-Tatane/improve-fr-translations
i18n: Improve French translations
2024-08-25 14:50:24 +02:00
El-Tatane
7c7d407f34 i18n: Improve French translations 2024-08-23 22:00:05 +02:00
James W.
c63a2dfbcd Merge pull request #26 from 0xThresh/dev
Test bumping the Open WebUI version
2024-08-23 12:11:24 -06:00
0xThresh.eth
e1022b3a28 Test bumping the Open WebUI version 2024-08-23 12:10:39 -06:00
James W.
0022902e8d Merge pull request #25 from 0xThresh/dev
Try removing push by digest
2024-08-23 12:03:42 -06:00
0xThresh.eth
9be7c8b969 Try removing push by digest 2024-08-23 12:03:06 -06:00
James W.
913b454fc3 Merge pull request #24 from 0xThresh/dev
Move version tags to latest when no new release is created
2024-08-23 11:54:09 -06:00
0xThresh.eth
ff1ea70dfa Only add version tag to main 2024-08-23 11:46:30 -06:00
0xThresh.eth
550386f52a Test moving tags in Actions 2024-08-23 11:40:02 -06:00
Timothy J. Baek
7a1fecbdb3 fix 2024-08-23 18:22:50 +02:00
Timothy J. Baek
8a99eaa68f fix 2024-08-23 18:21:19 +02:00
Timothy J. Baek
e442b3b169 fix: async image gen automatic1111 2024-08-23 16:51:34 +02:00
Timothy J. Baek
553293f4d5 refac: styling 2024-08-23 16:45:07 +02:00
Timothy J. Baek
48503573c1 refac: call overlay styling 2024-08-23 16:42:36 +02:00
Timothy J. Baek
4519ddd0e9 refac: files rbac 2024-08-23 16:19:04 +02:00
Timothy J. Baek
8b3d5e8b80 chore: format 2024-08-23 15:56:50 +02:00
Timothy J. Baek
0a5a2e67e8 fix: uploaded files leaking to other user chats issue
#4601
2024-08-23 15:02:23 +02:00
Timothy J. Baek
7b91be21b4 refac 2024-08-23 14:43:32 +02:00
Timothy J. Baek
591962d906 refac: input commands 2024-08-23 14:31:39 +02:00
Timothy Jaeryang Baek
64c0157271 Merge pull request #4842 from KarlLee830/translate
i18n: Update Chinese translation
2024-08-23 14:08:48 +02:00
Timothy Jaeryang Baek
f5c0e670aa Merge pull request #4847 from michaelpoluektov/fix-tools-param
fix: `__tools__` param
2024-08-23 14:08:32 +02:00
Michael Poluektov
83de28bac2 fix: tools param 2024-08-23 12:58:43 +01:00
Karl Lee
c6885a8bcf i18n: Update Chinese translation 2024-08-23 18:01:26 +08:00
Timothy J. Baek
5d8dbff486 refac 2024-08-22 17:37:47 +02:00
Timothy J. Baek
0939cb5ed6 refac: styling 2024-08-22 17:34:28 +02:00
Timothy J. Baek
153a2876b4 fix: mediaStream not stopping after exiting call mode 2024-08-22 17:27:22 +02:00
Timothy J. Baek
61503a654c enh: call=true url search param 2024-08-22 17:17:32 +02:00
Timothy J. Baek
c268a4e217 refac: only activate wakelock in call mode 2024-08-22 17:12:31 +02:00
Timothy J. Baek
70ab7735ba chore: format 2024-08-22 16:38:48 +02:00
Timothy J. Baek
25de3e753d fix 2024-08-22 16:34:12 +02:00
Timothy Jaeryang Baek
670672c067 Merge pull request #4813 from jannikstdl/rag-knowledge-status
feat: show rag status when using models with knowledge collections
2024-08-22 16:31:42 +02:00
Timothy J. Baek
85f8a80389 refac 2024-08-22 16:31:33 +02:00
Timothy J. Baek
673b893a8a refac 2024-08-22 16:11:19 +02:00
Timothy J. Baek
d8d2f3529f refac 2024-08-22 16:08:03 +02:00
Timothy J. Baek
63ba8145b9 refac 2024-08-22 16:02:29 +02:00
Timothy Jaeryang Baek
99db82a161 Merge pull request #4815 from michaelpoluektov/fix-user-valves
fix: Fix user valves
2024-08-22 15:25:45 +02:00
Timothy J. Baek
a3089e0472 fix 2024-08-22 15:24:48 +02:00
Timothy Jaeryang Baek
9186abf9c1 Merge branch 'dev' into fix-user-valves 2024-08-22 15:23:59 +02:00
Timothy J. Baek
97808ba1c3 refac 2024-08-22 15:23:32 +02:00
Timothy J. Baek
589420c208 refac 2024-08-22 15:20:19 +02:00
Timothy J. Baek
3bf7d569c6 refac 2024-08-22 15:11:31 +02:00
Timothy J. Baek
14187b027d refac 2024-08-22 15:09:06 +02:00
Timothy J. Baek
06f067fda9 refacfix 2024-08-22 15:03:39 +02:00
Michael Poluektov
9b5dfe64b7 fix: is not None 2024-08-22 13:58:10 +01:00
Timothy J. Baek
1c89c91f07 refac 2024-08-22 14:53:14 +02:00
Timothy J. Baek
ed5761f18f refac: rye -> uv 2024-08-22 14:38:05 +02:00
Michael Poluektov
16ec25d296 fix user valves 2024-08-22 13:34:35 +01:00
Jannik Streidl
abe17ab4b5 feat: show rag status when using models with knowledge collections 2024-08-22 14:30:11 +02:00
Timothy Jaeryang Baek
14f0e6a2ba Merge pull request #4783 from open-webui/dependabot/pip/backend/dev/langchain-community-0.2.12
chore(deps): bump langchain-community from 0.2.10 to 0.2.12 in /backend
2024-08-22 14:26:41 +02:00
Timothy Jaeryang Baek
f1f2f034f8 Merge pull request #4785 from open-webui/dependabot/pip/backend/dev/markdown-3.7
chore(deps): bump markdown from 3.6 to 3.7 in /backend
2024-08-22 14:26:33 +02:00
Timothy J. Baek
63418a583a fix: latex rendering issue 2024-08-22 14:24:49 +02:00
dependabot[bot]
4031cb9eda chore(deps): bump langchain-community from 0.2.10 to 0.2.12 in /backend
Bumps [langchain-community](https://github.com/langchain-ai/langchain) from 0.2.10 to 0.2.12.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-community==0.2.10...langchain-community==0.2.12)

---
updated-dependencies:
- dependency-name: langchain-community
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-22 12:10:43 +00:00
dependabot[bot]
ee6b8c5b72 chore(deps): bump markdown from 3.6 to 3.7 in /backend
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.6 to 3.7.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.6...3.7)

---
updated-dependencies:
- dependency-name: markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-22 12:07:04 +00:00
Timothy Jaeryang Baek
11aecbe79a Merge pull request #4768 from zhaofengli/db-url-fixes
fix: Fix parameter handling for PostgreSQL URLs
2024-08-22 14:01:28 +02:00
Timothy Jaeryang Baek
a9bace0f97 Merge pull request #4784 from open-webui/dependabot/pip/backend/dev/langchain-0.2.14
chore(deps): bump langchain from 0.2.12 to 0.2.14 in /backend
2024-08-22 13:59:27 +02:00
Timothy Jaeryang Baek
7e4fed2451 Merge pull request #4786 from open-webui/dependabot/pip/backend/dev/unstructured-0.15.7
chore(deps): bump unstructured from 0.15.5 to 0.15.7 in /backend
2024-08-22 13:59:03 +02:00
Timothy Jaeryang Baek
ac8a16ec5b Merge pull request #4787 from open-webui/dependabot/pip/backend/dev/langfuse-2.44.0
chore(deps): bump langfuse from 2.43.3 to 2.44.0 in /backend
2024-08-22 13:58:48 +02:00
Timothy Jaeryang Baek
95d016dea4 Merge pull request #4800 from aleixdorca/dev
i18n: Update catalan translation.json
2024-08-22 13:58:14 +02:00
Timothy Jaeryang Baek
abe36a3e67 Merge pull request #4803 from CJDaniel96/dev
fix: DeprecationWarning for datetime.utcnow() by using datetime.now(UTC)
2024-08-22 13:57:57 +02:00
USIGLOBAL\daniel_tsai
89ebbed67b fix: DeprecationWarning for datetime.utcnow() by using datetime.now(UTC) 2024-08-22 15:12:40 +08:00
Aleix Dorca
ec075e2612 Update catalan translation.json 2024-08-22 07:12:42 +02:00
Timothy Jaeryang Baek
e2b7296786 Merge pull request #4798 from open-webui/dev
fix: filter compatibility issue
2024-08-22 01:14:34 +02:00
Timothy J. Baek
6fcd40d4d8 fix: filter compatibility issue 2024-08-22 01:08:59 +02:00
Timothy Jaeryang Baek
847ca66001 Merge pull request #4795 from open-webui/dev
0.3.15
2024-08-22 00:28:30 +02:00
Timothy J. Baek
85b4129219 fix 2024-08-22 00:25:43 +02:00
Timothy J. Baek
c36f83df5b doc: changelog 2024-08-22 00:23:40 +02:00
Timothy J. Baek
bb026cdd9c fix: many model chat backward compatibility 2024-08-22 00:22:40 +02:00
Timothy J. Baek
8843898a8c fix: older many model chat compatibility 2024-08-22 00:03:58 +02:00
Timothy J. Baek
f036aa0a48 doc: changelog 2024-08-21 23:47:33 +02:00
Timothy J. Baek
1e928e463f chore: format 2024-08-21 23:35:54 +02:00
Timothy J. Baek
36e895c135 fix 2024-08-21 23:33:32 +02:00
Timothy J. Baek
3447f233fa fix 2024-08-21 23:27:23 +02:00
Timothy J. Baek
f3e8dd1f2e enh: comfyui logs 2024-08-21 23:22:12 +02:00
Timothy J. Baek
3f0b7b29db fix 2024-08-21 23:11:12 +02:00
Timothy J. Baek
95cf90d787 enh: comfyui seed node support 2024-08-21 23:05:20 +02:00
Timothy J. Baek
f3f6941205 fix: many model chat actions not working 2024-08-21 22:54:56 +02:00
Timothy J. Baek
4a21c5c5e7 refac 2024-08-21 22:42:25 +02:00
Timothy J. Baek
180f2b9a83 fix: functions 2024-08-21 22:39:36 +02:00
Timothy J. Baek
94eb91063c fix 2024-08-21 22:27:21 +02:00
Timothy J. Baek
dc4c6b3b14 enh: temporary-chat url search param 2024-08-21 18:55:12 +02:00
Timothy Jaeryang Baek
50d53c6f8d Merge pull request #4790 from open-webui/dev
fix
2024-08-21 18:33:57 +02:00
Timothy J. Baek
a93b0ac143 fix 2024-08-21 18:33:31 +02:00
Timothy Jaeryang Baek
ed92205d7d Merge pull request #4789 from open-webui/dev
fix
2024-08-21 18:30:10 +02:00
Timothy J. Baek
acaf135a2f fix 2024-08-21 18:29:52 +02:00
Timothy Jaeryang Baek
bf6c6afb21 Merge pull request #4788 from open-webui/main
dev
2024-08-21 17:41:15 +02:00
dependabot[bot]
f5994e3a44 chore(deps): bump langfuse from 2.43.3 to 2.44.0 in /backend
Bumps [langfuse](https://github.com/langfuse/langfuse) from 2.43.3 to 2.44.0.
- [Release notes](https://github.com/langfuse/langfuse/releases)
- [Commits](https://github.com/langfuse/langfuse/commits/v2.44.0)

---
updated-dependencies:
- dependency-name: langfuse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-21 15:38:07 +00:00
dependabot[bot]
ccf5bd1492 chore(deps): bump unstructured from 0.15.5 to 0.15.7 in /backend
Bumps [unstructured](https://github.com/Unstructured-IO/unstructured) from 0.15.5 to 0.15.7.
- [Release notes](https://github.com/Unstructured-IO/unstructured/releases)
- [Changelog](https://github.com/Unstructured-IO/unstructured/blob/0.15.7/CHANGELOG.md)
- [Commits](https://github.com/Unstructured-IO/unstructured/compare/0.15.5...0.15.7)

---
updated-dependencies:
- dependency-name: unstructured
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-21 15:38:05 +00:00
dependabot[bot]
510a0f3a2f chore(deps): bump langchain from 0.2.12 to 0.2.14 in /backend
Bumps [langchain](https://github.com/langchain-ai/langchain) from 0.2.12 to 0.2.14.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain==0.2.12...langchain==0.2.14)

---
updated-dependencies:
- dependency-name: langchain
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-21 15:37:56 +00:00
Timothy Jaeryang Baek
8a620cab44 Merge pull request #4623 from open-webui/dev
0.3.14
2024-08-21 17:36:58 +02:00
Timothy J. Baek
fcffb0adf2 fix 2024-08-21 17:28:09 +02:00
Timothy J. Baek
efcb56f0dc refac 2024-08-21 17:27:39 +02:00
Timothy J. Baek
86ee19178e doc: changelog 2024-08-21 17:09:18 +02:00
Timothy J. Baek
1fc306acd0 chore: backend bump 2024-08-21 15:47:03 +02:00
Timothy J. Baek
da1d5ad917 fix 2024-08-21 15:42:33 +02:00
Timothy J. Baek
b45db22a17 chore: format 2024-08-21 15:16:37 +02:00
Timothy J. Baek
19455ab04e fix 2024-08-21 15:15:29 +02:00
Timothy J. Baek
71b1661f00 fix 2024-08-21 14:49:54 +02:00
Timothy J. Baek
99764bfd29 fix 2024-08-21 14:49:17 +02:00
Timothy J. Baek
063e006446 feat: custom comfyui workflow
Co-Authored-By: John Karabudak <hello@johnthenerd.com>
2024-08-21 14:44:47 +02:00
Timothy J. Baek
436f009dab refac 2024-08-21 14:20:52 +02:00
Timothy J. Baek
71a66ed4cf refac 2024-08-21 14:18:47 +02:00
Timothy J. Baek
29bef261be refac 2024-08-21 14:16:33 +02:00
Timothy J. Baek
e2291f7148 refac 2024-08-21 01:39:30 +02:00
Timothy J. Baek
8b5aed7a2b refac 2024-08-21 01:21:03 +02:00
Timothy J. Baek
95057d2368 refac: image gen 2024-08-21 00:35:42 +02:00
Timothy Jaeryang Baek
20dadf9b5a Merge pull request #4760 from michaelpoluektov/tools-refac-2.1
Fix: tools filter
2024-08-20 18:51:28 +02:00
Michael Poluektov
3d6ac3a7db Merge branch 'dev' of https://github.com/open-webui/open-webui into tools-refac-2.1 2024-08-20 17:42:25 +01:00
Michael Poluektov
bd47bbbce9 fix tools filter 2024-08-20 17:41:51 +01:00
Timothy Jaeryang Baek
ddebfc7413 Merge pull request #4757 from OriginalSimon/dev
i18n: Update of the Ukrainian translation
2024-08-20 18:17:40 +02:00
Timothy J. Baek
c5310e84db feat: custom COMFYUI_WORKFLOW
deprecates several comfyui env vars
2024-08-20 18:17:15 +02:00
Simon
0c8301e79c Update translation.json 2024-08-20 17:44:20 +02:00
Timothy J. Baek
73faa8dc80 refac: styling 2024-08-20 17:03:20 +02:00
Timothy Jaeryang Baek
ee526b4b07 Merge pull request #4724 from michaelpoluektov/tools-refac-2.1
feat: Add `__tools__` optional param for function pipes
2024-08-20 17:01:13 +02:00
Michael Poluektov
454f59d59a undo frontend change 2024-08-20 15:48:14 +01:00
Michael Poluektov
2e3146263c put tool_ids and files in metadata 2024-08-20 15:41:49 +01:00
Michael Poluektov
bcbcd5fde9 Merge branch 'dev' of https://github.com/open-webui/open-webui into tools-refac-2.1 2024-08-20 14:56:47 +01:00
Timothy J. Baek
83a596612a fix 2024-08-20 14:28:19 +02:00
Timothy J. Baek
2b896989b8 refac 2024-08-20 14:27:14 +02:00
Timothy Jaeryang Baek
27109d22e4 Merge pull request #4743 from 5E-324/add-num_gpu
fix: Changes to num_gpu made in Settings > General won't be saved
2024-08-20 13:38:11 +02:00
Timothy Jaeryang Baek
22d8f8f1ef Merge pull request #4746 from 5E-324/fix-type-errors
chore: Fix type errors.
2024-08-20 13:37:08 +02:00
Zhuoran
fd26e5635d Fix type errors. 2024-08-20 08:44:09 +08:00
Zhuoran
b350b0023f Add num_gpu in General.svelte 2024-08-20 07:47:20 +08:00
Timothy J. Baek
330eb0fbb1 enh: user message edit 2024-08-19 21:51:10 +02:00
Timothy J. Baek
d79d3f1352 enh: mermaid dark theme 2024-08-19 19:42:31 +02:00
Michael Poluektov
44966db505 avoid ugly exception 2024-08-19 17:04:57 +01:00
Timothy J. Baek
1e8abea753 refac 2024-08-19 17:58:54 +02:00
Timothy J. Baek
21d8ff61bb refac 2024-08-19 17:57:47 +02:00
Michael Poluektov
9652c8f8af dont delete files and tool_ids 2024-08-19 16:57:29 +01:00
Timothy J. Baek
de8f5b9c13 enh: default title gen prompt 2024-08-19 17:54:34 +02:00
Michael Poluektov
c89df923c5 fix import error 2024-08-19 16:52:42 +01:00
Michael Poluektov
556bc8669a remove config options for now 2024-08-19 16:50:52 +01:00
Timothy J. Baek
89ba98e927 enh: better pdf CJK language support 2024-08-19 17:50:42 +02:00
Timothy J. Baek
6c8a15fae2 refac 2024-08-19 17:47:28 +02:00
Timothy J. Baek
68d8fd69c0 fix 2024-08-19 17:44:14 +02:00
Timothy J. Baek
b31de299e4 fix: mermaid rendering issue 2024-08-19 17:28:38 +02:00
Michael Poluektov
9d7037b730 add pydantic model from json 2024-08-19 16:27:38 +01:00
Michael Poluektov
5edc211392 pass docstring to function 2024-08-19 16:27:21 +01:00
Timothy J. Baek
1329eea5e5 refac 2024-08-19 17:00:48 +02:00
Timothy J. Baek
28022b056b chore: format 2024-08-19 16:51:17 +02:00
Timothy J. Baek
cbadf39d7d enh: user chat edit permission 2024-08-19 16:49:40 +02:00
Timothy Jaeryang Baek
ec99ac7121 Update SECURITY.md 2024-08-19 09:18:40 -05:00
Timothy J. Baek
dfa5041b6f refac: styling 2024-08-19 15:30:41 +02:00
Timothy J. Baek
0fa85c5c64 enh: enable message rating setting 2024-08-19 15:16:49 +02:00
Timothy J. Baek
5abe1076ed enh: model workspace shiftKey quick actions 2024-08-19 14:58:15 +02:00
Timothy Jaeryang Baek
7feda56e7b Merge pull request #4718 from open-webui/dependabot/pip/backend/dev/bcrypt-4.2.0
chore(deps): bump bcrypt from 4.1.3 to 4.2.0 in /backend
2024-08-19 14:17:00 +02:00
dependabot[bot]
a54d3ad512 chore(deps): bump bcrypt from 4.1.3 to 4.2.0 in /backend
Bumps [bcrypt](https://github.com/pyca/bcrypt) from 4.1.3 to 4.2.0.
- [Changelog](https://github.com/pyca/bcrypt/blob/main/release.py)
- [Commits](https://github.com/pyca/bcrypt/compare/4.1.3...4.2.0)

---
updated-dependencies:
- dependency-name: bcrypt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 12:05:37 +00:00
Timothy Jaeryang Baek
cdf9f5a4ec Merge pull request #4720 from open-webui/dependabot/pip/backend/dev/boto3-1.35.0
chore(deps): bump boto3 from 1.34.153 to 1.35.0 in /backend
2024-08-19 14:04:41 +02:00
Timothy Jaeryang Baek
a472bfe6dc Merge pull request #4719 from open-webui/dependabot/pip/backend/dev/faster-whisper-1.0.3
chore(deps): bump faster-whisper from 1.0.2 to 1.0.3 in /backend
2024-08-19 14:04:31 +02:00
Timothy Jaeryang Baek
f88d994c35 Merge pull request #4717 from open-webui/dependabot/pip/backend/dev/uvicorn-standard--0.30.6
chore(deps): bump uvicorn[standard] from 0.22.0 to 0.30.6 in /backend
2024-08-19 14:04:22 +02:00
Timothy Jaeryang Baek
ad92aded84 Merge pull request #4716 from open-webui/dependabot/pip/backend/dev/sqlalchemy-2.0.32
chore(deps): bump sqlalchemy from 2.0.31 to 2.0.32 in /backend
2024-08-19 14:03:43 +02:00
Timothy J. Baek
b4de0a52f8 fix
Co-Authored-By: elad_pt <124190990+elad-pticha@users.noreply.github.com>
2024-08-19 14:01:21 +02:00
Timothy Jaeryang Baek
bd23dac92e Merge pull request #4714 from crizCraig/set-cors
sec: Allow setting CORS origin
2024-08-19 13:55:28 +02:00
Michael Poluektov
528df12bf1 fix: nonetype error 2024-08-19 11:15:22 +01:00
Michael Poluektov
a933319adb import error? 2024-08-19 11:11:00 +01:00
Michael Poluektov
13c03bfd7d add __tools__ custom param 2024-08-19 11:08:27 +01:00
Michael Poluektov
18965dcdac delete keys if envvars are set 2024-08-19 11:03:55 +01:00
Michael Poluektov
a4a7d678f9 move tools utils to utils.tools 2024-08-19 10:53:12 +01:00
Michael Poluektov
fd422d2e3c use filters envvars 2024-08-19 10:46:52 +01:00
Michael Poluektov
ce7a1a73ac remove more nesting 2024-08-19 10:34:44 +01:00
Michael Poluektov
32874a816d add filter toggle envvars 2024-08-19 10:26:16 +01:00
Michael Poluektov
3164354c0b refactor into single wrapper 2024-08-19 10:23:40 +01:00
dependabot[bot]
f96aaf1177 chore(deps): bump boto3 from 1.34.153 to 1.35.0 in /backend
Bumps [boto3](https://github.com/boto/boto3) from 1.34.153 to 1.35.0.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.34.153...1.35.0)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 03:07:09 +00:00
dependabot[bot]
589c79f3c2 chore(deps): bump faster-whisper from 1.0.2 to 1.0.3 in /backend
Bumps [faster-whisper](https://github.com/SYSTRAN/faster-whisper) from 1.0.2 to 1.0.3.
- [Release notes](https://github.com/SYSTRAN/faster-whisper/releases)
- [Commits](https://github.com/SYSTRAN/faster-whisper/compare/v1.0.2...v1.0.3)

---
updated-dependencies:
- dependency-name: faster-whisper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 03:07:03 +00:00
dependabot[bot]
a0f6864216 chore(deps): bump uvicorn[standard] from 0.22.0 to 0.30.6 in /backend
Bumps [uvicorn[standard]](https://github.com/encode/uvicorn) from 0.22.0 to 0.30.6.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.22.0...0.30.6)

---
updated-dependencies:
- dependency-name: uvicorn[standard]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 03:06:54 +00:00
dependabot[bot]
a4cc2c5c48 chore(deps): bump sqlalchemy from 2.0.31 to 2.0.32 in /backend
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.31 to 2.0.32.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

---
updated-dependencies:
- dependency-name: sqlalchemy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 03:06:51 +00:00
Craig Quiter
0550d12106 Black format 2024-08-18 15:04:01 -07:00
Craig Quiter
845628c100 Fix tab format causing build failure 2024-08-18 15:00:49 -07:00
Craig Quiter
7bcdc10539 Optimize imports 2024-08-18 14:19:29 -07:00
Craig Quiter
d2f10d50bf Allow seting CORS origin 2024-08-18 14:19:29 -07:00
Timothy Jaeryang Baek
446b2a334a Merge pull request #4713 from FINNSEEFLY/task/adjust-localization
i18n: Update ru-RU and uk-UA localizations
2024-08-18 22:57:34 +02:00
FINNSEEFLY
b0fd90ada9 Adjust controls to ensure proper display of localized strings 2024-08-18 22:42:58 +03:00
FINNSEEFLY
6bfd48e412 Adjust uk localization 2024-08-18 22:40:18 +03:00
FINNSEEFLY
07ffd6e231 Adjust ru localization 2024-08-18 22:39:36 +03:00
Timothy J. Baek
c675beeda4 refac 2024-08-18 21:14:22 +02:00
Timothy J. Baek
fe0cf9506c refac 2024-08-18 21:11:59 +02:00
Timothy J. Baek
7c81509804 feat: merge responses 2024-08-18 20:59:59 +02:00
Timothy J. Baek
65923006a8 chore: format 2024-08-18 18:29:30 +02:00
Timothy J. Baek
b02f6db475 refac 2024-08-18 18:28:58 +02:00
Timothy J. Baek
7f394f3f00 refac 2024-08-18 18:21:59 +02:00
Timothy J. Baek
fc8524bbfd refac: styling 2024-08-18 18:20:36 +02:00
Timothy J. Baek
c9505531fd refac: styling 2024-08-18 17:40:26 +02:00
Timothy J. Baek
1b809fe42e refac: styling 2024-08-18 17:16:22 +02:00
Timothy J. Baek
a1b4df1b85 fix: cloned many model chat freezing issue 2024-08-18 16:47:12 +02:00
Timothy Jaeryang Baek
079f37a2d6 Merge pull request #4701 from ndrsfel/fix-rag-embedding-openai-batch-size-environment-variable
fix: RAG with OpenAI embedding models and batch_size environment variable fails silently
2024-08-18 13:24:18 +02:00
Andreas Feldl
0980066363 fix conversion 2024-08-18 12:46:47 +02:00
Timothy Jaeryang Baek
a3b6654cbb Merge pull request #4688 from amirsubhi/dev
i18n: Updated ms-MY Translation
2024-08-17 21:57:52 +02:00
amirsubhi
f4328325be Update i18n ms-MY Translation
Update Bahasa Malaysia Translation to reflect new update, and some spelling error
2024-08-18 02:17:51 +08:00
Timothy J. Baek
7badff49d8 refac 2024-08-17 19:43:04 +02:00
Timothy J. Baek
176c689f8d fix: unstructured md file parsing issue 2024-08-17 17:20:35 +02:00
Timothy J. Baek
fa20b1dc09 chore: format 2024-08-17 17:17:45 +02:00
Timothy J. Baek
2ca9989d20 refac 2024-08-17 17:15:44 +02:00
Timothy J. Baek
3420818c52 refac 2024-08-17 17:11:58 +02:00
Timothy J. Baek
0ae6ca608c refac 2024-08-17 17:01:35 +02:00
Timothy J. Baek
536b40890a refac 2024-08-17 16:57:27 +02:00
Timothy J. Baek
d5337917db refac 2024-08-17 16:46:04 +02:00
Timothy J. Baek
15f3ebba93 refac 2024-08-17 16:41:34 +02:00
Timothy J. Baek
e71f55e58f refac 2024-08-17 16:32:39 +02:00
Timothy J. Baek
fe747382c1 refac 2024-08-17 16:27:11 +02:00
Timothy J. Baek
c4946d42e0 refac 2024-08-17 16:24:11 +02:00
Timothy J. Baek
c1823b4b73 refac 2024-08-17 16:02:46 +02:00
Timothy J. Baek
862a30842c refac: chat_completion_inlets_handler -> chat_completion_filter_functions_handler 2024-08-17 16:00:18 +02:00
Timothy Jaeryang Baek
cbb0940ff8 Merge pull request #4602 from michaelpoluektov/tools-refac-1
refactor, perf: Tools refactor (progress PR 1)
2024-08-17 15:50:40 +02:00
Timothy Jaeryang Baek
bd8df3583d Merge pull request #4674 from crizCraig/sanitize-11labs-voiceid
sec: Sanitize 11labs voice id to address semgrep security issue: tainted-path-traversal-stdlib-fastapi
2024-08-17 15:49:56 +02:00
Craig Quiter
5f36807dbe Note tts defaults are from openai 2024-08-16 15:42:15 -07:00
Craig Quiter
442f50303a Sanitize voice_id 2024-08-16 15:10:53 -07:00
Craig Quiter
4560f3b1ae Return a dict from get_available_voices 2024-08-16 15:10:51 -07:00
Craig Quiter
59d2c670ba Optimize imports 2024-08-16 15:10:47 -07:00
Craig Quiter
02577f6a45 Cache elevenlabs voice call (can take 1s) 2024-08-16 15:10:41 -07:00
Timothy J. Baek
094fdd8943 fix 2024-08-16 19:23:36 +02:00
Timothy J. Baek
17169dff1f fix 2024-08-16 19:00:10 +02:00
Timothy J. Baek
28e3e6e8cb refac: many model chat 2024-08-16 18:54:30 +02:00
Timothy J. Baek
4f47053e93 refac 2024-08-16 17:51:50 +02:00
Timothy J. Baek
9025e9dbb1 fix: pseudo html rendering issue 2024-08-16 15:44:18 +02:00
Timothy J. Baek
eee1dad217 refac: styling 2024-08-16 15:37:17 +02:00
Timothy J. Baek
769df698be fix: visible backtick in codespan 2024-08-16 15:37:11 +02:00
Timothy J. Baek
4ef042e966 refac 2024-08-16 15:33:14 +02:00
Timothy J. Baek
92062ff722 refac 2024-08-16 15:19:47 +02:00
Timothy J. Baek
623aa08b9e refac 2024-08-16 15:15:06 +02:00
Timothy J. Baek
a529343b2b refac 2024-08-16 15:10:21 +02:00
Timothy J. Baek
2161903163 refac 2024-08-16 14:42:51 +02:00
Timothy Jaeryang Baek
3de9a1a130 Merge pull request #4651 from KarlLee830/translate
i18n: Update Chinese translation
2024-08-16 14:12:47 +02:00
Karl Lee
587c1a3ca2 i18n: Update Chinese translation 2024-08-16 16:37:02 +08:00
Timothy J. Baek
d224566957 refac: styling 2024-08-16 00:21:57 +02:00
Timothy J. Baek
8ea1a10525 enh: action __event_emitter__ support 2024-08-15 23:55:31 +02:00
Michael Poluektov
b6d6094018 Merge branch 'dev' into tools-refac-1 2024-08-15 21:35:31 +01:00
Timothy J. Baek
e5e1bac242 chore: format 2024-08-15 17:31:47 +02:00
Timothy J. Baek
8c2ba7f7ea enh: Actions __webui__ flag support 2024-08-15 17:28:43 +02:00
Timothy J. Baek
dc6ca61548 enh: temp chat
deprecates chat history setting and introduces temp chat from model selector
2024-08-15 16:54:16 +02:00
Timothy Jaeryang Baek
723caf2a09 Merge pull request #4621 from nthe/main
feat: Set content-type header in Ollama backend
2024-08-15 15:45:51 +02:00
Timothy J. Baek
439cb66672 refac: fuzzy search threshold 2024-08-15 15:44:38 +02:00
Timothy J. Baek
dbd5b4c9f1 enh: render markdown user message 2024-08-15 15:41:02 +02:00
Timothy Jaeryang Baek
4dd404ac3b Merge pull request #4614 from sebdanielsson/pwa-maskable-icon
fix: Make PWA icon maskable
2024-08-15 13:25:00 +02:00
Timothy J. Baek
ba370438b2 refac: "any maskable" is discouraged 2024-08-15 13:24:47 +02:00
Juraj Onuska
f73a60d96c fix: set content-type header in ollama backend 2024-08-15 13:15:12 +02:00
Sebastian
afe1f13c5b Make PWA icon maskable 2024-08-15 00:46:22 +02:00
Timothy J. Baek
0554cc6128 enh: shiftkey quick delete for tools and functions 2024-08-15 00:44:23 +02:00
Timothy J. Baek
5a6ece9513 refac: enhanced response content sanitisation
'<' and '>' can be correctly displayed now
2024-08-15 00:08:15 +02:00
Michael Poluektov
4042219b3e minor refac 2024-08-14 21:40:00 +01:00
Michael Poluektov
fdc89cbcee tool calling refactor 2024-08-14 21:40:00 +01:00
Michael Poluektov
6df6170c44 add get_configured_tools 2024-08-14 21:40:00 +01:00
Michael Poluektov
d598d4bb93 typing and tweaks 2024-08-14 21:40:00 +01:00
Michael Poluektov
790bdcf9fc rename tool calling helpers to use 'tool' instead of 'function' 2024-08-14 21:40:00 +01:00
Michael Poluektov
2efcda837c add try: except back 2024-08-14 21:40:00 +01:00
Michael Poluektov
e86688284a factor out get_function_calling_payload 2024-08-14 21:40:00 +01:00
Michael Poluektov
ff9d899f9c fix more LSP errors 2024-08-14 21:40:00 +01:00
Michael Poluektov
a68b918cbb refactor get_function_call_response 2024-08-14 21:40:00 +01:00
Michael Poluektov
9fb70969d7 factor out get_content_from_response 2024-08-14 21:40:00 +01:00
Michael Poluektov
0c9119d619 move task to metadata 2024-08-14 21:40:00 +01:00
Michael Poluektov
556141cdd8 refactor task 2024-08-14 21:40:00 +01:00
Michael Poluektov
60003c976a rename to chat_completions_inlet_handler for clarity 2024-08-14 21:40:00 +01:00
Michael Poluektov
23f1bee7bd cleanup 2024-08-14 21:40:00 +01:00
Michael Poluektov
589efcdc5f is_chat_completion_request helper, remove nesting 2024-08-14 21:40:00 +01:00
Michael Poluektov
3befadb29f remove unnecessary nesting, remove unused endpoint 2024-08-14 21:40:00 +01:00
Timothy Jaeryang Baek
13b0e7d64a Merge pull request #4434 from open-webui/dev
0.3.13
2024-08-14 21:45:19 +02:00
Timothy J. Baek
c8badfe21f refac 2024-08-14 21:42:43 +02:00
Timothy J. Baek
2a1b9cae91 doc: changelog 2024-08-14 21:39:11 +02:00
Timothy J. Baek
5ba7bbdd98 refac 2024-08-14 21:34:08 +02:00
Timothy J. Baek
9435d2044a refac: more robust mermaid chart rendering 2024-08-14 21:16:07 +02:00
Timothy J. Baek
609a42c29c refac: mermaid chart rendering 2024-08-14 17:34:44 +02:00
Timothy J. Baek
6a1e7ab038 chore: version bump 2024-08-14 17:13:37 +02:00
Timothy J. Baek
53daa15b9a chore: format 2024-08-14 17:07:16 +02:00
Timothy J. Baek
55097410f6 feat: haptic feedback on support devices (android)
Co-Authored-By: Danny Liu <dannyjialiliu@gmail.com>
2024-08-14 17:05:43 +02:00
Timothy J. Baek
04e2b6e2bd chore: format 2024-08-14 16:39:02 +02:00
Timothy Jaeryang Baek
9f0c9d973c Merge pull request #4597 from michaelpoluektov/cleanup
refactor: search and replace-able cleanup
2024-08-14 16:30:27 +02:00
Timothy J. Baek
1597e33a74 refac: mermaid chart rendering 2024-08-14 16:27:55 +02:00
Timothy Jaeryang Baek
0b218bbb72 Merge pull request #4598 from michaelpoluektov/cleanup-frontend
refactor: Remove unused frontend functions migrated to backend
2024-08-14 16:13:39 +02:00
Timothy J. Baek
7b21b718fe refac 2024-08-14 16:09:16 +02:00
Timothy J. Baek
6e5b557a1f refac 2024-08-14 16:08:23 +02:00
Timothy J. Baek
6aefc79807 refac: latex 2024-08-14 16:07:39 +02:00
Michael Poluektov
ec9e0dadea remove frontend functions migrated to backend 2024-08-14 14:33:20 +01:00
Michael Poluektov
0470146d7b replace Tuple with tuple 2024-08-14 13:58:37 +01:00
Michael Poluektov
a518d50477 format backend 2024-08-14 13:49:18 +01:00
Michael Poluektov
29f904db45 remove List imports 2024-08-14 13:46:31 +01:00
Michael Poluektov
038fc48ac0 replace == None with is None 2024-08-14 13:39:53 +01:00
Michael Poluektov
6f72def1ac replace except: with except Exception: 2024-08-14 13:38:19 +01:00
Timothy J. Baek
0ec1f9e331 fix: ENABLE_ADMIN_CHAT_ACCESS disabling user deletion 2024-08-14 12:23:24 +02:00
Timothy Jaeryang Baek
9682806476 Merge pull request #4372 from JTHesse/main
build: Adding ability to install requirements from frontmatter for tools and functions
2024-08-13 18:18:26 +02:00
Timothy Jaeryang Baek
fc6fa7887b Merge pull request #4579 from alexandregodard/main
Update main.py
2024-08-13 18:17:27 +02:00
Timothy J. Baek
e1e69cfbcb refac: sft -> default to safetensors 2024-08-13 17:15:20 +01:00
Alexandre GODARD
7a8f8960c5 Update main.py
Fix typo in update_reranking_model
2024-08-13 17:51:25 +02:00
Timothy Jaeryang Baek
30c44d431b Merge pull request #4538 from open-webui/dependabot/pip/backend/dev/chromadb-0.5.5
chore(deps): bump chromadb from 0.5.4 to 0.5.5 in /backend
2024-08-13 12:22:56 +02:00
Timothy Jaeryang Baek
b177976f29 Merge pull request #4539 from open-webui/dependabot/pip/backend/dev/langchain-0.2.12
chore(deps): bump langchain from 0.2.11 to 0.2.12 in /backend
2024-08-13 12:22:48 +02:00
Timothy J. Baek
af6b92a6fa chore: format 2024-08-13 11:22:08 +01:00
Timothy J. Baek
a1888b3757 refac 2024-08-13 11:21:17 +01:00
Timothy Jaeryang Baek
c75e77cdde Merge pull request #4554 from 5E-324/add-num_gpu
feat: Add advanced parameter num_gpu (Ollama)
2024-08-13 12:15:44 +02:00
Timothy Jaeryang Baek
6447b484c1 Merge pull request #4555 from 5E-324/ollama-params-fix
fix: Ollama parameters not shown in Chat Controls even if the current user is admin.
2024-08-13 12:13:40 +02:00
Timothy Jaeryang Baek
0c5236ac27 Merge pull request #4562 from simonaszilinskas/patch-5
Update Lithuanian translations
2024-08-13 12:13:11 +02:00
Timothy J. Baek
7ef5aa520c chore: format 2024-08-13 11:12:35 +01:00
Simonas
d620bcf516 Update Lithuanian translations 2024-08-13 03:10:08 -05:00
Zhuoran
b0c2e607b8 Set property "admin" of AdvancedParams in Controls 2024-08-13 10:06:51 +08:00
Zhuoran
56e2d579f2 Add advanced parameter num_gpu (Ollama) 2024-08-13 09:46:38 +08:00
Zhaofeng Li
e63d5778a8 fix: Decode URL-encoded characters in passwords
This enables using passwords containing special characters.
2024-08-12 08:52:16 -06:00
Zhaofeng Li
a53c2a8c6b fix: Pass all parsed options to ReconnectingPostgresqlDatabase 2024-08-12 08:52:16 -06:00
Timothy J. Baek
70f580ec45 fix 2024-08-12 15:10:08 +01:00
Timothy J. Baek
eae35dddc2 refac 2024-08-12 12:47:54 +01:00
Timothy Jaeryang Baek
bb979c9a78 Merge pull request #4540 from open-webui/dependabot/pip/backend/dev/pytest-approx-eq-8.3.2
chore(deps): update pytest requirement from ~=8.2.2 to ~=8.3.2 in /backend
2024-08-12 13:31:02 +02:00
Timothy Jaeryang Baek
4f959c31de Merge pull request #4537 from open-webui/dependabot/pip/backend/dev/langfuse-2.43.3
chore(deps): bump langfuse from 2.39.2 to 2.43.3 in /backend
2024-08-12 13:30:52 +02:00
Timothy Jaeryang Baek
3bbe065db1 Merge pull request #4541 from open-webui/dependabot/pip/backend/dev/pyjwt-crypto--2.9.0
chore(deps): bump pyjwt[crypto] from 2.8.0 to 2.9.0 in /backend
2024-08-12 13:30:43 +02:00
dependabot[bot]
41460e1335 chore(deps): bump pyjwt[crypto] from 2.8.0 to 2.9.0 in /backend
Bumps [pyjwt[crypto]](https://github.com/jpadilla/pyjwt) from 2.8.0 to 2.9.0.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.8.0...2.9.0)

---
updated-dependencies:
- dependency-name: pyjwt[crypto]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:15:42 +00:00
dependabot[bot]
ffdb44f887 chore(deps): update pytest requirement in /backend
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.2...8.3.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:15:40 +00:00
dependabot[bot]
549d3b4d10 chore(deps): bump langchain from 0.2.11 to 0.2.12 in /backend
Bumps [langchain](https://github.com/langchain-ai/langchain) from 0.2.11 to 0.2.12.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain==0.2.11...langchain==0.2.12)

---
updated-dependencies:
- dependency-name: langchain
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:15:35 +00:00
dependabot[bot]
879f85802a chore(deps): bump chromadb from 0.5.4 to 0.5.5 in /backend
Bumps [chromadb](https://github.com/chroma-core/chroma) from 0.5.4 to 0.5.5.
- [Release notes](https://github.com/chroma-core/chroma/releases)
- [Changelog](https://github.com/chroma-core/chroma/blob/main/RELEASE_PROCESS.md)
- [Commits](https://github.com/chroma-core/chroma/compare/0.5.4...0.5.5)

---
updated-dependencies:
- dependency-name: chromadb
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:15:30 +00:00
dependabot[bot]
d652a1bbb1 chore(deps): bump langfuse from 2.39.2 to 2.43.3 in /backend
Bumps [langfuse](https://github.com/langfuse/langfuse) from 2.39.2 to 2.43.3.
- [Release notes](https://github.com/langfuse/langfuse/releases)
- [Commits](https://github.com/langfuse/langfuse/commits)

---
updated-dependencies:
- dependency-name: langfuse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:15:25 +00:00
Timothy Jaeryang Baek
9c2429ff97 Merge pull request #4402 from michaelpoluektov/remove-ollama
refactor: re-use utils in Ollama
2024-08-12 00:45:15 +02:00
Timothy Jaeryang Baek
d0645d3c4f Merge pull request #4503 from open-webui/dependabot/pip/pip-621ce9c937
chore(deps): bump the pip group across 2 directories with 1 update
2024-08-12 00:40:46 +02:00
Timothy Jaeryang Baek
748be3e637 Merge pull request #4529 from cheahjs/fix/integration-tests
ci: fix cypress integration tests
2024-08-11 23:41:01 +02:00
Jun Siang Cheah
153ba168a0 tests: update share test to actually share 2024-08-11 22:30:25 +01:00
Jun Siang Cheah
c70b18b2ef tests: change how cypress detects chat messages 2024-08-11 16:22:33 +01:00
Jun Siang Cheah
af6420e06d ci: increase usable disk space for integration test 2024-08-11 14:17:32 +01:00
Michael Poluektov
547611b703 Merge branch 'dev' of https://github.com/open-webui/open-webui into remove-ollama 2024-08-10 11:47:20 +01:00
Timothy Jaeryang Baek
1b2ae7bb77 Merge pull request #4504 from OriginalSimon/dev
i18n: Update of the Ukrainian translation
2024-08-09 21:28:07 +02:00
Simon
5cd8011d53 Update translation.json 2024-08-09 21:03:19 +02:00
dependabot[bot]
208833d9f2 chore(deps): bump the pip group across 2 directories with 1 update
Bumps the pip group with 1 update in the / directory: [aiohttp](https://github.com/aio-libs/aiohttp).
Bumps the pip group with 1 update in the /backend directory: [aiohttp](https://github.com/aio-libs/aiohttp).


Updates `aiohttp` from 3.9.5 to 3.10.2
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.5...v3.10.2)

Updates `aiohttp` from 3.9.5 to 3.10.2
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.5...v3.10.2)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: aiohttp
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-09 18:21:50 +00:00
Timothy Jaeryang Baek
6863028540 Merge pull request #4500 from KarlLee830/translate
i18n: Update Chinese translation
2024-08-09 17:13:42 +02:00
Karl Lee
5e97a52cbe i18n: Update Chinese translation 2024-08-09 22:04:33 +08:00
Timothy Jaeryang Baek
af865ab035 Merge pull request #4474 from aleixdorca/dev
i18n: Updated catalan translation
2024-08-09 12:01:43 +02:00
Timothy J. Baek
01f622866f fix 2024-08-09 00:14:41 +02:00
Timothy J. Baek
e9d14601a1 refac 2024-08-09 00:08:20 +02:00
Timothy J. Baek
92e77d7b33 refac: katex 2024-08-09 00:01:38 +02:00
Timothy J. Baek
3b370bbcb3 fix 2024-08-08 20:46:39 +02:00
Aleix Dorca
20b1753a91 i18n: Update catalan translation.json 2024-08-08 17:18:59 +02:00
Aleix Dorca
b2379c7104 i18n: Update catalan translation.json 2024-08-08 17:16:52 +02:00
Timothy J. Baek
e491e96f88 fix: markdown '$$' rendering issue 2024-08-08 15:27:51 +02:00
Timothy J. Baek
8afc8c5714 chore: format 2024-08-08 15:07:59 +02:00
Timothy J. Baek
d388c20373 enh: codeblock i18n 2024-08-08 15:07:24 +02:00
Timothy J. Baek
13403cd7dc enh: codeblock i18n 2024-08-08 14:24:47 +02:00
Timothy Jaeryang Baek
52fd701f2e Merge pull request #4465 from open-webui/main
dev
2024-08-08 14:23:33 +02:00
Michael Poluektov
204a4fbe7a fix: backend format test 2024-08-08 12:45:23 +01:00
Michael Poluektov
549817627f Merge branch 'dev' into remove-ollama 2024-08-08 12:42:37 +01:00
Michael Poluektov
fa4d1d42a5 fix: backend format test 2024-08-08 12:41:41 +01:00
Michael Poluektov
309cd645f1 undo del 2024-08-08 12:30:07 +01:00
Michael Poluektov
a725801e55 fix: formatting test errors, remove print, merge dev 2024-08-08 11:34:48 +01:00
Michael Poluektov
8cdf9814bd fix: name differences 2024-08-08 11:01:00 +01:00
Michael Poluektov
e6bbce439d fix: repeat_penalty 2024-08-08 10:52:09 +01:00
Timothy Jaeryang Baek
8d257ed596 Merge commit from fork
SSRF Fix
2024-08-08 11:47:33 +02:00
Timothy Jaeryang Baek
a7063a598d Merge pull request #4448 from JohnTheNerd/comfyui-async-fix
fix: ComfyUI generation no longer causes FastAPI to stall for all users
2024-08-08 11:36:19 +02:00
Jan-Timo Hesse
367fa039a0 added install_frontmatter_requirements 2024-08-08 09:46:14 +02:00
Jan-Timo Hesse
71d88fe35d revert 2024-08-08 09:45:52 +02:00
John Karabudak
958fe9639a fix: ComfyUI generation no longer causes FastAPI to stall for all users
as the get_images() function involves a `while True` loop while waiting for a response from ComfyUI and is not async, when image generation is running the entire UI becomes unresponsive for all users.

furthermore, when image generation takes too long, the Docker health check starts failing.

this is certainly a bad fix as it does not convert everything to async, but rather just puts the blocking loop in a separate thread. however, it works and it at least fixes the problem for now.
2024-08-07 22:24:55 -02:30
Timothy Jaeryang Baek
670f28d694 Merge branch 'dev' into remove-ollama 2024-08-07 23:06:11 +02:00
Timothy Jaeryang Baek
3715994c25 Merge pull request #4439 from cdgco/dev
feat: Add OAuth Email Claim Variable
2024-08-07 22:13:10 +02:00
Carter Roeser
d72d5d0e8e feat: Add OAuth Email Claim Variable
Add an `OAUTH_EMAIL_CLAIM` variable to override the default "email" claim value.
2024-08-07 11:39:51 -07:00
Timothy J. Baek
dbe463a53d fix 2024-08-07 17:39:54 +02:00
Timothy J. Baek
678dd780ee chore: package 2024-08-07 17:39:00 +02:00
Timothy Jaeryang Baek
44c870447f Merge pull request #4385 from candidosales/sveltekit-2v
build: Migrated to SvelteKit 2v
2024-08-07 17:37:08 +02:00
Timothy Jaeryang Baek
70a8f6e707 Merge pull request #4431 from Nowheresly/fix4158_reconnect
feat: #4158 allow reconnection when websocket is closed
2024-08-07 17:13:57 +02:00
Sylvere Richard
2fb4d3356c fix: #4158 allow reconnection when websocket is closed
log reconnection attempts
mark session_id as mandatory on client-side
2024-08-07 17:05:55 +02:00
root
590fd129c8 SSRF Fix Updated 2024-08-07 10:59:22 -04:00
Timothy Jaeryang Baek
99d10d1189 Merge pull request #4430 from open-webui/dev
fix
2024-08-07 15:53:11 +02:00
Timothy J. Baek
ad9a7cb1e2 refac 2024-08-07 15:52:03 +02:00
Timothy J. Baek
8187922ef1 fix: "metadata" issue 2024-08-07 15:49:48 +02:00
Timothy Jaeryang Baek
c869652ef4 Merge pull request #4322 from open-webui/dev
0.3.12
2024-08-07 15:22:04 +02:00
Timothy J. Baek
240a30147d chore: requirements bump 2024-08-07 15:07:47 +02:00
Timothy J. Baek
91fdb86fcc chore: update pyproject.toml 2024-08-07 15:06:59 +02:00
Timothy J. Baek
0e5a56e2cf doc: changelog 2024-08-07 15:04:11 +02:00
Timothy J. Baek
40ecc2563a chore: format 2024-08-07 14:51:07 +02:00
Timothy J. Baek
7e473f194d fix: modal not closing in many model chat 2024-08-07 14:47:43 +02:00
Michael Poluektov
f62281a0c7 Merge branch 'dev' of https://github.com/open-webui/open-webui into remove-ollama 2024-08-07 11:47:46 +01:00
Timothy J. Baek
0c231fd387 fix: styling 2024-08-07 12:22:35 +02:00
Timothy Jaeryang Baek
7f3ebcaa91 Merge pull request #4410 from silentoplayz/silentoplayz-patch-1
docs: Update bug_report.md
2024-08-07 12:17:53 +02:00
root
1f8d08eaa2 SSRF Fix 2024-08-07 03:30:21 -04:00
Timothy J. Baek
5904ef86f2 refac 2024-08-07 02:18:29 +02:00
Timothy J. Baek
d692649bac refac 2024-08-07 02:11:37 +02:00
Timothy J. Baek
0d019a00c9 refac 2024-08-07 02:06:57 +02:00
Timothy J. Baek
e6b3de310b refac 2024-08-07 01:55:37 +02:00
silentoplayz
d19b96d0c2 Update bug_report.md 2024-08-06 23:10:04 +00:00
Timothy J. Baek
7cbc94592e fix: styling 2024-08-06 23:48:10 +02:00
Timothy J. Baek
9747f1e841 revert: markdown rendering 2024-08-06 23:34:51 +02:00
Timothy Jaeryang Baek
42bc24a646 Merge pull request #4404 from justinh-rahb/security-policy
Update SECURITY.md to Improve Vulnerability Reporting Process
2024-08-06 21:38:21 +02:00
Justin Hayes
35115957d8 Update SECURITY.md 2024-08-06 15:08:37 -04:00
Justin Hayes
b193eb1d82 Update SECURITY.md 2024-08-06 14:57:07 -04:00
Candido Sales Gomes
4105c9735e revert files 2024-08-06 09:38:42 -04:00
Michael Poluektov
ed205d82e8 fix: pop 2024-08-06 12:25:00 +01:00
Michael Poluektov
fc31267a54 refac: re-use utils.misc 2024-08-06 11:31:45 +01:00
Michael Poluektov
44c781f414 cleanup 2024-08-06 10:50:22 +01:00
Timothy J. Baek
ff90b125ee Revert "refac"
This reverts commit a140d319fe.
2024-08-06 11:43:47 +02:00
Michael Poluektov
831fe9f509 cleanup 2024-08-06 10:15:29 +01:00
Timothy J. Baek
a140d319fe refac 2024-08-06 10:29:29 +02:00
Timothy J. Baek
9581bf5dde refac: styling 2024-08-05 19:59:10 +02:00
Timothy J. Baek
76dcabdce6 fix 2024-08-05 19:54:32 +02:00
Timothy J. Baek
dc262a5f79 refac: styling 2024-08-05 19:43:51 +02:00
Timothy J. Baek
db5830dc28 refac: prose styling 2024-08-05 19:40:46 +02:00
Timothy J. Baek
ecf3d567cf chore: pyproject.toml 2024-08-05 19:29:32 +02:00
Timothy J. Baek
e8375e9acd refac 2024-08-05 19:16:57 +02:00
Timothy J. Baek
8c84c74197 refac 2024-08-05 18:58:57 +02:00
Timothy J. Baek
f7d1225c23 enh: codespan styling 2024-08-05 18:57:28 +02:00
Timothy Jaeryang Baek
3dc90b854c Merge pull request #4389 from open-webui/dev-markdown
refac: markdown
2024-08-05 18:01:26 +02:00
Timothy J. Baek
ac3c657315 refac 2024-08-05 18:00:55 +02:00
Timothy J. Baek
37b117a84c fix: styling 2024-08-05 18:00:04 +02:00
Timothy J. Baek
ab6346ea1c refac: markdown rendering
Co-Authored-By: Jun Siang Cheah <me@jscheah.me>
2024-08-05 17:47:18 +02:00
Candido Sales Gomes
b289eef523 typo 2024-08-05 11:16:28 -04:00
Timothy J. Baek
6e6f9862e6 fix 2024-08-05 17:15:07 +02:00
Timothy J. Baek
7d42a79177 refac: token rendering 2024-08-05 17:12:41 +02:00
Candido Sales Gomes
5315fb201d changelod updated 2024-08-05 11:10:31 -04:00
Candido Sales Gomes
6a012d290e migration to SvelteKit 2 2024-08-05 11:00:30 -04:00
Timothy Jaeryang Baek
05bbca5b07 Merge pull request #4369 from open-webui/dependabot/pip/backend/dev/black-24.8.0
chore(deps): bump black from 24.4.2 to 24.8.0 in /backend
2024-08-05 11:07:15 +02:00
Timothy Jaeryang Baek
5afe0be5b4 Merge pull request #4368 from open-webui/dependabot/pip/backend/dev/validators-0.33.0
chore(deps): bump validators from 0.28.1 to 0.33.0 in /backend
2024-08-05 11:07:04 +02:00
Timothy Jaeryang Baek
d8aa2cc05f Merge pull request #4367 from open-webui/dependabot/pip/backend/dev/python-pptx-1.0.0
chore(deps): bump python-pptx from 0.6.23 to 1.0.0 in /backend
2024-08-05 11:06:56 +02:00
Timothy Jaeryang Baek
7b071d403f Merge pull request #4366 from open-webui/dependabot/pip/backend/dev/pypdf-4.3.1
chore(deps): bump pypdf from 4.2.0 to 4.3.1 in /backend
2024-08-05 11:06:44 +02:00
Timothy Jaeryang Baek
d5b1e5e0c0 Merge pull request #4365 from open-webui/dependabot/pip/backend/dev/boto3-1.34.153
chore(deps): bump boto3 from 1.34.110 to 1.34.153 in /backend
2024-08-05 11:06:35 +02:00
Jan-Timo Hesse
cec5fdd144 Added EXTRA_MODULES argument 2024-08-05 09:42:16 +02:00
dependabot[bot]
d8498aa2b0 chore(deps): bump black from 24.4.2 to 24.8.0 in /backend
Bumps [black](https://github.com/psf/black) from 24.4.2 to 24.8.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.2...24.8.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 02:52:14 +00:00
dependabot[bot]
e593d3aee3 chore(deps): bump validators from 0.28.1 to 0.33.0 in /backend
Bumps [validators](https://github.com/python-validators/validators) from 0.28.1 to 0.33.0.
- [Release notes](https://github.com/python-validators/validators/releases)
- [Changelog](https://github.com/python-validators/validators/blob/master/CHANGES.md)
- [Commits](https://github.com/python-validators/validators/compare/0.28.1...0.33.0)

---
updated-dependencies:
- dependency-name: validators
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 02:52:10 +00:00
dependabot[bot]
323cfaf2d7 chore(deps): bump python-pptx from 0.6.23 to 1.0.0 in /backend
Bumps [python-pptx](https://github.com/scanny/python-pptx) from 0.6.23 to 1.0.0.
- [Changelog](https://github.com/scanny/python-pptx/blob/master/HISTORY.rst)
- [Commits](https://github.com/scanny/python-pptx/compare/v0.6.23...v1.0.0)

---
updated-dependencies:
- dependency-name: python-pptx
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 02:52:07 +00:00
dependabot[bot]
637f0c6fb2 chore(deps): bump pypdf from 4.2.0 to 4.3.1 in /backend
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 4.2.0 to 4.3.1.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/4.2.0...4.3.1)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 02:52:06 +00:00
dependabot[bot]
2756403102 chore(deps): bump boto3 from 1.34.110 to 1.34.153 in /backend
Bumps [boto3](https://github.com/boto/boto3) from 1.34.110 to 1.34.153.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.34.110...1.34.153)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 02:52:03 +00:00
Timothy Jaeryang Baek
92861d095a Merge pull request #4362 from PeterDaveHello/Update-locale-zh-TW
i18n: Update and improve zh-TW Traditional Chinese translation
2024-08-05 01:05:10 +02:00
Timothy J. Baek
bf6c6627e8 revert 2024-08-05 01:03:22 +02:00
Peter Dave Hello
b217cb76f0 i18n: Update and improve zh-TW Traditional Chinese translation 2024-08-05 03:29:12 +08:00
Timothy J. Baek
b414fde6ca fix 2024-08-04 18:34:29 +02:00
Timothy J. Baek
d8c39569be fix: infinite scroll stuck on loading issue 2024-08-04 18:20:59 +02:00
Timothy J. Baek
5ce15bb0df refac 2024-08-04 18:16:00 +02:00
Timothy J. Baek
88086935af feat: markdown image preview 2024-08-04 18:14:17 +02:00
Timothy J. Baek
ace3552e15 chore: format 2024-08-04 17:42:16 +02:00
Timothy Jaeryang Baek
003ceff7e4 Merge pull request #4349 from open-webui/dev-scroll
feat: Sidebar infinite scroll (pagination)
2024-08-04 17:36:18 +02:00
Timothy J. Baek
209ccdf668 refac 2024-08-04 17:35:26 +02:00
Timothy J. Baek
e5dd7e65d4 refac 2024-08-04 17:31:41 +02:00
Timothy J. Baek
b2999ad590 refac 2024-08-04 17:11:41 +02:00
Timothy Jaeryang Baek
1871a7a2fa Merge pull request #4354 from cheahjs/fix/admin-shared-chat-when-disabled
fix: admins shared chats with ENABLE_ADMIN_CHAT_ACCESS set to false
2024-08-04 17:08:33 +02:00
Timothy J. Baek
49677e9c9d refac 2024-08-04 17:04:15 +02:00
Jun Siang Cheah
73954f4a63 fix: admins viewing shared chats with ENABLE_ADMIN_CHAT_ACCESS set to false 2024-08-04 16:00:52 +01:00
Timothy J. Baek
a084938d9c refac: chatlist skip, limit -> page 2024-08-04 16:58:08 +02:00
Timothy Jaeryang Baek
1bf042ac84 Merge pull request #4351 from cheahjs/feat/disable-admin-chat-view
feat: add ENABLE_ADMIN_CHAT_ACCESS to control admin access to user chats
2024-08-04 16:37:30 +02:00
Timothy J. Baek
a2f9f7c975 refac 2024-08-04 16:36:44 +02:00
Jun Siang Cheah
565f40c642 feat: add ENABLE_ADMIN_CHAT_ACCESS to control admin access to user chats 2024-08-04 15:16:14 +01:00
Timothy J. Baek
4441338574 refac: onScroll -> IntersectionObserver for infinite scroll 2024-08-04 15:58:36 +02:00
Timothy Jaeryang Baek
389d650ee3 Merge pull request #4266 from thearyadev/sidebar-pagination
feat: Sidebar infinite scroll (pagination)
2024-08-04 15:33:09 +02:00
Timothy J. Baek
080d45239a fix: chat control "stop token" param issue 2024-08-04 14:27:18 +02:00
Timothy Jaeryang Baek
91851114e4 Merge pull request #4295 from michaelpoluektov/refactor-tools
refactor: Refactor OpenAI API to use helper functions, silence LSP/linter warnings
2024-08-04 14:17:52 +02:00
Timothy Jaeryang Baek
5b11099a0b Merge pull request #4335 from 5E-324/toggle-scrolling
feat: Add option to toggle scrolling to bottom when switching between different branches of the conversation
2024-08-04 14:11:03 +02:00
Timothy Jaeryang Baek
2996d1e096 Merge pull request #4332 from cheahjs/fix/integration-test-no-space
ci: prune docker cache earlier in integration tests
2024-08-04 14:09:39 +02:00
Timothy Jaeryang Baek
be82175f86 Merge pull request #4338 from KarlLee830/translate
i18n: Update Chinese Translation
2024-08-04 14:09:25 +02:00
Timothy Jaeryang Baek
05977bd1c7 Merge pull request #4342 from michaelpoluektov/fix-non-streaming-function-text
fix: function returning "str"
2024-08-04 14:09:12 +02:00
Timothy Jaeryang Baek
8074289a8f Merge pull request #4333 from JohnTheNerd/comfyui-fix
fix: made the COMFYUI_FLUX_FP8_CLIP environment variable bool instead of str
2024-08-04 14:08:44 +02:00
Michael Poluektov
f8ba0334e8 fix: non streaming functions 2024-08-04 12:10:02 +01:00
Karl Lee
7c9bed83d2 i18n: Update Chinese Translation 2024-08-04 16:00:42 +08:00
Zhuoran
482a7723b2 Default to true 2024-08-04 11:33:20 +08:00
Zhuoran
948d29b676 Add option to toggle scrolling to bottom when switching between branches 2024-08-04 11:15:20 +08:00
Aryan Kothari
3fa6c41303 chore: remove debug ui elements 2024-08-03 20:17:03 -04:00
Aryan Kothari
220a4bb535 add: loading animation 2024-08-03 20:13:59 -04:00
Aryan Kothari
287559e834 fix: tag deletion rehydration bug
fixes a bug that caused the deletion of a tag, when filtering by tag, to rehydrate all chats instead of the filtered list.
2024-08-03 19:42:45 -04:00
Aryan Kothari
cdac0cd1df refactor: disable pagination moved to a function
reduces repeated code
2024-08-03 19:40:31 -04:00
Michael Poluektov
3653126179 refac: undo raw split, remove gpt-4-vision-preview 2024-08-04 00:34:24 +01:00
Jun Siang Cheah
2eb662df85 fix: prune docker cache earlier in integration tests 2024-08-03 20:53:31 +01:00
John Karabudak
cdcf214455 made the COMFYUI_FLUX_FP8_CLIP environment variable bool instead of str
this should fix #4328
2024-08-03 16:58:03 -02:30
Timothy Jaeryang Baek
a75a9c953a Merge pull request #4329 from cheahjs/fix/missing-openai-usage-info
fix: missing openai usage information
2024-08-03 20:51:03 +02:00
Timothy Jaeryang Baek
800ba206f7 Merge pull request #4326 from amirsubhi/dev
i18n : Updated ms-MY Malay (Bahasa Malaysia) Language
2024-08-03 20:50:27 +02:00
Timothy Jaeryang Baek
8d5aa98297 Merge pull request #4325 from Yanyutin753/model_bug
💄 Fixed BUG that could not be deleted after @model was selected
2024-08-03 20:48:13 +02:00
Jun Siang Cheah
283234d51d fix: missing openai usage information 2024-08-03 19:06:19 +01:00
Aryan Kothari
f9e1a933a9 fix: bug in chat deletion pagination interact
change 1: when selecting a tag to filter the `tagView` store is set to disable paginated loading. This is so all tagged items can be loaded at once.  deleting a tag when in the filtered view returns to the unfiltered view. this change now sets the `tagView` store to `false` so pagination can continue

change 2: formatting
2024-08-03 11:53:02 -04:00
Clivia
ebd8ef1a9e 💄 Fixed BUG that could not be deleted after @model was selected 2024-08-03 23:36:30 +08:00
amirsubhi
ed691e26a6 Updated ms-MY Malay (Bahasa Malaysia) Language
Added ms-MY Malay (Bahasa Malaysia) Translation
2024-08-03 23:09:54 +08:00
Aryan Kothari
067d76fece fix: dynamically determine page size
- larger screens where chat list (35px*pageSize) is smaller than window.InnerHeight, will not be able to scroll.
- performance can dynamically scale, allowing mobile devices to load only what they need.
2024-08-03 10:35:13 -04:00
Timothy Jaeryang Baek
534c18c94c Merge pull request #4307 from Yanyutin753/@model_image
💄 Support @Model display model pictures
2024-08-03 16:01:45 +02:00
Timothy J. Baek
af9e0cc33a fix 2024-08-03 16:01:25 +02:00
Aryan Kothari
6847c2fc8c Merge branch 'origin/dev' into sidebar-pagination [skip ci] 2024-08-03 09:57:54 -04:00
Clivia
028eb7b351 Better Practice
 Better Practice
2024-08-03 21:37:45 +08:00
Michael Poluektov
12c21fac22 refac: apps/openai/main.py and utils 2024-08-03 14:24:26 +01:00
Timothy J. Baek
774defd184 fix: image preview element styling issue 2024-08-03 14:42:06 +02:00
Timothy Jaeryang Baek
6657f28694 Merge pull request #4309 from aleixdorca/dev
i18n: Update catalan translation.json
2024-08-03 14:18:09 +02:00
Aleix Dorca
9d7507236f i18n: Update catalan translation.json 2024-08-03 06:46:08 +02:00
Clivia
8f49429228 Show only models that are not be hidden 2024-08-03 10:58:12 +08:00
Clivia
f21e9dbd9a 💄 Support @Model display model pictures 2024-08-03 10:48:54 +08:00
Timothy Jaeryang Baek
d3146d20ad Merge pull request #4304 from open-webui/dev
fix: requirements
2024-08-03 00:48:57 +02:00
Timothy J. Baek
24a177a149 chore: requirements 2024-08-03 00:47:05 +02:00
Timothy Jaeryang Baek
a58dfccb7d Merge pull request #4273 from open-webui/dev
0.3.11
2024-08-03 00:03:15 +02:00
Timothy J. Baek
b35293228e refac 2024-08-03 00:01:54 +02:00
Timothy J. Baek
963e250654 refac 2024-08-02 23:54:18 +02:00
Timothy J. Baek
ca8b766c09 refac 2024-08-02 23:48:49 +02:00
Timothy J. Baek
21eca7f1c1 doc: changelog 2024-08-02 23:47:00 +02:00
Timothy J. Baek
8062866973 chore: format 2024-08-02 22:35:02 +02:00
Timothy Jaeryang Baek
99530358fd Merge pull request #4300 from JohnTheNerd/flux-image-gen
feat: added support for the new Flux image gen model using ComfyUI
2024-08-02 22:32:22 +02:00
Timothy J. Baek
621393ca62 chore: format 2024-08-02 22:31:37 +02:00
Timothy J. Baek
0c6284be02 fix: user voice should update when global voice updates 2024-08-02 22:28:39 +02:00
Timothy Jaeryang Baek
9d5e3e2a91 Merge pull request #4299 from open-webui/dev-elevenlabs
feat: Fetch ElevenLabs voice ID by name
2024-08-02 19:29:24 +02:00
Timothy J. Baek
7f260938db refac 2024-08-02 19:29:03 +02:00
Timothy J. Baek
c416444e24 fix 2024-08-02 19:26:34 +02:00
Timothy J. Baek
b559bc84a7 refac 2024-08-02 19:24:47 +02:00
Timothy Jaeryang Baek
3f53abb233 Merge pull request #4018 from justinh-rahb/elevenlabs-voice-names
feat: Fetch ElevenLabs voice ID by name
2024-08-02 18:44:48 +02:00
Timothy J. Baek
67efd0dd39 enh: enable tools with url search param 2024-08-02 18:32:51 +02:00
Timothy J. Baek
dcd32faa83 fix: styling 2024-08-02 18:12:54 +02:00
Timothy J. Baek
8fcb5cee66 enh: min_p 2024-08-02 18:11:20 +02:00
Timothy J. Baek
13b757d847 enh: min_p added to params 2024-08-02 18:10:12 +02:00
Timothy J. Baek
c6d7f24542 fix: block users from /workspace and /admin 2024-08-02 18:08:23 +02:00
Timothy Jaeryang Baek
4c1a9380e6 Merge pull request #3998 from ScribblerCoder/patch-1
fix: Dockerfile Healthcheck unexpected exit code
2024-08-02 17:56:27 +02:00
John Karabudak
ad6e8edcd3 added support for the new Flux image gen model using ComfyUI
this commit adds three environment variables:

- COMFYUI_FLUX: determines whether Flux is used, the workflow is completely different so this is necessary.
- COMFYUI_FLUX_WEIGHT_DTYPE: sets the weight precision for Flux. you will probably want to set this to "fp8_e4m3fn" as the fp16 weights take up about 24GB of VRAM. optional, defaults to "default".
- COMFYUI_FLUX_FP8_CLIP: Flux requires two CLIP models downloaded, one of which is available in fp8 and fp16. set to true if you are using the fp8 CLIP weights.
2024-08-02 13:23:20 -02:30
Timothy J. Baek
95c742ba9b chore: format 2024-08-02 17:47:43 +02:00
Timothy J. Baek
546d442626 refac 2024-08-02 17:45:30 +02:00
Timothy J. Baek
ed8c0b23a0 refac 2024-08-02 17:41:15 +02:00
Timothy J. Baek
c8f44b73f1 refac: user valves save handler 2024-08-02 17:36:16 +02:00
Timothy J. Baek
bf6b149b8b refac: user valves 2024-08-02 17:19:52 +02:00
Timothy Jaeryang Baek
f334c834e5 Merge pull request #4274 from Yanyutin753/display_size
💄Feat show the size of file and prepare for subsequent upload restrictions
2024-08-02 14:27:42 +02:00
Timothy Jaeryang Baek
7c850bb78a Merge pull request #4289 from OriginalSimon/dev
i18n: Update of the Ukrainian translation
2024-08-02 14:27:11 +02:00
Simon
a280fed4be Merge branch 'open-webui:dev' into dev 2024-08-02 14:07:04 +02:00
Timothy Jaeryang Baek
cf9b5241ae Merge pull request #4282 from laurentiu-miu/dev
i18n: Added Romanian translation
2024-08-02 13:31:33 +02:00
laurentium
dfa25af271 i18n: Romanian translation fix pull request deleted extra space 2024-08-02 13:14:50 +03:00
laurentium
b538c5a206 i18n: Romanian translation fix one-to-one equivalent with the en-US file 2024-08-02 12:58:11 +03:00
laurentium
4fa3fcbb3b i18n: Romanian translation 2024-08-02 12:03:00 +03:00
Clivia
b049ae269b 💄Feat show the size of file and prepare for subsequent upload restrictions 2024-08-02 09:46:16 +08:00
Timothy J. Baek
e5bf27e716 enh: include desc in fuzzy search 2024-08-02 01:53:53 +02:00
Timothy Jaeryang Baek
a9a6ed8b71 Merge pull request #4237 from michaelpoluektov/refactor-webui-main
refactor: Simplify functions
2024-08-02 01:47:06 +02:00
Timothy J. Baek
e6c64282fc refac 2024-08-02 01:45:50 +02:00
Timothy J. Baek
64b41655bb chore: format 2024-08-01 22:50:59 +02:00
Timothy J. Baek
6ac40552b4 feat: model selector fuzzy search
Co-Authored-By: Aryan Kothari <87589047+thearyadev@users.noreply.github.com>
2024-08-01 22:47:53 +02:00
Timothy Jaeryang Baek
039c5c540b Merge pull request #4225 from Yanyutin753/pref_file_upload
Initialize fileItem first to speed up file display
2024-08-01 22:09:59 +02:00
Timothy J. Baek
c9ed934d0b refac: file should not have 'uploaded' status 2024-08-01 22:09:29 +02:00
Aryan Kothari
06a64219bc fix: bool eval order 2024-08-01 15:54:12 -04:00
Timothy Jaeryang Baek
ef36b21684 Merge pull request #4253 from erickgamer787/fix-SensitiveInput-for-admin-pages
fix: Fix the SensitiveInput  the browser thought it was a password field
2024-08-01 21:43:42 +02:00
Timothy J. Baek
c44e51ae58 refac 2024-08-01 21:43:13 +02:00
Aryan Kothari
2c4bc7a2b2 refactor: uses of chats.set(...) support pagi sidebar 2024-08-01 15:20:36 -04:00
Aryan Kothari
62dc486c85 add: add paginated scroll handler 2024-08-01 15:19:14 -04:00
Aryan Kothari
d11961626c add: use skip and limit in api call 2024-08-01 15:15:49 -04:00
Aryan Kothari
519375b4c0 add: skip and limit use in query
- limit default changed to -1
2024-08-01 15:13:45 -04:00
Timothy Jaeryang Baek
6ecb7c80f1 Merge pull request #4262 from michaelpoluektov/fix-redirect-uri
fix: Fix custom redirect URI for OAuth behind reverse proxy
2024-08-01 20:57:27 +02:00
Timothy Jaeryang Baek
380cb93e46 Merge pull request #4257 from thearyadev/fix/pdf-gen-static-path
fix: pdf gen static path resolution
2024-08-01 20:57:00 +02:00
Timothy Jaeryang Baek
36e7662706 Merge pull request #4263 from mr-raw/dev
i18n: Translated missing keys. Minor changes to existing translations.
2024-08-01 20:41:00 +02:00
Aryan Kothari
49199819db add: stores for pagination state 2024-08-01 12:24:05 -04:00
Simon
aa8d26496c Merge branch 'open-webui:dev' into dev 2024-08-01 15:52:58 +02:00
Michael Poluektov
4619e32b6a undo changelog changes 2024-08-01 12:59:39 +01:00
Michael Poluektov
0352e956b6 fix: redirect uri 2024-08-01 12:54:06 +01:00
Michael Poluektov
f999956997 Merge remote-tracking branch 'oauth/main' into dev 2024-08-01 12:53:36 +01:00
Erik Raae
bfd268c5e6 Translated missing keys. Minor changes to existing translations. 2024-08-01 13:46:25 +02:00
Aryan Kothari
b7ad47017d fix: static dir path resolution
when running in different environments, the static_path is different.
This path is now 'determined' at runtime
2024-07-31 23:56:47 -04:00
Michael Poluektov
502b722902 Merge branch 'dev' of https://github.com/open-webui/open-webui into refactor-webui-main 2024-07-31 22:09:36 +01:00
Michael Poluektov
c89b34fd75 flatten job() 2024-07-31 22:05:37 +01:00
Michael Poluektov
b9b1fdd1a1 refac: rename message_template 2024-07-31 22:01:22 +01:00
Michael Poluektov
2e0fa1c6a0 refac: rename stream_message_template 2024-07-31 22:00:00 +01:00
Michael Poluektov
f8726719ef refac: rename whole_message_template, silence lsp 2024-07-31 21:58:40 +01:00
Erick Joseph
3569fe9c73 the fix for the issue where chrome thought the SensitiveInput input was a password field 2024-07-31 16:15:00 -03:00
Timothy Jaeryang Baek
4ffcabfb3f Merge pull request #4250 from erickgamer787/i18n-correction-to-pt-br
i18n: redone and updated the entire pt br translation
2024-07-31 21:01:42 +02:00
Erick Joseph
a7ed74744f correct and update all pt br translation 2024-07-31 15:53:02 -03:00
Michael Poluektov
ae0bb8f1eb Merge branch 'dev' of https://github.com/open-webui/open-webui into refactor-webui-main 2024-07-31 17:42:16 +01:00
Michael Poluektov
034411e47e fix: type not manifold 2024-07-31 17:24:00 +01:00
Michael Poluektov
baf58ef396 refac: use add_or_update_system_message 2024-07-31 17:16:07 +01:00
Michael Poluektov
006fc3495e fix: stream_message_template 2024-07-31 16:45:47 +01:00
Michael Poluektov
29a3b82336 refac: reuse stream_message_template 2024-07-31 15:26:26 +01:00
Michael Poluektov
22a5e196c9 simplify main.py 2024-07-31 14:01:40 +01:00
Michael Poluektov
deec41d29a fix: function early returns 2024-07-31 13:51:25 +01:00
Michael Poluektov
3978efd710 refac: Refactor functions 2024-07-31 13:35:02 +01:00
Timothy J. Baek
7a80e732df refac: styling 2024-07-31 12:37:49 +01:00
Clivia
6681df29d2 Initialize fileItem first to speed up file display 2024-07-31 07:25:53 +08:00
Timothy J. Baek
9d58bb1c66 fix: styling 2024-07-30 12:34:30 +01:00
Timothy J. Baek
acbdb05bd0 fix: styling 2024-07-30 11:44:32 +01:00
Simon
25f5259e84 Update translation.json 2024-07-29 14:16:13 +02:00
Timothy J. Baek
0ced153f86 refac 2024-07-28 23:17:49 +01:00
Timothy J. Baek
faca8c8b53 feat: multiple action support 2024-07-28 22:02:23 +01:00
Timothy Jaeryang Baek
4ad8181088 Merge pull request #4166 from que-nguyen/dev
Update Vietnamese translations
2024-07-28 21:08:39 +02:00
Que Nguyen
4f3ff4a69d Update Vietnamese translations 2024-07-28 21:44:25 +07:00
Timothy J. Baek
fc0f2f2b3a chore: format 2024-07-28 13:13:33 +01:00
Timothy J. Baek
b4cd084117 feat: action selector 2024-07-28 13:06:47 +01:00
Timothy J. Baek
c1fd55bb04 fix/refac: actions 2024-07-28 13:00:58 +01:00
Timothy J. Baek
77b2d2dbee refac: styling 2024-07-27 23:34:29 +01:00
Timothy J. Baek
f92aed1b91 fix 2024-07-27 23:07:58 +01:00
Timothy Jaeryang Baek
90a6be8001 Merge pull request #4138 from ther0bster/fix-socket-io-url
fix: socket.io client url
2024-07-27 16:17:36 +02:00
Timothy Jaeryang Baek
2e4de209fe Merge pull request #4149 from arsaboo/openrouter
chore: Add HTTP-Referer and X-Title headers for OpenRouter
2024-07-27 16:06:17 +02:00
Alok Saboo
287147687e Add HTTP-Referer and X-Title headers for OpenRouter 2024-07-27 09:43:03 -04:00
ther0bster
a53f5d01aa fix: don't break dev tests 2024-07-26 19:01:36 +02:00
Timothy J. Baek
1aaa2e8219 fix: ollama rag issue workaround 2024-07-26 12:22:13 +01:00
ther0bster
02b104f56b fix: socket.io client url
* fixes backend crash with IPv6 and some IPv4 setups
* instead of passing empty url, let socket.io set default url
  (defaults to window.location.host)
2024-07-25 21:23:28 +02:00
Timothy J. Baek
e691839771 refac: styling 2024-07-25 12:16:19 +01:00
Timothy J. Baek
4c22d130d9 refac: styling 2024-07-25 12:08:47 +01:00
Timothy Jaeryang Baek
065d23d0b1 Merge pull request #4068 from Louden7/main
feat: Added environment variable to hide email and password sign in elements
2024-07-25 11:21:49 +02:00
Timothy Jaeryang Baek
4b0a232ae1 Merge pull request #4059 from thearyadev/feat/model-selection-with-arrow-keys
feat: select model with arrow keys
2024-07-25 11:13:08 +02:00
Timothy Jaeryang Baek
81130c205c Merge pull request #4096 from open-webui/dependabot/pip/pip-b4bdd6eb86
chore(deps): bump the pip group across 2 directories with 2 updates
2024-07-25 11:12:47 +02:00
Dillon
36b94ca5f5 updated environment variable to suggested ENABLE_LOGIN_FORM 2024-07-24 21:44:40 -04:00
Aryan Kothari
9e4326a582 fix: unintentional import from previous commit 2024-07-24 19:03:31 -04:00
dependabot[bot]
8193c2f847 chore(deps): bump the pip group across 2 directories with 2 updates
Bumps the pip group with 2 updates in the / directory: [pymysql](https://github.com/PyMySQL/PyMySQL) and [langchain-community](https://github.com/langchain-ai/langchain).
Bumps the pip group with 1 update in the /backend directory: [langchain-community](https://github.com/langchain-ai/langchain).


Updates `pymysql` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/PyMySQL/PyMySQL/releases)
- [Changelog](https://github.com/PyMySQL/PyMySQL/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyMySQL/PyMySQL/compare/v1.1.0...v1.1.1)

Updates `langchain-community` from 0.2.0 to 0.2.9
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-community==0.2.0...langchain-community==0.2.9)

Updates `langchain-community` from 0.2.6 to 0.2.9
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-community==0.2.0...langchain-community==0.2.9)

---
updated-dependencies:
- dependency-name: pymysql
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: langchain-community
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: langchain-community
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-24 17:41:24 +00:00
Aryan Kothari
fbef731a04 fix: check filteredItems length before unsafe index access 2024-07-24 09:06:21 -04:00
Aryan Kothari
dbf88a2eca refactor: rename pseudoSelectedIndex to selectedModelIdx 2024-07-24 09:04:56 -04:00
Timothy J. Baek
413a9031eb chore: format 2024-07-24 11:36:41 +01:00
Timothy J. Baek
23e69bcdb4 enh: AsyncGenerator support 2024-07-24 11:29:57 +01:00
Timothy J. Baek
edff071cd2 refac 2024-07-24 11:25:07 +01:00
Timothy Jaeryang Baek
3b487cfae9 Merge pull request #4046 from thearyadev/chat-list-optimization
perf: optimize query for chat list
2024-07-24 12:21:04 +02:00
Timothy J. Baek
a8d2072e9f refac 2024-07-24 11:19:42 +01:00
Timothy Jaeryang Baek
260e42a691 Merge pull request #4036 from open-webui/dependabot/pip/backend/dev/google-generativeai-0.7.2
chore(deps): bump google-generativeai from 0.5.4 to 0.7.2 in /backend
2024-07-24 12:17:31 +02:00
Timothy Jaeryang Baek
596a9c60d7 Merge pull request #4039 from open-webui/dependabot/pip/backend/dev/rapidocr-onnxruntime-1.3.24
chore(deps): bump rapidocr-onnxruntime from 1.3.22 to 1.3.24 in /backend
2024-07-24 12:17:24 +02:00
Timothy Jaeryang Baek
a47e4a1148 Merge pull request #4047 from Peter-De-Ath/confirmDialog-add-inputValue
feat: add eventConfirmationInputValue handling in Chat.svelte
2024-07-24 12:16:45 +02:00
Timothy Jaeryang Baek
312c8b9e7a Merge pull request #4042 from Yanyutin753/model_image
💄 Add a model image to the model selector
2024-07-24 12:15:33 +02:00
Timothy Jaeryang Baek
1d99508943 Merge pull request #4055 from que-nguyen/dev
Update Vietnamese translations
2024-07-24 12:11:46 +02:00
Timothy Jaeryang Baek
b42fda0971 Merge pull request #4040 from open-webui/dependabot/pip/backend/dev/duckduckgo-search-approx-eq-6.2.1
chore(deps): update duckduckgo-search requirement from ~=6.1.12 to ~=6.2.1 in /backend
2024-07-24 12:11:10 +02:00
Timothy Jaeryang Baek
cf377d2e1c Merge pull request #4038 from open-webui/dependabot/pip/backend/dev/unstructured-0.15.0
chore(deps): bump unstructured from 0.14.10 to 0.15.0 in /backend
2024-07-24 12:07:50 +02:00
Timothy Jaeryang Baek
ec9d0b8a6d Merge pull request #4037 from open-webui/dependabot/pip/backend/dev/langfuse-2.39.2
chore(deps): bump langfuse from 2.38.0 to 2.39.2 in /backend
2024-07-24 12:07:41 +02:00
Timothy Jaeryang Baek
14cac8ed22 Merge pull request #4030 from songritk/main
i18n: Thai translation
2024-07-24 12:02:43 +02:00
Dillon
4ecf9dd62d Created if blocks to show or hide username, password, signin and or sections depending on new enable_username_password_login variable 2024-07-23 22:25:29 -04:00
Dillon
b56dcf155c Added enable_username_password_login to the Config object 2024-07-23 22:23:37 -04:00
Dillon
63ffdb38aa Added and set enable_username_password_login to the get_app_config function 2024-07-23 22:22:09 -04:00
Dillon
f9289d3079 Created new PersistentConfig for new environment variable ENABLE_USERNAME_PASSWORD_LOGIN 2024-07-23 22:20:45 -04:00
Dillon
709b56bc40 imported and added new ENABLE_USERNAME_PASSWORD_LOGIN environment variable 2024-07-23 22:19:41 -04:00
Aryan Kothari
eb38d382ba fix: pseudoSelectedIndex is reset when modal is closed. 2024-07-23 11:31:17 -04:00
Aryan Kothari
5beaa5d892 feat: select model with arrow keys (+enter) 2024-07-23 11:05:11 -04:00
Que Nguyen
01b24f6282 Update Vietnamese translations 2024-07-23 17:33:22 +07:00
Peter De-Ath
cbe3694b81 refac: add eventConfirmationInputValue handling in Chat.svelte 2024-07-22 20:43:31 +01:00
Aryan Kothari
f531a51e91 chore: formatting 2024-07-22 14:45:47 -04:00
Aryan Kothari
a0667dfd1b change /chats/ and /chats/list to utilize new function 2024-07-22 14:09:22 -04:00
Aryan Kothari
2b78e613a4 add func to get chat list with more specific sql query 2024-07-22 14:08:15 -04:00
Clivia
b34ab10b5e 💄 Add a model image to the model selector 2024-07-22 20:30:27 +08:00
dependabot[bot]
f07cc37939 chore(deps): update duckduckgo-search requirement in /backend
Updates the requirements on [duckduckgo-search](https://github.com/deedy5/duckduckgo_search) to permit the latest version.
- [Release notes](https://github.com/deedy5/duckduckgo_search/releases)
- [Commits](https://github.com/deedy5/duckduckgo_search/compare/v6.1.12...v6.2.1)

---
updated-dependencies:
- dependency-name: duckduckgo-search
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:44:43 +00:00
dependabot[bot]
957b0ecd15 chore(deps): bump rapidocr-onnxruntime from 1.3.22 to 1.3.24 in /backend
Bumps [rapidocr-onnxruntime](https://github.com/RapidAI/RapidOCR) from 1.3.22 to 1.3.24.
- [Release notes](https://github.com/RapidAI/RapidOCR/releases)
- [Commits](https://github.com/RapidAI/RapidOCR/compare/v1.3.22...v1.3.24)

---
updated-dependencies:
- dependency-name: rapidocr-onnxruntime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:44:40 +00:00
dependabot[bot]
659bc246c9 chore(deps): bump unstructured from 0.14.10 to 0.15.0 in /backend
Bumps [unstructured](https://github.com/Unstructured-IO/unstructured) from 0.14.10 to 0.15.0.
- [Release notes](https://github.com/Unstructured-IO/unstructured/releases)
- [Changelog](https://github.com/Unstructured-IO/unstructured/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Unstructured-IO/unstructured/compare/0.14.10...0.15.0)

---
updated-dependencies:
- dependency-name: unstructured
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:44:37 +00:00
dependabot[bot]
1502af7e94 chore(deps): bump langfuse from 2.38.0 to 2.39.2 in /backend
Bumps [langfuse](https://github.com/langfuse/langfuse) from 2.38.0 to 2.39.2.
- [Release notes](https://github.com/langfuse/langfuse/releases)
- [Commits](https://github.com/langfuse/langfuse/commits)

---
updated-dependencies:
- dependency-name: langfuse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:44:33 +00:00
dependabot[bot]
26c5a533ec chore(deps): bump google-generativeai from 0.5.4 to 0.7.2 in /backend
Bumps [google-generativeai](https://github.com/google/generative-ai-python) from 0.5.4 to 0.7.2.
- [Release notes](https://github.com/google/generative-ai-python/releases)
- [Changelog](https://github.com/google-gemini/generative-ai-python/blob/main/RELEASE.md)
- [Commits](https://github.com/google/generative-ai-python/compare/v0.5.4...v0.7.2)

---
updated-dependencies:
- dependency-name: google-generativeai
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:44:27 +00:00
Songrit Kitisriworapan
4274016491 i18n: Thai translation 2024-07-21 21:06:49 +07:00
Justin Hayes
c6c298b412 Fetch didn't happen 2024-07-20 11:02:59 -04:00
Timothy Jaeryang Baek
63eda0fe42 Merge pull request #4024 from Seth-Rothschild/fix-seed-0
fix: seed and temperature can be 0 in models
2024-07-20 14:01:34 +02:00
Seth Rothschild
c3693c91b3 fix: allow temperature and seed to be 0 2024-07-20 06:53:52 -04:00
Timothy J. Baek
e426067e46 fix: latex
Co-Authored-By: Clivia <132346501+Yanyutin753@users.noreply.github.com>
2024-07-20 11:33:27 +02:00
Timothy J. Baek
2e482eca6d refac 2024-07-20 11:29:44 +02:00
Timothy J. Baek
fdea1afc7f refac: latex should not use \\begin and \\end as delimiters 2024-07-20 11:24:57 +02:00
Timothy J. Baek
41fecb800d enh: latex 2024-07-20 11:17:24 +02:00
Timothy Jaeryang Baek
52cf06b36c Merge pull request #4021 from KarlLee830/translate
i18n: Update Chinese Translation
2024-07-20 11:05:27 +02:00
Timothy J. Baek
ebce006974 refac: latex handling 2024-07-20 10:58:29 +02:00
Karl Lee
ff60695a0f i18n: Update Chinese translation 2024-07-20 16:45:13 +08:00
Karl Lee
3aa9685f5a i18n: Update Chinese translation 2024-07-20 16:41:33 +08:00
Justin Hayes
6cecb964a9 name 2024-07-20 03:07:50 -04:00
Justin Hayes
0216ee101c enh: ElevenLabs voice name -> ID 2024-07-20 02:56:00 -04:00
Timothy J. Baek
d3c6bfb764 enh: latex 2024-07-19 16:54:28 +02:00
Timothy J. Baek
ea6a5121b3 chore: format 2024-07-19 13:58:56 +02:00
Timothy J. Baek
d6a4fe00b3 refac: styling 2024-07-19 13:57:35 +02:00
Timothy Jaeryang Baek
36318e8a1b Merge pull request #3992 from thearyadev/feat/enter-to-select-model-indicator
feat: add indicator for enter-triggered model selection
2024-07-19 13:41:43 +02:00
Timothy J. Baek
79562a2531 fix: elevenlabs tts 2024-07-19 13:30:36 +02:00
Timothy Jaeryang Baek
d2664ab2a6 Merge pull request #3999 from ricky-davis/importDocumentMappingTags
fix: importing document mapping now adds tags
2024-07-19 12:43:53 +02:00
Timothy J. Baek
e664a429a1 feat: elevenlabs tts support 2024-07-19 10:35:05 +02:00
Timothy J. Baek
b09bd1ed34 refac: styling 2024-07-19 10:17:59 +02:00
Lukas
f83c80aaec add changelog 2024-07-19 09:08:46 +02:00
Lukas
bbc8adca94 support custom redirect url in OAuth
closes #3727 #3945
2024-07-19 09:03:41 +02:00
rdavis
20c71d127b Added content field to Document mapping import to ensure tags get re-mapped 2024-07-18 20:53:06 -05:00
Aryan Kothari
e35df904a0 feat: add indicator for enter-triggered model selection 2024-07-18 20:48:14 -04:00
Timothy Jaeryang Baek
62682a8c4c Merge pull request #3990 from josx/josx/ext
chore RAG: adding languages known extensions for erlang, elixir, haskell and jsx/tsx
2024-07-19 02:10:15 +02:00
Timothy Jaeryang Baek
253c02cc3c Merge pull request #3982 from jonathan-rohde/fix/missing-tags-add-doc-modal
test: Add tests to verify basic document list features
2024-07-19 02:10:01 +02:00
ScribblerCoder
175d1cc8f2 patch Healtcheck
- Add optional PORT
- added `-n` to jq to return expected exit code when input is empty/null
2024-07-19 03:06:15 +03:00
José Luis Di Biase
23c9122458 chore RAG: adding languages known extension for erlang, elixir, haskell and jsx/tsx
Signed-off-by: José Luis Di Biase <josx@interorganic.com.ar>
2024-07-18 17:48:39 -03:00
Jonathan Rohde
b42d2886a2 enh: add missing file 2024-07-18 15:19:30 +02:00
Jonathan Rohde
c3f90ba347 enh: add translation keys 2024-07-18 15:09:02 +02:00
Jonathan Rohde
c6eba8c0a1 enh: add e2e tests for document list 2024-07-18 15:09:02 +02:00
Timothy Jaeryang Baek
51bdb4cbea Merge pull request #3962 from thearyadev/feat/enter-to-select-model
feat: enter selects first model in list
2024-07-18 13:16:35 +02:00
Timothy Jaeryang Baek
376b2d0297 Merge pull request #3972 from jonathan-rohde/fix/missing-tags-add-doc-modal
fix: missing tags add doc modal
2024-07-18 13:15:22 +02:00
Jonathan Rohde
7e03624408 fix: send tags to upload doc handler in modal dialog 2024-07-18 12:38:23 +02:00
Aryan Kothari
133f223df6 feat: enter selects first model in list 2024-07-17 17:47:17 -04:00
Timothy J. Baek
8dc73fdbdb enh: remove /health logging 2024-07-17 22:24:34 +02:00
Timothy J. Baek
8ec3ed1830 refac: file handling 2024-07-17 22:01:39 +02:00
Timothy J. Baek
8b71ce23bb refac: styling 2024-07-17 22:01:32 +02:00
Timothy Jaeryang Baek
82079e644a Merge pull request #3952 from open-webui/dev
fix
2024-07-17 19:04:40 +02:00
Timothy J. Baek
1e7a364c68 fix 2024-07-17 19:04:18 +02:00
Timothy Jaeryang Baek
c74e7df6a0 Merge pull request #3948 from open-webui/dev
0.3.10
2024-07-17 17:51:35 +02:00
Timothy J. Baek
29d8f8d91b refac: wording 2024-07-17 17:30:05 +02:00
Timothy J. Baek
0d1553562d chore: bump 2024-07-17 17:28:53 +02:00
Timothy J. Baek
8e3312c032 doc: changelog 2024-07-17 17:28:22 +02:00
Timothy Jaeryang Baek
878d12da24 Merge pull request #3946 from open-webui/dev
fix
2024-07-17 17:21:03 +02:00
Timothy J. Baek
c1dfafcc9e fix 2024-07-17 17:18:57 +02:00
Timothy Jaeryang Baek
6668d79519 Merge pull request #3944 from open-webui/dev
refac
2024-07-17 17:11:57 +02:00
Timothy J. Baek
775a3dc359 refac 2024-07-17 17:11:50 +02:00
Timothy J. Baek
98f935b8f7 fix 2024-07-17 17:00:43 +02:00
Timothy J. Baek
86359ef374 refac 2024-07-17 16:56:11 +02:00
Timothy Jaeryang Baek
ef8fbaae28 Merge pull request #3943 from open-webui/dev
fix: web search
2024-07-17 15:40:11 +02:00
Timothy J. Baek
9e48aeca45 fix: web search 2024-07-17 15:39:50 +02:00
Timothy Jaeryang Baek
9518111ed3 Merge pull request #3940 from open-webui/dev
fix: file upload status
2024-07-17 14:22:14 +02:00
Timothy J. Baek
4fea55bac3 fix: file upload status 2024-07-17 14:21:58 +02:00
Timothy Jaeryang Baek
027dd848eb Merge pull request #3933 from open-webui/dev
fix
2024-07-17 13:16:19 +02:00
Timothy J. Baek
98928fc5f0 fix 2024-07-17 13:15:57 +02:00
Timothy Jaeryang Baek
6e843ab563 Merge pull request #3882 from open-webui/dev
0.3.9
2024-07-17 12:18:37 +02:00
Timothy J. Baek
b3a0d47a67 doc: changelog 2024-07-17 12:17:15 +02:00
Timothy J. Baek
d492d29153 fix: files overlay 2024-07-17 12:02:54 +02:00
Timothy J. Baek
ed21f9f906 refac: styling 2024-07-17 11:53:49 +02:00
Timothy J. Baek
bdadfc958c chore: format 2024-07-17 11:48:52 +02:00
Timothy J. Baek
3bbd238d7d refac: styling 2024-07-17 11:43:11 +02:00
Timothy J. Baek
4eecdbadd3 enh: files chat control 2024-07-17 11:39:37 +02:00
Timothy J. Baek
a33b0abbe0 refac: styling 2024-07-17 10:19:33 +02:00
Timothy J. Baek
3d0f457306 refac 2024-07-17 10:16:27 +02:00
Timothy Jaeryang Baek
ca5f1c1efb Merge pull request #3906 from luisbrandao/dev
i18n: pt_br
2024-07-17 09:43:38 +02:00
Luis Alexandre Deschamps Brandao
e72592eac3 i18n: pt_br 2024-07-16 11:37:09 -03:00
Timothy J. Baek
72e9cecb17 fix: allow boolean values in params 2024-07-16 15:15:06 +02:00
Timothy J. Baek
27e7494853 refac: title gen should only run once 2024-07-16 14:00:09 +02:00
Timothy J. Baek
f0a8aca0e3 fix: automatic1111 auth key should not be required 2024-07-16 10:33:05 +02:00
Timothy Jaeryang Baek
4514595811 Merge pull request #3893 from luisbrandao/dev
translation pt_br
2024-07-16 00:59:26 -07:00
Luis Alexandre Deschamps Brandao
e0bcbf0b79 translation pt_br 2024-07-16 01:44:05 -03:00
Timothy Jaeryang Baek
285725eaab Merge pull request #3888 from aleixdorca/dev
i18n: Update Catalan Translations
2024-07-15 11:25:35 -07:00
aleix
9a4770eb17 i18n: Update Catalan Translations 2024-07-15 20:01:07 +02:00
Timothy Jaeryang Baek
8a11985fce Merge pull request #3887 from OriginalSimon/dev
Added i18n keys and update of Ukrainian translation
2024-07-15 10:06:45 -07:00
SimonOriginal
731b3654d8 add i18n keys 2024-07-15 16:45:29 +02:00
SimonOriginal
da4e976d5c add Ukrainian translation for new keys 2024-07-15 16:33:38 +02:00
SimonOriginal
b74739f91b refac 9 2024-07-15 16:31:23 +02:00
SimonOriginal
6b5c452a3c refac 8 2024-07-15 16:27:06 +02:00
Timothy J. Baek
40075f69f9 refac 2024-07-15 16:25:00 +02:00
SimonOriginal
7702803e5c refac 7 2024-07-15 16:24:47 +02:00
SimonOriginal
3731f1950a refac 6 2024-07-15 16:22:10 +02:00
SimonOriginal
9ab47cf628 refac 5 2024-07-15 16:20:18 +02:00
SimonOriginal
676688aabf refac 4 2024-07-15 16:14:56 +02:00
SimonOriginal
5958d8775c refac 3 2024-07-15 16:12:55 +02:00
SimonOriginal
dfd5de9381 add i18n keys 2024-07-15 15:41:07 +02:00
SimonOriginal
ac0164c4cc add Ukrainian translation for new keys 2024-07-15 15:35:49 +02:00
SimonOriginal
9e258ea466 add i18n keys 2024-07-15 15:34:21 +02:00
SimonOriginal
0aacb95700 add Ukrainian translation for new keys 2024-07-15 15:28:33 +02:00
SimonOriginal
3668179dfe refac 2 2024-07-15 15:16:49 +02:00
SimonOriginal
fa26b8d7cf refac 2024-07-15 15:14:43 +02:00
SimonOriginal
07283ca0cf Merge branch 'dev' of https://github.com/OriginalSimon/open-webui into dev 2024-07-15 15:02:01 +02:00
SimonOriginal
917dde7edf Fix i18n string syntax 2024-07-15 15:01:34 +02:00
SimonOriginal
8102347296 Fix i18n string syntax 2024-07-15 15:01:02 +02:00
Simon
736d8586f1 Merge branch 'open-webui:dev' into dev 2024-07-15 14:54:51 +02:00
SimonOriginal
c97d4bbb50 add i18n keys 2024-07-15 14:54:20 +02:00
Timothy J. Baek
553dcd208c refac 2024-07-15 14:16:28 +02:00
SimonOriginal
e19c327279 update Ukrainian translation 2024-07-15 14:15:10 +02:00
Timothy J. Baek
6d0e4852cc chore: bump 2024-07-15 13:57:47 +02:00
Timothy J. Baek
d258523a3c refac 2024-07-15 13:09:15 +02:00
Timothy J. Baek
dbc352f01b refac: documents file handling 2024-07-15 13:05:38 +02:00
Timothy J. Baek
5e8a74ef74 refac 2024-07-15 12:20:09 +02:00
Timothy J. Baek
3cc3671e74 enh: custom icon support for actions 2024-07-15 12:15:00 +02:00
Timothy J. Baek
d4d7c3d8b6 enh: citations link 2024-07-15 11:54:56 +02:00
Timothy J. Baek
69083b6485 revert 2024-07-15 11:09:05 +02:00
Timothy Jaeryang Baek
feba1f2e3c Merge pull request #3875 from open-webui/dependabot/pip/backend/dev/pydantic-2.8.2
chore(deps): bump pydantic from 2.7.1 to 2.8.2 in /backend
2024-07-15 02:03:29 -07:00
Timothy Jaeryang Baek
bb20251b43 Merge pull request #3878 from open-webui/dependabot/pip/backend/dev/unstructured-0.14.10
chore(deps): bump unstructured from 0.14.9 to 0.14.10 in /backend
2024-07-15 02:03:21 -07:00
Timothy J. Baek
1ec2e74b07 chore: format 2024-07-15 10:58:40 +02:00
Timothy Jaeryang Baek
db6f6e62b9 Merge pull request #3876 from open-webui/dependabot/pip/backend/dev/sqlalchemy-2.0.31
chore(deps): bump sqlalchemy from 2.0.30 to 2.0.31 in /backend
2024-07-14 19:39:26 -07:00
Timothy Jaeryang Baek
a99743c1c8 Merge pull request #3877 from open-webui/dependabot/pip/backend/dev/duckduckgo-search-approx-eq-6.1.12
chore(deps): update duckduckgo-search requirement from ~=6.1.7 to ~=6.1.12 in /backend
2024-07-14 19:39:00 -07:00
Timothy Jaeryang Baek
04dd0f2b72 Merge pull request #3879 from open-webui/dependabot/pip/backend/dev/chromadb-0.5.4
chore(deps): bump chromadb from 0.5.3 to 0.5.4 in /backend
2024-07-14 19:38:40 -07:00
dependabot[bot]
b4eb630fc2 chore(deps): bump chromadb from 0.5.3 to 0.5.4 in /backend
Bumps [chromadb](https://github.com/chroma-core/chroma) from 0.5.3 to 0.5.4.
- [Release notes](https://github.com/chroma-core/chroma/releases)
- [Changelog](https://github.com/chroma-core/chroma/blob/main/RELEASE_PROCESS.md)
- [Commits](https://github.com/chroma-core/chroma/compare/0.5.3...0.5.4)

---
updated-dependencies:
- dependency-name: chromadb
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 02:34:49 +00:00
dependabot[bot]
8494b97e05 chore(deps): bump unstructured from 0.14.9 to 0.14.10 in /backend
Bumps [unstructured](https://github.com/Unstructured-IO/unstructured) from 0.14.9 to 0.14.10.
- [Release notes](https://github.com/Unstructured-IO/unstructured/releases)
- [Changelog](https://github.com/Unstructured-IO/unstructured/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Unstructured-IO/unstructured/compare/0.14.9...0.14.10)

---
updated-dependencies:
- dependency-name: unstructured
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 02:34:45 +00:00
dependabot[bot]
a98ff3c151 chore(deps): update duckduckgo-search requirement in /backend
Updates the requirements on [duckduckgo-search](https://github.com/deedy5/duckduckgo_search) to permit the latest version.
- [Release notes](https://github.com/deedy5/duckduckgo_search/releases)
- [Commits](https://github.com/deedy5/duckduckgo_search/compare/v6.1.7...v6.1.12)

---
updated-dependencies:
- dependency-name: duckduckgo-search
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 02:34:40 +00:00
dependabot[bot]
b16967a29f chore(deps): bump sqlalchemy from 2.0.30 to 2.0.31 in /backend
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.30 to 2.0.31.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

---
updated-dependencies:
- dependency-name: sqlalchemy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 02:34:36 +00:00
dependabot[bot]
73afa73286 chore(deps): bump pydantic from 2.7.1 to 2.8.2 in /backend
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.7.1 to 2.8.2.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.7.1...v2.8.2)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 02:34:23 +00:00
Timothy Jaeryang Baek
63ab526bfb Merge pull request #3815 from JerryKwan/issue3813
fix the checking logic in get_model_path
2024-07-14 13:53:44 -07:00
Timothy Jaeryang Baek
cf92909d9a Merge pull request #3859 from aleixdorca/dev
i18n: Update Catalan Translation
2024-07-14 13:52:45 -07:00
aleix
ca6a71749c i18n: Update Catalan Translation 2024-07-14 09:16:44 +02:00
Timothy Jaeryang Baek
79778fa221 Merge pull request #3850 from KarlLee830/translate
i18n: Add some missing i18n keys and update Chinese translation
2024-07-13 10:24:21 -07:00
Timothy Jaeryang Baek
6806b01327 Merge pull request #3839 from Peter-De-Ath/fix-logging
fix: logging - after db migration
2024-07-13 10:23:44 -07:00
Karl Lee
6f06577f18 i18n: Update Chinese translation 2024-07-13 21:26:44 +08:00
Karl Lee
bc4bb0b4e5 chore: format 2024-07-13 21:22:38 +08:00
Karl Lee
f40aee9d2e i18n: added some missing i18n keys 2024-07-13 21:22:16 +08:00
Karl Lee
26bf1ef621 i18n: Update Chinese translation 2024-07-13 21:14:45 +08:00
Peter De-Ath
03618fd2e0 fix: update logging configuration in env.py 2024-07-12 21:12:30 +01:00
Timothy Jaeryang Baek
fa3721bcde Merge pull request #3824 from vquie/fix_translation
i18n: fix german translation for OAUTH_PROVIDER_NAME
2024-07-12 10:16:20 -07:00
Timothy Jaeryang Baek
a049b38ab5 Merge pull request #3825 from michaelpoluektov/replace-message-event
feat: Replace message event
2024-07-12 10:15:43 -07:00
Michael Poluektov
540a669dae feat: replace message event 2024-07-12 10:41:03 +01:00
Vitali Quiering
e266504463 Fix translation placeholder in German locale
- Corrected placeholder from {{Anbieter}} to {{provider}}
2024-07-12 11:40:10 +02:00
Jerry
f07172bfe6 fix the checking logic in get_model_path
fix the checking logic in function get_model_path()
2024-07-12 14:21:37 +08:00
Timothy J. Baek
856845e5f2 refac 2024-07-11 19:05:59 -07:00
Timothy J. Baek
14c0efe300 feat: chat action integration 2024-07-11 18:47:38 -07:00
Timothy J. Baek
eb10001eb7 feat: action function 2024-07-11 18:41:00 -07:00
Timothy J. Baek
90c3d68f00 enh: input type event call 2024-07-11 17:30:24 -07:00
Timothy J. Baek
97098edfeb feat: chat valves 2024-07-11 17:18:18 -07:00
Timothy J. Baek
9f9122b6d7 enh: ChatValves 2024-07-11 16:24:59 -07:00
Timothy J. Baek
8dcb3d78dc refac 2024-07-11 15:20:56 -07:00
Timothy J. Baek
4dd77b785a fix 2024-07-11 14:12:44 -07:00
Timothy J. Baek
7d7a29cfb9 fix 2024-07-11 13:53:47 -07:00
Timothy J. Baek
f462744fc8 refac 2024-07-11 13:43:44 -07:00
Timothy J. Baek
9ab97b834a revert: reset vector db 2024-07-11 13:22:24 -07:00
Timothy J. Baek
7ba7b959a8 feat: message event 2024-07-11 11:00:42 -07:00
Timothy J. Baek
b094153af2 fix 2024-07-11 10:41:13 -07:00
Timothy J. Baek
0ef27bfc5e refac 2024-07-11 10:40:10 -07:00
Timothy Jaeryang Baek
a62b0924df Update config.json 2024-07-11 00:02:59 -05:00
Timothy Jaeryang Baek
eff736acd2 Merge pull request #3774 from open-webui/dev
fix
2024-07-10 14:45:28 -07:00
Timothy J. Baek
38cc0da990 chore; format 2024-07-10 14:43:59 -07:00
Timothy J. Baek
37ff651723 refac 2024-07-10 14:43:00 -07:00
Timothy J. Baek
fae7db89e6 chore: dockerfile 2024-07-10 14:29:39 -07:00
Timothy J. Baek
ef21397f0d chore: dockerfile 2024-07-10 14:20:02 -07:00
Timothy Jaeryang Baek
2011cbd210 Merge pull request #3773 from open-webui/dev
fix: db
2024-07-10 13:36:15 -07:00
Timothy J. Baek
ebcc5be1bf fix: db 2024-07-10 13:35:52 -07:00
Timothy Jaeryang Baek
3661dd16b8 Merge pull request #3769 from open-webui/dev
chore: requirements
2024-07-10 13:12:47 -07:00
Timothy J. Baek
2aa5d26735 chore: requirements 2024-07-10 13:10:36 -07:00
Timothy Jaeryang Baek
d50639971a Merge pull request #3768 from open-webui/dev
dev
2024-07-10 13:07:52 -07:00
Timothy J. Baek
fede1e9e3b chore: changelog 2024-07-10 13:06:27 -07:00
Timothy Jaeryang Baek
f7777f489e Merge pull request #3753 from jonathan-rohde/fix/store-default-model
fix: preselect default model from config if no setting stored
2024-07-10 12:51:17 -07:00
Timothy Jaeryang Baek
93ae6084d6 Merge pull request #3755 from simonaszilinskas/patch-4
Update translation.json
2024-07-10 12:50:40 -07:00
Simonas
3b39334bae Update translation.json
Word not necessary in Lithuanian so modified it to be an arrow which would look good design wise and would not be weird gramatically
2024-07-10 04:35:16 -05:00
Jonathan Rohde
da8ee43481 fix: use default model from config if available 2024-07-10 08:43:28 +02:00
Timothy J. Baek
a843e81aaf chore: requirements 2024-07-09 18:23:52 -07:00
Timothy Jaeryang Baek
9bcd4ce5c0 Merge pull request #3559 from open-webui/dev
0.3.8
2024-07-09 14:25:16 -07:00
Timothy J. Baek
b38abf23bb chore: bump 2024-07-09 14:24:46 -07:00
Timothy J. Baek
7f2f45e176 doc: changelog 2024-07-09 14:21:06 -07:00
Timothy Jaeryang Baek
0444497eea Merge pull request #3734 from michaelpoluektov/refactor-main
refactor: Refactor backend/main.py
2024-07-09 12:48:33 -07:00
Michael Poluektov
1d20c27553 refac: use get_task_model_id() 2024-07-09 16:08:54 +01:00
Michael Poluektov
8f23df5749 fix: outlet __event_emitter__ 2024-07-09 15:57:24 +01:00
Michael Poluektov
144581a7df refac: get_sorted_pipelines() 2024-07-09 12:51:13 +01:00
Michael Poluektov
7ffd75b991 refac: black 2024-07-09 12:32:43 +01:00
Michael Poluektov
ff474936f8 refac: remove model param 2024-07-09 12:20:28 +01:00
Michael Poluektov
d7dd901f01 refac: remove nesting 2024-07-09 12:15:09 +01:00
Michael Poluektov
e3e02e04e8 refac: backend/main.py 2024-07-09 11:51:43 +01:00
Michael Poluektov
f9e3c47d4a rebase 2024-07-09 11:13:42 +01:00
Timothy J. Baek
24ef5af2a1 fix: code block 2024-07-09 00:41:56 -07:00
Timothy J. Baek
f8e2b31756 refac: styling 2024-07-09 00:26:02 -07:00
Timothy J. Baek
a11887cee1 enh: i said darker 2024-07-08 23:30:59 -07:00
Timothy J. Baek
78a5748727 refac 2024-07-08 23:21:17 -07:00
Timothy J. Baek
666a8ea5c0 refac 2024-07-08 23:18:35 -07:00
Timothy J. Baek
0bc46b19b3 refac 2024-07-08 23:17:57 -07:00
Timothy J. Baek
3f8af02aaa fix: styling 2024-07-08 23:16:54 -07:00
Timothy J. Baek
c9f5029a9d refac 2024-07-08 23:07:23 -07:00
Timothy Jaeryang Baek
aa896ba702 Merge pull request #3725 from aleixdorca/dev
i18n: Updated Catalan Translation
2024-07-08 22:25:28 -07:00
Timothy J. Baek
c2f4eab8ed refac: splash screen 2024-07-08 22:20:00 -07:00
Timothy J. Baek
47c76ab5fe refac: styling 2024-07-08 22:02:28 -07:00
aleix
2396010d6c i18n: Updated Catalan Translation 2024-07-09 07:01:34 +02:00
Timothy J. Baek
37285b8749 fix: do not include reserved params in specs 2024-07-08 21:52:23 -07:00
Timothy J. Baek
0a08a4d2fb refac 2024-07-08 21:40:22 -07:00
Timothy J. Baek
1b7ff1c5df feat: __event_call__ support 2024-07-08 21:39:06 -07:00
Timothy J. Baek
1d979d9b75 refac 2024-07-08 21:09:43 -07:00
Timothy J. Baek
d34e9ef935 refac: styling 2024-07-08 21:09:32 -07:00
Timothy J. Baek
d752002836 refac: styling 2024-07-08 20:17:09 -07:00
Timothy J. Baek
7df35d978f refac: styling 2024-07-08 20:15:13 -07:00
Timothy J. Baek
18ea8df685 fix: theme 2024-07-08 20:13:16 -07:00
Timothy J. Baek
a23146ebd1 refac: styling 2024-07-08 20:10:00 -07:00
Timothy J. Baek
446d85474e feat: darker oled 2024-07-08 19:55:00 -07:00
Timothy J. Baek
8942d0d0e2 refac: styling 2024-07-08 19:47:30 -07:00
Timothy J. Baek
eb1e176f14 chore: format 2024-07-08 19:40:18 -07:00
Timothy J. Baek
30e2ec7544 feat: chat controls integration 2024-07-08 19:26:31 -07:00
Timothy J. Baek
9cea5f75bb refac: styling 2024-07-08 18:31:58 -07:00
Timothy J. Baek
b8d153ebb2 feat: chat controls ui 2024-07-08 16:55:12 -07:00
Timothy J. Baek
781ad70598 refac: tooltip 2024-07-08 15:26:43 -07:00
Timothy J. Baek
3598aee71e refac: styling 2024-07-08 14:32:51 -07:00
Timothy J. Baek
e8fbb8f181 refac: styling 2024-07-08 14:20:11 -07:00
Timothy J. Baek
088e7b02a9 refac: styling 2024-07-08 13:35:25 -07:00
Timothy J. Baek
4b6ee584c2 fix: alembic 2024-07-08 12:55:27 -07:00
Timothy J. Baek
d3ef3a7494 refac 2024-07-08 12:42:52 -07:00
Timothy J. Baek
68d775e1ab chore: rm print 2024-07-08 12:08:27 -07:00
Timothy J. Baek
40abddff9a fix: font 2024-07-08 12:05:16 -07:00
Timothy J. Baek
68d6e738ac fix 2024-07-08 12:01:55 -07:00
Timothy J. Baek
3ddd88dad7 chore: rm print 2024-07-08 12:00:09 -07:00
Timothy J. Baek
42742d03d7 fix: model update 2024-07-08 11:58:36 -07:00
Timothy J. Baek
87f656b029 fix: tools update 2024-07-08 11:46:37 -07:00
Timothy Jaeryang Baek
489ef9b731 Merge pull request #3705 from open-webui/dependabot/pip/backend/dev/langfuse-2.38.0
chore(deps): bump langfuse from 2.36.2 to 2.38.0 in /backend
2024-07-08 11:36:05 -07:00
Timothy Jaeryang Baek
51ae387d59 Merge pull request #3708 from open-webui/dependabot/pip/backend/dev/peewee-3.17.6
chore(deps): bump peewee from 3.17.5 to 3.17.6 in /backend
2024-07-08 11:35:55 -07:00
Timothy Jaeryang Baek
642c5e035d Merge branch 'dev' into dependabot/pip/backend/dev/peewee-3.17.6 2024-07-08 11:35:48 -07:00
Timothy Jaeryang Baek
18962104a2 Merge pull request #3707 from open-webui/dependabot/pip/backend/dev/opencv-python-headless-4.10.0.84
chore(deps): bump opencv-python-headless from 4.9.0.80 to 4.10.0.84 in /backend
2024-07-08 11:35:21 -07:00
Timothy Jaeryang Baek
9eb0f89db8 Merge pull request #3706 from open-webui/dependabot/pip/backend/dev/alembic-1.13.2
chore(deps): bump alembic from 1.13.1 to 1.13.2 in /backend
2024-07-08 11:35:07 -07:00
Timothy Jaeryang Baek
1b660453f0 Merge pull request #3704 from open-webui/dependabot/pip/backend/dev/pytest-approx-eq-8.2.2
chore(deps): update pytest requirement from ~=8.2.1 to ~=8.2.2 in /backend
2024-07-08 11:34:51 -07:00
Timothy J. Baek
3b27acc77e fix 2024-07-08 11:34:24 -07:00
Timothy J. Baek
95426fc6c9 refac: do not use subprocess 2024-07-08 11:27:10 -07:00
Timothy J. Baek
39d3dcd032 fix: db 2024-07-08 10:46:35 -07:00
Timothy Jaeryang Baek
36c0f7f273 Merge pull request #3713 from jonathan-rohde/fix/missing-commits
fix: commit document delete
2024-07-08 10:22:40 -07:00
Jonathan Rohde
3b112375ee feat(documents): commit document delete 2024-07-08 09:14:45 +02:00
Timothy Jaeryang Baek
47ec2425ee Merge pull request #3692 from cheahjs/fix/integration-test
fix: delete docker build cache in integration test
2024-07-07 23:05:15 -07:00
Timothy J. Baek
d157af2fc7 chore: format 2024-07-07 23:04:50 -07:00
Timothy J. Baek
c1d706dc5a fix: db issues 2024-07-07 23:01:15 -07:00
Timothy Jaeryang Baek
a7fb560e84 Merge pull request #3699 from Peter-De-Ath/fix-update-user-email-auth
fix auth update_email_by_id - add db.commit
2024-07-07 22:58:20 -07:00
dependabot[bot]
44bbb40551 chore(deps): bump peewee from 3.17.5 to 3.17.6 in /backend
Bumps [peewee](https://github.com/coleifer/peewee) from 3.17.5 to 3.17.6.
- [Release notes](https://github.com/coleifer/peewee/releases)
- [Changelog](https://github.com/coleifer/peewee/blob/master/CHANGELOG.md)
- [Commits](https://github.com/coleifer/peewee/compare/3.17.5...3.17.6)

---
updated-dependencies:
- dependency-name: peewee
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 03:11:22 +00:00
dependabot[bot]
d9a393eae1 chore(deps): bump opencv-python-headless in /backend
Bumps [opencv-python-headless](https://github.com/opencv/opencv-python) from 4.9.0.80 to 4.10.0.84.
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

---
updated-dependencies:
- dependency-name: opencv-python-headless
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 03:11:12 +00:00
dependabot[bot]
842a6a6ee0 chore(deps): bump alembic from 1.13.1 to 1.13.2 in /backend
Bumps [alembic](https://github.com/sqlalchemy/alembic) from 1.13.1 to 1.13.2.
- [Release notes](https://github.com/sqlalchemy/alembic/releases)
- [Changelog](https://github.com/sqlalchemy/alembic/blob/main/CHANGES)
- [Commits](https://github.com/sqlalchemy/alembic/commits)

---
updated-dependencies:
- dependency-name: alembic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 03:11:10 +00:00
dependabot[bot]
404b47274e chore(deps): bump langfuse from 2.36.2 to 2.38.0 in /backend
Bumps [langfuse](https://github.com/langfuse/langfuse) from 2.36.2 to 2.38.0.
- [Release notes](https://github.com/langfuse/langfuse/releases)
- [Commits](https://github.com/langfuse/langfuse/commits/v2.38.0)

---
updated-dependencies:
- dependency-name: langfuse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 03:11:06 +00:00
dependabot[bot]
8eb03c02da chore(deps): update pytest requirement in /backend
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.1...8.2.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 03:11:04 +00:00
Peter De-Ath
1bb2724282 fix password update in AuthsTable model 2024-07-07 22:27:26 +01:00
Peter De-Ath
f971ba0c0b fix email update in AuthsTable model 2024-07-07 22:07:12 +01:00
Timothy J. Baek
d51e866505 fix: db 2024-07-07 09:09:09 -07:00
Timothy Jaeryang Baek
068dff6aff Merge pull request #3691 from robertpiosik/replace-deafult-font-to-inter
feat: Replace default UI font, Arimo to Inter
2024-07-07 09:01:22 -07:00
Timothy Jaeryang Baek
7e6c5193d6 Merge pull request #3688 from leobenkel/no-trace-when-success
fix: Remove the tracestack when the collection already exists
2024-07-07 09:00:23 -07:00
Timothy Jaeryang Baek
a6dd62082f Merge pull request #3679 from que-nguyen/dev
Updated the missing Vietnamese translation.
2024-07-07 08:59:57 -07:00
Jun Siang Cheah
4ae0a1f3f8 fix: delete docker build cache in integration test 2024-07-07 12:06:42 +01:00
Robert Piosik
21b8072f35 Replace default UI font, Arimo to Inter 2024-07-07 11:27:04 +02:00
Leo Benkel
a73a9c7310 Remove the tracestack when the collection already exists 2024-07-06 23:20:41 +02:00
Que Nguyen
08f0a19812 Updated the missing Vietnamese translation. 2024-07-06 22:12:50 +07:00
Timothy J. Baek
c9b85bd4a2 fix: delete 2024-07-06 08:10:58 -07:00
Timothy J. Baek
0d70d7c9ac chore: allow more headroom for migration tests 2024-07-05 23:58:13 -07:00
Timothy J. Baek
e8ed48bd7a chore: disable backend tests 2024-07-05 23:54:03 -07:00
Timothy J. Baek
d5716ae751 chore: format 2024-07-05 23:48:53 -07:00
Timothy Jaeryang Baek
8f6f76682b Merge pull request #3595 from open-webui/dev-migration
feat: db migration
2024-07-05 23:47:01 -07:00
Timothy Jaeryang Baek
4e75150174 Merge pull request #3669 from open-webui/dev-migration-session
dev
2024-07-05 23:39:29 -07:00
Timothy J. Baek
1436bb7c61 enh: handle peewee migration 2024-07-05 23:38:53 -07:00
Timothy Jaeryang Baek
d60f06608e Merge pull request #3668 from open-webui/dev
dev
2024-07-05 22:29:13 -07:00
Timothy Jaeryang Baek
97a8491866 Merge pull request #3631 from ricky-davis/CustomCollapsible
feat: Custom Collapsible component
2024-07-05 21:42:54 -07:00
Timothy J. Baek
73899e1c0d refac 2024-07-05 21:37:29 -07:00
Timothy Jaeryang Baek
70efbef0c7 Merge pull request #3636 from Peter-De-Ath/add-scroll-to-settings-tabs
fix: add scroll to admin/user settings tabs
2024-07-05 21:28:17 -07:00
Timothy J. Baek
c3c15cbb7e refac 2024-07-05 21:27:59 -07:00
Timothy Jaeryang Baek
89e6044bdb Merge pull request #3657 from aleixdorca/dev
i18n: Update Catalan Translation
2024-07-05 21:21:21 -07:00
Timothy Jaeryang Baek
3928ac1905 Merge pull request #3615 from michaelpoluektov/citations-event
feat: Citations event via __event_emitter__
2024-07-05 21:20:40 -07:00
Timothy J. Baek
983fe4b2bc refac 2024-07-05 21:20:27 -07:00
aleix
8fd128ef1c i18n: Update Catalan Translation 2024-07-05 21:02:38 +02:00
Timothy Jaeryang Baek
45fae65ec1 Merge pull request #3630 from KarlLee830/translate
i18n: Update Chinese translation
2024-07-04 23:14:24 -07:00
Peter De-Ath
8381346378 enh: add sideways scrolling to settings tabs container 2024-07-05 02:05:59 +01:00
Timothy J. Baek
67c2ab006d fix: pipe custom model 2024-07-04 13:41:18 -07:00
Michael Poluektov
55b7c30028 simplify citation API 2024-07-04 18:50:09 +01:00
rdavis
ca3f8e6cb5 chore: format 2024-07-04 15:18:21 +00:00
Karl Lee
f611533764 i18n: Update Chinese translation 2024-07-04 22:57:32 +08:00
rdavis
78ba18a680 refactor: Update Collapsible component to include dynamic margin for open state 2024-07-04 14:55:48 +00:00
rdavis
db58bb5f0f refactor: Removed dependency 2024-07-04 14:15:16 +00:00
rdavis
d5c0876a0b refactor: fixed new Collapsible Component to allow passed in classes
chore: format
2024-07-04 14:02:26 +00:00
rdavis
2389c36a70 refactor: Update WebSearchResults.svelte to use new CollapsibleComponent 2024-07-04 13:55:37 +00:00
rdavis
d20601dc47 feat: Add custom Collapsible component for collapsible content 2024-07-04 13:53:28 +00:00
Michael Poluektov
0527755600 use data field 2024-07-04 12:21:09 +01:00
Timothy J. Baek
740b6f5c17 fix: pull model 2024-07-04 00:42:18 -07:00
Timothy J. Baek
9a6cbafdef fix: user valves 2024-07-04 00:37:05 -07:00
Timothy J. Baek
8b13755d56 Update auths.py 2024-07-04 00:25:45 -07:00
Timothy J. Baek
8fe2a7bb75 fix 2024-07-03 23:39:16 -07:00
Timothy J. Baek
37a5d2c06b Update db.py 2024-07-03 23:32:46 -07:00
Timothy J. Baek
864646094e refac 2024-07-03 23:32:39 -07:00
Timothy J. Baek
1b65df3acc revert 2024-07-03 21:28:51 -07:00
Timothy J. Baek
bfc53b49fd revert 2024-07-03 21:28:14 -07:00
Timothy J. Baek
f6dcffab13 fix: pinned chat delete issue 2024-07-03 21:18:40 -07:00
Timothy J. Baek
15f6f7bd15 revert: peewee migrations 2024-07-03 21:12:16 -07:00
Timothy Jaeryang Baek
0d78b63805 Merge pull request #3621 from open-webui/dev
dev
2024-07-03 20:59:14 -07:00
Timothy Jaeryang Baek
3efb8ab6ba Merge pull request #3617 from moblangeois/improve-fr-ca-translations
i18n: Improve French (FR) and French Canadian (CA) translations
2024-07-03 20:40:44 -07:00
Morgan Blangeois
f5a33ed3f9 Merge remote-tracking branch 'upstream/dev' into improve-fr-ca-translations 2024-07-04 00:56:40 +02:00
Timothy Jaeryang Baek
08c024d752 Merge pull request #3569 from Semihal/custom-openid-claims
feat: Custom claims for OAuth
2024-07-03 15:56:37 -07:00
Timothy J. Baek
c83704d6ca refac: task flag
Co-Authored-By: Michael Poluektov <78477503+michaelpoluektov@users.noreply.github.com>
2024-07-03 15:46:56 -07:00
Morgan Blangeois
f548762892 Resolve merge conflicts in French translations 2024-07-04 00:40:56 +02:00
Timothy Jaeryang Baek
d0e0aba593 Merge pull request #3611 from bannert1337/i18n-de_DE
i18n(de_DE): added translations for new entries, updated old entries
2024-07-03 15:39:37 -07:00
Michael Poluektov
4e433d9015 wip: citations via __event_emitter__ 2024-07-03 18:18:33 +01:00
Morgan Blangeois
2fedd91ed9 feat: Improve French Canadian (fr-ca) translations 2024-07-03 17:20:57 +02:00
Morgan Blangeois
3cd0b1077d i18n: Improve French translations 2024-07-03 17:09:53 +02:00
bannert
1f026a1811 i18n(de_DE): added translations for new entries, updated old entries 2024-07-03 15:16:54 +02:00
Michael Poluektov
49b4211c06 Merge branch 'dev' of https://github.com/open-webui/open-webui into dev 2024-07-03 10:07:46 +01:00
Michael Poluektov
24c7990fd4 revert not delete on pipe 2024-07-03 09:12:00 +01:00
Timothy J. Baek
4d23957035 revert: model_validate 2024-07-02 21:56:32 -07:00
Timothy J. Baek
aa88022624 fix: functions 2024-07-02 21:50:53 -07:00
Timothy J. Baek
44a9b86eec fix: functions 2024-07-02 21:46:56 -07:00
Timothy J. Baek
647aa1966f chore: format 2024-07-02 16:51:30 -07:00
Timothy Jaeryang Baek
d0e89a0318 Merge pull request #3327 from jonathan-rohde/feat/sqlalchemy-instead-of-peewee
BREAKING CHANGE/sqlalchemy instead of peewee
2024-07-02 16:40:13 -07:00
Timothy Jaeryang Baek
2c061777ca Merge pull request #3591 from michaelpoluektov/fix-banners-env
fix: fix WEBUI_BANNERS environment variable not working
2024-07-02 16:22:06 -07:00
Timothy J. Baek
f57a435576 chore: bump 2024-07-02 16:08:03 -07:00
Timothy J. Baek
cf317f8fdf fix 2024-07-02 15:20:50 -07:00
Michael Poluektov
655238dcd7 banners: generic exception 2024-07-02 14:41:59 +01:00
Michael Poluektov
16fa454558 fix banners env 2024-07-02 14:17:36 +01:00
Michael Poluektov
02f242e9e8 keep title, task, function tags for pipelines 2024-07-02 11:52:46 +01:00
Michael Poluektov
09514751b5 Update main.py 2024-07-02 10:57:56 +01:00
Michael Poluektov
afd74213cc Update main.py 2024-07-02 10:20:50 +01:00
Timothy J. Baek
e4c85921b2 fix: styling 2024-07-02 01:16:57 -07:00
Timothy J. Baek
7725a877d6 enh: get_last_user_message_item 2024-07-02 00:37:21 -07:00
Timothy J. Baek
fefa8a81d0 chore: format 2024-07-01 23:12:38 -07:00
Timothy J. Baek
05ec71beb9 enh: pinned chats support 2024-07-01 23:08:01 -07:00
Timothy J. Baek
439ab7a335 refac 2024-07-01 22:18:45 -07:00
Timothy J. Baek
044a0fbbbe enh: bool, literal valves 2024-07-01 22:14:09 -07:00
Timothy J. Baek
d97a4d687e refac 2024-07-01 21:41:44 -07:00
Timothy J. Baek
52cae406b4 feat: chat event handler 2024-07-01 20:53:24 -07:00
Timothy J. Baek
d6dbd73ec9 fix 2024-07-01 20:15:27 -07:00
Timothy J. Baek
a07051f51b feat: __event_emitter__ 2024-07-01 20:05:02 -07:00
Timothy J. Baek
e5895af7a0 refac 2024-07-01 19:37:54 -07:00
Timothy J. Baek
c7a9b5ccfa refac: chat completion middleware 2024-07-01 19:33:58 -07:00
Timothy J. Baek
b62d2a9b28 refac 2024-07-01 17:15:10 -07:00
Timothy J. Baek
a392865615 refac 2024-07-01 17:11:09 -07:00
Timothy Jaeryang Baek
3c1ea24374 Merge pull request #3582 from nickovs/tika-document-text
feat: Support Tika for document text extraction
2024-07-01 17:07:40 -07:00
Timothy J. Baek
62ba6a2413 chore: format 2024-07-01 16:52:46 -07:00
Timothy J. Baek
b875efab1f enh: validate required open webui version 2024-07-01 16:50:35 -07:00
Timothy J. Baek
bd45b7a04b fix 2024-07-01 16:11:44 -07:00
Timothy J. Baek
9c01297191 fix 2024-07-01 16:11:24 -07:00
Timothy J. Baek
6d350fb8bc revert: text split 2024-07-01 16:04:24 -07:00
Timothy J. Baek
7212b7c8aa chore: bump 2024-07-01 15:49:48 -07:00
Timothy J. Baek
9cc46629c2 refac 2024-07-01 15:43:19 -07:00
Timothy Jaeryang Baek
a03629178e Merge pull request #3568 from fishhf/dev
fix: use AIOHTTP_CLIENT_TIMEOUT timeout setting for openai streaming response
2024-07-01 14:02:13 -07:00
Timothy Jaeryang Baek
46a084d457 Merge pull request #3580 from bannert1337/i18n--optimize-de_DE
i18n: rework de_DE locale
2024-07-01 13:29:06 -07:00
Nicko van Someren
7aa35a3757 Added HTML and Typescript UI components to support configration of text extraction engine.
Updated RAG /config and /config/update endpoints to support UI updates.

Fixed .dockerignore to prevent Python venv from being copied into Docker image.
2024-07-01 12:10:59 -06:00
bannert
7f937af029 i18n(de_DE): Update German translation strings for better grammar and clarity 2024-07-01 19:01:22 +02:00
bannert
4041484a19 i18n(de-DE): Improve translation consistency and accuracy 2024-07-01 18:55:28 +02:00
bannert
8a38b0a286 feat(config): exclude .vscode/settings.json from version control 2024-07-01 18:52:19 +02:00
bannert
19d4c7f6cd Update languages.json 2024-07-01 18:42:56 +02:00
bannert
4ead3dabd8 Delete src/lib/i18n/locales/de-DE/translation-common.json 2024-07-01 18:41:56 +02:00
bannert
77f5d90be3 Delete src/lib/i18n/locales/de-DE/translation-informal.json 2024-07-01 18:41:49 +02:00
bannert
db495a1df0 refactor: Revert changes to i18n/locales/languages.json 2024-07-01 18:40:57 +02:00
bannert
8634140306 refactor: Remove changes to i18n/index.ts 2024-07-01 18:38:52 +02:00
bannert
586de1f5ba feat(i18n): unify German translations and remove formal/informal versions 2024-07-01 18:31:13 +02:00
Jonathan Rohde
2aecd7d0b9 Merge branch 'refs/heads/dev' into feat/sqlalchemy-instead-of-peewee
# Conflicts:
#	backend/requirements.txt
2024-07-01 10:37:56 +02:00
Sergey Mihaylin
a94c7e5c09 fix lint 2024-07-01 10:36:21 +03:00
Sergey Mihaylin
e475f025b7 fix: merge request fail (remove picture_claim) 2024-07-01 10:25:25 +03:00
Sergey Mihaylin
6e934c2d17 Merge branch 'refs/heads/main' into custom-openid-claims
# Conflicts:
#	backend/main.py
2024-07-01 10:08:38 +03:00
Fish Lung
f89fa061e8 fix: use AIOHTTP_CLIENT_TIMEOUT timeout setting for openai streaming response 2024-07-01 14:29:26 +08:00
Timothy Jaeryang Baek
f3c1ff9efc Merge pull request #3564 from wanderingmeow/fix-regexp-safari-before-16.4
fix: RegExp "invalid group specifier name" exception on Safari < 16.4
2024-06-30 22:40:53 -07:00
Timothy J. Baek
4547afe0b9 chore: bump 2024-06-30 22:29:03 -07:00
Timothy J. Baek
7955c9ba3b refac 2024-06-30 22:28:43 -07:00
Timothy Jaeryang Baek
c52e16a844 Merge pull request #3562 from open-webui/dependabot/pip/backend/dev/sentence-transformers-3.0.1
chore(deps): bump sentence-transformers from 2.7.0 to 3.0.1 in /backend
2024-06-30 19:58:38 -07:00
Timothy Jaeryang Baek
c676a78cd7 Merge pull request #3543 from open-webui/dependabot/pip/backend/dev/openpyxl-3.1.5
chore(deps): bump openpyxl from 3.1.2 to 3.1.5 in /backend
2024-06-30 19:57:20 -07:00
Timothy Jaeryang Baek
61b2bcae47 Merge pull request #3563 from open-webui/dependabot/pip/backend/dev/langchain-community-0.2.6
chore(deps): bump langchain-community from 0.2.0 to 0.2.6 in /backend
2024-06-30 19:57:10 -07:00
Timothy Jaeryang Baek
ee59cbc634 Merge pull request #3561 from open-webui/dependabot/pip/backend/dev/requests-2.32.3
chore(deps): bump requests from 2.32.2 to 2.32.3 in /backend
2024-06-30 19:56:53 -07:00
Timothy Jaeryang Baek
0c552b4730 Merge pull request #3560 from open-webui/dependabot/pip/backend/dev/langfuse-2.36.2
chore(deps): bump langfuse from 2.33.0 to 2.36.2 in /backend
2024-06-30 19:56:45 -07:00
WanderingMeow
de3d49000e fix: RegExp "invalid group specifier name" exception on Safari < 16.4 (#3306, #3371) 2024-07-01 10:42:55 +08:00
dependabot[bot]
8c7fb0312c chore(deps): bump langchain-community from 0.2.0 to 0.2.6 in /backend
Bumps [langchain-community](https://github.com/langchain-ai/langchain) from 0.2.0 to 0.2.6.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-community==0.2.0...langchain-community==0.2.6)

---
updated-dependencies:
- dependency-name: langchain-community
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 02:30:30 +00:00
dependabot[bot]
0ee984b444 chore(deps): bump sentence-transformers from 2.7.0 to 3.0.1 in /backend
Bumps [sentence-transformers](https://github.com/UKPLab/sentence-transformers) from 2.7.0 to 3.0.1.
- [Release notes](https://github.com/UKPLab/sentence-transformers/releases)
- [Commits](https://github.com/UKPLab/sentence-transformers/compare/v2.7.0...v3.0.1)

---
updated-dependencies:
- dependency-name: sentence-transformers
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 02:30:25 +00:00
dependabot[bot]
2fadc0c68f chore(deps): bump requests from 2.32.2 to 2.32.3 in /backend
Bumps [requests](https://github.com/psf/requests) from 2.32.2 to 2.32.3.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.2...v2.32.3)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 02:30:22 +00:00
dependabot[bot]
3f31bb0975 chore(deps): bump langfuse from 2.33.0 to 2.36.2 in /backend
Bumps [langfuse](https://github.com/langfuse/langfuse) from 2.33.0 to 2.36.2.
- [Release notes](https://github.com/langfuse/langfuse/releases)
- [Commits](https://github.com/langfuse/langfuse/commits)

---
updated-dependencies:
- dependency-name: langfuse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 02:30:20 +00:00
Timothy Jaeryang Baek
5d1573fd1b Merge pull request #3557 from Naufal05R/patch-1
i18n: Update Indonesian translation
2024-06-30 17:46:56 -07:00
Timothy Jaeryang Baek
5c6e30cb5d Merge pull request #3558 from cheahjs/refac/reduce-startup-mem-usage
refac: reduce startup memory usage
2024-06-30 17:46:27 -07:00
Timothy J. Baek
a55d6e6077 fix: compare message 2024-06-30 17:45:28 -07:00
Jun Siang Cheah
a48ac6a209 refac: lazily load sentence_transformers to reduce start up memory usage 2024-07-01 08:13:56 +08:00
Jun Siang Cheah
17c684369e refac: lazily load faster_whisper to reduce start up memory usage 2024-07-01 08:13:02 +08:00
Naufal Rabbani
11210fb6e4 i18n: Update Indonesian translation 2024-07-01 06:48:57 +07:00
Timothy Jaeryang Baek
824966ad4a Merge pull request #3555 from open-webui/dev
fix: default locale
2024-06-30 14:53:27 -07:00
Timothy J. Baek
f77073410e refac 2024-06-30 14:52:18 -07:00
Nicko van Someren
9cf622d981 Added support for using Apache Tika as a document loader.
Added persistent configuration options to configure use and location of Tika service.

Updated backend.apps.rag.main:get_loader() to make use of Tika document loader.
2024-06-30 15:49:15 -06:00
Timothy J. Baek
d9a229b1ec fix: default locale 2024-06-30 14:48:05 -07:00
Timothy Jaeryang Baek
7bc88eb00d Merge pull request #3549 from open-webui/dev
refac: ollama non streaming response
2024-06-30 01:40:26 -07:00
Timothy J. Baek
f6efda9e2f refac: ollama non stream response 2024-06-30 01:30:19 -07:00
Timothy Jaeryang Baek
bb53282cb0 Merge pull request #3542 from open-webui/dependabot/pip/backend/dev/duckduckgo-search-approx-eq-6.1.7
chore(deps): update duckduckgo-search requirement from ~=6.1.5 to ~=6.1.7 in /backend
2024-06-29 20:44:19 -07:00
Timothy Jaeryang Baek
c933865172 Merge pull request #3541 from open-webui/dependabot/pip/backend/dev/langchain-chroma-0.1.2
chore(deps): bump langchain-chroma from 0.1.1 to 0.1.2 in /backend
2024-06-29 20:43:56 -07:00
Timothy Jaeryang Baek
ce990d3859 Merge pull request #3539 from open-webui/dependabot/pip/backend/dev/chromadb-0.5.3
chore(deps): bump chromadb from 0.5.0 to 0.5.3 in /backend
2024-06-29 20:43:46 -07:00
Timothy Jaeryang Baek
315c8b2af3 Merge pull request #3540 from open-webui/dependabot/pip/backend/dev/python-socketio-5.11.3
chore(deps): bump python-socketio from 5.11.2 to 5.11.3 in /backend
2024-06-29 20:43:31 -07:00
Timothy Jaeryang Baek
66182bac75 Merge pull request #3546 from open-webui/dev
refac: language detection
2024-06-29 20:41:32 -07:00
Timothy J. Baek
5ee7da54a1 refac: language detection 2024-06-29 20:41:06 -07:00
Timothy J. Baek
4b0c422ec5 chore: format 2024-06-29 20:33:10 -07:00
dependabot[bot]
5dacd41278 chore(deps): bump openpyxl from 3.1.2 to 3.1.5 in /backend
Bumps [openpyxl](https://openpyxl.readthedocs.io) from 3.1.2 to 3.1.5.

---
updated-dependencies:
- dependency-name: openpyxl
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-30 03:27:46 +00:00
dependabot[bot]
052c582930 chore(deps): update duckduckgo-search requirement in /backend
Updates the requirements on [duckduckgo-search](https://github.com/deedy5/duckduckgo_search) to permit the latest version.
- [Release notes](https://github.com/deedy5/duckduckgo_search/releases)
- [Commits](https://github.com/deedy5/duckduckgo_search/compare/v6.1.5...v6.1.7)

---
updated-dependencies:
- dependency-name: duckduckgo-search
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-30 03:27:43 +00:00
dependabot[bot]
3c0ce5d1b0 chore(deps): bump langchain-chroma from 0.1.1 to 0.1.2 in /backend
Bumps [langchain-chroma](https://github.com/langchain-ai/langchain) from 0.1.1 to 0.1.2.
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](https://github.com/langchain-ai/langchain/compare/langchain-chroma==0.1.1...langchain-chroma==0.1.2)

---
updated-dependencies:
- dependency-name: langchain-chroma
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-30 03:27:39 +00:00
dependabot[bot]
9d1aa4aebe chore(deps): bump python-socketio from 5.11.2 to 5.11.3 in /backend
Bumps [python-socketio](https://github.com/miguelgrinberg/python-socketio) from 5.11.2 to 5.11.3.
- [Release notes](https://github.com/miguelgrinberg/python-socketio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-socketio/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/python-socketio/compare/v5.11.2...v5.11.3)

---
updated-dependencies:
- dependency-name: python-socketio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-30 03:27:34 +00:00
dependabot[bot]
e540f8a4e4 chore(deps): bump chromadb from 0.5.0 to 0.5.3 in /backend
Bumps [chromadb](https://github.com/chroma-core/chroma) from 0.5.0 to 0.5.3.
- [Release notes](https://github.com/chroma-core/chroma/releases)
- [Changelog](https://github.com/chroma-core/chroma/blob/main/RELEASE_PROCESS.md)
- [Commits](https://github.com/chroma-core/chroma/compare/0.5.0...0.5.3)

---
updated-dependencies:
- dependency-name: chromadb
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-30 03:27:27 +00:00
Timothy Jaeryang Baek
4900ac5136 Merge pull request #3536 from open-webui/dev
0.3.7
2024-06-29 20:26:59 -07:00
Timothy J. Baek
58d8dd94fc chore: bump 2024-06-29 20:26:51 -07:00
Timothy J. Baek
df8d1dacc4 refac: browser language detection 2024-06-29 20:04:04 -07:00
Timothy Jaeryang Baek
56137acd94 Merge pull request #3507 from open-webui/dependabot/pip/authlib-1.3.1
chore(deps): bump authlib from 1.3.0 to 1.3.1
2024-06-29 19:52:43 -07:00
Timothy J. Baek
41c55fbb81 enh: boilerplate 2024-06-29 19:49:16 -07:00
Timothy J. Baek
16454c0de5 chore: format 2024-06-29 19:47:23 -07:00
Timothy J. Baek
d0567832cc fix 2024-06-29 19:40:54 -07:00
bannert
9c2313a1bd feat(i18n): improve init function with cleaner code and nullish coalescing operator
- Use object destructuring for clearer variable assignment.
   - Utilize the nullish coalescing operator to simplify ternary expressions.
   - Refactored the import statement to remove duplication.
2024-06-30 02:44:03 +02:00
Timothy Jaeryang Baek
61972ca97d Merge pull request #3519 from Naufal05R/main
i18n: Add Indonesian translate
2024-06-29 13:17:12 -07:00
Timothy Jaeryang Baek
73135b6e51 Merge pull request #3511 from Peter-De-Ath/ollama-chat-no-stream
fix: isInstance of streamingResponse but content-type is application/json
2024-06-29 13:16:32 -07:00
Timothy Jaeryang Baek
27709c835c Merge pull request #3497 from aguvener/dev
i18n: tr_TR translation updated with the latest changes
2024-06-29 13:15:59 -07:00
Timothy Jaeryang Baek
d3a67b44cd Merge pull request #3499 from Semihal/fix-oauth-openid
fix: First OIDC account is not admin
2024-06-29 13:15:42 -07:00
Timothy Jaeryang Baek
58398b6eeb Merge pull request #3514 from KarlLee830/translate
i18n: Update Chinese translation
2024-06-29 13:14:35 -07:00
Timothy Jaeryang Baek
98ae064cd0 Merge pull request #3525 from aleixdorca/dev
i18n: Updated Catalan Translations
2024-06-29 13:14:23 -07:00
Aleix Dorca
776082dc87 i18n: Updated Catalan Translation 2024-06-29 20:34:31 +02:00
aleix
6e03a1c168 i18n: Updated Catalan Translation 2024-06-29 17:25:11 +02:00
aleix
45cb1c0fcb Updated Catalan Translation 2024-06-29 17:21:03 +02:00
Naufal Rabbani
5b848dcf54 added indonesian language 2024-06-29 16:25:42 +07:00
Naufal Rabbani
2ef899220a added indonesian language 2024-06-29 16:18:45 +07:00
Karl Lee
8ab4b7ab47 i18n: Update Chinese translation 2024-06-29 04:22:04 +08:00
Peter De-Ath
269db0748a fix: isInstance of streamingResponse but content-type is application/json 2024-06-28 20:32:07 +01:00
bannert
6ffa189814 i18n: split locale for German formal and informal
translation-common.json is the base
translation-formal.json and translation-informal.json extend the base
2024-06-28 20:03:36 +02:00
bannert
24f84a6069 feat(i18n): fixed a word in German translation 2024-06-28 19:19:45 +02:00
bannert
c138445944 feat(i18n): update and optimize de_DE 2024-06-28 19:02:50 +02:00
dependabot[bot]
4d3e1ffbe6 chore(deps): bump authlib from 1.3.0 to 1.3.1
Bumps [authlib](https://github.com/lepture/authlib) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/lepture/authlib/releases)
- [Changelog](https://github.com/lepture/authlib/blob/master/docs/changelog.rst)
- [Commits](https://github.com/lepture/authlib/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: authlib
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-28 16:53:45 +00:00
Sergey Mihaylin
9f32e9ef60 fix username claim 2024-06-28 17:08:32 +03:00
Sergey Mihaylin
0c3f9a16e3 custom env for set custom claims for openid 2024-06-28 16:31:40 +03:00
Sergey Mihaylin
7d10dacad6 Fix: set jwt_token to cookie (instead of token from OIDC) 2024-06-28 16:20:57 +03:00
Sergey Mihaylin
57c330576d Fix: admin role for OIDC signup for first user 2024-06-28 16:20:34 +03:00
aguvener
3cc5da835c Update translation.json for minor change 2024-06-28 13:18:44 +03:00
aguvener
9111970580 Update translation.json 2024-06-28 13:06:50 +03:00
Jonathan Rohde
5391f4c1f7 feat(sqlalchemy): add new column 2024-06-28 09:21:07 +02:00
Jonathan Rohde
df47c496d3 Merge branch 'refs/heads/dev' into feat/sqlalchemy-instead-of-peewee
# Conflicts:
#	backend/apps/webui/models/functions.py
#	backend/apps/webui/routers/chats.py
2024-06-28 09:19:56 +02:00
Timothy Jaeryang Baek
24b638fcde Merge pull request #3486 from open-webui/dev
fix: trusted sign in
2024-06-27 21:44:54 -07:00
Timothy J. Baek
cd9170ed24 fix: trusted sign in 2024-06-27 21:44:35 -07:00
Timothy Jaeryang Baek
f7da94ff85 Merge pull request #3485 from open-webui/dev
fix: WEBUI_AUTH
2024-06-27 21:43:51 -07:00
Timothy J. Baek
feba50f68c fix: WEBUI_AUTH 2024-06-27 21:43:19 -07:00
Timothy Jaeryang Baek
b0724811df Merge pull request #3477 from open-webui/dev
fix: changelog
2024-06-27 13:38:44 -07:00
Timothy J. Baek
1dd54ced41 fix: changelog 2024-06-27 13:38:28 -07:00
Timothy Jaeryang Baek
1eebb85f48 Merge pull request #3323 from open-webui/dev
0.3.6
2024-06-27 13:36:02 -07:00
Timothy J. Baek
b224ba0030 refac: styling 2024-06-27 13:15:54 -07:00
Timothy J. Baek
46ae25826d chore: format 2024-06-27 13:13:16 -07:00
Timothy J. Baek
c954f1b4de refac 2024-06-27 13:12:37 -07:00
Timothy J. Baek
edbd07f893 feat: global filter 2024-06-27 13:04:12 -07:00
Timothy J. Baek
c8c85ba7fc refac 2024-06-27 12:16:55 -07:00
Timothy J. Baek
c262d9ad4f doc: changelog 2024-06-27 11:30:30 -07:00
Timothy J. Baek
3f5f410453 refac 2024-06-27 11:29:59 -07:00
Timothy J. Baek
3c7f45ced4 fix 2024-06-27 11:12:07 -07:00
Timothy J. Baek
c07da8d1f3 chore: format 2024-06-27 10:56:00 -07:00
Timothy Jaeryang Baek
d3b9f03bdb Merge pull request #3470 from djismgaming/dev
**i18n** Spanish translation updates
2024-06-27 10:51:21 -07:00
Timothy Jaeryang Baek
433abe5a25 Merge pull request #3471 from KarlLee830/translate 2024-06-27 10:37:32 -07:00
Karl Lee
b59684328d i18n: Update Chinese translation 2024-06-27 20:59:43 +08:00
Ismael
850d4aac70 additional Spanish strings updated 2024-06-27 07:33:38 -04:00
Ismael
bae87ec4ae Update translation.json
Spanish translation updates
2024-06-27 07:08:03 -04:00
Timothy J. Baek
a5138b7621 doc: changelog 2024-06-27 03:24:16 -07:00
Timothy J. Baek
4e6d165d00 refac 2024-06-27 00:43:31 -07:00
Jonathan Rohde
827b1e58e9 feat(sqlalchemy): execute tests in github actions 2024-06-27 07:48:31 +02:00
Jonathan Rohde
23e4d9daff feat(sqlalchemy): formatting 2024-06-27 07:48:26 +02:00
Jonathan Rohde
d4b6b7c4e8 feat(sqlalchemy): reverted not needed api change 2024-06-27 07:48:08 +02:00
Jonathan Rohde
642c352c69 feat(sqlalchemy): rebase 2024-06-27 07:48:08 +02:00
Jonathan Rohde
d88bd51e3c feat(sqlalchemy): format backend 2024-06-27 07:48:08 +02:00
Jonathan Rohde
2fb27adbf6 feat(sqlalchemy): add missing file 2024-06-27 07:48:08 +02:00
Jonathan Rohde
8f939cf55b feat(sqlalchemy): some fixes 2024-06-27 07:48:08 +02:00
Jonathan Rohde
a9b148791d feat(sqlalchemy): fix wrong column types 2024-06-27 07:48:08 +02:00
Jonathan Rohde
da403f3e3c feat(sqlalchemy): use session factory instead of context manager 2024-06-27 07:48:08 +02:00
Jonathan Rohde
eb01e8d275 feat(sqlalchemy): use scoped session 2024-06-27 07:48:08 +02:00
Jonathan Rohde
c134eab27a feat(sqlalchemy): format backend 2024-06-27 07:48:08 +02:00
Jonathan Rohde
320e658595 feat(sqlalchemy): cleanup fixes 2024-06-27 07:48:08 +02:00
Jonathan Rohde
070d9083d5 feat(sqlalchemy): use subprocess to do migrations 2024-06-27 07:48:08 +02:00
Jonathan Rohde
bee835cb65 feat(sqlalchemy): remove session reference from router 2024-06-27 07:48:08 +02:00
Jonathan Rohde
df09d0830a feat(sqlalchemy): Replace peewee with sqlalchemy 2024-06-27 07:48:08 +02:00
Timothy J. Baek
8dac2a2140 refac 2024-06-26 10:22:31 -07:00
Timothy Jaeryang Baek
aad23af3a3 Merge pull request #3456 from SimonOriginal/dev
i18n: Update of the Ukrainian translation
2024-06-26 09:47:26 -07:00
SimonOriginal
755850e453 add translation for new keys 2024-06-26 17:17:48 +02:00
Timothy J. Baek
581e7800fa fix 2024-06-26 00:36:35 -07:00
Timothy J. Baek
0ec4d56593 fix 2024-06-26 00:23:24 -07:00
Timothy J. Baek
0e7db89117 feat: import/export community 2024-06-26 00:22:26 -07:00
Timothy J. Baek
bc5e39d31b chore: format 2024-06-25 16:31:33 -07:00
Timothy J. Baek
6cd47a3c9b refac 2024-06-25 16:30:49 -07:00
Timothy Jaeryang Baek
70c985feec Merge pull request #3447 from ben-z/stt-model-configurable
fix: Make STT model configurable
2024-06-25 15:26:57 -07:00
Ben Zhang
044bd00386 Make STT model configurable 2024-06-25 21:46:12 +00:00
Timothy Jaeryang Baek
b0ed8ded48 Merge pull request #3437 from silentoplayz/patch-1
feat: case insensitive prompt/models selection chat input
2024-06-25 12:55:08 -07:00
Timothy J. Baek
8bdbd2f9fb fix: rm conversationMode 2024-06-25 12:27:00 -07:00
silentoplayz
ef619321ce Update Models.svelte
feat: case-insensitive @model-name search
2024-06-25 18:22:38 +00:00
silentoplayz
01ad197973 Update PromptCommands.svelte
feat: case-insensitive prompt search
2024-06-25 18:19:52 +00:00
Timothy J. Baek
a92c5381fb chore: format 2024-06-25 08:51:52 -07:00
Timothy Jaeryang Baek
3750e69e09 Merge pull request #3418 from cheahjs/feat/hide-tokens-in-ui
feat: hide all API keys by default in admin settings
2024-06-25 08:40:18 -07:00
Timothy Jaeryang Baek
771ac86163 Merge pull request #3417 from ricky-davis/addDeleteConfirmationToolsFunctions
feat: Added delete confirmation dialogs for Prompts, Tools, and Functions.
2024-06-25 08:18:36 -07:00
Timothy J. Baek
36e88d479b chore: format 2024-06-25 08:01:05 -07:00
Timothy J. Baek
c147147001 chore: format 2024-06-25 08:00:32 -07:00
rdavis
4d5e161a3e Updated Functions and Tools to use existing selected* Variable
Applied formatting
2024-06-25 08:28:43 -05:00
Jun Siang Cheah
f8f6943128 refac: use new SensitiveInput component 2024-06-25 20:15:29 +08:00
Jun Siang Cheah
d5b91fb084 feat: hide all API keys by default in admin settings 2024-06-25 19:53:22 +08:00
rdavis
263d4bf496 Added delete confirmation dialogs for Prompts, Tools, and Functions. 2024-06-24 22:50:35 -05:00
Timothy Jaeryang Baek
16a8eebd8d Merge pull request #3328 from FuturePrayer/AUTOMATIC1111_api_auth_support
feat: Supports making requests to the Automatic1111 backend when running with the --api-auth parameter
2024-06-24 19:40:55 -07:00
Timothy Jaeryang Baek
d17dc59246 Merge pull request #2574 from cheahjs/feat/oauth
feat: experimental SSO support for Google, Microsoft, and OIDC
2024-06-24 19:05:58 -07:00
Timothy Jaeryang Baek
09082a070b Merge pull request #3407 from jonathan-rohde/feat/case-insensitive-tag-selection
feat/case insensitive tag selection
2024-06-24 18:52:54 -07:00
Timothy J. Baek
a40d0ec3cb chore: requirements 2024-06-24 17:53:07 -07:00
Timothy J. Baek
bf4dcc10af fix: modal esc 2024-06-24 17:39:43 -07:00
Timothy J. Baek
503d16f49c chore: 333
Co-Authored-By: Jannes Höke <3945220+jh0ker@users.noreply.github.com>
2024-06-24 16:06:15 -07:00
Timothy J. Baek
9504c9c9b4 fix 2024-06-24 15:32:49 -07:00
Timothy J. Baek
284ab648b6 fix 2024-06-24 15:21:42 -07:00
Timothy J. Baek
0f4f01cee9 fix 2024-06-24 14:00:48 -07:00
Timothy J. Baek
68b3cce0fd fix: query memory 2024-06-24 14:00:08 -07:00
Timothy J. Baek
d361404a60 refac 2024-06-24 13:33:03 -07:00
Timothy J. Baek
465c3a9987 refac: playground styling 2024-06-24 13:11:49 -07:00
Timothy J. Baek
4c9fa6cf37 enh: pipe handling 2024-06-24 12:56:41 -07:00
Timothy J. Baek
837944dcc5 fix 2024-06-24 12:26:07 -07:00
Timothy J. Baek
9fb30d4787 fix 2024-06-24 12:23:12 -07:00
Timothy J. Baek
345b3491a7 fix: i18n 2024-06-24 12:21:19 -07:00
Timothy Jaeryang Baek
b4c9e46357 Merge pull request #3408 from SimonOriginal/dev
Added i18n keys and update of Ukrainian translation
2024-06-24 11:39:04 -07:00
Timothy J. Baek
f6082579c9 fix: wakelock 2024-06-24 11:29:21 -07:00
Timothy J. Baek
1c4e7f0324 refac 2024-06-24 11:17:18 -07:00
Simon
920fc29bdd Merge branch 'dev' into dev 2024-06-24 19:50:35 +02:00
SimonOriginal
d9c2b6e890 Add translation 2024-06-24 19:49:29 +02:00
Timothy J. Baek
74a4f642fd refac: valves save 2024-06-24 10:47:40 -07:00
SimonOriginal
e0e9fcaa24 Add keys i18n 2024-06-24 19:38:26 +02:00
Timothy J. Baek
6bad71adca fix 2024-06-24 10:37:57 -07:00
SimonOriginal
fbbffc4386 Add key adn translation 2024-06-24 19:04:31 +02:00
SimonOriginal
8dc9735873 start parser i18n 2024-06-24 18:24:21 +02:00
SimonOriginal
5e9e1108a3 fix errors 2024-06-24 18:21:29 +02:00
SimonOriginal
855b5508d0 start parser 2024-06-24 18:14:19 +02:00
SimonOriginal
2ece4e7cbb Add Ukrainian translation for keys + formatin 2024-06-24 18:12:39 +02:00
SimonOriginal
665f87e84a add toasts keys i18n 2024-06-24 18:09:45 +02:00
SimonOriginal
3d1de6144e Add Ukrainian translation for keys 2024-06-24 17:25:23 +02:00
SimonOriginal
9c81d84e16 Add toasts i18n key 2024-06-24 17:18:39 +02:00
Jonathan Rohde
c7855b3b9d feat(chat): formatting 2024-06-24 16:47:02 +02:00
Jonathan Rohde
09e95b8d3c feat(chat): ignore upper/lower case to select document/tag/collection 2024-06-24 16:44:44 +02:00
SimonOriginal
85b3b81617 fix key Database 2024-06-24 16:23:08 +02:00
SimonOriginal
06a337061b Add keys i18n 2024-06-24 16:19:56 +02:00
SimonOriginal
a8198d7a7f Update of Ukrainian translation 2024-06-24 16:07:51 +02:00
Jun Siang Cheah
79f8620b34 fix: format 2024-06-24 18:50:55 +08:00
Jun Siang Cheah
ca8c098f62 refac: update migrations to match dev 2024-06-24 18:48:28 +08:00
Jun Siang Cheah
f26d80dcae Merge remote-tracking branch 'upstream/dev' into feat/oauth 2024-06-24 18:46:48 +08:00
Timothy J. Baek
f54a66b86b chore: format 2024-06-23 23:31:56 -07:00
Timothy Jaeryang Baek
655ba475cc Merge pull request #3402 from josephrocca/patch-1
fix: scrollToBottom button container obstructing clicks on buttons beneath it
2024-06-23 23:30:33 -07:00
Timothy J. Baek
a82154de3f refac 2024-06-23 23:15:24 -07:00
josephrocca
82b44740db Fix scrollToBottom button container obstructing clicks on buttons beneath it 2024-06-24 14:10:32 +08:00
Timothy J. Baek
f33ca4c9a5 refac 2024-06-23 23:10:26 -07:00
Timothy J. Baek
bc73cb1390 enh: iframe message event listener 2024-06-23 21:48:06 -07:00
Timothy J. Baek
37a052327a chore: format 2024-06-23 21:14:31 -07:00
Timothy J. Baek
51adb1c04a enh: frontmatter version 2024-06-23 21:07:22 -07:00
Timothy J. Baek
9788633ce1 refac: wording 2024-06-23 21:01:07 -07:00
Timothy J. Baek
0b8f5c2232 enh: manifest modal 2024-06-23 21:00:34 -07:00
Timothy J. Baek
be2340d4ef refac: styling 2024-06-23 20:40:12 -07:00
Timothy J. Baek
5c0015cd66 fix: frontmatter 2024-06-23 20:37:41 -07:00
Timothy J. Baek
abf212c28f enh: tools & functions frontmatter 2024-06-23 20:31:40 -07:00
Timothy J. Baek
8b99870189 enh: filter function priority valve support 2024-06-23 20:11:08 -07:00
Timothy J. Baek
f4a2ae5eac enh: list valve 2024-06-23 19:49:48 -07:00
Timothy J. Baek
0250f69da0 fix: valves 2024-06-23 19:48:16 -07:00
Jun Siang Cheah
99e7b328a4 refac: add better logging for oauth errors 2024-06-24 10:43:53 +08:00
Timothy J. Baek
5f2d37dce5 fix: valves 2024-06-23 19:37:35 -07:00
Timothy J. Baek
2eb15ea1fc feat: SAFE_MODE 2024-06-23 19:28:33 -07:00
Timothy J. Baek
ab700a16be refac: all valves input should be required 2024-06-23 19:20:09 -07:00
Timothy J. Baek
0cf936f9e8 refac 2024-06-23 19:18:13 -07:00
Timothy J. Baek
26e735618e fix: tools valves 2024-06-23 19:10:52 -07:00
Timothy J. Baek
db9e5e008f refac: styling 2024-06-23 19:09:53 -07:00
Timothy Jaeryang Baek
65dbf9ba3f Merge pull request #3400 from open-webui/valves
feat: tools & functions valves
2024-06-23 19:07:32 -07:00
Timothy J. Baek
dc25f44d31 fix: handle default 2024-06-23 19:05:56 -07:00
Timothy J. Baek
627705a347 feat: valves 2024-06-23 19:02:27 -07:00
Timothy J. Baek
3a629ffe00 feat: global filter 2024-06-23 18:39:27 -07:00
Timothy J. Baek
d8c112d8b0 feat: function toggle support 2024-06-23 18:34:42 -07:00
Timothy J. Baek
3034f3d310 refac: styling 2024-06-23 18:06:41 -07:00
Timothy J. Baek
120b1857b2 enh: valves 2024-06-23 18:05:33 -07:00
Timothy J. Baek
58e69230a9 refac: styling 2024-06-23 17:44:31 -07:00
Timothy J. Baek
fc2001da83 refac: styling 2024-06-23 17:41:59 -07:00
Timothy J. Baek
5d7de927e5 enh: valve field desc support 2024-06-23 17:34:25 -07:00
Timothy J. Baek
7cd4a3cd1a chore: requirements 2024-06-23 17:22:11 -07:00
Timothy J. Baek
e52ed258f0 refac: styling 2024-06-23 17:18:36 -07:00
Timothy J. Baek
9c57402269 chore: format 2024-06-23 16:04:33 -07:00
Timothy J. Baek
7a218d77b7 refac: workspace 2024-06-23 16:03:21 -07:00
Timothy J. Baek
ecf1d89a8b refac: prompts ui 2024-06-23 15:57:16 -07:00
Timothy J. Baek
57455f084b refac: functions ui 2024-06-23 15:51:19 -07:00
Timothy J. Baek
44e3d384d5 refac: tools ui 2024-06-23 15:45:17 -07:00
Timothy J. Baek
8e2c377a21 refac: extractSentences 2024-06-22 16:33:20 -07:00
Timothy J. Baek
6ee94c5e97 chore: format 2024-06-22 16:15:19 -07:00
Timothy J. Baek
6e084b4a73 enh: voice call skip code block & expression 2024-06-22 16:13:13 -07:00
Timothy Jaeryang Baek
fd96c9c68d Merge pull request #3380 from Yash-1511/main
feat: add jina_search as new websearch provider
2024-06-22 15:19:38 -07:00
Timothy J. Baek
60e5adc70e enh: files api allow filename 2024-06-22 14:49:00 -07:00
Timothy J. Baek
de367e488d fix 2024-06-22 14:08:23 -07:00
Timothy J. Baek
df71d7c63b fix 2024-06-22 14:07:11 -07:00
Timothy J. Baek
5b64c28f33 refac 2024-06-22 14:06:19 -07:00
Timothy J. Baek
03bb4bcda6 refac: tool specs 2024-06-22 13:47:57 -07:00
Timothy J. Baek
2d795cffe0 refac: styling 2024-06-22 13:41:27 -07:00
Timothy J. Baek
bcefa71b03 refac: styling 2024-06-22 13:39:17 -07:00
Timothy J. Baek
b441511359 enh: wake lock 2024-06-22 13:35:18 -07:00
Timothy J. Baek
3af8c5b03d refac: wording 2024-06-22 13:22:26 -07:00
Timothy J. Baek
d0f34baaa3 feat: voice interruption toggle 2024-06-22 13:21:36 -07:00
Timothy J. Baek
98c18b3032 fix: web search 2024-06-22 13:13:46 -07:00
Timothy J. Baek
c1971fd8d7 refac: show default instead of none 2024-06-22 13:01:26 -07:00
Timothy J. Baek
cf6447eb2a feat: function exception handler 2024-06-22 12:43:30 -07:00
Timothy J. Baek
9205b90af6 fix 2024-06-22 12:26:03 -07:00
Timothy J. Baek
6ce91de7e0 fix 2024-06-22 12:25:02 -07:00
Timothy J. Baek
f524238910 fix 2024-06-22 12:24:46 -07:00
Timothy J. Baek
646832ba8c refac 2024-06-22 12:23:37 -07:00
Timothy J. Baek
6ccb5e8f67 feat: user valves support 2024-06-22 12:14:12 -07:00
Timothy J. Baek
d362fd027e feat: user valves integration 2024-06-22 12:08:32 -07:00
Timothy J. Baek
15fc23df87 feat: user valves endpoints 2024-06-22 11:26:33 -07:00
Yash-1511
7c9fb9199e feat: add jina_search as new websearch provider 2024-06-22 20:06:15 +05:30
Timothy J. Baek
8345bb55d4 refac: styling 2024-06-22 02:29:33 -07:00
Timothy J. Baek
e4af3852f7 refac: allow class in tools 2024-06-22 02:29:22 -07:00
Timothy J. Baek
0ac8e97447 refac: styling 2024-06-22 01:43:40 -07:00
Timothy J. Baek
a8a451344c refac 2024-06-22 01:42:28 -07:00
Timothy J. Baek
ae567796ee refac 2024-06-22 01:39:53 -07:00
Timothy Jaeryang Baek
9220fdc4a4 Merge pull request #3367 from aleixdorca/dev
i18n: Updated Catalan Translation
2024-06-21 23:26:45 -07:00
aleix
b06d7dd56a i18n: Update Catalan Translation 2024-06-21 20:52:25 +02:00
Timothy J. Baek
14fd3a8aca refac 2024-06-21 11:05:55 -07:00
Timothy Jaeryang Baek
74ba2d6548 Merge pull request #3346 from KarlLee830/translate
i18n: Update Chinese translation
2024-06-21 11:02:04 -07:00
Timothy Jaeryang Baek
372bbcdf34 Merge pull request #3364 from PeterDaveHello/Improve-zh-TW
i18n: Improve Traditional Chinese(zh-TW) locale
2024-06-21 11:01:12 -07:00
Peter Dave Hello
0c7df2cde2 Improve Traditional Chinese(zh-TW) locale 2024-06-22 01:44:34 +08:00
Jun Siang Cheah
981f384154 refac: modify oauth login logic for unique email addresses 2024-06-21 18:25:19 +01:00
Jun Siang Cheah
e011e7b695 fix: set auth cookie during oauth login 2024-06-21 14:35:57 +01:00
Jun Siang Cheah
416e8d1ef9 fix: db migration sync with dev 2024-06-21 14:35:57 +01:00
Jun Siang Cheah
49a00d61ac feat: show oauth sub in admin panel 2024-06-21 14:35:57 +01:00
Jun Siang Cheah
983112d17c feat: fetch and store oauth profile pictures as data URLs 2024-06-21 14:35:54 +01:00
Jun Siang Cheah
922dfae51c fix: broken tuple expansion 2024-06-21 13:44:10 +01:00
Jun Siang Cheah
4aab460905 Merge remote-tracking branch 'upstream/dev' into feat/oauth 2024-06-21 13:43:19 +01:00
Karl Lee
f0b5008fc8 i18n: Update Chinese translation 2024-06-21 15:44:06 +08:00
Karl Lee
4d66e39402 i18n: Update Chinese translation 2024-06-21 11:45:57 +08:00
Timothy J. Baek
a2ea6b1b5b enh: tool async support 2024-06-20 20:40:03 -07:00
Timothy J. Baek
4370f233a1 feat: pipe async support 2024-06-20 20:37:04 -07:00
Timothy J. Baek
5621025c12 feat: async filter support 2024-06-20 20:26:28 -07:00
Timothy J. Baek
6bb2f41812 feat: tool citation 2024-06-20 14:14:12 -07:00
Timothy J. Baek
58ae91369e refac 2024-06-20 13:49:04 -07:00
Timothy Jaeryang Baek
c72e911f6a Merge pull request #3337 from SimonOriginal/dev
Added {$i18n.t('')} keys, updated Ukrainian translation
2024-06-20 13:19:37 -07:00
Timothy J. Baek
f1de635988 refac: cookie 2024-06-20 13:14:58 -07:00
SimonOriginal
f62d033e6b Fixed indentation in About.svelte 2024-06-20 22:05:48 +02:00
SimonOriginal
7c304d225b fix key {.t('Created by')} 2024-06-20 21:57:33 +02:00
SimonOriginal
89b259acb8 add key i18n + update translation 2024-06-20 21:53:34 +02:00
SimonOriginal
571dfd8a69 ukrainian translation update 2024-06-20 21:51:29 +02:00
SimonOriginal
e29e54a8d2 add key i18n 2024-06-20 21:49:52 +02:00
SimonOriginal
05e251da0e fix translation 2024-06-20 21:44:01 +02:00
Timothy J. Baek
f342f8adc7 refac: code highlight optimisation 2024-06-20 12:27:34 -07:00
Timothy Jaeryang Baek
deb4e36095 Merge pull request #3331 from SimonOriginal/dev 2024-06-20 11:25:30 -07:00
Timothy Jaeryang Baek
619ee152b7 Merge pull request #3332 from KarlLee830/translate 2024-06-20 11:22:19 -07:00
Timothy Jaeryang Baek
6e04ca85cb Merge pull request #3333 from perfectra1n/dev 2024-06-20 11:21:51 -07:00
perf3ct
9f39bcb60e Fix /tags endpoint in postgres integration test
/api/health it is

/health it is
2024-06-20 09:30:30 -07:00
Karl Lee
64814098a3 i18n: Update Chinese translation 2024-06-20 23:58:35 +08:00
SimonOriginal
1bd6626ca5 Ukrainian translation update to v0.3.5 2024-06-20 17:36:17 +02:00
sihuangwlp
36de6576b8 fix issue with i18n 2024-06-20 21:21:37 +08:00
Timothy J. Baek
71a7750c9d refac: styling 2024-06-20 05:05:16 -07:00
Timothy J. Baek
5a2c2770a4 chore: format 2024-06-20 04:53:23 -07:00
Timothy Jaeryang Baek
09a81eb225 Merge pull request #3321 from open-webui/functions
feat: functions
2024-06-20 04:52:32 -07:00
Timothy J. Baek
9ebd308d28 refac 2024-06-20 04:51:51 -07:00
Timothy J. Baek
59fa2f8f26 refac: pipe function support 2024-06-20 04:47:40 -07:00
Timothy J. Baek
d6e4aef607 feat: pipe function 2024-06-20 04:38:59 -07:00
Timothy J. Baek
de26a78a16 refac 2024-06-20 04:21:55 -07:00
Timothy J. Baek
c689356b31 refac 2024-06-20 03:57:36 -07:00
Timothy J. Baek
015772ef9a refac 2024-06-20 03:45:13 -07:00
Timothy J. Baek
e20baad601 refac 2024-06-20 03:35:21 -07:00
Timothy J. Baek
a3f09949c0 refac 2024-06-20 03:29:50 -07:00
Timothy J. Baek
afd270523c feat: filter func outlet 2024-06-20 03:23:50 -07:00
Timothy J. Baek
3101ff143b refac: disable continuing with error message 2024-06-20 02:47:27 -07:00
Timothy J. Baek
f14ca48334 refac 2024-06-20 02:42:56 -07:00
Timothy J. Baek
96d7c3e99f fix: raise error 2024-06-20 02:37:36 -07:00
Timothy J. Baek
c4bd60114e feat: filter inlet support 2024-06-20 02:30:00 -07:00
Timothy J. Baek
6b8a7b9939 refac: chat completion middleware 2024-06-20 02:06:10 -07:00
Timothy J. Baek
448ca9d836 refac 2024-06-20 01:51:39 -07:00
Timothy J. Baek
08cc20cb93 feat: filter selector model 2024-06-20 01:44:52 -07:00
Timothy J. Baek
bf5775e07a refac 2024-06-20 01:16:31 -07:00
Timothy J. Baek
9108df177c refac: comments 2024-06-20 01:12:09 -07:00
Timothy J. Baek
40cde07e5c feat: function filter example boilerplate 2024-06-20 01:07:55 -07:00
Timothy J. Baek
43e08c6afa refac 2024-06-20 00:54:58 -07:00
Timothy J. Baek
27f8afebab feat: function db migration 2024-06-20 00:49:11 -07:00
Timothy J. Baek
f68aba687e feat: functions router 2024-06-20 00:37:02 -07:00
sihuangwlp
e16ae92edc complate missing field AUTOMATIC1111_API_AUTH 2024-06-20 14:53:38 +08:00
sihuangwlp
d3160166e9 Complete missing commas 2024-06-20 14:38:13 +08:00
sihuangwlp
bec04279aa Add AUTOMATIC1111_API_AUTH support 2024-06-20 14:15:49 +08:00
Timothy J. Baek
f9283bc311 enh: pipeline user email support 2024-06-19 17:19:35 -07:00
Timothy J. Baek
d5b76b5ed2 enh: iframe support 2024-06-19 16:51:29 -07:00
Timothy J. Baek
7b64b40270 refac 2024-06-19 15:26:35 -07:00
Timothy J. Baek
e3668a2f1c refac 2024-06-19 14:56:51 -07:00
Timothy J. Baek
ab270c1682 fix 2024-06-19 14:49:35 -07:00
Timothy Jaeryang Baek
1e0453221d Merge pull request #3221 from perfectra1n/feature-external-db-reconnect
feat: external db reconnect
2024-06-19 14:40:03 -07:00
Timothy J. Baek
b36c525ebc enh: cookie auth 2024-06-19 14:38:09 -07:00
Timothy J. Baek
1b100660af fix: image 2024-06-19 13:31:01 -07:00
Timothy Jaeryang Baek
1007f67ab1 Merge pull request #3301 from KarlLee830/translate
i18n: Update Chinese translation
2024-06-19 12:24:44 -07:00
Karl Lee
ac37b50be2 Update Chinese translation 2024-06-20 01:17:26 +08:00
Timothy Jaeryang Baek
ece48d640a Merge pull request #3293 from que-nguyen/patch-1
Refine and update Vietnamese translations in translation.json
2024-06-19 08:49:39 -07:00
Que Nguyen
8125fd3554 Update: Refine and update Vietnamese translations 2024-06-19 18:23:47 +07:00
Que Nguyen
9e87012489 Fix: Rename 'whitelist' to 'filter_list' in function 2024-06-19 18:22:29 +07:00
Timothy J. Baek
b6ad539379 refac 2024-06-18 19:44:32 -07:00
Timothy J. Baek
ce659b9e1c chore: format 2024-06-18 19:20:20 -07:00
Timothy J. Baek
dad7af6de1 enh: tool __model__ param support 2024-06-18 18:50:36 -07:00
Timothy J. Baek
dcac1a3cb7 enh: tool __id__ param support for cache dir 2024-06-18 18:14:18 -07:00
Timothy J. Baek
6f9a31eba5 feat: tool cache dir 2024-06-18 18:07:51 -07:00
Timothy J. Baek
eef125d085 refac: settings order 2024-06-18 17:48:56 -07:00
Timothy J. Baek
ff9b94bab7 refac: playground 2024-06-18 17:41:47 -07:00
Timothy J. Baek
d1eb2c2207 fix: model selector focus 2024-06-18 17:16:33 -07:00
Timothy J. Baek
807cfdecfb fix 2024-06-18 17:09:29 -07:00
Timothy J. Baek
31f768bf8a fix 2024-06-18 17:07:13 -07:00
Timothy J. Baek
a2e1ea103c feat: tools file handler support 2024-06-18 16:45:03 -07:00
Timothy J. Baek
d6ab954f81 refac: styling 2024-06-18 16:11:10 -07:00
Timothy J. Baek
514c7f1520 fix: rag 2024-06-18 16:08:42 -07:00
Timothy J. Baek
bcc27e3852 fix 2024-06-18 15:48:25 -07:00
Timothy J. Baek
35026849df refac: styling 2024-06-18 15:39:50 -07:00
Timothy J. Baek
d5a1030000 refac: uploads delete 2024-06-18 15:20:04 -07:00
Timothy J. Baek
9fa8633dcb fix: styling 2024-06-18 15:11:59 -07:00
Timothy J. Baek
1a22ae54a2 fix: styling 2024-06-18 14:58:19 -07:00
Timothy J. Baek
20e4f6cc16 refac 2024-06-18 14:55:18 -07:00
Timothy J. Baek
eb21750466 fix: files 2024-06-18 14:38:23 -07:00
Timothy J. Baek
d93160799f refac: files 2024-06-18 14:37:12 -07:00
Timothy J. Baek
b4bdea6d85 fix: files 2024-06-18 14:33:44 -07:00
Timothy J. Baek
83986620ee refac 2024-06-18 14:15:08 -07:00
Timothy J. Baek
9e7b7a895e refac: file upload 2024-06-18 13:50:18 -07:00
Timothy Jaeryang Baek
1000bcaeb7 Merge pull request #3274 from KarlLee830/translate
i18n: Update Chinese translation
2024-06-18 13:07:16 -07:00
perfectra1n
7e061d19ca Merge branch 'open-webui:main' into feature-external-db-reconnect 2024-06-18 12:11:28 -07:00
Timothy J. Baek
7c2a198370 feat: file db migration 2024-06-18 11:38:50 -07:00
Timothy J. Baek
146e550239 feat: files endpoint 2024-06-18 11:36:55 -07:00
Karl Lee
4d9220c2c8 i18n: Update Chinese translation 2024-06-19 02:21:34 +08:00
Karl Lee
3c0678fb84 i18n: Update Chinese translation 2024-06-19 02:17:18 +08:00
Karl Lee
6985567758 Update Chinese translation 2024-06-19 02:10:01 +08:00
Karl Lee
5a5bf20d42 chore: format 2024-06-19 02:03:33 +08:00
Timothy J. Baek
ba7091c25b refac 2024-06-18 10:36:06 -07:00
Timothy Jaeryang Baek
e076803f98 Merge pull request #3256 from shing100/dev
i18n: Update Korean Localization for Open-WebUI
2024-06-18 10:34:33 -07:00
Timothy J. Baek
453f9be16c refac 2024-06-18 10:26:53 -07:00
Timothy J. Baek
19b67f4975 feat: functions scaffold 2024-06-18 10:23:04 -07:00
Geun, Lim
0a3390947c i18n: Korean Localization for Open-WebUI
In the updated translation, we changed the theme to own language and changed the other language a little more naturally.
2024-06-18 14:56:37 +09:00
Timothy J. Baek
47d9c9fc74 refac 2024-06-17 20:46:42 -07:00
perf3ct
81b2416923 format 2024-06-17 16:47:09 -07:00
perf3ct
59c6ff727a borrow some of the previous PRs reconnection code 2024-06-17 16:44:20 -07:00
Timothy J. Baek
493fe562ac refac 2024-06-17 14:39:21 -07:00
Timothy J. Baek
b1d83fc42c chore: format 2024-06-17 14:32:23 -07:00
Timothy Jaeryang Baek
20f052eb37 Merge pull request #3112 from que-nguyen/searxng
Domain whitelisting for web search results
2024-06-17 14:30:17 -07:00
Timothy J. Baek
edfe20b2e1 fix 2024-06-17 14:28:56 -07:00
Timothy J. Baek
a4748af822 chore: bump pyodide 2024-06-17 14:26:10 -07:00
Timothy J. Baek
46e570bd04 fix: styling 2024-06-17 13:52:17 -07:00
Timothy J. Baek
686c5081e6 fix: model system prompt variable support 2024-06-17 13:47:48 -07:00
Timothy J. Baek
84bd4994cd refac: toolkit editor 2024-06-17 13:38:07 -07:00
Timothy J. Baek
55dfc2013a enh: __messages__ support for tools 2024-06-17 13:28:29 -07:00
Timothy J. Baek
4a3362f889 fix: help 2024-06-17 11:46:23 -07:00
Timothy J. Baek
44e145c6e9 fix: styling 2024-06-17 11:32:10 -07:00
Timothy J. Baek
eb98631ff6 refac 2024-06-17 11:11:54 -07:00
perf3ct
48e1356ed9 add logging for user upon db connection 2024-06-17 10:34:19 -07:00
perf3ct
5c655f298b stop even using pooled DBs in peewee 2024-06-17 09:56:31 -07:00
Timothy Jaeryang Baek
cc4e192a51 Merge pull request #3235 from seokho-son/dev 2024-06-17 08:53:42 -07:00
perf3ct
981866eb93 use autoconnect and stop using the mixin 2024-06-17 07:50:47 -07:00
Seokho Son
cc98e89baa Complete Korean Localization for Open-WebUI
Signed-off-by: Seokho Son <shsongist@gmail.com>
2024-06-17 22:00:53 +09:00
Timothy J. Baek
d8a1d7eb36 feat: character utils 2024-06-17 03:05:09 -07:00
Timothy J. Baek
2f7120a73a refac 2024-06-17 02:54:56 -07:00
Timothy J. Baek
a60d6c316e fix 2024-06-17 02:28:12 -07:00
Timothy J. Baek
ab62228877 feat: character card support 2024-06-17 02:26:07 -07:00
Timothy J. Baek
f1b350cbe6 enh: use model profile image in call 2024-06-17 01:55:06 -07:00
Timothy J. Baek
9023a60d0d refac 2024-06-17 01:42:04 -07:00
Timothy J. Baek
49fdb68908 chore: format 2024-06-17 01:36:43 -07:00
Timothy Jaeryang Baek
db7d63d11a Merge pull request #3227 from KarlLee830/translate
Add some missing i18n keys and update Chinese translation
2024-06-17 01:35:03 -07:00
Karl Lee
720ff35edf Add some missing i18n keys and update Chinese translation
Add some missing i18n keys and update Chinese translation
2024-06-17 16:32:36 +08:00
Timothy J. Baek
5fa355e1ae feat: background image 2024-06-17 01:31:22 -07:00
Que Nguyen
c487385980 Set filter_list as optional param in serpstack.py 2024-06-17 14:38:11 +07:00
Que Nguyen
bcb84235b1 Set filter_list as optional param in serply.py 2024-06-17 14:37:52 +07:00
Que Nguyen
6b8290fa6d Set filter_list as optional param in serper.py 2024-06-17 14:37:26 +07:00
Que Nguyen
9c446d9fb4 Set filter_list as optional param in searxng.py 2024-06-17 14:36:56 +07:00
Que Nguyen
3cc0e3ecb6 Refactor rag/main.py
Renamed function get_filtered_results
2024-06-17 14:36:26 +07:00
Que Nguyen
d8beed13b4 Set filter_list as optional param in google_pse.py 2024-06-17 14:35:27 +07:00
Que Nguyen
7d2ad8c4bf Set filter_list as optional param in duckduckgo.py 2024-06-17 14:34:59 +07:00
Que Nguyen
a02139ba9d Set filter_list as optional param in brave.py 2024-06-17 14:34:17 +07:00
Que Nguyen
b3d136b3b3 Refactored config.py
Renamed RAG_WEB_SEARCH_WHITE_LIST_DOMAINS to RAG_WEB_SEARCH_DOMAIN_FILTER_LIST
2024-06-17 14:33:23 +07:00
Que Nguyen
a3ac9ee774 Refactor main.py
Rename RAG_WEB_SEARCH_WHITE_LIST_DOMAINS to RAG_WEB_SEARCH_DOMAIN_FILTER_LIST
2024-06-17 14:31:44 +07:00
Que Nguyen
75e51ecf6d Merge branch 'open-webui:main' into searxng 2024-06-17 14:28:02 +07:00
Timothy J. Baek
a28ad06bf0 fix 2024-06-16 23:36:21 -07:00
Timothy Jaeryang Baek
9e4dd4b86f Merge pull request #3159 from open-webui/dev
0.3.5
2024-06-16 22:52:44 -07:00
Timothy J. Baek
4559c8af74 doc: changelog 2024-06-16 22:52:27 -07:00
Timothy J. Baek
4a67ae1195 fix: message delete issue 2024-06-16 22:28:26 -07:00
Timothy J. Baek
1efa25eed5 chore: format 2024-06-16 21:55:08 -07:00
Timothy J. Baek
54b65a89fd refac: call overlay 2024-06-16 21:52:50 -07:00
Timothy Jaeryang Baek
b4008b0b30 Merge pull request #3140 from ricky-davis/sortable-users
feat: Sortable users in admin panel
2024-06-16 21:49:08 -07:00
Timothy Jaeryang Baek
16c95991d3 Merge pull request #3145 from ricky-davis/sortable-chats
feat: Sortable chats in admin panel
2024-06-16 21:48:13 -07:00
Timothy Jaeryang Baek
f3bd81073d Merge pull request #3202 from JohnTheNerd/main
feat: added ability to set user name for federated auth
2024-06-16 17:56:29 -07:00
Timothy J. Baek
6d9ed32929 refac 2024-06-16 17:19:18 -07:00
Timothy J. Baek
ad2ffc33d8 refac: voice call tap to interrupt 2024-06-16 16:50:57 -07:00
Timothy J. Baek
e183b0e5ff chore: format 2024-06-16 15:34:15 -07:00
Timothy J. Baek
4b6b33b08b feat: user_location 2024-06-16 15:32:26 -07:00
perf3ct
10fa887eab fix peewee and playhouse connections to retry 2024-06-16 15:25:48 -07:00
John Karabudak
c00a6fa02a added ability to set user name for federated auth
this commit adds an optional environment variable named `WEBUI_AUTH_TRUSTED_NAME_HEADER`, which sets the user's name to the contents of that header. this only happens if the user is just being created, just like how the trusted e-mail header works.

if the environment variable or header is not present, we fall back to the original behavior which is to re-use the user e-mail address.

Co-Authored-By: Nikita Borzykh <sample@fastmail.com>
2024-06-16 18:44:10 -02:30
Timothy J. Baek
8e62c36148 enh: AIOHTTP_CLIENT_TIMEOUT None support 2024-06-16 13:56:49 -07:00
Timothy Jaeryang Baek
f76a569527 Merge pull request #3219 from JohnTheNerd/comfyui-configuration
feat: added support for Stable Diffusion 3 alongside more extensive ComfyUI configuration
2024-06-16 13:50:38 -07:00
Timothy Jaeryang Baek
9a6c2fafe3 Merge pull request #3204 from JohnTheNerd/fix-github-actions
build: fixed GitHub actions on usernames with uppercase characters
2024-06-16 13:50:00 -07:00
Timothy J. Baek
1c355929fc refac 2024-06-16 12:09:55 -06:00
John Karabudak
ea074fa9bf added Stable Diffusion 3 support alongside ComfyUI configuration
this commit adds four environment variables:

- COMFYUI_CFG_SCALE
- COMFYUI_SAMPLER
- COMFYUI_SCHEDULER
- COMFYUI_SD3 (merely setting this at all will enable SD3 mode)
2024-06-16 15:30:52 -02:30
John Karabudak
60ee08a8ac made the environment variable name IMAGE_NAME as requested 2024-06-16 15:27:13 -02:30
Timothy J. Baek
9f7ef209fa fix: chatlist 2024-06-16 11:36:15 -06:00
Timothy J. Baek
fc1a66ea76 feat: current_time, current_datetime 2024-06-16 10:39:48 -06:00
Timothy J. Baek
5d0b77e64a fix: shift delete 2024-06-16 10:27:34 -06:00
Timothy J. Baek
a4810a5e42 refac 2024-06-16 10:24:16 -06:00
Timothy Jaeryang Baek
39c466d542 Merge pull request #3212 from robbie-cahill/patch-1
Add host.docker.internal overide for docker dev
2024-06-16 09:07:59 -07:00
Timothy Jaeryang Baek
c8418da8c1 Merge pull request #3217 from theasp/better-body-logging
chore: Log API request bodies at debug level
2024-06-16 09:07:22 -07:00
perf3ct
75d713057c Merge remote-tracking branch 'upstream/main' into feature-external-db-reconnect 2024-06-16 09:03:57 -07:00
Andrew Phillips
c0c875eae2 Use log.debug() for logging request bodies for the backend API 2024-06-16 12:40:16 -03:00
Andrew Phillips
3eba963d03 Remove redundant logging 2024-06-16 12:38:20 -03:00
Robbie
78a145f181 Add host.docker.internal overide 2024-06-16 21:16:07 +10:00
Jun Siang Cheah
4ff17acc1b Merge remote-tracking branch 'upstream/dev' into feat/oauth 2024-06-16 08:31:05 +01:00
Timothy Jaeryang Baek
9928114ca8 Merge pull request #3205 from Peter-De-Ath/chat-selectors-dark-mode
style: update chat selectors dark mode colors
2024-06-15 22:33:22 -07:00
Timothy J. Baek
e5f4f64102 enh: remove trailing slash 2024-06-15 23:32:12 -06:00
Peter De-Ath
7a98c1750f enh: update dark mode colors on chat selectors - models 2024-06-16 03:18:15 +01:00
Peter De-Ath
ee279b7976 enh: update dark mode colors on chat selectors 2024-06-16 02:55:27 +01:00
John Karabudak
dbfb6d5993 fixed GitHub actions on usernames with uppercase characters 2024-06-15 22:42:29 -02:30
Que Nguyen
a02ba52de8 Merge branch 'dev' into searxng 2024-06-15 23:44:31 +07:00
Timothy J. Baek
1275371e10 fix: md model desc 2024-06-15 10:43:10 -06:00
Timothy J. Baek
f56da1a39f refac 2024-06-15 04:41:48 -06:00
Timothy J. Baek
fe9685867e enh: model desc md support 2024-06-15 04:32:18 -06:00
Timothy J. Baek
dfa2cf9e6d refac: AIOHTTP_CLIENT_TIMEOUT default value should match 2024-06-15 04:25:21 -06:00
Timothy J. Baek
262501304c enh: model preset delete confirmation 2024-06-15 04:13:30 -06:00
Timothy J. Baek
a0dbc970a9 enh: model delete confirmation 2024-06-15 04:07:40 -06:00
Timothy J. Baek
2abb6788fe enh: user delete confirmation 2024-06-15 04:04:29 -06:00
Timothy J. Baek
91cec11500 refac 2024-06-15 04:02:20 -06:00
Timothy J. Baek
68aca76805 fix 2024-06-15 03:39:21 -06:00
Timothy J. Baek
2f501aee14 chore: format 2024-06-15 03:36:17 -06:00
Timothy J. Baek
3c599e24e5 refac 2024-06-15 03:35:44 -06:00
Timothy Jaeryang Baek
a6ee7415d8 Merge pull request #3116 from Peter-De-Ath/memories-edit
feat: add abilty to edit memories
2024-06-15 01:58:57 -07:00
Timothy J. Baek
d3a3d27f70 chore: format 2024-06-15 02:55:02 -06:00
Timothy Jaeryang Baek
16f9dcf17a Merge pull request #3184 from PierreMesure/better-swedish
i18n: Better Swedish translation 🇸🇪
2024-06-15 01:53:27 -07:00
Jun Siang Cheah
f49d814dc0 Merge remote-tracking branch 'upstream/main' into feat/oauth 2024-06-15 09:51:18 +01:00
Pierre Mesure
cb988e58ba Better Swedish translation 2024-06-15 09:13:27 +02:00
Peter De-Ath
bec00e7e64 fix: change update_memory to correct naming convention
fix: update update_memory to POST
2024-06-14 21:23:34 +01:00
Timothy J. Baek
7ba98ad498 feat: chat item shift shorcut 2024-06-14 13:02:07 -07:00
Timothy J. Baek
aba2ca39d4 enh: delete confirm dialog 2024-06-14 11:24:15 -07:00
Timothy Jaeryang Baek
8db439a0d1 Merge pull request #3177 from Yash-1511/main
feat: add tavily web search in web search provider
2024-06-14 11:09:59 -07:00
Timothy Jaeryang Baek
aec8e47fbb Merge pull request #3174 from KarlLee830/translate
Update Chinese translation
2024-06-14 11:09:22 -07:00
Timothy J. Baek
d03a00758f refac: sidebar 2024-06-14 11:06:19 -07:00
Yash-1511
717bbe62a6 doc: update readme 2024-06-14 20:51:50 +05:30
Yash-1511
b9da72560a feat: add tavily web search in web search provider 2024-06-14 20:44:11 +05:30
Karl Lee
460bc43846 Update Chinese translation
Update Chinese translation
2024-06-14 22:18:56 +08:00
Timothy Jaeryang Baek
26505079b8 Merge pull request #3107 from TheTerrasque/defect/ollama-long-response-timeout
Fix: ollama long response timeout
2024-06-14 02:45:55 -07:00
Timothy J. Baek
3de4c6189b fix: voice input sensitivity 2024-06-14 02:41:27 -07:00
Timothy J. Baek
2e4f060ebb feat: emoji call 2024-06-14 02:30:36 -07:00
Timothy Jaeryang Baek
53858c9b0e Merge pull request #3161 from sammcj/num_batch
feat: add num_keep, num_batch
2024-06-14 00:14:46 -07:00
Timothy J. Baek
454a386612 refac 2024-06-14 00:10:52 -07:00
Timothy J. Baek
346caaa1db chore: format 2024-06-14 00:07:46 -07:00
Timothy J. Baek
42ba43fc81 fix 2024-06-14 00:05:01 -07:00
Sam McLeod
3f5e36271f feat: add num_keep, num_batch 2024-06-14 16:21:20 +10:00
Timothy J. Baek
18ae5860bc refac 2024-06-13 20:16:23 -07:00
Timothy J. Baek
7f70de99d3 refac: voice call 2024-06-13 20:15:23 -07:00
rdavis
385fcfe8d0 Swapped from inline style to using tailwind class. 2024-06-14 00:29:31 +00:00
rdavis
09a6206d28 Merge branch 'sortable-users' of github.com:ricky-davis/open-webui into sortable-users 2024-06-13 19:27:23 -05:00
rdavis
b0d9aa38d2 Swapped from inline style to using tailwind class. 2024-06-14 00:07:21 +00:00
rdavis
26575c5086 Changed column header text to match property.
Removed debugging code.
2024-06-13 23:59:15 +00:00
rdavis
91d53530e6 Added the ability to sort chats in the admin panel chats modal
Added "Updated at" column to the admin panel chats modal.
2024-06-13 23:24:52 +00:00
rdavis
c07e7221e5 Added the ability to sort users in the admin panel 2024-06-13 15:00:02 -05:00
rdavis
5844d0525a Added the ability to sort users in the admin panel 2024-06-13 19:01:13 +00:00
Timothy Jaeryang Baek
7ea572fdca Merge pull request #3138 from open-webui/main
dev
2024-06-13 11:15:21 -07:00
Timothy J. Baek
162643a4b1 fix 2024-06-13 11:14:33 -07:00
Timothy Jaeryang Baek
4727e5cbb1 Merge pull request #3128 from open-webui/voice-enh
enh: voice
2024-06-13 02:32:23 -07:00
Timothy J. Baek
b8136951e4 refac 2024-06-13 02:29:56 -07:00
Timothy J. Baek
5300d2c531 refac 2024-06-13 01:28:15 -07:00
Timothy J. Baek
d6fd2a8228 refac 2024-06-12 21:18:53 -07:00
Peter De-Ath
493e3068d8 enh: ability to edit memories 2024-06-13 02:42:07 +01:00
Que Nguyen
7b5f434a07 Implement domain whitelisting for web search results 2024-06-13 07:14:48 +07:00
Mikael Turøy
e130ad74d1 Added timeout setting for ollama streaming response 2024-06-12 22:50:15 +02:00
Timothy Jaeryang Baek
a382e82dec Merge pull request #3105 from open-webui/dev
fix/refac: docs
2024-06-12 13:45:43 -07:00
Timothy J. Baek
bdd2ac0015 fix/refac: docs 2024-06-12 13:45:13 -07:00
Timothy Jaeryang Baek
c0a06f7db4 Merge pull request #3103 from open-webui/dev
fix: filter pipeline
2024-06-12 13:35:43 -07:00
Timothy J. Baek
e82027310d fix 2024-06-12 13:34:34 -07:00
Timothy J. Baek
c6c0bc19d8 fix: filter pipeline 2024-06-12 13:31:05 -07:00
Timothy Jaeryang Baek
33bb787b15 Merge pull request #3095 from open-webui/dev
refac
2024-06-12 11:47:47 -07:00
Timothy J. Baek
c794d59fd5 revert: do not change the default 2024-06-12 11:47:19 -07:00
Timothy J. Baek
1fefafb254 refac 2024-06-12 11:44:05 -07:00
Timothy Jaeryang Baek
90dadf0bec Merge pull request #3073 from que-nguyen/searxng
Set searxng language to auto and enable safesearch (moderate).
2024-06-12 11:26:10 -07:00
Timothy Jaeryang Baek
95ff355737 Merge pull request #3094 from open-webui/dev
fix: chat deletion
2024-06-12 11:23:31 -07:00
Timothy J. Baek
c2d41b0376 fix: chat deletion 2024-06-12 11:23:11 -07:00
Timothy Jaeryang Baek
8f3c9b391b Merge pull request #3093 from open-webui/dev
fix
2024-06-12 11:21:44 -07:00
Timothy J. Baek
5a9d883a93 fix 2024-06-12 11:21:23 -07:00
Timothy Jaeryang Baek
c2e8af5ed1 Merge pull request #3090 from open-webui/dev
0.3.4
2024-06-12 11:13:41 -07:00
Timothy J. Baek
70a85d6111 doc: changelog 2024-06-12 11:13:24 -07:00
Timothy J. Baek
1163745a03 revert 2024-06-12 11:08:05 -07:00
Timothy J. Baek
529fcaa5c9 fix: document query save 2024-06-12 11:07:04 -07:00
Timothy J. Baek
681fd4ff3b fix: tools api 2024-06-12 10:55:26 -07:00
Que Nguyen
305ec59d76 Set searxng language as 'auto' and enable safesearch (moderate).
Configure searxng with language param set to auto and add "safesearch": 1 (moderate) for safer web results.
2024-06-12 21:33:33 +07:00
Timothy Jaeryang Baek
0917fa6f4a Merge pull request #3056 from open-webui/dev
refac
2024-06-12 03:15:25 -07:00
Timothy J. Baek
c7d3969a53 refac 2024-06-12 03:13:59 -07:00
Timothy Jaeryang Baek
c41b33c9c0 Merge pull request #3013 from open-webui/dev
0.3.3
2024-06-12 02:14:37 -07:00
Timothy J. Baek
7131ac24a7 chore: format 2024-06-12 02:12:39 -07:00
Timothy J. Baek
501cd2071c fix: fr translation 2024-06-12 02:10:38 -07:00
Timothy J. Baek
85a1233733 refac: styling 2024-06-12 02:09:00 -07:00
Timothy J. Baek
670fa83e2c doc: changelog 2024-06-12 02:05:12 -07:00
Timothy J. Baek
d03a53e755 doc: changelog 2024-06-12 01:58:38 -07:00
Timothy J. Baek
2ec416bd6b doc: readme 2024-06-12 01:49:13 -07:00
Timothy J. Baek
b1a391ca5d doc: readme 2024-06-12 01:46:28 -07:00
Timothy J. Baek
c0ca447041 chore: format 2024-06-12 01:37:53 -07:00
Timothy Jaeryang Baek
5d3db15eca Merge pull request #3049 from que-nguyen/dev
Refactor URL validation function
2024-06-12 01:36:34 -07:00
Timothy J. Baek
eead69068c fix: type casting 2024-06-12 01:35:42 -07:00
Timothy J. Baek
edae1ca4c7 chore: format 2024-06-12 01:32:22 -07:00
Timothy J. Baek
0c9cc2baa3 refac: message 2024-06-12 01:28:30 -07:00
Timothy J. Baek
326ac41422 refac: bypass confirm dialog for edit 2024-06-12 01:22:52 -07:00
Timothy J. Baek
dd2941bb43 feat: import confim dialog 2024-06-12 01:20:12 -07:00
Timothy J. Baek
a691ee08d8 feat: confirm dialog 2024-06-12 01:17:46 -07:00
Timothy J. Baek
e8fc522eba chore: format 2024-06-12 00:18:22 -07:00
Timothy J. Baek
482a41e49b fix 2024-06-12 00:16:54 -07:00
Timothy J. Baek
ae3d8ce0c0 refac 2024-06-12 00:15:45 -07:00
Timothy J. Baek
a2e30ace02 refac: her 2024-06-12 00:13:35 -07:00
Timothy J. Baek
cde9672a09 enh: her 2024-06-12 00:05:20 -07:00
Timothy J. Baek
db6ca856de Update requirements-dev.lock 2024-06-11 19:16:06 -07:00
Timothy J. Baek
bb5e615841 chore: python requirements 2024-06-11 19:14:47 -07:00
Timothy J. Baek
48ac4d9f2a fix 2024-06-11 18:23:42 -07:00
Que Nguyen
eb7bba81fe Refactor URL validation function
- The check for private IP addresses often did not yield the expected results, especially with errors like: `[Errno -2] Name or service not known`.
- Removed the check for private IP addresses in the URL validation process.
- Simplified the `validate_url` function to focus on validating the URL format and checking the existence of the URL using a HEAD request.
2024-06-12 08:15:04 +07:00
Timothy J. Baek
a43cb1eb25 refac: styling 2024-06-11 17:09:10 -07:00
Timothy J. Baek
e2d8872060 fix: e2e 2024-06-11 17:03:49 -07:00
Timothy J. Baek
ede584320f refac: tools edit 2024-06-11 16:54:21 -07:00
Timothy J. Baek
bc458d3ee0 refac 2024-06-11 16:15:54 -07:00
Timothy J. Baek
0d1f7265c4 refac 2024-06-11 16:15:19 -07:00
Timothy J. Baek
539201a032 chore: format 2024-06-11 15:44:36 -07:00
Timothy J. Baek
50ad2aa215 chore: format 2024-06-11 15:44:27 -07:00
Timothy J. Baek
5cd28c04b8 feat: model tools assignment 2024-06-11 15:29:46 -07:00
Timothy J. Baek
c3ce4d7f6a refac 2024-06-11 14:36:46 -07:00
Timothy J. Baek
9bd054490f refac 2024-06-11 14:32:01 -07:00
Timothy J. Baek
2be14d57bf fix 2024-06-11 14:30:18 -07:00
Timothy J. Baek
61e0a85aed feat: export tool 2024-06-11 12:24:36 -07:00
Timothy J. Baek
e483c6b598 refac: styling 2024-06-11 12:18:30 -07:00
Timothy J. Baek
db3b075796 refac: input menu tools 2024-06-11 12:16:11 -07:00
Timothy J. Baek
0bb26ae504 refac: tools 2024-06-11 11:31:14 -07:00
Timothy J. Baek
9d16dd997a refac 2024-06-11 11:15:43 -07:00
Timothy J. Baek
e4fe1fff97 feat: tool __user__ email 2024-06-11 10:54:11 -07:00
Timothy J. Baek
37ed31b0e2 feat: tools warning 2024-06-11 10:47:46 -07:00
Timothy J. Baek
dc82e681dd refac 2024-06-11 10:43:36 -07:00
Timothy J. Baek
4944824544 enh: __user__ example 2024-06-11 10:36:35 -07:00
Timothy J. Baek
67cd9b76ae refac: __user__ param 2024-06-11 10:35:13 -07:00
Timothy J. Baek
8a86f32700 feat: user hook 2024-06-11 10:19:59 -07:00
Timothy Jaeryang Baek
f62b15d8da Merge pull request #3042 from sime2408/fit/translations-croatian
Updated Croatian translation for user interface text
2024-06-11 09:55:17 -07:00
Timothy Jaeryang Baek
d709038b5b Merge pull request #3029 from Yash-1511/main
feat: add DuckDuckGo search functionality using duckduckgo_search library
2024-06-11 09:53:26 -07:00
Timothy Jaeryang Baek
a2631ed38e Merge pull request #3041 from cocktailpeanut/main
feat: custom HOST env variable on windows
2024-06-11 09:52:45 -07:00
Timothy Jaeryang Baek
8ffd8c3505 Merge pull request #3035 from ClassicOldSong/main
Fix frontend stops responding when backend throws error
2024-06-11 09:52:26 -07:00
sime2408
f74df0433b Updated Croatian translation for user interface text
Refined Croatian locale translations to improve understanding and clarity for Croatian users. Adjustments made include improving command descriptions, correcting grammar, and adapting the terminology to better fit the software context.
2024-06-11 18:52:08 +02:00
Timothy Jaeryang Baek
93fa98245b Merge pull request #3033 from que-nguyen/dev
Fixed the issue where a single URL error disrupts the Web Search
2024-06-11 09:52:07 -07:00
Timothy Jaeryang Baek
e7727aea9e Merge pull request #3024 from KarlLee830/translate
Update Chinese Translation
2024-06-11 09:51:34 -07:00
cocktailpeanut
884eb9f7ee update 2024-06-11 12:32:29 -04:00
Yukino Song
912b75f8ac Fix frontend stops responding when backend throw error 2024-06-11 23:25:07 +08:00
Que Nguyen
3bec60b80c Fixed the issue where a single URL error disrupts the data loading process in Web Search mode
To address the unresolved issue in the LangChain library where a single URL error disrupts the data loading process, the lazy_load method in the WebBaseLoader class has been modified. The enhanced method now handles exceptions appropriately, logging errors and continuing with the remaining URLs.
2024-06-11 22:06:14 +07:00
Yash-1511
07b08ef67e add: duckduckgo-search dependencies added in requirements.txt 2024-06-11 19:53:57 +05:30
Yash-1511
83f9475584 feat: add DuckDuckGo search functionality using duckduckgo_search library 2024-06-11 19:49:08 +05:30
Karl Lee
1ad5456fe0 Update Chinese Translation 2024-06-11 20:46:15 +08:00
Timothy J. Baek
bf1936de34 refac 2024-06-11 02:12:24 -07:00
Timothy J. Baek
827dd1b044 refac 2024-06-11 01:58:26 -07:00
Timothy J. Baek
b2028d187d chore: format 2024-06-11 01:34:29 -07:00
Timothy J. Baek
1e1b372d07 fix 2024-06-11 01:18:05 -07:00
Timothy J. Baek
bd5a8567ef refac: tools & rag 2024-06-11 01:10:24 -07:00
Timothy J. Baek
fc46532955 fix 2024-06-11 00:58:52 -07:00
Timothy Jaeryang Baek
5f29a9edf4 Merge pull request #2998 from que-nguyen/dev
Completed Vietnamese translation
2024-06-11 00:52:15 -07:00
Timothy J. Baek
91bc65c7da fix 2024-06-11 00:50:30 -07:00
Timothy J. Baek
a91db7f7a6 refac 2024-06-11 00:43:42 -07:00
Timothy Jaeryang Baek
e6fe3ada57 Merge pull request #3006 from open-webui/tools
feat: tools
2024-06-11 00:37:53 -07:00
Timothy J. Baek
354683296b refac 2024-06-11 00:37:31 -07:00
Timothy J. Baek
5237439e29 feat: tool desc 2024-06-11 00:32:16 -07:00
Timothy J. Baek
049b3136e8 refac 2024-06-11 00:24:25 -07:00
Timothy J. Baek
3d6f5f418d feat: tools full integration 2024-06-11 00:18:45 -07:00
Timothy J. Baek
a27175d672 feat: fc integration 2024-06-10 23:40:27 -07:00
Timothy J. Baek
ff1cd306d8 refac 2024-06-10 22:38:48 -07:00
Timothy J. Baek
aa7d25600f refac 2024-06-10 22:33:25 -07:00
Timothy J. Baek
0bae7ca615 feat: tool selector input menu 2024-06-10 22:29:24 -07:00
Timothy J. Baek
3578b5e337 refac: clone 2024-06-10 22:16:49 -07:00
Timothy J. Baek
8464b30485 refac 2024-06-10 22:10:53 -07:00
Timothy J. Baek
c961964647 enh: tool id validation 2024-06-10 21:59:06 -07:00
Timothy J. Baek
dd7ac4c53a refac: search 2024-06-10 21:55:34 -07:00
Timothy J. Baek
4601a0246f fix: tool edit 2024-06-10 21:53:51 -07:00
Timothy J. Baek
25c0eca414 feat: edit tool spinner 2024-06-10 21:47:25 -07:00
Timothy J. Baek
ca8be1ee4a feat: import tools 2024-06-10 21:38:29 -07:00
Timothy J. Baek
1611a3aa70 feat: export tools 2024-06-10 21:36:13 -07:00
Timothy J. Baek
b434ebf3ad feat: tools integration 2024-06-10 21:33:46 -07:00
Timothy Jaeryang Baek
d2ed99e201 Merge pull request #3008 from open-webui/main
dev
2024-06-10 21:07:35 -07:00
Timothy Jaeryang Baek
06976c4551 Merge pull request #3007 from open-webui/fix
fix
2024-06-10 21:07:13 -07:00
Timothy J. Baek
626643104e fix 2024-06-10 21:06:46 -07:00
Timothy J. Baek
c5683dd24c refac 2024-06-10 21:05:06 -07:00
Timothy J. Baek
6589464ddf refac 2024-06-10 20:58:47 -07:00
Timothy J. Baek
e27c264081 feat: tools apis 2024-06-10 20:43:11 -07:00
Timothy J. Baek
3a96e1f109 feat: tools backend 2024-06-10 20:39:55 -07:00
Timothy J. Baek
c4629c8c2d refac: tools 2024-06-10 19:30:48 -07:00
Timothy J. Baek
adea3af8d7 refac 2024-06-10 19:19:53 -07:00
Timothy Jaeryang Baek
ec516e95fa Merge pull request #3001 from open-webui/main
dev
2024-06-10 18:56:21 -07:00
Timothy Jaeryang Baek
481fd9f88a Merge pull request #3000 from open-webui/fix
fix
2024-06-10 18:56:01 -07:00
Timothy J. Baek
2bbaf1234c fix 2024-06-10 18:55:45 -07:00
Timothy Jaeryang Baek
690c25215d Merge pull request #2999 from open-webui/fix
fix
2024-06-10 18:55:18 -07:00
Timothy J. Baek
b72243c166 fix 2024-06-10 18:54:52 -07:00
Timothy J. Baek
8f2e799615 fix 2024-06-10 18:53:33 -07:00
Que Nguyen
8ecf262457 Completed Vietnamese translation 2024-06-11 08:49:06 +07:00
Timothy Jaeryang Baek
7fb785901e Merge pull request #2997 from open-webui/main
dev
2024-06-10 18:02:06 -07:00
Timothy Jaeryang Baek
5dc9b93916 Merge pull request #2996 from open-webui/fix
fix: regeneration
2024-06-10 17:58:42 -07:00
Timothy J. Baek
1241bc3e89 fix: regeneration 2024-06-10 17:58:07 -07:00
Timothy J. Baek
c5ed3452d2 refac 2024-06-10 17:52:12 -07:00
Timothy J. Baek
c2e6e44714 refac 2024-06-10 17:33:40 -07:00
Timothy J. Baek
6e7e575a18 refac 2024-06-10 17:30:07 -07:00
Timothy J. Baek
f43b545bdd refac 2024-06-10 17:24:42 -07:00
Timothy J. Baek
12a04b118f refac: styling 2024-06-10 17:22:44 -07:00
Timothy J. Baek
8b1e2ce279 feat: code format 2024-06-10 17:12:48 -07:00
Timothy J. Baek
fb0f106afe refac: styling 2024-06-10 16:37:33 -07:00
Timothy J. Baek
dd423f43de feat: default tools template 2024-06-10 16:35:42 -07:00
Timothy J. Baek
f2bd3fdf19 chore: rm console log 2024-06-10 16:16:08 -07:00
Timothy J. Baek
8ad52f0fcc feat: code editor 2024-06-10 16:02:23 -07:00
Timothy J. Baek
5a3736f1ee feat: tools page 2024-06-10 15:24:26 -07:00
Timothy J. Baek
54bbfa5e89 chore: npm 2024-06-10 14:49:03 -07:00
Timothy Jaeryang Baek
3933db2c91 Merge pull request #2992 from open-webui/dev
0.3.2
2024-06-10 13:53:56 -07:00
Timothy J. Baek
dc8f0987e1 doc: changelog 2024-06-10 13:53:47 -07:00
Timothy J. Baek
644f0fe6c3 chore: version bump 2024-06-10 13:52:35 -07:00
Timothy J. Baek
87b04b0fc3 fix: params 2024-06-10 13:41:13 -07:00
Timothy J. Baek
455403a4a4 fix 2024-06-10 13:29:28 -07:00
Timothy J. Baek
547b990041 refac: params 2024-06-10 13:29:09 -07:00
Timothy Jaeryang Baek
fcf8f2a704 Merge pull request #2952 from arkohut/tolerant-readonly-filesystem
fix: tolerant readonly filesystem for copy favicon to static dir
2024-06-10 11:59:06 -07:00
Timothy Jaeryang Baek
496e798cc7 Merge pull request #2973 from KarlLee830/translate
i18n: Add some missing i18n keys and update Chinese translation
2024-06-10 11:58:47 -07:00
Timothy Jaeryang Baek
e01b3569d5 Merge pull request #2983 from pedrosilva/ptPTtranslation
pt-PT translation
2024-06-10 11:58:34 -07:00
Timothy J. Baek
a75b68c19c refac: message status history 2024-06-10 11:40:58 -07:00
Timothy J. Baek
34f04c53fc fix: audio 2024-06-10 11:04:00 -07:00
Pedro Silva
2b87ab32ff Updated pt-PT translation 2024-06-10 15:27:06 +01:00
arkohut
d20f6cb45b fix: use Exception to handle all errors 2024-06-10 21:27:35 +08:00
Karl Lee
48c9fb0ddf Update Chinese translation 2024-06-10 18:02:52 +08:00
Timothy Jaeryang Baek
c609cc23eb Merge pull request #2964 from googio/dev
feat: adding Serply as another web search provider
2024-06-10 01:50:04 -07:00
Timothy Jaeryang Baek
3566002b0b doc 2024-06-10 03:49:23 -05:00
Timothy J. Baek
140d7ff721 refac 2024-06-10 01:07:24 -07:00
Timothy J. Baek
7349e1d8c8 refac 2024-06-10 00:56:13 -07:00
Timothy J. Baek
bf5a62298c refac 2024-06-10 00:15:46 -07:00
Timothy J. Baek
2972774d87 refac 2024-06-10 00:07:47 -07:00
Timothy Jaeryang Baek
75d455ac8f Merge pull request #2967 from open-webui/dev
0.3.1
2024-06-09 19:09:28 -07:00
Timothy J. Baek
64b6a8c5db doc: changelog 2024-06-09 19:08:57 -07:00
Timothy Jaeryang Baek
8947da57af Merge pull request #2966 from open-webui/dev
fix
2024-06-09 19:00:08 -07:00
Timothy J. Baek
16f09fff63 fix 2024-06-09 18:59:45 -07:00
teampen
14eb667fc8 add changes to web search in admin settings 2024-06-09 21:52:08 -04:00
teampen
79bf8d6dd3 undo changes to deprecated web search params 2024-06-09 21:43:13 -04:00
teampen
14d33f0fcc Merge branch 'add-serply' into dev 2024-06-09 21:40:50 -04:00
teampen
4dcec4855e adding Serply as an alternative web search 2024-06-09 21:39:46 -04:00
Timothy Jaeryang Baek
96a004d4d8 Merge pull request #2921 from open-webui/dev
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
teampen
efb4a710c8 adding Serply as an alternative web search 2024-06-09 20:44:34 -04: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
arkohut
8e9e429a91 fix: tolerant readonly filesystem for copy favicon to static dir 2024-06-09 23:23:28 +08: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
Jun Siang Cheah
bba4c4242f feat: add WEBUI_SESSION_COOKIE_SECURE 2024-06-07 09:13:42 +01: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
Jun Siang Cheah
ae376ec8fe Merge remote-tracking branch 'upstream/dev' into feat/oauth 2024-06-05 19:23:52 +01:00
Jun Siang Cheah
af4f8aa589 feat: add WEBUI_SESSION_COOKIE_SAME_SITE for when open webui is embedded 2024-06-05 19:21:42 +01: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
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
Timothy Jaeryang Baek
f28877f4db Merge pull request #2801 from open-webui/dev
0.2.4
2024-06-03 21:29:13 -07:00
Timothy J. Baek
b673ae7ab2 chore: version bump 2024-06-03 21:28:12 -07:00
Timothy Jaeryang Baek
8c3a6eb262 Merge pull request #2799 from mindspawn/proxy-fix
Enable use of http_proxy environment variable in openai and ollama calls
2024-06-03 21:19:53 -07:00
Timothy J. Baek
25336f85f3 feat: admin details in account pending overlay 2024-06-03 21:17:43 -07:00
mindspawn
74ed74f1a4 Enable http_proxy use for ollama calls. 2024-06-03 20:43:25 -07:00
mindspawn
94ebf02719 Enable http_proxy use for openai calls. 2024-06-03 20:41:59 -07:00
Timothy Jaeryang Baek
11bb1a6f7d Merge pull request #2795 from open-webui/dev
fix
2024-06-03 17:07:25 -07:00
Timothy J. Baek
61867c1545 Update searxng.py 2024-06-03 17:02:50 -07:00
Timothy J. Baek
4068a421bf fix 2024-06-03 17:00:35 -07:00
Timothy Jaeryang Baek
8a94d8a226 Merge pull request #2794 from open-webui/dev
fix
2024-06-03 15:52:04 -07:00
Timothy Jaeryang Baek
5a24ce06f0 Merge pull request #2792 from aguvener/dev
i18n: incorrect translations fixed
2024-06-03 15:51:47 -07:00
Timothy J. Baek
e72170bac7 doc: readme 2024-06-03 15:51:10 -07:00
Timothy J. Baek
dd93b0dd24 feat: documentation button 2024-06-03 15:45:33 -07:00
Timothy Jaeryang Baek
0ac04c9518 Merge pull request #2791 from open-webui/dev
doc: demo.gif
2024-06-03 15:17:22 -07:00
Timothy J. Baek
d28925de05 doc: demo.gif 2024-06-03 15:15:59 -07:00
aguvener
2c4c62fb75 Update translation.json 2024-06-04 01:15:42 +03:00
Timothy Jaeryang Baek
de162a1f32 Merge pull request #2789 from open-webui/dev
fix
2024-06-03 13:52:07 -07:00
Timothy J. Baek
aa7e5dbfce chore: format 2024-06-03 13:51:56 -07:00
Timothy J. Baek
8d99bffbdc chore: format 2024-06-03 13:51:32 -07:00
Timothy Jaeryang Baek
768941bded Merge pull request #2785 from cheahjs/feat/openai-embeddings-batch
feat: add RAG_EMBEDDING_OPENAI_BATCH_SIZE to batch multiple embeddings
2024-06-03 13:50:14 -07:00
Timothy Jaeryang Baek
e0772c6807 Merge pull request #2788 from open-webui/dev
fix: import model
2024-06-03 13:41:59 -07:00
Timothy J. Baek
cbd60168ea fix: import model 2024-06-03 13:41:33 -07:00
Timothy Jaeryang Baek
c6c5c0ddb2 Merge pull request #2787 from open-webui/dev
fix
2024-06-03 13:37:13 -07:00
Timothy Jaeryang Baek
7c35447666 Merge pull request #2786 from justinh-rahb/contributing-update
docs: add line re: keeping PRs open
2024-06-03 13:36:42 -07:00
Timothy J. Baek
58b5e0bf3e fix: modelfile edit 2024-06-03 13:35:03 -07:00
Justin Hayes
0586d76b5d Add line re: keeping PRs open 2024-06-03 16:26:30 -04:00
Timothy Jaeryang Baek
eb3fcef6d7 Merge pull request #2784 from open-webui/dev
fix
2024-06-03 13:16:29 -07:00
Timothy Jaeryang Baek
59a730cb8b Merge pull request #2783 from cheahjs/fix/searxng-backwards-compat
fix: add backwards compat with older searxng urls
2024-06-03 13:16:10 -07:00
Jun Siang Cheah
7fefbb316d fix: add backwards compat with older searxng urls 2024-06-03 21:13:10 +01:00
Timothy Jaeryang Baek
14646e84ea Merge pull request #2782 from open-webui/dev
0.2.3
2024-06-03 13:06:46 -07:00
Timothy Jaeryang Baek
ba56edab19 Merge pull request #2781 from Lhemamou/dev
fix: lithuanian language doesn't appear in the languages list (#2780)
2024-06-03 13:05:20 -07:00
Timothy J. Baek
a233a8855b chore: version bump 2024-06-03 13:04:18 -07:00
Lhemamou
c11fdad82d add lithuanian 2024-06-03 21:56:07 +02:00
Timothy J. Baek
82f7b6c315 refac: modelfiles migration 2024-06-03 12:48:17 -07:00
Timothy Jaeryang Baek
92d9b38110 Merge branch 'dev' into feat/openai-embeddings-batch 2024-06-03 12:39:09 -07:00
Timothy Jaeryang Baek
36a66fcfc4 Merge pull request #2774 from cheahjs/feat/title-edit-improvements
feat: title edit improvements
2024-06-03 12:34:02 -07:00
Timothy Jaeryang Baek
ea27bc50f5 Merge pull request #2750 from KarlLee830/dev
Improve Chinese translation
2024-06-03 12:33:13 -07:00
Timothy Jaeryang Baek
8a9c18ddd5 Merge branch 'dev' into dev 2024-06-03 12:33:03 -07:00
Timothy Jaeryang Baek
3729771f33 Merge pull request #2760 from nirabo/fix/searxng
Fix/searxng
2024-06-03 12:32:03 -07:00
Timothy Jaeryang Baek
ab58947a19 Merge pull request #2775 from cheahjs/feat/allow-nonlocal-tts
feat: allow nonlocal tts voices
2024-06-03 12:31:20 -07:00
Timothy J. Baek
f9351af6a3 refac: message input 2024-06-03 12:30:37 -07:00
Jun Siang Cheah
8f03daeaf6 fix: selected local tts voice not shown in settings 2024-06-03 19:11:37 +01:00
Jun Siang Cheah
de03bf834e feat: add option to allow nonlocal TTS voices 2024-06-03 19:11:14 +01:00
Jun Siang Cheah
db3d48ee15 feat: automatically focus title input when editing 2024-06-03 18:49:34 +01:00
Jun Siang Cheah
6022f6f5df feat: double click title to edit 2024-06-03 18:48:27 +01:00
Karl Lee
2d1a890ed9 Improve more Chinese translation content
Improve more Chinese translation content
2024-06-03 22:08:58 +08:00
Lyuboslav Petrov
08443b3c55 Revert log level to debug 2024-06-03 12:48:40 +03:00
Lyuboslav Petrov
7e761a69a7 FIX searxng URL construction using params for arg passing
Accept additional parameters such as language, time_range, and categories to tailor the search results.
Raise an exception if a request error occurs during the search process.
Use params argument to construct the query string
Sort by relevance
Expand docstring
2024-06-03 12:44:46 +03:00
Timothy Jaeryang Baek
be08dbf00d Merge pull request #2753 from open-webui/dev
fix
2024-06-02 22:36:43 -07:00
Timothy J. Baek
b4fca046a8 fix 2024-06-02 22:36:23 -07:00
Timothy Jaeryang Baek
61287a16d5 Merge pull request #2752 from open-webui/dev
fix: #2751
2024-06-02 22:29:16 -07:00
Timothy J. Baek
16e72b2f67 fix: #2751 2024-06-02 22:28:56 -07:00
Karl Lee
80d173c1c3 Improve Chinese translation
Corrected the terrible errors in the Chinese translation and improved the overall translation quality.
2024-06-03 12:50:31 +08:00
Timothy Jaeryang Baek
4b459e372f Merge pull request #2749 from open-webui/dev
feat: single chat export
2024-06-02 21:39:36 -07:00
Timothy J. Baek
fddf693dad feat: single chat export 2024-06-02 21:39:09 -07:00
Timothy Jaeryang Baek
a39ab4dd24 Merge pull request #2747 from open-webui/dev
fix: render mermaid after edit
2024-06-02 19:09:19 -07:00
Timothy Jaeryang Baek
13db33e947 Merge pull request #2746 from Yanyutin753/translate
📌fix format #2744
2024-06-02 19:08:47 -07:00
Timothy J. Baek
727a837e53 fix: render mermaid after edit 2024-06-02 19:08:18 -07:00
Yanyutin753
22d7ce2b7f 📌fix format 2024-06-03 10:04:17 +08:00
Timothy Jaeryang Baek
1d4c358624 Merge pull request #2745 from open-webui/dev
fix
2024-06-02 19:03:16 -07:00
Timothy J. Baek
a3ecf62564 fix: chat completed 2024-06-02 19:02:46 -07:00
Timothy Jaeryang Baek
6199296205 Merge pull request #2744 from Yanyutin753/translate
 use Azure API 3.0 to translate almost all languages and complete those without translations in v0.2.0
2024-06-02 18:55:08 -07:00
Yanyutin753
5ea88f2e4f use Azure API 3.0 to translate almost all languages and complete those without translations in v0.2.0 2024-06-03 09:48:49 +08:00
Timothy Jaeryang Baek
5be97b81d6 Merge pull request #2743 from open-webui/dev
fix: changelog
2024-06-02 18:27:36 -07:00
Timothy J. Baek
42f335851f fix: changelog 2024-06-02 18:27:18 -07:00
Timothy Jaeryang Baek
0744806523 Merge pull request #2742 from open-webui/dev
0.2.2
2024-06-02 18:26:09 -07:00
Timothy J. Baek
a36555a25a chore: version bump 2024-06-02 18:26:00 -07:00
Timothy J. Baek
814fbb73f3 feat: RESET_CONFIG_ON_START 2024-06-02 18:14:36 -07:00
Timothy J. Baek
3d74c04f50 feat: mermaid rendering support 2024-06-02 18:03:30 -07:00
Timothy J. Baek
a9e5003c4f fix: filter outlet 2024-06-02 17:49:44 -07:00
Yanyutin753
8114fa93cf translation zh-CN 2024-06-03 08:32:39 +08:00
Timothy J. Baek
32a61ea15d fix: pipelines 2024-06-02 16:46:33 -07:00
Timothy Jaeryang Baek
d9a3e4db39 Merge pull request #2731 from cheahjs/fix/ollama-cancellation
fix: ollama and openai stream cancellation
2024-06-02 16:27:11 -07:00
Timothy Jaeryang Baek
c5ff4c24e1 Merge branch 'dev' into fix/ollama-cancellation 2024-06-02 16:27:01 -07:00
Timothy Jaeryang Baek
9b3fdb1838 Merge pull request #2741 from open-webui/dev
fix: validate lengths for openai urls and keys
2024-06-02 16:21:28 -07:00
Timothy J. Baek
27ff3ab112 fix: validate lengths for openai urls and keys 2024-06-02 16:20:22 -07:00
Timothy Jaeryang Baek
d09164b729 Merge pull request #2739 from open-webui/dev
fix
2024-06-02 15:19:59 -07:00
Timothy Jaeryang Baek
44597314c6 Merge pull request #2737 from cheahjs/fix/docker-tag-again
fix: another attempt at fixing tag docker builds
2024-06-02 14:49:18 -07:00
Jun Siang Cheah
3176fe0c2b fix: another attempt at fixing tag docker builds 2024-06-02 22:35:59 +01:00
Jun Siang Cheah
b5b2b70f4a fix: bad payload refactor 2024-06-02 19:40:18 +01:00
Jun Siang Cheah
7f74426a22 fix: openai streaming cancellation using aiohttp 2024-06-02 18:48:45 +01:00
Jun Siang Cheah
4dd51badfe fix: ollama streaming cancellation using aiohttp 2024-06-02 18:06:12 +01:00
Jun Siang Cheah
24c35c308d fix: stream defaults to true, return request ID 2024-06-02 17:09:15 +01:00
Jun Siang Cheah
0cb8163321 feat: add RAG_EMBEDDING_OPENAI_BATCH_SIZE to batch multiple embeddings 2024-06-02 15:34:31 +01:00
Беклемишев Петр Алексеевич
ad32a2ef3c Drop mysql restarts 2024-05-31 13:26:23 +07:00
Беклемишев Петр Алексеевич
e59e1f5049 Fix rebase artifacts 2024-05-30 20:44:13 +07:00
Беклемишев Петр Алексеевич
e1fa453eda Test reconnection to postgres in gh actions 2024-05-30 20:41:10 +07:00
Беклемишев Петр Алексеевич
dfbc125947 Reconnect to postgresql & mysql external databases when getting disconnected 2024-05-30 20:41:06 +07:00
Jun Siang Cheah
a1f4706aa1 fix: OAUTH_MERGE_ACCOUNTS_BY_EMAIL not being correctly read 2024-05-27 18:16:36 +01:00
Jun Siang Cheah
6a36039a59 Merge remote-tracking branch 'upstream/dev' into feat/oauth 2024-05-27 18:14:43 +01:00
Jun Siang Cheah
985fdca585 refac: move things around, uplift oauth endpoints 2024-05-27 18:07:38 +01:00
Jun Siang Cheah
06dbf59742 feat: make oauth config persist into config.json 2024-05-27 17:21:24 +01:00
Jun Siang Cheah
4a4e323a44 refac: rename OPENID -> OAUTH 2024-05-27 17:17:34 +01:00
Jun Siang Cheah
776bb2892c fix: bad user get 2024-05-26 13:07:41 +01:00
Jun Siang Cheah
7385016e36 fix: only get user by emails without oauth sub 2024-05-26 11:59:21 +01:00
Jun Siang Cheah
b3557d05b1 fix: bad authlib version 2024-05-26 11:32:42 +01:00
Jun Siang Cheah
0210a105bf feat: experimental SSO support for Google, Microsoft, and OIDC 2024-05-26 11:26:15 +01:00
Jun Siang Cheah
a842d8d62b deps: add authlib 2024-05-26 11:25:29 +01:00
429 changed files with 64906 additions and 22040 deletions

View File

@@ -10,7 +10,8 @@ node_modules
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
__pycache__
.env
.idea
venv
_old
uploads
.ipynb_checkpoints

View File

@@ -8,36 +8,43 @@ assignees: ''
# Bug Report
## Description
## Installation Method
**Bug Summary:**
[Provide a brief but clear summary of the bug]
**Steps to Reproduce:**
[Outline the steps to reproduce the bug. Be as detailed as possible.]
**Expected Behavior:**
[Describe what you expected to happen.]
**Actual Behavior:**
[Describe what actually happened.]
[Describe the method you used to install the project, e.g., git clone, Docker, pip, etc.]
## Environment
- **Open WebUI Version:** [e.g., 0.1.120]
- **Ollama (if applicable):** [e.g., 0.1.30, 0.1.32-rc1]
- **Open WebUI Version:** [e.g., v0.3.11]
- **Ollama (if applicable):** [e.g., v0.2.0, v0.1.32-rc1]
- **Operating System:** [e.g., Windows 10, macOS Big Sur, Ubuntu 20.04]
- **Browser (if applicable):** [e.g., Chrome 100.0, Firefox 98.0]
## Reproduction Details
**Confirmation:**
- [ ] I have read and followed all the instructions provided in the README.md.
- [ ] I am on the latest version of both Open WebUI and Ollama.
- [ ] I have included the browser console logs.
- [ ] I have included the Docker container logs.
- [ ] I have provided the exact steps to reproduce the bug in the "Steps to Reproduce" section below.
## Expected Behavior:
[Describe what you expected to happen.]
## Actual Behavior:
[Describe what actually happened.]
## Description
**Bug Summary:**
[Provide a brief but clear summary of the bug]
## Reproduction Details
**Steps to Reproduce:**
[Outline the steps to reproduce the bug. Be as detailed as possible.]
## Logs and Screenshots
@@ -47,13 +54,9 @@ assignees: ''
**Docker Container Logs:**
[Include relevant Docker container logs, if applicable]
**Screenshots (if applicable):**
**Screenshots/Screen Recordings (if applicable):**
[Attach any relevant screenshots to help illustrate the issue]
## Installation Method
[Describe the method you used to install the project, e.g., manual installation, Docker, package manager, etc.]
## Additional Information
[Include any additional details that may help in understanding and reproducing the issue. This could include specific configurations, error messages, or anything else relevant to the bug.]

View File

@@ -3,9 +3,10 @@ updates:
- package-ecosystem: pip
directory: '/backend'
schedule:
interval: weekly
interval: monthly
target-branch: 'dev'
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
# Check for updates to GitHub Actions every week
interval: 'weekly'
interval: monthly

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

View File

@@ -10,61 +10,63 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for changes in package.json
run: |
git diff --cached --diff-filter=d package.json || {
echo "No changes to package.json"
exit 1
}
- name: Get version number from package.json
id: get_version
run: |
VERSION=$(jq -r '.version' package.json)
echo "::set-output name=version::$VERSION"
- name: Check for changes in package.json
run: |
git diff --cached --diff-filter=d package.json || {
echo "No changes to package.json"
exit 1
}
- name: Extract latest CHANGELOG entry
id: changelog
run: |
CHANGELOG_CONTENT=$(awk 'BEGIN {print_section=0;} /^## \[/ {if (print_section == 0) {print_section=1;} else {exit;}} print_section {print;}' CHANGELOG.md)
CHANGELOG_ESCAPED=$(echo "$CHANGELOG_CONTENT" | sed ':a;N;$!ba;s/\n/%0A/g')
echo "Extracted latest release notes from CHANGELOG.md:"
echo -e "$CHANGELOG_CONTENT"
echo "::set-output name=content::$CHANGELOG_ESCAPED"
- name: Get version number from package.json
id: get_version
run: |
VERSION=$(jq -r '.version' package.json)
echo "::set-output name=version::$VERSION"
- name: Create GitHub release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const changelog = `${{ steps.changelog.outputs.content }}`;
const release = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: `v${{ steps.get_version.outputs.version }}`,
name: `v${{ steps.get_version.outputs.version }}`,
body: changelog,
})
console.log(`Created release ${release.data.html_url}`)
- name: Extract latest CHANGELOG entry
id: changelog
run: |
CHANGELOG_CONTENT=$(awk 'BEGIN {print_section=0;} /^## \[/ {if (print_section == 0) {print_section=1;} else {exit;}} print_section {print;}' CHANGELOG.md)
CHANGELOG_ESCAPED=$(echo "$CHANGELOG_CONTENT" | sed ':a;N;$!ba;s/\n/%0A/g')
echo "Extracted latest release notes from CHANGELOG.md:"
echo -e "$CHANGELOG_CONTENT"
echo "::set-output name=content::$CHANGELOG_ESCAPED"
- name: Upload package to GitHub release
uses: actions/upload-artifact@v4
with:
name: package
path: .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create GitHub release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const changelog = `${{ steps.changelog.outputs.content }}`;
const release = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: `v${{ steps.get_version.outputs.version }}`,
name: `v${{ steps.get_version.outputs.version }}`,
body: changelog,
})
console.log(`Created release ${release.data.html_url}`)
- name: Trigger Docker build workflow
uses: actions/github-script@v7
with:
script: |
github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'docker-build.yaml',
ref: 'v${{ steps.get_version.outputs.version }}',
})
- name: Upload package to GitHub release
uses: actions/upload-artifact@v4
with:
name: package
path: |
.
!.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger Docker build workflow
uses: actions/github-script@v7
with:
script: |
github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'docker-build.yaml',
ref: 'v${{ steps.get_version.outputs.version }}',
})

View File

@@ -11,8 +11,6 @@ on:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
FULL_IMAGE_NAME: ghcr.io/${{ github.repository }}
jobs:
build-main-image:
@@ -28,6 +26,15 @@ jobs:
- linux/arm64
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Prepare
run: |
platform=${{ matrix.platform }}
@@ -70,9 +77,10 @@ jobs:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=tag
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
flavor: |
prefix=cache-${{ matrix.platform }}-
latest=false
- name: Build Docker image (latest)
uses: docker/build-push-action@v5
@@ -115,6 +123,15 @@ jobs:
- linux/arm64
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Prepare
run: |
platform=${{ matrix.platform }}
@@ -159,8 +176,10 @@ jobs:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
flavor: |
prefix=cache-cuda-${{ matrix.platform }}-
latest=false
- name: Build Docker image (cuda)
uses: docker/build-push-action@v5
@@ -204,6 +223,15 @@ jobs:
- linux/arm64
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Prepare
run: |
platform=${{ matrix.platform }}
@@ -248,8 +276,10 @@ jobs:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
flavor: |
prefix=cache-ollama-${{ matrix.platform }}-
latest=false
- name: Build Docker image (ollama)
uses: docker/build-push-action@v5
@@ -282,8 +312,17 @@ jobs:
merge-main-images:
runs-on: ubuntu-latest
needs: [ build-main-image ]
needs: [build-main-image]
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Download digests
uses: actions/download-artifact@v4
with:
@@ -325,11 +364,19 @@ jobs:
run: |
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
merge-cuda-images:
runs-on: ubuntu-latest
needs: [ build-cuda-image ]
needs: [build-cuda-image]
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Download digests
uses: actions/download-artifact@v4
with:
@@ -375,8 +422,17 @@ jobs:
merge-ollama-images:
runs-on: ubuntu-latest
needs: [ build-ollama-image ]
needs: [build-ollama-image]
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Download digests
uses: actions/download-artifact@v4
with:

View File

@@ -15,6 +15,13 @@ jobs:
name: Run Cypress Integration Tests
runs-on: ubuntu-latest
steps:
- name: Maximize build space
uses: AdityaGarg8/remove-unwanted-software@v4.1
with:
remove-android: 'true'
remove-haskell: 'true'
remove-codeql: 'true'
- name: Checkout Repository
uses: actions/checkout@v4
@@ -25,7 +32,11 @@ jobs:
--file docker-compose.api.yaml \
--file docker-compose.a1111-test.yaml \
up --detach --build
- name: Delete Docker build cache
run: |
docker builder prune --all --force
- name: Wait for Ollama to be up
timeout-minutes: 5
run: |
@@ -67,6 +78,28 @@ jobs:
path: compose-logs.txt
if-no-files-found: ignore
# pytest:
# name: Run Backend Tests
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Set up Python
# uses: actions/setup-python@v4
# with:
# python-version: ${{ matrix.python-version }}
# - name: Install dependencies
# run: |
# python -m pip install --upgrade pip
# pip install -r backend/requirements.txt
# - name: pytest run
# run: |
# ls -al
# cd backend
# PYTHONPATH=. pytest . -o log_cli=true -o log_cli_level=INFO
migration_test:
name: Run Migration Tests
runs-on: ubuntu-latest
@@ -82,18 +115,18 @@ jobs:
--health-retries 5
ports:
- 5432:5432
# mysql:
# image: mysql
# env:
# MYSQL_ROOT_PASSWORD: mysql
# MYSQL_DATABASE: mysql
# options: >-
# --health-cmd "mysqladmin ping -h localhost"
# --health-interval 10s
# --health-timeout 5s
# --health-retries 5
# ports:
# - 3306:3306
# mysql:
# image: mysql
# env:
# MYSQL_ROOT_PASSWORD: mysql
# MYSQL_DATABASE: mysql
# options: >-
# --health-cmd "mysqladmin ping -h localhost"
# --health-interval 10s
# --health-timeout 5s
# --health-retries 5
# ports:
# - 3306:3306
steps:
- name: Checkout Repository
uses: actions/checkout@v4
@@ -124,13 +157,13 @@ jobs:
GLOBAL_LOG_LEVEL: debug
run: |
cd backend
uvicorn main:app --port "8080" --forwarded-allow-ips '*' &
uvicorn open_webui.main:app --port "8080" --forwarded-allow-ips '*' &
UVICORN_PID=$!
# Wait up to 20 seconds for the server to start
for i in {1..20}; do
# Wait up to 40 seconds for the server to start
for i in {1..40}; do
curl -s http://localhost:8080/api/config > /dev/null && break
sleep 1
if [ $i -eq 20 ]; then
if [ $i -eq 40 ]; then
echo "Server failed to start"
kill -9 $UVICORN_PID
exit 1
@@ -142,7 +175,6 @@ jobs:
echo "Server has stopped"
exit 1
fi
- name: Test backend with Postgres
if: success() || steps.sqlite.conclusion == 'failure'
@@ -152,7 +184,7 @@ jobs:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
run: |
cd backend
uvicorn main:app --port "8081" --forwarded-allow-ips '*' &
uvicorn open_webui.main:app --port "8081" --forwarded-allow-ips '*' &
UVICORN_PID=$!
# Wait up to 20 seconds for the server to start
for i in {1..20}; do
@@ -171,6 +203,25 @@ jobs:
exit 1
fi
# Check that service will reconnect to postgres when connection will be closed
status_code=$(curl --write-out %{http_code} -s --output /dev/null http://localhost:8081/health/db)
if [[ "$status_code" -ne 200 ]] ; then
echo "Server has failed before postgres reconnect check"
exit 1
fi
echo "Terminating all connections to postgres..."
python -c "import os, psycopg2 as pg2; \
conn = pg2.connect(dsn=os.environ['DATABASE_URL'].replace('+pool', '')); \
cur = conn.cursor(); \
cur.execute('SELECT pg_terminate_backend(psa.pid) FROM pg_stat_activity psa WHERE datname = current_database() AND pid <> pg_backend_pid();')"
status_code=$(curl --write-out %{http_code} -s --output /dev/null http://localhost:8081/health/db)
if [[ "$status_code" -ne 200 ]] ; then
echo "Server has not reconnected to postgres after connection was closed: returned status $status_code"
exit 1
fi
# - name: Test backend with MySQL
# if: success() || steps.sqlite.conclusion == 'failure' || steps.postgres.conclusion == 'failure'
# env:
@@ -179,7 +230,7 @@ jobs:
# DATABASE_URL: mysql://root:mysql@localhost:3306/mysql
# run: |
# cd backend
# uvicorn main:app --port "8083" --forwarded-allow-ips '*' &
# uvicorn open_webui.main:app --port "8083" --forwarded-allow-ips '*' &
# UVICORN_PID=$!
# # Wait up to 20 seconds for the server to start
# for i in {1..20}; do

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- main # or whatever branch you want to use
- pypi-release
jobs:
release:

1
.gitignore vendored
View File

@@ -306,3 +306,4 @@ dist
# cypress artifacts
cypress/videos
cypress/screenshots
.vscode/settings.json

View File

@@ -5,6 +5,619 @@ 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.29] - 2023-09-25
### Fixed
- **🔧 KaTeX Rendering Improvement**: Resolved specific corner cases in KaTeX rendering to enhance the display of complex mathematical notation.
- **📞 'Call' URL Parameter Fix**: Corrected functionality for 'call' URL search parameter ensuring reliable activation of voice calls through URL triggers.
- **🔄 Configuration Reset Fix**: Fixed the RESET_CONFIG_ON_START to ensure settings revert to default correctly upon each startup, improving reliability in configuration management.
- **🌍 Filter Outlet Hook Fix**: Addressed issues in the filter outlet hook, ensuring all filter functions operate as intended.
## [0.3.28] - 2024-09-24
### Fixed
- **🔍 Web Search Functionality**: Corrected an issue where the web search option was not functioning properly.
## [0.3.27] - 2024-09-24
### Fixed
- **🔄 Periodic Cleanup Error Resolved**: Fixed a critical RuntimeError related to the 'periodic_usage_pool_cleanup' coroutine, ensuring smooth and efficient performance post-pip install, correcting a persisting issue from version 0.3.26.
- **📊 Enhanced LaTeX Rendering**: Improved rendering for LaTeX content, enhancing clarity and visual presentation in documents and mathematical models.
## [0.3.26] - 2024-09-24
### Fixed
- **🔄 Event Loop Error Resolution**: Addressed a critical error where a missing running event loop caused 'periodic_usage_pool_cleanup' to fail with pip installs. This fix ensures smoother and more reliable updates and installations, enhancing overall system stability.
## [0.3.25] - 2024-09-24
### Fixed
- **🖼️ Image Generation Functionality**: Resolved an issue where image generation was not functioning, restoring full capability for visual content creation.
- **⚖️ Rate Response Corrections**: Addressed a problem where rate responses were not working, ensuring reliable feedback mechanisms are operational.
## [0.3.24] - 2024-09-24
### Added
- **🚀 Rendering Optimization**: Significantly improved message rendering performance, enhancing user experience and webui responsiveness.
- **💖 Favorite Response Feature in Chat Overview**: Users can now mark responses as favorite directly from the chat overview, enhancing ease of retrieval and organization of preferred responses.
- **💬 Create Message Pairs with Shortcut**: Implemented creation of new message pairs using Cmd/Ctrl+Shift+Enter, making conversation editing faster and more intuitive.
- **🌍 Expanded User Prompt Variables**: Added weekday, timezone, and language information variables to user prompts to match system prompt variables.
- **🎵 Enhanced Audio Support**: Now includes support for 'audio/x-m4a' files, broadening compatibility with audio content within the platform.
- **🔏 Model URL Search Parameter**: Added an ability to select a model directly via URL parameters, streamlining navigation and model access.
- **📄 Enhanced PDF Citations**: PDF citations now open at the associated page, streamlining reference checks and document handling.
- **🔧Use of Redis in Sockets**: Enhanced socket implementation to fully support Redis, enabling effective stateless instances suitable for scalable load balancing.
- **🌍 Stream Individual Model Responses**: Allows specific models to have individualized streaming settings, enhancing performance and customization.
- **🕒 Display Model Hash and Last Modified Timestamp for Ollama Models**: Provides critical model details directly in the Models workspace for enhanced tracking.
- **❗ Update Info Notification for Admins**: Ensures administrators receive immediate updates upon login, keeping them informed of the latest changes and system statuses.
### Fixed
- **🗑️ Temporary File Handling On Windows**: Fixed an issue causing errors when accessing a temporary file being used by another process, Tools & Functions should now work as intended.
- **🔓 Authentication Toggle Issue**: Resolved the malfunction where setting 'WEBUI_AUTH=False' did not appropriately disable authentication, ensuring that user experience and system security settings function as configured.
- **🔧 Save As Copy Issue for Many Model Chats**: Resolved an error preventing users from save messages as copies in many model chats.
- **🔒 Sidebar Closure on Mobile**: Resolved an issue where the mobile sidebar remained open after menu engagement, improving user interface responsivity and comfort.
- **🛡️ Tooltip XSS Vulnerability**: Resolved a cross-site scripting (XSS) issue within tooltips, ensuring enhanced security and data integrity during user interactions.
### Changed
- **↩️ Deprecated Interface Stream Response Settings**: Moved to advanced parameters to streamline interface settings and enhance user clarity.
- **⚙️ Renamed 'speedRate' to 'playbackRate'**: Standardizes terminology, improving usability and understanding in media settings.
## [0.3.23] - 2024-09-21
### Added
- **🚀 WebSocket Redis Support**: Enhanced load balancing capabilities for multiple instance setups, promoting better performance and reliability in WebUI.
- **🔧 Adjustable Chat Controls**: Introduced width-adjustable chat controls, enabling a personalized and more comfortable user interface.
- **🌎 i18n Updates**: Improved and updated the Chinese translations.
### Fixed
- **🌐 Task Model Unloading Issue**: Modified task handling to use the Ollama /api/chat endpoint instead of OpenAI compatible endpoint, ensuring models stay loaded and ready with custom parameters, thus minimizing delays in task execution.
- **📝 Title Generation Fix for OpenAI Compatible APIs**: Resolved an issue preventing the generation of titles, enhancing consistency and reliability when using multiple API providers.
- **🗃️ RAG Duplicate Collection Issue**: Fixed a bug causing repeated processing of the same uploaded file. Now utilizes indexed files to prevent unnecessary duplications, optimizing resource usage.
- **🖼️ Image Generation Enhancement**: Refactored OpenAI image generation endpoint to be asynchronous, preventing the WebUI from becoming unresponsive during processing, thus enhancing user experience.
- **🔓 Downgrade Authlib**: Reverted Authlib to version 1.3.1 to address and resolve issues concerning OAuth functionality.
### Changed
- **🔍 Improved Message Interaction**: Enhanced the message node interface to allow for easier focus redirection with a simple click, streamlining user interaction.
- **✨ Styling Refactor**: Updated WebUI styling for a cleaner, more modern look, enhancing user experience across the platform.
## [0.3.22] - 2024-09-19
### Added
- **⭐ Chat Overview**: Introducing a node-based interactive messages diagram for improved visualization of conversation flows.
- **🔗 Multiple Vector DB Support**: Now supports multiple vector databases, including the newly added Milvus support. Community contributions for additional database support are highly encouraged!
- **📡 Experimental Non-Stream Chat Completion**: Experimental feature allowing the use of OpenAI o1 models, which do not support streaming, ensuring more versatile model deployment.
- **🔍 Experimental Colbert-AI Reranker Integration**: Added support for "jinaai/jina-colbert-v2" as a reranker, enhancing search relevance and accuracy. Note: it may not function at all on low-spec computers.
- **🕸️ ENABLE_WEBSOCKET_SUPPORT**: Added environment variable for instances to ignore websocket upgrades, stabilizing connections on platforms with websocket issues.
- **🔊 Azure Speech Service Integration**: Added support for Azure Speech services for Text-to-Speech (TTS).
- **🎚️ Customizable Playback Speed**: Playback speed control is now available in Call mode settings, allowing users to adjust audio playback speed to their preferences.
- **🧠 Enhanced Error Messaging**: System now displays helpful error messages directly to users during chat completion issues.
- **📂 Save Model as Transparent PNG**: Model profile images are now saved as PNGs, supporting transparency and improving visual integration.
- **📱 iPhone Compatibility Adjustments**: Added padding to accommodate the iPhone navigation bar, improving UI display on these devices.
- **🔗 Secure Response Headers**: Implemented security response headers, bolstering web application security.
- **🔧 Enhanced AUTOMATIC1111 Settings**: Users can now configure 'CFG Scale', 'Sampler', and 'Scheduler' parameters directly in the admin settings, enhancing workflow flexibility without source code modifications.
- **🌍 i18n Updates**: Enhanced translations for Chinese, Ukrainian, Russian, and French, fostering a better localized experience.
### Fixed
- **🛠️ Chat Message Deletion**: Resolved issues with chat message deletion, ensuring a smoother user interaction and system stability.
- **🔢 Ordered List Numbering**: Fixed the incorrect ordering in lists.
### Changed
- **🎨 Transparent Icon Handling**: Allowed model icons to be displayed on transparent backgrounds, improving UI aesthetics.
- **📝 Improved RAG Template**: Enhanced Retrieval-Augmented Generation template, optimizing context handling and error checking for more precise operation.
## [0.3.21] - 2024-09-08
### Added
- **📊 Document Count Display**: Now displays the total number of documents directly within the dashboard.
- **🚀 Ollama Embed API Endpoint**: Enabled /api/embed endpoint proxy support.
### Fixed
- **🐳 Docker Launch Issue**: Resolved the problem preventing Open-WebUI from launching correctly when using Docker.
### Changed
- **🔍 Enhanced Search Prompts**: Improved the search query generation prompts for better accuracy and user interaction, enhancing the overall search experience.
## [0.3.20] - 2024-09-07
### Added
- **🌐 Translation Update**: Updated Catalan translations to improve user experience for Catalan speakers.
### Fixed
- **📄 PDF Download**: Resolved a configuration issue with fonts directory, ensuring PDFs are now downloaded with the correct formatting.
- **🛠️ Installation of Tools & Functions Requirements**: Fixed a bug where necessary requirements for tools and functions were not properly installing.
- **🔗 Inline Image Link Rendering**: Enabled rendering of images directly from links in chat.
- **📞 Post-Call User Interface Cleanup**: Adjusted UI behavior to automatically close chat controls after a voice call ends, reducing screen clutter.
- **🎙️ Microphone Deactivation Post-Call**: Addressed an issue where the microphone remained active after calls.
- **✍️ Markdown Spacing Correction**: Corrected spacing in Markdown rendering, ensuring text appears neatly and as expected.
- **🔄 Message Re-rendering**: Fixed an issue causing all response messages to re-render with each new message, now improving chat performance.
### Changed
- **🌐 Refined Web Search Integration**: Deprecated the Search Query Generation Prompt threshold; introduced a toggle button for "Enable Web Search Query Generation" allowing users to opt-in to using web search more judiciously.
- **📝 Default Prompt Templates Update**: Emptied environment variable templates for search and title generation now default to the Open WebUI default prompt templates, simplifying configuration efforts.
## [0.3.19] - 2024-09-05
### Added
- **🌐 Translation Update**: Improved Chinese translations.
### Fixed
- **📂 DATA_DIR Overriding**: Fixed an issue to avoid overriding DATA_DIR, preventing errors when directories are set identically, ensuring smoother operation and data management.
- **🛠️ Frontmatter Extraction**: Fixed the extraction process for frontmatter in tools and functions.
### Changed
- **🎨 UI Styling**: Refined the user interface styling for enhanced visual coherence and user experience.
## [0.3.18] - 2024-09-04
### Added
- **🛠️ Direct Database Execution for Tools & Functions**: Enhanced the execution of Python files for tools and functions, now directly loading from the database for a more streamlined backend process.
### Fixed
- **🔄 Automatic Rewrite of Import Statements in Tools & Functions**: Tool and function scripts that import 'utils', 'apps', 'main', 'config' will now automatically rename these with 'open_webui.', ensuring compatibility and consistency across different modules.
- **🎨 Styling Adjustments**: Minor fixes in the visual styling to improve user experience and interface consistency.
## [0.3.17] - 2024-09-04
### Added
- **🔄 Import/Export Configuration**: Users can now import and export webui configurations from admin settings > Database, simplifying setup replication across systems.
- **🌍 Web Search via URL Parameter**: Added support for activating web search directly through URL by setting 'web-search=true'.
- **🌐 SearchApi Integration**: Added support for SearchApi as an alternative web search provider, enhancing search capabilities within the platform.
- **🔍 Literal Type Support in Tools**: Tools now support the Literal type.
- **🌍 Updated Translations**: Improved translations for Chinese, Ukrainian, and Catalan.
### Fixed
- **🔧 Pip Install Issue**: Resolved the issue where pip install failed due to missing 'alembic.ini', ensuring smoother installation processes.
- **🌃 Automatic Theme Update**: Fixed an issue where the color theme did not update dynamically with system changes.
- **🛠️ User Agent in ComfyUI**: Added default headers in ComfyUI to fix access issues, improving reliability in network communications.
- **🔄 Missing Chat Completion Response Headers**: Ensured proper return of proxied response headers during chat completion, improving API reliability.
- **🔗 Websocket Connection Prioritization**: Modified socket.io configuration to prefer websockets and more reliably fallback to polling, enhancing connection stability.
- **🎭 Accessibility Enhancements**: Added missing ARIA labels for buttons, improving accessibility for visually impaired users.
- **⚖️ Advanced Parameter**: Fixed an issue ensuring that advanced parameters are correctly applied in all scenarios, ensuring consistent behavior of user-defined settings.
### Changed
- **🔁 Namespace Reorganization**: Reorganized all Python files under the 'open_webui' namespace to streamline the project structure and improve maintainability. Tools and functions importing from 'utils' should now use 'open_webui.utils'.
- **🚧 Dependency Updates**: Updated several backend dependencies like 'aiohttp', 'authlib', 'duckduckgo-search', 'flask-cors', and 'langchain' to their latest versions, enhancing performance and security.
## [0.3.16] - 2024-08-27
### Added
- **🚀 Config DB Migration**: Migrated configuration handling from config.json to the database, enabling high-availability setups and load balancing across multiple Open WebUI instances.
- **🔗 Call Mode Activation via URL**: Added a 'call=true' URL search parameter enabling direct shortcuts to activate call mode, enhancing user interaction on mobile devices.
- **✨ TTS Content Control**: Added functionality to control how message content is segmented for Text-to-Speech (TTS) generation requests, allowing for more flexible speech output options.
- **😄 Show Knowledge Search Status**: Enhanced model usage transparency by displaying status when working with knowledge-augmented models, helping users understand the system's state during queries.
- **👆 Click-to-Copy for Codespan**: Enhanced interactive experience in the WebUI by allowing users to click to copy content from code spans directly.
- **🚫 API User Blocking via Model Filter**: Introduced the ability to block API users based on customized model filters, enhancing security and control over API access.
- **🎬 Call Overlay Styling**: Adjusted call overlay styling on large screens to not cover the entire interface, but only the chat control area, for a more unobtrusive interaction experience.
### Fixed
- **🔧 LaTeX Rendering Issue**: Addressed an issue that affected the correct rendering of LaTeX.
- **📁 File Leak Prevention**: Resolved the issue of uploaded files mistakenly being accessible across user chats.
- **🔧 Pipe Functions with '**files**' Param**: Fixed issues with '**files**' parameter not functioning correctly in pipe functions.
- **📝 Markdown Processing for RAG**: Fixed issues with processing Markdown in files.
- **🚫 Duplicate System Prompts**: Fixed bugs causing system prompts to duplicate.
### Changed
- **🔋 Wakelock Permission**: Optimized the activation of wakelock to only engage during call mode, conserving device resources and improving battery performance during idle periods.
- **🔍 Content-Type for Ollama Chats**: Added 'application/x-ndjson' content-type to '/api/chat' endpoint responses to match raw Ollama responses.
- **✋ Disable Signups Conditionally**: Implemented conditional logic to disable sign-ups when 'ENABLE_LOGIN_FORM' is set to false.
## [0.3.15] - 2024-08-21
### Added
- **🔗 Temporary Chat Activation**: Integrated a new URL parameter 'temporary-chat=true' to enable temporary chat sessions directly through the URL.
- **🌄 ComfyUI Seed Node Support**: Introduced seed node support in ComfyUI for image generation, allowing users to specify node IDs for randomized seed assignment.
### Fixed
- **🛠️ Tools and Functions**: Resolved a critical issue where Tools and Functions were not properly functioning, restoring full capability and reliability to these essential features.
- **🔘 Chat Action Button in Many Model Chat**: Fixed the malfunctioning of chat action buttons in many model chat environments, ensuring a smoother and more responsive user interaction.
- **⏪ Many Model Chat Compatibility**: Restored backward compatibility for many model chats.
## [0.3.14] - 2024-08-21
### Added
- **🛠️ Custom ComfyUI Workflow**: Deprecating several older environment variables, this enhancement introduces a new, customizable workflow for a more tailored user experience.
- **🔀 Merge Responses in Many Model Chat**: Enhances the dialogue by merging responses from multiple models into a single, coherent reply, improving the interaction quality in many model chats.
- **✅ Multiple Instances of Same Model in Chats**: Enhanced many model chat to support adding multiple instances of the same model.
- **🔧 Quick Actions in Model Workspace**: Enhanced Shift key quick actions for hiding/unhiding and deleting models, facilitating a smoother workflow.
- **🗨️ Markdown Rendering in User Messages**: User messages are now rendered in Markdown, enhancing readability and interaction.
- **💬 Temporary Chat Feature**: Introduced a temporary chat feature, deprecating the old chat history setting to enhance user interaction flexibility.
- **🖋️ User Message Editing**: Enhanced the user chat editing feature to allow saving changes without sending, providing more flexibility in message management.
- **🛡️ Security Enhancements**: Various security improvements implemented across the platform to ensure safer user experiences.
- **🌍 Updated Translations**: Enhanced translations for Chinese, Ukrainian, and Bahasa Malaysia, improving localization and user comprehension.
### Fixed
- **📑 Mermaid Rendering Issue**: Addressed issues with Mermaid chart rendering to ensure clean and clear visual data representation.
- **🎭 PWA Icon Maskability**: Fixed the Progressive Web App icon to be maskable, ensuring proper display on various device home screens.
- **🔀 Cloned Model Chat Freezing Issue**: Fixed a bug where cloning many model chats would cause freezing, enhancing stability and responsiveness.
- **🔍 Generic Error Handling and Refinements**: Various minor fixes and refinements to address previously untracked issues, ensuring smoother operations.
### Changed
- **🖼️ Image Generation Refactor**: Overhauled image generation processes for improved efficiency and quality.
- **🔨 Refactor Tool and Function Calling**: Refactored tool and function calling mechanisms for improved clarity and maintainability.
- **🌐 Backend Library Updates**: Updated critical backend libraries including SQLAlchemy, uvicorn[standard], faster-whisper, bcrypt, and boto3 for enhanced performance and security.
### Removed
- **🚫 Deprecated ComfyUI Environment Variables**: Removed several outdated environment variables related to ComfyUI settings, simplifying configuration management.
## [0.3.13] - 2024-08-14
### Added
- **🎨 Enhanced Markdown Rendering**: Significant improvements in rendering markdown, ensuring smooth and reliable display of LaTeX and Mermaid charts, enhancing user experience with more robust visual content.
- **🔄 Auto-Install Tools & Functions Python Dependencies**: For 'Tools' and 'Functions', Open WebUI now automatically install extra python requirements specified in the frontmatter, streamlining setup processes and customization.
- **🌀 OAuth Email Claim Customization**: Introduced an 'OAUTH_EMAIL_CLAIM' variable to allow customization of the default "email" claim within OAuth configurations, providing greater flexibility in authentication processes.
- **📶 Websocket Reconnection**: Enhanced reliability with the capability to automatically reconnect when a websocket is closed, ensuring consistent and stable communication.
- **🤳 Haptic Feedback on Support Devices**: Android devices now support haptic feedback for an immersive tactile experience during certain interactions.
### Fixed
- **🛠️ ComfyUI Performance Improvement**: Addressed an issue causing FastAPI to stall when ComfyUI image generation was active; now runs in a separate thread to prevent UI unresponsiveness.
- **🔀 Session Handling**: Fixed an issue mandating session_id on client-side to ensure smoother session management and transitions.
- **🖋️ Minor Bug Fixes and Format Corrections**: Various minor fixes including typo corrections, backend formatting improvements, and test amendments enhancing overall system stability and performance.
### Changed
- **🚀 Migration to SvelteKit 2**: Upgraded the underlying framework to SvelteKit version 2, offering enhanced speed, better code structure, and improved deployment capabilities.
- **🧹 General Cleanup and Refactoring**: Performed broad cleanup and refactoring across the platform, improving code efficiency and maintaining high standards of code health.
- **🚧 Integration Testing Improvements**: Modified how Cypress integration tests detect chat messages and updated sharing tests for better reliability and accuracy.
- **📁 Standardized '.safetensors' File Extension**: Renamed the '.sft' file extension to '.safetensors' for ComfyUI workflows, standardizing file formats across the platform.
### Removed
- **🗑️ Deprecated Frontend Functions**: Removed frontend functions that were migrated to backend to declutter the codebase and reduce redundancy.
## [0.3.12] - 2024-08-07
### Added
- **🔄 Sidebar Infinite Scroll**: Added an infinite scroll feature in the sidebar for more efficient chat navigation, reducing load times and enhancing user experience.
- **🚀 Enhanced Markdown Rendering**: Support for rendering all code blocks and making images clickable for preview; codespan styling is also enhanced to improve readability and user interaction.
- **🔒 Admin Shared Chat Visibility**: Admins no longer have default visibility over shared chats when ENABLE_ADMIN_CHAT_ACCESS is set to false, tightening security and privacy settings for users.
- **🌍 Language Updates**: Added Malay (Bahasa Malaysia) translation and updated Catalan and Traditional Chinese translations to improve accessibility for more users.
### Fixed
- **📊 Markdown Rendering Issues**: Resolved issues with markdown rendering to ensure consistent and correct display across components.
- **🛠️ Styling Issues**: Multiple fixes applied to styling throughout the application, improving the overall visual experience and interface consistency.
- **🗃️ Modal Handling**: Fixed an issue where modals were not closing correctly in various model chat scenarios, enhancing usability and interface reliability.
- **📄 Missing OpenAI Usage Information**: Resolved issues where usage statistics for OpenAI services were not being correctly displayed, ensuring users have access to crucial data for managing and monitoring their API consumption.
- **🔧 Non-Streaming Support for Functions Plugin**: Fixed a functionality issue with the Functions plugin where non-streaming operations were not functioning as intended, restoring full capabilities for async and sync integration within the platform.
- **🔄 Environment Variable Type Correction (COMFYUI_FLUX_FP8_CLIP)**: Corrected the data type of the 'COMFYUI_FLUX_FP8_CLIP' environment variable from string to boolean, ensuring environment settings apply correctly and enhance configuration management.
### Changed
- **🔧 Backend Dependency Updates**: Updated several backend dependencies such as boto3, pypdf, python-pptx, validators, and black, ensuring up-to-date security and performance optimizations.
## [0.3.11] - 2024-08-02
### Added
- **📊 Model Information Display**: Added visuals for model selection, including images next to model names for more intuitive navigation.
- **🗣 ElevenLabs Voice Adaptations**: Voice enhancements including support for ElevenLabs voice ID by name for personalized vocal interactions.
- **⌨️ Arrow Keys Model Selection**: Users can now use arrow keys for quicker model selection, enhancing accessibility.
- **🔍 Fuzzy Search in Model Selector**: Enhanced model selector with fuzzy search to locate models swiftly, including descriptions.
- **🕹️ ComfyUI Flux Image Generation**: Added support for the new Flux image gen model; introduces environment controls like weight precision and CLIP model options in Settings.
- **💾 Display File Size for Uploads**: Enhanced file interface now displays file size, preparing for upcoming upload restrictions.
- **🎚️ Advanced Params "Min P"**: Added 'Min P' parameter in the advanced settings for customized model precision control.
- **🔒 Enhanced OAuth**: Introduced custom redirect URI support for OAuth behind reverse proxies, enabling safer authentication processes.
- **🖥 Enhanced Latex Rendering**: Adjustments made to latex rendering processes, now accurately detecting and presenting latex inputs from text.
- **🌐 Internationalization**: Enhanced with new Romanian and updated Vietnamese and Ukrainian translations, helping broaden accessibility for international users.
### Fixed
- **🔧 Tags Handling in Document Upload**: Tags are now properly sent to the upload document handler, resolving issues with missing metadata.
- **🖥️ Sensitive Input Fields**: Corrected browser misinterpretation of secure input fields, preventing misclassification as password fields.
- **📂 Static Path Resolution in PDF Generation**: Fixed static paths that adjust dynamically to prevent issues across various environments.
### Changed
- **🎨 UI/UX Styling Enhancements**: Multiple minor styling updates for a cleaner and more intuitive user interface.
- **🚧 Refactoring Various Components**: Numerous refactoring changes across styling, file handling, and function simplifications for clarity and performance.
- **🎛️ User Valves Management**: Moved user valves from settings to direct chat controls for more user-friendly access during interactions.
### Removed
- **⚙️ Health Check Logging**: Removed verbose logging from the health checking processes to declutter logs and improve backend performance.
## [0.3.10] - 2024-07-17
### Fixed
- **🔄 Improved File Upload**: Addressed the issue where file uploads lacked animation.
- **💬 Chat Continuity**: Fixed a problem where existing chats were not functioning properly in some instances.
- **🗂️ Chat File Reset**: Resolved the issue of chat files not resetting for new conversations, now ensuring a clean slate for each chat session.
- **📁 Document Workspace Uploads**: Corrected the handling of document uploads in the workspace using the Files API.
## [0.3.9] - 2024-07-17
### Added
- **📁 Files Chat Controls**: We've reverted to the old file handling behavior where uploaded files are always included. You can now manage files directly within the chat controls section, giving you the ability to remove files as needed.
- **🔧 "Action" Function Support**: Introducing a new "Action" function to write custom buttons to the message toolbar. This feature enables more interactive messaging, with documentation coming soon.
- **📜 Citations Handling**: For newly uploaded files in documents workspace, citations will now display the actual filename. Additionally, you can click on these filenames to open the file in a new tab for easier access.
- **🛠️ Event Emitter and Call Updates**: Enhanced 'event_emitter' to allow message replacement and 'event_call' to support text input for Tools and Functions. Detailed documentation will be provided shortly.
- **🎨 Styling Refactor**: Various styling updates for a cleaner and more cohesive user interface.
- **🌐 Enhanced Translations**: Improved translations for Catalan, Ukrainian, and Brazilian Portuguese.
### Fixed
- **🔧 Chat Controls Priority**: Resolved an issue where Chat Controls values were being overridden by model information parameters. The priority is now Chat Controls, followed by Global Settings, then Model Settings.
- **🪲 Debug Logs**: Fixed an issue where debug logs were not being logged properly.
- **🔑 Automatic1111 Auth Key**: The auth key for Automatic1111 is no longer required.
- **📝 Title Generation**: Ensured that the title generation runs only once, even when multiple models are in a chat.
- **✅ Boolean Values in Params**: Added support for boolean values in parameters.
- **🖼️ Files Overlay Styling**: Fixed the styling issue with the files overlay.
### Changed
- **⬆️ Dependency Updates**
- Upgraded 'pydantic' from version 2.7.1 to 2.8.2.
- Upgraded 'sqlalchemy' from version 2.0.30 to 2.0.31.
- Upgraded 'unstructured' from version 0.14.9 to 0.14.10.
- Upgraded 'chromadb' from version 0.5.3 to 0.5.4.
## [0.3.8] - 2024-07-09
### Added
- **💬 Chat Controls**: Easily adjust parameters for each chat session, offering more precise control over your interactions.
- **📌 Pinned Chats**: Support for pinned chats, allowing you to keep important conversations easily accessible.
- **📄 Apache Tika Integration**: Added support for using Apache Tika as a document loader, enhancing document processing capabilities.
- **🛠️ Custom Environment for OpenID Claims**: Allows setting custom claims for OpenID, providing more flexibility in user authentication.
- **🔧 Enhanced Tools & Functions API**: Introduced 'event_emitter' and 'event_call', now you can also add citations for better documentation and tracking. Detailed documentation will be provided on our documentation website.
- **↔️ Sideways Scrolling in Settings**: Settings tabs container now supports horizontal scrolling for easier navigation.
- **🌑 Darker OLED Theme**: Includes a new, darker OLED theme and improved styling for the light theme, enhancing visual appeal.
- **🌐 Language Updates**: Updated translations for Indonesian, German, French, and Catalan languages, expanding accessibility.
### Fixed
- **⏰ OpenAI Streaming Timeout**: Resolved issues with OpenAI streaming response using the 'AIOHTTP_CLIENT_TIMEOUT' setting, ensuring reliable performance.
- **💡 User Valves**: Fixed malfunctioning user valves, ensuring proper functionality.
- **🔄 Collapsible Components**: Addressed issues with collapsible components not working, restoring expected behavior.
### Changed
- **🗃️ Database Backend**: Switched from Peewee to SQLAlchemy for improved concurrency support, enhancing database performance.
- **⬆️ ChromaDB Update**: Upgraded to version 0.5.3. Ensure your remote ChromaDB instance matches this version.
- **🔤 Primary Font Styling**: Updated primary font to Archivo for better visual consistency.
- **🔄 Font Change for Windows**: Replaced Arimo with Inter font for Windows users, improving readability.
- **🚀 Lazy Loading**: Implemented lazy loading for 'faster_whisper' and 'sentence_transformers' to reduce startup memory usage.
- **📋 Task Generation Payload**: Task generations now include only the "task" field in the body instead of "title".
## [0.3.7] - 2024-06-29
### Added
- **🌐 Enhanced Internationalization (i18n)**: Newly introduced Indonesian translation, and updated translations for Turkish, Chinese, and Catalan languages to improve user accessibility.
### Fixed
- **🕵️‍♂️ Browser Language Detection**: Corrected the issue where the application was not properly detecting and adapting to the browser's language settings.
- **🔐 OIDC Admin Role Assignment**: Fixed a bug where the admin role was not being assigned to the first user who signed up via OpenID Connect (OIDC).
- **💬 Chat/Completions Endpoint**: Resolved an issue where the chat/completions endpoint was non-functional when the stream option was set to False.
- **🚫 'WEBUI_AUTH' Configuration**: Addressed the problem where setting 'WEBUI_AUTH' to False was not being applied correctly.
### Changed
- **📦 Dependency Update**: Upgraded 'authlib' from version 1.3.0 to 1.3.1 to ensure better security and performance enhancements.
## [0.3.6] - 2024-06-27
### Added
- **✨ "Functions" Feature**: You can now utilize "Functions" like filters (middleware) and pipe (model) functions directly within the WebUI. While largely compatible with Pipelines, these native functions can be executed easily within Open WebUI. Example use cases for filter functions include usage monitoring, real-time translation, moderation, and automemory. For pipe functions, the scope ranges from Cohere and Anthropic integration directly within Open WebUI, enabling "Valves" for per-user OpenAI API key usage, and much more. If you encounter issues, SAFE_MODE has been introduced.
- **📁 Files API**: Compatible with OpenAI, this feature allows for custom Retrieval-Augmented Generation (RAG) in conjunction with the Filter Function. More examples will be shared on our community platform and official documentation website.
- **🛠️ Tool Enhancements**: Tools now support citations and "Valves". Documentation will be available shortly.
- **🔗 Iframe Support via Files API**: Enables rendering HTML directly into your chat interface using functions and tools. Use cases include playing games like DOOM and Snake, displaying a weather applet, and implementing Anthropic "artifacts"-like features. Stay tuned for updates on our community platform and documentation.
- **🔒 Experimental OAuth Support**: New experimental OAuth support. Check our documentation for more details.
- **🖼️ Custom Background Support**: Set a custom background from Settings > Interface to personalize your experience.
- **🔑 AUTOMATIC1111_API_AUTH Support**: Enhanced security for the AUTOMATIC1111 API.
- **🎨 Code Highlight Optimization**: Improved code highlighting features.
- **🎙️ Voice Interruption Feature**: Reintroduced and now toggleable from Settings > Interface.
- **💤 Wakelock API**: Now in use to prevent screen dimming during important tasks.
- **🔐 API Key Privacy**: All API keys are now hidden by default for better security.
- **🔍 New Web Search Provider**: Added jina_search as a new option.
- **🌐 Enhanced Internationalization (i18n)**: Improved Korean translation and updated Chinese and Ukrainian translations.
### Fixed
- **🔧 Conversation Mode Issue**: Fixed the issue where Conversation Mode remained active after being removed from settings.
- **📏 Scroll Button Obstruction**: Resolved the issue where the scrollToBottom button container obstructed clicks on buttons beneath it.
### Changed
- **⏲️ AIOHTTP_CLIENT_TIMEOUT**: Now set to 'None' by default for improved configuration flexibility.
- **📞 Voice Call Enhancements**: Improved by skipping code blocks and expressions during calls.
- **🚫 Error Message Handling**: Disabled the continuation of operations with error messages.
- **🗂️ Playground Relocation**: Moved the Playground from the workspace to the user menu for better user experience.
## [0.3.5] - 2024-06-16
### Added
- **📞 Enhanced Voice Call**: Text-to-speech (TTS) callback now operates in real-time for each sentence, reducing latency by not waiting for full completion.
- **👆 Tap to Interrupt**: During a call, you can now stop the assistant from speaking by simply tapping, instead of using voice. This resolves the issue of the speaker's voice being mistakenly registered as input.
- **😊 Emoji Call**: Toggle this feature on from the Settings > Interface, allowing LLMs to express emotions using emojis during voice calls for a more dynamic interaction.
- **🖱️ Quick Archive/Delete**: Use the Shift key + mouseover on the chat list to swiftly archive or delete items.
- **📝 Markdown Support in Model Descriptions**: You can now format model descriptions with markdown, enabling bold text, links, etc.
- **🧠 Editable Memories**: Adds the capability to modify memories.
- **📋 Admin Panel Sorting**: Introduces the ability to sort users/chats within the admin panel.
- **🌑 Dark Mode for Quick Selectors**: Dark mode now available for chat quick selectors (prompts, models, documents).
- **🔧 Advanced Parameters**: Adds 'num_keep' and 'num_batch' to advanced parameters for customization.
- **📅 Dynamic System Prompts**: New variables '{{CURRENT_DATETIME}}', '{{CURRENT_TIME}}', '{{USER_LOCATION}}' added for system prompts. Ensure '{{USER_LOCATION}}' is toggled on from Settings > Interface.
- **🌐 Tavily Web Search**: Includes Tavily as a web search provider option.
- **🖊️ Federated Auth Usernames**: Ability to set user names for federated authentication.
- **🔗 Auto Clean URLs**: When adding connection URLs, trailing slashes are now automatically removed.
- **🌐 Enhanced Translations**: Improved Chinese and Swedish translations.
### Fixed
- **⏳ AIOHTTP_CLIENT_TIMEOUT**: Introduced a new environment variable 'AIOHTTP_CLIENT_TIMEOUT' for requests to Ollama lasting longer than 5 minutes. Default is 300 seconds; set to blank ('') for no timeout.
- **❌ Message Delete Freeze**: Resolved an issue where message deletion would sometimes cause the web UI to freeze.
## [0.3.4] - 2024-06-12
### Fixed
- **🔒 Mixed Content with HTTPS Issue**: Resolved a problem where mixed content (HTTP and HTTPS) was causing security warnings and blocking resources on HTTPS sites.
- **🔍 Web Search Issue**: Addressed the problem where web search functionality was not working correctly. The 'ENABLE_RAG_LOCAL_WEB_FETCH' option has been reintroduced to restore proper web searching capabilities.
- **💾 RAG Template Not Being Saved**: Fixed an issue where the RAG template was not being saved correctly, ensuring your custom templates are now preserved as expected.
## [0.3.3] - 2024-06-12
### Added
- **🛠️ Native Python Function Calling**: Introducing native Python function calling within Open WebUI. Weve also included a built-in code editor to seamlessly develop and integrate function code within the 'Tools' workspace. With this, you can significantly enhance your LLMs capabilities by creating custom RAG pipelines, web search tools, and even agent-like features such as sending Discord messages.
- **🌐 DuckDuckGo Integration**: Added DuckDuckGo as a web search provider, giving you more search options.
- **🌏 Enhanced Translations**: Improved translations for Vietnamese and Chinese languages, making the interface more accessible.
### Fixed
- **🔗 Web Search URL Error Handling**: Fixed the issue where a single URL error would disrupt the data loading process in Web Search mode. Now, such errors will be handled gracefully to ensure uninterrupted data loading.
- **🖥️ Frontend Responsiveness**: Resolved the problem where the frontend would stop responding if the backend encounters an error while downloading a model. Improved error handling to maintain frontend stability.
- **🔧 Dependency Issues in pip**: Fixed issues related to pip installations, ensuring all dependencies are correctly managed to prevent installation errors.
## [0.3.2] - 2024-06-10
### Added
- **🔍 Web Search Query Status**: The web search query will now persist in the results section to aid in easier debugging and tracking of search queries.
- **🌐 New Web Search Provider**: We have added Serply as a new option for web search providers, giving you more choices for your search needs.
- **🌏 Improved Translations**: We've enhanced translations for Chinese and Portuguese.
### Fixed
- **🎤 Audio File Upload Issue**: The bug that prevented audio files from being uploaded in chat input has been fixed, ensuring smooth communication.
- **💬 Message Input Handling**: Improved the handling of message inputs by instantly clearing images and text after sending, along with immediate visual indications when a response message is loading, enhancing user feedback.
- **⚙️ Parameter Registration and Validation**: Fixed the issue where parameters were not registering in certain cases and addressed the problem where users were unable to save due to invalid input errors.
## [0.3.1] - 2024-06-09
### Fixed
- **💬 Chat Functionality**: Resolved the issue where chat functionality was not working for specific models.
## [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
- **👤 Improved Account Pending Page**: The account pending page now displays admin details by default to avoid confusion. You can disable this feature in the admin settings if needed.
- **🌐 HTTP Proxy Support**: We have enabled the use of the 'http_proxy' environment variable in OpenAI and Ollama API calls, making it easier to configure network settings.
- **❓ Quick Access to Documentation**: You can now easily access Open WebUI documents via a question mark button located at the bottom right corner of the screen (available on larger screens like PCs).
- **🌍 Enhanced Translation**: Improvements have been made to translations.
### Fixed
- **🔍 SearxNG Web Search**: Fixed the issue where the SearxNG web search functionality was not working properly.
## [0.2.3] - 2024-06-03
### Added
- **📁 Export Chat as JSON**: You can now export individual chats as JSON files from the navbar menu by navigating to 'Download > Export Chat'. This makes sharing specific conversations easier.
- **✏️ Edit Titles with Double Click**: Double-click on titles to rename them quickly and efficiently.
- **🧩 Batch Multiple Embeddings**: Introduced 'RAG_EMBEDDING_OPENAI_BATCH_SIZE' to process multiple embeddings in a batch, enhancing performance for large datasets.
- **🌍 Improved Translations**: Enhanced the translation quality across various languages for a better user experience.
### Fixed
- **🛠️ Modelfile Migration Script**: Fixed an issue where the modelfile migration script would fail if an invalid modelfile was encountered.
- **💬 Zhuyin Input Method on Mac**: Resolved an issue where using the Zhuyin input method in the Web UI on a Mac caused text to send immediately upon pressing the enter key, leading to incorrect input.
- **🔊 Local TTS Voice Selection**: Fixed the issue where the selected local Text-to-Speech (TTS) voice was not being displayed in settings.
## [0.2.2] - 2024-06-02
### Added
- **🌊 Mermaid Rendering Support**: We've included support for Mermaid rendering. This allows you to create beautiful diagrams and flowcharts directly within Open WebUI.
- **🔄 New Environment Variable 'RESET_CONFIG_ON_START'**: Introducing a new environment variable: 'RESET_CONFIG_ON_START'. Set this variable to reset your configuration settings upon starting the application, making it easier to revert to default settings.
### Fixed
- **🔧 Pipelines Filter Issue**: We've addressed an issue with the pipelines where filters were not functioning as expected.
## [0.2.1] - 2024-06-02
### Added

View File

@@ -74,6 +74,10 @@ ENV RAG_EMBEDDING_MODEL="$USE_EMBEDDING_MODEL_DOCKER" \
## Hugging Face download cache ##
ENV HF_HOME="/app/backend/data/cache/embedding/models"
## Torch Extensions ##
# ENV TORCH_EXTENSIONS_DIR="/.cache/torch_extensions"
#### Other models ##########################################################
WORKDIR /app/backend
@@ -96,7 +100,8 @@ RUN chown -R $UID:$GID /app $HOME
RUN if [ "$USE_OLLAMA" = "true" ]; then \
apt-get update && \
# Install pandoc and netcat
apt-get install -y --no-install-recommends pandoc netcat-openbsd curl && \
apt-get install -y --no-install-recommends git build-essential pandoc netcat-openbsd curl && \
apt-get install -y --no-install-recommends gcc python3-dev && \
# for RAG OCR
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
# install helper tools
@@ -107,8 +112,9 @@ RUN if [ "$USE_OLLAMA" = "true" ]; then \
rm -rf /var/lib/apt/lists/*; \
else \
apt-get update && \
# Install pandoc and netcat
apt-get install -y --no-install-recommends pandoc netcat-openbsd curl jq && \
# Install pandoc, netcat and gcc
apt-get install -y --no-install-recommends git build-essential pandoc gcc netcat-openbsd curl jq && \
apt-get install -y --no-install-recommends gcc python3-dev && \
# for RAG OCR
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
# cleanup
@@ -149,11 +155,12 @@ COPY --chown=$UID:$GID ./backend .
EXPOSE 8080
HEALTHCHECK CMD curl --silent --fail http://localhost:8080/health | jq -e '.status == true' || exit 1
HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq -ne 'input.status == true' || exit 1
USER $UID:$GID
ARG BUILD_HASH
ENV WEBUI_BUILD_VERSION=${BUILD_HASH}
ENV DOCKER true
CMD [ "bash", "start.sh"]

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)
@@ -21,7 +21,7 @@ Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI d
- 🤝 **Ollama/OpenAI API Integration**: Effortlessly integrate OpenAI-compatible APIs for versatile conversations alongside Ollama models. Customize the OpenAI API URL to link with **LMStudio, GroqCloud, Mistral, OpenRouter, and more**.
- 🧩 **Pipelines, Open WebUI Plugin Support**: Seamlessly integrate custom logic and Python libraries into Open WebUI using [Pipelines Plugin Framework](https://github.com/open-webui/pipelines). Launch your Pipelines instance, set the OpenAI URL to the Pipelines URL, and explore endless possibilities. [Examples](https://github.com/open-webui/pipelines/examples) include **Function Calling**, User **Rate Limiting** to control access, **Usage Monitoring** with tools like Langfuse, **Live Translation with LibreTranslate** for multilingual support, **Toxic Message Filtering** and much more.
- 🧩 **Pipelines, Open WebUI Plugin Support**: Seamlessly integrate custom logic and Python libraries into Open WebUI using [Pipelines Plugin Framework](https://github.com/open-webui/pipelines). Launch your Pipelines instance, set the OpenAI URL to the Pipelines URL, and explore endless possibilities. [Examples](https://github.com/open-webui/pipelines/tree/main/examples) include **Function Calling**, User **Rate Limiting** to control access, **Usage Monitoring** with tools like Langfuse, **Live Translation with LibreTranslate** for multilingual support, **Toxic Message Filtering** and much more.
- 📱 **Responsive Design**: Enjoy a seamless experience across Desktop PC, Laptop, and Mobile devices.
@@ -29,11 +29,15 @@ Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI d
- ✒️🔢 **Full Markdown and LaTeX Support**: Elevate your LLM experience with comprehensive Markdown and LaTeX capabilities for enriched interaction.
- 🎤📹 **Hands-Free Voice/Video Call**: Experience seamless communication with integrated hands-free voice and video call features, allowing for a more dynamic and interactive chat environment.
- 🛠️ **Model Builder**: Easily create Ollama models via the Web UI. Create and add custom characters/agents, customize chat elements, and import models effortlessly through [Open WebUI Community](https://openwebui.com/) integration.
- 🐍 **Native Python Function Calling Tool**: Enhance your LLMs with built-in code editor support in the tools workspace. Bring Your Own Function (BYOF) by simply adding your pure Python functions, enabling seamless integration with LLMs.
- 📚 **Local RAG Integration**: Dive into the future of chat interactions with groundbreaking Retrieval Augmented Generation (RAG) support. This feature seamlessly integrates document interactions into your chat experience. You can load documents directly into the chat or add files to your document library, effortlessly accessing them using the `#` command before a query.
- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, and `serper`, and inject the results directly into your chat experience.
- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, `serper`, `Serply`, `DuckDuckGo`, `TavilySearch` and `SearchApi` and inject the results directly into your chat experience.
- 🌐 **Web Browsing Capability**: Seamlessly integrate websites into your chat experience using the `#` command followed by a URL. This feature allows you to incorporate web content directly into your conversations, enhancing the richness and depth of your interactions.
@@ -55,11 +59,31 @@ Don't forget to explore our sibling project, [Open WebUI Community](https://open
## How to Install 🚀
> [!NOTE]
> Please note that for certain Docker environments, additional configurations might be needed. If you encounter any connection issues, our detailed guide on [Open WebUI Documentation](https://docs.openwebui.com/) is ready to assist you.
### Installation via Python pip 🐍
Open WebUI can be installed using pip, the Python package installer. Before proceeding, ensure you're using **Python 3.11** to avoid compatibility issues.
1. **Install Open WebUI**:
Open your terminal and run the following command to install Open WebUI:
```bash
pip install open-webui
```
2. **Running Open WebUI**:
After installation, you can start Open WebUI by executing:
```bash
open-webui serve
```
This will start the Open WebUI server, which you can access at [http://localhost:8080](http://localhost:8080)
### Quick Start with Docker 🐳
> [!NOTE]
> Please note that for certain Docker environments, additional configurations might be needed. If you encounter any connection issues, our detailed guide on [Open WebUI Documentation](https://docs.openwebui.com/) is ready to assist you.
> [!WARNING]
> When using Docker to install Open WebUI, make sure to include the `-v open-webui:/app/backend/data` in your Docker command. This step is crucial as it ensures your database is properly mounted and prevents any loss of data.
@@ -146,10 +170,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 --add-host=host.docker.internal:host-gateway --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/).

View File

@@ -18,6 +18,10 @@ If you're experiencing connection issues, its often due to the WebUI docker c
docker run -d --network=host -v open-webui:/app/backend/data -e OLLAMA_BASE_URL=http://127.0.0.1:11434 --name open-webui --restart always ghcr.io/open-webui/open-webui:main
```
### Error on Slow Reponses for Ollama
Open WebUI has a default timeout of 5 minutes for Ollama to finish generating the response. If needed, this can be adjusted via the environment variable AIOHTTP_CLIENT_TIMEOUT, which sets the timeout in seconds.
### General Connection Errors
**Ensure Ollama Version is Up-to-Date**: Always start by checking that you have the latest version of Ollama. Visit [Ollama's official site](https://ollama.com/) for the latest updates.

6
backend/.gitignore vendored
View File

@@ -8,9 +8,5 @@ _test
Pipfile
!/data
/data/*
!/data/litellm
/data/litellm/*
!data/litellm/config.yaml
!data/config.json
/open_webui/data/*
.webui_secret_key

View File

@@ -1,226 +0,0 @@
import os
import logging
from fastapi import (
FastAPI,
Request,
Depends,
HTTPException,
status,
UploadFile,
File,
Form,
)
from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware
from faster_whisper import WhisperModel
from pydantic import BaseModel
import requests
import hashlib
from pathlib import Path
import json
from constants import ERROR_MESSAGES
from utils.utils import (
decode_token,
get_current_user,
get_verified_user,
get_admin_user,
)
from utils.misc import calculate_sha256
from config import (
SRC_LOG_LEVELS,
CACHE_DIR,
UPLOAD_DIR,
WHISPER_MODEL,
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,
AppConfig,
)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["AUDIO"])
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
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
# setting device type for whisper model
whisper_device_type = DEVICE_TYPE if DEVICE_TYPE and DEVICE_TYPE == "cuda" else "cpu"
log.info(f"whisper_device_type: {whisper_device_type}")
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
@app.get("/config")
async def get_openai_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,
}
@app.post("/config/update")
async def update_openai_config(
form_data: OpenAIConfigUpdateForm, user=Depends(get_admin_user)
):
if form_data.key == "":
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.API_KEY_NOT_FOUND)
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
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,
}
@app.post("/speech")
async def speech(request: Request, user=Depends(get_verified_user)):
body = await request.body()
name = hashlib.sha256(body).hexdigest()
file_path = SPEECH_CACHE_DIR.joinpath(f"{name}.mp3")
file_body_path = SPEECH_CACHE_DIR.joinpath(f"{name}.json")
# Check if the file already exists in the cache
if file_path.is_file():
return FileResponse(file_path)
headers = {}
headers["Authorization"] = f"Bearer {app.state.config.OPENAI_API_KEY}"
headers["Content-Type"] = "application/json"
r = None
try:
r = requests.post(
url=f"{app.state.config.OPENAI_API_BASE_URL}/audio/speech",
data=body,
headers=headers,
stream=True,
)
r.raise_for_status()
# Save the streaming content to a file
with open(file_path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
with open(file_body_path, "w") as f:
json.dump(json.loads(body.decode("utf-8")), f)
# Return the saved file
return FileResponse(file_path)
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,
)
@app.post("/transcriptions")
def transcribe(
file: UploadFile = File(...),
user=Depends(get_current_user),
):
log.info(f"file.content_type: {file.content_type}")
if file.content_type not in ["audio/mpeg", "audio/wav"]:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.FILE_NOT_SUPPORTED,
)
try:
filename = file.filename
file_path = f"{UPLOAD_DIR}/{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,
}
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"
)
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)])
return {"text": transcript.strip()}
except Exception as e:
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(e),
)

View File

@@ -1,527 +0,0 @@
import re
import requests
from fastapi import (
FastAPI,
Request,
Depends,
HTTPException,
status,
UploadFile,
File,
Form,
)
from fastapi.middleware.cors import CORSMiddleware
from faster_whisper import WhisperModel
from constants import ERROR_MESSAGES
from utils.utils import (
get_current_user,
get_admin_user,
)
from apps.images.utils.comfyui import ImageGenerationPayload, comfyui_generate_image
from utils.misc import calculate_sha256
from typing import Optional
from pydantic import BaseModel
from pathlib import Path
import mimetypes
import uuid
import base64
import json
import logging
from config import (
SRC_LOG_LEVELS,
CACHE_DIR,
IMAGE_GENERATION_ENGINE,
ENABLE_IMAGE_GENERATION,
AUTOMATIC1111_BASE_URL,
COMFYUI_BASE_URL,
IMAGES_OPENAI_API_BASE_URL,
IMAGES_OPENAI_API_KEY,
IMAGE_GENERATION_MODEL,
IMAGE_SIZE,
IMAGE_STEPS,
AppConfig,
)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["IMAGES"])
IMAGE_CACHE_DIR = Path(CACHE_DIR).joinpath("./image/generations/")
IMAGE_CACHE_DIR.mkdir(parents=True, exist_ok=True)
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.state.config = AppConfig()
app.state.config.ENGINE = IMAGE_GENERATION_ENGINE
app.state.config.ENABLED = ENABLE_IMAGE_GENERATION
app.state.config.OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL
app.state.config.OPENAI_API_KEY = IMAGES_OPENAI_API_KEY
app.state.config.MODEL = IMAGE_GENERATION_MODEL
app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
app.state.config.IMAGE_SIZE = IMAGE_SIZE
app.state.config.IMAGE_STEPS = IMAGE_STEPS
@app.get("/config")
async def get_config(request: Request, user=Depends(get_admin_user)):
return {
"engine": app.state.config.ENGINE,
"enabled": app.state.config.ENABLED,
}
class ConfigUpdateForm(BaseModel):
engine: str
enabled: bool
@app.post("/config/update")
async def update_config(form_data: ConfigUpdateForm, user=Depends(get_admin_user)):
app.state.config.ENGINE = form_data.engine
app.state.config.ENABLED = form_data.enabled
return {
"engine": app.state.config.ENGINE,
"enabled": app.state.config.ENABLED,
}
class EngineUrlUpdateForm(BaseModel):
AUTOMATIC1111_BASE_URL: Optional[str] = None
COMFYUI_BASE_URL: Optional[str] = None
@app.get("/url")
async def get_engine_url(user=Depends(get_admin_user)):
return {
"AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL,
"COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL,
}
@app.post("/url/update")
async def update_engine_url(
form_data: EngineUrlUpdateForm, user=Depends(get_admin_user)
):
if form_data.AUTOMATIC1111_BASE_URL == None:
app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
else:
url = form_data.AUTOMATIC1111_BASE_URL.strip("/")
try:
r = requests.head(url)
app.state.config.AUTOMATIC1111_BASE_URL = url
except Exception as e:
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
if form_data.COMFYUI_BASE_URL == None:
app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
else:
url = form_data.COMFYUI_BASE_URL.strip("/")
try:
r = requests.head(url)
app.state.config.COMFYUI_BASE_URL = url
except Exception as e:
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
return {
"AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL,
"COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL,
"status": True,
}
class OpenAIConfigUpdateForm(BaseModel):
url: str
key: str
@app.get("/openai/config")
async def get_openai_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,
}
@app.post("/openai/config/update")
async def update_openai_config(
form_data: OpenAIConfigUpdateForm, user=Depends(get_admin_user)
):
if form_data.key == "":
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.API_KEY_NOT_FOUND)
app.state.config.OPENAI_API_BASE_URL = form_data.url
app.state.config.OPENAI_API_KEY = form_data.key
return {
"status": True,
"OPENAI_API_BASE_URL": app.state.config.OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.OPENAI_API_KEY,
}
class ImageSizeUpdateForm(BaseModel):
size: str
@app.get("/size")
async def get_image_size(user=Depends(get_admin_user)):
return {"IMAGE_SIZE": app.state.config.IMAGE_SIZE}
@app.post("/size/update")
async def update_image_size(
form_data: ImageSizeUpdateForm, user=Depends(get_admin_user)
):
pattern = r"^\d+x\d+$" # Regular expression pattern
if re.match(pattern, form_data.size):
app.state.config.IMAGE_SIZE = form_data.size
return {
"IMAGE_SIZE": app.state.config.IMAGE_SIZE,
"status": True,
}
else:
raise HTTPException(
status_code=400,
detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 512x512)."),
)
class ImageStepsUpdateForm(BaseModel):
steps: int
@app.get("/steps")
async def get_image_size(user=Depends(get_admin_user)):
return {"IMAGE_STEPS": app.state.config.IMAGE_STEPS}
@app.post("/steps/update")
async def update_image_size(
form_data: ImageStepsUpdateForm, user=Depends(get_admin_user)
):
if form_data.steps >= 0:
app.state.config.IMAGE_STEPS = form_data.steps
return {
"IMAGE_STEPS": app.state.config.IMAGE_STEPS,
"status": True,
}
else:
raise HTTPException(
status_code=400,
detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 50)."),
)
@app.get("/models")
def get_models(user=Depends(get_current_user)):
try:
if app.state.config.ENGINE == "openai":
return [
{"id": "dall-e-2", "name": "DALL·E 2"},
{"id": "dall-e-3", "name": "DALL·E 3"},
]
elif app.state.config.ENGINE == "comfyui":
r = requests.get(url=f"{app.state.config.COMFYUI_BASE_URL}/object_info")
info = r.json()
return list(
map(
lambda model: {"id": model, "name": model},
info["CheckpointLoaderSimple"]["input"]["required"]["ckpt_name"][0],
)
)
else:
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models"
)
models = r.json()
return list(
map(
lambda model: {"id": model["title"], "name": model["model_name"]},
models,
)
)
except Exception as e:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
@app.get("/models/default")
async def get_default_model(user=Depends(get_admin_user)):
try:
if app.state.config.ENGINE == "openai":
return {
"model": (
app.state.config.MODEL if app.state.config.MODEL else "dall-e-2"
)
}
elif app.state.config.ENGINE == "comfyui":
return {"model": (app.state.config.MODEL if app.state.config.MODEL else "")}
else:
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options"
)
options = r.json()
return {"model": options["sd_model_checkpoint"]}
except Exception as e:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
class UpdateModelForm(BaseModel):
model: str
def set_model_handler(model: str):
if app.state.config.ENGINE in ["openai", "comfyui"]:
app.state.config.MODEL = model
return app.state.config.MODEL
else:
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options"
)
options = r.json()
if model != options["sd_model_checkpoint"]:
options["sd_model_checkpoint"] = model
r = requests.post(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options",
json=options,
)
return options
@app.post("/models/default/update")
def update_default_model(
form_data: UpdateModelForm,
user=Depends(get_current_user),
):
return set_model_handler(form_data.model)
class GenerateImageForm(BaseModel):
model: Optional[str] = None
prompt: str
n: int = 1
size: Optional[str] = None
negative_prompt: Optional[str] = None
def save_b64_image(b64_str):
try:
image_id = str(uuid.uuid4())
if "," in b64_str:
header, encoded = b64_str.split(",", 1)
mime_type = header.split(";")[0]
img_data = base64.b64decode(encoded)
image_format = mimetypes.guess_extension(mime_type)
image_filename = f"{image_id}{image_format}"
file_path = IMAGE_CACHE_DIR / f"{image_filename}"
with open(file_path, "wb") as f:
f.write(img_data)
return image_filename
else:
image_filename = f"{image_id}.png"
file_path = IMAGE_CACHE_DIR.joinpath(image_filename)
img_data = base64.b64decode(b64_str)
# Write the image data to a file
with open(file_path, "wb") as f:
f.write(img_data)
return image_filename
except Exception as e:
log.exception(f"Error saving image: {e}")
return None
def save_url_image(url):
image_id = str(uuid.uuid4())
try:
r = requests.get(url)
r.raise_for_status()
if r.headers["content-type"].split("/")[0] == "image":
mime_type = r.headers["content-type"]
image_format = mimetypes.guess_extension(mime_type)
if not image_format:
raise ValueError("Could not determine image type from MIME type")
image_filename = f"{image_id}{image_format}"
file_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}")
with open(file_path, "wb") as image_file:
for chunk in r.iter_content(chunk_size=8192):
image_file.write(chunk)
return image_filename
else:
log.error(f"Url does not point to an image.")
return None
except Exception as e:
log.exception(f"Error saving image: {e}")
return None
@app.post("/generations")
def generate_image(
form_data: GenerateImageForm,
user=Depends(get_current_user),
):
width, height = tuple(map(int, app.state.config.IMAGE_SIZE.split("x")))
r = None
try:
if app.state.config.ENGINE == "openai":
headers = {}
headers["Authorization"] = f"Bearer {app.state.config.OPENAI_API_KEY}"
headers["Content-Type"] = "application/json"
data = {
"model": (
app.state.config.MODEL
if app.state.config.MODEL != ""
else "dall-e-2"
),
"prompt": form_data.prompt,
"n": form_data.n,
"size": (
form_data.size if form_data.size else app.state.config.IMAGE_SIZE
),
"response_format": "b64_json",
}
r = requests.post(
url=f"{app.state.config.OPENAI_API_BASE_URL}/images/generations",
json=data,
headers=headers,
)
r.raise_for_status()
res = r.json()
images = []
for image in res["data"]:
image_filename = save_b64_image(image["b64_json"])
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump(data, f)
return images
elif app.state.config.ENGINE == "comfyui":
data = {
"prompt": form_data.prompt,
"width": width,
"height": height,
"n": form_data.n,
}
if app.state.config.IMAGE_STEPS is not None:
data["steps"] = app.state.config.IMAGE_STEPS
if form_data.negative_prompt is not None:
data["negative_prompt"] = form_data.negative_prompt
data = ImageGenerationPayload(**data)
res = comfyui_generate_image(
app.state.config.MODEL,
data,
user.id,
app.state.config.COMFYUI_BASE_URL,
)
log.debug(f"res: {res}")
images = []
for image in res["data"]:
image_filename = save_url_image(image["url"])
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump(data.model_dump(exclude_none=True), f)
log.debug(f"images: {images}")
return images
else:
if form_data.model:
set_model_handler(form_data.model)
data = {
"prompt": form_data.prompt,
"batch_size": form_data.n,
"width": width,
"height": height,
}
if app.state.config.IMAGE_STEPS is not None:
data["steps"] = app.state.config.IMAGE_STEPS
if form_data.negative_prompt is not None:
data["negative_prompt"] = form_data.negative_prompt
r = requests.post(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/txt2img",
json=data,
)
res = r.json()
log.debug(f"res: {res}")
images = []
for image in res["images"]:
image_filename = save_b64_image(image)
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump({**data, "info": res["info"]}, f)
return images
except Exception as e:
error = e
if r != None:
data = r.json()
if "error" in data:
error = data["error"]["message"]
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(error))

View File

@@ -1,234 +0,0 @@
import websocket # NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
import uuid
import json
import urllib.request
import urllib.parse
import random
import logging
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["COMFYUI"])
from pydantic import BaseModel
from typing import Optional
COMFYUI_DEFAULT_PROMPT = """
{
"3": {
"inputs": {
"seed": 0,
"steps": 20,
"cfg": 8,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1,
"model": [
"4",
0
],
"positive": [
"6",
0
],
"negative": [
"7",
0
],
"latent_image": [
"5",
0
]
},
"class_type": "KSampler",
"_meta": {
"title": "KSampler"
}
},
"4": {
"inputs": {
"ckpt_name": "model.safetensors"
},
"class_type": "CheckpointLoaderSimple",
"_meta": {
"title": "Load Checkpoint"
}
},
"5": {
"inputs": {
"width": 512,
"height": 512,
"batch_size": 1
},
"class_type": "EmptyLatentImage",
"_meta": {
"title": "Empty Latent Image"
}
},
"6": {
"inputs": {
"text": "Prompt",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"7": {
"inputs": {
"text": "Negative Prompt",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"8": {
"inputs": {
"samples": [
"3",
0
],
"vae": [
"4",
2
]
},
"class_type": "VAEDecode",
"_meta": {
"title": "VAE Decode"
}
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage",
"_meta": {
"title": "Save Image"
}
}
}
"""
def queue_prompt(prompt, client_id, base_url):
log.info("queue_prompt")
p = {"prompt": prompt, "client_id": client_id}
data = json.dumps(p).encode("utf-8")
req = urllib.request.Request(f"{base_url}/prompt", data=data)
return json.loads(urllib.request.urlopen(req).read())
def get_image(filename, subfolder, folder_type, base_url):
log.info("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
with urllib.request.urlopen(f"{base_url}/view?{url_values}") as response:
return response.read()
def get_image_url(filename, subfolder, folder_type, base_url):
log.info("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
return f"{base_url}/view?{url_values}"
def get_history(prompt_id, base_url):
log.info("get_history")
with urllib.request.urlopen(f"{base_url}/history/{prompt_id}") as response:
return json.loads(response.read())
def get_images(ws, prompt, client_id, base_url):
prompt_id = queue_prompt(prompt, client_id, base_url)["prompt_id"]
output_images = []
while True:
out = ws.recv()
if isinstance(out, str):
message = json.loads(out)
if message["type"] == "executing":
data = message["data"]
if data["node"] is None and data["prompt_id"] == prompt_id:
break # Execution is done
else:
continue # previews are binary data
history = get_history(prompt_id, base_url)[prompt_id]
for o in history["outputs"]:
for node_id in history["outputs"]:
node_output = history["outputs"][node_id]
if "images" in node_output:
for image in node_output["images"]:
url = get_image_url(
image["filename"], image["subfolder"], image["type"], base_url
)
output_images.append({"url": url})
return {"data": output_images}
class ImageGenerationPayload(BaseModel):
prompt: str
negative_prompt: Optional[str] = ""
steps: Optional[int] = None
seed: Optional[int] = None
width: int
height: int
n: int = 1
def comfyui_generate_image(
model: str, payload: ImageGenerationPayload, client_id, base_url
):
ws_url = base_url.replace("http://", "ws://").replace("https://", "wss://")
comfyui_prompt = json.loads(COMFYUI_DEFAULT_PROMPT)
comfyui_prompt["4"]["inputs"]["ckpt_name"] = model
comfyui_prompt["5"]["inputs"]["batch_size"] = payload.n
comfyui_prompt["5"]["inputs"]["width"] = payload.width
comfyui_prompt["5"]["inputs"]["height"] = payload.height
# set the text prompt for our positive CLIPTextEncode
comfyui_prompt["6"]["inputs"]["text"] = payload.prompt
comfyui_prompt["7"]["inputs"]["text"] = payload.negative_prompt
if payload.steps:
comfyui_prompt["3"]["inputs"]["steps"] = payload.steps
comfyui_prompt["3"]["inputs"]["seed"] = (
payload.seed if payload.seed else random.randint(0, 18446744073709551614)
)
try:
ws = websocket.WebSocket()
ws.connect(f"{ws_url}/ws?clientId={client_id}")
log.info("WebSocket connection established.")
except Exception as e:
log.exception(f"Failed to connect to WebSocket server: {e}")
return None
try:
images = get_images(ws, comfyui_prompt, client_id, base_url)
except Exception as e:
log.exception(f"Error while receiving images: {e}")
images = None
ws.close()
return images

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
from typing import Optional
from pydantic import BaseModel
class SearchResult(BaseModel):
link: str
title: Optional[str]
snippet: Optional[str]

View File

@@ -1,44 +0,0 @@
import logging
import requests
from apps.rag.search.main import SearchResult
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_searxng(query_url: str, query: str, count: int) -> list[SearchResult]:
"""Search a SearXNG instance for a query and return the results as a list of SearchResult objects.
Args:
query_url (str): The URL of the SearXNG instance to search. Must contain "<query>" as a placeholder
query (str): The query to search for
"""
url = query_url.replace("<query>", query)
if "&format=json" not in url:
url += "&format=json"
log.debug(f"searching {url}")
r = requests.get(
url,
headers={
"User-Agent": "Open WebUI (https://github.com/open-webui/open-webui) RAG Bot",
"Accept": "text/html",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.5",
"Connection": "keep-alive",
},
)
r.raise_for_status()
json_response = r.json()
results = json_response.get("results", [])
sorted_results = sorted(results, key=lambda x: x.get("score", 0), reverse=True)
return [
SearchResult(
link=result["url"], title=result.get("title"), snippet=result.get("content")
)
for result in sorted_results[:count]
]

View File

@@ -1,39 +0,0 @@
import json
from peewee import *
from peewee_migrate import Router
from playhouse.db_url import connect
from config import SRC_LOG_LEVELS, DATA_DIR, DATABASE_URL, BACKEND_DIR
import os
import logging
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["DB"])
class JSONField(TextField):
def db_value(self, value):
return json.dumps(value)
def python_value(self, value):
if value is not None:
return json.loads(value)
# Check if the file exists
if os.path.exists(f"{DATA_DIR}/ollama.db"):
# Rename the file
os.rename(f"{DATA_DIR}/ollama.db", f"{DATA_DIR}/webui.db")
log.info("Database migrated from Ollama-WebUI successfully.")
else:
pass
DB = connect(DATABASE_URL)
log.info(f"Connected to a {DB.__class__.__name__} database.")
router = Router(
DB,
migrate_dir=BACKEND_DIR / "apps" / "webui" / "internal" / "migrations",
logger=log,
)
router.run()
DB.connect(reuse_if_open=True)

View File

@@ -1,21 +0,0 @@
# Database Migrations
This directory contains all the database migrations for the web app.
Migrations are done using the [`peewee-migrate`](https://github.com/klen/peewee_migrate) library.
Migrations are automatically ran at app startup.
## Creating a migration
Have you made a change to the schema of an existing model?
You will need to create a migration file to ensure that existing databases are updated for backwards compatibility.
1. Have a database file (`webui.db`) that has the old schema prior to any of your changes.
2. Make your changes to the models.
3. From the `backend` directory, run the following command:
```bash
pw_migrate create --auto --auto-source apps.webui.models --database sqlite:///${SQLITE_DB} --directory apps/web/internal/migrations ${MIGRATION_NAME}
```
- `$SQLITE_DB` should be the path to the database file.
- `$MIGRATION_NAME` should be a descriptive name for the migration.
4. The migration file will be created in the `apps/web/internal/migrations` directory.

View File

@@ -1,81 +0,0 @@
from fastapi import FastAPI, Depends
from fastapi.routing import APIRoute
from fastapi.middleware.cors import CORSMiddleware
from apps.webui.routers import (
auths,
users,
chats,
documents,
models,
prompts,
configs,
memories,
utils,
)
from config import (
WEBUI_BUILD_HASH,
WEBUI_AUTH,
DEFAULT_MODELS,
DEFAULT_PROMPT_SUGGESTIONS,
DEFAULT_USER_ROLE,
ENABLE_SIGNUP,
USER_PERMISSIONS,
WEBHOOK_URL,
WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
JWT_EXPIRES_IN,
WEBUI_BANNERS,
AppConfig,
ENABLE_COMMUNITY_SHARING,
)
app = FastAPI()
origins = ["*"]
app.state.config = AppConfig()
app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP
app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN
app.state.config.DEFAULT_MODELS = DEFAULT_MODELS
app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
app.state.config.WEBHOOK_URL = WEBHOOK_URL
app.state.config.BANNERS = WEBUI_BANNERS
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
app.state.MODELS = {}
app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auths.router, prefix="/auths", tags=["auths"])
app.include_router(users.router, prefix="/users", tags=["users"])
app.include_router(chats.router, prefix="/chats", tags=["chats"])
app.include_router(documents.router, prefix="/documents", tags=["documents"])
app.include_router(models.router, prefix="/models", tags=["models"])
app.include_router(prompts.router, prefix="/prompts", tags=["prompts"])
app.include_router(memories.router, prefix="/memories", tags=["memories"])
app.include_router(configs.router, prefix="/configs", tags=["configs"])
app.include_router(utils.router, prefix="/utils", tags=["utils"])
@app.get("/")
async def get_status():
return {
"status": True,
"auth": WEBUI_AUTH,
"default_models": app.state.config.DEFAULT_MODELS,
"default_prompt_suggestions": app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
}

View File

@@ -1,346 +0,0 @@
from pydantic import BaseModel
from typing import List, Union, Optional
from peewee import *
from playhouse.shortcuts import model_to_dict
import json
import uuid
import time
from apps.webui.internal.db import DB
####################
# Chat DB Schema
####################
class Chat(Model):
id = CharField(unique=True)
user_id = CharField()
title = TextField()
chat = TextField() # Save Chat JSON as Text
created_at = BigIntegerField()
updated_at = BigIntegerField()
share_id = CharField(null=True, unique=True)
archived = BooleanField(default=False)
class Meta:
database = DB
class ChatModel(BaseModel):
id: str
user_id: str
title: str
chat: str
created_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
share_id: Optional[str] = None
archived: bool = False
####################
# Forms
####################
class ChatForm(BaseModel):
chat: dict
class ChatTitleForm(BaseModel):
title: str
class ChatResponse(BaseModel):
id: str
user_id: str
title: str
chat: dict
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
share_id: Optional[str] = None # id of the chat to be shared
archived: bool
class ChatTitleIdResponse(BaseModel):
id: str
title: str
updated_at: int
created_at: int
class ChatTable:
def __init__(self, db):
self.db = db
db.create_tables([Chat])
def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
id = str(uuid.uuid4())
chat = ChatModel(
**{
"id": id,
"user_id": user_id,
"title": (
form_data.chat["title"] if "title" in form_data.chat else "New Chat"
),
"chat": json.dumps(form_data.chat),
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
result = Chat.create(**chat.model_dump())
return chat if result else None
def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
try:
query = Chat.update(
chat=json.dumps(chat),
title=chat["title"] if "title" in chat else "New Chat",
updated_at=int(time.time()),
).where(Chat.id == id)
query.execute()
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
except:
return None
def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
# Get the existing chat to share
chat = Chat.get(Chat.id == chat_id)
# Check if the chat is already shared
if chat.share_id:
return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
# Create a new chat with the same data, but with a new ID
shared_chat = ChatModel(
**{
"id": str(uuid.uuid4()),
"user_id": f"shared-{chat_id}",
"title": chat.title,
"chat": chat.chat,
"created_at": chat.created_at,
"updated_at": int(time.time()),
}
)
shared_result = Chat.create(**shared_chat.model_dump())
# Update the original chat with the share_id
result = (
Chat.update(share_id=shared_chat.id).where(Chat.id == chat_id).execute()
)
return shared_chat if (shared_result and result) else None
def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
try:
print("update_shared_chat_by_id")
chat = Chat.get(Chat.id == chat_id)
print(chat)
query = Chat.update(
title=chat.title,
chat=chat.chat,
).where(Chat.id == chat.share_id)
query.execute()
chat = Chat.get(Chat.id == chat.share_id)
return ChatModel(**model_to_dict(chat))
except:
return None
def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
try:
query = Chat.delete().where(Chat.user_id == f"shared-{chat_id}")
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
def update_chat_share_id_by_id(
self, id: str, share_id: Optional[str]
) -> Optional[ChatModel]:
try:
query = Chat.update(
share_id=share_id,
).where(Chat.id == id)
query.execute()
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
except:
return None
def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
try:
chat = self.get_chat_by_id(id)
query = Chat.update(
archived=(not chat.archived),
).where(Chat.id == id)
query.execute()
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
except:
return None
def archive_all_chats_by_user_id(self, user_id: str) -> bool:
try:
chats = self.get_chats_by_user_id(user_id)
for chat in chats:
query = Chat.update(
archived=True,
).where(Chat.id == chat.id)
query.execute()
return True
except:
return False
def get_archived_chat_list_by_user_id(
self, user_id: str, skip: int = 0, limit: int = 50
) -> List[ChatModel]:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select()
.where(Chat.archived == True)
.where(Chat.user_id == user_id)
.order_by(Chat.updated_at.desc())
# .limit(limit)
# .offset(skip)
]
def get_chat_list_by_user_id(
self,
user_id: str,
include_archived: bool = False,
skip: int = 0,
limit: int = 50,
) -> List[ChatModel]:
if include_archived:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select()
.where(Chat.user_id == user_id)
.order_by(Chat.updated_at.desc())
# .limit(limit)
# .offset(skip)
]
else:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select()
.where(Chat.archived == False)
.where(Chat.user_id == user_id)
.order_by(Chat.updated_at.desc())
# .limit(limit)
# .offset(skip)
]
def get_chat_list_by_chat_ids(
self, chat_ids: List[str], skip: int = 0, limit: int = 50
) -> List[ChatModel]:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select()
.where(Chat.archived == False)
.where(Chat.id.in_(chat_ids))
.order_by(Chat.updated_at.desc())
]
def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
try:
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
except:
return None
def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
try:
chat = Chat.get(Chat.share_id == id)
if chat:
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
else:
return None
except:
return None
def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
try:
chat = Chat.get(Chat.id == id, Chat.user_id == user_id)
return ChatModel(**model_to_dict(chat))
except:
return None
def get_chats(self, skip: int = 0, limit: int = 50) -> List[ChatModel]:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select().order_by(Chat.updated_at.desc())
# .limit(limit).offset(skip)
]
def get_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
return [
ChatModel(**model_to_dict(chat))
for chat in Chat.select()
.where(Chat.user_id == user_id)
.order_by(Chat.updated_at.desc())
# .limit(limit).offset(skip)
]
def delete_chat_by_id(self, id: str) -> bool:
try:
query = Chat.delete().where((Chat.id == id))
query.execute() # Remove the rows, return number of rows removed.
return True and self.delete_shared_chat_by_chat_id(id)
except:
return False
def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
try:
query = Chat.delete().where((Chat.id == id) & (Chat.user_id == user_id))
query.execute() # Remove the rows, return number of rows removed.
return True and self.delete_shared_chat_by_chat_id(id)
except:
return False
def delete_chats_by_user_id(self, user_id: str) -> bool:
try:
self.delete_shared_chats_by_user_id(user_id)
query = Chat.delete().where(Chat.user_id == user_id)
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
try:
shared_chat_ids = [
f"shared-{chat.id}"
for chat in Chat.select().where(Chat.user_id == user_id)
]
query = Chat.delete().where(Chat.user_id << shared_chat_ids)
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
Chats = ChatTable(DB)

View File

@@ -1,160 +0,0 @@
from pydantic import BaseModel
from peewee import *
from playhouse.shortcuts import model_to_dict
from typing import List, Union, Optional
import time
import logging
from utils.utils import decode_token
from utils.misc import get_gravatar_url
from apps.webui.internal.db import DB
import json
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Documents DB Schema
####################
class Document(Model):
collection_name = CharField(unique=True)
name = CharField(unique=True)
title = TextField()
filename = TextField()
content = TextField(null=True)
user_id = CharField()
timestamp = BigIntegerField()
class Meta:
database = DB
class DocumentModel(BaseModel):
collection_name: str
name: str
title: str
filename: str
content: Optional[str] = None
user_id: str
timestamp: int # timestamp in epoch
####################
# Forms
####################
class DocumentResponse(BaseModel):
collection_name: str
name: str
title: str
filename: str
content: Optional[dict] = None
user_id: str
timestamp: int # timestamp in epoch
class DocumentUpdateForm(BaseModel):
name: str
title: str
class DocumentForm(DocumentUpdateForm):
collection_name: str
filename: str
content: Optional[str] = None
class DocumentsTable:
def __init__(self, db):
self.db = db
self.db.create_tables([Document])
def insert_new_doc(
self, user_id: str, form_data: DocumentForm
) -> Optional[DocumentModel]:
document = DocumentModel(
**{
**form_data.model_dump(),
"user_id": user_id,
"timestamp": int(time.time()),
}
)
try:
result = Document.create(**document.model_dump())
if result:
return document
else:
return None
except:
return None
def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
try:
document = Document.get(Document.name == name)
return DocumentModel(**model_to_dict(document))
except:
return None
def get_docs(self) -> List[DocumentModel]:
return [
DocumentModel(**model_to_dict(doc))
for doc in Document.select()
# .limit(limit).offset(skip)
]
def update_doc_by_name(
self, name: str, form_data: DocumentUpdateForm
) -> Optional[DocumentModel]:
try:
query = Document.update(
title=form_data.title,
name=form_data.name,
timestamp=int(time.time()),
).where(Document.name == name)
query.execute()
doc = Document.get(Document.name == form_data.name)
return DocumentModel(**model_to_dict(doc))
except Exception as e:
log.exception(e)
return None
def update_doc_content_by_name(
self, name: str, updated: dict
) -> Optional[DocumentModel]:
try:
doc = self.get_doc_by_name(name)
doc_content = json.loads(doc.content if doc.content else "{}")
doc_content = {**doc_content, **updated}
query = Document.update(
content=json.dumps(doc_content),
timestamp=int(time.time()),
).where(Document.name == name)
query.execute()
doc = Document.get(Document.name == name)
return DocumentModel(**model_to_dict(doc))
except Exception as e:
log.exception(e)
return None
def delete_doc_by_name(self, name: str) -> bool:
try:
query = Document.delete().where((Document.name == name))
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
Documents = DocumentsTable(DB)

View File

@@ -1,118 +0,0 @@
from pydantic import BaseModel
from peewee import *
from playhouse.shortcuts import model_to_dict
from typing import List, Union, Optional
from apps.webui.internal.db import DB
from apps.webui.models.chats import Chats
import time
import uuid
####################
# Memory DB Schema
####################
class Memory(Model):
id = CharField(unique=True)
user_id = CharField()
content = TextField()
updated_at = BigIntegerField()
created_at = BigIntegerField()
class Meta:
database = DB
class MemoryModel(BaseModel):
id: str
user_id: str
content: str
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
####################
# Forms
####################
class MemoriesTable:
def __init__(self, db):
self.db = db
self.db.create_tables([Memory])
def insert_new_memory(
self,
user_id: str,
content: str,
) -> Optional[MemoryModel]:
id = str(uuid.uuid4())
memory = MemoryModel(
**{
"id": id,
"user_id": user_id,
"content": content,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
result = Memory.create(**memory.model_dump())
if result:
return memory
else:
return None
def get_memories(self) -> List[MemoryModel]:
try:
memories = Memory.select()
return [MemoryModel(**model_to_dict(memory)) for memory in memories]
except:
return None
def get_memories_by_user_id(self, user_id: str) -> List[MemoryModel]:
try:
memories = Memory.select().where(Memory.user_id == user_id)
return [MemoryModel(**model_to_dict(memory)) for memory in memories]
except:
return None
def get_memory_by_id(self, id) -> Optional[MemoryModel]:
try:
memory = Memory.get(Memory.id == id)
return MemoryModel(**model_to_dict(memory))
except:
return None
def delete_memory_by_id(self, id: str) -> bool:
try:
query = Memory.delete().where(Memory.id == id)
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
def delete_memories_by_user_id(self, user_id: str) -> bool:
try:
query = Memory.delete().where(Memory.user_id == user_id)
query.execute()
return True
except:
return False
def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
try:
query = Memory.delete().where(Memory.id == id, Memory.user_id == user_id)
query.execute()
return True
except:
return False
Memories = MemoriesTable(DB)

View File

@@ -1,118 +0,0 @@
from pydantic import BaseModel
from peewee import *
from playhouse.shortcuts import model_to_dict
from typing import List, Union, Optional
import time
from utils.utils import decode_token
from utils.misc import get_gravatar_url
from apps.webui.internal.db import DB
import json
####################
# Prompts DB Schema
####################
class Prompt(Model):
command = CharField(unique=True)
user_id = CharField()
title = TextField()
content = TextField()
timestamp = BigIntegerField()
class Meta:
database = DB
class PromptModel(BaseModel):
command: str
user_id: str
title: str
content: str
timestamp: int # timestamp in epoch
####################
# Forms
####################
class PromptForm(BaseModel):
command: str
title: str
content: str
class PromptsTable:
def __init__(self, db):
self.db = db
self.db.create_tables([Prompt])
def insert_new_prompt(
self, user_id: str, form_data: PromptForm
) -> Optional[PromptModel]:
prompt = PromptModel(
**{
"user_id": user_id,
"command": form_data.command,
"title": form_data.title,
"content": form_data.content,
"timestamp": int(time.time()),
}
)
try:
result = Prompt.create(**prompt.model_dump())
if result:
return prompt
else:
return None
except:
return None
def get_prompt_by_command(self, command: str) -> Optional[PromptModel]:
try:
prompt = Prompt.get(Prompt.command == command)
return PromptModel(**model_to_dict(prompt))
except:
return None
def get_prompts(self) -> List[PromptModel]:
return [
PromptModel(**model_to_dict(prompt))
for prompt in Prompt.select()
# .limit(limit).offset(skip)
]
def update_prompt_by_command(
self, command: str, form_data: PromptForm
) -> Optional[PromptModel]:
try:
query = Prompt.update(
title=form_data.title,
content=form_data.content,
timestamp=int(time.time()),
).where(Prompt.command == command)
query.execute()
prompt = Prompt.get(Prompt.command == command)
return PromptModel(**model_to_dict(prompt))
except:
return None
def delete_prompt_by_command(self, command: str) -> bool:
try:
query = Prompt.delete().where((Prompt.command == command))
query.execute() # Remove the rows, return number of rows removed.
return True
except:
return False
Prompts = PromptsTable(DB)

View File

@@ -1,237 +0,0 @@
from pydantic import BaseModel
from typing import List, Union, Optional
from peewee import *
from playhouse.shortcuts import model_to_dict
import json
import uuid
import time
import logging
from apps.webui.internal.db import DB
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Tag DB Schema
####################
class Tag(Model):
id = CharField(unique=True)
name = CharField()
user_id = CharField()
data = TextField(null=True)
class Meta:
database = DB
class ChatIdTag(Model):
id = CharField(unique=True)
tag_name = CharField()
chat_id = CharField()
user_id = CharField()
timestamp = BigIntegerField()
class Meta:
database = DB
class TagModel(BaseModel):
id: str
name: str
user_id: str
data: Optional[str] = None
class ChatIdTagModel(BaseModel):
id: str
tag_name: str
chat_id: str
user_id: str
timestamp: int
####################
# Forms
####################
class ChatIdTagForm(BaseModel):
tag_name: str
chat_id: str
class TagChatIdsResponse(BaseModel):
chat_ids: List[str]
class ChatTagsResponse(BaseModel):
tags: List[str]
class TagTable:
def __init__(self, db):
self.db = db
db.create_tables([Tag, ChatIdTag])
def insert_new_tag(self, name: str, user_id: str) -> Optional[TagModel]:
id = str(uuid.uuid4())
tag = TagModel(**{"id": id, "user_id": user_id, "name": name})
try:
result = Tag.create(**tag.model_dump())
if result:
return tag
else:
return None
except Exception as e:
return None
def get_tag_by_name_and_user_id(
self, name: str, user_id: str
) -> Optional[TagModel]:
try:
tag = Tag.get(Tag.name == name, Tag.user_id == user_id)
return TagModel(**model_to_dict(tag))
except Exception as e:
return None
def add_tag_to_chat(
self, user_id: str, form_data: ChatIdTagForm
) -> Optional[ChatIdTagModel]:
tag = self.get_tag_by_name_and_user_id(form_data.tag_name, user_id)
if tag == None:
tag = self.insert_new_tag(form_data.tag_name, user_id)
id = str(uuid.uuid4())
chatIdTag = ChatIdTagModel(
**{
"id": id,
"user_id": user_id,
"chat_id": form_data.chat_id,
"tag_name": tag.name,
"timestamp": int(time.time()),
}
)
try:
result = ChatIdTag.create(**chatIdTag.model_dump())
if result:
return chatIdTag
else:
return None
except:
return None
def get_tags_by_user_id(self, user_id: str) -> List[TagModel]:
tag_names = [
ChatIdTagModel(**model_to_dict(chat_id_tag)).tag_name
for chat_id_tag in ChatIdTag.select()
.where(ChatIdTag.user_id == user_id)
.order_by(ChatIdTag.timestamp.desc())
]
return [
TagModel(**model_to_dict(tag))
for tag in Tag.select()
.where(Tag.user_id == user_id)
.where(Tag.name.in_(tag_names))
]
def get_tags_by_chat_id_and_user_id(
self, chat_id: str, user_id: str
) -> List[TagModel]:
tag_names = [
ChatIdTagModel(**model_to_dict(chat_id_tag)).tag_name
for chat_id_tag in ChatIdTag.select()
.where((ChatIdTag.user_id == user_id) & (ChatIdTag.chat_id == chat_id))
.order_by(ChatIdTag.timestamp.desc())
]
return [
TagModel(**model_to_dict(tag))
for tag in Tag.select()
.where(Tag.user_id == user_id)
.where(Tag.name.in_(tag_names))
]
def get_chat_ids_by_tag_name_and_user_id(
self, tag_name: str, user_id: str
) -> Optional[ChatIdTagModel]:
return [
ChatIdTagModel(**model_to_dict(chat_id_tag))
for chat_id_tag in ChatIdTag.select()
.where((ChatIdTag.user_id == user_id) & (ChatIdTag.tag_name == tag_name))
.order_by(ChatIdTag.timestamp.desc())
]
def count_chat_ids_by_tag_name_and_user_id(
self, tag_name: str, user_id: str
) -> int:
return (
ChatIdTag.select()
.where((ChatIdTag.tag_name == tag_name) & (ChatIdTag.user_id == user_id))
.count()
)
def delete_tag_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> bool:
try:
query = ChatIdTag.delete().where(
(ChatIdTag.tag_name == tag_name) & (ChatIdTag.user_id == user_id)
)
res = query.execute() # Remove the rows, return number of rows removed.
log.debug(f"res: {res}")
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
if tag_count == 0:
# Remove tag item from Tag col as well
query = Tag.delete().where(
(Tag.name == tag_name) & (Tag.user_id == user_id)
)
query.execute() # Remove the rows, return number of rows removed.
return True
except Exception as e:
log.error(f"delete_tag: {e}")
return False
def delete_tag_by_tag_name_and_chat_id_and_user_id(
self, tag_name: str, chat_id: str, user_id: str
) -> bool:
try:
query = ChatIdTag.delete().where(
(ChatIdTag.tag_name == tag_name)
& (ChatIdTag.chat_id == chat_id)
& (ChatIdTag.user_id == user_id)
)
res = query.execute() # Remove the rows, return number of rows removed.
log.debug(f"res: {res}")
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
if tag_count == 0:
# Remove tag item from Tag col as well
query = Tag.delete().where(
(Tag.name == tag_name) & (Tag.user_id == user_id)
)
query.execute() # Remove the rows, return number of rows removed.
return True
except Exception as e:
log.error(f"delete_tag: {e}")
return False
def delete_tags_by_chat_id_and_user_id(self, chat_id: str, user_id: str) -> bool:
tags = self.get_tags_by_chat_id_and_user_id(chat_id, user_id)
for tag in tags:
self.delete_tag_by_tag_name_and_chat_id_and_user_id(
tag.tag_name, chat_id, user_id
)
return True
Tags = TagTable(DB)

View File

@@ -1,218 +0,0 @@
from pydantic import BaseModel, ConfigDict
from peewee import *
from playhouse.shortcuts import model_to_dict
from typing import List, Union, Optional
import time
from utils.misc import get_gravatar_url
from apps.webui.internal.db import DB, JSONField
from apps.webui.models.chats import Chats
####################
# User DB Schema
####################
class User(Model):
id = CharField(unique=True)
name = CharField()
email = CharField()
role = CharField()
profile_image_url = TextField()
last_active_at = BigIntegerField()
updated_at = BigIntegerField()
created_at = BigIntegerField()
api_key = CharField(null=True, unique=True)
settings = JSONField(null=True)
class Meta:
database = DB
class UserSettings(BaseModel):
ui: Optional[dict] = {}
model_config = ConfigDict(extra="allow")
pass
class UserModel(BaseModel):
id: str
name: str
email: str
role: str = "pending"
profile_image_url: str
last_active_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
api_key: Optional[str] = None
settings: Optional[UserSettings] = None
####################
# Forms
####################
class UserRoleUpdateForm(BaseModel):
id: str
role: str
class UserUpdateForm(BaseModel):
name: str
email: str
profile_image_url: str
password: Optional[str] = None
class UsersTable:
def __init__(self, db):
self.db = db
self.db.create_tables([User])
def insert_new_user(
self,
id: str,
name: str,
email: str,
profile_image_url: str = "/user.png",
role: str = "pending",
) -> Optional[UserModel]:
user = UserModel(
**{
"id": id,
"name": name,
"email": email,
"role": role,
"profile_image_url": profile_image_url,
"last_active_at": int(time.time()),
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
result = User.create(**user.model_dump())
if result:
return user
else:
return None
def get_user_by_id(self, id: str) -> Optional[UserModel]:
try:
user = User.get(User.id == id)
return UserModel(**model_to_dict(user))
except:
return None
def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
try:
user = User.get(User.api_key == api_key)
return UserModel(**model_to_dict(user))
except:
return None
def get_user_by_email(self, email: str) -> Optional[UserModel]:
try:
user = User.get(User.email == email)
return UserModel(**model_to_dict(user))
except:
return None
def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
return [
UserModel(**model_to_dict(user))
for user in User.select()
# .limit(limit).offset(skip)
]
def get_num_users(self) -> Optional[int]:
return User.select().count()
def get_first_user(self) -> UserModel:
try:
user = User.select().order_by(User.created_at).first()
return UserModel(**model_to_dict(user))
except:
return None
def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
try:
query = User.update(role=role).where(User.id == id)
query.execute()
user = User.get(User.id == id)
return UserModel(**model_to_dict(user))
except:
return None
def update_user_profile_image_url_by_id(
self, id: str, profile_image_url: str
) -> Optional[UserModel]:
try:
query = User.update(profile_image_url=profile_image_url).where(
User.id == id
)
query.execute()
user = User.get(User.id == id)
return UserModel(**model_to_dict(user))
except:
return None
def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
try:
query = User.update(last_active_at=int(time.time())).where(User.id == id)
query.execute()
user = User.get(User.id == id)
return UserModel(**model_to_dict(user))
except:
return None
def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
try:
query = User.update(**updated).where(User.id == id)
query.execute()
user = User.get(User.id == id)
return UserModel(**model_to_dict(user))
except:
return None
def delete_user_by_id(self, id: str) -> bool:
try:
# Delete User Chats
result = Chats.delete_chats_by_user_id(id)
if result:
# Delete User
query = User.delete().where(User.id == id)
query.execute() # Remove the rows, return number of rows removed.
return True
else:
return False
except:
return False
def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
try:
query = User.update(api_key=api_key).where(User.id == id)
result = query.execute()
return True if result == 1 else False
except:
return False
def get_user_api_key_by_id(self, id: str) -> Optional[str]:
try:
user = User.get(User.id == id)
return user.api_key
except:
return None
Users = UsersTable(DB)

View File

@@ -1,145 +0,0 @@
from fastapi import Response, Request
from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta
from typing import List, Union, Optional
from fastapi import APIRouter
from pydantic import BaseModel
import logging
from apps.webui.models.memories import Memories, MemoryModel
from utils.utils import get_verified_user
from constants import ERROR_MESSAGES
from config import SRC_LOG_LEVELS, CHROMA_CLIENT
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
router = APIRouter()
@router.get("/ef")
async def get_embeddings(request: Request):
return {"result": request.app.state.EMBEDDING_FUNCTION("hello world")}
############################
# GetMemories
############################
@router.get("/", response_model=List[MemoryModel])
async def get_memories(user=Depends(get_verified_user)):
return Memories.get_memories_by_user_id(user.id)
############################
# AddMemory
############################
class AddMemoryForm(BaseModel):
content: str
@router.post("/add", response_model=Optional[MemoryModel])
async def add_memory(
request: Request, form_data: AddMemoryForm, user=Depends(get_verified_user)
):
memory = Memories.insert_new_memory(user.id, form_data.content)
memory_embedding = request.app.state.EMBEDDING_FUNCTION(memory.content)
collection = CHROMA_CLIENT.get_or_create_collection(name=f"user-memory-{user.id}")
collection.upsert(
documents=[memory.content],
ids=[memory.id],
embeddings=[memory_embedding],
metadatas=[{"created_at": memory.created_at}],
)
return memory
############################
# QueryMemory
############################
class QueryMemoryForm(BaseModel):
content: str
@router.post("/query")
async def query_memory(
request: Request, form_data: QueryMemoryForm, user=Depends(get_verified_user)
):
query_embedding = request.app.state.EMBEDDING_FUNCTION(form_data.content)
collection = CHROMA_CLIENT.get_or_create_collection(name=f"user-memory-{user.id}")
results = collection.query(
query_embeddings=[query_embedding],
n_results=1, # how many results to return
)
return results
############################
# ResetMemoryFromVectorDB
############################
@router.get("/reset", response_model=bool)
async def reset_memory_from_vector_db(
request: Request, user=Depends(get_verified_user)
):
CHROMA_CLIENT.delete_collection(f"user-memory-{user.id}")
collection = CHROMA_CLIENT.get_or_create_collection(name=f"user-memory-{user.id}")
memories = Memories.get_memories_by_user_id(user.id)
for memory in memories:
memory_embedding = request.app.state.EMBEDDING_FUNCTION(memory.content)
collection.upsert(
documents=[memory.content],
ids=[memory.id],
embeddings=[memory_embedding],
)
return True
############################
# DeleteMemoriesByUserId
############################
@router.delete("/user", response_model=bool)
async def delete_memory_by_user_id(user=Depends(get_verified_user)):
result = Memories.delete_memories_by_user_id(user.id)
if result:
try:
CHROMA_CLIENT.delete_collection(f"user-memory-{user.id}")
except Exception as e:
log.error(e)
return True
return False
############################
# DeleteMemoryById
############################
@router.delete("/{memory_id}", response_model=bool)
async def delete_memory_by_id(memory_id: str, user=Depends(get_verified_user)):
result = Memories.delete_memory_by_id_and_user_id(memory_id, user.id)
if result:
collection = CHROMA_CLIENT.get_or_create_collection(
name=f"user-memory-{user.id}"
)
collection.delete(ids=[memory_id])
return True
return False

View File

@@ -1,931 +0,0 @@
import os
import sys
import logging
import importlib.metadata
import pkgutil
import chromadb
from chromadb import Settings
from base64 import b64encode
from bs4 import BeautifulSoup
from typing import TypeVar, Generic, Union
from pydantic import BaseModel
from typing import Optional
from pathlib import Path
import json
import yaml
import markdown
import requests
import shutil
from secrets import token_bytes
from constants import ERROR_MESSAGES
####################################
# Load .env file
####################################
BACKEND_DIR = Path(__file__).parent # the path containing this file
BASE_DIR = BACKEND_DIR.parent # the path containing the backend/
print(BASE_DIR)
try:
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv(str(BASE_DIR / ".env")))
except ImportError:
print("dotenv not installed, skipping...")
####################################
# LOGGING
####################################
log_levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]
GLOBAL_LOG_LEVEL = os.environ.get("GLOBAL_LOG_LEVEL", "").upper()
if GLOBAL_LOG_LEVEL in log_levels:
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL, force=True)
else:
GLOBAL_LOG_LEVEL = "INFO"
log = logging.getLogger(__name__)
log.info(f"GLOBAL_LOG_LEVEL: {GLOBAL_LOG_LEVEL}")
log_sources = [
"AUDIO",
"COMFYUI",
"CONFIG",
"DB",
"IMAGES",
"MAIN",
"MODELS",
"OLLAMA",
"OPENAI",
"RAG",
"WEBHOOK",
]
SRC_LOG_LEVELS = {}
for source in log_sources:
log_env_var = source + "_LOG_LEVEL"
SRC_LOG_LEVELS[source] = os.environ.get(log_env_var, "").upper()
if SRC_LOG_LEVELS[source] not in log_levels:
SRC_LOG_LEVELS[source] = GLOBAL_LOG_LEVEL
log.info(f"{log_env_var}: {SRC_LOG_LEVELS[source]}")
log.setLevel(SRC_LOG_LEVELS["CONFIG"])
WEBUI_NAME = os.environ.get("WEBUI_NAME", "Open WebUI")
if WEBUI_NAME != "Open WebUI":
WEBUI_NAME += " (Open WebUI)"
WEBUI_URL = os.environ.get("WEBUI_URL", "http://localhost:3000")
WEBUI_FAVICON_URL = "https://openwebui.com/favicon.png"
####################################
# ENV (dev,test,prod)
####################################
ENV = os.environ.get("ENV", "dev")
try:
PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
except:
try:
PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
except importlib.metadata.PackageNotFoundError:
PACKAGE_DATA = {"version": "0.0.0"}
VERSION = PACKAGE_DATA["version"]
# Function to parse each section
def parse_section(section):
items = []
for li in section.find_all("li"):
# Extract raw HTML string
raw_html = str(li)
# Extract text without HTML tags
text = li.get_text(separator=" ", strip=True)
# Split into title and content
parts = text.split(": ", 1)
title = parts[0].strip() if len(parts) > 1 else ""
content = parts[1].strip() if len(parts) > 1 else text
items.append({"title": title, "content": content, "raw": raw_html})
return items
try:
changelog_path = BASE_DIR / "CHANGELOG.md"
with open(str(changelog_path.absolute()), "r", encoding="utf8") as file:
changelog_content = file.read()
except:
changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode()
# Convert markdown content to HTML
html_content = markdown.markdown(changelog_content)
# Parse the HTML content
soup = BeautifulSoup(html_content, "html.parser")
# Initialize JSON structure
changelog_json = {}
# Iterate over each version
for version in soup.find_all("h2"):
version_number = version.get_text().strip().split(" - ")[0][1:-1] # Remove brackets
date = version.get_text().strip().split(" - ")[1]
version_data = {"date": date}
# Find the next sibling that is a h3 tag (section title)
current = version.find_next_sibling()
while current and current.name != "h2":
if current.name == "h3":
section_title = current.get_text().lower() # e.g., "added", "fixed"
section_items = parse_section(current.find_next_sibling("ul"))
version_data[section_title] = section_items
# Move to the next element
current = current.find_next_sibling()
changelog_json[version_number] = version_data
CHANGELOG = changelog_json
####################################
# WEBUI_BUILD_HASH
####################################
WEBUI_BUILD_HASH = os.environ.get("WEBUI_BUILD_HASH", "dev-build")
####################################
# DATA/FRONTEND BUILD DIR
####################################
DATA_DIR = Path(os.getenv("DATA_DIR", BACKEND_DIR / "data")).resolve()
FRONTEND_BUILD_DIR = Path(os.getenv("FRONTEND_BUILD_DIR", BASE_DIR / "build")).resolve()
try:
CONFIG_DATA = json.loads((DATA_DIR / "config.json").read_text())
except:
CONFIG_DATA = {}
####################################
# Config helpers
####################################
def save_config():
try:
with open(f"{DATA_DIR}/config.json", "w") as f:
json.dump(CONFIG_DATA, f, indent="\t")
except Exception as e:
log.exception(e)
def get_config_value(config_path: str):
path_parts = config_path.split(".")
cur_config = CONFIG_DATA
for key in path_parts:
if key in cur_config:
cur_config = cur_config[key]
else:
return None
return cur_config
T = TypeVar("T")
class PersistentConfig(Generic[T]):
def __init__(self, env_name: str, config_path: str, env_value: T):
self.env_name = env_name
self.config_path = config_path
self.env_value = env_value
self.config_value = get_config_value(config_path)
if self.config_value is not None:
log.info(f"'{env_name}' loaded from config.json")
self.value = self.config_value
else:
self.value = env_value
def __str__(self):
return str(self.value)
@property
def __dict__(self):
raise TypeError(
"PersistentConfig object cannot be converted to dict, use config_get or .value instead."
)
def __getattribute__(self, item):
if item == "__dict__":
raise TypeError(
"PersistentConfig object cannot be converted to dict, use config_get or .value instead."
)
return super().__getattribute__(item)
def save(self):
# Don't save if the value is the same as the env value and the config value
if self.env_value == self.value:
if self.config_value == self.value:
return
log.info(f"Saving '{self.env_name}' to config.json")
path_parts = self.config_path.split(".")
config = CONFIG_DATA
for key in path_parts[:-1]:
if key not in config:
config[key] = {}
config = config[key]
config[path_parts[-1]] = self.value
save_config()
self.config_value = self.value
class AppConfig:
_state: dict[str, PersistentConfig]
def __init__(self):
super().__setattr__("_state", {})
def __setattr__(self, key, value):
if isinstance(value, PersistentConfig):
self._state[key] = value
else:
self._state[key].value = value
self._state[key].save()
def __getattr__(self, key):
return self._state[key].value
####################################
# WEBUI_AUTH (Required for security)
####################################
WEBUI_AUTH = os.environ.get("WEBUI_AUTH", "True").lower() == "true"
WEBUI_AUTH_TRUSTED_EMAIL_HEADER = os.environ.get(
"WEBUI_AUTH_TRUSTED_EMAIL_HEADER", None
)
JWT_EXPIRES_IN = PersistentConfig(
"JWT_EXPIRES_IN", "auth.jwt_expiry", os.environ.get("JWT_EXPIRES_IN", "-1")
)
####################################
# Static DIR
####################################
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")
else:
logging.warning(f"Frontend favicon not found at {frontend_favicon}")
####################################
# CUSTOM_NAME
####################################
CUSTOM_NAME = os.environ.get("CUSTOM_NAME", "")
if CUSTOM_NAME:
try:
r = requests.get(f"https://api.openwebui.com/api/v1/custom/{CUSTOM_NAME}")
data = r.json()
if r.ok:
if "logo" in data:
WEBUI_FAVICON_URL = url = (
f"https://api.openwebui.com{data['logo']}"
if data["logo"][0] == "/"
else data["logo"]
)
r = requests.get(url, stream=True)
if r.status_code == 200:
with open(f"{STATIC_DIR}/favicon.png", "wb") as f:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, f)
WEBUI_NAME = data["name"]
except Exception as e:
log.exception(e)
pass
####################################
# File Upload DIR
####################################
UPLOAD_DIR = f"{DATA_DIR}/uploads"
Path(UPLOAD_DIR).mkdir(parents=True, exist_ok=True)
####################################
# Cache DIR
####################################
CACHE_DIR = f"{DATA_DIR}/cache"
Path(CACHE_DIR).mkdir(parents=True, exist_ok=True)
####################################
# Docs DIR
####################################
DOCS_DIR = os.getenv("DOCS_DIR", f"{DATA_DIR}/docs")
Path(DOCS_DIR).mkdir(parents=True, exist_ok=True)
####################################
# LITELLM_CONFIG
####################################
def create_config_file(file_path):
directory = os.path.dirname(file_path)
# Check if directory exists, if not, create it
if not os.path.exists(directory):
os.makedirs(directory)
# Data to write into the YAML file
config_data = {
"general_settings": {},
"litellm_settings": {},
"model_list": [],
"router_settings": {},
}
# Write data to YAML file
with open(file_path, "w") as file:
yaml.dump(config_data, file)
LITELLM_CONFIG_PATH = f"{DATA_DIR}/litellm/config.yaml"
# if not os.path.exists(LITELLM_CONFIG_PATH):
# log.info("Config file doesn't exist. Creating...")
# create_config_file(LITELLM_CONFIG_PATH)
# log.info("Config file created successfully.")
####################################
# OLLAMA_BASE_URL
####################################
ENABLE_OLLAMA_API = PersistentConfig(
"ENABLE_OLLAMA_API",
"ollama.enable",
os.environ.get("ENABLE_OLLAMA_API", "True").lower() == "true",
)
OLLAMA_API_BASE_URL = os.environ.get(
"OLLAMA_API_BASE_URL", "http://localhost:11434/api"
)
OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "")
K8S_FLAG = os.environ.get("K8S_FLAG", "")
USE_OLLAMA_DOCKER = os.environ.get("USE_OLLAMA_DOCKER", "false")
if OLLAMA_BASE_URL == "" and OLLAMA_API_BASE_URL != "":
OLLAMA_BASE_URL = (
OLLAMA_API_BASE_URL[:-4]
if OLLAMA_API_BASE_URL.endswith("/api")
else OLLAMA_API_BASE_URL
)
if ENV == "prod":
if OLLAMA_BASE_URL == "/ollama" and not K8S_FLAG:
if USE_OLLAMA_DOCKER.lower() == "true":
# if you use all-in-one docker container (Open WebUI + Ollama)
# with the docker build arg USE_OLLAMA=true (--build-arg="USE_OLLAMA=true") this only works with http://localhost:11434
OLLAMA_BASE_URL = "http://localhost:11434"
else:
OLLAMA_BASE_URL = "http://host.docker.internal:11434"
elif K8S_FLAG:
OLLAMA_BASE_URL = "http://ollama-service.open-webui.svc.cluster.local:11434"
OLLAMA_BASE_URLS = os.environ.get("OLLAMA_BASE_URLS", "")
OLLAMA_BASE_URLS = OLLAMA_BASE_URLS if OLLAMA_BASE_URLS != "" else OLLAMA_BASE_URL
OLLAMA_BASE_URLS = [url.strip() for url in OLLAMA_BASE_URLS.split(";")]
OLLAMA_BASE_URLS = PersistentConfig(
"OLLAMA_BASE_URLS", "ollama.base_urls", OLLAMA_BASE_URLS
)
####################################
# OPENAI_API
####################################
ENABLE_OPENAI_API = PersistentConfig(
"ENABLE_OPENAI_API",
"openai.enable",
os.environ.get("ENABLE_OPENAI_API", "True").lower() == "true",
)
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
OPENAI_API_BASE_URL = os.environ.get("OPENAI_API_BASE_URL", "")
if OPENAI_API_BASE_URL == "":
OPENAI_API_BASE_URL = "https://api.openai.com/v1"
OPENAI_API_KEYS = os.environ.get("OPENAI_API_KEYS", "")
OPENAI_API_KEYS = OPENAI_API_KEYS if OPENAI_API_KEYS != "" else OPENAI_API_KEY
OPENAI_API_KEYS = [url.strip() for url in OPENAI_API_KEYS.split(";")]
OPENAI_API_KEYS = PersistentConfig(
"OPENAI_API_KEYS", "openai.api_keys", OPENAI_API_KEYS
)
OPENAI_API_BASE_URLS = os.environ.get("OPENAI_API_BASE_URLS", "")
OPENAI_API_BASE_URLS = (
OPENAI_API_BASE_URLS if OPENAI_API_BASE_URLS != "" else OPENAI_API_BASE_URL
)
OPENAI_API_BASE_URLS = [
url.strip() if url != "" else "https://api.openai.com/v1"
for url in OPENAI_API_BASE_URLS.split(";")
]
OPENAI_API_BASE_URLS = PersistentConfig(
"OPENAI_API_BASE_URLS", "openai.api_base_urls", OPENAI_API_BASE_URLS
)
OPENAI_API_KEY = ""
try:
OPENAI_API_KEY = OPENAI_API_KEYS.value[
OPENAI_API_BASE_URLS.value.index("https://api.openai.com/v1")
]
except:
pass
OPENAI_API_BASE_URL = "https://api.openai.com/v1"
####################################
# WEBUI
####################################
ENABLE_SIGNUP = PersistentConfig(
"ENABLE_SIGNUP",
"ui.enable_signup",
(
False
if not WEBUI_AUTH
else os.environ.get("ENABLE_SIGNUP", "True").lower() == "true"
),
)
DEFAULT_MODELS = PersistentConfig(
"DEFAULT_MODELS", "ui.default_models", os.environ.get("DEFAULT_MODELS", None)
)
DEFAULT_PROMPT_SUGGESTIONS = PersistentConfig(
"DEFAULT_PROMPT_SUGGESTIONS",
"ui.prompt_suggestions",
[
{
"title": ["Help me study", "vocabulary for a college entrance exam"],
"content": "Help me study vocabulary: write a sentence for me to fill in the blank, and I'll try to pick the correct option.",
},
{
"title": ["Give me ideas", "for what to do with my kids' art"],
"content": "What are 5 creative things I could do with my kids' art? I don't want to throw them away, but it's also so much clutter.",
},
{
"title": ["Tell me a fun fact", "about the Roman Empire"],
"content": "Tell me a random fun fact about the Roman Empire",
},
{
"title": ["Show me a code snippet", "of a website's sticky header"],
"content": "Show me a code snippet of a website's sticky header in CSS and JavaScript.",
},
{
"title": [
"Explain options trading",
"if I'm familiar with buying and selling stocks",
],
"content": "Explain options trading in simple terms if I'm familiar with buying and selling stocks.",
},
{
"title": ["Overcome procrastination", "give me tips"],
"content": "Could you start by asking me about instances when I procrastinate the most and then give me some suggestions to overcome it?",
},
],
)
DEFAULT_USER_ROLE = PersistentConfig(
"DEFAULT_USER_ROLE",
"ui.default_user_role",
os.getenv("DEFAULT_USER_ROLE", "pending"),
)
USER_PERMISSIONS_CHAT_DELETION = (
os.environ.get("USER_PERMISSIONS_CHAT_DELETION", "True").lower() == "true"
)
USER_PERMISSIONS = PersistentConfig(
"USER_PERMISSIONS",
"ui.user_permissions",
{"chat": {"deletion": USER_PERMISSIONS_CHAT_DELETION}},
)
ENABLE_MODEL_FILTER = PersistentConfig(
"ENABLE_MODEL_FILTER",
"model_filter.enable",
os.environ.get("ENABLE_MODEL_FILTER", "False").lower() == "true",
)
MODEL_FILTER_LIST = os.environ.get("MODEL_FILTER_LIST", "")
MODEL_FILTER_LIST = PersistentConfig(
"MODEL_FILTER_LIST",
"model_filter.list",
[model.strip() for model in MODEL_FILTER_LIST.split(";")],
)
WEBHOOK_URL = PersistentConfig(
"WEBHOOK_URL", "webhook_url", os.environ.get("WEBHOOK_URL", "")
)
ENABLE_ADMIN_EXPORT = os.environ.get("ENABLE_ADMIN_EXPORT", "True").lower() == "true"
ENABLE_COMMUNITY_SHARING = PersistentConfig(
"ENABLE_COMMUNITY_SHARING",
"ui.enable_community_sharing",
os.environ.get("ENABLE_COMMUNITY_SHARING", "True").lower() == "true",
)
class BannerModel(BaseModel):
id: str
type: str
title: Optional[str] = None
content: str
dismissible: bool
timestamp: int
WEBUI_BANNERS = PersistentConfig(
"WEBUI_BANNERS",
"ui.banners",
[BannerModel(**banner) for banner in json.loads("[]")],
)
####################################
# WEBUI_SECRET_KEY
####################################
WEBUI_SECRET_KEY = os.environ.get(
"WEBUI_SECRET_KEY",
os.environ.get(
"WEBUI_JWT_SECRET_KEY", "t0p-s3cr3t"
), # DEPRECATED: remove at next major version
)
if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
####################################
# RAG
####################################
CHROMA_DATA_PATH = f"{DATA_DIR}/vector_db"
CHROMA_TENANT = os.environ.get("CHROMA_TENANT", chromadb.DEFAULT_TENANT)
CHROMA_DATABASE = os.environ.get("CHROMA_DATABASE", chromadb.DEFAULT_DATABASE)
CHROMA_HTTP_HOST = os.environ.get("CHROMA_HTTP_HOST", "")
CHROMA_HTTP_PORT = int(os.environ.get("CHROMA_HTTP_PORT", "8000"))
# Comma-separated list of header=value pairs
CHROMA_HTTP_HEADERS = os.environ.get("CHROMA_HTTP_HEADERS", "")
if CHROMA_HTTP_HEADERS:
CHROMA_HTTP_HEADERS = dict(
[pair.split("=") for pair in CHROMA_HTTP_HEADERS.split(",")]
)
else:
CHROMA_HTTP_HEADERS = None
CHROMA_HTTP_SSL = os.environ.get("CHROMA_HTTP_SSL", "false").lower() == "true"
# this uses the model defined in the Dockerfile ENV variable. If you dont use docker or docker based deployments such as k8s, the default embedding model will be used (sentence-transformers/all-MiniLM-L6-v2)
RAG_TOP_K = PersistentConfig(
"RAG_TOP_K", "rag.top_k", int(os.environ.get("RAG_TOP_K", "5"))
)
RAG_RELEVANCE_THRESHOLD = PersistentConfig(
"RAG_RELEVANCE_THRESHOLD",
"rag.relevance_threshold",
float(os.environ.get("RAG_RELEVANCE_THRESHOLD", "0.0")),
)
ENABLE_RAG_HYBRID_SEARCH = PersistentConfig(
"ENABLE_RAG_HYBRID_SEARCH",
"rag.enable_hybrid_search",
os.environ.get("ENABLE_RAG_HYBRID_SEARCH", "").lower() == "true",
)
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION = PersistentConfig(
"ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION",
"rag.enable_web_loader_ssl_verification",
os.environ.get("ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION", "True").lower() == "true",
)
RAG_EMBEDDING_ENGINE = PersistentConfig(
"RAG_EMBEDDING_ENGINE",
"rag.embedding_engine",
os.environ.get("RAG_EMBEDDING_ENGINE", ""),
)
PDF_EXTRACT_IMAGES = PersistentConfig(
"PDF_EXTRACT_IMAGES",
"rag.pdf_extract_images",
os.environ.get("PDF_EXTRACT_IMAGES", "False").lower() == "true",
)
RAG_EMBEDDING_MODEL = PersistentConfig(
"RAG_EMBEDDING_MODEL",
"rag.embedding_model",
os.environ.get("RAG_EMBEDDING_MODEL", "sentence-transformers/all-MiniLM-L6-v2"),
)
log.info(f"Embedding model set: {RAG_EMBEDDING_MODEL.value}"),
RAG_EMBEDDING_MODEL_AUTO_UPDATE = (
os.environ.get("RAG_EMBEDDING_MODEL_AUTO_UPDATE", "").lower() == "true"
)
RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE = (
os.environ.get("RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE", "").lower() == "true"
)
RAG_RERANKING_MODEL = PersistentConfig(
"RAG_RERANKING_MODEL",
"rag.reranking_model",
os.environ.get("RAG_RERANKING_MODEL", ""),
)
if RAG_RERANKING_MODEL.value != "":
log.info(f"Reranking model set: {RAG_RERANKING_MODEL.value}"),
RAG_RERANKING_MODEL_AUTO_UPDATE = (
os.environ.get("RAG_RERANKING_MODEL_AUTO_UPDATE", "").lower() == "true"
)
RAG_RERANKING_MODEL_TRUST_REMOTE_CODE = (
os.environ.get("RAG_RERANKING_MODEL_TRUST_REMOTE_CODE", "").lower() == "true"
)
if CHROMA_HTTP_HOST != "":
CHROMA_CLIENT = chromadb.HttpClient(
host=CHROMA_HTTP_HOST,
port=CHROMA_HTTP_PORT,
headers=CHROMA_HTTP_HEADERS,
ssl=CHROMA_HTTP_SSL,
tenant=CHROMA_TENANT,
database=CHROMA_DATABASE,
settings=Settings(allow_reset=True, anonymized_telemetry=False),
)
else:
CHROMA_CLIENT = chromadb.PersistentClient(
path=CHROMA_DATA_PATH,
settings=Settings(allow_reset=True, anonymized_telemetry=False),
tenant=CHROMA_TENANT,
database=CHROMA_DATABASE,
)
# device type embedding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
USE_CUDA = os.environ.get("USE_CUDA_DOCKER", "false")
if USE_CUDA.lower() == "true":
DEVICE_TYPE = "cuda"
else:
DEVICE_TYPE = "cpu"
CHUNK_SIZE = PersistentConfig(
"CHUNK_SIZE", "rag.chunk_size", int(os.environ.get("CHUNK_SIZE", "1500"))
)
CHUNK_OVERLAP = PersistentConfig(
"CHUNK_OVERLAP",
"rag.chunk_overlap",
int(os.environ.get("CHUNK_OVERLAP", "100")),
)
DEFAULT_RAG_TEMPLATE = """Use the following context as your learned knowledge, inside <context></context> XML tags.
<context>
[context]
</context>
When answer to user:
- If you don't know, just say that you don't know.
- If you don't know when you are not sure, ask for clarification.
Avoid mentioning that you obtained the information from the context.
And answer according to the language of the user's question.
Given the context information, answer the query.
Query: [query]"""
RAG_TEMPLATE = PersistentConfig(
"RAG_TEMPLATE",
"rag.template",
os.environ.get("RAG_TEMPLATE", DEFAULT_RAG_TEMPLATE),
)
RAG_OPENAI_API_BASE_URL = PersistentConfig(
"RAG_OPENAI_API_BASE_URL",
"rag.openai_api_base_url",
os.getenv("RAG_OPENAI_API_BASE_URL", OPENAI_API_BASE_URL),
)
RAG_OPENAI_API_KEY = PersistentConfig(
"RAG_OPENAI_API_KEY",
"rag.openai_api_key",
os.getenv("RAG_OPENAI_API_KEY", OPENAI_API_KEY),
)
ENABLE_RAG_LOCAL_WEB_FETCH = (
os.getenv("ENABLE_RAG_LOCAL_WEB_FETCH", "False").lower() == "true"
)
YOUTUBE_LOADER_LANGUAGE = PersistentConfig(
"YOUTUBE_LOADER_LANGUAGE",
"rag.youtube_loader_language",
os.getenv("YOUTUBE_LOADER_LANGUAGE", "en").split(","),
)
ENABLE_RAG_WEB_SEARCH = PersistentConfig(
"ENABLE_RAG_WEB_SEARCH",
"rag.web.search.enable",
os.getenv("ENABLE_RAG_WEB_SEARCH", "False").lower() == "true",
)
RAG_WEB_SEARCH_ENGINE = PersistentConfig(
"RAG_WEB_SEARCH_ENGINE",
"rag.web.search.engine",
os.getenv("RAG_WEB_SEARCH_ENGINE", ""),
)
SEARXNG_QUERY_URL = PersistentConfig(
"SEARXNG_QUERY_URL",
"rag.web.search.searxng_query_url",
os.getenv("SEARXNG_QUERY_URL", ""),
)
GOOGLE_PSE_API_KEY = PersistentConfig(
"GOOGLE_PSE_API_KEY",
"rag.web.search.google_pse_api_key",
os.getenv("GOOGLE_PSE_API_KEY", ""),
)
GOOGLE_PSE_ENGINE_ID = PersistentConfig(
"GOOGLE_PSE_ENGINE_ID",
"rag.web.search.google_pse_engine_id",
os.getenv("GOOGLE_PSE_ENGINE_ID", ""),
)
BRAVE_SEARCH_API_KEY = PersistentConfig(
"BRAVE_SEARCH_API_KEY",
"rag.web.search.brave_search_api_key",
os.getenv("BRAVE_SEARCH_API_KEY", ""),
)
SERPSTACK_API_KEY = PersistentConfig(
"SERPSTACK_API_KEY",
"rag.web.search.serpstack_api_key",
os.getenv("SERPSTACK_API_KEY", ""),
)
SERPSTACK_HTTPS = PersistentConfig(
"SERPSTACK_HTTPS",
"rag.web.search.serpstack_https",
os.getenv("SERPSTACK_HTTPS", "True").lower() == "true",
)
SERPER_API_KEY = PersistentConfig(
"SERPER_API_KEY",
"rag.web.search.serper_api_key",
os.getenv("SERPER_API_KEY", ""),
)
RAG_WEB_SEARCH_RESULT_COUNT = PersistentConfig(
"RAG_WEB_SEARCH_RESULT_COUNT",
"rag.web.search.result_count",
int(os.getenv("RAG_WEB_SEARCH_RESULT_COUNT", "3")),
)
RAG_WEB_SEARCH_CONCURRENT_REQUESTS = PersistentConfig(
"RAG_WEB_SEARCH_CONCURRENT_REQUESTS",
"rag.web.search.concurrent_requests",
int(os.getenv("RAG_WEB_SEARCH_CONCURRENT_REQUESTS", "10")),
)
####################################
# Transcribe
####################################
WHISPER_MODEL = os.getenv("WHISPER_MODEL", "base")
WHISPER_MODEL_DIR = os.getenv("WHISPER_MODEL_DIR", f"{CACHE_DIR}/whisper/models")
WHISPER_MODEL_AUTO_UPDATE = (
os.environ.get("WHISPER_MODEL_AUTO_UPDATE", "").lower() == "true"
)
####################################
# Images
####################################
IMAGE_GENERATION_ENGINE = PersistentConfig(
"IMAGE_GENERATION_ENGINE",
"image_generation.engine",
os.getenv("IMAGE_GENERATION_ENGINE", ""),
)
ENABLE_IMAGE_GENERATION = PersistentConfig(
"ENABLE_IMAGE_GENERATION",
"image_generation.enable",
os.environ.get("ENABLE_IMAGE_GENERATION", "").lower() == "true",
)
AUTOMATIC1111_BASE_URL = PersistentConfig(
"AUTOMATIC1111_BASE_URL",
"image_generation.automatic1111.base_url",
os.getenv("AUTOMATIC1111_BASE_URL", ""),
)
COMFYUI_BASE_URL = PersistentConfig(
"COMFYUI_BASE_URL",
"image_generation.comfyui.base_url",
os.getenv("COMFYUI_BASE_URL", ""),
)
IMAGES_OPENAI_API_BASE_URL = PersistentConfig(
"IMAGES_OPENAI_API_BASE_URL",
"image_generation.openai.api_base_url",
os.getenv("IMAGES_OPENAI_API_BASE_URL", OPENAI_API_BASE_URL),
)
IMAGES_OPENAI_API_KEY = PersistentConfig(
"IMAGES_OPENAI_API_KEY",
"image_generation.openai.api_key",
os.getenv("IMAGES_OPENAI_API_KEY", OPENAI_API_KEY),
)
IMAGE_SIZE = PersistentConfig(
"IMAGE_SIZE", "image_generation.size", os.getenv("IMAGE_SIZE", "512x512")
)
IMAGE_STEPS = PersistentConfig(
"IMAGE_STEPS", "image_generation.steps", int(os.getenv("IMAGE_STEPS", 50))
)
IMAGE_GENERATION_MODEL = PersistentConfig(
"IMAGE_GENERATION_MODEL",
"image_generation.model",
os.getenv("IMAGE_GENERATION_MODEL", ""),
)
####################################
# 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_OPENAI_API_KEY = PersistentConfig(
"AUDIO_OPENAI_API_KEY",
"audio.openai.api_key",
os.getenv("AUDIO_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_OPENAI_API_VOICE = PersistentConfig(
"AUDIO_OPENAI_API_VOICE",
"audio.openai.api_voice",
os.getenv("AUDIO_OPENAI_API_VOICE", "alloy"),
)
####################################
# Database
####################################
DATABASE_URL = os.environ.get("DATABASE_URL", f"sqlite:///{DATA_DIR}/webui.db")

View File

@@ -1,36 +0,0 @@
{
"version": 0,
"ui": {
"default_locale": "en-US",
"prompt_suggestions": [
{
"title": ["Help me study", "vocabulary for a college entrance exam"],
"content": "Help me study vocabulary: write a sentence for me to fill in the blank, and I'll try to pick the correct option."
},
{
"title": ["Give me ideas", "for what to do with my kids' art"],
"content": "What are 5 creative things I could do with my kids' art? I don't want to throw them away, but it's also so much clutter."
},
{
"title": ["Tell me a fun fact", "about the Roman Empire"],
"content": "Tell me a random fun fact about the Roman Empire"
},
{
"title": ["Show me a code snippet", "of a website's sticky header"],
"content": "Show me a code snippet of a website's sticky header in CSS and JavaScript."
},
{
"title": ["Explain options trading", "if I'm familiar with buying and selling stocks"],
"content": "Explain options trading in simple terms if I'm familiar with buying and selling stocks."
},
{
"title": ["Overcome procrastination", "give me tips"],
"content": "Could you start by asking me about instances when I procrastinate the most and then give me some suggestions to overcome it?"
},
{
"title": ["Grammar check", "rewrite it for better readability "],
"content": "Check the following sentence for grammar and clarity: \"[sentence]\". Rewrite it for better readability while maintaining its original meaning."
}
]
}
}

View File

@@ -1,4 +0,0 @@
general_settings: {}
litellm_settings: {}
model_list: []
router_settings: {}

View File

@@ -1 +1 @@
dir for backend files (db, documents, etc.)
docker dir for backend files (db, documents, etc.)

View File

@@ -1,2 +1,2 @@
PORT="${PORT:-8080}"
uvicorn main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*' --reload
uvicorn open_webui.main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*' --reload

View File

@@ -1,973 +0,0 @@
from contextlib import asynccontextmanager
from bs4 import BeautifulSoup
import json
import markdown
import time
import os
import sys
import logging
import aiohttp
import requests
import mimetypes
from fastapi import FastAPI, Request, Depends, status
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
from fastapi import HTTPException
from fastapi.middleware.wsgi import WSGIMiddleware
from fastapi.middleware.cors import CORSMiddleware
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.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
from apps.webui.models.models import Models, ModelModel
from utils.utils import (
get_admin_user,
get_verified_user,
get_current_user,
get_http_authorization_cred,
)
from apps.rag.utils import rag_messages
from config import (
CONFIG_DATA,
WEBUI_NAME,
WEBUI_URL,
WEBUI_AUTH,
ENV,
VERSION,
CHANGELOG,
FRONTEND_BUILD_DIR,
CACHE_DIR,
STATIC_DIR,
ENABLE_OPENAI_API,
ENABLE_OLLAMA_API,
ENABLE_MODEL_FILTER,
MODEL_FILTER_LIST,
GLOBAL_LOG_LEVEL,
SRC_LOG_LEVELS,
WEBHOOK_URL,
ENABLE_ADMIN_EXPORT,
AppConfig,
WEBUI_BUILD_HASH,
)
from constants import ERROR_MESSAGES
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
class SPAStaticFiles(StaticFiles):
async def get_response(self, path: str, scope):
try:
return await super().get_response(path, scope)
except (HTTPException, StarletteHTTPException) as ex:
if ex.status_code == 404:
return await super().get_response("index.html", scope)
else:
raise ex
print(
rf"""
___ __ __ _ _ _ ___
/ _ \ _ __ ___ _ __ \ \ / /__| |__ | | | |_ _|
| | | | '_ \ / _ \ '_ \ \ \ /\ / / _ \ '_ \| | | || |
| |_| | |_) | __/ | | | \ V V / __/ |_) | |_| || |
\___/| .__/ \___|_| |_| \_/\_/ \___|_.__/ \___/|___|
|_|
v{VERSION} - building the best open-source AI user interface.
{f"Commit: {WEBUI_BUILD_HASH}" if WEBUI_BUILD_HASH != "dev-build" else ""}
https://github.com/open-webui/open-webui
"""
)
@asynccontextmanager
async def lifespan(app: FastAPI):
yield
app = FastAPI(
docs_url="/docs" if ENV == "dev" else None, redoc_url=None, lifespan=lifespan
)
app.state.config = AppConfig()
app.state.config.ENABLE_OPENAI_API = ENABLE_OPENAI_API
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.MODELS = {}
origins = ["*"]
# Custom middleware to add security headers
# class SecurityHeadersMiddleware(BaseHTTPMiddleware):
# async def dispatch(self, request: Request, call_next):
# response: Response = await call_next(request)
# response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
# response.headers["Cross-Origin-Embedder-Policy"] = "require-corp"
# return response
# app.add_middleware(SecurityHeadersMiddleware)
class RAGMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
return_citations = False
if request.method == "POST" and (
"/ollama/api/chat" in request.url.path
or "/chat/completions" in request.url.path
):
log.debug(f"request.url.path: {request.url.path}")
# Read the original request body
body = await request.body()
# Decode body to string
body_str = body.decode("utf-8")
# Parse string to JSON
data = json.loads(body_str) if body_str else {}
return_citations = data.get("citations", False)
if "citations" in data:
del data["citations"]
# Example: Add a new key-value pair or modify existing ones
# data["modified"] = True # Example modification
if "docs" in data:
data = {**data}
data["messages"], citations = rag_messages(
docs=data["docs"],
messages=data["messages"],
template=rag_app.state.config.RAG_TEMPLATE,
embedding_function=rag_app.state.EMBEDDING_FUNCTION,
k=rag_app.state.config.TOP_K,
reranking_function=rag_app.state.sentence_transformer_rf,
r=rag_app.state.config.RELEVANCE_THRESHOLD,
hybrid_search=rag_app.state.config.ENABLE_RAG_HYBRID_SEARCH,
)
del data["docs"]
log.debug(
f"data['messages']: {data['messages']}, citations: {citations}"
)
modified_body_bytes = json.dumps(data).encode("utf-8")
# Replace the request body with the modified one
request._body = modified_body_bytes
# Set custom header to ensure content-length matches new body length
request.headers.__dict__["_list"] = [
(b"content-length", str(len(modified_body_bytes)).encode("utf-8")),
*[
(k, v)
for k, v in request.headers.raw
if k.lower() != b"content-length"
],
]
response = await call_next(request)
if return_citations:
# Inject the citations into the response
if isinstance(response, StreamingResponse):
# If it's a streaming response, inject it as SSE event or NDJSON line
content_type = response.headers.get("Content-Type")
if "text/event-stream" in content_type:
return StreamingResponse(
self.openai_stream_wrapper(response.body_iterator, citations),
)
if "application/x-ndjson" in content_type:
return StreamingResponse(
self.ollama_stream_wrapper(response.body_iterator, citations),
)
return response
async def _receive(self, body: bytes):
return {"type": "http.request", "body": body, "more_body": False}
async def openai_stream_wrapper(self, original_generator, citations):
yield f"data: {json.dumps({'citations': citations})}\n\n"
async for data in original_generator:
yield data
async def ollama_stream_wrapper(self, original_generator, citations):
yield f"{json.dumps({'citations': citations})}\n"
async for data in original_generator:
yield data
app.add_middleware(RAGMiddleware)
class PipelineMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if request.method == "POST" and (
"/ollama/api/chat" in request.url.path
or "/chat/completions" in request.url.path
):
log.debug(f"request.url.path: {request.url.path}")
# Read the original request body
body = await request.body()
# Decode body to string
body_str = body.decode("utf-8")
# 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"]
modified_body_bytes = json.dumps(data).encode("utf-8")
# Replace the request body with the modified one
request._body = modified_body_bytes
# Set custom header to ensure content-length matches new body length
request.headers.__dict__["_list"] = [
(b"content-length", str(len(modified_body_bytes)).encode("utf-8")),
*[
(k, v)
for k, v in request.headers.raw
if k.lower() != b"content-length"
],
]
response = await call_next(request)
return response
async def _receive(self, body: bytes):
return {"type": "http.request", "body": body, "more_body": False}
app.add_middleware(PipelineMiddleware)
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.middleware("http")
async def check_url(request: Request, call_next):
if len(app.state.MODELS) == 0:
await get_all_models()
else:
pass
start_time = int(time.time())
response = await call_next(request)
process_time = int(time.time()) - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
@app.middleware("http")
async def update_embedding_function(request: Request, call_next):
response = await call_next(request)
if "/embedding/update" in request.url.path:
webui_app.state.EMBEDDING_FUNCTION = rag_app.state.EMBEDDING_FUNCTION
return response
app.mount("/ollama", ollama_app)
app.mount("/openai", openai_app)
app.mount("/images/api/v1", images_app)
app.mount("/audio/api/v1", audio_app)
app.mount("/rag/api/v1", rag_app)
app.mount("/api/v1", webui_app)
webui_app.state.EMBEDDING_FUNCTION = rag_app.state.EMBEDDING_FUNCTION
async def get_all_models():
openai_models = []
ollama_models = []
if app.state.config.ENABLE_OPENAI_API:
openai_models = await get_openai_models()
openai_models = openai_models["data"]
if app.state.config.ENABLE_OLLAMA_API:
ollama_models = await get_ollama_models()
ollama_models = [
{
"id": model["model"],
"name": model["name"],
"object": "model",
"created": int(time.time()),
"owned_by": "ollama",
"ollama": model,
}
for model in ollama_models["models"]
]
models = openai_models + ollama_models
custom_models = Models.get_all_models()
for custom_model in custom_models:
if custom_model.base_model_id == None:
for model in models:
if (
custom_model.id == model["id"]
or custom_model.id == model["id"].split(":")[0]
):
model["name"] = custom_model.name
model["info"] = custom_model.model_dump()
else:
owned_by = "openai"
for model in models:
if (
custom_model.base_model_id == model["id"]
or custom_model.base_model_id == model["id"].split(":")[0]
):
owned_by = model["owned_by"]
break
models.append(
{
"id": custom_model.id,
"name": custom_model.name,
"object": "model",
"created": custom_model.created_at,
"owned_by": owned_by,
"info": custom_model.model_dump(),
"preset": True,
}
)
app.state.MODELS = {model["id"]: model for model in models}
webui_app.state.MODELS = app.state.MODELS
return models
@app.get("/api/models")
async def get_models(user=Depends(get_verified_user)):
models = await get_all_models()
# Filter out filter pipelines
models = [
model
for model in models
if "pipeline" not in model or model["pipeline"].get("type", None) != "filter"
]
if app.state.config.ENABLE_MODEL_FILTER:
if user.role == "user":
models = list(
filter(
lambda model: model["id"] in app.state.config.MODEL_FILTER_LIST,
models,
)
)
return {"data": models}
return {"data": models}
@app.post("/api/chat/completed")
async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
data = form_data
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"])
model = app.state.MODELS[model_id]
if "pipeline" in model:
sorted_filters = [model] + sorted_filters
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/outlet",
headers=headers,
json={
"user": {"id": user.id, "name": user.name, "role": user.role},
"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
return data
@app.get("/api/pipelines/list")
async def get_pipelines_list(user=Depends(get_admin_user)):
responses = await get_openai_models(raw=True)
print(responses)
urlIdxs = [idx for idx, response in enumerate(responses) if "pipelines" in response]
return {
"data": [
{
"url": openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx],
"idx": urlIdx,
}
for urlIdx in urlIdxs
]
}
class AddPipelineForm(BaseModel):
url: str
urlIdx: int
@app.post("/api/pipelines/add")
async def add_pipeline(form_data: AddPipelineForm, user=Depends(get_admin_user)):
r = None
try:
urlIdx = form_data.urlIdx
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.post(
f"{url}/pipelines/add", headers=headers, json={"url": form_data.url}
)
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,
)
class DeletePipelineForm(BaseModel):
id: str
urlIdx: int
@app.delete("/api/pipelines/delete")
async def delete_pipeline(form_data: DeletePipelineForm, user=Depends(get_admin_user)):
r = None
try:
urlIdx = form_data.urlIdx
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.delete(
f"{url}/pipelines/delete", headers=headers, json={"id": form_data.id}
)
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,
)
@app.get("/api/pipelines")
async def get_pipelines(urlIdx: Optional[int] = None, user=Depends(get_admin_user)):
r = None
try:
urlIdx
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.get(f"{url}/pipelines", headers=headers)
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,
)
@app.get("/api/pipelines/{pipeline_id}/valves")
async def get_pipeline_valves(
urlIdx: Optional[int], pipeline_id: str, user=Depends(get_admin_user)
):
models = await get_all_models()
r = None
try:
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.get(f"{url}/{pipeline_id}/valves", headers=headers)
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,
)
@app.get("/api/pipelines/{pipeline_id}/valves/spec")
async def get_pipeline_valves_spec(
urlIdx: Optional[int], pipeline_id: str, user=Depends(get_admin_user)
):
models = await get_all_models()
r = None
try:
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.get(f"{url}/{pipeline_id}/valves/spec", headers=headers)
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,
)
@app.post("/api/pipelines/{pipeline_id}/valves/update")
async def update_pipeline_valves(
urlIdx: Optional[int],
pipeline_id: str,
form_data: dict,
user=Depends(get_admin_user),
):
models = await get_all_models()
r = None
try:
url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
headers = {"Authorization": f"Bearer {key}"}
r = requests.post(
f"{url}/{pipeline_id}/valves/update",
headers=headers,
json={**form_data},
)
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,
)
@app.get("/api/config")
async def get_app_config():
# Checking and Handling the Absence of 'ui' in CONFIG_DATA
default_locale = "en-US"
if "ui" in CONFIG_DATA:
default_locale = CONFIG_DATA["ui"].get("default_locale", "en-US")
# The Rest of the Function Now Uses the Variables Defined Above
return {
"status": True,
"name": WEBUI_NAME,
"version": VERSION,
"default_locale": default_locale,
"default_models": webui_app.state.config.DEFAULT_MODELS,
"default_prompt_suggestions": webui_app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
"features": {
"auth": WEBUI_AUTH,
"auth_trusted_header": bool(webui_app.state.AUTH_TRUSTED_EMAIL_HEADER),
"enable_signup": webui_app.state.config.ENABLE_SIGNUP,
"enable_web_search": rag_app.state.config.ENABLE_RAG_WEB_SEARCH,
"enable_image_generation": images_app.state.config.ENABLED,
"enable_community_sharing": webui_app.state.config.ENABLE_COMMUNITY_SHARING,
"enable_admin_export": ENABLE_ADMIN_EXPORT,
},
}
@app.get("/api/config/model/filter")
async def get_model_filter_config(user=Depends(get_admin_user)):
return {
"enabled": app.state.config.ENABLE_MODEL_FILTER,
"models": app.state.config.MODEL_FILTER_LIST,
}
class ModelFilterConfigForm(BaseModel):
enabled: bool
models: List[str]
@app.post("/api/config/model/filter")
async def update_model_filter_config(
form_data: ModelFilterConfigForm, user=Depends(get_admin_user)
):
app.state.config.ENABLE_MODEL_FILTER = form_data.enabled
app.state.config.MODEL_FILTER_LIST = form_data.models
return {
"enabled": app.state.config.ENABLE_MODEL_FILTER,
"models": app.state.config.MODEL_FILTER_LIST,
}
@app.get("/api/webhook")
async def get_webhook_url(user=Depends(get_admin_user)):
return {
"url": app.state.config.WEBHOOK_URL,
}
class UrlForm(BaseModel):
url: str
@app.post("/api/webhook")
async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
app.state.config.WEBHOOK_URL = form_data.url
webui_app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL
return {
"url": app.state.config.WEBHOOK_URL,
}
@app.get("/api/community_sharing", response_model=bool)
async def get_community_sharing_status(request: Request, user=Depends(get_admin_user)):
return webui_app.state.config.ENABLE_COMMUNITY_SHARING
@app.get("/api/community_sharing/toggle", response_model=bool)
async def toggle_community_sharing(request: Request, user=Depends(get_admin_user)):
webui_app.state.config.ENABLE_COMMUNITY_SHARING = (
not webui_app.state.config.ENABLE_COMMUNITY_SHARING
)
return webui_app.state.config.ENABLE_COMMUNITY_SHARING
@app.get("/api/version")
async def get_app_config():
return {
"version": VERSION,
}
@app.get("/api/changelog")
async def get_app_changelog():
return {key: CHANGELOG[key] for idx, key in enumerate(CHANGELOG) if idx < 5}
@app.get("/api/version/updates")
async def get_app_latest_release_version():
try:
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.github.com/repos/open-webui/open-webui/releases/latest"
) as response:
response.raise_for_status()
data = await response.json()
latest_version = data["tag_name"]
return {"current": VERSION, "latest": latest_version[1:]}
except aiohttp.ClientError as e:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=ERROR_MESSAGES.RATE_LIMIT_EXCEEDED,
)
@app.get("/manifest.json")
async def get_manifest_json():
return {
"name": WEBUI_NAME,
"short_name": WEBUI_NAME,
"start_url": "/",
"display": "standalone",
"background_color": "#343541",
"theme_color": "#343541",
"orientation": "portrait-primary",
"icons": [{"src": "/static/logo.png", "type": "image/png", "sizes": "500x500"}],
}
@app.get("/opensearch.xml")
async def get_opensearch_xml():
xml_content = rf"""
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>{WEBUI_NAME}</ShortName>
<Description>Search {WEBUI_NAME}</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/x-icon">{WEBUI_URL}/favicon.png</Image>
<Url type="text/html" method="get" template="{WEBUI_URL}/?q={"{searchTerms}"}"/>
<moz:SearchForm>{WEBUI_URL}</moz:SearchForm>
</OpenSearchDescription>
"""
return Response(content=xml_content, media_type="application/xml")
@app.get("/health")
async def healthcheck():
return {"status": True}
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
app.mount("/cache", StaticFiles(directory=CACHE_DIR), name="cache")
if os.path.exists(FRONTEND_BUILD_DIR):
mimetypes.add_type("text/javascript", ".js")
app.mount(
"/",
SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True),
name="spa-static-files",
)
else:
log.warning(
f"Frontend build directory not found at '{FRONTEND_BUILD_DIR}'. Serving API only."
)

View File

@@ -9,8 +9,6 @@ import uvicorn
app = typer.Typer()
KEY_FILE = Path.cwd() / ".webui_secret_key"
if (frontend_build_dir := Path(__file__).parent / "frontend").exists():
os.environ["FRONTEND_BUILD_DIR"] = str(frontend_build_dir)
@app.command()
@@ -18,6 +16,7 @@ def serve(
host: str = "0.0.0.0",
port: int = 8080,
):
os.environ["FROM_INIT_PY"] = "true"
if os.getenv("WEBUI_SECRET_KEY") is None:
typer.echo(
"Loading WEBUI_SECRET_KEY from file, not provided as an environment variable."
@@ -40,9 +39,23 @@ def serve(
"/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib",
]
)
import main # we need set environment variables before importing main
try:
import torch
uvicorn.run(main.app, host=host, port=port, forwarded_allow_ips="*")
assert torch.cuda.is_available(), "CUDA not available"
typer.echo("CUDA seems to be working")
except Exception as e:
typer.echo(
"Error when testing CUDA but USE_CUDA_DOCKER is true. "
"Resetting USE_CUDA_DOCKER to false and removing "
f"LD_LIBRARY_PATH modifications: {e}"
)
os.environ["USE_CUDA_DOCKER"] = "false"
os.environ["LD_LIBRARY_PATH"] = ":".join(LD_LIBRARY_PATH)
import open_webui.main # we need set environment variables before importing main
uvicorn.run(open_webui.main.app, host=host, port=port, forwarded_allow_ips="*")
@app.command()
@@ -52,7 +65,11 @@ def dev(
reload: bool = True,
):
uvicorn.run(
"main:app", host=host, port=port, reload=reload, forwarded_allow_ips="*"
"open_webui.main:app",
host=host,
port=port,
reload=reload,
forwarded_allow_ips="*",
)

View File

@@ -0,0 +1,114 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = migrations
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python>=3.9 or backports.zoneinfo library.
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
# string value is passed to ZoneInfo()
# leave blank for localtime
# timezone =
# max length of characters to apply to the
# "slug" field
# truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; This defaults
# to migrations/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator" below.
# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions
# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
# set to 'true' to search source files recursively
# in each "version_locations" directory
# new in Alembic version 1.10
# recursive_version_locations = false
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
# sqlalchemy.url = REPLACE_WITH_DATABASE_URL
[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME
# lint with attempts to fix using "ruff" - use the exec runner, execute a binary
# hooks = ruff
# ruff.type = exec
# ruff.executable = %(here)s/.venv/bin/ruff
# ruff.options = --fix REVISION_SCRIPT_FILENAME
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

View File

@@ -0,0 +1,583 @@
import hashlib
import json
import logging
import os
import uuid
from functools import lru_cache
from pathlib import Path
import requests
from open_webui.config import (
AUDIO_STT_ENGINE,
AUDIO_STT_MODEL,
AUDIO_STT_OPENAI_API_BASE_URL,
AUDIO_STT_OPENAI_API_KEY,
AUDIO_TTS_API_KEY,
AUDIO_TTS_ENGINE,
AUDIO_TTS_MODEL,
AUDIO_TTS_OPENAI_API_BASE_URL,
AUDIO_TTS_OPENAI_API_KEY,
AUDIO_TTS_SPLIT_ON,
AUDIO_TTS_VOICE,
AUDIO_TTS_AZURE_SPEECH_REGION,
AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT,
CACHE_DIR,
CORS_ALLOW_ORIGIN,
WHISPER_MODEL,
WHISPER_MODEL_AUTO_UPDATE,
WHISPER_MODEL_DIR,
AppConfig,
)
from open_webui.constants import ERROR_MESSAGES
from open_webui.env import SRC_LOG_LEVELS, DEVICE_TYPE
from fastapi import Depends, FastAPI, File, HTTPException, Request, UploadFile, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from pydantic import BaseModel
from open_webui.utils.utils import get_admin_user, get_current_user, get_verified_user
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["AUDIO"])
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGIN,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.state.config = AppConfig()
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
app.state.config.TTS_API_KEY = AUDIO_TTS_API_KEY
app.state.config.TTS_SPLIT_ON = AUDIO_TTS_SPLIT_ON
app.state.config.TTS_AZURE_SPEECH_REGION = AUDIO_TTS_AZURE_SPEECH_REGION
app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT
# setting device type for whisper model
whisper_device_type = DEVICE_TYPE if DEVICE_TYPE and DEVICE_TYPE == "cuda" else "cpu"
log.info(f"whisper_device_type: {whisper_device_type}")
SPEECH_CACHE_DIR = Path(CACHE_DIR).joinpath("./audio/speech/")
SPEECH_CACHE_DIR.mkdir(parents=True, exist_ok=True)
class TTSConfigForm(BaseModel):
OPENAI_API_BASE_URL: str
OPENAI_API_KEY: str
API_KEY: str
ENGINE: str
MODEL: str
VOICE: str
SPLIT_ON: str
AZURE_SPEECH_REGION: str
AZURE_SPEECH_OUTPUT_FORMAT: 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_audio_config(user=Depends(get_admin_user)):
return {
"tts": {
"OPENAI_API_BASE_URL": app.state.config.TTS_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.TTS_OPENAI_API_KEY,
"API_KEY": app.state.config.TTS_API_KEY,
"ENGINE": app.state.config.TTS_ENGINE,
"MODEL": app.state.config.TTS_MODEL,
"VOICE": app.state.config.TTS_VOICE,
"SPLIT_ON": app.state.config.TTS_SPLIT_ON,
"AZURE_SPEECH_REGION": app.state.config.TTS_AZURE_SPEECH_REGION,
"AZURE_SPEECH_OUTPUT_FORMAT": app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT,
},
"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_audio_config(
form_data: AudioConfigUpdateForm, user=Depends(get_admin_user)
):
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_API_KEY = form_data.tts.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.TTS_SPLIT_ON = form_data.tts.SPLIT_ON
app.state.config.TTS_AZURE_SPEECH_REGION = form_data.tts.AZURE_SPEECH_REGION
app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = (
form_data.tts.AZURE_SPEECH_OUTPUT_FORMAT
)
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 {
"tts": {
"OPENAI_API_BASE_URL": app.state.config.TTS_OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.TTS_OPENAI_API_KEY,
"API_KEY": app.state.config.TTS_API_KEY,
"ENGINE": app.state.config.TTS_ENGINE,
"MODEL": app.state.config.TTS_MODEL,
"VOICE": app.state.config.TTS_VOICE,
"SPLIT_ON": app.state.config.TTS_SPLIT_ON,
"AZURE_SPEECH_REGION": app.state.config.TTS_AZURE_SPEECH_REGION,
"AZURE_SPEECH_OUTPUT_FORMAT": app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT,
},
"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("/speech")
async def speech(request: Request, user=Depends(get_verified_user)):
body = await request.body()
name = hashlib.sha256(body).hexdigest()
file_path = SPEECH_CACHE_DIR.joinpath(f"{name}.mp3")
file_body_path = SPEECH_CACHE_DIR.joinpath(f"{name}.json")
# Check if the file already exists in the cache
if file_path.is_file():
return FileResponse(file_path)
if app.state.config.TTS_ENGINE == "openai":
headers = {}
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:
pass
r = None
try:
r = requests.post(
url=f"{app.state.config.TTS_OPENAI_API_BASE_URL}/audio/speech",
data=body,
headers=headers,
stream=True,
)
r.raise_for_status()
# Save the streaming content to a file
with open(file_path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
with open(file_body_path, "w") as f:
json.dump(json.loads(body.decode("utf-8")), f)
# Return the saved file
return FileResponse(file_path)
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 Exception:
error_detail = f"External: {e}"
raise HTTPException(
status_code=r.status_code if r != None else 500,
detail=error_detail,
)
elif app.state.config.TTS_ENGINE == "elevenlabs":
payload = None
try:
payload = json.loads(body.decode("utf-8"))
except Exception as e:
log.exception(e)
raise HTTPException(status_code=400, detail="Invalid JSON payload")
voice_id = payload.get("voice", "")
if voice_id not in get_available_voices():
raise HTTPException(
status_code=400,
detail="Invalid voice id",
)
url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
headers = {
"Accept": "audio/mpeg",
"Content-Type": "application/json",
"xi-api-key": app.state.config.TTS_API_KEY,
}
data = {
"text": payload["input"],
"model_id": app.state.config.TTS_MODEL,
"voice_settings": {"stability": 0.5, "similarity_boost": 0.5},
}
try:
r = requests.post(url, json=data, headers=headers)
r.raise_for_status()
# Save the streaming content to a file
with open(file_path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
with open(file_body_path, "w") as f:
json.dump(json.loads(body.decode("utf-8")), f)
# Return the saved file
return FileResponse(file_path)
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 Exception:
error_detail = f"External: {e}"
raise HTTPException(
status_code=r.status_code if r != None else 500,
detail=error_detail,
)
elif app.state.config.TTS_ENGINE == "azure":
payload = None
try:
payload = json.loads(body.decode("utf-8"))
except Exception as e:
log.exception(e)
raise HTTPException(status_code=400, detail="Invalid JSON payload")
region = app.state.config.TTS_AZURE_SPEECH_REGION
language = app.state.config.TTS_VOICE
locale = "-".join(app.state.config.TTS_VOICE.split("-")[:1])
output_format = app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT
url = f"https://{region}.tts.speech.microsoft.com/cognitiveservices/v1"
headers = {
"Ocp-Apim-Subscription-Key": app.state.config.TTS_API_KEY,
"Content-Type": "application/ssml+xml",
"X-Microsoft-OutputFormat": output_format,
}
data = f"""<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="{locale}">
<voice name="{language}">{payload["input"]}</voice>
</speak>"""
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
with open(file_path, "wb") as f:
f.write(response.content)
return FileResponse(file_path)
else:
log.error(f"Error synthesizing speech - {response.reason}")
raise HTTPException(
status_code=500, detail=f"Error synthesizing speech - {response.reason}"
)
@app.post("/transcriptions")
def transcribe(
file: UploadFile = File(...),
user=Depends(get_current_user),
):
log.info(f"file.content_type: {file.content_type}")
if file.content_type not in ["audio/mpeg", "audio/wav", "audio/ogg", "audio/x-m4a"]:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.FILE_NOT_SUPPORTED,
)
try:
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()
if app.state.config.STT_ENGINE == "":
from faster_whisper import WhisperModel
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}")
try:
model = WhisperModel(**whisper_kwargs)
except Exception:
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)
)
transcript = "".join([segment.text for segment in list(segments)])
data = {"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": app.state.config.STT_MODEL}
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 Exception:
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)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(e),
)
def get_available_models() -> list[dict]:
if app.state.config.TTS_ENGINE == "openai":
return [{"id": "tts-1"}, {"id": "tts-1-hd"}]
elif app.state.config.TTS_ENGINE == "elevenlabs":
headers = {
"xi-api-key": app.state.config.TTS_API_KEY,
"Content-Type": "application/json",
}
try:
response = requests.get(
"https://api.elevenlabs.io/v1/models", headers=headers, timeout=5
)
response.raise_for_status()
models = response.json()
return [
{"name": model["name"], "id": model["model_id"]} for model in models
]
except requests.RequestException as e:
log.error(f"Error fetching voices: {str(e)}")
return []
@app.get("/models")
async def get_models(user=Depends(get_verified_user)):
return {"models": get_available_models()}
def get_available_voices() -> dict:
"""Returns {voice_id: voice_name} dict"""
ret = {}
if app.state.config.TTS_ENGINE == "openai":
ret = {
"alloy": "alloy",
"echo": "echo",
"fable": "fable",
"onyx": "onyx",
"nova": "nova",
"shimmer": "shimmer",
}
elif app.state.config.TTS_ENGINE == "elevenlabs":
try:
ret = get_elevenlabs_voices()
except Exception:
# Avoided @lru_cache with exception
pass
elif app.state.config.TTS_ENGINE == "azure":
try:
region = app.state.config.TTS_AZURE_SPEECH_REGION
url = f"https://{region}.tts.speech.microsoft.com/cognitiveservices/voices/list"
headers = {"Ocp-Apim-Subscription-Key": app.state.config.TTS_API_KEY}
response = requests.get(url, headers=headers)
response.raise_for_status()
voices = response.json()
for voice in voices:
ret[voice["ShortName"]] = (
f"{voice['DisplayName']} ({voice['ShortName']})"
)
except requests.RequestException as e:
log.error(f"Error fetching voices: {str(e)}")
return ret
@lru_cache
def get_elevenlabs_voices() -> dict:
"""
Note, set the following in your .env file to use Elevenlabs:
AUDIO_TTS_ENGINE=elevenlabs
AUDIO_TTS_API_KEY=sk_... # Your Elevenlabs API key
AUDIO_TTS_VOICE=EXAVITQu4vr4xnSDxMaL # From https://api.elevenlabs.io/v1/voices
AUDIO_TTS_MODEL=eleven_multilingual_v2
"""
headers = {
"xi-api-key": app.state.config.TTS_API_KEY,
"Content-Type": "application/json",
}
try:
# TODO: Add retries
response = requests.get("https://api.elevenlabs.io/v1/voices", headers=headers)
response.raise_for_status()
voices_data = response.json()
voices = {}
for voice in voices_data.get("voices", []):
voices[voice["voice_id"]] = voice["name"]
except requests.RequestException as e:
# Avoid @lru_cache with exception
log.error(f"Error fetching voices: {str(e)}")
raise RuntimeError(f"Error fetching voices: {str(e)}")
return voices
@app.get("/voices")
async def get_voices(user=Depends(get_verified_user)):
return {"voices": [{"id": k, "name": v} for k, v in get_available_voices().items()]}

View File

@@ -0,0 +1,597 @@
import asyncio
import base64
import json
import logging
import mimetypes
import re
import uuid
from pathlib import Path
from typing import Optional
import requests
from open_webui.apps.images.utils.comfyui import (
ComfyUIGenerateImageForm,
ComfyUIWorkflow,
comfyui_generate_image,
)
from open_webui.config import (
AUTOMATIC1111_API_AUTH,
AUTOMATIC1111_BASE_URL,
AUTOMATIC1111_CFG_SCALE,
AUTOMATIC1111_SAMPLER,
AUTOMATIC1111_SCHEDULER,
CACHE_DIR,
COMFYUI_BASE_URL,
COMFYUI_WORKFLOW,
COMFYUI_WORKFLOW_NODES,
CORS_ALLOW_ORIGIN,
ENABLE_IMAGE_GENERATION,
IMAGE_GENERATION_ENGINE,
IMAGE_GENERATION_MODEL,
IMAGE_SIZE,
IMAGE_STEPS,
IMAGES_OPENAI_API_BASE_URL,
IMAGES_OPENAI_API_KEY,
AppConfig,
)
from open_webui.constants import ERROR_MESSAGES
from open_webui.env import SRC_LOG_LEVELS
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from open_webui.utils.utils import get_admin_user, get_verified_user
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["IMAGES"])
IMAGE_CACHE_DIR = Path(CACHE_DIR).joinpath("./image/generations/")
IMAGE_CACHE_DIR.mkdir(parents=True, exist_ok=True)
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGIN,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.state.config = AppConfig()
app.state.config.ENGINE = IMAGE_GENERATION_ENGINE
app.state.config.ENABLED = ENABLE_IMAGE_GENERATION
app.state.config.OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL
app.state.config.OPENAI_API_KEY = IMAGES_OPENAI_API_KEY
app.state.config.MODEL = IMAGE_GENERATION_MODEL
app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH
app.state.config.AUTOMATIC1111_CFG_SCALE = AUTOMATIC1111_CFG_SCALE
app.state.config.AUTOMATIC1111_SAMPLER = AUTOMATIC1111_SAMPLER
app.state.config.AUTOMATIC1111_SCHEDULER = AUTOMATIC1111_SCHEDULER
app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
app.state.config.COMFYUI_WORKFLOW = COMFYUI_WORKFLOW
app.state.config.COMFYUI_WORKFLOW_NODES = COMFYUI_WORKFLOW_NODES
app.state.config.IMAGE_SIZE = IMAGE_SIZE
app.state.config.IMAGE_STEPS = IMAGE_STEPS
@app.get("/config")
async def get_config(request: Request, user=Depends(get_admin_user)):
return {
"enabled": app.state.config.ENABLED,
"engine": app.state.config.ENGINE,
"openai": {
"OPENAI_API_BASE_URL": app.state.config.OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.OPENAI_API_KEY,
},
"automatic1111": {
"AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL,
"AUTOMATIC1111_API_AUTH": app.state.config.AUTOMATIC1111_API_AUTH,
"AUTOMATIC1111_CFG_SCALE": app.state.config.AUTOMATIC1111_CFG_SCALE,
"AUTOMATIC1111_SAMPLER": app.state.config.AUTOMATIC1111_SAMPLER,
"AUTOMATIC1111_SCHEDULER": app.state.config.AUTOMATIC1111_SCHEDULER,
},
"comfyui": {
"COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL,
"COMFYUI_WORKFLOW": app.state.config.COMFYUI_WORKFLOW,
"COMFYUI_WORKFLOW_NODES": app.state.config.COMFYUI_WORKFLOW_NODES,
},
}
class OpenAIConfigForm(BaseModel):
OPENAI_API_BASE_URL: str
OPENAI_API_KEY: str
class Automatic1111ConfigForm(BaseModel):
AUTOMATIC1111_BASE_URL: str
AUTOMATIC1111_API_AUTH: str
AUTOMATIC1111_CFG_SCALE: Optional[str]
AUTOMATIC1111_SAMPLER: Optional[str]
AUTOMATIC1111_SCHEDULER: Optional[str]
class ComfyUIConfigForm(BaseModel):
COMFYUI_BASE_URL: str
COMFYUI_WORKFLOW: str
COMFYUI_WORKFLOW_NODES: list[dict]
class ConfigForm(BaseModel):
enabled: bool
engine: str
openai: OpenAIConfigForm
automatic1111: Automatic1111ConfigForm
comfyui: ComfyUIConfigForm
@app.post("/config/update")
async def update_config(form_data: ConfigForm, user=Depends(get_admin_user)):
app.state.config.ENGINE = form_data.engine
app.state.config.ENABLED = form_data.enabled
app.state.config.OPENAI_API_BASE_URL = form_data.openai.OPENAI_API_BASE_URL
app.state.config.OPENAI_API_KEY = form_data.openai.OPENAI_API_KEY
app.state.config.AUTOMATIC1111_BASE_URL = (
form_data.automatic1111.AUTOMATIC1111_BASE_URL
)
app.state.config.AUTOMATIC1111_API_AUTH = (
form_data.automatic1111.AUTOMATIC1111_API_AUTH
)
app.state.config.AUTOMATIC1111_CFG_SCALE = (
float(form_data.automatic1111.AUTOMATIC1111_CFG_SCALE)
if form_data.automatic1111.AUTOMATIC1111_CFG_SCALE
else None
)
app.state.config.AUTOMATIC1111_SAMPLER = (
form_data.automatic1111.AUTOMATIC1111_SAMPLER
if form_data.automatic1111.AUTOMATIC1111_SAMPLER
else None
)
app.state.config.AUTOMATIC1111_SCHEDULER = (
form_data.automatic1111.AUTOMATIC1111_SCHEDULER
if form_data.automatic1111.AUTOMATIC1111_SCHEDULER
else None
)
app.state.config.COMFYUI_BASE_URL = form_data.comfyui.COMFYUI_BASE_URL.strip("/")
app.state.config.COMFYUI_WORKFLOW = form_data.comfyui.COMFYUI_WORKFLOW
app.state.config.COMFYUI_WORKFLOW_NODES = form_data.comfyui.COMFYUI_WORKFLOW_NODES
return {
"enabled": app.state.config.ENABLED,
"engine": app.state.config.ENGINE,
"openai": {
"OPENAI_API_BASE_URL": app.state.config.OPENAI_API_BASE_URL,
"OPENAI_API_KEY": app.state.config.OPENAI_API_KEY,
},
"automatic1111": {
"AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL,
"AUTOMATIC1111_API_AUTH": app.state.config.AUTOMATIC1111_API_AUTH,
"AUTOMATIC1111_CFG_SCALE": app.state.config.AUTOMATIC1111_CFG_SCALE,
"AUTOMATIC1111_SAMPLER": app.state.config.AUTOMATIC1111_SAMPLER,
"AUTOMATIC1111_SCHEDULER": app.state.config.AUTOMATIC1111_SCHEDULER,
},
"comfyui": {
"COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL,
"COMFYUI_WORKFLOW": app.state.config.COMFYUI_WORKFLOW,
"COMFYUI_WORKFLOW_NODES": app.state.config.COMFYUI_WORKFLOW_NODES,
},
}
def get_automatic1111_api_auth():
if app.state.config.AUTOMATIC1111_API_AUTH is None:
return ""
else:
auth1111_byte_string = app.state.config.AUTOMATIC1111_API_AUTH.encode("utf-8")
auth1111_base64_encoded_bytes = base64.b64encode(auth1111_byte_string)
auth1111_base64_encoded_string = auth1111_base64_encoded_bytes.decode("utf-8")
return f"Basic {auth1111_base64_encoded_string}"
@app.get("/config/url/verify")
async def verify_url(user=Depends(get_admin_user)):
if app.state.config.ENGINE == "automatic1111":
try:
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options",
headers={"authorization": get_automatic1111_api_auth()},
)
r.raise_for_status()
return True
except Exception:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
elif app.state.config.ENGINE == "comfyui":
try:
r = requests.get(url=f"{app.state.config.COMFYUI_BASE_URL}/object_info")
r.raise_for_status()
return True
except Exception:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
else:
return True
def set_image_model(model: str):
log.info(f"Setting image model to {model}")
app.state.config.MODEL = model
if app.state.config.ENGINE in ["", "automatic1111"]:
api_auth = get_automatic1111_api_auth()
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options",
headers={"authorization": api_auth},
)
options = r.json()
if model != options["sd_model_checkpoint"]:
options["sd_model_checkpoint"] = model
r = requests.post(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options",
json=options,
headers={"authorization": api_auth},
)
return app.state.config.MODEL
def get_image_model():
if app.state.config.ENGINE == "openai":
return app.state.config.MODEL if app.state.config.MODEL else "dall-e-2"
elif app.state.config.ENGINE == "comfyui":
return app.state.config.MODEL if app.state.config.MODEL else ""
elif app.state.config.ENGINE == "automatic1111" or app.state.config.ENGINE == "":
try:
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options",
headers={"authorization": get_automatic1111_api_auth()},
)
options = r.json()
return options["sd_model_checkpoint"]
except Exception as e:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
class ImageConfigForm(BaseModel):
MODEL: str
IMAGE_SIZE: str
IMAGE_STEPS: int
@app.get("/image/config")
async def get_image_config(user=Depends(get_admin_user)):
return {
"MODEL": app.state.config.MODEL,
"IMAGE_SIZE": app.state.config.IMAGE_SIZE,
"IMAGE_STEPS": app.state.config.IMAGE_STEPS,
}
@app.post("/image/config/update")
async def update_image_config(form_data: ImageConfigForm, user=Depends(get_admin_user)):
set_image_model(form_data.MODEL)
pattern = r"^\d+x\d+$"
if re.match(pattern, form_data.IMAGE_SIZE):
app.state.config.IMAGE_SIZE = form_data.IMAGE_SIZE
else:
raise HTTPException(
status_code=400,
detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 512x512)."),
)
if form_data.IMAGE_STEPS >= 0:
app.state.config.IMAGE_STEPS = form_data.IMAGE_STEPS
else:
raise HTTPException(
status_code=400,
detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 50)."),
)
return {
"MODEL": app.state.config.MODEL,
"IMAGE_SIZE": app.state.config.IMAGE_SIZE,
"IMAGE_STEPS": app.state.config.IMAGE_STEPS,
}
@app.get("/models")
def get_models(user=Depends(get_verified_user)):
try:
if app.state.config.ENGINE == "openai":
return [
{"id": "dall-e-2", "name": "DALL·E 2"},
{"id": "dall-e-3", "name": "DALL·E 3"},
]
elif app.state.config.ENGINE == "comfyui":
# TODO - get models from comfyui
r = requests.get(url=f"{app.state.config.COMFYUI_BASE_URL}/object_info")
info = r.json()
workflow = json.loads(app.state.config.COMFYUI_WORKFLOW)
model_node_id = None
for node in app.state.config.COMFYUI_WORKFLOW_NODES:
if node["type"] == "model":
if node["node_ids"]:
model_node_id = node["node_ids"][0]
break
if model_node_id:
model_list_key = None
print(workflow[model_node_id]["class_type"])
for key in info[workflow[model_node_id]["class_type"]]["input"][
"required"
]:
if "_name" in key:
model_list_key = key
break
if model_list_key:
return list(
map(
lambda model: {"id": model, "name": model},
info[workflow[model_node_id]["class_type"]]["input"][
"required"
][model_list_key][0],
)
)
else:
return list(
map(
lambda model: {"id": model, "name": model},
info["CheckpointLoaderSimple"]["input"]["required"][
"ckpt_name"
][0],
)
)
elif (
app.state.config.ENGINE == "automatic1111" or app.state.config.ENGINE == ""
):
r = requests.get(
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models",
headers={"authorization": get_automatic1111_api_auth()},
)
models = r.json()
return list(
map(
lambda model: {"id": model["title"], "name": model["model_name"]},
models,
)
)
except Exception as e:
app.state.config.ENABLED = False
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
class GenerateImageForm(BaseModel):
model: Optional[str] = None
prompt: str
size: Optional[str] = None
n: int = 1
negative_prompt: Optional[str] = None
def save_b64_image(b64_str):
try:
image_id = str(uuid.uuid4())
if "," in b64_str:
header, encoded = b64_str.split(",", 1)
mime_type = header.split(";")[0]
img_data = base64.b64decode(encoded)
image_format = mimetypes.guess_extension(mime_type)
image_filename = f"{image_id}{image_format}"
file_path = IMAGE_CACHE_DIR / f"{image_filename}"
with open(file_path, "wb") as f:
f.write(img_data)
return image_filename
else:
image_filename = f"{image_id}.png"
file_path = IMAGE_CACHE_DIR.joinpath(image_filename)
img_data = base64.b64decode(b64_str)
# Write the image data to a file
with open(file_path, "wb") as f:
f.write(img_data)
return image_filename
except Exception as e:
log.exception(f"Error saving image: {e}")
return None
def save_url_image(url):
image_id = str(uuid.uuid4())
try:
r = requests.get(url)
r.raise_for_status()
if r.headers["content-type"].split("/")[0] == "image":
mime_type = r.headers["content-type"]
image_format = mimetypes.guess_extension(mime_type)
if not image_format:
raise ValueError("Could not determine image type from MIME type")
image_filename = f"{image_id}{image_format}"
file_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}")
with open(file_path, "wb") as image_file:
for chunk in r.iter_content(chunk_size=8192):
image_file.write(chunk)
return image_filename
else:
log.error("Url does not point to an image.")
return None
except Exception as e:
log.exception(f"Error saving image: {e}")
return None
@app.post("/generations")
async def image_generations(
form_data: GenerateImageForm,
user=Depends(get_verified_user),
):
width, height = tuple(map(int, app.state.config.IMAGE_SIZE.split("x")))
r = None
try:
if app.state.config.ENGINE == "openai":
headers = {}
headers["Authorization"] = f"Bearer {app.state.config.OPENAI_API_KEY}"
headers["Content-Type"] = "application/json"
data = {
"model": (
app.state.config.MODEL
if app.state.config.MODEL != ""
else "dall-e-2"
),
"prompt": form_data.prompt,
"n": form_data.n,
"size": (
form_data.size if form_data.size else app.state.config.IMAGE_SIZE
),
"response_format": "b64_json",
}
# Use asyncio.to_thread for the requests.post call
r = await asyncio.to_thread(
requests.post,
url=f"{app.state.config.OPENAI_API_BASE_URL}/images/generations",
json=data,
headers=headers,
)
r.raise_for_status()
res = r.json()
images = []
for image in res["data"]:
image_filename = save_b64_image(image["b64_json"])
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump(data, f)
return images
elif app.state.config.ENGINE == "comfyui":
data = {
"prompt": form_data.prompt,
"width": width,
"height": height,
"n": form_data.n,
}
if app.state.config.IMAGE_STEPS is not None:
data["steps"] = app.state.config.IMAGE_STEPS
if form_data.negative_prompt is not None:
data["negative_prompt"] = form_data.negative_prompt
form_data = ComfyUIGenerateImageForm(
**{
"workflow": ComfyUIWorkflow(
**{
"workflow": app.state.config.COMFYUI_WORKFLOW,
"nodes": app.state.config.COMFYUI_WORKFLOW_NODES,
}
),
**data,
}
)
res = await comfyui_generate_image(
app.state.config.MODEL,
form_data,
user.id,
app.state.config.COMFYUI_BASE_URL,
)
log.debug(f"res: {res}")
images = []
for image in res["data"]:
image_filename = save_url_image(image["url"])
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump(form_data.model_dump(exclude_none=True), f)
log.debug(f"images: {images}")
return images
elif (
app.state.config.ENGINE == "automatic1111" or app.state.config.ENGINE == ""
):
if form_data.model:
set_image_model(form_data.model)
data = {
"prompt": form_data.prompt,
"batch_size": form_data.n,
"width": width,
"height": height,
}
if app.state.config.IMAGE_STEPS is not None:
data["steps"] = app.state.config.IMAGE_STEPS
if form_data.negative_prompt is not None:
data["negative_prompt"] = form_data.negative_prompt
if app.state.config.AUTOMATIC1111_CFG_SCALE:
data["cfg_scale"] = app.state.config.AUTOMATIC1111_CFG_SCALE
if app.state.config.AUTOMATIC1111_SAMPLER:
data["sampler_name"] = app.state.config.AUTOMATIC1111_SAMPLER
if app.state.config.AUTOMATIC1111_SCHEDULER:
data["scheduler"] = app.state.config.AUTOMATIC1111_SCHEDULER
# Use asyncio.to_thread for the requests.post call
r = await asyncio.to_thread(
requests.post,
url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/txt2img",
json=data,
headers={"authorization": get_automatic1111_api_auth()},
)
res = r.json()
log.debug(f"res: {res}")
images = []
for image in res["images"]:
image_filename = save_b64_image(image)
images.append({"url": f"/cache/image/generations/{image_filename}"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
with open(file_body_path, "w") as f:
json.dump({**data, "info": res["info"]}, f)
return images
except Exception as e:
error = e
if r != None:
data = r.json()
if "error" in data:
error = data["error"]["message"]
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(error))

View File

@@ -0,0 +1,174 @@
import asyncio
import json
import logging
import random
import urllib.parse
import urllib.request
from typing import Optional
import websocket # NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["COMFYUI"])
default_headers = {"User-Agent": "Mozilla/5.0"}
def queue_prompt(prompt, client_id, base_url):
log.info("queue_prompt")
p = {"prompt": prompt, "client_id": client_id}
data = json.dumps(p).encode("utf-8")
log.debug(f"queue_prompt data: {data}")
try:
req = urllib.request.Request(
f"{base_url}/prompt", data=data, headers=default_headers
)
response = urllib.request.urlopen(req).read()
return json.loads(response)
except Exception as e:
log.exception(f"Error while queuing prompt: {e}")
raise e
def get_image(filename, subfolder, folder_type, base_url):
log.info("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
req = urllib.request.Request(
f"{base_url}/view?{url_values}", headers=default_headers
)
with urllib.request.urlopen(req) as response:
return response.read()
def get_image_url(filename, subfolder, folder_type, base_url):
log.info("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
return f"{base_url}/view?{url_values}"
def get_history(prompt_id, base_url):
log.info("get_history")
req = urllib.request.Request(
f"{base_url}/history/{prompt_id}", headers=default_headers
)
with urllib.request.urlopen(req) as response:
return json.loads(response.read())
def get_images(ws, prompt, client_id, base_url):
prompt_id = queue_prompt(prompt, client_id, base_url)["prompt_id"]
output_images = []
while True:
out = ws.recv()
if isinstance(out, str):
message = json.loads(out)
if message["type"] == "executing":
data = message["data"]
if data["node"] is None and data["prompt_id"] == prompt_id:
break # Execution is done
else:
continue # previews are binary data
history = get_history(prompt_id, base_url)[prompt_id]
for o in history["outputs"]:
for node_id in history["outputs"]:
node_output = history["outputs"][node_id]
if "images" in node_output:
for image in node_output["images"]:
url = get_image_url(
image["filename"], image["subfolder"], image["type"], base_url
)
output_images.append({"url": url})
return {"data": output_images}
class ComfyUINodeInput(BaseModel):
type: Optional[str] = None
node_ids: list[str] = []
key: Optional[str] = "text"
value: Optional[str] = None
class ComfyUIWorkflow(BaseModel):
workflow: str
nodes: list[ComfyUINodeInput]
class ComfyUIGenerateImageForm(BaseModel):
workflow: ComfyUIWorkflow
prompt: str
negative_prompt: Optional[str] = None
width: int
height: int
n: int = 1
steps: Optional[int] = None
seed: Optional[int] = None
async def comfyui_generate_image(
model: str, payload: ComfyUIGenerateImageForm, client_id, base_url
):
ws_url = base_url.replace("http://", "ws://").replace("https://", "wss://")
workflow = json.loads(payload.workflow.workflow)
for node in payload.workflow.nodes:
if node.type:
if node.type == "model":
for node_id in node.node_ids:
workflow[node_id]["inputs"][node.key] = model
elif node.type == "prompt":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["text"] = payload.prompt
elif node.type == "negative_prompt":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["text"] = payload.negative_prompt
elif node.type == "width":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["width"] = payload.width
elif node.type == "height":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["height"] = payload.height
elif node.type == "n":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["batch_size"] = payload.n
elif node.type == "steps":
for node_id in node.node_ids:
workflow[node_id]["inputs"]["steps"] = payload.steps
elif node.type == "seed":
seed = (
payload.seed
if payload.seed
else random.randint(0, 18446744073709551614)
)
for node_id in node.node_ids:
workflow[node_id]["inputs"][node.key] = seed
else:
for node_id in node.node_ids:
workflow[node_id]["inputs"][node.key] = node.value
try:
ws = websocket.WebSocket()
ws.connect(f"{ws_url}/ws?clientId={client_id}")
log.info("WebSocket connection established.")
except Exception as e:
log.exception(f"Failed to connect to WebSocket server: {e}")
return None
try:
log.info("Sending workflow to WebSocket server.")
log.info(f"Workflow: {workflow}")
images = await asyncio.to_thread(get_images, ws, workflow, client_id, base_url)
except Exception as e:
log.exception(f"Error while receiving images: {e}")
images = None
ws.close()
return images

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,39 @@
from fastapi import FastAPI, Request, Response, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
import requests
import aiohttp
import asyncio
import hashlib
import json
import logging
from pathlib import Path
from typing import Literal, Optional, overload
from pydantic import BaseModel
from apps.webui.models.models import Models
from apps.webui.models.users import Users
from constants import ERROR_MESSAGES
from utils.utils import (
decode_token,
get_current_user,
get_verified_user,
get_admin_user,
)
from config import (
SRC_LOG_LEVELS,
import aiohttp
import requests
from open_webui.apps.webui.models.models import Models
from open_webui.config import (
AIOHTTP_CLIENT_TIMEOUT,
CACHE_DIR,
CORS_ALLOW_ORIGIN,
ENABLE_MODEL_FILTER,
ENABLE_OPENAI_API,
MODEL_FILTER_LIST,
OPENAI_API_BASE_URLS,
OPENAI_API_KEYS,
CACHE_DIR,
ENABLE_MODEL_FILTER,
MODEL_FILTER_LIST,
AppConfig,
)
from typing import List, Optional
from open_webui.constants import ERROR_MESSAGES
from open_webui.env import SRC_LOG_LEVELS
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, StreamingResponse
from pydantic import BaseModel
from starlette.background import BackgroundTask
import hashlib
from pathlib import Path
from open_webui.utils.payload import (
apply_model_params_to_body_openai,
apply_model_system_prompt_to_body,
)
from open_webui.utils.utils import get_admin_user, get_verified_user
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["OPENAI"])
@@ -41,7 +41,7 @@ log.setLevel(SRC_LOG_LEVELS["OPENAI"])
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_origins=CORS_ALLOW_ORIGIN,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
@@ -64,8 +64,6 @@ app.state.MODELS = {}
async def check_url(request: Request, call_next):
if len(app.state.MODELS) == 0:
await get_all_models()
else:
pass
response = await call_next(request)
return response
@@ -87,11 +85,11 @@ async def update_config(form_data: OpenAIConfigForm, user=Depends(get_admin_user
class UrlsUpdateForm(BaseModel):
urls: List[str]
urls: list[str]
class KeysUpdateForm(BaseModel):
keys: List[str]
keys: list[str]
@app.get("/urls")
@@ -170,7 +168,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
res = r.json()
if "error" in res:
error_detail = f"External: {res['error']}"
except:
except Exception:
error_detail = f"External: {e}"
raise HTTPException(
@@ -185,7 +183,7 @@ async def fetch_url(url, key):
timeout = aiohttp.ClientTimeout(total=5)
try:
headers = {"Authorization": f"Bearer {key}"}
async with aiohttp.ClientSession(timeout=timeout) as session:
async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
async with session.get(url, headers=headers) as response:
return await response.json()
except Exception as e:
@@ -194,6 +192,16 @@ async def fetch_url(url, key):
return None
async def cleanup_response(
response: Optional[aiohttp.ClientResponse],
session: Optional[aiohttp.ClientSession],
):
if response:
response.close()
if session:
await session.close()
def merge_models_lists(model_lists):
log.debug(f"merge_models_lists {model_lists}")
merged_list = []
@@ -212,58 +220,93 @@ def merge_models_lists(model_lists):
for model in models
if "api.openai.com"
not in app.state.config.OPENAI_API_BASE_URLS[idx]
or "gpt" in model["id"]
or not any(
name in model["id"]
for name in [
"babbage",
"dall-e",
"davinci",
"embedding",
"tts",
"whisper",
]
)
]
)
return merged_list
async def get_all_models(raw: bool = False):
def is_openai_api_disabled():
api_keys = app.state.config.OPENAI_API_KEYS
no_keys = len(api_keys) == 1 and api_keys[0] == ""
return no_keys or not app.state.config.ENABLE_OPENAI_API
async def get_all_models_raw() -> list:
if is_openai_api_disabled():
return []
# Check if API KEYS length is same than API URLS length
num_urls = len(app.state.config.OPENAI_API_BASE_URLS)
num_keys = len(app.state.config.OPENAI_API_KEYS)
if num_keys != num_urls:
# if there are more keys than urls, remove the extra keys
if num_keys > num_urls:
new_keys = app.state.config.OPENAI_API_KEYS[:num_urls]
app.state.config.OPENAI_API_KEYS = new_keys
# if there are more urls than keys, add empty keys
else:
app.state.config.OPENAI_API_KEYS += [""] * (num_urls - num_keys)
tasks = [
fetch_url(f"{url}/models", app.state.config.OPENAI_API_KEYS[idx])
for idx, url in enumerate(app.state.config.OPENAI_API_BASE_URLS)
]
responses = await asyncio.gather(*tasks)
log.debug(f"get_all_models:responses() {responses}")
return responses
@overload
async def get_all_models(raw: Literal[True]) -> list: ...
@overload
async def get_all_models(raw: Literal[False] = False) -> dict[str, list]: ...
async def get_all_models(raw=False) -> dict[str, list] | list:
log.info("get_all_models()")
if is_openai_api_disabled():
return [] if raw else {"data": []}
if (
len(app.state.config.OPENAI_API_KEYS) == 1
and app.state.config.OPENAI_API_KEYS[0] == ""
) or not app.state.config.ENABLE_OPENAI_API:
models = {"data": []}
else:
tasks = [
fetch_url(f"{url}/models", app.state.config.OPENAI_API_KEYS[idx])
for idx, url in enumerate(app.state.config.OPENAI_API_BASE_URLS)
]
responses = await get_all_models_raw()
if raw:
return responses
responses = await asyncio.gather(*tasks)
log.debug(f"get_all_models:responses() {responses}")
def extract_data(response):
if response and "data" in response:
return response["data"]
if isinstance(response, list):
return response
return None
if raw:
return responses
models = {"data": merge_models_lists(map(extract_data, responses))}
models = {
"data": merge_models_lists(
list(
map(
lambda response: (
response["data"]
if (response and "data" in response)
else (response if isinstance(response, list) else None)
),
responses,
)
)
)
}
log.debug(f"models: {models}")
app.state.MODELS = {model["id"]: model for model in models["data"]}
log.debug(f"models: {models}")
app.state.MODELS = {model["id"]: model for model in models["data"]}
return models
@app.get("/models")
@app.get("/models/{url_idx}")
async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_user)):
if url_idx == None:
async def get_models(url_idx: Optional[int] = None, user=Depends(get_verified_user)):
if url_idx is None:
models = await get_all_models()
if app.state.config.ENABLE_MODEL_FILTER:
if user.role == "user":
@@ -290,10 +333,24 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
r.raise_for_status()
response_data = r.json()
if "api.openai.com" in url:
response_data["data"] = list(
filter(lambda model: "gpt" in model["id"], response_data["data"])
)
# Filter the response data
response_data["data"] = [
model
for model in response_data["data"]
if not any(
name in model["id"]
for name in [
"babbage",
"dall-e",
"davinci",
"embedding",
"tts",
"whisper",
]
)
]
return response_data
except Exception as e:
@@ -304,7 +361,7 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
res = r.json()
if "error" in res:
error_detail = f"External: {res['error']}"
except:
except Exception:
error_detail = f"External: {e}"
raise HTTPException(
@@ -313,108 +370,124 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
)
@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}
if "metadata" in payload:
del payload["metadata"]
model_id = form_data.get("model")
model_info = Models.get_model_by_id(model_id)
if model_info:
if model_info.base_model_id:
payload["model"] = model_info.base_model_id
params = model_info.params.model_dump()
payload = apply_model_params_to_body_openai(params, payload)
payload = apply_model_system_prompt_to_body(params, payload, user)
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,
"email": user.email,
"role": user.role,
}
url = app.state.config.OPENAI_API_BASE_URLS[idx]
key = app.state.config.OPENAI_API_KEYS[idx]
# Change max_completion_tokens to max_tokens (Backward compatible)
if "api.openai.com" not in url and not payload["model"].lower().startswith("o1-"):
if "max_completion_tokens" in payload:
# Remove "max_completion_tokens" from the payload
payload["max_tokens"] = payload["max_completion_tokens"]
del payload["max_completion_tokens"]
else:
if "max_tokens" in payload and "max_completion_tokens" in payload:
del payload["max_tokens"]
# Convert the modified body back to JSON
payload = json.dumps(payload)
log.debug(payload)
headers = {}
headers["Authorization"] = f"Bearer {key}"
headers["Content-Type"] = "application/json"
if "openrouter.ai" in app.state.config.OPENAI_API_BASE_URLS[idx]:
headers["HTTP-Referer"] = "https://openwebui.com/"
headers["X-Title"] = "Open WebUI"
r = None
session = None
streaming = False
response = None
try:
session = aiohttp.ClientSession(
trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT)
)
r = await session.request(
method="POST",
url=f"{url}/chat/completions",
data=payload,
headers=headers,
)
# 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:
try:
response = await r.json()
except Exception as e:
log.error(e)
response = await r.text()
r.raise_for_status()
return response
except Exception as e:
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if isinstance(response, dict):
if "error" in response:
error_detail = f"{response['error']['message'] if 'message' in response['error'] else response['error']}"
elif isinstance(response, str):
error_detail = response
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()
# 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)
payload = None
try:
if "chat/completions" in path:
body = body.decode("utf-8")
body = json.loads(body)
payload = {**body}
model_id = body.get("model")
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
model_info.params = model_info.params.model_dump()
if model_info.params:
if model_info.params.get("temperature", None):
payload["temperature"] = int(
model_info.params.get("temperature")
)
if model_info.params.get("top_p", None):
payload["top_p"] = int(model_info.params.get("top_p", None))
if model_info.params.get("max_tokens", None):
payload["max_tokens"] = int(
model_info.params.get("max_tokens", None)
)
if model_info.params.get("frequency_penalty", None):
payload["frequency_penalty"] = int(
model_info.params.get("frequency_penalty", None)
)
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),
},
)
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)
print(payload)
url = app.state.config.OPENAI_API_BASE_URLS[idx]
key = app.state.config.OPENAI_API_KEYS[idx]
@@ -426,40 +499,48 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
headers["Content-Type"] = "application/json"
r = None
session = None
streaming = False
try:
r = requests.request(
session = aiohttp.ClientSession(trust_env=True)
r = await session.request(
method=request.method,
url=target_url,
data=payload if payload else body,
data=body,
headers=headers,
stream=True,
)
r.raise_for_status()
# Check if response is SSE
if "text/event-stream" in r.headers.get("Content-Type", ""):
streaming = True
return StreamingResponse(
r.iter_content(chunk_size=8192),
status_code=r.status_code,
r.content,
status_code=r.status,
headers=dict(r.headers),
background=BackgroundTask(
cleanup_response, response=r, session=session
),
)
else:
response_data = r.json()
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 = r.json()
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:
except Exception:
error_detail = f"External: {e}"
raise HTTPException(
status_code=r.status_code if r else 500, detail=error_detail
)
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()

View File

@@ -1,15 +1,17 @@
import logging
from typing import Optional
import requests
from apps.rag.search.main import SearchResult
from config import SRC_LOG_LEVELS
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_brave(api_key: str, query: str, count: int) -> list[SearchResult]:
def search_brave(
api_key: str, query: str, count: int, filter_list: Optional[list[str]] = None
) -> list[SearchResult]:
"""Search using Brave's Search API and return the results as a list of SearchResult objects.
Args:
@@ -29,6 +31,9 @@ def search_brave(api_key: str, query: str, count: int) -> list[SearchResult]:
json_response = response.json()
results = json_response.get("web", {}).get("results", [])
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["url"], title=result.get("title"), snippet=result.get("snippet")

View File

@@ -0,0 +1,50 @@
import logging
from typing import Optional
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from duckduckgo_search import DDGS
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_duckduckgo(
query: str, count: int, filter_list: Optional[list[str]] = None
) -> list[SearchResult]:
"""
Search using DuckDuckGo's Search API and return the results as a list of SearchResult objects.
Args:
query (str): The query to search for
count (int): The number of results to return
Returns:
list[SearchResult]: A list of search results
"""
# Use the DDGS context manager to create a DDGS object
with DDGS() as ddgs:
# Use the ddgs.text() method to perform the search
ddgs_gen = ddgs.text(
query, safesearch="moderate", max_results=count, backend="api"
)
# Check if there are search results
if ddgs_gen:
# Convert the search results into a list
search_results = [r for r in ddgs_gen]
# Create an empty list to store the SearchResult objects
results = []
# Iterate over each search result
for result in search_results:
# Create a SearchResult object and append it to the results list
results.append(
SearchResult(
link=result["href"],
title=result.get("title"),
snippet=result.get("body"),
)
)
if filter_list:
results = get_filtered_results(results, filter_list)
# Return the list of search results
return results

View File

@@ -1,17 +1,20 @@
import json
import logging
from typing import Optional
import requests
from apps.rag.search.main import SearchResult
from config import SRC_LOG_LEVELS
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_google_pse(
api_key: str, search_engine_id: str, query: str, count: int
api_key: str,
search_engine_id: str,
query: str,
count: int,
filter_list: Optional[list[str]] = None,
) -> list[SearchResult]:
"""Search using Google's Programmable Search Engine API and return the results as a list of SearchResult objects.
@@ -35,6 +38,8 @@ def search_google_pse(
json_response = response.json()
results = json_response.get("items", [])
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["link"],

View File

@@ -0,0 +1,41 @@
import logging
import requests
from open_webui.apps.rag.search.main import SearchResult
from open_webui.env import SRC_LOG_LEVELS
from yarl import URL
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_jina(query: str, count: int) -> list[SearchResult]:
"""
Search using Jina's Search API and return the results as a list of SearchResult objects.
Args:
query (str): The query to search for
count (int): The number of results to return
Returns:
list[SearchResult]: A list of search results
"""
jina_search_endpoint = "https://s.jina.ai/"
headers = {
"Accept": "application/json",
}
url = str(URL(jina_search_endpoint + query))
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
results = []
for result in data["data"][:count]:
results.append(
SearchResult(
link=result["url"],
title=result.get("title"),
snippet=result.get("content"),
)
)
return results

View File

@@ -0,0 +1,22 @@
from typing import Optional
from urllib.parse import urlparse
from pydantic import BaseModel
def get_filtered_results(results, filter_list):
if not filter_list:
return results
filtered_results = []
for result in results:
url = result.get("url") or result.get("link", "")
domain = urlparse(url).netloc
if any(domain.endswith(filtered_domain) for filtered_domain in filter_list):
filtered_results.append(result)
return filtered_results
class SearchResult(BaseModel):
link: str
title: Optional[str]
snippet: Optional[str]

View File

@@ -0,0 +1,48 @@
import logging
from typing import Optional
from urllib.parse import urlencode
import requests
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_searchapi(
api_key: str,
engine: str,
query: str,
count: int,
filter_list: Optional[list[str]] = None,
) -> list[SearchResult]:
"""Search using searchapi.io's API and return the results as a list of SearchResult objects.
Args:
api_key (str): A searchapi.io API key
query (str): The query to search for
"""
url = "https://www.searchapi.io/api/v1/search"
engine = engine or "google"
payload = {"engine": engine, "q": query, "api_key": api_key}
url = f"{url}?{urlencode(payload)}"
response = requests.request("GET", url)
json_response = response.json()
log.info(f"results from searchapi search: {json_response}")
results = sorted(
json_response.get("organic_results", []), key=lambda x: x.get("position", 0)
)
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["link"], title=result["title"], snippet=result["snippet"]
)
for result in results[:count]
]

View File

@@ -0,0 +1,91 @@
import logging
from typing import Optional
import requests
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_searxng(
query_url: str,
query: str,
count: int,
filter_list: Optional[list[str]] = None,
**kwargs,
) -> list[SearchResult]:
"""
Search a SearXNG instance for a given query and return the results as a list of SearchResult objects.
The function allows passing additional parameters such as language or time_range to tailor the search result.
Args:
query_url (str): The base URL of the SearXNG server.
query (str): The search term or question to find in the SearXNG database.
count (int): The maximum number of results to retrieve from the search.
Keyword Args:
language (str): Language filter for the search results; e.g., "en-US". Defaults to an empty string.
safesearch (int): Safe search filter for safer web results; 0 = off, 1 = moderate, 2 = strict. Defaults to 1 (moderate).
time_range (str): Time range for filtering results by date; e.g., "2023-04-05..today" or "all-time". Defaults to ''.
categories: (Optional[list[str]]): Specific categories within which the search should be performed, defaulting to an empty string if not provided.
Returns:
list[SearchResult]: A list of SearchResults sorted by relevance score in descending order.
Raise:
requests.exceptions.RequestException: If a request error occurs during the search process.
"""
# Default values for optional parameters are provided as empty strings or None when not specified.
language = kwargs.get("language", "en-US")
safesearch = kwargs.get("safesearch", "1")
time_range = kwargs.get("time_range", "")
categories = "".join(kwargs.get("categories", []))
params = {
"q": query,
"format": "json",
"pageno": 1,
"safesearch": safesearch,
"language": language,
"time_range": time_range,
"categories": categories,
"theme": "simple",
"image_proxy": 0,
}
# Legacy query format
if "<query>" in query_url:
# Strip all query parameters from the URL
query_url = query_url.split("?")[0]
log.debug(f"searching {query_url}")
response = requests.get(
query_url,
headers={
"User-Agent": "Open WebUI (https://github.com/open-webui/open-webui) RAG Bot",
"Accept": "text/html",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.5",
"Connection": "keep-alive",
},
params=params,
)
response.raise_for_status() # Raise an exception for HTTP errors.
json_response = response.json()
results = json_response.get("results", [])
sorted_results = sorted(results, key=lambda x: x.get("score", 0), reverse=True)
if filter_list:
sorted_results = get_filtered_results(sorted_results, filter_list)
return [
SearchResult(
link=result["url"], title=result.get("title"), snippet=result.get("content")
)
for result in sorted_results[:count]
]

View File

@@ -1,16 +1,18 @@
import json
import logging
from typing import Optional
import requests
from apps.rag.search.main import SearchResult
from config import SRC_LOG_LEVELS
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_serper(api_key: str, query: str, count: int) -> list[SearchResult]:
def search_serper(
api_key: str, query: str, count: int, filter_list: Optional[list[str]] = None
) -> list[SearchResult]:
"""Search using serper.dev's API and return the results as a list of SearchResult objects.
Args:
@@ -29,6 +31,8 @@ def search_serper(api_key: str, query: str, count: int) -> list[SearchResult]:
results = sorted(
json_response.get("organic", []), key=lambda x: x.get("position", 0)
)
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["link"],

View File

@@ -0,0 +1,69 @@
import logging
from typing import Optional
from urllib.parse import urlencode
import requests
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_serply(
api_key: str,
query: str,
count: int,
hl: str = "us",
limit: int = 10,
device_type: str = "desktop",
proxy_location: str = "US",
filter_list: Optional[list[str]] = None,
) -> list[SearchResult]:
"""Search using serper.dev's API and return the results as a list of SearchResult objects.
Args:
api_key (str): A serply.io API key
query (str): The query to search for
hl (str): Host Language code to display results in (reference https://developers.google.com/custom-search/docs/xml_results?hl=en#wsInterfaceLanguages)
limit (int): The maximum number of results to return [10-100, defaults to 10]
"""
log.info("Searching with Serply")
url = "https://api.serply.io/v1/search/"
query_payload = {
"q": query,
"language": "en",
"num": limit,
"gl": proxy_location.upper(),
"hl": hl.lower(),
}
url = f"{url}{urlencode(query_payload)}"
headers = {
"X-API-KEY": api_key,
"X-User-Agent": device_type,
"User-Agent": "open-webui",
"X-Proxy-Location": proxy_location,
}
response = requests.request("GET", url, headers=headers)
response.raise_for_status()
json_response = response.json()
log.info(f"results from serply search: {json_response}")
results = sorted(
json_response.get("results", []), key=lambda x: x.get("realPosition", 0)
)
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["link"],
title=result.get("title"),
snippet=result.get("description"),
)
for result in results[:count]
]

View File

@@ -1,17 +1,20 @@
import json
import logging
from typing import Optional
import requests
from apps.rag.search.main import SearchResult
from config import SRC_LOG_LEVELS
from open_webui.apps.rag.search.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_serpstack(
api_key: str, query: str, count: int, https_enabled: bool = True
api_key: str,
query: str,
count: int,
filter_list: Optional[list[str]] = None,
https_enabled: bool = True,
) -> list[SearchResult]:
"""Search using serpstack.com's and return the results as a list of SearchResult objects.
@@ -35,6 +38,8 @@ def search_serpstack(
results = sorted(
json_response.get("organic_results", []), key=lambda x: x.get("position", 0)
)
if filter_list:
results = get_filtered_results(results, filter_list)
return [
SearchResult(
link=result["url"], title=result.get("title"), snippet=result.get("snippet")

View File

@@ -0,0 +1,38 @@
import logging
import requests
from open_webui.apps.rag.search.main import SearchResult
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def search_tavily(api_key: str, query: str, count: int) -> list[SearchResult]:
"""Search using Tavily's Search API and return the results as a list of SearchResult objects.
Args:
api_key (str): A Tavily Search API key
query (str): The query to search for
Returns:
list[SearchResult]: A list of search results
"""
url = "https://api.tavily.com/search"
data = {"query": query, "api_key": api_key}
response = requests.post(url, json=data)
response.raise_for_status()
json_response = response.json()
raw_search_results = json_response.get("results", [])
return [
SearchResult(
link=result["url"],
title=result.get("title", ""),
snippet=result.get("content"),
)
for result in raw_search_results[:count]
]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,206 @@
{
"ads": [],
"ads_count": 0,
"answers": [],
"results": [
{
"title": "Apple",
"link": "https://www.apple.com/",
"description": "Discover the innovative world of Apple and shop everything iPhone, iPad, Apple Watch, Mac, and Apple TV, plus explore accessories, entertainment, ...",
"additional_links": [
{
"text": "AppleApplehttps://www.apple.com",
"href": "https://www.apple.com/"
}
],
"cite": {},
"subdomains": [
{
"title": "Support",
"link": "https://support.apple.com/",
"description": "SupportContact - iPhone Support - Billing and Subscriptions - Apple Repair"
},
{
"title": "Store",
"link": "https://www.apple.com/store",
"description": "StoreShop iPhone - Shop iPad - App Store - Shop Mac - ..."
},
{
"title": "Mac",
"link": "https://www.apple.com/mac/",
"description": "MacMacBook Air - MacBook Pro - iMac - Compare Mac models - Mac mini"
},
{
"title": "iPad",
"link": "https://www.apple.com/ipad/",
"description": "iPadShop iPad - iPad Pro - iPad Air - Compare iPad models - ..."
},
{
"title": "Watch",
"link": "https://www.apple.com/watch/",
"description": "WatchShop Apple Watch - Series 9 - SE - Ultra 2 - Nike - Hermès - ..."
}
],
"realPosition": 1
},
{
"title": "Apple",
"link": "https://www.apple.com/",
"description": "Discover the innovative world of Apple and shop everything iPhone, iPad, Apple Watch, Mac, and Apple TV, plus explore accessories, entertainment, ...",
"additional_links": [
{
"text": "AppleApplehttps://www.apple.com",
"href": "https://www.apple.com/"
}
],
"cite": {},
"realPosition": 2
},
{
"title": "Apple Inc.",
"link": "https://en.wikipedia.org/wiki/Apple_Inc.",
"description": "Apple Inc. (formerly Apple Computer, Inc.) is an American multinational corporation and technology company headquartered in Cupertino, California, ...",
"additional_links": [
{
"text": "Apple Inc.Wikipediahttps://en.wikipedia.org wiki Apple_Inc",
"href": "https://en.wikipedia.org/wiki/Apple_Inc."
},
{
"text": "",
"href": "https://en.wikipedia.org/wiki/Apple_Inc."
},
{
"text": "History",
"href": "https://en.wikipedia.org/wiki/History_of_Apple_Inc."
},
{
"text": "List of Apple products",
"href": "https://en.wikipedia.org/wiki/List_of_Apple_products"
},
{
"text": "Litigation involving Apple Inc.",
"href": "https://en.wikipedia.org/wiki/Litigation_involving_Apple_Inc."
},
{
"text": "Apple Park",
"href": "https://en.wikipedia.org/wiki/Apple_Park"
}
],
"cite": {
"domain": "https://en.wikipedia.org wiki Apple_Inc",
"span": " wiki Apple_Inc"
},
"realPosition": 3
},
{
"title": "Apple Inc. (AAPL) Company Profile & Facts",
"link": "https://finance.yahoo.com/quote/AAPL/profile/",
"description": "Apple Inc. designs, manufactures, and markets smartphones, personal computers, tablets, wearables, and accessories worldwide. The company offers iPhone, a line ...",
"additional_links": [
{
"text": "Apple Inc. (AAPL) Company Profile & FactsYahoo Financehttps://finance.yahoo.com quote AAPL profile",
"href": "https://finance.yahoo.com/quote/AAPL/profile/"
}
],
"cite": {
"domain": "https://finance.yahoo.com quote AAPL profile",
"span": " quote AAPL profile"
},
"realPosition": 4
},
{
"title": "Apple Inc - Company Profile and News",
"link": "https://www.bloomberg.com/profile/company/AAPL:US",
"description": "Apple Inc. Apple Inc. designs, manufactures, and markets smartphones, personal computers, tablets, wearables and accessories, and sells a variety of related ...",
"additional_links": [
{
"text": "Apple Inc - Company Profile and NewsBloomberghttps://www.bloomberg.com company AAPL:US",
"href": "https://www.bloomberg.com/profile/company/AAPL:US"
},
{
"text": "",
"href": "https://www.bloomberg.com/profile/company/AAPL:US"
}
],
"cite": {
"domain": "https://www.bloomberg.com company AAPL:US",
"span": " company AAPL:US"
},
"realPosition": 5
},
{
"title": "Apple Inc. | History, Products, Headquarters, & Facts",
"link": "https://www.britannica.com/money/Apple-Inc",
"description": "May 22, 2024 — Apple Inc. is an American multinational technology company that revolutionized the technology sector through its innovation of computer ...",
"additional_links": [
{
"text": "Apple Inc. | History, Products, Headquarters, & FactsBritannicahttps://www.britannica.com money Apple-Inc",
"href": "https://www.britannica.com/money/Apple-Inc"
},
{
"text": "",
"href": "https://www.britannica.com/money/Apple-Inc"
}
],
"cite": {
"domain": "https://www.britannica.com money Apple-Inc",
"span": " money Apple-Inc"
},
"realPosition": 6
}
],
"shopping_ads": [],
"places": [
{
"title": "Apple Inc."
},
{
"title": "Apple Inc"
},
{
"title": "Apple Inc"
}
],
"related_searches": {
"images": [],
"text": [
{
"title": "apple inc full form",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Inc+full+form&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhPEAE"
},
{
"title": "apple company history",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+company+history&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhOEAE"
},
{
"title": "apple store",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Store&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhQEAE"
},
{
"title": "apple id",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+id&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhSEAE"
},
{
"title": "apple inc industry",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Inc+industry&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhREAE"
},
{
"title": "apple login",
"link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+login&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhTEAE"
}
]
},
"image_results": [],
"carousel": [],
"total": 2450000000,
"knowledge_graph": "",
"related_questions": [
"What does the Apple Inc do?",
"Why did Apple change to Apple Inc?",
"Who owns Apple Inc.?",
"What is Apple Inc best known for?"
],
"carousel_count": 0,
"ts": 2.491065263748169,
"device_type": null
}

View File

@@ -1,42 +1,68 @@
import os
import logging
import os
import uuid
from typing import Optional, Union
import requests
from typing import List
from apps.ollama.main import (
generate_ollama_embeddings,
GenerateEmbeddingsForm,
)
from huggingface_hub import snapshot_download
from langchain_core.documents import Document
from langchain.retrievers import ContextualCompressionRetriever, EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain.retrievers import (
ContextualCompressionRetriever,
EnsembleRetriever,
from langchain_core.documents import Document
from open_webui.apps.ollama.main import (
GenerateEmbeddingsForm,
generate_ollama_embeddings,
)
from open_webui.apps.rag.vector.connector import VECTOR_DB_CLIENT
from open_webui.utils.misc import get_last_user_message
from typing import Optional
from open_webui.env import SRC_LOG_LEVELS
from config import (
SRC_LOG_LEVELS,
CHROMA_CLIENT,
SEARXNG_QUERY_URL,
GOOGLE_PSE_API_KEY,
GOOGLE_PSE_ENGINE_ID,
BRAVE_SEARCH_API_KEY,
SERPSTACK_API_KEY,
SERPSTACK_HTTPS,
SERPER_API_KEY,
)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
from typing import Any
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.retrievers import BaseRetriever
class VectorSearchRetriever(BaseRetriever):
collection_name: Any
embedding_function: Any
top_k: int
def _get_relevant_documents(
self,
query: str,
*,
run_manager: CallbackManagerForRetrieverRun,
) -> list[Document]:
result = VECTOR_DB_CLIENT.search(
collection_name=self.collection_name,
vectors=[self.embedding_function(query)],
limit=self.top_k,
)
ids = result.ids[0]
metadatas = result.metadatas[0]
documents = result.documents[0]
results = []
for idx in range(len(ids)):
results.append(
Document(
metadata=metadatas[idx],
page_content=documents[idx],
)
)
return results
def query_doc(
collection_name: str,
query: str,
@@ -44,17 +70,18 @@ def query_doc(
k: int,
):
try:
collection = CHROMA_CLIENT.get_collection(name=collection_name)
query_embeddings = embedding_function(query)
result = collection.query(
query_embeddings=[query_embeddings],
n_results=k,
result = VECTOR_DB_CLIENT.search(
collection_name=collection_name,
vectors=[embedding_function(query)],
limit=k,
)
print("result", result)
log.info(f"query_doc:result {result}")
return result
except Exception as e:
print(e)
raise e
@@ -65,27 +92,25 @@ def query_doc_with_hybrid_search(
k: int,
reranking_function,
r: float,
):
) -> dict:
try:
collection = CHROMA_CLIENT.get_collection(name=collection_name)
documents = collection.get() # get all documents
result = VECTOR_DB_CLIENT.get(collection_name=collection_name)
bm25_retriever = BM25Retriever.from_texts(
texts=documents.get("documents"),
metadatas=documents.get("metadatas"),
texts=result.documents[0],
metadatas=result.metadatas[0],
)
bm25_retriever.k = k
chroma_retriever = ChromaRetriever(
collection=collection,
vector_search_retriever = VectorSearchRetriever(
collection_name=collection_name,
embedding_function=embedding_function,
top_n=k,
top_k=k,
)
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, chroma_retriever], weights=[0.5, 0.5]
retrievers=[bm25_retriever, vector_search_retriever], weights=[0.5, 0.5]
)
compressor = RerankCompressor(
embedding_function=embedding_function,
top_n=k,
@@ -110,7 +135,9 @@ def query_doc_with_hybrid_search(
raise e
def merge_and_sort_query_results(query_results, k, reverse=False):
def merge_and_sort_query_results(
query_results: list[dict], k: int, reverse: bool = False
) -> list[dict]:
# Initialize lists to store combined data
combined_distances = []
combined_documents = []
@@ -152,35 +179,40 @@ def merge_and_sort_query_results(query_results, k, reverse=False):
def query_collection(
collection_names: List[str],
collection_names: list[str],
query: str,
embedding_function,
k: int,
):
) -> dict:
results = []
for collection_name in collection_names:
try:
result = query_doc(
collection_name=collection_name,
query=query,
k=k,
embedding_function=embedding_function,
)
results.append(result)
except:
if collection_name:
try:
result = query_doc(
collection_name=collection_name,
query=query,
k=k,
embedding_function=embedding_function,
)
results.append(result.model_dump())
except Exception as e:
log.exception(f"Error when querying the collection: {e}")
else:
pass
return merge_and_sort_query_results(results, k=k)
def query_collection_with_hybrid_search(
collection_names: List[str],
collection_names: list[str],
query: str,
embedding_function,
k: int,
reranking_function,
r: float,
):
) -> dict:
results = []
error = False
for collection_name in collection_names:
try:
result = query_doc_with_hybrid_search(
@@ -192,14 +224,39 @@ def query_collection_with_hybrid_search(
r=r,
)
results.append(result)
except:
pass
except Exception as e:
log.exception(
"Error when querying the collection with " f"hybrid_search: {e}"
)
error = True
if error:
raise Exception(
"Hybrid search failed for all collections. Using Non hybrid search as fallback."
)
return merge_and_sort_query_results(results, k=k, reverse=True)
def rag_template(template: str, context: str, query: str):
template = template.replace("[context]", context)
template = template.replace("[query]", query)
count = template.count("[context]")
assert "[context]" in template, "RAG template does not contain '[context]'"
if "<context>" in context and "</context>" in context:
log.debug(
"WARNING: Potential prompt injection attack: the RAG "
"context contains '<context>' and '</context>'. This might be "
"nothing, or the user might be trying to hack something."
)
if "[query]" in context:
query_placeholder = f"[query-{str(uuid.uuid4())}]"
template = template.replace("[query]", query_placeholder)
template = template.replace("[context]", context)
template = template.replace(query_placeholder, query)
else:
template = template.replace("[context]", context)
template = template.replace("[query]", query)
return template
@@ -209,6 +266,7 @@ def get_embedding_function(
embedding_function,
openai_key,
openai_url,
batch_size,
):
if embedding_engine == "":
return lambda query: embedding_function.encode(query).tolist()
@@ -232,81 +290,70 @@ def get_embedding_function(
def generate_multiple(query, f):
if isinstance(query, list):
return [f(q) for q in query]
if embedding_engine == "openai":
embeddings = []
for i in range(0, len(query), batch_size):
embeddings.extend(f(query[i : i + batch_size]))
return embeddings
else:
return [f(q) for q in query]
else:
return f(query)
return lambda query: generate_multiple(query, func)
def rag_messages(
docs,
def get_rag_context(
files,
messages,
template,
embedding_function,
k,
reranking_function,
r,
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 = ""
log.debug(f"files: {files} {messages} {embedding_function} {reranking_function}")
query = get_last_user_message(messages)
extracted_collections = []
relevant_contexts = []
for doc in docs:
for file in files:
context = None
collection_names = (
doc["collection_names"]
if doc["type"] == "collection"
else [doc["collection_name"]]
file["collection_names"]
if file["type"] == "collection"
else [file["collection_name"]] if file["collection_name"] else []
)
collection_names = set(collection_names).difference(extracted_collections)
if not collection_names:
log.debug(f"skipping {doc} as it has already been extracted")
log.debug(f"skipping {file} as it has already been extracted")
continue
try:
if doc["type"] == "text":
context = doc["content"]
context = None
if file["type"] == "text":
context = file["content"]
else:
if hybrid_search:
context = query_collection_with_hybrid_search(
collection_names=collection_names,
query=query,
embedding_function=embedding_function,
k=k,
reranking_function=reranking_function,
r=r,
)
else:
try:
context = query_collection_with_hybrid_search(
collection_names=collection_names,
query=query,
embedding_function=embedding_function,
k=k,
reranking_function=reranking_function,
r=r,
)
except Exception as e:
log.debug(
"Error when using hybrid search, using"
" non hybrid search as fallback."
)
if (not hybrid_search) or (context is None):
context = query_collection(
collection_names=collection_names,
query=query,
@@ -315,21 +362,22 @@ def rag_messages(
)
except Exception as e:
log.exception(e)
context = None
if context:
relevant_contexts.append({**context, "source": doc})
relevant_contexts.append({**context, "source": file})
extracted_collections.extend(collection_names)
context_string = ""
contexts = []
citations = []
for context in relevant_contexts:
try:
if "documents" in context:
context_string += "\n\n".join(
[text for text in context["documents"][0] if text is not None]
contexts.append(
"\n\n".join(
[text for text in context["documents"][0] if text is not None]
)
)
if "metadatas" in context:
@@ -343,35 +391,7 @@ def rag_messages(
except Exception as e:
log.exception(e)
context_string = context_string.strip()
ra_content = rag_template(
template=template,
context=context_string,
query=query,
)
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
return messages, citations
return contexts, citations
def get_model_path(model: str, update_model: bool = False):
@@ -413,8 +433,22 @@ def get_model_path(model: str, update_model: bool = False):
def generate_openai_embeddings(
model: str, text: str, key: str, url: str = "https://api.openai.com/v1"
model: str,
text: Union[str, list[str]],
key: str,
url: str = "https://api.openai.com/v1",
):
if isinstance(text, list):
embeddings = generate_openai_batch_embeddings(model, text, key, url)
else:
embeddings = generate_openai_batch_embeddings(model, [text], key, url)
return embeddings[0] if isinstance(text, str) else embeddings
def generate_openai_batch_embeddings(
model: str, texts: list[str], key: str, url: str = "https://api.openai.com/v1"
) -> Optional[list[list[float]]]:
try:
r = requests.post(
f"{url}/embeddings",
@@ -422,12 +456,12 @@ def generate_openai_embeddings(
"Content-Type": "application/json",
"Authorization": f"Bearer {key}",
},
json={"input": text, "model": model},
json={"input": texts, "model": model},
)
r.raise_for_status()
data = r.json()
if "data" in data:
return data["data"][0]["embedding"]
return [elem["embedding"] for elem in data["data"]]
else:
raise "Something went wrong :/"
except Exception as e:
@@ -435,54 +469,11 @@ def generate_openai_embeddings(
return None
from typing import Any
from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
class ChromaRetriever(BaseRetriever):
collection: Any
embedding_function: Any
top_n: int
def _get_relevant_documents(
self,
query: str,
*,
run_manager: CallbackManagerForRetrieverRun,
) -> List[Document]:
query_embeddings = self.embedding_function(query)
results = self.collection.query(
query_embeddings=[query_embeddings],
n_results=self.top_n,
)
ids = results["ids"][0]
metadatas = results["metadatas"][0]
documents = results["documents"][0]
results = []
for idx in range(len(ids)):
results.append(
Document(
metadata=metadatas[idx],
page_content=documents[idx],
)
)
return results
import operator
from typing import Optional, Sequence
from langchain_core.documents import BaseDocumentCompressor, Document
from langchain_core.callbacks import Callbacks
from langchain_core.pydantic_v1 import Extra
from sentence_transformers import util
from langchain_core.documents import BaseDocumentCompressor, Document
class RerankCompressor(BaseDocumentCompressor):
@@ -492,7 +483,7 @@ class RerankCompressor(BaseDocumentCompressor):
r_score: float
class Config:
extra = Extra.forbid
extra = "forbid"
arbitrary_types_allowed = True
def compress_documents(
@@ -508,6 +499,8 @@ class RerankCompressor(BaseDocumentCompressor):
[(query, doc.page_content) for doc in documents]
)
else:
from sentence_transformers import util
query_embedding = self.embedding_function(query)
document_embedding = self.embedding_function(
[doc.page_content for doc in documents]

View File

@@ -0,0 +1,10 @@
from open_webui.apps.rag.vector.dbs.chroma import ChromaClient
from open_webui.apps.rag.vector.dbs.milvus import MilvusClient
from open_webui.config import VECTOR_DB
if VECTOR_DB == "milvus":
VECTOR_DB_CLIENT = MilvusClient()
else:
VECTOR_DB_CLIENT = ChromaClient()

View File

@@ -0,0 +1,122 @@
import chromadb
from chromadb import Settings
from chromadb.utils.batch_utils import create_batches
from typing import Optional
from open_webui.apps.rag.vector.main import VectorItem, SearchResult, GetResult
from open_webui.config import (
CHROMA_DATA_PATH,
CHROMA_HTTP_HOST,
CHROMA_HTTP_PORT,
CHROMA_HTTP_HEADERS,
CHROMA_HTTP_SSL,
CHROMA_TENANT,
CHROMA_DATABASE,
)
class ChromaClient:
def __init__(self):
if CHROMA_HTTP_HOST != "":
self.client = chromadb.HttpClient(
host=CHROMA_HTTP_HOST,
port=CHROMA_HTTP_PORT,
headers=CHROMA_HTTP_HEADERS,
ssl=CHROMA_HTTP_SSL,
tenant=CHROMA_TENANT,
database=CHROMA_DATABASE,
settings=Settings(allow_reset=True, anonymized_telemetry=False),
)
else:
self.client = chromadb.PersistentClient(
path=CHROMA_DATA_PATH,
settings=Settings(allow_reset=True, anonymized_telemetry=False),
tenant=CHROMA_TENANT,
database=CHROMA_DATABASE,
)
def has_collection(self, collection_name: str) -> bool:
# Check if the collection exists based on the collection name.
collections = self.client.list_collections()
return collection_name in [collection.name for collection in collections]
def delete_collection(self, collection_name: str):
# Delete the collection based on the collection name.
return self.client.delete_collection(name=collection_name)
def search(
self, collection_name: str, vectors: list[list[float | int]], limit: int
) -> Optional[SearchResult]:
# Search for the nearest neighbor items based on the vectors and return 'limit' number of results.
collection = self.client.get_collection(name=collection_name)
if collection:
result = collection.query(
query_embeddings=vectors,
n_results=limit,
)
return SearchResult(
**{
"ids": result["ids"],
"distances": result["distances"],
"documents": result["documents"],
"metadatas": result["metadatas"],
}
)
return None
def get(self, collection_name: str) -> Optional[GetResult]:
# Get all the items in the collection.
collection = self.client.get_collection(name=collection_name)
if collection:
result = collection.get()
return GetResult(
**{
"ids": [result["ids"]],
"documents": [result["documents"]],
"metadatas": [result["metadatas"]],
}
)
return None
def insert(self, collection_name: str, items: list[VectorItem]):
# Insert the items into the collection, if the collection does not exist, it will be created.
collection = self.client.get_or_create_collection(name=collection_name)
ids = [item["id"] for item in items]
documents = [item["text"] for item in items]
embeddings = [item["vector"] for item in items]
metadatas = [item["metadata"] for item in items]
for batch in create_batches(
api=self.client,
documents=documents,
embeddings=embeddings,
ids=ids,
metadatas=metadatas,
):
collection.add(*batch)
def upsert(self, collection_name: str, items: list[VectorItem]):
# Update the items in the collection, if the items are not present, insert them. If the collection does not exist, it will be created.
collection = self.client.get_or_create_collection(name=collection_name)
ids = [item["id"] for item in items]
documents = [item["text"] for item in items]
embeddings = [item["vector"] for item in items]
metadatas = [item["metadata"] for item in items]
collection.upsert(
ids=ids, documents=documents, embeddings=embeddings, metadatas=metadatas
)
def delete(self, collection_name: str, ids: list[str]):
# Delete the items from the collection based on the ids.
collection = self.client.get_collection(name=collection_name)
if collection:
collection.delete(ids=ids)
def reset(self):
# Resets the database. This will delete all collections and item entries.
return self.client.reset()

View File

@@ -0,0 +1,205 @@
from pymilvus import MilvusClient as Client
from pymilvus import FieldSchema, DataType
import json
from typing import Optional
from open_webui.apps.rag.vector.main import VectorItem, SearchResult, GetResult
from open_webui.config import (
MILVUS_URI,
)
class MilvusClient:
def __init__(self):
self.collection_prefix = "open_webui"
self.client = Client(uri=MILVUS_URI)
def _result_to_get_result(self, result) -> GetResult:
print(result)
ids = []
documents = []
metadatas = []
for match in result:
_ids = []
_documents = []
_metadatas = []
for item in match:
_ids.append(item.get("id"))
_documents.append(item.get("data", {}).get("text"))
_metadatas.append(item.get("metadata"))
ids.append(_ids)
documents.append(_documents)
metadatas.append(_metadatas)
return GetResult(
**{
"ids": ids,
"documents": documents,
"metadatas": metadatas,
}
)
def _result_to_search_result(self, result) -> SearchResult:
print(result)
ids = []
distances = []
documents = []
metadatas = []
for match in result:
_ids = []
_distances = []
_documents = []
_metadatas = []
for item in match:
_ids.append(item.get("id"))
_distances.append(item.get("distance"))
_documents.append(item.get("entity", {}).get("data", {}).get("text"))
_metadatas.append(item.get("entity", {}).get("metadata"))
ids.append(_ids)
distances.append(_distances)
documents.append(_documents)
metadatas.append(_metadatas)
return SearchResult(
**{
"ids": ids,
"distances": distances,
"documents": documents,
"metadatas": metadatas,
}
)
def _create_collection(self, collection_name: str, dimension: int):
schema = self.client.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
schema.add_field(
field_name="id",
datatype=DataType.VARCHAR,
is_primary=True,
max_length=65535,
)
schema.add_field(
field_name="vector",
datatype=DataType.FLOAT_VECTOR,
dim=dimension,
description="vector",
)
schema.add_field(field_name="data", datatype=DataType.JSON, description="data")
schema.add_field(
field_name="metadata", datatype=DataType.JSON, description="metadata"
)
index_params = self.client.prepare_index_params()
index_params.add_index(
field_name="vector", index_type="HNSW", metric_type="COSINE", params={}
)
self.client.create_collection(
collection_name=f"{self.collection_prefix}_{collection_name}",
schema=schema,
index_params=index_params,
)
def has_collection(self, collection_name: str) -> bool:
# Check if the collection exists based on the collection name.
return self.client.has_collection(
collection_name=f"{self.collection_prefix}_{collection_name}"
)
def delete_collection(self, collection_name: str):
# Delete the collection based on the collection name.
return self.client.drop_collection(
collection_name=f"{self.collection_prefix}_{collection_name}"
)
def search(
self, collection_name: str, vectors: list[list[float | int]], limit: int
) -> Optional[SearchResult]:
# Search for the nearest neighbor items based on the vectors and return 'limit' number of results.
result = self.client.search(
collection_name=f"{self.collection_prefix}_{collection_name}",
data=vectors,
limit=limit,
output_fields=["data", "metadata"],
)
return self._result_to_search_result(result)
def get(self, collection_name: str) -> Optional[GetResult]:
# Get all the items in the collection.
result = self.client.query(
collection_name=f"{self.collection_prefix}_{collection_name}",
filter='id != ""',
)
return self._result_to_get_result([result])
def insert(self, collection_name: str, items: list[VectorItem]):
# Insert the items into the collection, if the collection does not exist, it will be created.
if not self.client.has_collection(
collection_name=f"{self.collection_prefix}_{collection_name}"
):
self._create_collection(
collection_name=collection_name, dimension=len(items[0]["vector"])
)
return self.client.insert(
collection_name=f"{self.collection_prefix}_{collection_name}",
data=[
{
"id": item["id"],
"vector": item["vector"],
"data": {"text": item["text"]},
"metadata": item["metadata"],
}
for item in items
],
)
def upsert(self, collection_name: str, items: list[VectorItem]):
# Update the items in the collection, if the items are not present, insert them. If the collection does not exist, it will be created.
if not self.client.has_collection(
collection_name=f"{self.collection_prefix}_{collection_name}"
):
self._create_collection(
collection_name=collection_name, dimension=len(items[0]["vector"])
)
return self.client.upsert(
collection_name=f"{self.collection_prefix}_{collection_name}",
data=[
{
"id": item["id"],
"vector": item["vector"],
"data": {"text": item["text"]},
"metadata": item["metadata"],
}
for item in items
],
)
def delete(self, collection_name: str, ids: list[str]):
# Delete the items from the collection based on the ids.
return self.client.delete(
collection_name=f"{self.collection_prefix}_{collection_name}",
ids=ids,
)
def reset(self):
# Resets the database. This will delete all collections and item entries.
collection_names = self.client.list_collections()
for collection_name in collection_names:
if collection_name.startswith(self.collection_prefix):
self.client.drop_collection(collection_name=collection_name)

View File

@@ -0,0 +1,19 @@
from pydantic import BaseModel
from typing import Optional, List, Any
class VectorItem(BaseModel):
id: str
text: str
vector: List[float | int]
metadata: Any
class GetResult(BaseModel):
ids: Optional[List[List[str]]]
documents: Optional[List[List[str]]]
metadatas: Optional[List[List[Any]]]
class SearchResult(GetResult):
distances: Optional[List[List[float | int]]]

View File

@@ -0,0 +1,219 @@
import asyncio
import socketio
import logging
import sys
import time
from open_webui.apps.webui.models.users import Users
from open_webui.env import (
ENABLE_WEBSOCKET_SUPPORT,
WEBSOCKET_MANAGER,
WEBSOCKET_REDIS_URL,
)
from open_webui.utils.utils import decode_token
from open_webui.apps.socket.utils import RedisDict
from open_webui.env import (
GLOBAL_LOG_LEVEL,
SRC_LOG_LEVELS,
)
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["SOCKET"])
if WEBSOCKET_MANAGER == "redis":
mgr = socketio.AsyncRedisManager(WEBSOCKET_REDIS_URL)
sio = socketio.AsyncServer(
cors_allowed_origins=[],
async_mode="asgi",
transports=(
["polling", "websocket"] if ENABLE_WEBSOCKET_SUPPORT else ["polling"]
),
allow_upgrades=ENABLE_WEBSOCKET_SUPPORT,
always_connect=True,
client_manager=mgr,
)
else:
sio = socketio.AsyncServer(
cors_allowed_origins=[],
async_mode="asgi",
transports=(
["polling", "websocket"] if ENABLE_WEBSOCKET_SUPPORT else ["polling"]
),
allow_upgrades=ENABLE_WEBSOCKET_SUPPORT,
always_connect=True,
)
# Dictionary to maintain the user pool
if WEBSOCKET_MANAGER == "redis":
SESSION_POOL = RedisDict("open-webui:session_pool", redis_url=WEBSOCKET_REDIS_URL)
USER_POOL = RedisDict("open-webui:user_pool", redis_url=WEBSOCKET_REDIS_URL)
USAGE_POOL = RedisDict("open-webui:usage_pool", redis_url=WEBSOCKET_REDIS_URL)
else:
SESSION_POOL = {}
USER_POOL = {}
USAGE_POOL = {}
# Timeout duration in seconds
TIMEOUT_DURATION = 3
async def periodic_usage_pool_cleanup():
while True:
now = int(time.time())
for model_id, connections in list(USAGE_POOL.items()):
# Creating a list of sids to remove if they have timed out
expired_sids = [
sid
for sid, details in connections.items()
if now - details["updated_at"] > TIMEOUT_DURATION
]
for sid in expired_sids:
del connections[sid]
if not connections:
log.debug(f"Cleaning up model {model_id} from usage pool")
del USAGE_POOL[model_id]
else:
USAGE_POOL[model_id] = connections
# Emit updated usage information after cleaning
await sio.emit("usage", {"models": get_models_in_use()})
await asyncio.sleep(TIMEOUT_DURATION)
app = socketio.ASGIApp(
sio,
socketio_path="/ws/socket.io",
)
def get_models_in_use():
# List models that are currently in use
models_in_use = list(USAGE_POOL.keys())
return models_in_use
@sio.on("usage")
async def usage(sid, data):
model_id = data["model"]
# Record the timestamp for the last update
current_time = int(time.time())
# Store the new usage data and task
USAGE_POOL[model_id] = {
**(USAGE_POOL[model_id] if model_id in USAGE_POOL else {}),
sid: {"updated_at": current_time},
}
# Broadcast the usage data to all clients
await sio.emit("usage", {"models": get_models_in_use()})
@sio.event
async def connect(sid, environ, auth):
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}")
await sio.emit("user-count", {"count": len(USER_POOL.items())})
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 not auth or "token" not in auth:
return
data = decode_token(auth["token"])
if data is None or "id" not in data:
return
user = Users.get_user_by_id(data["id"])
if not user:
return
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}")
await sio.emit("user-count", {"count": len(USER_POOL.items())})
@sio.on("user-count")
async def user_count(sid):
await sio.emit("user-count", {"count": len(USER_POOL.items())})
@sio.event
async def disconnect(sid):
if sid in SESSION_POOL:
user_id = SESSION_POOL[sid]
del SESSION_POOL[sid]
USER_POOL[user_id] = [_sid for _sid in USER_POOL[user_id] if _sid != sid]
if len(USER_POOL[user_id]) == 0:
del USER_POOL[user_id]
await sio.emit("user-count", {"count": len(USER_POOL)})
else:
pass
# print(f"Unknown session ID {sid} disconnected")
def get_event_emitter(request_info):
async def __event_emitter__(event_data):
await sio.emit(
"chat-events",
{
"chat_id": request_info["chat_id"],
"message_id": request_info["message_id"],
"data": event_data,
},
to=request_info["session_id"],
)
return __event_emitter__
def get_event_call(request_info):
async def __event_call__(event_data):
response = await sio.call(
"chat-events",
{
"chat_id": request_info["chat_id"],
"message_id": request_info["message_id"],
"data": event_data,
},
to=request_info["session_id"],
)
return response
return __event_call__

View File

@@ -0,0 +1,59 @@
import json
import redis
class RedisDict:
def __init__(self, name, redis_url):
self.name = name
self.redis = redis.Redis.from_url(redis_url, decode_responses=True)
def __setitem__(self, key, value):
serialized_value = json.dumps(value)
self.redis.hset(self.name, key, serialized_value)
def __getitem__(self, key):
value = self.redis.hget(self.name, key)
if value is None:
raise KeyError(key)
return json.loads(value)
def __delitem__(self, key):
result = self.redis.hdel(self.name, key)
if result == 0:
raise KeyError(key)
def __contains__(self, key):
return self.redis.hexists(self.name, key)
def __len__(self):
return self.redis.hlen(self.name)
def keys(self):
return self.redis.hkeys(self.name)
def values(self):
return [json.loads(v) for v in self.redis.hvals(self.name)]
def items(self):
return [(k, json.loads(v)) for k, v in self.redis.hgetall(self.name).items()]
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
def clear(self):
self.redis.delete(self.name)
def update(self, other=None, **kwargs):
if other is not None:
for k, v in other.items() if hasattr(other, "items") else other:
self[k] = v
for k, v in kwargs.items():
self[k] = v
def setdefault(self, key, default=None):
if key not in self:
self[key] = default
return self[key]

View File

@@ -0,0 +1,92 @@
import json
import logging
from contextlib import contextmanager
from typing import Any, Optional
from open_webui.apps.webui.internal.wrappers import register_connection
from open_webui.env import OPEN_WEBUI_DIR, DATABASE_URL, SRC_LOG_LEVELS
from peewee_migrate import Router
from sqlalchemy import Dialect, create_engine, types
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.sql.type_api import _T
from typing_extensions import Self
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["DB"])
class JSONField(types.TypeDecorator):
impl = types.Text
cache_ok = True
def process_bind_param(self, value: Optional[_T], dialect: Dialect) -> Any:
return json.dumps(value)
def process_result_value(self, value: Optional[_T], dialect: Dialect) -> Any:
if value is not None:
return json.loads(value)
def copy(self, **kw: Any) -> Self:
return JSONField(self.impl.length)
def db_value(self, value):
return json.dumps(value)
def python_value(self, value):
if value is not None:
return json.loads(value)
# Workaround to handle the peewee migration
# This is required to ensure the peewee migration is handled before the alembic migration
def handle_peewee_migration(DATABASE_URL):
# db = None
try:
# Replace the postgresql:// with postgres:// to handle the peewee migration
db = register_connection(DATABASE_URL.replace("postgresql://", "postgres://"))
migrate_dir = OPEN_WEBUI_DIR / "apps" / "webui" / "internal" / "migrations"
router = Router(db, logger=log, migrate_dir=migrate_dir)
router.run()
db.close()
except Exception as e:
log.error(f"Failed to initialize the database connection: {e}")
raise
finally:
# Properly closing the database connection
if db and not db.is_closed():
db.close()
# Assert if db connection has been closed
assert db.is_closed(), "Database connection is still open."
handle_peewee_migration(DATABASE_URL)
SQLALCHEMY_DATABASE_URL = DATABASE_URL
if "sqlite" in SQLALCHEMY_DATABASE_URL:
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
else:
engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True)
SessionLocal = sessionmaker(
autocommit=False, autoflush=False, bind=engine, expire_on_commit=False
)
Base = declarative_base()
Session = scoped_session(SessionLocal)
def get_session():
db = SessionLocal()
try:
yield db
finally:
db.close()
get_db = contextmanager(get_session)

View File

@@ -30,7 +30,7 @@ import peewee as pw
from peewee_migrate import Migrator
import json
from utils.misc import parse_ollama_modelfile
from open_webui.utils.misc import parse_ollama_modelfile
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext

View File

@@ -0,0 +1,61 @@
"""Peewee migrations -- 009_add_models.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
@migrator.create_model
class Tool(pw.Model):
id = pw.TextField(unique=True)
user_id = pw.TextField()
name = pw.TextField()
content = pw.TextField()
specs = pw.TextField()
meta = pw.TextField()
created_at = pw.BigIntegerField(null=False)
updated_at = pw.BigIntegerField(null=False)
class Meta:
table_name = "tool"
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_model("tool")

View File

@@ -0,0 +1,48 @@
"""Peewee migrations -- 002_add_local_sharing.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
# Adding fields info to the 'user' table
migrator.add_fields("user", info=pw.TextField(null=True))
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
# Remove the settings field
migrator.remove_fields("user", "info")

View File

@@ -0,0 +1,55 @@
"""Peewee migrations -- 009_add_models.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
@migrator.create_model
class File(pw.Model):
id = pw.TextField(unique=True)
user_id = pw.TextField()
filename = pw.TextField()
meta = pw.TextField()
created_at = pw.BigIntegerField(null=False)
class Meta:
table_name = "file"
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_model("file")

View File

@@ -0,0 +1,61 @@
"""Peewee migrations -- 009_add_models.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
@migrator.create_model
class Function(pw.Model):
id = pw.TextField(unique=True)
user_id = pw.TextField()
name = pw.TextField()
type = pw.TextField()
content = pw.TextField()
meta = pw.TextField()
created_at = pw.BigIntegerField(null=False)
updated_at = pw.BigIntegerField(null=False)
class Meta:
table_name = "function"
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_model("function")

View File

@@ -0,0 +1,50 @@
"""Peewee migrations -- 009_add_models.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
migrator.add_fields("tool", valves=pw.TextField(null=True))
migrator.add_fields("function", valves=pw.TextField(null=True))
migrator.add_fields("function", is_active=pw.BooleanField(default=False))
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_fields("tool", "valves")
migrator.remove_fields("function", "valves")
migrator.remove_fields("function", "is_active")

View File

@@ -0,0 +1,45 @@
"""Peewee migrations -- 017_add_user_oauth_sub.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
migrator.add_fields(
"user",
oauth_sub=pw.TextField(null=True, unique=True),
)
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_fields("user", "oauth_sub")

View File

@@ -0,0 +1,49 @@
"""Peewee migrations -- 017_add_user_oauth_sub.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
migrator.add_fields(
"function",
is_global=pw.BooleanField(default=False),
)
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_fields("function", "is_global")

View File

@@ -0,0 +1,66 @@
import logging
from contextvars import ContextVar
from open_webui.env import SRC_LOG_LEVELS
from peewee import *
from peewee import InterfaceError as PeeWeeInterfaceError
from peewee import PostgresqlDatabase
from playhouse.db_url import connect, parse
from playhouse.shortcuts import ReconnectMixin
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["DB"])
db_state_default = {"closed": None, "conn": None, "ctx": None, "transactions": None}
db_state = ContextVar("db_state", default=db_state_default.copy())
class PeeweeConnectionState(object):
def __init__(self, **kwargs):
super().__setattr__("_state", db_state)
super().__init__(**kwargs)
def __setattr__(self, name, value):
self._state.get()[name] = value
def __getattr__(self, name):
value = self._state.get()[name]
return value
class CustomReconnectMixin(ReconnectMixin):
reconnect_errors = (
# psycopg2
(OperationalError, "termin"),
(InterfaceError, "closed"),
# peewee
(PeeWeeInterfaceError, "closed"),
)
class ReconnectingPostgresqlDatabase(CustomReconnectMixin, PostgresqlDatabase):
pass
def register_connection(db_url):
db = connect(db_url, unquote_password=True)
if isinstance(db, PostgresqlDatabase):
# Enable autoconnect for SQLite databases, managed by Peewee
db.autoconnect = True
db.reuse_if_open = True
log.info("Connected to PostgreSQL database")
# Get the connection details
connection = parse(db_url, unquote_password=True)
# Use our custom database class that supports reconnection
db = ReconnectingPostgresqlDatabase(**connection)
db.connect(reuse_if_open=True)
elif isinstance(db, SqliteDatabase):
# Enable autoconnect for SQLite databases, managed by Peewee
db.autoconnect = True
db.reuse_if_open = True
log.info("Connected to SQLite database")
else:
raise ValueError("Unsupported database connection")
return db

View File

@@ -0,0 +1,390 @@
import inspect
import json
import logging
from typing import AsyncGenerator, Generator, Iterator
from open_webui.apps.socket.main import get_event_call, get_event_emitter
from open_webui.apps.webui.models.functions import Functions
from open_webui.apps.webui.models.models import Models
from open_webui.apps.webui.routers import (
auths,
chats,
configs,
documents,
files,
functions,
memories,
models,
prompts,
tools,
users,
utils,
)
from open_webui.apps.webui.utils import load_function_module_by_id
from open_webui.config import (
ADMIN_EMAIL,
CORS_ALLOW_ORIGIN,
DEFAULT_MODELS,
DEFAULT_PROMPT_SUGGESTIONS,
DEFAULT_USER_ROLE,
ENABLE_COMMUNITY_SHARING,
ENABLE_LOGIN_FORM,
ENABLE_MESSAGE_RATING,
ENABLE_SIGNUP,
JWT_EXPIRES_IN,
OAUTH_EMAIL_CLAIM,
OAUTH_PICTURE_CLAIM,
OAUTH_USERNAME_CLAIM,
SHOW_ADMIN_DETAILS,
USER_PERMISSIONS,
WEBHOOK_URL,
WEBUI_AUTH,
WEBUI_BANNERS,
AppConfig,
)
from open_webui.env import (
WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
WEBUI_AUTH_TRUSTED_NAME_HEADER,
)
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from open_webui.utils.misc import (
openai_chat_chunk_message_template,
openai_chat_completion_message_template,
)
from open_webui.utils.payload import (
apply_model_params_to_body_openai,
apply_model_system_prompt_to_body,
)
from open_webui.utils.tools import get_tools
app = FastAPI()
log = logging.getLogger(__name__)
app.state.config = AppConfig()
app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP
app.state.config.ENABLE_LOGIN_FORM = ENABLE_LOGIN_FORM
app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN
app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
app.state.AUTH_TRUSTED_NAME_HEADER = WEBUI_AUTH_TRUSTED_NAME_HEADER
app.state.config.SHOW_ADMIN_DETAILS = SHOW_ADMIN_DETAILS
app.state.config.ADMIN_EMAIL = ADMIN_EMAIL
app.state.config.DEFAULT_MODELS = DEFAULT_MODELS
app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
app.state.config.WEBHOOK_URL = WEBHOOK_URL
app.state.config.BANNERS = WEBUI_BANNERS
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING
app.state.config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM
app.state.config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM
app.state.config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
app.state.MODELS = {}
app.state.TOOLS = {}
app.state.FUNCTIONS = {}
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGIN,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(configs.router, prefix="/configs", tags=["configs"])
app.include_router(auths.router, prefix="/auths", tags=["auths"])
app.include_router(users.router, prefix="/users", tags=["users"])
app.include_router(chats.router, prefix="/chats", tags=["chats"])
app.include_router(documents.router, prefix="/documents", tags=["documents"])
app.include_router(models.router, prefix="/models", tags=["models"])
app.include_router(prompts.router, prefix="/prompts", tags=["prompts"])
app.include_router(memories.router, prefix="/memories", tags=["memories"])
app.include_router(files.router, prefix="/files", tags=["files"])
app.include_router(tools.router, prefix="/tools", tags=["tools"])
app.include_router(functions.router, prefix="/functions", tags=["functions"])
app.include_router(utils.router, prefix="/utils", tags=["utils"])
@app.get("/")
async def get_status():
return {
"status": True,
"auth": WEBUI_AUTH,
"default_models": app.state.config.DEFAULT_MODELS,
"default_prompt_suggestions": app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
}
def get_function_module(pipe_id: str):
# Check if function is already loaded
if pipe_id not in app.state.FUNCTIONS:
function_module, _, _ = load_function_module_by_id(pipe_id)
app.state.FUNCTIONS[pipe_id] = function_module
else:
function_module = app.state.FUNCTIONS[pipe_id]
if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
valves = Functions.get_function_valves_by_id(pipe_id)
function_module.valves = function_module.Valves(**(valves if valves else {}))
return function_module
async def get_pipe_models():
pipes = Functions.get_functions_by_type("pipe", active_only=True)
pipe_models = []
for pipe in pipes:
function_module = get_function_module(pipe.id)
# Check if function is a manifold
if hasattr(function_module, "pipes"):
sub_pipes = []
# Check if pipes is a function or a list
try:
if callable(function_module.pipes):
sub_pipes = function_module.pipes()
else:
sub_pipes = function_module.pipes
except Exception as e:
log.exception(e)
sub_pipes = []
print(sub_pipes)
for p in sub_pipes:
sub_pipe_id = f'{pipe.id}.{p["id"]}'
sub_pipe_name = p["name"]
if hasattr(function_module, "name"):
sub_pipe_name = f"{function_module.name}{sub_pipe_name}"
pipe_flag = {"type": pipe.type}
pipe_models.append(
{
"id": sub_pipe_id,
"name": sub_pipe_name,
"object": "model",
"created": pipe.created_at,
"owned_by": "openai",
"pipe": pipe_flag,
}
)
else:
pipe_flag = {"type": "pipe"}
pipe_models.append(
{
"id": pipe.id,
"name": pipe.name,
"object": "model",
"created": pipe.created_at,
"owned_by": "openai",
"pipe": pipe_flag,
}
)
return pipe_models
async def execute_pipe(pipe, params):
if inspect.iscoroutinefunction(pipe):
return await pipe(**params)
else:
return pipe(**params)
async def get_message_content(res: str | Generator | AsyncGenerator) -> str:
if isinstance(res, str):
return res
if isinstance(res, Generator):
return "".join(map(str, res))
if isinstance(res, AsyncGenerator):
return "".join([str(stream) async for stream in res])
def process_line(form_data: dict, line):
if isinstance(line, BaseModel):
line = line.model_dump_json()
line = f"data: {line}"
if isinstance(line, dict):
line = f"data: {json.dumps(line)}"
try:
line = line.decode("utf-8")
except Exception:
pass
if line.startswith("data:"):
return f"{line}\n\n"
else:
line = openai_chat_chunk_message_template(form_data["model"], line)
return f"data: {json.dumps(line)}\n\n"
def get_pipe_id(form_data: dict) -> str:
pipe_id = form_data["model"]
if "." in pipe_id:
pipe_id, _ = pipe_id.split(".", 1)
print(pipe_id)
return pipe_id
def get_function_params(function_module, form_data, user, extra_params=None):
if extra_params is None:
extra_params = {}
pipe_id = get_pipe_id(form_data)
# Get the signature of the function
sig = inspect.signature(function_module.pipe)
params = {"body": form_data} | {
k: v for k, v in extra_params.items() if k in sig.parameters
}
if "__user__" in params and hasattr(function_module, "UserValves"):
user_valves = Functions.get_user_valves_by_id_and_user_id(pipe_id, user.id)
try:
params["__user__"]["valves"] = function_module.UserValves(**user_valves)
except Exception as e:
log.exception(e)
params["__user__"]["valves"] = function_module.UserValves()
return params
async def generate_function_chat_completion(form_data, user):
model_id = form_data.get("model")
model_info = Models.get_model_by_id(model_id)
metadata = form_data.pop("metadata", {})
files = metadata.get("files", [])
tool_ids = metadata.get("tool_ids", [])
# Check if tool_ids is None
if tool_ids is None:
tool_ids = []
__event_emitter__ = None
__event_call__ = None
__task__ = None
if metadata:
if all(k in metadata for k in ("session_id", "chat_id", "message_id")):
__event_emitter__ = get_event_emitter(metadata)
__event_call__ = get_event_call(metadata)
__task__ = metadata.get("task", None)
extra_params = {
"__event_emitter__": __event_emitter__,
"__event_call__": __event_call__,
"__task__": __task__,
"__files__": files,
"__user__": {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
},
}
extra_params["__tools__"] = get_tools(
app,
tool_ids,
user,
{
**extra_params,
"__model__": app.state.MODELS[form_data["model"]],
"__messages__": form_data["messages"],
"__files__": files,
},
)
if model_info:
if model_info.base_model_id:
form_data["model"] = model_info.base_model_id
params = model_info.params.model_dump()
form_data = apply_model_params_to_body_openai(params, form_data)
form_data = apply_model_system_prompt_to_body(params, form_data, user)
pipe_id = get_pipe_id(form_data)
function_module = get_function_module(pipe_id)
pipe = function_module.pipe
params = get_function_params(function_module, form_data, user, extra_params)
if form_data["stream"]:
async def stream_content():
try:
res = await execute_pipe(pipe, params)
# Directly return if the response is a StreamingResponse
if isinstance(res, StreamingResponse):
async for data in res.body_iterator:
yield data
return
if isinstance(res, dict):
yield f"data: {json.dumps(res)}\n\n"
return
except Exception as e:
print(f"Error: {e}")
yield f"data: {json.dumps({'error': {'detail':str(e)}})}\n\n"
return
if isinstance(res, str):
message = openai_chat_chunk_message_template(form_data["model"], res)
yield f"data: {json.dumps(message)}\n\n"
if isinstance(res, Iterator):
for line in res:
yield process_line(form_data, line)
if isinstance(res, AsyncGenerator):
async for line in res:
yield process_line(form_data, line)
if isinstance(res, str) or isinstance(res, Generator):
finish_message = openai_chat_chunk_message_template(
form_data["model"], ""
)
finish_message["choices"][0]["finish_reason"] = "stop"
yield f"data: {json.dumps(finish_message)}\n\n"
yield "data: [DONE]"
return StreamingResponse(stream_content(), media_type="text/event-stream")
else:
try:
res = await execute_pipe(pipe, params)
except Exception as e:
print(f"Error: {e}")
return {"error": {"detail": str(e)}}
if isinstance(res, StreamingResponse) or isinstance(res, dict):
return res
if isinstance(res, BaseModel):
return res.model_dump()
message = await get_message_content(res)
return openai_chat_completion_message_template(form_data["model"], message)

View File

@@ -1,16 +1,13 @@
from pydantic import BaseModel
from typing import List, Union, Optional
import time
import uuid
import logging
from peewee import *
import uuid
from typing import Optional
from apps.webui.models.users import UserModel, Users
from utils.utils import verify_password
from apps.webui.internal.db import DB
from config import SRC_LOG_LEVELS
from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.apps.webui.models.users import UserModel, Users
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel
from sqlalchemy import Boolean, Column, String, Text
from open_webui.utils.utils import verify_password
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
@@ -20,14 +17,13 @@ log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
class Auth(Model):
id = CharField(unique=True)
email = CharField()
password = TextField()
active = BooleanField()
class Auth(Base):
__tablename__ = "auth"
class Meta:
database = DB
id = Column(String, primary_key=True)
email = Column(String)
password = Column(Text)
active = Column(Boolean)
class AuthModel(BaseModel):
@@ -94,10 +90,6 @@ class AddUserForm(SignupForm):
class AuthsTable:
def __init__(self, db):
self.db = db
self.db.create_tables([Auth])
def insert_new_auth(
self,
email: str,
@@ -105,36 +97,45 @@ class AuthsTable:
name: str,
profile_image_url: str = "/user.png",
role: str = "pending",
oauth_sub: Optional[str] = None,
) -> Optional[UserModel]:
log.info("insert_new_auth")
with get_db() as db:
log.info("insert_new_auth")
id = str(uuid.uuid4())
id = str(uuid.uuid4())
auth = AuthModel(
**{"id": id, "email": email, "password": password, "active": True}
)
result = Auth.create(**auth.model_dump())
auth = AuthModel(
**{"id": id, "email": email, "password": password, "active": True}
)
result = Auth(**auth.model_dump())
db.add(result)
user = Users.insert_new_user(id, name, email, profile_image_url, role)
user = Users.insert_new_user(
id, name, email, profile_image_url, role, oauth_sub
)
if result and user:
return user
else:
return None
db.commit()
db.refresh(result)
if result and user:
return user
else:
return None
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
log.info(f"authenticate_user: {email}")
try:
auth = Auth.get(Auth.email == email, Auth.active == True)
if auth:
if verify_password(password, auth.password):
user = Users.get_user_by_id(auth.id)
return user
with get_db() as db:
auth = db.query(Auth).filter_by(email=email, active=True).first()
if auth:
if verify_password(password, auth.password):
user = Users.get_user_by_id(auth.id)
return user
else:
return None
else:
return None
else:
return None
except:
except Exception:
return None
def authenticate_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
@@ -146,52 +147,55 @@ class AuthsTable:
try:
user = Users.get_user_by_api_key(api_key)
return user if user else None
except:
except Exception:
return False
def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
log.info(f"authenticate_user_by_trusted_header: {email}")
try:
auth = Auth.get(Auth.email == email, Auth.active == True)
if auth:
user = Users.get_user_by_id(auth.id)
return user
except:
with get_db() as db:
auth = db.query(Auth).filter_by(email=email, active=True).first()
if auth:
user = Users.get_user_by_id(auth.id)
return user
except Exception:
return None
def update_user_password_by_id(self, id: str, new_password: str) -> bool:
try:
query = Auth.update(password=new_password).where(Auth.id == id)
result = query.execute()
return True if result == 1 else False
except:
with get_db() as db:
result = (
db.query(Auth).filter_by(id=id).update({"password": new_password})
)
db.commit()
return True if result == 1 else False
except Exception:
return False
def update_email_by_id(self, id: str, email: str) -> bool:
try:
query = Auth.update(email=email).where(Auth.id == id)
result = query.execute()
return True if result == 1 else False
except:
with get_db() as db:
result = db.query(Auth).filter_by(id=id).update({"email": email})
db.commit()
return True if result == 1 else False
except Exception:
return False
def delete_auth_by_id(self, id: str) -> bool:
try:
# Delete User
result = Users.delete_user_by_id(id)
with get_db() as db:
# Delete User
result = Users.delete_user_by_id(id)
if result:
# Delete Auth
query = Auth.delete().where(Auth.id == id)
query.execute() # Remove the rows, return number of rows removed.
if result:
db.query(Auth).filter_by(id=id).delete()
db.commit()
return True
else:
return False
except:
return True
else:
return False
except Exception:
return False
Auths = AuthsTable(DB)
Auths = AuthsTable()

View File

@@ -0,0 +1,386 @@
import json
import time
import uuid
from typing import Optional
from open_webui.apps.webui.internal.db import Base, get_db
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Boolean, Column, String, Text
####################
# Chat DB Schema
####################
class Chat(Base):
__tablename__ = "chat"
id = Column(String, primary_key=True)
user_id = Column(String)
title = Column(Text)
chat = Column(Text) # Save Chat JSON as Text
created_at = Column(BigInteger)
updated_at = Column(BigInteger)
share_id = Column(Text, unique=True, nullable=True)
archived = Column(Boolean, default=False)
class ChatModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: str
user_id: str
title: str
chat: str
created_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
share_id: Optional[str] = None
archived: bool = False
####################
# Forms
####################
class ChatForm(BaseModel):
chat: dict
class ChatTitleForm(BaseModel):
title: str
class ChatResponse(BaseModel):
id: str
user_id: str
title: str
chat: dict
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
share_id: Optional[str] = None # id of the chat to be shared
archived: bool
class ChatTitleIdResponse(BaseModel):
id: str
title: str
updated_at: int
created_at: int
class ChatTable:
def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
with get_db() as db:
id = str(uuid.uuid4())
chat = ChatModel(
**{
"id": id,
"user_id": user_id,
"title": (
form_data.chat["title"]
if "title" in form_data.chat
else "New Chat"
),
"chat": json.dumps(form_data.chat),
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
result = Chat(**chat.model_dump())
db.add(result)
db.commit()
db.refresh(result)
return ChatModel.model_validate(result) if result else None
def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
try:
with get_db() as db:
chat_obj = db.get(Chat, id)
chat_obj.chat = json.dumps(chat)
chat_obj.title = chat["title"] if "title" in chat else "New Chat"
chat_obj.updated_at = int(time.time())
db.commit()
db.refresh(chat_obj)
return ChatModel.model_validate(chat_obj)
except Exception:
return None
def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
with get_db() as db:
# Get the existing chat to share
chat = db.get(Chat, chat_id)
# Check if the chat is already shared
if chat.share_id:
return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
# Create a new chat with the same data, but with a new ID
shared_chat = ChatModel(
**{
"id": str(uuid.uuid4()),
"user_id": f"shared-{chat_id}",
"title": chat.title,
"chat": chat.chat,
"created_at": chat.created_at,
"updated_at": int(time.time()),
}
)
shared_result = Chat(**shared_chat.model_dump())
db.add(shared_result)
db.commit()
db.refresh(shared_result)
# Update the original chat with the share_id
result = (
db.query(Chat)
.filter_by(id=chat_id)
.update({"share_id": shared_chat.id})
)
db.commit()
return shared_chat if (shared_result and result) else None
def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
print("update_shared_chat_by_id")
chat = db.get(Chat, chat_id)
print(chat)
chat.title = chat.title
chat.chat = chat.chat
db.commit()
db.refresh(chat)
return self.get_chat_by_id(chat.share_id)
except Exception:
return None
def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
try:
with get_db() as db:
db.query(Chat).filter_by(user_id=f"shared-{chat_id}").delete()
db.commit()
return True
except Exception:
return False
def update_chat_share_id_by_id(
self, id: str, share_id: Optional[str]
) -> Optional[ChatModel]:
try:
with get_db() as db:
chat = db.get(Chat, id)
chat.share_id = share_id
db.commit()
db.refresh(chat)
return ChatModel.model_validate(chat)
except Exception:
return None
def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
chat = db.get(Chat, id)
chat.archived = not chat.archived
db.commit()
db.refresh(chat)
return ChatModel.model_validate(chat)
except Exception:
return None
def archive_all_chats_by_user_id(self, user_id: str) -> bool:
try:
with get_db() as db:
db.query(Chat).filter_by(user_id=user_id).update({"archived": True})
db.commit()
return True
except Exception:
return False
def get_archived_chat_list_by_user_id(
self, user_id: str, skip: int = 0, limit: int = 50
) -> list[ChatModel]:
with get_db() as db:
all_chats = (
db.query(Chat)
.filter_by(user_id=user_id, archived=True)
.order_by(Chat.updated_at.desc())
# .limit(limit).offset(skip)
.all()
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def get_chat_list_by_user_id(
self,
user_id: str,
include_archived: bool = False,
skip: int = 0,
limit: int = 50,
) -> list[ChatModel]:
with get_db() as db:
query = db.query(Chat).filter_by(user_id=user_id)
if not include_archived:
query = query.filter_by(archived=False)
all_chats = (
query.order_by(Chat.updated_at.desc())
# .limit(limit).offset(skip)
.all()
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def get_chat_title_id_list_by_user_id(
self,
user_id: str,
include_archived: bool = False,
skip: Optional[int] = None,
limit: Optional[int] = None,
) -> list[ChatTitleIdResponse]:
with get_db() as db:
query = db.query(Chat).filter_by(user_id=user_id)
if not include_archived:
query = query.filter_by(archived=False)
query = query.order_by(Chat.updated_at.desc()).with_entities(
Chat.id, Chat.title, Chat.updated_at, Chat.created_at
)
if limit:
query = query.limit(limit)
if skip:
query = query.offset(skip)
all_chats = query.all()
# result has to be destrctured from sqlalchemy `row` and mapped to a dict since the `ChatModel`is not the returned dataclass.
return [
ChatTitleIdResponse.model_validate(
{
"id": chat[0],
"title": chat[1],
"updated_at": chat[2],
"created_at": chat[3],
}
)
for chat in all_chats
]
def get_chat_list_by_chat_ids(
self, chat_ids: list[str], skip: int = 0, limit: int = 50
) -> list[ChatModel]:
with get_db() as db:
all_chats = (
db.query(Chat)
.filter(Chat.id.in_(chat_ids))
.filter_by(archived=False)
.order_by(Chat.updated_at.desc())
.all()
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
chat = db.get(Chat, id)
return ChatModel.model_validate(chat)
except Exception:
return None
def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
chat = db.query(Chat).filter_by(share_id=id).first()
if chat:
return self.get_chat_by_id(id)
else:
return None
except Exception:
return None
def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
return ChatModel.model_validate(chat)
except Exception:
return None
def get_chats(self, skip: int = 0, limit: int = 50) -> list[ChatModel]:
with get_db() as db:
all_chats = (
db.query(Chat)
# .limit(limit).offset(skip)
.order_by(Chat.updated_at.desc())
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def get_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
with get_db() as db:
all_chats = (
db.query(Chat)
.filter_by(user_id=user_id)
.order_by(Chat.updated_at.desc())
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def get_archived_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
with get_db() as db:
all_chats = (
db.query(Chat)
.filter_by(user_id=user_id, archived=True)
.order_by(Chat.updated_at.desc())
)
return [ChatModel.model_validate(chat) for chat in all_chats]
def delete_chat_by_id(self, id: str) -> bool:
try:
with get_db() as db:
db.query(Chat).filter_by(id=id).delete()
db.commit()
return True and self.delete_shared_chat_by_chat_id(id)
except Exception:
return False
def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
try:
with get_db() as db:
db.query(Chat).filter_by(id=id, user_id=user_id).delete()
db.commit()
return True and self.delete_shared_chat_by_chat_id(id)
except Exception:
return False
def delete_chats_by_user_id(self, user_id: str) -> bool:
try:
with get_db() as db:
self.delete_shared_chats_by_user_id(user_id)
db.query(Chat).filter_by(user_id=user_id).delete()
db.commit()
return True
except Exception:
return False
def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
try:
with get_db() as db:
chats_by_user = db.query(Chat).filter_by(user_id=user_id).all()
shared_chat_ids = [f"shared-{chat.id}" for chat in chats_by_user]
db.query(Chat).filter(Chat.user_id.in_(shared_chat_ids)).delete()
db.commit()
return True
except Exception:
return False
Chats = ChatTable()

View File

@@ -0,0 +1,157 @@
import json
import logging
import time
from typing import Optional
from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Documents DB Schema
####################
class Document(Base):
__tablename__ = "document"
collection_name = Column(String, primary_key=True)
name = Column(String, unique=True)
title = Column(Text)
filename = Column(Text)
content = Column(Text, nullable=True)
user_id = Column(String)
timestamp = Column(BigInteger)
class DocumentModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
collection_name: str
name: str
title: str
filename: str
content: Optional[str] = None
user_id: str
timestamp: int # timestamp in epoch
####################
# Forms
####################
class DocumentResponse(BaseModel):
collection_name: str
name: str
title: str
filename: str
content: Optional[dict] = None
user_id: str
timestamp: int # timestamp in epoch
class DocumentUpdateForm(BaseModel):
name: str
title: str
class DocumentForm(DocumentUpdateForm):
collection_name: str
filename: str
content: Optional[str] = None
class DocumentsTable:
def insert_new_doc(
self, user_id: str, form_data: DocumentForm
) -> Optional[DocumentModel]:
with get_db() as db:
document = DocumentModel(
**{
**form_data.model_dump(),
"user_id": user_id,
"timestamp": int(time.time()),
}
)
try:
result = Document(**document.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return DocumentModel.model_validate(result)
else:
return None
except Exception:
return None
def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
try:
with get_db() as db:
document = db.query(Document).filter_by(name=name).first()
return DocumentModel.model_validate(document) if document else None
except Exception:
return None
def get_docs(self) -> list[DocumentModel]:
with get_db() as db:
return [
DocumentModel.model_validate(doc) for doc in db.query(Document).all()
]
def update_doc_by_name(
self, name: str, form_data: DocumentUpdateForm
) -> Optional[DocumentModel]:
try:
with get_db() as db:
db.query(Document).filter_by(name=name).update(
{
"title": form_data.title,
"name": form_data.name,
"timestamp": int(time.time()),
}
)
db.commit()
return self.get_doc_by_name(form_data.name)
except Exception as e:
log.exception(e)
return None
def update_doc_content_by_name(
self, name: str, updated: dict
) -> Optional[DocumentModel]:
try:
doc = self.get_doc_by_name(name)
doc_content = json.loads(doc.content if doc.content else "{}")
doc_content = {**doc_content, **updated}
with get_db() as db:
db.query(Document).filter_by(name=name).update(
{
"content": json.dumps(doc_content),
"timestamp": int(time.time()),
}
)
db.commit()
return self.get_doc_by_name(name)
except Exception as e:
log.exception(e)
return None
def delete_doc_by_name(self, name: str) -> bool:
try:
with get_db() as db:
db.query(Document).filter_by(name=name).delete()
db.commit()
return True
except Exception:
return False
Documents = DocumentsTable()

View File

@@ -0,0 +1,121 @@
import logging
import time
from typing import Optional
from open_webui.apps.webui.internal.db import Base, JSONField, get_db
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Files DB Schema
####################
class File(Base):
__tablename__ = "file"
id = Column(String, primary_key=True)
user_id = Column(String)
filename = Column(Text)
meta = Column(JSONField)
created_at = Column(BigInteger)
class FileModel(BaseModel):
id: str
user_id: str
filename: str
meta: dict
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class FileModelResponse(BaseModel):
id: str
user_id: str
filename: str
meta: dict
created_at: int # timestamp in epoch
class FileForm(BaseModel):
id: str
filename: str
meta: dict = {}
class FilesTable:
def insert_new_file(self, user_id: str, form_data: FileForm) -> Optional[FileModel]:
with get_db() as db:
file = FileModel(
**{
**form_data.model_dump(),
"user_id": user_id,
"created_at": int(time.time()),
}
)
try:
result = File(**file.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return FileModel.model_validate(result)
else:
return None
except Exception as e:
print(f"Error creating tool: {e}")
return None
def get_file_by_id(self, id: str) -> Optional[FileModel]:
with get_db() as db:
try:
file = db.get(File, id)
return FileModel.model_validate(file)
except Exception:
return None
def get_files(self) -> list[FileModel]:
with get_db() as db:
return [FileModel.model_validate(file) for file in db.query(File).all()]
def get_files_by_user_id(self, user_id: str) -> list[FileModel]:
with get_db() as db:
return [
FileModel.model_validate(file)
for file in db.query(File).filter_by(user_id=user_id).all()
]
def delete_file_by_id(self, id: str) -> bool:
with get_db() as db:
try:
db.query(File).filter_by(id=id).delete()
db.commit()
return True
except Exception:
return False
def delete_all_files(self) -> bool:
with get_db() as db:
try:
db.query(File).delete()
db.commit()
return True
except Exception:
return False
Files = FilesTable()

View File

@@ -0,0 +1,270 @@
import logging
import time
from typing import Optional
from open_webui.apps.webui.internal.db import Base, JSONField, get_db
from open_webui.apps.webui.models.users import Users
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Boolean, Column, String, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Functions DB Schema
####################
class Function(Base):
__tablename__ = "function"
id = Column(String, primary_key=True)
user_id = Column(String)
name = Column(Text)
type = Column(Text)
content = Column(Text)
meta = Column(JSONField)
valves = Column(JSONField)
is_active = Column(Boolean)
is_global = Column(Boolean)
updated_at = Column(BigInteger)
created_at = Column(BigInteger)
class FunctionMeta(BaseModel):
description: Optional[str] = None
manifest: Optional[dict] = {}
class FunctionModel(BaseModel):
id: str
user_id: str
name: str
type: str
content: str
meta: FunctionMeta
is_active: bool = False
is_global: bool = False
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class FunctionResponse(BaseModel):
id: str
user_id: str
type: str
name: str
meta: FunctionMeta
is_active: bool
is_global: bool
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
class FunctionForm(BaseModel):
id: str
name: str
content: str
meta: FunctionMeta
class FunctionValves(BaseModel):
valves: Optional[dict] = None
class FunctionsTable:
def insert_new_function(
self, user_id: str, type: str, form_data: FunctionForm
) -> Optional[FunctionModel]:
function = FunctionModel(
**{
**form_data.model_dump(),
"user_id": user_id,
"type": type,
"updated_at": int(time.time()),
"created_at": int(time.time()),
}
)
try:
with get_db() as db:
result = Function(**function.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return FunctionModel.model_validate(result)
else:
return None
except Exception as e:
print(f"Error creating tool: {e}")
return None
def get_function_by_id(self, id: str) -> Optional[FunctionModel]:
try:
with get_db() as db:
function = db.get(Function, id)
return FunctionModel.model_validate(function)
except Exception:
return None
def get_functions(self, active_only=False) -> list[FunctionModel]:
with get_db() as db:
if active_only:
return [
FunctionModel.model_validate(function)
for function in db.query(Function).filter_by(is_active=True).all()
]
else:
return [
FunctionModel.model_validate(function)
for function in db.query(Function).all()
]
def get_functions_by_type(
self, type: str, active_only=False
) -> list[FunctionModel]:
with get_db() as db:
if active_only:
return [
FunctionModel.model_validate(function)
for function in db.query(Function)
.filter_by(type=type, is_active=True)
.all()
]
else:
return [
FunctionModel.model_validate(function)
for function in db.query(Function).filter_by(type=type).all()
]
def get_global_filter_functions(self) -> list[FunctionModel]:
with get_db() as db:
return [
FunctionModel.model_validate(function)
for function in db.query(Function)
.filter_by(type="filter", is_active=True, is_global=True)
.all()
]
def get_global_action_functions(self) -> list[FunctionModel]:
with get_db() as db:
return [
FunctionModel.model_validate(function)
for function in db.query(Function)
.filter_by(type="action", is_active=True, is_global=True)
.all()
]
def get_function_valves_by_id(self, id: str) -> Optional[dict]:
with get_db() as db:
try:
function = db.get(Function, id)
return function.valves if function.valves else {}
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_function_valves_by_id(
self, id: str, valves: dict
) -> Optional[FunctionValves]:
with get_db() as db:
try:
function = db.get(Function, id)
function.valves = valves
function.updated_at = int(time.time())
db.commit()
db.refresh(function)
return self.get_function_by_id(id)
except Exception:
return None
def get_user_valves_by_id_and_user_id(
self, id: str, user_id: str
) -> Optional[dict]:
try:
user = Users.get_user_by_id(user_id)
user_settings = user.settings.model_dump() if user.settings else {}
# Check if user has "functions" and "valves" settings
if "functions" not in user_settings:
user_settings["functions"] = {}
if "valves" not in user_settings["functions"]:
user_settings["functions"]["valves"] = {}
return user_settings["functions"]["valves"].get(id, {})
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_user_valves_by_id_and_user_id(
self, id: str, user_id: str, valves: dict
) -> Optional[dict]:
try:
user = Users.get_user_by_id(user_id)
user_settings = user.settings.model_dump() if user.settings else {}
# Check if user has "functions" and "valves" settings
if "functions" not in user_settings:
user_settings["functions"] = {}
if "valves" not in user_settings["functions"]:
user_settings["functions"]["valves"] = {}
user_settings["functions"]["valves"][id] = valves
# Update the user settings in the database
Users.update_user_by_id(user_id, {"settings": user_settings})
return user_settings["functions"]["valves"][id]
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_function_by_id(self, id: str, updated: dict) -> Optional[FunctionModel]:
with get_db() as db:
try:
db.query(Function).filter_by(id=id).update(
{
**updated,
"updated_at": int(time.time()),
}
)
db.commit()
return self.get_function_by_id(id)
except Exception:
return None
def deactivate_all_functions(self) -> Optional[bool]:
with get_db() as db:
try:
db.query(Function).update(
{
"is_active": False,
"updated_at": int(time.time()),
}
)
db.commit()
return True
except Exception:
return None
def delete_function_by_id(self, id: str) -> bool:
with get_db() as db:
try:
db.query(Function).filter_by(id=id).delete()
db.commit()
return True
except Exception:
return False
Functions = FunctionsTable()

View File

@@ -0,0 +1,137 @@
import time
import uuid
from typing import Optional
from open_webui.apps.webui.internal.db import Base, get_db
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
####################
# Memory DB Schema
####################
class Memory(Base):
__tablename__ = "memory"
id = Column(String, primary_key=True)
user_id = Column(String)
content = Column(Text)
updated_at = Column(BigInteger)
created_at = Column(BigInteger)
class MemoryModel(BaseModel):
id: str
user_id: str
content: str
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class MemoriesTable:
def insert_new_memory(
self,
user_id: str,
content: str,
) -> Optional[MemoryModel]:
with get_db() as db:
id = str(uuid.uuid4())
memory = MemoryModel(
**{
"id": id,
"user_id": user_id,
"content": content,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
result = Memory(**memory.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return MemoryModel.model_validate(result)
else:
return None
def update_memory_by_id(
self,
id: str,
content: str,
) -> Optional[MemoryModel]:
with get_db() as db:
try:
db.query(Memory).filter_by(id=id).update(
{"content": content, "updated_at": int(time.time())}
)
db.commit()
return self.get_memory_by_id(id)
except Exception:
return None
def get_memories(self) -> list[MemoryModel]:
with get_db() as db:
try:
memories = db.query(Memory).all()
return [MemoryModel.model_validate(memory) for memory in memories]
except Exception:
return None
def get_memories_by_user_id(self, user_id: str) -> list[MemoryModel]:
with get_db() as db:
try:
memories = db.query(Memory).filter_by(user_id=user_id).all()
return [MemoryModel.model_validate(memory) for memory in memories]
except Exception:
return None
def get_memory_by_id(self, id: str) -> Optional[MemoryModel]:
with get_db() as db:
try:
memory = db.get(Memory, id)
return MemoryModel.model_validate(memory)
except Exception:
return None
def delete_memory_by_id(self, id: str) -> bool:
with get_db() as db:
try:
db.query(Memory).filter_by(id=id).delete()
db.commit()
return True
except Exception:
return False
def delete_memories_by_user_id(self, user_id: str) -> bool:
with get_db() as db:
try:
db.query(Memory).filter_by(user_id=user_id).delete()
db.commit()
return True
except Exception:
return False
def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
with get_db() as db:
try:
db.query(Memory).filter_by(id=id, user_id=user_id).delete()
db.commit()
return True
except Exception:
return False
Memories = MemoriesTable()

View File

@@ -1,19 +1,11 @@
import json
import logging
import time
from typing import Optional
import peewee as pw
from peewee import *
from playhouse.shortcuts import model_to_dict
from open_webui.apps.webui.internal.db import Base, JSONField, get_db
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from apps.webui.internal.db import DB, JSONField
from typing import List, Union, Optional
from config import SRC_LOG_LEVELS
import time
from sqlalchemy import BigInteger, Column, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
@@ -32,7 +24,7 @@ class ModelParams(BaseModel):
# ModelMeta is a model for the data stored in the meta field of the Model table
class ModelMeta(BaseModel):
profile_image_url: Optional[str] = "/favicon.png"
profile_image_url: Optional[str] = "/static/favicon.png"
description: Optional[str] = None
"""
@@ -46,38 +38,37 @@ class ModelMeta(BaseModel):
pass
class Model(pw.Model):
id = pw.TextField(unique=True)
class Model(Base):
__tablename__ = "model"
id = Column(Text, primary_key=True)
"""
The model's id as used in the API. If set to an existing model, it will override the model.
"""
user_id = pw.TextField()
user_id = Column(Text)
base_model_id = pw.TextField(null=True)
base_model_id = Column(Text, nullable=True)
"""
An optional pointer to the actual model that should be used when proxying requests.
"""
name = pw.TextField()
name = Column(Text)
"""
The human-readable display name of the model.
"""
params = JSONField()
params = Column(JSONField)
"""
Holds a JSON encoded blob of parameters, see `ModelParams`.
"""
meta = JSONField()
meta = Column(JSONField)
"""
Holds a JSON encoded blob of metadata, see `ModelMeta`.
"""
updated_at = BigIntegerField()
created_at = BigIntegerField()
class Meta:
database = DB
updated_at = Column(BigInteger)
created_at = Column(BigInteger)
class ModelModel(BaseModel):
@@ -92,6 +83,8 @@ class ModelModel(BaseModel):
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
@@ -115,13 +108,6 @@ class ModelForm(BaseModel):
class ModelsTable:
def __init__(
self,
db: pw.SqliteDatabase | pw.PostgresqlDatabase,
):
self.db = db
self.db.create_tables([Model])
def insert_new_model(
self, form_data: ModelForm, user_id: str
) -> Optional[ModelModel]:
@@ -134,34 +120,46 @@ class ModelsTable:
}
)
try:
result = Model.create(**model.model_dump())
with get_db() as db:
result = Model(**model.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return model
else:
return None
if result:
return ModelModel.model_validate(result)
else:
return None
except Exception as e:
print(e)
return None
def get_all_models(self) -> List[ModelModel]:
return [ModelModel(**model_to_dict(model)) for model in Model.select()]
def get_all_models(self) -> list[ModelModel]:
with get_db() as db:
return [ModelModel.model_validate(model) for model in db.query(Model).all()]
def get_model_by_id(self, id: str) -> Optional[ModelModel]:
try:
model = Model.get(Model.id == id)
return ModelModel(**model_to_dict(model))
except:
with get_db() as db:
model = db.get(Model, id)
return ModelModel.model_validate(model)
except Exception:
return None
def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
try:
# update only the fields that are present in the model
query = Model.update(**model.model_dump()).where(Model.id == id)
query.execute()
with get_db() as db:
# update only the fields that are present in the model
result = (
db.query(Model)
.filter_by(id=id)
.update(model.model_dump(exclude={"id"}, exclude_none=True))
)
db.commit()
model = Model.get(Model.id == id)
return ModelModel(**model_to_dict(model))
model = db.get(Model, id)
db.refresh(model)
return ModelModel.model_validate(model)
except Exception as e:
print(e)
@@ -169,11 +167,13 @@ class ModelsTable:
def delete_model_by_id(self, id: str) -> bool:
try:
query = Model.delete().where(Model.id == id)
query.execute()
return True
except:
with get_db() as db:
db.query(Model).filter_by(id=id).delete()
db.commit()
return True
except Exception:
return False
Models = ModelsTable(DB)
Models = ModelsTable()

View File

@@ -0,0 +1,110 @@
import time
from typing import Optional
from open_webui.apps.webui.internal.db import Base, get_db
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
####################
# Prompts DB Schema
####################
class Prompt(Base):
__tablename__ = "prompt"
command = Column(String, primary_key=True)
user_id = Column(String)
title = Column(Text)
content = Column(Text)
timestamp = Column(BigInteger)
class PromptModel(BaseModel):
command: str
user_id: str
title: str
content: str
timestamp: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class PromptForm(BaseModel):
command: str
title: str
content: str
class PromptsTable:
def insert_new_prompt(
self, user_id: str, form_data: PromptForm
) -> Optional[PromptModel]:
prompt = PromptModel(
**{
"user_id": user_id,
"command": form_data.command,
"title": form_data.title,
"content": form_data.content,
"timestamp": int(time.time()),
}
)
try:
with get_db() as db:
result = Prompt(**prompt.dict())
db.add(result)
db.commit()
db.refresh(result)
if result:
return PromptModel.model_validate(result)
else:
return None
except Exception:
return None
def get_prompt_by_command(self, command: str) -> Optional[PromptModel]:
try:
with get_db() as db:
prompt = db.query(Prompt).filter_by(command=command).first()
return PromptModel.model_validate(prompt)
except Exception:
return None
def get_prompts(self) -> list[PromptModel]:
with get_db() as db:
return [
PromptModel.model_validate(prompt) for prompt in db.query(Prompt).all()
]
def update_prompt_by_command(
self, command: str, form_data: PromptForm
) -> Optional[PromptModel]:
try:
with get_db() as db:
prompt = db.query(Prompt).filter_by(command=command).first()
prompt.title = form_data.title
prompt.content = form_data.content
prompt.timestamp = int(time.time())
db.commit()
return PromptModel.model_validate(prompt)
except Exception:
return None
def delete_prompt_by_command(self, command: str) -> bool:
try:
with get_db() as db:
db.query(Prompt).filter_by(command=command).delete()
db.commit()
return True
except Exception:
return False
Prompts = PromptsTable()

View File

@@ -0,0 +1,262 @@
import logging
import time
import uuid
from typing import Optional
from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Tag DB Schema
####################
class Tag(Base):
__tablename__ = "tag"
id = Column(String, primary_key=True)
name = Column(String)
user_id = Column(String)
data = Column(Text, nullable=True)
class ChatIdTag(Base):
__tablename__ = "chatidtag"
id = Column(String, primary_key=True)
tag_name = Column(String)
chat_id = Column(String)
user_id = Column(String)
timestamp = Column(BigInteger)
class TagModel(BaseModel):
id: str
name: str
user_id: str
data: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class ChatIdTagModel(BaseModel):
id: str
tag_name: str
chat_id: str
user_id: str
timestamp: int
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class ChatIdTagForm(BaseModel):
tag_name: str
chat_id: str
class TagChatIdsResponse(BaseModel):
chat_ids: list[str]
class ChatTagsResponse(BaseModel):
tags: list[str]
class TagTable:
def insert_new_tag(self, name: str, user_id: str) -> Optional[TagModel]:
with get_db() as db:
id = str(uuid.uuid4())
tag = TagModel(**{"id": id, "user_id": user_id, "name": name})
try:
result = Tag(**tag.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return TagModel.model_validate(result)
else:
return None
except Exception:
return None
def get_tag_by_name_and_user_id(
self, name: str, user_id: str
) -> Optional[TagModel]:
try:
with get_db() as db:
tag = db.query(Tag).filter_by(name=name, user_id=user_id).first()
return TagModel.model_validate(tag)
except Exception:
return None
def add_tag_to_chat(
self, user_id: str, form_data: ChatIdTagForm
) -> Optional[ChatIdTagModel]:
tag = self.get_tag_by_name_and_user_id(form_data.tag_name, user_id)
if tag is None:
tag = self.insert_new_tag(form_data.tag_name, user_id)
id = str(uuid.uuid4())
chatIdTag = ChatIdTagModel(
**{
"id": id,
"user_id": user_id,
"chat_id": form_data.chat_id,
"tag_name": tag.name,
"timestamp": int(time.time()),
}
)
try:
with get_db() as db:
result = ChatIdTag(**chatIdTag.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return ChatIdTagModel.model_validate(result)
else:
return None
except Exception:
return None
def get_tags_by_user_id(self, user_id: str) -> list[TagModel]:
with get_db() as db:
tag_names = [
chat_id_tag.tag_name
for chat_id_tag in (
db.query(ChatIdTag)
.filter_by(user_id=user_id)
.order_by(ChatIdTag.timestamp.desc())
.all()
)
]
return [
TagModel.model_validate(tag)
for tag in (
db.query(Tag)
.filter_by(user_id=user_id)
.filter(Tag.name.in_(tag_names))
.all()
)
]
def get_tags_by_chat_id_and_user_id(
self, chat_id: str, user_id: str
) -> list[TagModel]:
with get_db() as db:
tag_names = [
chat_id_tag.tag_name
for chat_id_tag in (
db.query(ChatIdTag)
.filter_by(user_id=user_id, chat_id=chat_id)
.order_by(ChatIdTag.timestamp.desc())
.all()
)
]
return [
TagModel.model_validate(tag)
for tag in (
db.query(Tag)
.filter_by(user_id=user_id)
.filter(Tag.name.in_(tag_names))
.all()
)
]
def get_chat_ids_by_tag_name_and_user_id(
self, tag_name: str, user_id: str
) -> list[ChatIdTagModel]:
with get_db() as db:
return [
ChatIdTagModel.model_validate(chat_id_tag)
for chat_id_tag in (
db.query(ChatIdTag)
.filter_by(user_id=user_id, tag_name=tag_name)
.order_by(ChatIdTag.timestamp.desc())
.all()
)
]
def count_chat_ids_by_tag_name_and_user_id(
self, tag_name: str, user_id: str
) -> int:
with get_db() as db:
return (
db.query(ChatIdTag)
.filter_by(tag_name=tag_name, user_id=user_id)
.count()
)
def delete_tag_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> bool:
try:
with get_db() as db:
res = (
db.query(ChatIdTag)
.filter_by(tag_name=tag_name, user_id=user_id)
.delete()
)
log.debug(f"res: {res}")
db.commit()
tag_count = self.count_chat_ids_by_tag_name_and_user_id(
tag_name, user_id
)
if tag_count == 0:
# Remove tag item from Tag col as well
db.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
db.commit()
return True
except Exception as e:
log.error(f"delete_tag: {e}")
return False
def delete_tag_by_tag_name_and_chat_id_and_user_id(
self, tag_name: str, chat_id: str, user_id: str
) -> bool:
try:
with get_db() as db:
res = (
db.query(ChatIdTag)
.filter_by(tag_name=tag_name, chat_id=chat_id, user_id=user_id)
.delete()
)
log.debug(f"res: {res}")
db.commit()
tag_count = self.count_chat_ids_by_tag_name_and_user_id(
tag_name, user_id
)
if tag_count == 0:
# Remove tag item from Tag col as well
db.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
db.commit()
return True
except Exception as e:
log.error(f"delete_tag: {e}")
return False
def delete_tags_by_chat_id_and_user_id(self, chat_id: str, user_id: str) -> bool:
tags = self.get_tags_by_chat_id_and_user_id(chat_id, user_id)
for tag in tags:
self.delete_tag_by_tag_name_and_chat_id_and_user_id(
tag.tag_name, chat_id, user_id
)
return True
Tags = TagTable()

View File

@@ -0,0 +1,202 @@
import logging
import time
from typing import Optional
from open_webui.apps.webui.internal.db import Base, JSONField, get_db
from open_webui.apps.webui.models.users import Users
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Tools DB Schema
####################
class Tool(Base):
__tablename__ = "tool"
id = Column(String, primary_key=True)
user_id = Column(String)
name = Column(Text)
content = Column(Text)
specs = Column(JSONField)
meta = Column(JSONField)
valves = Column(JSONField)
updated_at = Column(BigInteger)
created_at = Column(BigInteger)
class ToolMeta(BaseModel):
description: Optional[str] = None
manifest: Optional[dict] = {}
class ToolModel(BaseModel):
id: str
user_id: str
name: str
content: str
specs: list[dict]
meta: ToolMeta
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
class ToolResponse(BaseModel):
id: str
user_id: str
name: str
meta: ToolMeta
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
class ToolForm(BaseModel):
id: str
name: str
content: str
meta: ToolMeta
class ToolValves(BaseModel):
valves: Optional[dict] = None
class ToolsTable:
def insert_new_tool(
self, user_id: str, form_data: ToolForm, specs: list[dict]
) -> Optional[ToolModel]:
with get_db() as db:
tool = ToolModel(
**{
**form_data.model_dump(),
"specs": specs,
"user_id": user_id,
"updated_at": int(time.time()),
"created_at": int(time.time()),
}
)
try:
result = Tool(**tool.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return ToolModel.model_validate(result)
else:
return None
except Exception as e:
print(f"Error creating tool: {e}")
return None
def get_tool_by_id(self, id: str) -> Optional[ToolModel]:
try:
with get_db() as db:
tool = db.get(Tool, id)
return ToolModel.model_validate(tool)
except Exception:
return None
def get_tools(self) -> list[ToolModel]:
with get_db() as db:
return [ToolModel.model_validate(tool) for tool in db.query(Tool).all()]
def get_tool_valves_by_id(self, id: str) -> Optional[dict]:
try:
with get_db() as db:
tool = db.get(Tool, id)
return tool.valves if tool.valves else {}
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_tool_valves_by_id(self, id: str, valves: dict) -> Optional[ToolValves]:
try:
with get_db() as db:
db.query(Tool).filter_by(id=id).update(
{"valves": valves, "updated_at": int(time.time())}
)
db.commit()
return self.get_tool_by_id(id)
except Exception:
return None
def get_user_valves_by_id_and_user_id(
self, id: str, user_id: str
) -> Optional[dict]:
try:
user = Users.get_user_by_id(user_id)
user_settings = user.settings.model_dump() if user.settings else {}
# Check if user has "tools" and "valves" settings
if "tools" not in user_settings:
user_settings["tools"] = {}
if "valves" not in user_settings["tools"]:
user_settings["tools"]["valves"] = {}
return user_settings["tools"]["valves"].get(id, {})
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_user_valves_by_id_and_user_id(
self, id: str, user_id: str, valves: dict
) -> Optional[dict]:
try:
user = Users.get_user_by_id(user_id)
user_settings = user.settings.model_dump() if user.settings else {}
# Check if user has "tools" and "valves" settings
if "tools" not in user_settings:
user_settings["tools"] = {}
if "valves" not in user_settings["tools"]:
user_settings["tools"]["valves"] = {}
user_settings["tools"]["valves"][id] = valves
# Update the user settings in the database
Users.update_user_by_id(user_id, {"settings": user_settings})
return user_settings["tools"]["valves"][id]
except Exception as e:
print(f"An error occurred: {e}")
return None
def update_tool_by_id(self, id: str, updated: dict) -> Optional[ToolModel]:
try:
with get_db() as db:
db.query(Tool).filter_by(id=id).update(
{**updated, "updated_at": int(time.time())}
)
db.commit()
tool = db.query(Tool).get(id)
db.refresh(tool)
return ToolModel.model_validate(tool)
except Exception:
return None
def delete_tool_by_id(self, id: str) -> bool:
try:
with get_db() as db:
db.query(Tool).filter_by(id=id).delete()
db.commit()
return True
except Exception:
return False
Tools = ToolsTable()

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