mirror of
https://github.com/open-webui/open-webui
synced 2025-03-23 22:31:38 +00:00
refac
This commit is contained in:
parent
628310b12b
commit
6a21a77ee9
backend
src/lib/components
@ -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):
|
class ContentExtractionConfig(BaseModel):
|
||||||
engine: str = ""
|
engine: str = ""
|
||||||
tika_server_url: Optional[str] = None
|
tika_server_url: Optional[str] = None
|
||||||
@ -472,6 +477,7 @@ class WebConfig(BaseModel):
|
|||||||
|
|
||||||
class ConfigUpdateForm(BaseModel):
|
class ConfigUpdateForm(BaseModel):
|
||||||
pdf_extract_images: Optional[bool] = None
|
pdf_extract_images: Optional[bool] = None
|
||||||
|
file: Optional[FileConfig] = None
|
||||||
content_extraction: Optional[ContentExtractionConfig] = None
|
content_extraction: Optional[ContentExtractionConfig] = None
|
||||||
chunk: Optional[ChunkParamUpdateForm] = None
|
chunk: Optional[ChunkParamUpdateForm] = None
|
||||||
youtube: Optional[YoutubeLoaderConfig] = 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
|
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:
|
if form_data.content_extraction is not None:
|
||||||
log.info(f"Updating text settings: {form_data.content_extraction}")
|
log.info(f"Updating text settings: {form_data.content_extraction}")
|
||||||
app.state.config.CONTENT_EXTRACTION_ENGINE = form_data.content_extraction.engine
|
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 {
|
return {
|
||||||
"status": True,
|
"status": True,
|
||||||
|
"pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
|
||||||
"file": {
|
"file": {
|
||||||
"max_size": app.state.config.FILE_MAX_SIZE,
|
"max_size": app.state.config.FILE_MAX_SIZE,
|
||||||
"max_count": app.state.config.FILE_MAX_COUNT,
|
"max_count": app.state.config.FILE_MAX_COUNT,
|
||||||
},
|
},
|
||||||
"pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
|
|
||||||
"content_extraction": {
|
"content_extraction": {
|
||||||
"engine": app.state.config.CONTENT_EXTRACTION_ENGINE,
|
"engine": app.state.config.CONTENT_EXTRACTION_ENGINE,
|
||||||
"tika_server_url": app.state.config.TIKA_SERVER_URL,
|
"tika_server_url": app.state.config.TIKA_SERVER_URL,
|
||||||
|
@ -1939,6 +1939,10 @@ async def get_app_config(request: Request):
|
|||||||
"engine": audio_app.state.config.STT_ENGINE,
|
"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},
|
"permissions": {**webui_app.state.config.USER_PERMISSIONS},
|
||||||
}
|
}
|
||||||
if user is not None
|
if user is not None
|
||||||
|
@ -359,8 +359,11 @@
|
|||||||
<Models />
|
<Models />
|
||||||
{:else if selectedTab === 'documents'}
|
{:else if selectedTab === 'documents'}
|
||||||
<Documents
|
<Documents
|
||||||
saveHandler={() => {
|
on:save={async () => {
|
||||||
toast.success($i18n.t('Settings saved successfully!'));
|
toast.success($i18n.t('Settings saved successfully!'));
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
await config.set(await getBackendConfig());
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{:else if selectedTab === 'web'}
|
{:else if selectedTab === 'web'}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { onMount, getContext, createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
import { getDocs } from '$lib/apis/documents';
|
import { getDocs } from '$lib/apis/documents';
|
||||||
import { deleteAllFiles, deleteFileById } from '$lib/apis/files';
|
import { deleteAllFiles, deleteFileById } from '$lib/apis/files';
|
||||||
import {
|
import {
|
||||||
@ -18,14 +22,12 @@
|
|||||||
import ResetVectorDBConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
import ResetVectorDBConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||||
|
|
||||||
import { documents, models } from '$lib/stores';
|
import { documents, models } from '$lib/stores';
|
||||||
import { onMount, getContext } from 'svelte';
|
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||||
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
export let saveHandler: Function;
|
|
||||||
|
|
||||||
let scanDirLoading = false;
|
let scanDirLoading = false;
|
||||||
let updateEmbeddingModelLoading = false;
|
let updateEmbeddingModelLoading = false;
|
||||||
let updateRerankingModelLoading = false;
|
let updateRerankingModelLoading = false;
|
||||||
@ -164,19 +166,22 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
embeddingModelUpdateHandler();
|
await embeddingModelUpdateHandler();
|
||||||
|
|
||||||
if (querySettings.hybrid) {
|
if (querySettings.hybrid) {
|
||||||
rerankingModelUpdateHandler();
|
await rerankingModelUpdateHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
|
if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
|
||||||
toast.error($i18n.t('Tika Server URL required.'));
|
toast.error($i18n.t('Tika Server URL required.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await updateRAGConfig(localStorage.token, {
|
const res = await updateRAGConfig(localStorage.token, {
|
||||||
pdf_extract_images: pdfExtractImages,
|
pdf_extract_images: pdfExtractImages,
|
||||||
|
file: {
|
||||||
|
max_size: fileMaxSize === '' ? null : fileMaxSize,
|
||||||
|
max_count: fileMaxCount === '' ? null : fileMaxCount
|
||||||
|
},
|
||||||
chunk: {
|
chunk: {
|
||||||
chunk_overlap: chunkOverlap,
|
chunk_overlap: chunkOverlap,
|
||||||
chunk_size: chunkSize
|
chunk_size: chunkSize
|
||||||
@ -188,6 +193,8 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
await updateQuerySettings(localStorage.token, querySettings);
|
await updateQuerySettings(localStorage.token, querySettings);
|
||||||
|
|
||||||
|
dispatch('save');
|
||||||
};
|
};
|
||||||
|
|
||||||
const setEmbeddingConfig = async () => {
|
const setEmbeddingConfig = async () => {
|
||||||
@ -233,8 +240,8 @@
|
|||||||
tikaServerUrl = res.content_extraction.tika_server_url;
|
tikaServerUrl = res.content_extraction.tika_server_url;
|
||||||
showTikaServerUrl = contentExtractionEngine === 'tika';
|
showTikaServerUrl = contentExtractionEngine === 'tika';
|
||||||
|
|
||||||
fileMaxSize = res.file.max_size;
|
fileMaxSize = res?.file.max_size ?? '';
|
||||||
fileMaxCount = res.file.max_count;
|
fileMaxCount = res?.file.max_count ?? '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -271,7 +278,6 @@
|
|||||||
class="flex flex-col h-full justify-between space-y-3 text-sm"
|
class="flex flex-col h-full justify-between space-y-3 text-sm"
|
||||||
on:submit|preventDefault={() => {
|
on:submit|preventDefault={() => {
|
||||||
submitHandler();
|
submitHandler();
|
||||||
saveHandler();
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class=" space-y-2.5 overflow-y-scroll scrollbar-hidden h-full pr-1.5">
|
<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="text-sm font-medium">{$i18n.t('Files')}</div>
|
||||||
|
|
||||||
<div class=" my-2 flex gap-1.5">
|
<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="w-full">
|
||||||
<div class=" self-center text-xs font-medium min-w-fit mb-1">
|
<div class=" self-center text-xs font-medium min-w-fit mb-1">
|
||||||
{$i18n.t('Max Upload Size')}
|
{$i18n.t('Max Upload Size')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="self-center">
|
<div class="self-center">
|
||||||
|
<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
|
<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"
|
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"
|
type="number"
|
||||||
placeholder={$i18n.t('Enter File Size (MB)')}
|
placeholder={$i18n.t('Leave empty for unlimited')}
|
||||||
bind:value={fileMaxSize}
|
bind:value={fileMaxSize}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
min="0"
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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.`
|
`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 {
|
} else {
|
||||||
// Reset chat input textarea
|
// Reset chat input textarea
|
||||||
const chatTextAreaElement = document.getElementById('chat-textarea');
|
const chatTextAreaElement = document.getElementById('chat-textarea');
|
||||||
|
@ -173,6 +173,20 @@
|
|||||||
|
|
||||||
const inputFilesHandler = async (inputFiles) => {
|
const inputFilesHandler = async (inputFiles) => {
|
||||||
inputFiles.forEach((file) => {
|
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 (['image/gif', 'image/webp', 'image/jpeg', 'image/png'].includes(file['type'])) {
|
||||||
if (visionCapableModels.length === 0) {
|
if (visionCapableModels.length === 0) {
|
||||||
toast.error($i18n.t('Selected model(s) do not support image inputs'));
|
toast.error($i18n.t('Selected model(s) do not support image inputs'));
|
||||||
@ -222,7 +236,6 @@
|
|||||||
|
|
||||||
if (e.dataTransfer?.files) {
|
if (e.dataTransfer?.files) {
|
||||||
const inputFiles = Array.from(e.dataTransfer?.files);
|
const inputFiles = Array.from(e.dataTransfer?.files);
|
||||||
console.log(file, file.name.split('.').at(-1));
|
|
||||||
if (inputFiles && inputFiles.length > 0) {
|
if (inputFiles && inputFiles.length > 0) {
|
||||||
console.log(inputFiles);
|
console.log(inputFiles);
|
||||||
inputFilesHandler(inputFiles);
|
inputFilesHandler(inputFiles);
|
||||||
|
Loading…
Reference in New Issue
Block a user