refac
Some checks failed
Deploy to HuggingFace Spaces / check-secret (push) Has been cancelled
Frontend Build / Frontend Unit Tests (push) Has been cancelled
Create and publish Docker images with specific build args / build-main-image (linux/amd64, ubuntu-latest) (push) Has been cancelled
Create and publish Docker images with specific build args / build-main-image (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Create and publish Docker images with specific build args / build-cuda-image (linux/amd64, ubuntu-latest) (push) Has been cancelled
Create and publish Docker images with specific build args / build-cuda-image (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Create and publish Docker images with specific build args / build-cuda126-image (linux/amd64, ubuntu-latest) (push) Has been cancelled
Create and publish Docker images with specific build args / build-cuda126-image (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Create and publish Docker images with specific build args / build-ollama-image (linux/amd64, ubuntu-latest) (push) Has been cancelled
Create and publish Docker images with specific build args / build-ollama-image (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Create and publish Docker images with specific build args / build-slim-image (linux/amd64, ubuntu-latest) (push) Has been cancelled
Create and publish Docker images with specific build args / build-slim-image (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Python CI / Format Backend (push) Has been cancelled
Frontend Build / Format & Build Frontend (push) Has been cancelled
Deploy to HuggingFace Spaces / deploy (push) Has been cancelled
Create and publish Docker images with specific build args / merge-main-images (push) Has been cancelled
Create and publish Docker images with specific build args / merge-cuda-images (push) Has been cancelled
Create and publish Docker images with specific build args / merge-cuda126-images (push) Has been cancelled
Create and publish Docker images with specific build args / merge-ollama-images (push) Has been cancelled
Create and publish Docker images with specific build args / merge-slim-images (push) Has been cancelled

This commit is contained in:
Timothy Jaeryang Baek 2025-12-20 18:12:03 +04:00
parent 4c2e5c93e9
commit fe653a1336
3 changed files with 160 additions and 164 deletions

View file

@ -331,13 +331,21 @@ class Loader:
elif self.engine == "mineru" and file_ext in [
"pdf"
]: # MinerU currently only supports PDF
mineru_timeout = self.kwargs.get("MINERU_API_TIMEOUT", 300)
if mineru_timeout:
try:
mineru_timeout = int(mineru_timeout)
except ValueError:
mineru_timeout = 300
loader = MinerULoader(
file_path=file_path,
api_mode=self.kwargs.get("MINERU_API_MODE", "local"),
api_url=self.kwargs.get("MINERU_API_URL", "http://localhost:8000"),
api_key=self.kwargs.get("MINERU_API_KEY", ""),
params=self.kwargs.get("MINERU_PARAMS", {}),
timeout=int(self.kwargs.get("MINERU_API_TIMEOUT", 300)),
timeout=mineru_timeout,
)
elif (
self.engine == "mistral_ocr"

View file

@ -26,7 +26,7 @@ class MinerULoader:
api_url: str = "http://localhost:8000",
api_key: str = "",
params: dict = None,
timeout: int = 300,
timeout: Optional[int] = 300,
):
self.file_path = file_path
self.api_mode = api_mode.lower()
@ -103,7 +103,7 @@ class MinerULoader:
f"{self.api_url}/file_parse",
data=form_data,
files=files,
timeout=self.timeout, # 5 minute timeout for large documents
timeout=self.timeout,
)
response.raise_for_status()
@ -302,7 +302,7 @@ class MinerULoader:
response = requests.put(
upload_url,
data=f,
timeout=self.timeout, # 5 minute timeout for large files
timeout=self.timeout,
)
response.raise_for_status()
except FileNotFoundError:

View file

@ -1,9 +1,12 @@
<script lang="ts">
import * as XLSX from 'xlsx';
import { getContext, onMount, tick } from 'svelte';
import { formatFileSize, getLineCount } from '$lib/utils';
import { WEBUI_API_BASE_URL } from '$lib/constants';
import { getKnowledgeById } from '$lib/apis/knowledge';
import * as XLSX from 'xlsx';
import { getFileById } from '$lib/apis/files';
import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
import Markdown from '$lib/components/chat/Messages/Markdown.svelte';
@ -17,7 +20,6 @@
import Tooltip from './Tooltip.svelte';
import dayjs from 'dayjs';
import Spinner from './Spinner.svelte';
import { getFileById } from '$lib/apis/files';
export let item;
export let show = false;
@ -130,7 +132,6 @@
});
};
$: if (selectedSheet && excelWorkbook) {
renderExcelSheet();
}
@ -348,175 +349,162 @@
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{:else if isExcel}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{#if selectedTab === 'preview'}
{#if excelError}
<div class="text-red-500 text-sm p-4">
{excelError}
</div>
{:else}
{#if excelSheetNames.length > 1}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
{#each excelSheetNames as sheetName}
<button
class="min-w-fit py-1.5 px-4 border-b {selectedSheet === sheetName
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedSheet = sheetName;
}}>{sheetName}</button
>
{/each}
</div>
{/if}
{#if excelHtml}
<div class="excel-table-container overflow-auto max-h-[60vh]">
{@html excelHtml}
</div>
{:else}
<div class="text-gray-500 text-sm p-4">No content available</div>
{/if}
{/if}
{:else}
{:else if isExcel}
<div
class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap"
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
{(item?.file?.data?.content ?? '').trim() || 'No content'}
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{/if}
{:else}
{#if isAudio}
<audio
src={`${WEBUI_API_BASE_URL}/files/${item.id}/content`}
class="w-full border-0 rounded-lg mb-2"
controls
playsinline
/>
{/if}
{#if item?.file?.data}
{#if isMarkdown}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{#if selectedTab === 'preview'}
<div
class="max-h-[60vh] overflow-scroll scrollbar-hidden text-sm prose dark:prose-invert max-w-full"
>
<Markdown
content={item.file.data.content}
id="markdown-viewer"
/>
{#if selectedTab === 'preview'}
{#if excelError}
<div class="text-red-500 text-sm p-4">
{excelError}
</div>
{:else}
<div
class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap"
>
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{:else if isCode}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
{#if excelSheetNames.length > 1}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
{#each excelSheetNames as sheetName}
<button
class="min-w-fit py-1.5 px-4 border-b {selectedSheet === sheetName
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedSheet = sheetName;
}}>{sheetName}</button
>
{/each}
</div>
{/if}
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{#if selectedTab === 'preview'}
<div
class="max-h-[60vh] overflow-scroll scrollbar-hidden text-sm relative"
>
<CodeBlock
code={item.file.data.content}
lang={item.name.split('.').pop()}
token={null}
edit={false}
run={false}
save={false}
/>
</div>
{:else}
<div
class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap"
>
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{#if excelHtml}
<div class="excel-table-container overflow-auto max-h-[60vh]">
{@html excelHtml}
</div>
{:else}
<div class="text-gray-500 text-sm p-4">No content available</div>
{/if}
{/if}
{:else}
<div
class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap"
>
<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{/if}
{:else}
{#if isAudio}
<audio
src={`${WEBUI_API_BASE_URL}/files/${item.id}/content`}
class="w-full border-0 rounded-lg mb-2"
controls
playsinline
/>
{/if}
{#if item?.file?.data}
{#if isMarkdown}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{#if selectedTab === 'preview'}
<div
class="max-h-[60vh] overflow-scroll scrollbar-hidden text-sm prose dark:prose-invert max-w-full"
>
<Markdown content={item.file.data.content} id="markdown-viewer" />
</div>
{:else}
<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{:else if isCode}
<div
class="flex mb-2.5 scrollbar-none overflow-x-auto w-full border-b border-gray-50 dark:border-gray-850/30 text-center text-sm font-medium bg-transparent dark:text-gray-200"
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === ''
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = '';
}}>{$i18n.t('Content')}</button
>
<button
class="min-w-fit py-1.5 px-4 border-b {selectedTab === 'preview'
? ' '
: ' border-transparent text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
type="button"
on:click={() => {
selectedTab = 'preview';
}}>{$i18n.t('Preview')}</button
>
</div>
{#if selectedTab === 'preview'}
<div class="max-h-[60vh] overflow-scroll scrollbar-hidden text-sm relative">
<CodeBlock
code={item.file.data.content}
lang={item.name.split('.').pop()}
token={null}
edit={false}
run={false}
save={false}
/>
</div>
{:else}
<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{:else}
<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
{(item?.file?.data?.content ?? '').trim() || 'No content'}
</div>
{/if}
{/if}
{/if}
{:else}
<div class="flex items-center justify-center py-6">