diff --git a/backend/open_webui/models/models.py b/backend/open_webui/models/models.py index 36b0792a6b..9bd3f888c1 100755 --- a/backend/open_webui/models/models.py +++ b/backend/open_webui/models/models.py @@ -1,3 +1,4 @@ +import json import logging import time from typing import Optional @@ -319,9 +320,20 @@ class ModelsTable: tag = filter.get('tag') if tag: - like_pattern = f'%"{tag.lower()}"%' - meta_text = func.lower(cast(Model.meta, String)) - stmt = stmt.filter(meta_text.like(like_pattern)) + # SQLite stores JSON text via json.dumps(ensure_ascii=True), + # so non-ASCII chars are \uXXXX-escaped. PostgreSQL native JSONB + # stores literal Unicode. Use the right pattern for each. + if db.bind.dialect.name == 'sqlite': + if tag.isascii(): + meta_text = func.lower(cast(Model.meta, String)) + pattern = f'%{json.dumps(tag.lower())}%' + else: + meta_text = cast(Model.meta, String) + pattern = f'%{json.dumps(tag)}%' + else: + meta_text = func.lower(cast(Model.meta, String)) + pattern = f'%{json.dumps(tag.lower(), ensure_ascii=False)}%' + stmt = stmt.filter(meta_text.like(pattern)) order_by = filter.get('order_by') direction = filter.get('direction') diff --git a/backend/open_webui/models/prompts.py b/backend/open_webui/models/prompts.py index 64f66bec86..fbf5401203 100644 --- a/backend/open_webui/models/prompts.py +++ b/backend/open_webui/models/prompts.py @@ -1,3 +1,4 @@ +import json import time import uuid from typing import Optional @@ -292,10 +293,22 @@ class PromptsTable: tag = filter.get('tag') if tag: - # Search for tag in JSON array field - like_pattern = f'%"{tag.lower()}"%' - tags_text = func.lower(cast(Prompt.tags, String)) - stmt = stmt.filter(tags_text.like(like_pattern)) + # SQLite stores JSON text via json.dumps(ensure_ascii=True), + # so non-ASCII chars are \uXXXX-escaped. PostgreSQL native JSONB + # stores literal Unicode. Use the right pattern for each. + if db.bind.dialect.name == 'sqlite': + if tag.isascii(): + tags_text = func.lower(cast(Prompt.tags, String)) + pattern = f'%{json.dumps(tag.lower())}%' + else: + # LOWER() is ASCII-only; non-ASCII codepoints would + # produce different \uXXXX escapes when lowered. + tags_text = cast(Prompt.tags, String) + pattern = f'%{json.dumps(tag)}%' + else: + tags_text = func.lower(cast(Prompt.tags, String)) + pattern = f'%{json.dumps(tag.lower(), ensure_ascii=False)}%' + stmt = stmt.filter(tags_text.like(pattern)) order_by = filter.get('order_by') direction = filter.get('direction')