Merge branch 'dev' into feat/customizable-title-prompt-length

This commit is contained in:
Timothy Jaeryang Baek 2024-04-14 14:02:53 -07:00 committed by GitHub
commit a938ffb586
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 187 additions and 43 deletions

View file

@ -28,6 +28,7 @@ from config import (
UPLOAD_DIR,
WHISPER_MODEL,
WHISPER_MODEL_DIR,
WHISPER_MODEL_AUTO_UPDATE,
DEVICE_TYPE,
)
@ -69,12 +70,24 @@ def transcribe(
f.write(contents)
f.close()
model = WhisperModel(
WHISPER_MODEL,
device=whisper_device_type,
compute_type="int8",
download_root=WHISPER_MODEL_DIR,
)
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(

View file

@ -29,7 +29,13 @@ import base64
import json
import logging
from config import SRC_LOG_LEVELS, CACHE_DIR, AUTOMATIC1111_BASE_URL, COMFYUI_BASE_URL
from config import (
SRC_LOG_LEVELS,
CACHE_DIR,
ENABLE_IMAGE_GENERATION,
AUTOMATIC1111_BASE_URL,
COMFYUI_BASE_URL,
)
log = logging.getLogger(__name__)
@ -48,7 +54,7 @@ app.add_middleware(
)
app.state.ENGINE = ""
app.state.ENABLED = False
app.state.ENABLED = ENABLE_IMAGE_GENERATION
app.state.OPENAI_API_KEY = ""
app.state.MODEL = ""

View file

@ -612,8 +612,13 @@ async def generate_embeddings(
user=Depends(get_current_user),
):
if url_idx == None:
if form_data.model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[form_data.model]["urls"])
model = form_data.model
if ":" not in model:
model = f"{model}:latest"
if model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[model]["urls"])
else:
raise HTTPException(
status_code=400,
@ -672,8 +677,13 @@ async def generate_completion(
):
if url_idx == None:
if form_data.model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[form_data.model]["urls"])
model = form_data.model
if ":" not in model:
model = f"{model}:latest"
if model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[model]["urls"])
else:
raise HTTPException(
status_code=400,
@ -770,8 +780,13 @@ async def generate_chat_completion(
):
if url_idx == None:
if form_data.model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[form_data.model]["urls"])
model = form_data.model
if ":" not in model:
model = f"{model}:latest"
if model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[model]["urls"])
else:
raise HTTPException(
status_code=400,
@ -874,8 +889,13 @@ async def generate_openai_chat_completion(
):
if url_idx == None:
if form_data.model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[form_data.model]["urls"])
model = form_data.model
if ":" not in model:
model = f"{model}:latest"
if model in app.state.MODELS:
url_idx = random.choice(app.state.MODELS[model]["urls"])
else:
raise HTTPException(
status_code=400,

View file

@ -413,7 +413,7 @@ RAG_EMBEDDING_MODEL_AUTO_UPDATE = (
)
# device type embbeding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
# 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":
@ -450,11 +450,17 @@ Query: [query]"""
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
####################################
ENABLE_IMAGE_GENERATION = (
os.environ.get("ENABLE_IMAGE_GENERATION", "").lower() == "true"
)
AUTOMATIC1111_BASE_URL = os.getenv("AUTOMATIC1111_BASE_URL", "")
COMFYUI_BASE_URL = os.getenv("COMFYUI_BASE_URL", "")

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="manifest" href="%sveltekit.assets%/manifest.json" />
<link rel="manifest" href="%sveltekit.assets%/manifest.json" crossorigin="use-credentials" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<meta name="robots" content="noindex,nofollow" />
<script>

View file

@ -18,6 +18,7 @@
import { synthesizeOpenAISpeech } from '$lib/apis/openai';
import { imageGenerations } from '$lib/apis/images';
import {
approximateToHumanReadable,
extractSentences,
revertSanitizedResponseContent,
sanitizeResponseContent
@ -122,7 +123,10 @@
eval_count: ${message.info.eval_count ?? 'N/A'}<br/>
eval_duration: ${
Math.round(((message.info.eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms</span>`,
}ms<br/>
approximate_total: ${approximateToHumanReadable(
message.info.total_duration
)}</span>`,
allowHTML: true
});
}

View file

@ -33,7 +33,7 @@
: items;
const pullModelHandler = async () => {
const sanitizedModelTag = searchValue.trim();
const sanitizedModelTag = searchValue.trim().replace(/^ollama\s+(run|pull)\s+/, '');
console.log($MODEL_DOWNLOAD_POOL);
if ($MODEL_DOWNLOAD_POOL[sanitizedModelTag]) {

View file

@ -139,7 +139,7 @@
};
const pullModelHandler = async () => {
const sanitizedModelTag = modelTag.trim();
const sanitizedModelTag = modelTag.trim().replace(/^ollama\s+(run|pull)\s+/, '');
if (modelDownloadStatus[sanitizedModelTag]) {
toast.error(
$i18n.t(`Model '{{modelTag}}' is already in queue for downloading.`, {

View file

@ -0,0 +1,42 @@
<script lang="ts">
import { Pagination } from 'bits-ui';
import { createEventDispatcher } from 'svelte';
import ChevronLeft from '../icons/ChevronLeft.svelte';
import ChevronRight from '../icons/ChevronRight.svelte';
export let page = 0;
export let count = 0;
export let perPage = 20;
</script>
<div class="flex justify-center">
<Pagination.Root bind:page {count} {perPage} let:pages>
<div class="my-2 flex items-center">
<Pagination.PrevButton
class="mr-[25px] inline-flex size-8 items-center justify-center rounded-[9px] bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 active:scale-98 disabled:cursor-not-allowed disabled:text-gray-400 dark:disabled:text-gray-700 hover:disabled:bg-transparent dark:hover:disabled:bg-transparent"
>
<ChevronLeft className="size-4" strokeWidth="2" />
</Pagination.PrevButton>
<div class="flex items-center gap-2.5">
{#each pages as page (page.key)}
{#if page.type === 'ellipsis'}
<div class="text-sm font-medium text-foreground-alt">...</div>
{:else}
<Pagination.Page
{page}
class="inline-flex size-8 items-center justify-center rounded-[9px] bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 text-sm font-medium hover:bg-dark-10 active:scale-98 disabled:cursor-not-allowed disabled:opacity-50 hover:disabled:bg-transparent data-[selected]:bg-black data-[selected]:text-gray-100 data-[selected]:hover:bg-black dark:data-[selected]:bg-white dark:data-[selected]:text-gray-900 dark:data-[selected]:hover:bg-white"
>
{page.value}
</Pagination.Page>
{/if}
{/each}
</div>
<Pagination.NextButton
class="ml-[25px] inline-flex size-8 items-center justify-center rounded-[9px] bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 active:scale-98 disabled:cursor-not-allowed disabled:text-gray-400 dark:disabled:text-gray-700 hover:disabled:bg-transparent dark:hover:disabled:bg-transparent"
>
<ChevronRight className="size-4" strokeWidth="2" />
</Pagination.NextButton>
</div>
</Pagination.Root>
</div>

View file

@ -0,0 +1,15 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</script>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />
</svg>

View file

@ -0,0 +1,15 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</script>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
</svg>

View file

@ -26,14 +26,14 @@
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[130px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow"
class="w-full max-w-[150px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-900 dark:text-white shadow"
sideOffset={-2}
side="bottom"
align="start"
transition={flyAndScale}
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer"
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer dark:hover:bg-gray-850 rounded-md"
on:click={() => {
renameHandler();
}}
@ -43,7 +43,7 @@
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer"
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer dark:hover:bg-gray-850 rounded-md"
on:click={() => {
deleteHandler();
}}

View file

@ -55,9 +55,9 @@
"Check for updates": "Kiểm tra cập nhật",
"Checking for updates...": "Đang kiểm tra cập nhật...",
"Choose a model before saving...": "Chọn mô hình trước khi lưu...",
"Chunk Overlap": "Kích thước chồng lấn (overlap)",
"Chunk Overlap": "Chồng lấn (overlap)",
"Chunk Params": "Cài đặt số lượng ký tự cho khối ký tự (chunk)",
"Chunk Size": "Kích thc khối (size)",
"Chunk Size": "Kích thước khối (size)",
"Click here for help.": "Bấm vào đây để được trợ giúp.",
"Click here to check other modelfiles.": "Bấm vào đây để kiểm tra các tệp mô tả mô hình (modelfiles) khác.",
"Click here to select": "Bấm vào đây để chọn",
@ -65,7 +65,7 @@
"click here.": "bấm vào đây.",
"Click on the user role button to change a user's role.": "Bấm vào nút trong cột VAI TRÒ để thay đổi quyền của người sử dụng.",
"Close": "Đóng",
"Collection": "Bộ sưu tập",
"Collection": "Tổng hợp mọi tài liệu",
"Command": "Lệnh",
"Confirm Password": "Xác nhận Mật khẩu",
"Connections": "Kết nối",
@ -76,7 +76,7 @@
"Copy last response": "Sao chép phản hồi cuối cùng",
"Copying to clipboard was successful!": "Sao chép vào clipboard thành công!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Tạo một cụm từ súc tích, 3-5 từ làm tiêu đề cho truy vấn sau, tuân thủ nghiêm ngặt giới hạn 3-5 từ và tránh sử dụng từ 'tiêu đề':",
"Create a modelfile": "Tạo tệp mô tả mô hình",
"Create a modelfile": "Tạo tệp mô tả cho mô hình",
"Create Account": "Tạo Tài khoản",
"Created at": "Được tạo vào lúc",
"Created by": "Được tạo bởi",
@ -347,7 +347,7 @@
"Valid time units:": "Đơn vị thời gian hợp lệ:",
"variable": "biến",
"variable to have them replaced with clipboard content.": "biến để có chúng được thay thế bằng nội dung clipboard.",
"Version": "Phiên bản",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "Tiện ích WebUI",
"WebUI Settings": "Cài đặt WebUI",

View file

@ -493,4 +493,25 @@ export const templatePrompt = (template: string, prompt: string) => {
}
return template;
export const approximateToHumanReadable = (nanoseconds: number) => {
const seconds = Math.floor((nanoseconds / 1e9) % 60);
const minutes = Math.floor((nanoseconds / 6e10) % 60);
const hours = Math.floor((nanoseconds / 3.6e12) % 24);
const results: string[] = [];
if (seconds >= 0) {
results.push(`${seconds}s`);
}
if (minutes > 0) {
results.push(`${minutes}m`);
}
if (hours > 0) {
results.push(`${hours}h`);
}
return results.reverse().join(' ');
};

View file

@ -106,11 +106,6 @@
// IndexedDB Not Found
}
console.log();
await models.set(await getModels());
await tick();
await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
await modelfiles.set(await getModelfiles(localStorage.token));

View file

@ -12,6 +12,7 @@
import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
import EditUserModal from '$lib/components/admin/EditUserModal.svelte';
import SettingsModal from '$lib/components/admin/SettingsModal.svelte';
import Pagination from '$lib/components/common/Pagination.svelte';
const i18n = getContext('i18n');
@ -21,6 +22,8 @@
let search = '';
let selectedUser = null;
let page = 1;
let showSettingsModal = false;
let showEditUserModal = false;
@ -159,15 +162,17 @@
</tr>
</thead>
<tbody>
{#each users.filter((user) => {
if (search === '') {
return true;
} else {
let name = user.name.toLowerCase();
const query = search.toLowerCase();
return name.includes(query);
}
}) as user}
{#each users
.filter((user) => {
if (search === '') {
return true;
} else {
let name = user.name.toLowerCase();
const query = search.toLowerCase();
return name.includes(query);
}
})
.slice((page - 1) * 20, page * 20) as user}
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700 text-xs">
<td class="px-3 py-2 min-w-[7rem] w-28">
<button
@ -270,6 +275,8 @@
<div class=" text-gray-500 text-xs mt-2 text-right">
{$i18n.t("Click on the user role button to change a user's role.")}
</div>
<Pagination bind:page count={users.length} />
</div>
</div>
</div>