enh/pref: convert markdown base64 images to urls
Some checks are pending
Deploy to HuggingFace Spaces / check-secret (push) Waiting to run
Deploy to HuggingFace Spaces / deploy (push) Blocked by required conditions
Create and publish Docker images with specific build args / build-main-image (linux/amd64, ubuntu-latest) (push) Waiting to run
Create and publish Docker images with specific build args / build-main-image (linux/arm64, ubuntu-24.04-arm) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/amd64, ubuntu-latest) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda-image (linux/arm64, ubuntu-24.04-arm) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda126-image (linux/amd64, ubuntu-latest) (push) Waiting to run
Create and publish Docker images with specific build args / build-cuda126-image (linux/arm64, ubuntu-24.04-arm) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/amd64, ubuntu-latest) (push) Waiting to run
Create and publish Docker images with specific build args / build-ollama-image (linux/arm64, ubuntu-24.04-arm) (push) Waiting to run
Create and publish Docker images with specific build args / build-slim-image (linux/amd64, ubuntu-latest) (push) Waiting to run
Create and publish Docker images with specific build args / build-slim-image (linux/arm64, ubuntu-24.04-arm) (push) Waiting to run
Create and publish Docker images with specific build args / merge-main-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-cuda-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-cuda126-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-ollama-images (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge-slim-images (push) Blocked by required conditions
Python CI / Format Backend (push) Waiting to run
Frontend Build / Frontend Unit Tests (push) Waiting to run
Frontend Build / Format & Build Frontend (push) Waiting to run

Co-Authored-By: Shirasawa <kaguyashirasawa@gmail.com>
This commit is contained in:
Timothy Jaeryang Baek 2025-11-20 04:00:02 -05:00
parent 17ac79920f
commit 4c28f19bdd
3 changed files with 30 additions and 2 deletions

View file

@ -544,6 +544,10 @@ else:
# CHAT # CHAT
#################################### ####################################
ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION = (
os.environ.get("REPLACE_IMAGE_URLS_IN_CHAT_RESPONSE", "False").lower() == "true"
)
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = os.environ.get( CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = os.environ.get(
"CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE", "1" "CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE", "1"
) )

View file

@ -16,10 +16,15 @@ from open_webui.routers.files import upload_file_handler
import mimetypes import mimetypes
import base64 import base64
import io import io
import re
BASE64_IMAGE_URL_PREFIX = re.compile(r"data:image/\w+;base64,", re.IGNORECASE)
MARKDOWN_IMAGE_URL_PATTERN = re.compile(r"!\[(.*?)\]\((.+?)\)", re.IGNORECASE)
def get_image_url_from_base64(request, base64_image_string, metadata, user): def get_image_url_from_base64(request, base64_image_string, metadata, user):
if "data:image/png;base64" in base64_image_string: if BASE64_IMAGE_URL_PREFIX.match(base64_image_string):
image_url = "" image_url = ""
# Extract base64 image data from the line # Extract base64 image data from the line
image_data, content_type = get_image_data(base64_image_string) image_data, content_type = get_image_data(base64_image_string)
@ -35,6 +40,19 @@ def get_image_url_from_base64(request, base64_image_string, metadata, user):
return None return None
def convert_markdown_base64_images(request, content: str, metadata, user):
def replace(match):
base64_string = match.group(2)
MIN_REPLACEMENT_URL_LENGTH = 1024
if len(base64_string) > MIN_REPLACEMENT_URL_LENGTH:
url = get_image_url_from_base64(request, base64_string, metadata, user)
if url:
return f"![{match.group(1)}]({url})"
return match.group(0)
return MARKDOWN_IMAGE_URL_PATTERN.sub(replace, content)
def load_b64_audio_data(b64_str): def load_b64_audio_data(b64_str):
try: try:
if "," in b64_str: if "," in b64_str:

View file

@ -58,7 +58,7 @@ from open_webui.routers.memories import query_memory, QueryMemoryForm
from open_webui.utils.webhook import post_webhook from open_webui.utils.webhook import post_webhook
from open_webui.utils.files import ( from open_webui.utils.files import (
get_audio_url_from_base64, convert_markdown_base64_images,
get_file_url_from_base64, get_file_url_from_base64,
get_image_url_from_base64, get_image_url_from_base64,
) )
@ -112,6 +112,7 @@ from open_webui.config import (
from open_webui.env import ( from open_webui.env import (
SRC_LOG_LEVELS, SRC_LOG_LEVELS,
GLOBAL_LOG_LEVEL, GLOBAL_LOG_LEVEL,
ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION,
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE, CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE,
CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES, CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES,
BYPASS_MODEL_ACCESS_CONTROL, BYPASS_MODEL_ACCESS_CONTROL,
@ -2680,6 +2681,11 @@ async def process_chat_response(
} }
) )
if ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION:
value = convert_markdown_base64_images(
request, value, metadata, user
)
content = f"{content}{value}" content = f"{content}{value}"
if not content_blocks: if not content_blocks:
content_blocks.append( content_blocks.append(