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
3b3d0cce
Unverified
Commit
3b3d0cce
authored
Apr 08, 2024
by
Jannik S
Committed by
GitHub
Apr 08, 2024
Browse files
Merge branch 'dev' into dockerfile-optimisation
parents
073f06d4
72110c29
Changes
65
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
175 additions
and
38 deletions
+175
-38
.env.example
.env.example
+5
-1
.github/workflows/build-release.yml
.github/workflows/build-release.yml
+11
-0
.github/workflows/docker-build.yaml
.github/workflows/docker-build.yaml
+1
-0
CHANGELOG.md
CHANGELOG.md
+17
-0
backend/apps/ollama/main.py
backend/apps/ollama/main.py
+2
-1
backend/apps/rag/main.py
backend/apps/rag/main.py
+4
-18
backend/apps/web/models/auths.py
backend/apps/web/models/auths.py
+8
-2
backend/apps/web/models/chats.py
backend/apps/web/models/chats.py
+12
-0
backend/apps/web/models/users.py
backend/apps/web/models/users.py
+8
-3
backend/apps/web/routers/auths.py
backend/apps/web/routers/auths.py
+5
-1
backend/apps/web/routers/chats.py
backend/apps/web/routers/chats.py
+9
-1
backend/apps/web/routers/utils.py
backend/apps/web/routers/utils.py
+69
-8
backend/config.py
backend/config.py
+6
-2
backend/main.py
backend/main.py
+14
-1
backend/requirements.txt
backend/requirements.txt
+4
-0
backend/static/fonts/NotoSans-Bold.ttf
backend/static/fonts/NotoSans-Bold.ttf
+0
-0
backend/static/fonts/NotoSans-Italic.ttf
backend/static/fonts/NotoSans-Italic.ttf
+0
-0
backend/static/fonts/NotoSans-Regular.ttf
backend/static/fonts/NotoSans-Regular.ttf
+0
-0
backend/static/fonts/NotoSansJP-Regular.ttf
backend/static/fonts/NotoSansJP-Regular.ttf
+0
-0
backend/static/fonts/NotoSansKR-Regular.ttf
backend/static/fonts/NotoSansKR-Regular.ttf
+0
-0
No files found.
.env.example
View file @
3b3d0cce
...
...
@@ -10,3 +10,7 @@ OPENAI_API_KEY=''
# DO NOT TRACK
SCARF_NO_ANALYTICS=true
DO_NOT_TRACK=true
# Use locally bundled version of the LiteLLM cost map json
# to avoid repetitive startup connections
LITELLM_LOCAL_MODEL_COST_MAP="True"
.github/workflows/build-release.yml
View file @
3b3d0cce
...
...
@@ -57,3 +57,14 @@ jobs:
path
:
.
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 }}',
})
.github/workflows/docker-build.yaml
View file @
3b3d0cce
...
...
@@ -2,6 +2,7 @@ name: Create and publish Docker images with specific build args
# Configures this workflow to run every time a change is pushed to the branch called `release`.
on
:
workflow_dispatch
:
push
:
branches
:
-
main
...
...
CHANGELOG.md
View file @
3b3d0cce
...
...
@@ -5,6 +5,23 @@ 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.117] - 2024-04-03
### Added
-
🗨️
**Local Chat Sharing**
: Share chat links seamlessly between users.
-
🔑
**API Key Generation Support**
: Generate secret keys to leverage Open WebUI with OpenAI libraries.
-
📄
**Chat Download as PDF**
: Easily download chats in PDF format.
-
📝
**Improved Logging**
: Enhancements to logging functionality.
-
📧
**Trusted Email Authentication**
: Authenticate using a trusted email header.
### Fixed
-
🌷
**Enhanced Dutch Translation**
: Improved translation for Dutch users.
-
⚪
**White Theme Styling**
: Resolved styling issue with the white theme.
-
📜
**LaTeX Chat Screen Overflow**
: Fixed screen overflow issue with LaTeX rendering.
-
🔒
**Security Patches**
: Applied necessary security patches.
## [0.1.116] - 2024-03-31
### Added
...
...
backend/apps/ollama/main.py
View file @
3b3d0cce
...
...
@@ -215,7 +215,8 @@ async def get_ollama_versions(url_idx: Optional[int] = None):
if
len
(
responses
)
>
0
:
lowest_version
=
min
(
responses
,
key
=
lambda
x
:
tuple
(
map
(
int
,
x
[
"version"
].
split
(
"."
)))
responses
,
key
=
lambda
x
:
tuple
(
map
(
int
,
x
[
"version"
].
split
(
"-"
)[
0
].
split
(
"."
))),
)
return
{
"version"
:
lowest_version
[
"version"
]}
...
...
backend/apps/rag/main.py
View file @
3b3d0cce
...
...
@@ -8,7 +8,7 @@ from fastapi import (
Form
,
)
from
fastapi.middleware.cors
import
CORSMiddleware
import
os
,
shutil
,
logging
import
os
,
shutil
,
logging
,
re
from
pathlib
import
Path
from
typing
import
List
...
...
@@ -438,25 +438,11 @@ def store_doc(
log
.
info
(
f
"file.content_type:
{
file
.
content_type
}
"
)
try
:
is_valid_filename
=
True
unsanitized_filename
=
file
.
filename
if
not
unsanitized_filename
.
isascii
():
is_valid_filename
=
False
filename
=
os
.
path
.
basename
(
unsanitized_filename
)
unvalidated_file_path
=
f
"
{
UPLOAD_DIR
}
/
{
unsanitized_filename
}
"
dereferenced_file_path
=
str
(
Path
(
unvalidated_file_path
).
resolve
(
strict
=
False
))
if
not
dereferenced_file_path
.
startswith
(
UPLOAD_DIR
):
is_valid_filename
=
False
file_path
=
f
"
{
UPLOAD_DIR
}
/
{
filename
}
"
if
is_valid_filename
:
file_path
=
dereferenced_file_path
else
:
raise
HTTPException
(
status_code
=
status
.
HTTP_400_BAD_REQUEST
,
detail
=
ERROR_MESSAGES
.
DEFAULT
(),
)
filename
=
file
.
filename
contents
=
file
.
file
.
read
()
with
open
(
file_path
,
"wb"
)
as
f
:
f
.
write
(
contents
)
...
...
@@ -467,7 +453,7 @@ def store_doc(
collection_name
=
calculate_sha256
(
f
)[:
63
]
f
.
close
()
loader
,
known_type
=
get_loader
(
file
.
filename
,
file
.
content_type
,
file_path
)
loader
,
known_type
=
get_loader
(
filename
,
file
.
content_type
,
file_path
)
data
=
loader
.
load
()
try
:
...
...
backend/apps/web/models/auths.py
View file @
3b3d0cce
...
...
@@ -86,6 +86,7 @@ class SignupForm(BaseModel):
name
:
str
email
:
str
password
:
str
profile_image_url
:
Optional
[
str
]
=
"/user.png"
class
AuthsTable
:
...
...
@@ -94,7 +95,12 @@ class AuthsTable:
self
.
db
.
create_tables
([
Auth
])
def
insert_new_auth
(
self
,
email
:
str
,
password
:
str
,
name
:
str
,
role
:
str
=
"pending"
self
,
email
:
str
,
password
:
str
,
name
:
str
,
profile_image_url
:
str
=
"/user.png"
,
role
:
str
=
"pending"
,
)
->
Optional
[
UserModel
]:
log
.
info
(
"insert_new_auth"
)
...
...
@@ -105,7 +111,7 @@ class AuthsTable:
)
result
=
Auth
.
create
(
**
auth
.
model_dump
())
user
=
Users
.
insert_new_user
(
id
,
name
,
email
,
role
)
user
=
Users
.
insert_new_user
(
id
,
name
,
email
,
profile_image_url
,
role
)
if
result
and
user
:
return
user
...
...
backend/apps/web/models/chats.py
View file @
3b3d0cce
...
...
@@ -206,6 +206,18 @@ class ChatTable:
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
)
...
...
backend/apps/web/models/users.py
View file @
3b3d0cce
...
...
@@ -31,7 +31,7 @@ class UserModel(BaseModel):
name
:
str
email
:
str
role
:
str
=
"pending"
profile_image_url
:
str
=
"/user.png"
profile_image_url
:
str
timestamp
:
int
# timestamp in epoch
api_key
:
Optional
[
str
]
=
None
...
...
@@ -59,7 +59,12 @@ class UsersTable:
self
.
db
.
create_tables
([
User
])
def
insert_new_user
(
self
,
id
:
str
,
name
:
str
,
email
:
str
,
role
:
str
=
"pending"
self
,
id
:
str
,
name
:
str
,
email
:
str
,
profile_image_url
:
str
=
"/user.png"
,
role
:
str
=
"pending"
,
)
->
Optional
[
UserModel
]:
user
=
UserModel
(
**
{
...
...
@@ -67,7 +72,7 @@ class UsersTable:
"name"
:
name
,
"email"
:
email
,
"role"
:
role
,
"profile_image_url"
:
"/user.png"
,
"profile_image_url"
:
profile_image_url
,
"timestamp"
:
int
(
time
.
time
()),
}
)
...
...
backend/apps/web/routers/auths.py
View file @
3b3d0cce
...
...
@@ -163,7 +163,11 @@ async def signup(request: Request, form_data: SignupForm):
)
hashed
=
get_password_hash
(
form_data
.
password
)
user
=
Auths
.
insert_new_auth
(
form_data
.
email
.
lower
(),
hashed
,
form_data
.
name
,
role
form_data
.
email
.
lower
(),
hashed
,
form_data
.
name
,
form_data
.
profile_image_url
,
role
,
)
if
user
:
...
...
backend/apps/web/routers/chats.py
View file @
3b3d0cce
...
...
@@ -251,6 +251,14 @@ async def delete_shared_chat_by_id(id: str, user=Depends(get_current_user)):
@
router
.
get
(
"/share/{share_id}"
,
response_model
=
Optional
[
ChatResponse
])
async
def
get_shared_chat_by_id
(
share_id
:
str
,
user
=
Depends
(
get_current_user
)):
if
user
.
role
==
"pending"
:
raise
HTTPException
(
status_code
=
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
ERROR_MESSAGES
.
NOT_FOUND
)
if
user
.
role
==
"user"
:
chat
=
Chats
.
get_chat_by_share_id
(
share_id
)
elif
user
.
role
==
"admin"
:
chat
=
Chats
.
get_chat_by_id
(
share_id
)
if
chat
:
...
...
backend/apps/web/routers/utils.py
View file @
3b3d0cce
from
fastapi
import
APIRouter
,
UploadFile
,
File
,
BackgroundTasks
from
fastapi
import
APIRouter
,
UploadFile
,
File
,
Response
from
fastapi
import
Depends
,
HTTPException
,
status
from
starlette.responses
import
StreamingResponse
,
FileResponse
from
pydantic
import
BaseModel
import
requests
import
os
import
aiohttp
import
json
from
fpdf
import
FPDF
import
markdown
from
utils.utils
import
get_admin_user
...
...
@@ -16,7 +13,7 @@ from utils.misc import calculate_sha256, get_gravatar_url
from
config
import
OLLAMA_BASE_URLS
,
DATA_DIR
,
UPLOAD_DIR
from
constants
import
ERROR_MESSAGES
from
typing
import
List
router
=
APIRouter
()
...
...
@@ -28,6 +25,70 @@ async def get_gravatar(
return
get_gravatar_url
(
email
)
class
MarkdownForm
(
BaseModel
):
md
:
str
@
router
.
post
(
"/markdown"
)
async
def
get_html_from_markdown
(
form_data
:
MarkdownForm
,
):
return
{
"html"
:
markdown
.
markdown
(
form_data
.
md
)}
class
ChatForm
(
BaseModel
):
title
:
str
messages
:
List
[
dict
]
@
router
.
post
(
"/pdf"
)
async
def
download_chat_as_pdf
(
form_data
:
ChatForm
,
):
pdf
=
FPDF
()
pdf
.
add_page
()
STATIC_DIR
=
"./static"
FONTS_DIR
=
f
"
{
STATIC_DIR
}
/fonts"
pdf
.
add_font
(
"NotoSans"
,
""
,
f
"
{
FONTS_DIR
}
/NotoSans-Regular.ttf"
)
pdf
.
add_font
(
"NotoSans"
,
"b"
,
f
"
{
FONTS_DIR
}
/NotoSans-Bold.ttf"
)
pdf
.
add_font
(
"NotoSans"
,
"i"
,
f
"
{
FONTS_DIR
}
/NotoSans-Italic.ttf"
)
pdf
.
add_font
(
"NotoSansKR"
,
""
,
f
"
{
FONTS_DIR
}
/NotoSansKR-Regular.ttf"
)
pdf
.
add_font
(
"NotoSansJP"
,
""
,
f
"
{
FONTS_DIR
}
/NotoSansJP-Regular.ttf"
)
pdf
.
set_font
(
"NotoSans"
,
size
=
12
)
pdf
.
set_fallback_fonts
([
"NotoSansKR"
,
"NotoSansJP"
])
pdf
.
set_auto_page_break
(
auto
=
True
,
margin
=
15
)
# Adjust the effective page width for multi_cell
effective_page_width
=
(
pdf
.
w
-
2
*
pdf
.
l_margin
-
10
)
# Subtracted an additional 10 for extra padding
# Add chat messages
for
message
in
form_data
.
messages
:
role
=
message
[
"role"
]
content
=
message
[
"content"
]
pdf
.
set_font
(
"NotoSans"
,
"B"
,
size
=
14
)
# Bold for the role
pdf
.
multi_cell
(
effective_page_width
,
10
,
f
"
{
role
.
upper
()
}
"
,
0
,
"L"
)
pdf
.
ln
(
1
)
# Extra space between messages
pdf
.
set_font
(
"NotoSans"
,
size
=
10
)
# Regular for content
pdf
.
multi_cell
(
effective_page_width
,
6
,
content
,
0
,
"L"
)
pdf
.
ln
(
1.5
)
# Extra space between messages
# Save the pdf with name .pdf
pdf_bytes
=
pdf
.
output
()
return
Response
(
content
=
bytes
(
pdf_bytes
),
media_type
=
"application/pdf"
,
headers
=
{
"Content-Disposition"
:
f
"attachment;filename=chat.pdf"
},
)
@
router
.
get
(
"/db/download"
)
async
def
download_db
(
user
=
Depends
(
get_admin_user
)):
...
...
backend/config.py
View file @
3b3d0cce
...
...
@@ -25,8 +25,9 @@ try:
except
ImportError
:
log
.
warning
(
"dotenv not installed, skipping..."
)
WEBUI_NAME
=
"Open WebUI"
WEBUI_NAME
=
os
.
environ
.
get
(
"WEBUI_NAME"
,
"Open WebUI"
)
WEBUI_FAVICON_URL
=
"https://openwebui.com/favicon.png"
shutil
.
copyfile
(
"../build/favicon.png"
,
"./static/favicon.png"
)
####################################
...
...
@@ -149,6 +150,7 @@ log.setLevel(SRC_LOG_LEVELS["CONFIG"])
####################################
CUSTOM_NAME
=
os
.
environ
.
get
(
"CUSTOM_NAME"
,
""
)
if
CUSTOM_NAME
:
try
:
r
=
requests
.
get
(
f
"https://api.openwebui.com/api/v1/custom/
{
CUSTOM_NAME
}
"
)
...
...
@@ -171,7 +173,9 @@ if CUSTOM_NAME:
except
Exception
as
e
:
log
.
exception
(
e
)
pass
else
:
if
WEBUI_NAME
!=
"Open WebUI"
:
WEBUI_NAME
+=
" (Open WebUI)"
####################################
# DATA/FRONTEND BUILD DIR
...
...
backend/main.py
View file @
3b3d0cce
...
...
@@ -84,7 +84,6 @@ app.state.MODEL_FILTER_LIST = MODEL_FILTER_LIST
app
.
state
.
WEBHOOK_URL
=
WEBHOOK_URL
origins
=
[
"*"
]
...
...
@@ -284,6 +283,20 @@ async def get_app_latest_release_version():
)
@
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"
:
"/favicon.png"
,
"type"
:
"image/png"
,
"sizes"
:
"844x884"
}],
}
app
.
mount
(
"/static"
,
StaticFiles
(
directory
=
"static"
),
name
=
"static"
)
app
.
mount
(
"/cache"
,
StaticFiles
(
directory
=
"data/cache"
),
name
=
"cache"
)
...
...
backend/requirements.txt
View file @
3b3d0cce
...
...
@@ -18,6 +18,8 @@ peewee-migrate
bcrypt
litellm==1.30.7
boto3
argon2-cffi
apscheduler
google-generativeai
...
...
@@ -40,6 +42,8 @@ xlrd
opencv-python-headless
rapidocr-onnxruntime
fpdf2
faster-whisper
PyJWT
...
...
backend/static/fonts/NotoSans-Bold.ttf
0 → 100644
View file @
3b3d0cce
File added
backend/static/fonts/NotoSans-Italic.ttf
0 → 100644
View file @
3b3d0cce
File added
backend/static/fonts/NotoSans-Regular.ttf
0 → 100644
View file @
3b3d0cce
File added
backend/static/fonts/NotoSansJP-Regular.ttf
0 → 100644
View file @
3b3d0cce
File added
backend/static/fonts/NotoSansKR-Regular.ttf
0 → 100644
View file @
3b3d0cce
File added
Prev
1
2
3
4
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