Browse Source

feat: global image compression

Timothy Jaeryang Baek 1 week ago
parent
commit
6c54ca552a

+ 28 - 1
backend/open_webui/config.py

@@ -2107,6 +2107,27 @@ RAG_FILE_MAX_SIZE = PersistentConfig(
     ),
     ),
 )
 )
 
 
+FILE_IMAGE_COMPRESSION_WIDTH = PersistentConfig(
+    "FILE_IMAGE_COMPRESSION_WIDTH",
+    "file.image_compression_width",
+    (
+        int(os.environ.get("FILE_IMAGE_COMPRESSION_WIDTH"))
+        if os.environ.get("FILE_IMAGE_COMPRESSION_WIDTH")
+        else None
+    ),
+)
+
+FILE_IMAGE_COMPRESSION_HEIGHT = PersistentConfig(
+    "FILE_IMAGE_COMPRESSION_HEIGHT",
+    "file.image_compression_height",
+    (
+        int(os.environ.get("FILE_IMAGE_COMPRESSION_HEIGHT"))
+        if os.environ.get("FILE_IMAGE_COMPRESSION_HEIGHT")
+        else None
+    ),
+)
+
+
 RAG_ALLOWED_FILE_EXTENSIONS = PersistentConfig(
 RAG_ALLOWED_FILE_EXTENSIONS = PersistentConfig(
     "RAG_ALLOWED_FILE_EXTENSIONS",
     "RAG_ALLOWED_FILE_EXTENSIONS",
     "rag.file.allowed_extensions",
     "rag.file.allowed_extensions",
@@ -2909,7 +2930,13 @@ AUDIO_STT_MODEL = PersistentConfig(
 AUDIO_STT_SUPPORTED_CONTENT_TYPES = PersistentConfig(
 AUDIO_STT_SUPPORTED_CONTENT_TYPES = PersistentConfig(
     "AUDIO_STT_SUPPORTED_CONTENT_TYPES",
     "AUDIO_STT_SUPPORTED_CONTENT_TYPES",
     "audio.stt.supported_content_types",
     "audio.stt.supported_content_types",
-    os.getenv("AUDIO_STT_SUPPORTED_CONTENT_TYPES", "").split(","),
+    [
+        content_type.strip()
+        for content_type in os.environ.get(
+            "AUDIO_STT_SUPPORTED_CONTENT_TYPES", ""
+        ).split(",")
+        if content_type.strip()
+    ],
 )
 )
 
 
 AUDIO_STT_AZURE_API_KEY = PersistentConfig(
 AUDIO_STT_AZURE_API_KEY = PersistentConfig(

+ 10 - 0
backend/open_webui/main.py

@@ -211,6 +211,8 @@ from open_webui.config import (
     RAG_ALLOWED_FILE_EXTENSIONS,
     RAG_ALLOWED_FILE_EXTENSIONS,
     RAG_FILE_MAX_COUNT,
     RAG_FILE_MAX_COUNT,
     RAG_FILE_MAX_SIZE,
     RAG_FILE_MAX_SIZE,
+    FILE_IMAGE_COMPRESSION_WIDTH,
+    FILE_IMAGE_COMPRESSION_HEIGHT,
     RAG_OPENAI_API_BASE_URL,
     RAG_OPENAI_API_BASE_URL,
     RAG_OPENAI_API_KEY,
     RAG_OPENAI_API_KEY,
     RAG_AZURE_OPENAI_BASE_URL,
     RAG_AZURE_OPENAI_BASE_URL,
@@ -713,9 +715,13 @@ app.state.config.TOP_K = RAG_TOP_K
 app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER
 app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER
 app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD
 app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD
 app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT
 app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT
+
+
 app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS
 app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS
 app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE
 app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE
 app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
 app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
+app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = FILE_IMAGE_COMPRESSION_WIDTH
+app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = FILE_IMAGE_COMPRESSION_HEIGHT
 
 
 
 
 app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
 app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
@@ -1558,6 +1564,10 @@ async def get_app_config(request: Request):
                 "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,
+                    "image_compression": {
+                        "width": app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
+                        "height": app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
+                    },
                 },
                 },
                 "permissions": {**app.state.config.USER_PERMISSIONS},
                 "permissions": {**app.state.config.USER_PERMISSIONS},
                 "google_drive": {
                 "google_drive": {

+ 12 - 8
backend/open_webui/routers/retrieval.py

@@ -432,6 +432,8 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
         # File upload settings
         # File upload settings
         "FILE_MAX_SIZE": request.app.state.config.FILE_MAX_SIZE,
         "FILE_MAX_SIZE": request.app.state.config.FILE_MAX_SIZE,
         "FILE_MAX_COUNT": request.app.state.config.FILE_MAX_COUNT,
         "FILE_MAX_COUNT": request.app.state.config.FILE_MAX_COUNT,
+        "FILE_IMAGE_COMPRESSION_WIDTH": request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
+        "FILE_IMAGE_COMPRESSION_HEIGHT": request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
         "ALLOWED_FILE_EXTENSIONS": request.app.state.config.ALLOWED_FILE_EXTENSIONS,
         "ALLOWED_FILE_EXTENSIONS": request.app.state.config.ALLOWED_FILE_EXTENSIONS,
         # Integration settings
         # Integration settings
         "ENABLE_GOOGLE_DRIVE_INTEGRATION": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
         "ENABLE_GOOGLE_DRIVE_INTEGRATION": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
@@ -599,6 +601,8 @@ class ConfigForm(BaseModel):
     # File upload settings
     # File upload settings
     FILE_MAX_SIZE: Optional[int] = None
     FILE_MAX_SIZE: Optional[int] = None
     FILE_MAX_COUNT: Optional[int] = None
     FILE_MAX_COUNT: Optional[int] = None
+    FILE_IMAGE_COMPRESSION_WIDTH: Optional[int] = None
+    FILE_IMAGE_COMPRESSION_HEIGHT: Optional[int] = None
     ALLOWED_FILE_EXTENSIONS: Optional[List[str]] = None
     ALLOWED_FILE_EXTENSIONS: Optional[List[str]] = None
 
 
     # Integration settings
     # Integration settings
@@ -847,15 +851,13 @@ async def update_rag_config(
     )
     )
 
 
     # File upload settings
     # File upload settings
-    request.app.state.config.FILE_MAX_SIZE = (
-        form_data.FILE_MAX_SIZE
-        if form_data.FILE_MAX_SIZE is not None
-        else request.app.state.config.FILE_MAX_SIZE
+    request.app.state.config.FILE_MAX_SIZE = form_data.FILE_MAX_SIZE
+    request.app.state.config.FILE_MAX_COUNT = form_data.FILE_MAX_COUNT
+    request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = (
+        form_data.FILE_IMAGE_COMPRESSION_WIDTH
     )
     )
-    request.app.state.config.FILE_MAX_COUNT = (
-        form_data.FILE_MAX_COUNT
-        if form_data.FILE_MAX_COUNT is not None
-        else request.app.state.config.FILE_MAX_COUNT
+    request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = (
+        form_data.FILE_IMAGE_COMPRESSION_HEIGHT
     )
     )
     request.app.state.config.ALLOWED_FILE_EXTENSIONS = (
     request.app.state.config.ALLOWED_FILE_EXTENSIONS = (
         form_data.ALLOWED_FILE_EXTENSIONS
         form_data.ALLOWED_FILE_EXTENSIONS
@@ -1025,6 +1027,8 @@ async def update_rag_config(
         # File upload settings
         # File upload settings
         "FILE_MAX_SIZE": request.app.state.config.FILE_MAX_SIZE,
         "FILE_MAX_SIZE": request.app.state.config.FILE_MAX_SIZE,
         "FILE_MAX_COUNT": request.app.state.config.FILE_MAX_COUNT,
         "FILE_MAX_COUNT": request.app.state.config.FILE_MAX_COUNT,
+        "FILE_IMAGE_COMPRESSION_WIDTH": request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
+        "FILE_IMAGE_COMPRESSION_HEIGHT": request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
         "ALLOWED_FILE_EXTENSIONS": request.app.state.config.ALLOWED_FILE_EXTENSIONS,
         "ALLOWED_FILE_EXTENSIONS": request.app.state.config.ALLOWED_FILE_EXTENSIONS,
         # Integration settings
         # Integration settings
         "ENABLE_GOOGLE_DRIVE_INTEGRATION": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
         "ENABLE_GOOGLE_DRIVE_INTEGRATION": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,

+ 44 - 0
src/lib/components/admin/Settings/Documents.svelte

@@ -1144,6 +1144,50 @@
 							</Tooltip>
 							</Tooltip>
 						</div>
 						</div>
 					</div>
 					</div>
+
+					<div class="  mb-2.5 flex w-full justify-between">
+						<div class=" self-center text-xs font-medium">{$i18n.t('Image Compression Width')}</div>
+						<div class="flex items-center relative">
+							<Tooltip
+								content={$i18n.t(
+									'The width in pixels to compress images to. Leave empty for no compression.'
+								)}
+								placement="top-start"
+							>
+								<input
+									class="flex-1 w-full text-sm bg-transparent outline-hidden"
+									type="number"
+									placeholder={$i18n.t('Leave empty for no compression')}
+									bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_WIDTH}
+									autocomplete="off"
+									min="0"
+								/>
+							</Tooltip>
+						</div>
+					</div>
+
+					<div class="  mb-2.5 flex w-full justify-between">
+						<div class=" self-center text-xs font-medium">
+							{$i18n.t('Image Compression Height')}
+						</div>
+						<div class="flex items-center relative">
+							<Tooltip
+								content={$i18n.t(
+									'The height in pixels to compress images to. Leave empty for no compression.'
+								)}
+								placement="top-start"
+							>
+								<input
+									class="flex-1 w-full text-sm bg-transparent outline-hidden"
+									type="number"
+									placeholder={$i18n.t('Leave empty for no compression')}
+									bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_HEIGHT}
+									autocomplete="off"
+									min="0"
+								/>
+							</Tooltip>
+						</div>
+					</div>
 				</div>
 				</div>
 
 
 				<div class="mb-3">
 				<div class="mb-3">

+ 24 - 3
src/lib/components/channel/MessageInput.svelte

@@ -110,9 +110,30 @@
 				reader.onload = async (event) => {
 				reader.onload = async (event) => {
 					let imageUrl = event.target.result;
 					let imageUrl = event.target.result;
 
 
-					if ($settings?.imageCompression ?? false) {
-						const width = $settings?.imageCompressionSize?.width ?? null;
-						const height = $settings?.imageCompressionSize?.height ?? null;
+					if (
+						($settings?.imageCompression ?? false) ||
+						($config?.file?.image_compression?.width ?? null) ||
+						($config?.file?.image_compression?.height ?? null)
+					) {
+						let width = null;
+						let height = null;
+
+						if ($settings?.imageCompression ?? false) {
+							width = $settings?.imageCompressionSize?.width ?? null;
+							height = $settings?.imageCompressionSize?.height ?? null;
+						}
+
+						if (
+							($config?.file?.image_compression?.width ?? null) ||
+							($config?.file?.image_compression?.height ?? null)
+						) {
+							if (width > ($config?.file?.image_compression?.width ?? null)) {
+								width = $config?.file?.image_compression?.width ?? null;
+							}
+							if (height > ($config?.file?.image_compression?.height ?? null)) {
+								height = $config?.file?.image_compression?.height ?? null;
+							}
+						}
 
 
 						if (width || height) {
 						if (width || height) {
 							imageUrl = await compressImage(imageUrl, width, height);
 							imageUrl = await compressImage(imageUrl, width, height);

+ 24 - 3
src/lib/components/chat/MessageInput.svelte

@@ -355,9 +355,30 @@
 				reader.onload = async (event) => {
 				reader.onload = async (event) => {
 					let imageUrl = event.target.result;
 					let imageUrl = event.target.result;
 
 
-					if ($settings?.imageCompression ?? false) {
-						const width = $settings?.imageCompressionSize?.width ?? null;
-						const height = $settings?.imageCompressionSize?.height ?? null;
+					if (
+						($settings?.imageCompression ?? false) ||
+						($config?.file?.image_compression?.width ?? null) ||
+						($config?.file?.image_compression?.height ?? null)
+					) {
+						let width = null;
+						let height = null;
+
+						if ($settings?.imageCompression ?? false) {
+							width = $settings?.imageCompressionSize?.width ?? null;
+							height = $settings?.imageCompressionSize?.height ?? null;
+						}
+
+						if (
+							($config?.file?.image_compression?.width ?? null) ||
+							($config?.file?.image_compression?.height ?? null)
+						) {
+							if (width > ($config?.file?.image_compression?.width ?? null)) {
+								width = $config?.file?.image_compression?.width ?? null;
+							}
+							if (height > ($config?.file?.image_compression?.height ?? null)) {
+								height = $config?.file?.image_compression?.height ?? null;
+							}
+						}
 
 
 						if (width || height) {
 						if (width || height) {
 							imageUrl = await compressImage(imageUrl, width, height);
 							imageUrl = await compressImage(imageUrl, width, height);