This commit is contained in:
Timothy J. Baek 2024-08-27 17:05:24 +02:00
parent 628310b12b
commit 6a21a77ee9
6 changed files with 107 additions and 36 deletions

View File

@ -434,6 +434,11 @@ async def get_rag_config(user=Depends(get_admin_user)):
}
class FileConfig(BaseModel):
max_size: Optional[int] = None
max_count: Optional[int] = None
class ContentExtractionConfig(BaseModel):
engine: str = ""
tika_server_url: Optional[str] = None
@ -472,6 +477,7 @@ class WebConfig(BaseModel):
class ConfigUpdateForm(BaseModel):
pdf_extract_images: Optional[bool] = None
file: Optional[FileConfig] = None
content_extraction: Optional[ContentExtractionConfig] = None
chunk: Optional[ChunkParamUpdateForm] = None
youtube: Optional[YoutubeLoaderConfig] = None
@ -486,6 +492,10 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
else app.state.config.PDF_EXTRACT_IMAGES
)
if form_data.file is not None:
app.state.config.FILE_MAX_SIZE = form_data.file.max_size
app.state.config.FILE_MAX_COUNT = form_data.file.max_count
if form_data.content_extraction is not None:
log.info(f"Updating text settings: {form_data.content_extraction}")
app.state.config.CONTENT_EXTRACTION_ENGINE = form_data.content_extraction.engine
@ -526,11 +536,11 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
return {
"status": True,
"pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
"file": {
"max_size": app.state.config.FILE_MAX_SIZE,
"max_count": app.state.config.FILE_MAX_COUNT,
},
"pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
"content_extraction": {
"engine": app.state.config.CONTENT_EXTRACTION_ENGINE,
"tika_server_url": app.state.config.TIKA_SERVER_URL,

View File

@ -1939,6 +1939,10 @@ async def get_app_config(request: Request):
"engine": audio_app.state.config.STT_ENGINE,
},
},
"file": {
"max_size": rag_app.state.config.FILE_MAX_SIZE,
"max_count": rag_app.state.config.FILE_MAX_COUNT,
},
"permissions": {**webui_app.state.config.USER_PERMISSIONS},
}
if user is not None

View File

@ -359,8 +359,11 @@
<Models />
{:else if selectedTab === 'documents'}
<Documents
saveHandler={() => {
on:save={async () => {
toast.success($i18n.t('Settings saved successfully!'));
await tick();
await config.set(await getBackendConfig());
}}
/>
{:else if selectedTab === 'web'}

View File

@ -1,4 +1,8 @@
<script lang="ts">
import { onMount, getContext, createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
import { getDocs } from '$lib/apis/documents';
import { deleteAllFiles, deleteFileById } from '$lib/apis/files';
import {
@ -18,14 +22,12 @@
import ResetVectorDBConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
import { documents, models } from '$lib/stores';
import { onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
export let saveHandler: Function;
let scanDirLoading = false;
let updateEmbeddingModelLoading = false;
let updateRerankingModelLoading = false;
@ -164,19 +166,22 @@
};
const submitHandler = async () => {
embeddingModelUpdateHandler();
await embeddingModelUpdateHandler();
if (querySettings.hybrid) {
rerankingModelUpdateHandler();
await rerankingModelUpdateHandler();
}
if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
toast.error($i18n.t('Tika Server URL required.'));
return;
}
const res = await updateRAGConfig(localStorage.token, {
pdf_extract_images: pdfExtractImages,
file: {
max_size: fileMaxSize === '' ? null : fileMaxSize,
max_count: fileMaxCount === '' ? null : fileMaxCount
},
chunk: {
chunk_overlap: chunkOverlap,
chunk_size: chunkSize
@ -188,6 +193,8 @@
});
await updateQuerySettings(localStorage.token, querySettings);
dispatch('save');
};
const setEmbeddingConfig = async () => {
@ -233,8 +240,8 @@
tikaServerUrl = res.content_extraction.tika_server_url;
showTikaServerUrl = contentExtractionEngine === 'tika';
fileMaxSize = res.file.max_size;
fileMaxCount = res.file.max_count;
fileMaxSize = res?.file.max_size ?? '';
fileMaxCount = res?.file.max_count ?? '';
}
});
</script>
@ -271,7 +278,6 @@
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={() => {
submitHandler();
saveHandler();
}}
>
<div class=" space-y-2.5 overflow-y-scroll scrollbar-hidden h-full pr-1.5">
@ -622,36 +628,50 @@
<div class="text-sm font-medium">{$i18n.t('Files')}</div>
<div class=" my-2 flex gap-1.5">
<div class=" w-full justify-between">
<div class="self-center text-xs font-medium min-w-fit mb-1">
{$i18n.t('Max Upload Count')}
</div>
<div class="self-center">
<input
class=" w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Enter File Count')}
bind:value={fileMaxCount}
autocomplete="off"
min="0"
/>
</div>
</div>
<div class="w-full">
<div class=" self-center text-xs font-medium min-w-fit mb-1">
{$i18n.t('Max Upload Size')}
</div>
<div class="self-center">
<input
class="w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Enter File Size (MB)')}
bind:value={fileMaxSize}
autocomplete="off"
min="0"
/>
<Tooltip
content={$i18n.t(
'The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.'
)}
placement="top-start"
>
<input
class="w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Leave empty for unlimited')}
bind:value={fileMaxSize}
autocomplete="off"
min="0"
/>
</Tooltip>
</div>
</div>
<div class=" w-full">
<div class="self-center text-xs font-medium min-w-fit mb-1">
{$i18n.t('Max Upload Count')}
</div>
<div class="self-center">
<Tooltip
content={$i18n.t(
'The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.'
)}
placement="top-start"
>
<input
class=" w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
type="number"
placeholder={$i18n.t('Leave empty for unlimited')}
bind:value={fileMaxCount}
autocomplete="off"
min="0"
/>
</Tooltip>
</div>
</div>
</div>

View File

@ -542,6 +542,27 @@
`Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.`
)
);
} else if (
($config?.file?.max_count ?? null) !== null &&
files.length + chatFiles.length > $config?.file?.max_count
) {
console.log(chatFiles.length, files.length);
toast.error(
$i18n.t(`You can only chat with a maximum of {{maxCount}} file(s) at a time.`, {
maxCount: $config?.file?.max_count
})
);
} else if (
($config?.file?.max_size ?? null) !== null &&
[...files, ...chatFiles].some(
(file) => file.size > ($config?.file?.max_size ?? 0) * 1024 * 1024
)
) {
toast.error(
$i18n.t(`File size should not exceed {{maxSize}} MB.`, {
maxSize: $config?.file?.max_size
})
);
} else {
// Reset chat input textarea
const chatTextAreaElement = document.getElementById('chat-textarea');

View File

@ -173,6 +173,20 @@
const inputFilesHandler = async (inputFiles) => {
inputFiles.forEach((file) => {
console.log(file, file.name.split('.').at(-1));
if (
($config?.file?.max_size ?? null) !== null &&
file.size > ($config?.file?.max_size ?? 0) * 1024 * 1024
) {
toast.error(
$i18n.t(`File size should not exceed {{maxSize}} MB.`, {
maxSize: $config?.file?.max_size
})
);
return;
}
if (['image/gif', 'image/webp', 'image/jpeg', 'image/png'].includes(file['type'])) {
if (visionCapableModels.length === 0) {
toast.error($i18n.t('Selected model(s) do not support image inputs'));
@ -222,7 +236,6 @@
if (e.dataTransfer?.files) {
const inputFiles = Array.from(e.dataTransfer?.files);
console.log(file, file.name.split('.').at(-1));
if (inputFiles && inputFiles.length > 0) {
console.log(inputFiles);
inputFilesHandler(inputFiles);