Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
3b0cb794
Unverified
Commit
3b0cb794
authored
Mar 31, 2024
by
Timothy Jaeryang Baek
Committed by
GitHub
Mar 31, 2024
Browse files
Merge pull request #1362 from open-webui/dev
0.1.116
parents
ac294a74
46a18104
Changes
57
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
217 additions
and
96 deletions
+217
-96
.github/workflows/format-backend.yaml
.github/workflows/format-backend.yaml
+2
-0
.github/workflows/format-build-frontend.yaml
.github/workflows/format-build-frontend.yaml
+3
-0
CHANGELOG.md
CHANGELOG.md
+18
-0
backend/apps/audio/main.py
backend/apps/audio/main.py
+7
-1
backend/apps/ollama/main.py
backend/apps/ollama/main.py
+12
-2
backend/apps/rag/main.py
backend/apps/rag/main.py
+59
-43
backend/apps/web/models/auths.py
backend/apps/web/models/auths.py
+1
-0
backend/apps/web/models/documents.py
backend/apps/web/models/documents.py
+1
-0
backend/apps/web/models/modelfiles.py
backend/apps/web/models/modelfiles.py
+12
-12
backend/apps/web/models/prompts.py
backend/apps/web/models/prompts.py
+9
-6
backend/apps/web/models/tags.py
backend/apps/web/models/tags.py
+1
-0
backend/apps/web/routers/chats.py
backend/apps/web/routers/chats.py
+1
-0
backend/apps/web/routers/configs.py
backend/apps/web/routers/configs.py
+6
-2
backend/apps/web/routers/modelfiles.py
backend/apps/web/routers/modelfiles.py
+24
-21
backend/apps/web/routers/users.py
backend/apps/web/routers/users.py
+1
-0
backend/config.py
backend/config.py
+18
-3
backend/constants.py
backend/constants.py
+2
-0
backend/data/config.json
backend/data/config.json
+1
-0
backend/main.py
backend/main.py
+11
-5
backend/utils/webhook.py
backend/utils/webhook.py
+28
-1
No files found.
.github/workflows/format-backend.yaml
View file @
3b0cb794
...
...
@@ -25,3 +25,5 @@ jobs:
pip install yapf
-
name
:
Format backend
run
:
bun run format:backend
-
name
:
Check for changes after format
run
:
git diff --exit-code
.github/workflows/format-build-frontend.yaml
View file @
3b0cb794
...
...
@@ -18,5 +18,8 @@ jobs:
run
:
bun install
-
name
:
Format frontend
run
:
bun run format
-
name
:
Check for changes after format
run
:
git diff --exit-code
-
name
:
Build frontend
if
:
always()
run
:
bun run build
CHANGELOG.md
View file @
3b0cb794
...
...
@@ -5,6 +5,24 @@ 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.1.116] - 2024-03-31
### Added
-
**🔄 Enhanced UI**
: Model selector now conveniently located in the navbar, enabling seamless switching between multiple models during conversations.
-
**🔍 Improved Model Selector**
: Directly pull a model from the selector/Models now display detailed information for better understanding.
-
**💬 Webhook Support**
: Now compatible with Google Chat and Microsoft Teams.
-
**🌐 Localization**
: Korean translation (I18n) now available.
-
**🌑 Dark Theme**
: OLED dark theme introduced for reduced strain during prolonged usage.
-
**🏷️ Tag Autocomplete**
: Dropdown feature added for effortless chat tagging.
### Fixed
-
**🔽 Auto-Scrolling**
: Addressed OpenAI auto-scrolling issue.
-
**🏷️ Tag Validation**
: Implemented tag validation to prevent empty string tags.
-
**🚫 Model Whitelisting**
: Resolved LiteLLM model whitelisting issue.
-
**✅ Spelling**
: Corrected various spelling issues for improved readability.
## [0.1.115] - 2024-03-24
### Added
...
...
backend/apps/audio/main.py
View file @
3b0cb794
...
...
@@ -22,7 +22,13 @@ from utils.utils import (
)
from
utils.misc
import
calculate_sha256
from
config
import
SRC_LOG_LEVELS
,
CACHE_DIR
,
UPLOAD_DIR
,
WHISPER_MODEL
,
WHISPER_MODEL_DIR
from
config
import
(
SRC_LOG_LEVELS
,
CACHE_DIR
,
UPLOAD_DIR
,
WHISPER_MODEL
,
WHISPER_MODEL_DIR
,
)
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"AUDIO"
])
...
...
backend/apps/ollama/main.py
View file @
3b0cb794
...
...
@@ -33,7 +33,13 @@ from constants import ERROR_MESSAGES
from
utils.utils
import
decode_token
,
get_current_user
,
get_admin_user
from
config
import
SRC_LOG_LEVELS
,
OLLAMA_BASE_URLS
,
MODEL_FILTER_ENABLED
,
MODEL_FILTER_LIST
,
UPLOAD_DIR
from
config
import
(
SRC_LOG_LEVELS
,
OLLAMA_BASE_URLS
,
MODEL_FILTER_ENABLED
,
MODEL_FILTER_LIST
,
UPLOAD_DIR
,
)
from
utils.misc
import
calculate_sha256
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -770,7 +776,11 @@ async def generate_chat_completion(
r
=
None
log
.
debug
(
"form_data.model_dump_json(exclude_none=True).encode(): {0} "
.
format
(
form_data
.
model_dump_json
(
exclude_none
=
True
).
encode
()))
log
.
debug
(
"form_data.model_dump_json(exclude_none=True).encode(): {0} "
.
format
(
form_data
.
model_dump_json
(
exclude_none
=
True
).
encode
()
)
)
def
get_request
():
nonlocal
form_data
...
...
backend/apps/rag/main.py
View file @
3b0cb794
...
...
@@ -21,6 +21,7 @@ from langchain_community.document_loaders import (
TextLoader
,
PyPDFLoader
,
CSVLoader
,
BSHTMLLoader
,
Docx2txtLoader
,
UnstructuredEPubLoader
,
UnstructuredWordDocumentLoader
,
...
...
@@ -114,6 +115,7 @@ class CollectionNameForm(BaseModel):
class
StoreWebForm
(
CollectionNameForm
):
url
:
str
@
app
.
get
(
"/"
)
async
def
get_status
():
return
{
...
...
@@ -296,13 +298,18 @@ def store_web(form_data: StoreWebForm, user=Depends(get_current_user)):
def
store_data_in_vector_db
(
data
,
collection_name
,
overwrite
:
bool
=
False
)
->
bool
:
text_splitter
=
RecursiveCharacterTextSplitter
(
chunk_size
=
app
.
state
.
CHUNK_SIZE
,
chunk_overlap
=
app
.
state
.
CHUNK_OVERLAP
,
add_start_index
=
True
,
)
docs
=
text_splitter
.
split_documents
(
data
)
return
store_docs_in_vector_db
(
docs
,
collection_name
,
overwrite
)
if
len
(
docs
)
>
0
:
return
store_docs_in_vector_db
(
docs
,
collection_name
,
overwrite
),
None
else
:
raise
ValueError
(
ERROR_MESSAGES
.
EMPTY_CONTENT
)
def
store_text_in_vector_db
(
...
...
@@ -318,6 +325,7 @@ def store_text_in_vector_db(
def
store_docs_in_vector_db
(
docs
,
collection_name
,
overwrite
:
bool
=
False
)
->
bool
:
texts
=
[
doc
.
page_content
for
doc
in
docs
]
metadatas
=
[
doc
.
metadata
for
doc
in
docs
]
...
...
@@ -402,6 +410,8 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
loader
=
UnstructuredRSTLoader
(
file_path
,
mode
=
"elements"
)
elif
file_ext
==
"xml"
:
loader
=
UnstructuredXMLLoader
(
file_path
)
elif
file_ext
in
[
"htm"
,
"html"
]:
loader
=
BSHTMLLoader
(
file_path
,
open_encoding
=
"unicode_escape"
)
elif
file_ext
==
"md"
:
loader
=
UnstructuredMarkdownLoader
(
file_path
)
elif
file_content_type
==
"application/epub+zip"
:
...
...
@@ -452,19 +462,21 @@ def store_doc(
loader
,
known_type
=
get_loader
(
file
.
filename
,
file
.
content_type
,
file_path
)
data
=
loader
.
load
()
result
=
store_data_in_vector_db
(
data
,
collection_name
)
if
result
:
return
{
"status"
:
True
,
"collection_name"
:
collection_name
,
"filename"
:
filename
,
"known_type"
:
known_type
,
}
else
:
try
:
result
=
store_data_in_vector_db
(
data
,
collection_name
)
if
result
:
return
{
"status"
:
True
,
"collection_name"
:
collection_name
,
"filename"
:
filename
,
"known_type"
:
known_type
,
}
except
Exception
as
e
:
raise
HTTPException
(
status_code
=
status
.
HTTP_500_INTERNAL_SERVER_ERROR
,
detail
=
ERROR_MESSAGES
.
DEFAULT
()
,
detail
=
e
,
)
except
Exception
as
e
:
log
.
exception
(
e
)
...
...
@@ -529,38 +541,42 @@ def scan_docs_dir(user=Depends(get_admin_user)):
)
data
=
loader
.
load
()
result
=
store_data_in_vector_db
(
data
,
collection_name
)
if
result
:
sanitized_filename
=
sanitize_filename
(
filename
)
doc
=
Documents
.
get_doc_by_name
(
sanitized_filename
)
if
doc
==
None
:
doc
=
Documents
.
insert_new_doc
(
user
.
id
,
DocumentForm
(
**
{
"name"
:
sanitized_filename
,
"title"
:
filename
,
"collection_name"
:
collection_name
,
"filename"
:
filename
,
"content"
:
(
json
.
dumps
(
{
"tags"
:
list
(
map
(
lambda
name
:
{
"name"
:
name
},
tags
,
try
:
result
=
store_data_in_vector_db
(
data
,
collection_name
)
if
result
:
sanitized_filename
=
sanitize_filename
(
filename
)
doc
=
Documents
.
get_doc_by_name
(
sanitized_filename
)
if
doc
==
None
:
doc
=
Documents
.
insert_new_doc
(
user
.
id
,
DocumentForm
(
**
{
"name"
:
sanitized_filename
,
"title"
:
filename
,
"collection_name"
:
collection_name
,
"filename"
:
filename
,
"content"
:
(
json
.
dumps
(
{
"tags"
:
list
(
map
(
lambda
name
:
{
"name"
:
name
},
tags
,
)
)
)
}
)
if
len
(
tags
)
else
"{}"
),
}
),
)
}
)
if
len
(
tags
)
else
"{}"
),
}
),
)
except
Exception
as
e
:
print
(
e
)
pass
except
Exception
as
e
:
log
.
exception
(
e
)
...
...
backend/apps/web/models/auths.py
View file @
3b0cb794
...
...
@@ -11,6 +11,7 @@ from utils.utils import verify_password
from
apps.web.internal.db
import
DB
from
config
import
SRC_LOG_LEVELS
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"MODELS"
])
...
...
backend/apps/web/models/documents.py
View file @
3b0cb794
...
...
@@ -13,6 +13,7 @@ from apps.web.internal.db import DB
import
json
from
config
import
SRC_LOG_LEVELS
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"MODELS"
])
...
...
backend/apps/web/models/modelfiles.py
View file @
3b0cb794
...
...
@@ -64,8 +64,8 @@ class ModelfilesTable:
self
.
db
.
create_tables
([
Modelfile
])
def
insert_new_modelfile
(
self
,
user_id
:
str
,
form_data
:
ModelfileForm
)
->
Optional
[
ModelfileModel
]:
self
,
user_id
:
str
,
form_data
:
ModelfileForm
)
->
Optional
[
ModelfileModel
]:
if
"tagName"
in
form_data
.
modelfile
:
modelfile
=
ModelfileModel
(
**
{
...
...
@@ -73,7 +73,8 @@ class ModelfilesTable:
"tag_name"
:
form_data
.
modelfile
[
"tagName"
],
"modelfile"
:
json
.
dumps
(
form_data
.
modelfile
),
"timestamp"
:
int
(
time
.
time
()),
})
}
)
try
:
result
=
Modelfile
.
create
(
**
modelfile
.
model_dump
())
...
...
@@ -87,29 +88,28 @@ class ModelfilesTable:
else
:
return
None
def
get_modelfile_by_tag_name
(
self
,
tag_name
:
str
)
->
Optional
[
ModelfileModel
]:
def
get_modelfile_by_tag_name
(
self
,
tag_name
:
str
)
->
Optional
[
ModelfileModel
]:
try
:
modelfile
=
Modelfile
.
get
(
Modelfile
.
tag_name
==
tag_name
)
return
ModelfileModel
(
**
model_to_dict
(
modelfile
))
except
:
return
None
def
get_modelfiles
(
self
,
skip
:
int
=
0
,
limit
:
int
=
50
)
->
List
[
ModelfileResponse
]:
def
get_modelfiles
(
self
,
skip
:
int
=
0
,
limit
:
int
=
50
)
->
List
[
ModelfileResponse
]:
return
[
ModelfileResponse
(
**
{
**
model_to_dict
(
modelfile
),
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
})
for
modelfile
in
Modelfile
.
select
()
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
for
modelfile
in
Modelfile
.
select
()
# .limit(limit).offset(skip)
]
def
update_modelfile_by_tag_name
(
self
,
tag_name
:
str
,
modelfile
:
dict
)
->
Optional
[
ModelfileModel
]:
self
,
tag_name
:
str
,
modelfile
:
dict
)
->
Optional
[
ModelfileModel
]:
try
:
query
=
Modelfile
.
update
(
modelfile
=
json
.
dumps
(
modelfile
),
...
...
backend/apps/web/models/prompts.py
View file @
3b0cb794
...
...
@@ -52,8 +52,9 @@ class PromptsTable:
self
.
db
=
db
self
.
db
.
create_tables
([
Prompt
])
def
insert_new_prompt
(
self
,
user_id
:
str
,
form_data
:
PromptForm
)
->
Optional
[
PromptModel
]:
def
insert_new_prompt
(
self
,
user_id
:
str
,
form_data
:
PromptForm
)
->
Optional
[
PromptModel
]:
prompt
=
PromptModel
(
**
{
"user_id"
:
user_id
,
...
...
@@ -61,7 +62,8 @@ class PromptsTable:
"title"
:
form_data
.
title
,
"content"
:
form_data
.
content
,
"timestamp"
:
int
(
time
.
time
()),
})
}
)
try
:
result
=
Prompt
.
create
(
**
prompt
.
model_dump
())
...
...
@@ -81,13 +83,14 @@ class PromptsTable:
def
get_prompts
(
self
)
->
List
[
PromptModel
]:
return
[
PromptModel
(
**
model_to_dict
(
prompt
))
for
prompt
in
Prompt
.
select
()
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
]:
self
,
command
:
str
,
form_data
:
PromptForm
)
->
Optional
[
PromptModel
]:
try
:
query
=
Prompt
.
update
(
title
=
form_data
.
title
,
...
...
backend/apps/web/models/tags.py
View file @
3b0cb794
...
...
@@ -11,6 +11,7 @@ import logging
from
apps.web.internal.db
import
DB
from
config
import
SRC_LOG_LEVELS
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"MODELS"
])
...
...
backend/apps/web/routers/chats.py
View file @
3b0cb794
...
...
@@ -29,6 +29,7 @@ from apps.web.models.tags import (
from
constants
import
ERROR_MESSAGES
from
config
import
SRC_LOG_LEVELS
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"MODELS"
])
...
...
backend/apps/web/routers/configs.py
View file @
3b0cb794
...
...
@@ -10,7 +10,12 @@ import uuid
from
apps.web.models.users
import
Users
from
utils.utils
import
get_password_hash
,
get_current_user
,
get_admin_user
,
create_token
from
utils.utils
import
(
get_password_hash
,
get_current_user
,
get_admin_user
,
create_token
,
)
from
utils.misc
import
get_gravatar_url
,
validate_email_format
from
constants
import
ERROR_MESSAGES
...
...
@@ -43,7 +48,6 @@ async def set_global_default_models(
return
request
.
app
.
state
.
DEFAULT_MODELS
@
router
.
post
(
"/default/suggestions"
,
response_model
=
List
[
PromptSuggestion
])
async
def
set_global_default_suggestions
(
request
:
Request
,
...
...
backend/apps/web/routers/modelfiles.py
View file @
3b0cb794
...
...
@@ -24,9 +24,9 @@ router = APIRouter()
@
router
.
get
(
"/"
,
response_model
=
List
[
ModelfileResponse
])
async
def
get_modelfiles
(
skip
:
int
=
0
,
limit
:
int
=
50
,
user
=
Depends
(
get_current_user
)
):
async
def
get_modelfiles
(
skip
:
int
=
0
,
limit
:
int
=
50
,
user
=
Depends
(
get_current_user
)
):
return
Modelfiles
.
get_modelfiles
(
skip
,
limit
)
...
...
@@ -36,17 +36,16 @@ async def get_modelfiles(skip: int = 0,
@
router
.
post
(
"/create"
,
response_model
=
Optional
[
ModelfileResponse
])
async
def
create_new_modelfile
(
form_data
:
ModelfileForm
,
user
=
Depends
(
get_admin_user
)):
async
def
create_new_modelfile
(
form_data
:
ModelfileForm
,
user
=
Depends
(
get_admin_user
)):
modelfile
=
Modelfiles
.
insert_new_modelfile
(
user
.
id
,
form_data
)
if
modelfile
:
return
ModelfileResponse
(
**
{
**
modelfile
.
model_dump
(),
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
...
...
@@ -60,17 +59,18 @@ async def create_new_modelfile(form_data: ModelfileForm,
@
router
.
post
(
"/"
,
response_model
=
Optional
[
ModelfileResponse
])
async
def
get_modelfile_by_tag_name
(
form_data
:
ModelfileTagNameForm
,
user
=
Depends
(
get_current_user
)):
async
def
get_modelfile_by_tag_name
(
form_data
:
ModelfileTagNameForm
,
user
=
Depends
(
get_current_user
)
):
modelfile
=
Modelfiles
.
get_modelfile_by_tag_name
(
form_data
.
tag_name
)
if
modelfile
:
return
ModelfileResponse
(
**
{
**
modelfile
.
model_dump
(),
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
...
...
@@ -84,8 +84,9 @@ async def get_modelfile_by_tag_name(form_data: ModelfileTagNameForm,
@
router
.
post
(
"/update"
,
response_model
=
Optional
[
ModelfileResponse
])
async
def
update_modelfile_by_tag_name
(
form_data
:
ModelfileUpdateForm
,
user
=
Depends
(
get_admin_user
)):
async
def
update_modelfile_by_tag_name
(
form_data
:
ModelfileUpdateForm
,
user
=
Depends
(
get_admin_user
)
):
modelfile
=
Modelfiles
.
get_modelfile_by_tag_name
(
form_data
.
tag_name
)
if
modelfile
:
updated_modelfile
=
{
...
...
@@ -94,14 +95,15 @@ async def update_modelfile_by_tag_name(form_data: ModelfileUpdateForm,
}
modelfile
=
Modelfiles
.
update_modelfile_by_tag_name
(
form_data
.
tag_name
,
updated_modelfile
)
form_data
.
tag_name
,
updated_modelfile
)
return
ModelfileResponse
(
**
{
**
modelfile
.
model_dump
(),
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
"modelfile"
:
json
.
loads
(
modelfile
.
modelfile
),
}
)
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
...
...
@@ -115,7 +117,8 @@ async def update_modelfile_by_tag_name(form_data: ModelfileUpdateForm,
@
router
.
delete
(
"/delete"
,
response_model
=
bool
)
async
def
delete_modelfile_by_tag_name
(
form_data
:
ModelfileTagNameForm
,
user
=
Depends
(
get_admin_user
)):
async
def
delete_modelfile_by_tag_name
(
form_data
:
ModelfileTagNameForm
,
user
=
Depends
(
get_admin_user
)
):
result
=
Modelfiles
.
delete_modelfile_by_tag_name
(
form_data
.
tag_name
)
return
result
backend/apps/web/routers/users.py
View file @
3b0cb794
...
...
@@ -16,6 +16,7 @@ from utils.utils import get_current_user, get_password_hash, get_admin_user
from
constants
import
ERROR_MESSAGES
from
config
import
SRC_LOG_LEVELS
log
=
logging
.
getLogger
(
__name__
)
log
.
setLevel
(
SRC_LOG_LEVELS
[
"MODELS"
])
...
...
backend/config.py
View file @
3b0cb794
...
...
@@ -26,6 +26,7 @@ except ImportError:
log
.
warning
(
"dotenv not installed, skipping..."
)
WEBUI_NAME
=
"Open WebUI"
WEBUI_FAVICON_URL
=
"https://openwebui.com/favicon.png"
shutil
.
copyfile
(
"../build/favicon.png"
,
"./static/favicon.png"
)
####################################
...
...
@@ -116,7 +117,18 @@ else:
log
=
logging
.
getLogger
(
__name__
)
log
.
info
(
f
"GLOBAL_LOG_LEVEL:
{
GLOBAL_LOG_LEVEL
}
"
)
log_sources
=
[
"AUDIO"
,
"CONFIG"
,
"DB"
,
"IMAGES"
,
"LITELLM"
,
"MAIN"
,
"MODELS"
,
"OLLAMA"
,
"OPENAI"
,
"RAG"
]
log_sources
=
[
"AUDIO"
,
"CONFIG"
,
"DB"
,
"IMAGES"
,
"LITELLM"
,
"MAIN"
,
"MODELS"
,
"OLLAMA"
,
"OPENAI"
,
"RAG"
,
]
SRC_LOG_LEVELS
=
{}
...
...
@@ -141,7 +153,7 @@ if CUSTOM_NAME:
data
=
r
.
json
()
if
r
.
ok
:
if
"logo"
in
data
:
url
=
(
WEBUI_FAVICON_URL
=
url
=
(
f
"https://api.openwebui.com
{
data
[
'logo'
]
}
"
if
data
[
"logo"
][
0
]
==
"/"
else
data
[
"logo"
]
...
...
@@ -238,7 +250,7 @@ OLLAMA_API_BASE_URL = os.environ.get(
)
OLLAMA_BASE_URL
=
os
.
environ
.
get
(
"OLLAMA_BASE_URL"
,
""
)
K8S_FLAG
=
os
.
environ
.
get
(
"K8S_FLAG"
,
""
)
if
OLLAMA_BASE_URL
==
""
and
OLLAMA_API_BASE_URL
!=
""
:
OLLAMA_BASE_URL
=
(
...
...
@@ -251,6 +263,9 @@ if ENV == "prod":
if
OLLAMA_BASE_URL
==
"/ollama"
:
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
...
...
backend/constants.py
View file @
3b0cb794
...
...
@@ -60,3 +60,5 @@ class ERROR_MESSAGES(str, Enum):
MODEL_NOT_FOUND
=
lambda
name
=
""
:
f
"Model '
{
name
}
' was not found"
OPENAI_NOT_FOUND
=
lambda
name
=
""
:
f
"OpenAI API was not found"
OLLAMA_NOT_FOUND
=
"WebUI could not connect to Ollama"
EMPTY_CONTENT
=
"The content provided is empty. Please ensure that there is text or data present before proceeding."
backend/data/config.json
View file @
3b0cb794
{
"version"
:
0
,
"ui"
:
{
"default_locale"
:
"en-US"
,
"prompt_suggestions"
:
[
{
"title"
:
[
...
...
backend/main.py
View file @
3b0cb794
...
...
@@ -32,6 +32,7 @@ from utils.utils import get_admin_user
from
apps.rag.utils
import
rag_messages
from
config
import
(
CONFIG_DATA
,
WEBUI_NAME
,
ENV
,
VERSION
,
...
...
@@ -49,6 +50,7 @@ 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
:
...
...
@@ -88,7 +90,6 @@ class RAGMiddleware(BaseHTTPMiddleware):
# Example: Add a new key-value pair or modify existing ones
# data["modified"] = True # Example modification
if
"docs"
in
data
:
data
=
{
**
data
}
data
[
"messages"
]
=
rag_messages
(
data
[
"docs"
],
...
...
@@ -163,11 +164,15 @@ app.mount("/rag/api/v1", rag_app)
@
app
.
get
(
"/api/config"
)
async
def
get_app_config
():
return
{
"status"
:
True
,
"name"
:
WEBUI_NAME
,
"version"
:
VERSION
,
"default_locale"
:
(
CONFIG_DATA
[
"ui"
][
"default_locale"
]
if
"default_locale"
in
CONFIG_DATA
[
"ui"
]
else
"en-US"
),
"images"
:
images_app
.
state
.
ENABLED
,
"default_models"
:
webui_app
.
state
.
DEFAULT_MODELS
,
"default_prompt_suggestions"
:
webui_app
.
state
.
DEFAULT_PROMPT_SUGGESTIONS
,
...
...
@@ -191,7 +196,6 @@ class ModelFilterConfigForm(BaseModel):
async
def
update_model_filter_config
(
form_data
:
ModelFilterConfigForm
,
user
=
Depends
(
get_admin_user
)
):
app
.
state
.
MODEL_FILTER_ENABLED
=
form_data
.
enabled
app
.
state
.
MODEL_FILTER_LIST
=
form_data
.
models
...
...
@@ -201,6 +205,9 @@ async def update_model_filter_config(
openai_app
.
state
.
MODEL_FILTER_ENABLED
=
app
.
state
.
MODEL_FILTER_ENABLED
openai_app
.
state
.
MODEL_FILTER_LIST
=
app
.
state
.
MODEL_FILTER_LIST
litellm_app
.
state
.
MODEL_FILTER_ENABLED
=
app
.
state
.
MODEL_FILTER_ENABLED
litellm_app
.
state
.
MODEL_FILTER_LIST
=
app
.
state
.
MODEL_FILTER_LIST
return
{
"enabled"
:
app
.
state
.
MODEL_FILTER_ENABLED
,
"models"
:
app
.
state
.
MODEL_FILTER_LIST
,
...
...
@@ -231,7 +238,6 @@ async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
@
app
.
get
(
"/api/version"
)
async
def
get_app_config
():
return
{
"version"
:
VERSION
,
}
...
...
@@ -239,7 +245,7 @@ async def get_app_config():
@
app
.
get
(
"/api/changelog"
)
async
def
get_app_changelog
():
return
CHANGELOG
return
{
key
:
CHANGELOG
[
key
]
for
idx
,
key
in
enumerate
(
CHANGELOG
)
if
idx
<
5
}
@
app
.
get
(
"/api/version/updates"
)
...
...
backend/utils/webhook.py
View file @
3b0cb794
import
json
import
requests
from
config
import
VERSION
,
WEBUI_FAVICON_URL
,
WEBUI_NAME
def
post_webhook
(
url
:
str
,
message
:
str
,
event_data
:
dict
)
->
bool
:
try
:
payload
=
{}
if
"https://hooks.slack.com"
in
url
:
# Slack and Google Chat Webhooks
if
"https://hooks.slack.com"
in
url
or
"https://chat.googleapis.com"
in
url
:
payload
[
"text"
]
=
message
# Discord Webhooks
elif
"https://discord.com/api/webhooks"
in
url
:
payload
[
"content"
]
=
message
# Microsoft Teams Webhooks
elif
"webhook.office.com"
in
url
:
action
=
event_data
.
get
(
"action"
,
"undefined"
)
facts
=
[
{
"name"
:
name
,
"value"
:
value
}
for
name
,
value
in
json
.
loads
(
event_data
.
get
(
"user"
,
{})).
items
()
]
payload
=
{
"@type"
:
"MessageCard"
,
"@context"
:
"http://schema.org/extensions"
,
"themeColor"
:
"0076D7"
,
"summary"
:
message
,
"sections"
:
[
{
"activityTitle"
:
message
,
"activitySubtitle"
:
f
"
{
WEBUI_NAME
}
(
{
VERSION
}
) -
{
action
}
"
,
"activityImage"
:
WEBUI_FAVICON_URL
,
"facts"
:
facts
,
"markdown"
:
True
,
}
],
}
# Default Payload
else
:
payload
=
{
**
event_data
}
...
...
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment