forked from open-webui/open-webui
Merge Updates & Dockerfile improvements
This commit is contained in:
parent
fdef2abdfb
commit
9763d885be
155 changed files with 14509 additions and 4803 deletions
|
@ -27,7 +27,8 @@ from utils.utils import (
|
|||
create_token,
|
||||
)
|
||||
from utils.misc import parse_duration, validate_email_format
|
||||
from constants import ERROR_MESSAGES
|
||||
from utils.webhook import post_webhook
|
||||
from constants import ERROR_MESSAGES, WEBHOOK_MESSAGES
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
@ -155,6 +156,17 @@ async def signup(request: Request, form_data: SignupForm):
|
|||
)
|
||||
# response.set_cookie(key='token', value=token, httponly=True)
|
||||
|
||||
if request.app.state.WEBHOOK_URL:
|
||||
post_webhook(
|
||||
request.app.state.WEBHOOK_URL,
|
||||
WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
|
||||
{
|
||||
"action": "signup",
|
||||
"message": WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
|
||||
"user": user.model_dump_json(exclude_none=True),
|
||||
},
|
||||
)
|
||||
|
||||
return {
|
||||
"token": token,
|
||||
"token_type": "Bearer",
|
||||
|
|
|
@ -5,6 +5,7 @@ from utils.utils import get_current_user, get_admin_user
|
|||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
import json
|
||||
import logging
|
||||
|
||||
from apps.web.models.users import Users
|
||||
from apps.web.models.chats import (
|
||||
|
@ -27,6 +28,11 @@ 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"])
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
############################
|
||||
|
@ -78,7 +84,7 @@ async def create_new_chat(form_data: ChatForm, user=Depends(get_current_user)):
|
|||
chat = Chats.insert_new_chat(user.id, form_data)
|
||||
return ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
|
||||
except Exception as e:
|
||||
print(e)
|
||||
log.exception(e)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()
|
||||
)
|
||||
|
@ -95,7 +101,7 @@ async def get_all_tags(user=Depends(get_current_user)):
|
|||
tags = Tags.get_tags_by_user_id(user.id)
|
||||
return tags
|
||||
except Exception as e:
|
||||
print(e)
|
||||
log.exception(e)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,6 +7,7 @@ from fastapi import APIRouter
|
|||
from pydantic import BaseModel
|
||||
import time
|
||||
import uuid
|
||||
import logging
|
||||
|
||||
from apps.web.models.users import UserModel, UserUpdateForm, UserRoleUpdateForm, Users
|
||||
from apps.web.models.auths import Auths
|
||||
|
@ -14,6 +15,11 @@ from apps.web.models.auths import Auths
|
|||
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"])
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
############################
|
||||
|
@ -83,7 +89,7 @@ async def update_user_by_id(
|
|||
|
||||
if form_data.password:
|
||||
hashed = get_password_hash(form_data.password)
|
||||
print(hashed)
|
||||
log.debug(f"hashed: {hashed}")
|
||||
Auths.update_user_password_by_id(user_id, hashed)
|
||||
|
||||
Auths.update_email_by_id(user_id, form_data.email.lower())
|
||||
|
|
|
@ -21,155 +21,6 @@ from constants import ERROR_MESSAGES
|
|||
router = APIRouter()
|
||||
|
||||
|
||||
class UploadBlobForm(BaseModel):
|
||||
filename: str
|
||||
|
||||
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def parse_huggingface_url(hf_url):
|
||||
try:
|
||||
# Parse the URL
|
||||
parsed_url = urlparse(hf_url)
|
||||
|
||||
# Get the path and split it into components
|
||||
path_components = parsed_url.path.split("/")
|
||||
|
||||
# Extract the desired output
|
||||
user_repo = "/".join(path_components[1:3])
|
||||
model_file = path_components[-1]
|
||||
|
||||
return model_file
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
async def download_file_stream(url, file_path, file_name, chunk_size=1024 * 1024):
|
||||
done = False
|
||||
|
||||
if os.path.exists(file_path):
|
||||
current_size = os.path.getsize(file_path)
|
||||
else:
|
||||
current_size = 0
|
||||
|
||||
headers = {"Range": f"bytes={current_size}-"} if current_size > 0 else {}
|
||||
|
||||
timeout = aiohttp.ClientTimeout(total=600) # Set the timeout
|
||||
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.get(url, headers=headers) as response:
|
||||
total_size = int(response.headers.get("content-length", 0)) + current_size
|
||||
|
||||
with open(file_path, "ab+") as file:
|
||||
async for data in response.content.iter_chunked(chunk_size):
|
||||
current_size += len(data)
|
||||
file.write(data)
|
||||
|
||||
done = current_size == total_size
|
||||
progress = round((current_size / total_size) * 100, 2)
|
||||
yield f'data: {{"progress": {progress}, "completed": {current_size}, "total": {total_size}}}\n\n'
|
||||
|
||||
if done:
|
||||
file.seek(0)
|
||||
hashed = calculate_sha256(file)
|
||||
file.seek(0)
|
||||
|
||||
url = f"{OLLAMA_BASE_URLS[0]}/blobs/sha256:{hashed}"
|
||||
response = requests.post(url, data=file)
|
||||
|
||||
if response.ok:
|
||||
res = {
|
||||
"done": done,
|
||||
"blob": f"sha256:{hashed}",
|
||||
"name": file_name,
|
||||
}
|
||||
os.remove(file_path)
|
||||
|
||||
yield f"data: {json.dumps(res)}\n\n"
|
||||
else:
|
||||
raise "Ollama: Could not create blob, Please try again."
|
||||
|
||||
|
||||
@router.get("/download")
|
||||
async def download(
|
||||
url: str,
|
||||
):
|
||||
# url = "https://huggingface.co/TheBloke/stablelm-zephyr-3b-GGUF/resolve/main/stablelm-zephyr-3b.Q2_K.gguf"
|
||||
file_name = parse_huggingface_url(url)
|
||||
|
||||
if file_name:
|
||||
file_path = f"{UPLOAD_DIR}/{file_name}"
|
||||
|
||||
return StreamingResponse(
|
||||
download_file_stream(url, file_path, file_name),
|
||||
media_type="text/event-stream",
|
||||
)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@router.post("/upload")
|
||||
def upload(file: UploadFile = File(...)):
|
||||
file_path = f"{UPLOAD_DIR}/{file.filename}"
|
||||
|
||||
# Save file in chunks
|
||||
with open(file_path, "wb+") as f:
|
||||
for chunk in file.file:
|
||||
f.write(chunk)
|
||||
|
||||
def file_process_stream():
|
||||
total_size = os.path.getsize(file_path)
|
||||
chunk_size = 1024 * 1024
|
||||
try:
|
||||
with open(file_path, "rb") as f:
|
||||
total = 0
|
||||
done = False
|
||||
|
||||
while not done:
|
||||
chunk = f.read(chunk_size)
|
||||
if not chunk:
|
||||
done = True
|
||||
continue
|
||||
|
||||
total += len(chunk)
|
||||
progress = round((total / total_size) * 100, 2)
|
||||
|
||||
res = {
|
||||
"progress": progress,
|
||||
"total": total_size,
|
||||
"completed": total,
|
||||
}
|
||||
yield f"data: {json.dumps(res)}\n\n"
|
||||
|
||||
if done:
|
||||
f.seek(0)
|
||||
hashed = calculate_sha256(f)
|
||||
f.seek(0)
|
||||
|
||||
url = f"{OLLAMA_BASE_URLS[0]}/blobs/sha256:{hashed}"
|
||||
response = requests.post(url, data=f)
|
||||
|
||||
if response.ok:
|
||||
res = {
|
||||
"done": done,
|
||||
"blob": f"sha256:{hashed}",
|
||||
"name": file.filename,
|
||||
}
|
||||
os.remove(file_path)
|
||||
yield f"data: {json.dumps(res)}\n\n"
|
||||
else:
|
||||
raise Exception(
|
||||
"Ollama: Could not create blob, Please try again."
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
res = {"error": str(e)}
|
||||
yield f"data: {json.dumps(res)}\n\n"
|
||||
|
||||
return StreamingResponse(file_process_stream(), media_type="text/event-stream")
|
||||
|
||||
|
||||
@router.get("/gravatar")
|
||||
async def get_gravatar(
|
||||
email: str,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue