From 1555252c4a60cbf0be96d4725ea25b42e101cdf9 Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:43:25 -0500 Subject: [PATCH 001/120] fix: handle undefined model in createMessagePair function (#20663) - Add a null check when looking up model to prevent JavaScript error when trying to add a message pair in a chat with an invalid/corrupt model ID. --- src/lib/components/chat/Chat.svelte | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index ff41dfe472..d7341257f2 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1282,6 +1282,11 @@ const modelId = selectedModels[0]; const model = $models.filter((m) => m.id === modelId).at(0); + if (!model) { + toast.error($i18n.t('Model not found')); + return; + } + const messages = createMessagesList(history, history.currentId); const parentMessage = messages.length !== 0 ? messages.at(-1) : null; From e26f6acc3b67831dd3d80d4eae59b96adca858b4 Mon Sep 17 00:00:00 2001 From: Kailey Wong <61530252+kaileywong@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:44:35 -0800 Subject: [PATCH 002/120] fix: use proper X-Api-Key header format when docling api key provided (#20652) --- backend/open_webui/retrieval/loaders/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/retrieval/loaders/main.py b/backend/open_webui/retrieval/loaders/main.py index 2b83e44283..bf7c7286b5 100644 --- a/backend/open_webui/retrieval/loaders/main.py +++ b/backend/open_webui/retrieval/loaders/main.py @@ -143,7 +143,7 @@ class DoclingLoader: with open(self.file_path, "rb") as f: headers = {} if self.api_key: - headers["X-Api-Key"] = f"Bearer {self.api_key}" + headers["X-Api-Key"] = f"{self.api_key}" r = requests.post( f"{self.url}/v1/convert/file", From 1d343aeae41dff8f4ebd1e08720db80780f62159 Mon Sep 17 00:00:00 2001 From: EntropyYue <164553692+EntropyYue@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:46:00 +0800 Subject: [PATCH 003/120] enh: Make builtin search web tools asynchronous (#20630) Co-authored-by: Tim Baek Co-authored-by: joaoback <156559121+joaoback@users.noreply.github.com> --- backend/open_webui/tools/builtin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index d26e032727..144d18d284 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -166,7 +166,7 @@ async def search_web( engine = __request__.app.state.config.WEB_SEARCH_ENGINE user = UserModel(**__user__) if __user__ else None - results = _search_web(__request__, engine, query, user) + results = await asyncio.to_thread(_search_web, __request__, engine, query, user) # Limit results results = results[:count] if results else [] From 1c1f72f05c526dbf7be2740f0e16c79289589f3e Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:15:02 +0100 Subject: [PATCH 004/120] Update builtin.py (#20705) --- backend/open_webui/tools/builtin.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index 144d18d284..fcd1d4d233 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -1599,6 +1599,25 @@ async def query_knowledge_files( if not __user__: return json.dumps({"error": "User context not available"}) + # Coerce parameters from LLM tool calls (may come as strings) + if isinstance(count, str): + try: + count = int(count) + except ValueError: + count = 5 # Default fallback + + # Handle knowledge_ids being string "None", "null", or empty + if isinstance(knowledge_ids, str): + if knowledge_ids.lower() in ("none", "null", ""): + knowledge_ids = None + else: + # Try to parse as JSON array if it looks like one + try: + knowledge_ids = json.loads(knowledge_ids) + except json.JSONDecodeError: + # Treat as single ID + knowledge_ids = [knowledge_ids] + try: from open_webui.models.knowledge import Knowledges from open_webui.models.files import Files From 711a2cd7385ea755b789083dfbecdf7916cf740d Mon Sep 17 00:00:00 2001 From: Kylapaallikko Date: Sat, 17 Jan 2026 19:37:14 +0200 Subject: [PATCH 005/120] Update translation.json (#20741) Added missing translations and minor changes to wording of the translations. --- src/lib/i18n/locales/fi-FI/translation.json | 208 ++++++++++---------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index 2e092f59a3..ff34a7b91d 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -12,10 +12,10 @@ "{{COUNT}} Available Tools": "{{COUNT}} työkalua saatavilla", "{{COUNT}} characters": "{{COUNT}} kirjainta", "{{COUNT}} extracted lines": "{{COUNT}} poimittua riviä", - "{{COUNT}} files": "", + "{{COUNT}} files": "{{COUNT}} tiedostoa", "{{COUNT}} hidden lines": "{{COUNT}} piilotettua riviä", "{{COUNT}} Replies": "{{COUNT}} vastausta", - "{{COUNT}} Rows": "", + "{{COUNT}} Rows": "{{COUNT}} riviä", "{{COUNT}} Sources": "{{COUNT}} lähdettä", "{{COUNT}} words": "{{COUNT}} sanaa", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", @@ -47,7 +47,7 @@ "Activate this command by typing \"/{{COMMAND}}\" to chat input.": "Aktivoi tämä komento kirjoittamalla \"/{{COMMAND}}\" chat-syötteeseen.", "Active": "Aktiivinen", "Active Users": "Aktiiviset käyttäjät", - "Activity": "", + "Activity": "Toiminta", "Add": "Lisää", "Add a model ID": "Lisää mallitunnus", "Add a short description about what this model does": "Lisää lyhyt kuvaus siitä, mitä tämä malli tekee", @@ -70,15 +70,15 @@ "Add text content": "Lisää tekstisisältöä", "Add User": "Lisää käyttäjä", "Add User Group": "Lisää käyttäjäryhmä", - "Add webpage": "", + "Add webpage": "Lisää verkkosivu", "Additional Config": "Lisäasetukset", "Additional configuration options for marker. This should be a JSON string with key-value pairs. For example, '{\"key\": \"value\"}'. Supported keys include: disable_links, keep_pageheader_in_output, keep_pagefooter_in_output, filter_blank_pages, drop_repeated_text, layout_coverage_threshold, merge_threshold, height_tolerance, gap_threshold, image_threshold, min_line_length, level_count, default_level": "", "Additional Parameters": "Lisäparametrit", "Adds filenames, titles, sections, and snippets into the BM25 text to improve lexical recall.": "", - "Adjusting these settings will apply changes universally to all users.": "Näiden asetusten säätäminen vaikuttaa kaikkiin käyttäjiin.", + "Adjusting these settings will apply changes universally to all users.": "Näiden asetusten muokkaaminen vaikuttaa kaikkiin käyttäjiin.", "admin": "hallinta", "Admin": "Ylläpito", - "Admin Contact Email": "", + "Admin Contact Email": "Ylläpidon sähköposti", "Admin Panel": "Ylläpitopaneeli", "Admin Settings": "Ylläpitoasetukset", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Ylläpitäjillä on pääsy kaikkiin työkaluihin koko ajan; käyttäjät tarvitsevat työkaluja mallille määritettynä työtilassa.", @@ -131,7 +131,7 @@ "and {{COUNT}} more": "ja {{COUNT}} muuta", "and create a new shared link.": "ja luo uusi jaettu linkki.", "Android": "Android", - "Anyone": "", + "Anyone": "Kukatahansa", "API Base URL": "API:n verkko-osoite", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API verkko-osoite Datalabb Marker palveluun. Oletuksena: https://www.datalab.to/api/v1/marker", "API Key": "API-avain", @@ -140,7 +140,7 @@ "API keys": "API-avaimet", "API Keys": "API-avaimet", "API Mode": "API-moodi", - "API Timeout": "", + "API Timeout": "API aikakatkaisu", "API Version": "API-versio", "API Version is required": "API-versio vaaditaan", "Application DN": "Sovelluksen DN", @@ -159,7 +159,7 @@ "Are you sure?": "Oletko varma?", "Arena Models": "Arena-mallit", "Artifacts": "Artefaktit", - "Asc": "", + "Asc": "Nouseva", "Ask": "Kysy", "Ask a question": "Kysy kysymys", "Assistant": "Avustaja", @@ -177,7 +177,7 @@ "Authenticate": "Todentaa", "Authentication": "Todennus", "Auto": "Automaattinen", - "Auto (Random)": "", + "Auto (Random)": "Automaattinen (satunnainen)", "Auto-Copy Response to Clipboard": "Kopioi vastaus automaattisesti leikepöydälle", "Auto-playback response": "Toista vastaus automaattisesti", "Autocomplete Generation": "Automaattisen täydennyksen luonti", @@ -216,12 +216,12 @@ "Boosting or penalizing specific tokens for constrained responses. Bias values will be clamped between -100 and 100 (inclusive). (Default: none)": "Tiettyjen tokeneiden tehostaminen tai rankaiseminen rajoitetuista vastauksista. Poikkeaman arvot rajoitetaan välille -100 ja 100 (mukaan lukien). (Oletus: ei mitään)", "Brave": "", "Brave Search API Key": "Brave Search API -avain", - "Builtin Tools": "", + "Builtin Tools": "Sisäänrakennetut työkalut", "Bullet List": "Luettelo", "Button ID": "Painikkeen ID", "Button Label": "Painikkeen nimi", "Button Prompt": "Painikkeen kehoite", - "by {{name}}": "", + "by {{name}}": "tekijä {{name}}", "By {{name}}": "Tekijä {{name}}", "Bypass Embedding and Retrieval": "Ohita upotus ja haku", "Bypass Web Loader": "Ohita verkkolataaja", @@ -231,8 +231,8 @@ "Call feature is not supported when using Web STT engine": "Puhelutoimintoa ei tueta käytettäessä web-puheentunnistusmoottoria", "Camera": "Kamera", "Cancel": "Peruuta", - "Cannot create an empty note.": "", - "Capabilities": "Ominaisuuksia", + "Cannot create an empty note.": "Tyhjää muistiinpanoa ei voi luoda.", + "Capabilities": "Ominaisuudet", "Capture": "Näyttökuva", "Capture Audio": "Kaappaa ääntä", "Certificate Path": "Varmennepolku", @@ -241,7 +241,7 @@ "Channel deleted successfully": "Kanavan poisto onnistui", "Channel Name": "Kanavan nimi", "Channel name cannot be empty.": "Kanavan nimi ei voi olla tyhjä", - "Channel name must be less than 128 characters": "", + "Channel name must be less than 128 characters": "Kanavan nimi oltava alle 128 merkkiä pitkä", "Channel Type": "Kanavatyyppi", "Channel updated successfully": "Kanavan päivitys onnistui", "Channels": "Kanavat", @@ -264,10 +264,10 @@ "Check for updates": "Tarkista päivitykset", "Checking for updates...": "Tarkistetaan päivityksiä...", "Choose a model before saving...": "Valitse malli ennen tallentamista...", - "Chunk Min Size Target": "", + "Chunk Min Size Target": "Osien vähimmäiskoko", "Chunk Overlap": "Päällekkäisten osien määrä", "Chunk Size": "Osien koko", - "Chunks smaller than this threshold will be merged with neighboring chunks when possible. Set to 0 to disable merging.": "", + "Chunks smaller than this threshold will be merged with neighboring chunks when possible. Set to 0 to disable merging.": "Kynnysarvoa pienemmät osat yhdistetään viereisiin osiin mahdollisuuksien mukaan. Aseta arvoksi 0 poistaaksesi yhdistämisen käytöstä.", "Ciphers": "Salausalgoritmi", "Citation": "Lähdeviite", "Citations": "Lähdeviitteet", @@ -303,7 +303,7 @@ "Code Block": "Koodilohko", "Code Editor": "Koodieditori", "Code execution": "Koodin suoritus", - "Code Execution": "", + "Code Execution": "Koodin suoritus", "Code Execution Engine": "Koodin suoritusmoottori", "Code Execution Timeout": "Koodin suorittamisen aikakatkaisu", "Code formatted successfully": "Koodin muotoilu onnistui", @@ -313,7 +313,7 @@ "Collaboration channel where people join as members": "Yhteistyökanava, johon ihmiset liittyvät jäseninä", "Collapse": "Pienennä", "Collection": "Kokoelma", - "Collections": "", + "Collections": "Kokoelmat", "Color": "Väri", "ComfyUI": "ComfyUI", "ComfyUI API Key": "ComfyUI API -avain", @@ -346,12 +346,12 @@ "Contact Admin for WebUI Access": "Ota yhteyttä ylläpitäjään WebUI-käyttöä varten", "Content": "Sisältö", "Content Extraction Engine": "Sisällönpoimintamoottori", - "Content lengths (character counts only)": "", + "Content lengths (character counts only)": "Sisällön pituus (vain merkkimäärä)", "Continue Response": "Jatka vastausta", "Continue with {{provider}}": "Jatka palvelulla {{provider}}", "Continue with Email": "Jatka sähköpostilla", "Continue with LDAP": "Jatka LDAP:illa", - "Control how message text is split for TTS requests. 'Punctuation' splits into sentences, 'paragraphs' splits into paragraphs, and 'none' keeps the message as a single string.": "Säädä, miten viestin teksti jaetaan puhesynteesipyyntöjä varten. 'Välimerkit' jakaa lauseisiin, 'kappaleet' jakaa kappaleisiin ja 'ei mitään' pitää viestin yhtenä merkkijonona.", + "Control how message text is split for TTS requests. 'Punctuation' splits into sentences, 'paragraphs' splits into paragraphs, and 'none' keeps the message as a single string.": "Muokkaa, miten viestin teksti jaetaan puhesynteesipyyntöjä varten. 'Välimerkit' jakaa lauseisiin, 'kappaleet' jakaa kappaleisiin ja 'ei mitään' pitää viestin yhtenä merkkijonona.", "Control the repetition of token sequences in the generated text. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 1.1) will be more lenient. At 1, it is disabled.": "", "Controls": "Ohjaimet", "Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text.": "Kontrolloi yhtenäisyyden ja monimuotoisuuden tasapainoa tuloksessa. Pienempi arvo tuottaa kohdennetumman ja johdonmukaisemman tekstin.", @@ -367,7 +367,7 @@ "Copy link": "Kopioi linkki", "Copy Link": "Kopioi linkki", "Copy to clipboard": "Kopioi leikepöydälle", - "Copy URL": "", + "Copy URL": "Kopioi linkki", "Copying to clipboard was successful!": "Kopioiminen leikepöydälle onnistui!", "CORS must be properly configured by the provider to allow requests from Open WebUI.": "CORS täytyy olla konfiguroitu palveluntarjoajan toimesta pyyntöjen hyväksymiseksi Open WebUI:sta.", "Create": "Luo", @@ -384,14 +384,14 @@ "Create Model": "Luo malli", "Create new key": "Luo uusi avain", "Create new secret key": "Luo uusi salainen avain", - "Create note": "", + "Create note": "Luo muistiinpano", "Create Note": "Luo muistiinpano", "Create your first note by clicking on the plus button below.": "Luo ensimmäinen muistiinpanosi painamalla alla olevaa plus painiketta.", "Created at": "Luotu", "Created At": "Luotu", "Created by": "Luonut", "Created by you": "Sinun luomasi", - "Created on {{date}}": "", + "Created on {{date}}": "Luotu {{date}}", "CSV Import": "CSV-tuonti", "Ctrl+Enter to Send": "Ctrl+Enter lähettääksesi", "Current Model": "Nykyinen malli", @@ -417,7 +417,7 @@ "Default description enabled": "Oletuskuvaus käytössä", "Default Features": "Oletus ominaisuudet", "Default Filters": "Oletus suodattimet", - "Default Group": "Oletus ryhmä", + "Default Group": "Oletusryhmä", "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Oletustila toimii laajemman mallivalikoiman kanssa kutsumalla työkaluja kerran ennen suorittamista. Natiivitila hyödyntää mallin sisäänrakennettuja työkalujen kutsumisominaisuuksia, mutta edellyttää, että malli tukee tätä ominaisuutta.", "Default Model": "Oletusmalli", "Default model updated": "Oletusmalli päivitetty", @@ -447,12 +447,12 @@ "delete this link": "poista tämä linkki", "Delete tool?": "Haluatko varmasti poistaa tämän työkalun?", "Delete User": "Poista käyttäjä", - "Deleted": "", + "Deleted": "Poistettu", "Deleted {{deleteModelTag}}": "Poistettu {{deleteModelTag}}", "Deleted {{name}}": "Poistettu {{nimi}}", "Deleted User": "Käyttäjä poistettu", "Deployment names are required for Azure OpenAI": "Azure OpenAI:lle vaaditaan käyttöönottojen nimet", - "Desc": "", + "Desc": "Laskeva", "Describe your knowledge base and objectives": "Kuvaa tietokantasi ja tavoitteesi", "Description": "Kuvaus", "Detect Artifacts Automatically": "Tunnista artefaktit automaattisesti", @@ -489,7 +489,7 @@ "Dive into knowledge": "Uppoudu tietoon", "Do not install functions from sources you do not fully trust.": "Älä asenna toimintoja lähteistä, joihin et luota täysin.", "Do not install tools from sources you do not fully trust.": "Älä asenna työkaluja lähteistä, joihin et luota täysin.", - "Do you want to sync your usage stats with Open WebUI Community?": "", + "Do you want to sync your usage stats with Open WebUI Community?": "Haluatko jakaa käyttötilastosi Open WebUI yhteisön kanssa?", "Docling": "Docling", "Docling Parameters": "Docling parametrit", "Docling Server URL required.": "Docling palvelimen verkko-osoite vaaditaan.", @@ -498,7 +498,7 @@ "Document Intelligence endpoint required.": "Document Intelligence pääte vaaditaan", "Document Intelligence Model": "Document Intelligence malli", "Documentation": "Dokumentaatio", - "Documents": "", + "Documents": "Dokumentit", "does not make any external connections, and your data stays securely on your locally hosted server.": "ei tee ulkoisia yhteyksiä, ja tietosi pysyvät turvallisesti paikallisesti isännöidyllä palvelimellasi.", "Domain Filter List": "Verkko-osoitteiden suodatuslista", "don't fetch random pipelines from sources you don't trust.": "Älä hae satunnaisia pipelineja epäluotettavista lähteistä.", @@ -509,11 +509,11 @@ "Done": "Valmis", "Download": "Lataa", "Download & Delete": "Lataa ja poista", - "Download as JSON": "", + "Download as JSON": "Lataa JSON:na", "Download as SVG": "Lataa SVG:nä", "Download canceled": "Lataus peruutettu", "Download Database": "Lataa tietokanta", - "Downloading stats...": "", + "Downloading stats...": "Ladataa tilastoja...", "Draw": "Piirros", "Drop any files here to upload": "Pudota tähän ladattavat tiedostot", "DuckDuckGo": "", @@ -522,7 +522,7 @@ "e.g. 60": "esim. 60", "e.g. A filter to remove profanity from text": "esim. suodatin, joka poistaa kirosanoja tekstistä", "e.g. about the Roman Empire": "esim. Rooman valtakunta", - "e.g. alloy, echo, shimmer": "", + "e.g. alloy, echo, shimmer": "esim. alloy, echo, shimmer", "e.g. en": "esim. en", "e.g. My Filter": "esim. Oma suodatin", "e.g. My Tools": "esim. Omat työkalut", @@ -575,7 +575,7 @@ "Endpoint URL": "Päätepiste verkko-osoite", "Enforce Temporary Chat": "Pakota väliaikaiset keskustelut", "Enhance": "Paranna", - "Enrich Hybrid Search Text": "", + "Enrich Hybrid Search Text": "Rikasta hybridihakutekstiä", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Varmista, että CSV-tiedostossasi on 4 saraketta tässä järjestyksessä: Nimi, Sähköposti, Salasana, Rooli.", "Enter {{role}} message here": "Kirjoita {{role}}-viesti tähän", "Enter a detail about yourself for your LLMs to recall": "Kirjoita yksityiskohta itsestäsi, jonka LLM-ohjelmat voivat muistaa", @@ -592,7 +592,7 @@ "Enter Bocha Search API Key": "Kirjoita Bocha Search API -avain", "Enter Brave Search API Key": "Kirjoita Brave Search API -avain", "Enter certificate path": "Kirjoita varmennepolku", - "Enter Chunk Min Size Target": "", + "Enter Chunk Min Size Target": "Kirjoita osien vähimmäiskoko", "Enter Chunk Overlap": "Syötä osien päällekkäisyys", "Enter Chunk Size": "Syötä osien koko", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Syötä pilkulla erottaen \"token:bias_value\" parit (esim. 5432:100, 413:-100)", @@ -616,7 +616,7 @@ "Enter External Web Search URL": "Kirjoita ulkoisen Web Search verkko-osoite", "Enter Firecrawl API Base URL": "Kirjoita Firecrawl API -verkko-osoite", "Enter Firecrawl API Key": "Kirjoita Firecrawl API-avain", - "Enter Firecrawl Timeout": "", + "Enter Firecrawl Timeout": "Kirjoita Firecrawl aikakatkaisu", "Enter folder name": "Kirjoita kansion nimi", "Enter function name filter list (e.g. func1, !func2)": "Kirjoita funktion nimen suodatinluettelo (esim. func1, !func2)", "Enter Github Raw URL": "Kirjoita Github Raw -verkko-osoite", @@ -625,7 +625,7 @@ "Enter hex color (e.g. #FF0000)": "Kirjota hex väri (esim. #FF0000)", "Enter ID": "Kirjoita ID", "Enter Image Size (e.g. 512x512)": "Kirjoita kuvan koko (esim. 512x512)", - "Enter Jina API Base URL": "", + "Enter Jina API Base URL": "Kirjoita Jina API verkko-osoite", "Enter Jina API Key": "Kirjoita Jina API -avain", "Enter JSON config (e.g., {\"disable_links\": true})": "Kirjoita JSON asetus (esim. {\"disable_links\": true})", "Enter Jupyter Password": "Kirjoita Jupyter salasana", @@ -634,7 +634,7 @@ "Enter Kagi Search API Key": "Kirjoita Kagi Search API -avain", "Enter Key Behavior": "Enter näppäimen käyttäytyminen", "Enter language codes": "Kirjoita kielikoodit", - "Enter MinerU API Key": "", + "Enter MinerU API Key": "Kirjoita MinerU API-avain", "Enter Mistral API Base URL": "Kirjoita Mistral API verkko-osoite", "Enter Mistral API Key": "Kirjoita Mistral API-avain", "Enter Model ID": "Kirjoita mallitunnus", @@ -654,7 +654,7 @@ "Enter SearchApi API Key": "Kirjoita SearchApi API -avain", "Enter SearchApi Engine": "Kirjoita SearchApi-moottori", "Enter Searxng Query URL": "Kirjoita Searxng-kyselyn verkko-osoite", - "Enter Searxng search language": "", + "Enter Searxng search language": "Kirjoita Searxng hakukieli", "Enter Seed": "Kirjoita siemenluku", "Enter SerpApi API Key": "Kirjoita SerpApi API -avain", "Enter SerpApi Engine": "Valitse SerpApi Moottori", @@ -760,10 +760,10 @@ "Failed to generate title": "Otsikon luonti epäonnistui", "Failed to import models": "Mallien tuonti epäonnistui", "Failed to load chat preview": "Keskustelun esikatselun lataaminen epäonnistui", - "Failed to load Excel/CSV file. Please try downloading it instead.": "", + "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV tiedoston lataaminen epäonnistui. Yritä ladata se sen sijaan.", "Failed to load file content.": "Tiedoston sisällön lataaminen epäonnistui.", "Failed to move chat": "Keskustelun siirto epäonnistui", - "Failed to process URL: {{url}}": "", + "Failed to process URL: {{url}}": "Verkko-osoitteen käsittely epäonnistui: {{url}}", "Failed to read clipboard contents": "Leikepöydän sisällön lukeminen epäonnistui", "Failed to remove member": "Jäsenen poistaminen epäonnistui", "Failed to render diagram": "Diagrammin renderöinti epäonnistui", @@ -777,7 +777,7 @@ "Features": "Ominaisuudet", "Features Permissions": "Ominaisuuksien käyttöoikeudet", "February": "helmikuu", - "Feedback": "", + "Feedback": "Palaute", "Feedback deleted successfully": "Palaute poistettu onnistuneesti", "Feedback Details": "Palautteen tiedot", "Feedback History": "Palautehistoria", @@ -786,7 +786,7 @@ "File": "Tiedosto", "File added successfully.": "Tiedosto lisätty onnistuneesti.", "File content updated successfully.": "Tiedoston sisältö päivitetty onnistuneesti.", - "File Context": "", + "File Context": "Tiedoston konteksti", "File Mode": "Tiedostotila", "File not found.": "Tiedostoa ei löytynyt.", "File removed successfully.": "Tiedosto poistettu onnistuneesti.", @@ -802,13 +802,13 @@ "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Sormenjäljen väärentäminen havaittu: Alkukirjaimia ei voi käyttää avatarina. Käytetään oletusprofiilikuvaa.", "Firecrawl API Base URL": "Firecrawl API -verkko-osoite", "Firecrawl API Key": "Firecrawl API-avain", - "Firecrawl Timeout (s)": "", + "Firecrawl Timeout (s)": "Firecrawl aikakatkaisu (t)", "Floating Quick Actions": "Kelluvat pikakomennot", "Focus Chat Input": "Kohdista keskustelu tekstikenttään", "Folder": "Kansio", "Folder Background Image": "Kansion taustakuva", "Folder deleted successfully": "Kansio poistettu onnistuneesti", - "Folder Max File Count": "", + "Folder Max File Count": "Kansion tiedostojen enimmäismäärä", "Folder Name": "Kansion nimi", "Folder name cannot be empty.": "Kansion nimi ei voi olla tyhjä.", "Folder name updated successfully": "Kansion nimi päivitetty onnistuneesti", @@ -868,7 +868,7 @@ "Google PSE API Key": "Google PSE API -avain", "Google PSE Engine Id": "Google PSE -moottorin tunnus", "Gravatar": "Gravatar", - "Grid": "", + "Grid": "Ruudukko", "Grokipedia": "", "Group": "Ryhmä", "Group Channel": "Ryhmäkanava", @@ -923,7 +923,7 @@ "Image Prompt Generation": "Kuvan kehote generointi", "Image Prompt Generation Prompt": "Kuvan generoinnin kehote", "Image Size": "Kuvan koko", - "Images": "", + "Images": "Kuvat", "Import": "Tuo", "Import Chats": "Tuo keskustelut", "Import Config from JSON File": "Tuo asetukset JSON-tiedostosta", @@ -942,7 +942,7 @@ "Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "Kuinka nopeasti algoritmi mukautuu generoidun tekstin palautteeseen. Alempi oppimisnopeus hidastaa mukautumista, kun taas nopeampi oppimisnopeus tekee algoritmistä reagoivamman.", "Info": "Tiedot", "Initials": "Nimikirjaimet", - "Inject file content into conversation context": "", + "Inject file content into conversation context": "Upota tiedostosisältö keskustelun kontekstiin", "Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "Upota koko sisältö kontekstiin kattavaa käsittelyä varten. Tätä suositellaan monimutkaisille kyselyille.", "Input": "Tekstikenttä", "Input Key (e.g. text, unet_name, steps)": "Syötteen arvo (esim. text, unet_namme, steps)", @@ -956,7 +956,7 @@ "Integration": "Integrointi", "Integrations": "Integraatiot", "Interface": "Käyttöliittymä", - "Interface Settings Access": "", + "Interface Settings Access": "Käyttöliittymän asetusten käyttöoikeus", "Invalid file content": "Virheellinen tiedostosisältö", "Invalid file format.": "Virheellinen tiedostomuoto.", "Invalid JSON file": "Virheellinen JSON tiedosto", @@ -970,7 +970,7 @@ "is typing...": "Kirjoittaa...", "Italic": "Kursiivi", "January": "tammikuu", - "Jina API Base URL": "", + "Jina API Base URL": "Jina API verkko-osoite", "Jina API Key": "Jina API -avain", "join our Discord for help.": "liity Discordiimme saadaksesi apua.", "JSON": "JSON", @@ -995,7 +995,7 @@ "Knowledge created successfully.": "Tietokanta luotu onnistuneesti.", "Knowledge deleted successfully.": "Tietokanta poistettu onnistuneesti.", "Knowledge Description": "Tietokannan kuvaus", - "Knowledge exported successfully": "", + "Knowledge exported successfully": "Tietokanta viety onnistuneesti", "Knowledge Name": "Tietokannan nimi", "Knowledge Public Sharing": "Tietokannan julkinen jakaminen", "Knowledge reset successfully.": "Tietokanta nollattu onnistuneesti.", @@ -1022,7 +1022,7 @@ "Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "Jätä tyhjäksi sisällyttääksesi \"{{url}}/api/tags\" päätepisteen mallit", "Leave empty to include all models from \"{{url}}/models\" endpoint": "Jätä tyhjäksi sisällyttääksesi \"{{url}}/models\" päätepisteen mallit", "Leave empty to include all models or select specific models": "Jätä tyhjäksi, jos haluat sisällyttää kaikki mallit tai valitse tietyt mallit", - "Leave empty to use first admin user": "", + "Leave empty to use first admin user": "Jätä tyhjäksi käyttääksesi ensimmäistä ylläpitäjää", "Leave empty to use the default model (voxtral-mini-latest).": "Jätä tyhjäks käyttääksesi oletusmallia (voxtral-mini-latest)", "Leave empty to use the default prompt, or enter a custom prompt": "Jätä tyhjäksi käyttääksesi oletuskehotetta tai kirjoita mukautettu kehote", "Leave model field empty to use the default model.": "Jätä malli kenttä tyhjäksi käyttääksesi oletus mallia.", @@ -1031,8 +1031,8 @@ "License": "Lisenssi", "Lift List": "Nostolista", "Light": "Vaalea", - "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", - "List": "", + "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Rajoita samanaikaisia hakukyselyitä. 0 = rajoittamaton (oletus). Aseta arvoon 1 peräkkäistä suoritusta varten (suositellaan API-rajapinnoille, joilla on tiukat nopeusrajoitukset, kuten Brave-ilmaistaso).", + "List": "Lista", "Listening...": "Kuuntelee...", "Llama.cpp": "Llama.cpp", "LLMs can make mistakes. Verify important information.": "Kielimallit voivat tehdä virheitä. Tarkista tärkeät tiedot.", @@ -1062,12 +1062,12 @@ "Manage your account information.": "Hallitse tilitietojasi", "March": "maaliskuu", "Markdown": "Markdown", - "Markdown Header Text Splitter": "", + "Markdown Header Text Splitter": "Markdown-otsikkotekstin jakaja", "Max Speakers": "Puhujien enimmäismäärä", "Max Upload Count": "Latausten enimmäismäärä", "Max Upload Size": "Latausten enimmäiskoko", - "Maximum number of files allowed per folder.": "", - "Maximum number of files per folder is {{max}}.": "", + "Maximum number of files allowed per folder.": "Kansiota kohden sallittujen tiedostojen enimmäismäärä.", + "Maximum number of files per folder is {{max}}.": "Tiedostojen enimmäismäärä kansiossa on {{max}}.", "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Enintään 3 mallia voidaan ladata samanaikaisesti. Yritä myöhemmin uudelleen.", "May": "toukokuu", "MBR": "MBR", @@ -1077,7 +1077,7 @@ "Member removed successfully": "Jäsen poistettu onnistuneesti", "Members": "Jäsenet", "Members added successfully": "Jäsen lisätty onnistuneesti", - "Memories": "", + "Memories": "Muistot", "Memories accessible by LLMs will be shown here.": "Muistitiedostot, joita LLM-ohjelmat käyttävät, näkyvät tässä.", "Memory": "Muisti", "Memory added successfully": "Muisti lisätty onnistuneesti", @@ -1087,7 +1087,7 @@ "Merge Responses": "Yhdistä vastaukset", "Merged Response": "Yhdistetty vastaus", "Message": "Viesti", - "Message counts and response timestamps": "", + "Message counts and response timestamps": "Viestien määrä ja vastausten aikaleimat", "Message rating should be enabled to use this feature": "Tämän toiminnon käyttämiseksi viestiarviointi on otettava käyttöön", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Linkin luomisen jälkeen lähettämäsi viestit eivät ole jaettuja. Käyttäjät, joilla on verkko-osoite, voivat tarkastella jaettua keskustelua.", "Microsoft OneDrive": "", @@ -1120,11 +1120,11 @@ "Model Name": "Mallin nimi", "Model name already exists, please choose a different one": "Mallin nimi on jo olemassa, valitse toinen nimi.", "Model Name is required.": "Mallin nimi on pakollinen", - "Model names and usage frequency": "", + "Model names and usage frequency": "Mallien nimet ja käyttötiheys", "Model not selected": "Mallia ei ole valittu", "Model Params": "Mallin parametrit", "Model Permissions": "Mallin käyttöoikeudet", - "Model responses or outputs": "", + "Model responses or outputs": "Mallin vastaukset tai tuotokset", "Model unloaded successfully": "Malli purettu onnistuneesti", "Model updated successfully": "Malli päivitetty onnistuneesti", "Model(s) do not support file upload": "Malli(t) ei tue tiedostojen lataamista", @@ -1145,22 +1145,22 @@ "Name and ID are required, please fill them out": "Nimi ja ID vaaditaan, täytä puuttuvat kentät", "Name your knowledge base": "Anna tietokannalle nimi", "Native": "Natiivi", - "New": "", + "New": "Uusi", "New Button": "Uusi painike", "New Chat": "Uusi keskustelu", "New Folder": "Uusi kansio", "New Function": "Uusi toiminto", "New Knowledge": "Uutta tietoa", "New Model": "Uusi malli", - "New Note": "", + "New Note": "Uusi muistiinpano", "New Password": "Uusi salasana", "New Prompt": "Uusi kehoite", "New Temporary Chat": "Uusi väliaikainen keskustelu", "New Tool": "Uusi työkalu", - "New Webhook": "", + "New Webhook": "Uusi Webhook", "new-channel": "uusi-kanava", "Next message": "Seuraava viesti", - "No activity data": "", + "No activity data": "Ei aktiivisuustietoja", "No authentication": "Ei todennusta", "No chats found": "Keskuteluja ei löytynyt", "No chats found for this user.": "Käyttäjän keskusteluja ei löytynyt.", @@ -1171,14 +1171,14 @@ "No conversation to save": "Ei tallennettavaa keskustelua", "No distance available": "Etäisyyttä ei saatavilla", "No expiration can pose security risks.": "Vanhenemisen laittamatta jättäminen voi altistaa tietoturvariskeille.", - "No feedback found": "", + "No feedback found": "Ei palautetta", "No file selected": "Tiedostoa ei ole valittu", - "No files in this knowledge base.": "", + "No files in this knowledge base.": "Tässä tietokannassa ei ole tiedostoja.", "No functions found": "Funktioita ei löytynyt", "No groups with access, add a group to grant access": "Ei ryhmiä, joilla on pääsy, lisää ryhmä antaaksesi pääsyn", "No HTML, CSS, or JavaScript content found.": "HTML-, CSS- tai JavaScript-sisältöä ei löytynyt.", "No inference engine with management support found": "", - "No knowledge bases found.": "", + "No knowledge bases found.": "Tietokantoja ei löytynyt.", "No knowledge found": "Tietoa ei löytynyt", "No memories to clear": "Ei muistia tyhjennettäväksi", "No model IDs": "Ei mallitunnuksia", @@ -1186,7 +1186,7 @@ "No models selected": "Malleja ei ole valittu", "No Notes": "Ei muistiinpanoja", "No notes found": "Muistiinpanoja ei löytynyt", - "No one": "", + "No one": "Kukaan", "No pinned messages": "Ei kiinnitettyjä viestejä", "No prompts found": "Kehoitteita ei löytynyt", "No results": "Ei tuloksia", @@ -1199,7 +1199,7 @@ "No users were found.": "Käyttäjiä ei löytynyt.", "No valves": "Ei venttiileitä", "No valves to update": "Ei venttiileitä päivitettäväksi", - "No webhooks yet": "", + "No webhooks yet": "Ei vielä webhookeja", "Node Ids": "Node id:t", "None": "Ei mikään", "Not factually correct": "Ei faktuaalisesti oikein", @@ -1239,7 +1239,7 @@ "Only invited users can access": "Vain kutsutut jäsenet voivat päästä", "Only markdown files are allowed": "Vain markdown tiedostot ovat sallittuja", "Only select users and groups with permission can access": "Vain valitut käyttäjät ja ryhmät, joilla on käyttöoikeus, pääsevät käyttämään", - "Only sync new/updated chats": "", + "Only sync new/updated chats": "Synkronoi vain uudet/päivitetyt keskustelut", "Oops! Looks like the URL is invalid. Please double-check and try again.": "Hups! Näyttää siltä, että verkko-osoite on virheellinen. Tarkista se ja yritä uudelleen.", "Oops! There are files still uploading. Please wait for the upload to complete.": "Hups! Tiedostoja on vielä ladattavana. Odota, että lataus on valmis.", "Oops! There was an error in the previous response.": "Hups! Edellisessä vastauksessa oli virhe.", @@ -1256,7 +1256,7 @@ "Open WebUI can use tools provided by any OpenAPI server.": "Open WebUI voi käyttää minkä tahansa OpenAPI-palvelimen tarjoamia työkaluja.", "Open WebUI uses faster-whisper internally.": "Open WebUI käyttää faster-whisperia sisäisesti.", "Open WebUI uses SpeechT5 and CMU Arctic speaker embeddings.": "Open WebUI käyttää SpeechT5:tä ja CMU Arctic -kaiuttimen upotuksia.", - "Open WebUI version": "", + "Open WebUI version": "Open WebUI versio", "Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "Open WebUI -versio (v{{OPEN_WEBUI_VERSION}}) on alempi kuin vaadittu versio (v{{REQUIRED_VERSION}})", "OpenAI": "OpenAI", "OpenAI API": "OpenAI API", @@ -1281,8 +1281,8 @@ "page": "sivu", "Paginate": "Sivutus", "Parameters": "Parametrit", - "Parent message not found": "", - "Participate in community leaderboards and evaluations! Syncing aggregated usage stats helps drive research and improvements to Open WebUI. Your privacy is paramount: no message content is ever shared.": "", + "Parent message not found": "Ylätason viestiä ei löytynyt", + "Participate in community leaderboards and evaluations! Syncing aggregated usage stats helps drive research and improvements to Open WebUI. Your privacy is paramount: no message content is ever shared.": "Osallistu yhteisön tulostaulukoihin ja arviointeihin! Koottujen käyttötilastojen synkronointi auttaa edistämään Open WebUI:n tutkimuksia ja parannuksia. Tietosuojasi on ensiarvoisen tärkeää: viestien sisältöä ei koskaan jaeta.", "Password": "Salasana", "Passwords do not match.": "Salasanat eivät täsmää", "Paste Large Text as File": "Liitä suuri teksti tiedostona", @@ -1308,7 +1308,7 @@ "Pipe": "Putki", "Pipeline deleted successfully": "Putki poistettu onnistuneesti", "Pipeline downloaded successfully": "Putki ladattu onnistuneesti", - "Pipelines": "", + "Pipelines": "Putkistot", "Pipelines are a plugin system with arbitrary code execution —": "Pipelines on liitännäisjärjestelmä, jossa voidaan suorittaa mielivaltaista koodia —", "Pipelines Not Detected": "Putkistoja ei havaittu", "Pipelines Valves": "Putkistojen venttiilit", @@ -1371,8 +1371,8 @@ "Read": "Lue", "Read Aloud": "Lue ääneen", "Read more →": "Lue lisää →", - "Read Only": "", - "Read-Only Access": "", + "Read Only": "Vain luku", + "Read-Only Access": "Vain lukuoikeus", "Reason": "Päättely", "Reasoning Effort": "Päättelyn määrä", "Reasoning Tags": "Päättely tagit", @@ -1545,7 +1545,7 @@ "Sets the stop sequences to use. When this pattern is encountered, the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.": "Määrittää käytettävät lopetussekvenssit. Kun tämä kuvio havaitaan, LLM lopettaa tekstin tuottamisen ja palauttaa. Useita lopetuskuvioita voidaan asettaa määrittämällä useita erillisiä lopetusparametreja mallitiedostoon.", "Setting": "Asetus", "Settings": "Asetukset", - "Settings Permissions": "", + "Settings Permissions": "Asetuksien käyttöoikeudet", "Settings saved successfully!": "Asetukset tallennettu onnistuneesti!", "Share": "Jaa", "Share Chat": "Jaa keskustelu", @@ -1556,7 +1556,7 @@ "Show": "Näytä", "Show \"What's New\" modal on login": "Näytä \"Mitä uutta\" -modaali kirjautumisen yhteydessä", "Show Admin Details in Account Pending Overlay": "Näytä ylläpitäjän tiedot odottavan tilin päällä", - "Show Files": "", + "Show Files": "Näytä tiedostot", "Show Formatting Toolbar": "Näytä muotoilupalkki", "Show image preview": "Näytä kuvan esikatselu", "Show Model": "Näytä malli", @@ -1581,7 +1581,7 @@ "Sonar Pro": "Sonar Pro", "Sonar Reasoning": "Sonar Reasoning", "Sonar Reasoning Pro": "Sonar Reasoning Pro", - "Sort": "", + "Sort": "Järjestele", "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Lähde", @@ -1600,7 +1600,7 @@ "STDOUT/STDERR": "STDOUT/STDERR", "Steps": "Askeleet", "Stop": "Pysäytä", - "Stop Download": "", + "Stop Download": "Lopeta lataus", "Stop Generating": "Lopeta generointi", "Stop Sequence": "Lopetussekvenssi", "Stream Chat Response": "Streamaa keskusteluvastaus", @@ -1621,14 +1621,14 @@ "Support": "Tuki", "Support this plugin:": "Tue tätä lisäosaa:", "Supported MIME Types": "Tuetut MIME-tyypit", - "Sync": "", - "Sync Complete!": "", + "Sync": "Synkronoi", + "Sync Complete!": "Synkronointi valmis!", "Sync directory": "Synkronoitu hakemisto", - "Sync Failed": "", - "Sync Usage Stats": "", - "Syncing stats...": "", - "Syncing...": "", - "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", + "Sync Failed": "Synkronointi epäonnistui", + "Sync Usage Stats": "Synkronoinnin käyttötilastot", + "Syncing stats...": "Synkronoidaan tilastoja...", + "Syncing...": "Synkronoidaan...", + "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synkronoi vain keskustelut, joihin on tehty päivityksiä viimeisen synkronoinnin aikaleiman jälkeen. Poista käytöstä synkronoidaksesi kaikki keskustelut uudelleen.", "System": "Järjestelmä", "System Instructions": "Järjestelmäohjeet", "System Prompt": "Järjestelmäkehote", @@ -1673,7 +1673,7 @@ "The Weight of BM25 Hybrid Search. 0 more semantic, 1 more lexical. Default 0.5": "", "The width in pixels to compress images to. Leave empty for no compression.": "Leveys pikseleinä, johon kuvat pakataan. Jätä tyhjäksi, jos et halua pakkausta.", "Theme": "Teema", - "There was an error syncing your stats. Please try again.": "", + "There was an error syncing your stats. Please try again.": "Tilastojen synkronoinnissa tapahtui virhe. Yritä uudelleen.", "Thinking...": "Ajattelee...", "This action cannot be undone. Do you wish to continue?": "Tätä toimintoa ei voi peruuttaa. Haluatko jatkaa?", "This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "Tämä kanava on luotiin {{createdAt}}. Tämä on {{channelName}} kanavan alku.", @@ -1702,7 +1702,7 @@ "Tika": "Tika", "Tika Server URL required.": "Tika palvelimen verkko-osoite vaaditaan.", "Tiktoken": "Tiktoken", - "Timeout": "", + "Timeout": "Aikakatkaisu", "Title": "Otsikko", "Title Auto-Generation": "Otsikon automaattinen luonti", "Title cannot be an empty string.": "Otsikko ei voi olla tyhjä merkkijono.", @@ -1787,7 +1787,7 @@ "Upload Pipeline": "Lataa putki", "Upload Progress": "Latauksen edistyminen", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Latauksen edistyminen: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", - "Uploaded files or images": "", + "Uploaded files or images": "Ladatut tiedostot tai kuvat", "Uploading file...": "Ladataan tiedostoa...", "URL": "URL", "URL is required": "URL vaaditaan", @@ -1805,8 +1805,8 @@ "User Groups": "Käyttäjäryhmät", "User location successfully retrieved.": "Käyttäjän sijainti haettu onnistuneesti.", "User menu": "Käyttäjävalikko", - "User ratings (thumbs up/down)": "", - "User Status": "", + "User ratings (thumbs up/down)": "Käyttäjien arviot (peukku ylös/alas)", + "User Status": "Käyttäjän tila", "User Webhooks": "Käyttäjän Webhook:it", "Username": "Käyttäjätunnus", "users": "käyttäjät", @@ -1847,10 +1847,10 @@ "Web Search Engine": "Hakukoneet", "Web Search in Chat": "Verkkohaku keskustelussa", "Web Search Query Generation": "Verkkohakukyselyn luonti", - "Webhook Name": "", + "Webhook Name": "Webhook nimi", "Webhook URL": "Webhook verkko-osoite", - "Webhooks": "", - "Webpage URLs": "", + "Webhooks": "Webhookit", + "Webpage URLs": "Verkkosivujen verkko-osoitteet", "WebUI Settings": "WebUI-asetukset", "WebUI URL": "WebUI-osoite", "WebUI will make requests to \"{{url}}\"": "WebUI lähettää pyyntöjä osoitteeseen \"{{url}}\"", @@ -1858,15 +1858,15 @@ "WebUI will make requests to \"{{url}}/chat/completions\"": "WebUI lähettää pyyntöjä osoitteeseen \"{{url}}/chat/completions\"", "What are you trying to achieve?": "Mitä yrität saavuttaa?", "What are you working on?": "Mitä olet työskentelemässä?", - "What is NOT shared:": "", - "What is shared:": "", + "What is NOT shared:": "Mitä EI jaeta:", + "What is shared:": "Mitä jaetaan:", "What's New in": "Mitä uutta", "What's on your mind?": "Mitä ajattelet?", "When enabled, the model will respond to each chat message in real-time, generating a response as soon as the user sends a message. This mode is useful for live chat applications, but may impact performance on slower hardware.": "Kun käytössä, malli vastaa jokaiseen chatviestiin reaaliajassa, tuottaen vastauksen heti kun käyttäjä lähettää viestin. Tämä tila on hyödyllinen reaaliaikaisissa chat-sovelluksissa, mutta voi vaikuttaa suorituskykyyn hitaammilla laitteistoilla.", "wherever you are": "missä tahansa oletkin", "Whether to paginate the output. Each page will be separated by a horizontal rule and page number. Defaults to False.": "Sivutetaanko tuloste. Jokainen sivu erotetaan toisistaan vaakasuoralla viivalla ja sivunumerolla. Oletusarvo ei käytössä.", "Whisper (Local)": "Whisper (paikallinen)", - "Who can share to this group": "", + "Who can share to this group": "Ketkä voivat jakaa tähän ryhmään", "Why?": "Miksi?", "Widescreen Mode": "Laajakuvatila", "Width": "Leveys", @@ -1891,12 +1891,12 @@ "You can only chat with a maximum of {{maxCount}} file(s) at a time.": "Voit keskustella enintään {{maxCount}} tiedoston kanssa kerralla.", "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Voit personoida vuorovaikutustasi LLM-ohjelmien kanssa lisäämällä muistoja 'Hallitse'-painikkeen kautta, jolloin ne ovat hyödyllisempiä ja räätälöityjä sinua varten.", "You cannot upload an empty file.": "Et voi ladata tyhjää tiedostoa.", - "You do not have permission to edit this model": "", - "You do not have permission to edit this prompt.": "", - "You do not have permission to save this prompt.": "", + "You do not have permission to edit this model": "Sinulla ei ole oikeuksia muokata tätä mallinetta", + "You do not have permission to edit this prompt.": "Sinulla ei ole oikeuksia muokata tätä kehotetta.", + "You do not have permission to save this prompt.": "Sinulla ei ole oikeuksia tallentaa tätä kehotetta.", "You do not have permission to send messages in this channel.": "Sinulla ei ole oikeuksia lähettää viestejä tähän kanavaan.", "You do not have permission to send messages in this thread.": "Sinulla ei ole oikeuksia lähettää viestejä tähän ketjuun.", - "You do not have permission to upload files to this knowledge base.": "", + "You do not have permission to upload files to this knowledge base.": "Sinulla ei ole oikeuksia ladata tiedostoja tähän tietokantaan.", "You do not have permission to upload files.": "Sinulla ei ole lupaa ladata tiedostoja.", "You have no archived conversations.": "Sinulla ei ole arkistoituja keskusteluja.", "You have shared this chat": "Olet jakanut tämän keskustelun", @@ -1905,8 +1905,8 @@ "Your Account": "Tilisi", "Your account status is currently pending activation.": "Tilisi tila on tällä hetkellä odottaa aktivointia.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Koko panoksesi menee suoraan lisäosan kehittäjälle; Open WebUI ei pidätä prosenttiosuutta. Valittu rahoitusalusta voi kuitenkin periä omia maksujaan.", - "Your message text or inputs": "", - "Your usage stats have been successfully synced.": "", + "Your message text or inputs": "Viestisi teksti tai syöteet", + "Your usage stats have been successfully synced.": "Käyttötilastosi on synkronoitu onnistuneesti.", "YouTube": "YouTube", "Youtube Language": "Youtube kieli", "Youtube Proxy URL": "Youtube-välityspalvelimen verkko-osoite" From 26e95f2a927f90793a99ad2371271beb364d019d Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 17 Jan 2026 18:39:24 +0100 Subject: [PATCH 006/120] fix-csv-export (#20688) --- .../chat/Messages/Markdown/MarkdownTokens.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte b/src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte index bf8ad99931..d22cd2e7dc 100644 --- a/src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte +++ b/src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte @@ -53,16 +53,16 @@ const exportTableToCSVHandler = (token, tokenIdx = 0) => { console.log('Exporting table to CSV'); - // Extract header row text and escape for CSV. - const header = token.header.map((headerCell) => `"${headerCell.text.replace(/"/g, '""')}"`); + // Extract header row text, decode HTML entities, and escape for CSV. + const header = token.header.map((headerCell) => `"${decode(headerCell.text).replace(/"/g, '""')}"`); // Create an array for rows that will hold the mapped cell text. const rows = token.rows.map((row) => row.map((cell) => { // Map tokens into a single text const cellContent = cell.tokens.map((token) => token.text).join(''); - // Escape double quotes and wrap the content in double quotes - return `"${cellContent.replace(/"/g, '""')}"`; + // Decode HTML entities and escape double quotes, wrap in double quotes + return `"${decode(cellContent).replace(/"/g, '""')}"`; }) ); From 409f565f09bd554dd211f63c75aba3f2044e714d Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 17 Jan 2026 21:41:48 +0400 Subject: [PATCH 007/120] refac --- backend/open_webui/routers/files.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/open_webui/routers/files.py b/backend/open_webui/routers/files.py index e3dd63525a..130d0486bb 100644 --- a/backend/open_webui/routers/files.py +++ b/backend/open_webui/routers/files.py @@ -332,6 +332,8 @@ def upload_file_handler( detail=ERROR_MESSAGES.DEFAULT("Error uploading file"), ) + except HTTPException as e: + raise e except Exception as e: log.exception(e) raise HTTPException( From 716f2986b9da787103668af1c96a9a9303424a6a Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 17 Jan 2026 18:44:32 +0100 Subject: [PATCH 008/120] dep bump (#20735) --- backend/requirements-min.txt | 6 +++--- backend/requirements.txt | 24 ++++++++++++------------ pyproject.toml | 24 ++++++++++++------------ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/backend/requirements-min.txt b/backend/requirements-min.txt index 115d1bc92f..412dae1f3f 100644 --- a/backend/requirements-min.txt +++ b/backend/requirements-min.txt @@ -25,8 +25,8 @@ httpx[socks,http2,zstd,cli,brotli]==0.28.1 starsessions[redis]==2.2.1 sqlalchemy==2.0.45 -alembic==1.17.2 -peewee==3.18.3 +alembic==1.18.1 +peewee==3.19.0 peewee-migrate==1.14.3 pycrdt==0.12.44 @@ -41,7 +41,7 @@ asgiref==3.11.0 mcp==1.25.0 openai -langchain==1.2.0 +langchain==1.2.4 langchain-community==0.4.1 langchain-classic==1.0.1 langchain-text-splitters==1.1.0 diff --git a/backend/requirements.txt b/backend/requirements.txt index 51f0a8a1ae..7fa7d9ee14 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -23,8 +23,8 @@ starsessions[redis]==2.2.1 python-mimeparse==2.0.0 sqlalchemy==2.0.45 -alembic==1.17.2 -peewee==3.18.3 +alembic==1.18.1 +peewee==3.19.0 peewee-migrate==1.14.3 pycrdt==0.12.44 @@ -42,19 +42,19 @@ mcp==1.25.0 openai anthropic -google-genai==1.56.0 +google-genai==1.59.0 -langchain==1.2.0 +langchain==1.2.4 langchain-community==0.4.1 langchain-classic==1.0.1 langchain-text-splitters==1.1.0 fake-useragent==2.2.0 -chromadb==1.4.0 +chromadb==1.4.1 weaviate-client==4.19.2 opensearch-py==3.1.0 -transformers==4.57.3 +transformers==4.57.6 sentence-transformers==5.2.0 accelerate pyarrow==20.0.0 # fix: pin pyarrow version to 20 for rpi compatibility #15897 @@ -62,12 +62,12 @@ einops==0.8.1 ftfy==6.3.1 chardet==5.2.0 -pypdf==6.5.0 +pypdf==6.6.0 fpdf2==2.8.5 pymdown-extensions==10.20 docx2txt==0.9 python-pptx==1.0.2 -unstructured==0.18.24 +unstructured==0.18.27 msoffcrypto-tool==5.4.2 nltk==3.9.2 Markdown==3.10 @@ -98,7 +98,7 @@ ddgs==9.10.0 azure-ai-documentintelligence==1.0.2 azure-identity==1.25.1 -azure-storage-blob==12.27.1 +azure-storage-blob==12.28.0 azure-search-documents==11.6.0 ## Google Drive @@ -107,7 +107,7 @@ google-auth-httplib2 google-auth-oauthlib googleapis-common-protos==1.72.0 -google-cloud-storage==3.7.0 +google-cloud-storage==3.8.0 ## Databases pymongo @@ -115,7 +115,7 @@ psycopg2-binary==2.9.11 pgvector==0.4.2 PyMySQL==1.1.2 -boto3==1.42.21 +boto3==1.42.29 pymilvus==2.6.6 qdrant-client==1.16.2 @@ -138,7 +138,7 @@ pytest-docker~=3.2.5 ldap3==2.9.1 ## Firecrawl -firecrawl-py==4.12.0 +firecrawl-py==4.13.0 ## Trace opentelemetry-api==1.39.1 diff --git a/pyproject.toml b/pyproject.toml index 893e1d018a..b7df0dd78e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,8 +31,8 @@ dependencies = [ "python-mimeparse==2.0.0", "sqlalchemy==2.0.45", - "alembic==1.17.2", - "peewee==3.18.3", + "alembic==1.18.1", + "peewee==3.19.0", "peewee-migrate==1.14.3", "pycrdt==0.12.44", @@ -49,20 +49,20 @@ dependencies = [ "openai", "anthropic", - "google-genai==1.56.0", + "google-genai==1.59.0", - "langchain==1.2.0", + "langchain==1.2.4", "langchain-community==0.4.1", "langchain-classic==1.0.1", "langchain-text-splitters==1.1.0", "fake-useragent==2.2.0", - "chromadb==1.4.0", + "chromadb==1.4.1", "opensearch-py==3.1.0", "PyMySQL==1.1.2", - "boto3==1.42.21", + "boto3==1.42.29", - "transformers==4.57.3", + "transformers==4.57.6", "sentence-transformers==5.2.0", "accelerate", "pyarrow==20.0.0", # fix: pin pyarrow version to 20 for rpi compatibility #15897 @@ -70,12 +70,12 @@ dependencies = [ "ftfy==6.3.1", "chardet==5.2.0", - "pypdf==6.5.0", + "pypdf==6.6.0", "fpdf2==2.8.5", "pymdown-extensions==10.20", "docx2txt==0.9", "python-pptx==1.0.2", - "unstructured==0.18.24", + "unstructured==0.18.27", "msoffcrypto-tool==5.4.2", "nltk==3.9.2", "Markdown==3.10", @@ -110,10 +110,10 @@ dependencies = [ "google-auth-oauthlib", "googleapis-common-protos==1.72.0", - "google-cloud-storage==3.7.0", + "google-cloud-storage==3.8.0", "azure-identity==1.25.1", - "azure-storage-blob==12.27.1", + "azure-storage-blob==12.28.0", "ldap3==2.9.1", ] @@ -156,7 +156,7 @@ all = [ "oracledb==3.4.1", "colbert-ai==0.2.22", - "firecrawl-py==4.12.0", + "firecrawl-py==4.13.0", "azure-search-documents==11.6.0", ] From 9d642f63542cccae6fd7a4c888344dd2773f2f2f Mon Sep 17 00:00:00 2001 From: rohithshenoy <249723738+rohithshenoy@users.noreply.github.com> Date: Sat, 17 Jan 2026 23:18:52 +0530 Subject: [PATCH 009/120] Added support for connecting to self hosted weaviate deployments using connect_to_custom replacing connect_to_local, which is better suited for cases where HTTP and GRPC are hosted on different ingresses. (#20620) Co-authored-by: Tim Baek Co-authored-by: joaoback <156559121+joaoback@users.noreply.github.com> Co-authored-by: rohithshenoyg@gmail.com --- backend/open_webui/config.py | 4 ++++ .../open_webui/retrieval/vector/dbs/weaviate.py | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index dab5b6cfe8..ed7df33ed2 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -2246,9 +2246,13 @@ ENABLE_QDRANT_MULTITENANCY_MODE = ( QDRANT_COLLECTION_PREFIX = os.environ.get("QDRANT_COLLECTION_PREFIX", "open-webui") WEAVIATE_HTTP_HOST = os.environ.get("WEAVIATE_HTTP_HOST", "") +WEAVIATE_GRPC_HOST = os.environ.get("WEAVIATE_GRPC_HOST", "") WEAVIATE_HTTP_PORT = int(os.environ.get("WEAVIATE_HTTP_PORT", "8080")) WEAVIATE_GRPC_PORT = int(os.environ.get("WEAVIATE_GRPC_PORT", "50051")) WEAVIATE_API_KEY = os.environ.get("WEAVIATE_API_KEY") +WEAVIATE_HTTP_SECURE = os.environ.get("WEAVIATE_HTTP_SECURE", "false").lower() == "true" +WEAVIATE_GRPC_SECURE = os.environ.get("WEAVIATE_GRPC_SECURE", "false").lower() == "true" +WEAVIATE_SKIP_INIT_CHECKS = os.environ.get("WEAVIATE_SKIP_INIT_CHECKS", "false").lower() == "true" # OpenSearch OPENSEARCH_URI = os.environ.get("OPENSEARCH_URI", "https://localhost:9200") diff --git a/backend/open_webui/retrieval/vector/dbs/weaviate.py b/backend/open_webui/retrieval/vector/dbs/weaviate.py index d204e8293a..dcc648c788 100644 --- a/backend/open_webui/retrieval/vector/dbs/weaviate.py +++ b/backend/open_webui/retrieval/vector/dbs/weaviate.py @@ -12,9 +12,13 @@ from open_webui.retrieval.vector.main import ( from open_webui.retrieval.vector.utils import process_metadata from open_webui.config import ( WEAVIATE_HTTP_HOST, + WEAVIATE_GRPC_HOST, WEAVIATE_HTTP_PORT, WEAVIATE_GRPC_PORT, WEAVIATE_API_KEY, + WEAVIATE_HTTP_SECURE, + WEAVIATE_GRPC_SECURE, + WEAVIATE_SKIP_INIT_CHECKS, ) @@ -52,9 +56,13 @@ class WeaviateClient(VectorDBBase): try: # Build connection parameters connection_params = { - "host": WEAVIATE_HTTP_HOST, - "port": WEAVIATE_HTTP_PORT, + "http_host": WEAVIATE_HTTP_HOST, + "http_port": WEAVIATE_HTTP_PORT, + "http_secure": WEAVIATE_HTTP_SECURE, + "grpc_host": WEAVIATE_GRPC_HOST, "grpc_port": WEAVIATE_GRPC_PORT, + "grpc_secure": WEAVIATE_GRPC_SECURE, + "skip_init_checks": WEAVIATE_SKIP_INIT_CHECKS, } # Only add auth_credentials if WEAVIATE_API_KEY exists and is not empty @@ -63,7 +71,7 @@ class WeaviateClient(VectorDBBase): weaviate.classes.init.Auth.api_key(WEAVIATE_API_KEY) ) - self.client = weaviate.connect_to_local(**connection_params) + self.client = weaviate.connect_to_custom(**connection_params) self.client.connect() except Exception as e: raise ConnectionError(f"Failed to connect to Weaviate: {e}") from e From 5cfb7a08cbde5d39aaf4097b849a80da87c30d66 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 17 Jan 2026 21:52:12 +0400 Subject: [PATCH 010/120] refac --- backend/open_webui/env.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index ff48a3abfe..aeba69b480 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -673,7 +673,11 @@ WEBSOCKET_SERVER_LOGGING = ( os.environ.get("WEBSOCKET_SERVER_LOGGING", "False").lower() == "true" ) WEBSOCKET_SERVER_ENGINEIO_LOGGING = ( - os.environ.get("WEBSOCKET_SERVER_LOGGING", "False").lower() == "true" + os.environ.get( + "WEBSOCKET_SERVER_ENGINEIO_LOGGING", + os.environ.get("WEBSOCKET_SERVER_LOGGING", "False"), + ).lower() + == "true" ) WEBSOCKET_SERVER_PING_TIMEOUT = os.environ.get("WEBSOCKET_SERVER_PING_TIMEOUT", "20") try: From e9926694c30cdccafe8a3e3c0cb49050af210651 Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:42:33 -0500 Subject: [PATCH 011/120] fix: add username search support to workspace and admin pages (#20780) This fix restores and extends the username/email search functionality across workspace pages that was originally added in PR #14002. The issue was that: 1. The backend search functions for Models and Knowledge only searched `User.name` and `User.email`, but not `User.username` 2. The Functions admin page lacked user search entirely Changes made: Added User.username to backend search conditions for Models and Knowledge pages Added complete user search (name, email, username) to the Functions admin page client-side filter --- backend/open_webui/models/knowledge.py | 3 +++ backend/open_webui/models/models.py | 3 +++ src/lib/components/admin/Functions.svelte | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/models/knowledge.py b/backend/open_webui/models/knowledge.py index 7f99f828c7..8612842015 100644 --- a/backend/open_webui/models/knowledge.py +++ b/backend/open_webui/models/knowledge.py @@ -229,6 +229,9 @@ class KnowledgeTable: or_( Knowledge.name.ilike(f"%{query_key}%"), Knowledge.description.ilike(f"%{query_key}%"), + User.name.ilike(f"%{query_key}%"), + User.email.ilike(f"%{query_key}%"), + User.username.ilike(f"%{query_key}%"), ) ) diff --git a/backend/open_webui/models/models.py b/backend/open_webui/models/models.py index 5457413f0d..42ae2e8ddc 100755 --- a/backend/open_webui/models/models.py +++ b/backend/open_webui/models/models.py @@ -294,6 +294,9 @@ class ModelsTable: or_( Model.name.ilike(f"%{query_key}%"), Model.base_model_id.ilike(f"%{query_key}%"), + User.name.ilike(f"%{query_key}%"), + User.email.ilike(f"%{query_key}%"), + User.username.ilike(f"%{query_key}%"), ) ) diff --git a/src/lib/components/admin/Functions.svelte b/src/lib/components/admin/Functions.svelte index 67a1fbbdfd..06de4576b2 100644 --- a/src/lib/components/admin/Functions.svelte +++ b/src/lib/components/admin/Functions.svelte @@ -86,7 +86,10 @@ (selectedType !== '' ? f.type === selectedType : true) && (query === '' || f.name.toLowerCase().includes(query.toLowerCase()) || - f.id.toLowerCase().includes(query.toLowerCase())) && + f.id.toLowerCase().includes(query.toLowerCase()) || + (f.user?.name || '').toLowerCase().includes(query.toLowerCase()) || + (f.user?.email || '').toLowerCase().includes(query.toLowerCase()) || + (f.user?.username || '').toLowerCase().includes(query.toLowerCase())) && (viewOption === '' || (viewOption === 'created' && f.user_id === $user?.id) || (viewOption === 'shared' && f.user_id !== $user?.id)) From 7a42efec53e50e102680d8b77d6c23c141182370 Mon Sep 17 00:00:00 2001 From: Toru Suzuki <35589743+zolgear@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:42:58 +0900 Subject: [PATCH 012/120] `i18n: Update translation.json (ja-JP)` (#20772) * i18n: Update Japanese translation * i18n: Update Japanese translation --------- Co-authored-by: Tim Baek Co-authored-by: joaoback <156559121+joaoback@users.noreply.github.com> --- src/lib/i18n/locales/ja-JP/translation.json | 168 ++++++++++---------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index 641c92f282..76f5d9e934 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -16,9 +16,9 @@ "{{COUNT}} hidden lines": "{{COUNT}} 行が非表示", "{{COUNT}} Replies": "{{COUNT}} 件の返信", "{{COUNT}} Rows": "", - "{{COUNT}} Sources": "", + "{{COUNT}} Sources": "{{COUNT}} 件のソース", "{{COUNT}} words": "{{COUNT}} 語", - "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", + "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} のダウンロードがキャンセルされました", "{{NAMES}} reacted with {{REACTION}}": "", "{{user}}'s Chats": "{{user}} のチャット", @@ -32,7 +32,7 @@ "A task model is used when performing tasks such as generating titles for chats and web search queries": "タスクモデルは、チャットやウェブ検索クエリのタイトルの生成などのタスクを実行するときに使用されます", "a user": "ユーザー", "About": "概要", - "Accept Autocomplete Generation\nJump to Prompt Variable": "", + "Accept Autocomplete Generation\nJump to Prompt Variable": "オートコンプリートの提案を受け入れる\nプロンプト変数へ移動", "Access": "アクセス", "Access Control": "アクセス制御", "Accessible to all users": "すべてのユーザーにアクセス可能", @@ -57,7 +57,7 @@ "Add Content": "コンテンツを追加", "Add content here": "ここへコンテンツを追加", "Add Custom Parameter": "カスタムパラメータを追加", - "Add Custom Prompt": "", + "Add Custom Prompt": "カスタムプロンプトを追加", "Add Details": "より詳しく", "Add Files": "ファイルを追加", "Add Member": "", @@ -78,7 +78,7 @@ "Adjusting these settings will apply changes universally to all users.": "これらの設定を変更すると、すべてのユーザーに変更が適用されます。", "admin": "管理者", "Admin": "管理者", - "Admin Contact Email": "", + "Admin Contact Email": "管理者の連絡先メールアドレス", "Admin Panel": "管理者パネル", "Admin Settings": "管理者設定", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理者は全てのツールにアクセスできます。ユーザーからはワークスペースのモデルごとに割り当てられたツールのみ使用可能です。", @@ -100,13 +100,13 @@ "Allow Chat Share": "チャットの共有を許可", "Allow Chat System Prompt": "チャットシステムプロンプトを許可", "Allow Chat Valves": "チャットバルブを許可", - "Allow Continue Response": "", - "Allow Delete Messages": "", + "Allow Continue Response": "続きの応答を許可", + "Allow Delete Messages": "メッセージの削除を許可", "Allow File Upload": "ファイルのアップロードを許可", "Allow Multiple Models in Chat": "チャットで複数のモデルを許可", "Allow non-local voices": "ローカル以外のボイスを許可", - "Allow Rate Response": "", - "Allow Regenerate Response": "", + "Allow Rate Response": "応答の評価を許可", + "Allow Regenerate Response": "再生成を許可", "Allow Speech to Text": "音声をテキストに変換を許可", "Allow Temporary Chat": "一時的なチャットを許可", "Allow Text to Speech": "テキストを音声に変換を許可", @@ -131,7 +131,7 @@ "and {{COUNT}} more": "および{{COUNT}}件", "and create a new shared link.": "そして、新しい共有リンクを作成します。", "Android": "", - "Anyone": "", + "Anyone": "全員", "API Base URL": "API ベース URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab MarkerサービスのAPIベースURL。デフォルトは https://www.datalab.to/api/v1/marker です", "API Key": "API キー", @@ -164,7 +164,7 @@ "Ask a question": "質問する", "Assistant": "アシスタント", "Async Embedding Processing": "", - "Attach File From Knowledge": "", + "Attach File From Knowledge": "ナレッジからファイルを添付", "Attach Knowledge": "ナレッジを追加", "Attach Notes": "ノートを追加", "Attach Webpage": "ウェブページを追加", @@ -186,7 +186,7 @@ "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111のAuthを入力", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 ベース URL", "AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 ベース URL が必要です。", - "Automatically inject system tools in native function calling mode (e.g., timestamps, memory, chat history, notes, etc.)": "", + "Automatically inject system tools in native function calling mode (e.g., timestamps, memory, chat history, notes, etc.)": "ネイティブの関数呼び出しモードにおいて、システムツール(例: タイムスタンプ、メモリー、チャット履歴、ノートなど)を自動的に注入します", "Available list": "利用可能リスト", "Available Tools": "利用可能ツール", "available users": "利用可能なユーザー", @@ -216,7 +216,7 @@ "Boosting or penalizing specific tokens for constrained responses. Bias values will be clamped between -100 and 100 (inclusive). (Default: none)": "特定のトークンの強調またはペナルティを適用します。バイアス値は-100から100(包括的)にクランプされます。(デフォルト:なし)", "Brave": "", "Brave Search API Key": "Brave Search APIキー", - "Builtin Tools": "", + "Builtin Tools": "組み込みツール", "Bullet List": "箇条書きリスト", "Button ID": "ボタンID", "Button Label": "ボタンラベル", @@ -273,7 +273,7 @@ "Citations": "引用", "Clear memory": "メモリをクリア", "Clear Memory": "メモリをクリア", - "Clear status": "", + "Clear status": "ステータスをクリア", "click here": "ここをクリック", "Click here for filter guides.": "フィルターガイドはこちらをクリックしてください。", "Click here for help.": "ヘルプについてはここをクリックしてください。", @@ -295,7 +295,7 @@ "Close Banner": "バナーを閉じる", "Close Configure Connection Modal": "接続設定モーダルを閉じる", "Close modal": "モーダルを閉じる", - "Close Modal": "", + "Close Modal": "モーダルを閉じる", "Close settings modal": "設定モーダルを閉じる", "Close Sidebar": "サイドバーを閉じる", "cloud": "", @@ -362,8 +362,8 @@ "Copied to clipboard": "クリップボードにコピーしました。", "Copy": "コピー", "Copy Formatted Text": "フォーマットされたテキストをコピー", - "Copy Last Code Block": "", - "Copy Last Response": "", + "Copy Last Code Block": "直前のコードブロックをコピー", + "Copy Last Response": "直前の応答をコピー", "Copy link": "リンクをコピー", "Copy Link": "リンクをコピー", "Copy to clipboard": "クリップボードにコピー", @@ -384,7 +384,7 @@ "Create Model": "", "Create new key": "新しいキーを作成", "Create new secret key": "新しいシークレットキーを作成", - "Create note": "", + "Create note": "ノートを作成", "Create Note": "ノートを作成", "Create your first note by clicking on the plus button below.": "プラスボタンをクリックして最初のノートを作成します。", "Created at": "作成日時", @@ -415,9 +415,9 @@ "Default (SentenceTransformers)": "デフォルト (SentenceTransformers)", "Default action buttons will be used.": "デフォルトのアクションボタンが使用されます", "Default description enabled": "デフォルト説明が有効です", - "Default Features": "", + "Default Features": "デフォルト機能", "Default Filters": "", - "Default Group": "", + "Default Group": "デフォルトグループ", "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "デフォルトモードは、実行前にツールを一度呼び出すことで、より広範なモデルで動作します。ネイティブモードは、モデルの組み込みのツール呼び出し機能を活用しますが、モデルがこの機能をサポートしている必要があります。", "Default Model": "デフォルトモデル", "Default model updated": "デフォルトモデルが更新されました", @@ -480,12 +480,12 @@ "Discover, download, and explore model presets": "モデルプリセットを探してダウンロードする", "Discussion channel where access is based on groups and permissions": "", "Display": "表示", - "Display chat title in tab": "", + "Display chat title in tab": "チャットのタイトルをタブに表示", "Display Emoji in Call": "コールで絵文字を表示", "Display Multi-model Responses in Tabs": "複数モデルの応答をタブで表示する", "Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示", "Displays citations in the response": "応答に引用を表示", - "Displays status updates (e.g., web search progress) in the response": "", + "Displays status updates (e.g., web search progress) in the response": "レスポンスにステータスの更新(例: ウェブ検索の進行状況)を表示します", "Dive into knowledge": "知識に飛び込む", "Do not install functions from sources you do not fully trust.": "信頼できないソースからFunctionをインストールしないでください。", "Do not install tools from sources you do not fully trust.": "信頼できないソースからツールをインストールしないでください。", @@ -521,16 +521,16 @@ "e.g. \"json\" or a JSON schema": "例: \"json\" または JSON スキーマ", "e.g. 60": "", "e.g. A filter to remove profanity from text": "例: テキストから不適切な表現を削除するフィルター", - "e.g. about the Roman Empire": "", - "e.g. alloy, echo, shimmer": "", - "e.g. en": "", + "e.g. about the Roman Empire": "例: ローマ帝国について", + "e.g. alloy, echo, shimmer": "例: alloy, echo, shimmer", + "e.g. en": "例: ja", "e.g. My Filter": "", "e.g. My Tools": "", "e.g. my_filter": "", "e.g. my_tools": "", "e.g. pdf, docx, txt": "", - "e.g. Tell me a fun fact": "", - "e.g. Tell me a fun fact about the Roman Empire": "", + "e.g. Tell me a fun fact": "例: 面白い豆知識を教えて", + "e.g. Tell me a fun fact about the Roman Empire": "例: ローマ帝国についての面白い豆知識を教えて", "e.g. Tools for performing various operations": "e.g. 様々な操作を実行するためのツール", "e.g., 3, 4, 5 (leave blank for default)": "e.g. 3, 4, 5 (空白でデフォルト)", "e.g., audio/wav,audio/mpeg,video/* (leave blank for defaults)": "e.g., audio/wav,audio/mpeg,video/* (空白でデフォルト)", @@ -543,7 +543,7 @@ "Edit Default Permissions": "デフォルトの許可を編集", "Edit Folder": "フォルダを編集", "Edit Image": "", - "Edit Last Message": "", + "Edit Last Message": "直前のメッセージを編集", "Edit Memory": "メモリを編集", "Edit User": "ユーザーを編集", "Edit User Group": "ユーザーグループを編集", @@ -559,7 +559,7 @@ "Embedding Batch Size": "埋め込みモデルバッチサイズ", "Embedding Model": "埋め込みモデル", "Embedding Model Engine": "埋め込みモデルエンジン", - "Enable API Keys": "", + "Enable API Keys": "API キーを有効にする", "Enable autocomplete generation for chat messages": "チャットメッセージの自動補完を有効にする", "Enable Code Execution": "コードの実行を有効にする", "Enable Code Interpreter": "コードインタプリタを有効にする", @@ -786,7 +786,7 @@ "File": "ファイル", "File added successfully.": "ファイル追加が成功しました。", "File content updated successfully.": "ファイルコンテンツ追加が成功しました。", - "File Context": "", + "File Context": "ファイルコンテキスト", "File Mode": "ファイルモード", "File not found.": "ファイルが見つかりません。", "File removed successfully.": "ファイル削除が成功しました。", @@ -804,11 +804,11 @@ "Firecrawl API Key": "Firecrawl APIキー", "Firecrawl Timeout (s)": "", "Floating Quick Actions": "フローティング クイックアクション", - "Focus Chat Input": "", + "Focus Chat Input": "チャット入力欄にフォーカス", "Folder": "フォルダー", "Folder Background Image": "フォルダーの背景画像", "Folder deleted successfully": "フォルダー削除が成功しました。", - "Folder Max File Count": "", + "Folder Max File Count": "フォルダー内の最大ファイル数", "Folder Name": "フォルダ名", "Folder name cannot be empty.": "フォルダー名を入力してください。", "Folder name updated successfully": "フォルダー名の変更に成功しました。", @@ -854,7 +854,7 @@ "General": "一般", "Generate": "生成", "Generate an image": "画像を生成", - "Generate Message Pair": "", + "Generate Message Pair": "メッセージペアを生成", "Generated Image": "", "Generating search query": "検索クエリの生成", "Generating...": "生成中...", @@ -942,7 +942,7 @@ "Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "生成されたテキストからのフィードバックに対するアルゴリズムの応答速度を影響します。低い学習率はより遅い調整をもたらし、高い学習率はアルゴリズムをより反応的にします。", "Info": "情報", "Initials": "イニシャル", - "Inject file content into conversation context": "", + "Inject file content into conversation context": "ファイル内容を会話のコンテキストに挿入する", "Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "全文を取り込むことで全体を処理します。複雑な問い合わせの場合に推奨されます。", "Input": "入力", "Input Key (e.g. text, unet_name, steps)": "入力キー", @@ -954,9 +954,9 @@ "Install from Github URL": "Github URLからインストール", "Instant Auto-Send After Voice Transcription": "音声文字変換後に自動送信", "Integration": "連携", - "Integrations": "", + "Integrations": "連携", "Interface": "インターフェース", - "Interface Settings Access": "", + "Interface Settings Access": "インターフェース設定へのアクセス", "Invalid file content": "無効なファイル内容", "Invalid file format.": "無効なファイル形式", "Invalid JSON file": "無効なJSONファイル", @@ -988,7 +988,7 @@ "Key": "キー", "Key is required": "キーは必須です", "Keyboard shortcuts": "キーボードショートカット", - "Keyboard Shortcuts": "", + "Keyboard Shortcuts": "キーボードショートカット", "Knowledge": "ナレッジベース", "Knowledge Access": "ナレッジアクセス", "Knowledge Base": "ナレッジベース", @@ -999,7 +999,7 @@ "Knowledge Name": "ナレッジベースの名前", "Knowledge Public Sharing": "ナレッジベースの公開共有", "Knowledge reset successfully.": "ナレッジベースのリセットに成功しました", - "Knowledge Sharing": "", + "Knowledge Sharing": "ナレッジベースの共有", "Knowledge updated successfully": "ナレッジベースのアップデートに成功しました", "Kokoro.js (Browser)": "Kokoro.js (ブラウザ)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1022,7 +1022,7 @@ "Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "空欄にすると \"{{url}}/api/tags\" エンドポイントからすべてのモデルを読み込みます", "Leave empty to include all models from \"{{url}}/models\" endpoint": "空欄にすると \"{{url}}/models\" エンドポイントからすべてのモデルを読み込みます", "Leave empty to include all models or select specific models": "モデルを選択。空欄にするとすべてのモデルを読み込みます", - "Leave empty to use first admin user": "", + "Leave empty to use first admin user": "空欄で最初の管理者ユーザー", "Leave empty to use the default model (voxtral-mini-latest).": "", "Leave empty to use the default prompt, or enter a custom prompt": "カスタムプロンプトを入力。空欄ならデフォルトプロンプト", "Leave model field empty to use the default model.": "モデル欄を空欄にしてデフォルトモデルを使用", @@ -1066,8 +1066,8 @@ "Max Speakers": "最大話者数", "Max Upload Count": "最大アップロード数", "Max Upload Size": "最大アップロードサイズ", - "Maximum number of files allowed per folder.": "", - "Maximum number of files per folder is {{max}}.": "", + "Maximum number of files allowed per folder.": "1 つのフォルダーに保存できるファイルの最大数を指定します。", + "Maximum number of files per folder is {{max}}.": "フォルダー内のファイル数は最大 {{max}} 件までです。", "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "同時にダウンロードできるモデルは最大 3 つです。後でもう一度お試しください。", "May": "5月", "MBR": "", @@ -1075,9 +1075,9 @@ "MCP support is experimental and its specification changes often, which can lead to incompatibilities. OpenAPI specification support is directly maintained by the Open WebUI team, making it the more reliable option for compatibility.": "", "Medium": "中", "Member removed successfully": "", - "Members": "", + "Members": "メンバー", "Members added successfully": "", - "Memories": "", + "Memories": "メモリー", "Memories accessible by LLMs will be shown here.": "LLM がアクセスできるメモリはここに表示されます。", "Memory": "メモリ", "Memory added successfully": "メモリに追加されました。", @@ -1086,7 +1086,7 @@ "Memory updated successfully": "メモリアップデート成功", "Merge Responses": "応答を統合", "Merged Response": "統合された応答", - "Message": "", + "Message": "メッセージ", "Message counts and response timestamps": "", "Message rating should be enabled to use this feature": "この機能を使用するには、メッセージ評価を有効にする必要があります。", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "リンクを作成した後で送信したメッセージは共有されません。URL を持つユーザーは共有チャットを閲覧できます。", @@ -1134,7 +1134,7 @@ "Models configuration saved successfully": "モデル設定が正常に保存されました", "Models imported successfully": "", "Models Public Sharing": "モデルの公開共有", - "Models Sharing": "", + "Models Sharing": "モデルの共有", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search APIキー", "More": "もっと見る", @@ -1155,7 +1155,7 @@ "New Note": "新しいノート", "New Password": "新しいパスワード", "New Prompt": "新しいプロンプト", - "New Temporary Chat": "", + "New Temporary Chat": "新しい一時的なチャット", "New Tool": "新しいツール", "New Webhook": "", "new-channel": "新しいチャンネル", @@ -1186,16 +1186,16 @@ "No models selected": "モデルが選択されていません", "No Notes": "ノートがありません", "No notes found": "ノートが見つかりません", - "No one": "", + "No one": "誰もいない", "No pinned messages": "", - "No prompts found": "", + "No prompts found": "プロンプトが見つかりません", "No results": "結果が見つかりません", "No results found": "結果が見つかりません", "No search query generated": "検索クエリは生成されません", "No source available": "使用可能なソースがありません", - "No sources found": "", + "No sources found": "ソースが見つかりません", "No suggestion prompts": "提案プロンプトはありません", - "No tools found": "", + "No tools found": "ツールが見つかりません", "No users were found.": "ユーザーが見つかりません。", "No valves": "バルブがありません", "No valves to update": "更新するバルブがありません", @@ -1209,8 +1209,8 @@ "Note deleted successfully": "ノートが正常に削除されました", "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "注意:最小スコアを設定した場合、検索は最小スコア以上のスコアを持つドキュメントのみを返します。", "Notes": "ノート", - "Notes Public Sharing": "", - "Notes Sharing": "", + "Notes Public Sharing": "ノートの公開共有", + "Notes Sharing": "ノートの共有", "Notification Sound": "通知音", "Notification Webhook": "通知Webhook", "Notifications": "デスクトップ通知", @@ -1229,12 +1229,12 @@ "Ollama Version": "Ollama バージョン", "On": "オン", "OneDrive": "", - "Only active when \"Paste Large Text as File\" setting is toggled on.": "", - "Only active when the chat input is in focus and an LLM is generating a response.": "", - "Only active when the chat input is in focus.": "", + "Only active when \"Paste Large Text as File\" setting is toggled on.": "\"大きなテキストをファイルとして貼り付ける\"がオンの場合にのみ有効です。", + "Only active when the chat input is in focus and an LLM is generating a response.": "チャット入力欄にフォーカスがあり、LLMが応答を生成しているときのみ有効です。", + "Only active when the chat input is in focus.": "チャット入力欄にフォーカスがあるときのみ有効です。", "Only alphanumeric characters and hyphens are allowed": "英数字とハイフンのみが使用できます", "Only alphanumeric characters and hyphens are allowed in the command string.": "コマンド文字列には英数字とハイフンのみが使用できます。", - "Only can be triggered when the chat input is in focus.": "", + "Only can be triggered when the chat input is in focus.": "チャット入力欄にフォーカスがあるときのみ使用できます。", "Only collections can be edited, create a new knowledge base to edit/add documents.": "コレクションのみ編集できます。新しいナレッジベースを作成してドキュメントを編集/追加してください。", "Only invited users can access": "", "Only markdown files are allowed": "マークダウンファイルのみが許可されています", @@ -1250,7 +1250,7 @@ "Open modal to configure connection": "接続設定のモーダルを開く", "Open Modal To Manage Floating Quick Actions": "フローティング クイックアクションを管理するモーダルを開く", "Open Modal To Manage Image Compression": "", - "Open Settings": "", + "Open Settings": "設定を開く", "Open Sidebar": "サイドバーを開く", "Open User Profile Menu": "ユーザープロフィールメニューを開く", "Open WebUI can use tools provided by any OpenAPI server.": "OpenWebUI は任意のOpenAPI サーバーが提供するツールを使用できます。", @@ -1340,7 +1340,7 @@ "Prefer not to say": "回答しない", "Prefix ID": "Prefix ID", "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "Prefix ID はモデル ID に接頭辞を追加することで、他の接続との競合を避けるために使用されます - 空の場合は無効にします", - "Prevent File Creation": "", + "Prevent File Creation": "ファイル作成を防止", "Preview": "プレビュー", "Previous 30 days": "過去30日間", "Previous 7 days": "過去7日間", @@ -1356,14 +1356,14 @@ "Prompts": "プロンプト", "Prompts Access": "プロンプトアクセス", "Prompts Public Sharing": "プロンプトの公開共有", - "Prompts Sharing": "", + "Prompts Sharing": "プロンプトの共有", "Provider Type": "", "Public": "公開", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com から \"{{searchValue}}\" をプル", "Pull a model from Ollama.com": "Ollama.com からモデルをプル", "Pull Model": "", "Query Generation Prompt": "クエリ生成プロンプト", - "Querying": "", + "Querying": "照会中", "Quick Actions": "クイックアクション", "RAG Template": "RAG テンプレート", "Rating": "評価", @@ -1381,11 +1381,11 @@ "Redirecting you to Open WebUI Community": "OpenWebUI コミュニティにリダイレクトしています", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "無意味な生成の確率を減少させます。高い値(例:100)はより多様な回答を提供し、低い値(例:10)ではより保守的になります。", "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "あなたのことは「User」としてください(例:「User はスペイン語を学んでいます」)", - "Reference Chats": "", + "Reference Chats": "チャットを参照", "Refused when it shouldn't have": "拒否すべきでないのに拒否した", "Regenerate": "再生成", "Regenerate Menu": "再生成メニュー", - "Regenerate Response": "", + "Regenerate Response": "回答を再生成", "Register Again": "", "Register Client": "", "Registered": "", @@ -1428,9 +1428,9 @@ "RESULT": "結果", "Retrieval": "検索", "Retrieval Query Generation": "検索クエリ生成", - "Retrieved {{count}} sources": "", + "Retrieved {{count}} sources": "{{count}} 件のソースを取得", "Retrieved {{count}} sources_other": "", - "Retrieved 1 source": "", + "Retrieved 1 source": "1 件のソースを取得", "Rich Text Input for Chat": "チャットのリッチテキスト入力", "Role": "ロール", "Rosé Pine": "Rosé Pine", @@ -1474,7 +1474,7 @@ "SearchApi API Key": "SearchApiのAPIKey", "SearchApi Engine": "SearchApiエンジン", "Searched {{count}} sites": "{{count}} サイトを検索しました", - "Searching": "", + "Searching": "検索中", "Searching \"{{searchQuery}}\"": "「{{searchQuery}}」を検索中...", "Searching Knowledge for \"{{searchQuery}}\"": "「{{searchQuery}}」のナレッジを検索中...", "Searching the web": "ウェブを検索中...", @@ -1542,9 +1542,9 @@ "Sets the random number seed to use for generation. Setting this to a specific number will make the model generate the same text for the same prompt.": "生成に用いる乱数シードを設定します。特定の数値を設定すると、同じプロンプトで同じテキストが生成されます。", "Sets the size of the context window used to generate the next token.": "次のトークンを生成する際に使用するコンテキストウィンドウのサイズを設定します。", "Sets the stop sequences to use. When this pattern is encountered, the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.": "停止シーケンスを設定します。このパターンに達するとLLMはテキスト生成を停止し、結果を返します。複数の停止パターンは、モデルファイル内で複数のstopパラメータを指定することで設定可能です。", - "Setting": "", + "Setting": "設定", "Settings": "設定", - "Settings Permissions": "", + "Settings Permissions": "設定に関する権限", "Settings saved successfully!": "設定が正常に保存されました!", "Share": "共有", "Share Chat": "チャットを共有", @@ -1559,7 +1559,7 @@ "Show Formatting Toolbar": "フォーマットツールバーを表示", "Show image preview": "画像のプレビューを表示", "Show Model": "モデルを表示", - "Show Shortcuts": "", + "Show Shortcuts": "ショートカットを表示", "Show your support!": "サポートを表示", "Showcased creativity": "創造性を披露", "Sign in": "サインイン", @@ -1593,14 +1593,14 @@ "Start of the channel": "チャンネルの開始", "Start Tag": "", "Status": "ステータス", - "Status cleared successfully": "", - "Status updated successfully": "", - "Status Updates": "", + "Status cleared successfully": "正常にステータスをクリアしました", + "Status updated successfully": "正常にステータスを更新しました", + "Status Updates": "ステータス更新", "STDOUT/STDERR": "STDOUT/STDERR", "Steps": "", "Stop": "停止", "Stop Download": "", - "Stop Generating": "", + "Stop Generating": "生成を停止", "Stop Sequence": "ストップシーケンス", "Stream Chat Response": "チャットレスポンスのストリーム", "Stream Delta Chunk Size": "ストリームの差分チャンクサイズ", @@ -1611,7 +1611,7 @@ "STT Model": "STTモデル", "STT Settings": "STT設定", "Stylized PDF Export": "スタイル付きPDFエクスポート", - "Subtitle": "", + "Subtitle": "サブタイトル", "Success": "成功", "Successfully imported {{userCount}} users.": "{{userCount}} 人のユーザが正常にインポートされました。", "Successfully updated.": "正常に更新されました。", @@ -1636,7 +1636,7 @@ "Tags Generation": "タグ生成", "Tags Generation Prompt": "タグ生成プロンプト", "Tail free sampling is used to reduce the impact of less probable tokens from the output. A higher value (e.g., 2.0) will reduce the impact more, while a value of 1.0 disables this setting.": "Tail Free Samplingは、出力中の確率の低いトークンの影響を抑えるための手法です。値が高い(例:2.0)ほど影響を減らし、1.0の場合は無効となります。", - "Talk to Model": "", + "Talk to Model": "モデルに話しかける", "Tap to interrupt": "タップして中断", "Task List": "タスクリスト", "Task Model": "タスクモデル", @@ -1658,7 +1658,7 @@ "The evaluation leaderboard is based on the Elo rating system and is updated in real-time.": "評価リーダーボードはElo評価システムに基づいており、実時間で更新されています。", "The format to return a response in. Format can be json or a JSON schema.": "レスポンスのフォーマット。jsonか、JSONスキーマを指定できます。", "The height in pixels to compress images to. Leave empty for no compression.": "画像の圧縮後のピクセル単位での高さ。空欄で圧縮を無効化します", - "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "入力音声の言語を指定します。ISO-639-1形式(例:en)で指定すると精度や処理速度が向上します。空欄にすると自動言語検出が行われます。", + "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "入力音声の言語を指定します。ISO-639-1形式(例: ja)で指定すると精度や処理速度が向上します。空欄にすると自動言語検出が行われます。", "The LDAP attribute that maps to the mail that users use to sign in.": "ユーザーがサインインに使用するメールのLDAP属性。", "The LDAP attribute that maps to the username that users use to sign in.": "ユーザーがサインインに使用するユーザー名のLDAP属性。", "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "リーダーボードは現在ベータ版であり、アルゴリズムを改善する際に評価計算を調整する場合があります。", @@ -1717,8 +1717,8 @@ "To select toolkits here, add them to the \"Tools\" workspace first.": "ここでツールキットを選択するには、まず \"Tools\" ワークスペースに追加してください。", "Toast notifications for new updates": "新しい更新のトースト通知", "Today": "今日", - "Today at {{LOCALIZED_TIME}}": "", - "Toggle Sidebar": "", + "Today at {{LOCALIZED_TIME}}": "今日 {{LOCALIZED_TIME}}", + "Toggle Sidebar": "サイドバーを切り替える", "Toggle whether current connection is active.": "この接続の有効性を切り替える", "Token": "トークン", "Too verbose": "冗長すぎる", @@ -1736,7 +1736,7 @@ "Tools Function Calling Prompt": "ツール関数呼び出しプロンプト", "Tools have a function calling system that allows arbitrary code execution.": "ツールは任意のコード実行を可能にする関数呼び出しシステムを持っています。", "Tools Public Sharing": "ツールの公開共有", - "Tools Sharing": "", + "Tools Sharing": "ツールの共有", "Top": "", "Top K": "トップ K", "Top K Reranker": "トップ K リランカー", @@ -1749,11 +1749,11 @@ "TTS Settings": "TTS 設定", "TTS Voice": "TTSボイス", "Type": "種類", - "Type here...": "", + "Type here...": "ここに入力してください...", "Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (ダウンロード) URL を入力してください", "Uh-oh! There was an issue with the response.": "レスポンスに問題がありました。", "UI": "", - "UI Scale": "", + "UI Scale": "UIの拡大率", "Unarchive All": "すべてアーカイブ解除", "Unarchive All Archived Chats": "すべてのアーカイブされたチャットをアーカイブ解除", "Unarchive Chat": "チャットをアーカイブ解除", @@ -1771,7 +1771,7 @@ "Update and Copy Link": "リンクの更新とコピー", "Update for the latest features and improvements.": "最新の機能と改善点を更新します。", "Update password": "パスワードを更新", - "Update your status": "", + "Update your status": "ステータスを変更", "Updated": "更新されました", "Updated at": "更新日時", "Updated At": "更新日時", @@ -1805,7 +1805,7 @@ "User location successfully retrieved.": "ユーザーの位置情報が正常に取得されました。", "User menu": "ユーザーメニュー", "User ratings (thumbs up/down)": "", - "User Status": "", + "User Status": "ユーザーステータス", "User Webhooks": "ユーザWebhook", "Username": "ユーザー名", "users": "", @@ -1865,7 +1865,7 @@ "wherever you are": "どこにいても", "Whether to paginate the output. Each page will be separated by a horizontal rule and page number. Defaults to False.": "出力をページ分けするかどうか。各ページは水平線とページ番号で分割されます。デフォルトでは無効", "Whisper (Local)": "Whisper (ローカル)", - "Who can share to this group": "", + "Who can share to this group": "このグループを共有できるユーザー", "Why?": "どうしてですか?", "Widescreen Mode": "ワイドスクリーンモード", "Width": "幅", @@ -1884,7 +1884,7 @@ "Yahoo": "", "Yandex": "", "Yesterday": "昨日", - "Yesterday at {{LOCALIZED_TIME}}": "", + "Yesterday at {{LOCALIZED_TIME}}": "昨日 {{LOCALIZED_TIME}}", "You": "あなた", "You are currently using a trial license. Please contact support to upgrade your license.": "現在、試用ライセンスを使用しています。サポートにお問い合わせください。", "You can only chat with a maximum of {{maxCount}} file(s) at a time.": "同時にチャットに使用できるファイルは最大{{maxCount}}個までです。", From be75bc506adb048ef11b1612c0e3662511c920d0 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 19 Jan 2026 13:49:12 +0400 Subject: [PATCH 013/120] refac --- src/lib/components/admin/Users/UserList.svelte | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/components/admin/Users/UserList.svelte b/src/lib/components/admin/Users/UserList.svelte index 97b647ba56..93490be59e 100644 --- a/src/lib/components/admin/Users/UserList.svelte +++ b/src/lib/components/admin/Users/UserList.svelte @@ -97,6 +97,10 @@ } }; + $: if (query) { + page = 1; + } + $: if (query !== null && page !== null && orderBy !== null && direction !== null) { getUserList(); } From 98cb2d3411d3a6f14f479c5013f17fb7a2c4dec3 Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:58:48 -0500 Subject: [PATCH 014/120] feat: Add MATLAB syntax highlighting support for code blocks (#20773) * feat: Add MATLAB syntax highlighting support for code blocks Add MATLAB syntax highlighting support by fixing issues in both CodeEditor (editable) and CodeBlock (read-only) components. Changes: - CodeEditor.svelte: Added 'matlab' alias to CodeMirror's Octave language (MATLAB-compatible syntax) - CodeBlock.svelte: Fixed highlight.js usage to use highlight() directly when language is recognized, falling back to highlightAuto() only for unknown languages * revert: not needed --- src/lib/components/common/CodeEditor.svelte | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/components/common/CodeEditor.svelte b/src/lib/components/common/CodeEditor.svelte index 50c2a7cd18..ef8ed503d5 100644 --- a/src/lib/components/common/CodeEditor.svelte +++ b/src/lib/components/common/CodeEditor.svelte @@ -104,6 +104,12 @@ }) ); + // Add 'matlab' alias to Octave language (MATLAB-compatible syntax) + const octaveLang = languages.find((l) => l.name === 'Octave'); + if (octaveLang && !octaveLang.alias.includes('matlab')) { + octaveLang.alias.push('matlab'); + } + const getLang = async () => { const language = languages.find((l) => l.alias.includes(lang)); return await language?.load(); From 6ae3ddd66bbb260b8f65cc6ab5adc4dfab9fe18a Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:59:44 -0500 Subject: [PATCH 015/120] fix: truncate long model names and IDs in UI (#20696) - Added line-clamp-1 truncation and tooltips to long model names and IDs in the Evaluations and Models admin sections to prevent visual overflow. Model names now display truncated with full name and ID available on hover. --- src/lib/components/admin/Evaluations/Feedbacks.svelte | 10 ++++++---- .../components/admin/Evaluations/Leaderboard.svelte | 4 +++- .../admin/Evaluations/LeaderboardModal.svelte | 9 ++++++--- .../components/admin/Settings/Models/ModelList.svelte | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/lib/components/admin/Evaluations/Feedbacks.svelte b/src/lib/components/admin/Evaluations/Feedbacks.svelte index 0ec5678f0e..ccf1735431 100644 --- a/src/lib/components/admin/Evaluations/Feedbacks.svelte +++ b/src/lib/components/admin/Evaluations/Feedbacks.svelte @@ -302,9 +302,11 @@
{#if feedback.data?.sibling_model_ids} -
+ +
{feedback.data?.model_id}
+
@@ -320,11 +322,11 @@
{:else} -
+ +
{feedback.data?.model_id}
+
{/if}
diff --git a/src/lib/components/admin/Evaluations/Leaderboard.svelte b/src/lib/components/admin/Evaluations/Leaderboard.svelte index e16e62c98c..0dd501a153 100644 --- a/src/lib/components/admin/Evaluations/Leaderboard.svelte +++ b/src/lib/components/admin/Evaluations/Leaderboard.svelte @@ -182,7 +182,9 @@ alt={model.name} class="size-5 rounded-full object-cover" /> - {model.name} + + {model.name} +
diff --git a/src/lib/components/admin/Evaluations/LeaderboardModal.svelte b/src/lib/components/admin/Evaluations/LeaderboardModal.svelte index fc3ec6eb10..6730e739d7 100644 --- a/src/lib/components/admin/Evaluations/LeaderboardModal.svelte +++ b/src/lib/components/admin/Evaluations/LeaderboardModal.svelte @@ -4,6 +4,7 @@ import { getModelHistory } from '$lib/apis/evaluations'; import ModelActivityChart from './ModelActivityChart.svelte'; import XMark from '$lib/components/icons/XMark.svelte'; + import Tooltip from '$lib/components/common/Tooltip.svelte'; export let show = false; export let model = null; @@ -60,9 +61,11 @@ {#if model}
-
- {model.name} -
+ +
+ {model.name} +
+
diff --git a/src/lib/components/admin/Settings/Models/ModelList.svelte b/src/lib/components/admin/Settings/Models/ModelList.svelte index cc86e52e5f..d501a485d4 100644 --- a/src/lib/components/admin/Settings/Models/ModelList.svelte +++ b/src/lib/components/admin/Settings/Models/ModelList.svelte @@ -50,7 +50,7 @@
-
+
{#if $models.find((model) => model.id === modelId)} {$models.find((model) => model.id === modelId).name} {:else} From 38bf0b6eec16879bd962c89edcd142c93758ee3b Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:00:48 +0100 Subject: [PATCH 016/120] feat: Add new ENV VAR for custom error message on error on signup / password change due to password not meeting requirements (#20650) * add env var for custom auth pw message * Update auth.py * Update auth.py --- backend/open_webui/env.py | 2 ++ backend/open_webui/routers/auths.py | 4 ++++ backend/open_webui/utils/auth.py | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index aeba69b480..0bbe1b89c4 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -455,6 +455,8 @@ except Exception as e: r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$" ) +PASSWORD_VALIDATION_HINT = os.environ.get("PASSWORD_VALIDATION_HINT", "") + BYPASS_MODEL_ACCESS_CONTROL = ( os.environ.get("BYPASS_MODEL_ACCESS_CONTROL", "False").lower() == "true" diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 30d4ebe4cc..b1e5bdc8ab 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -813,6 +813,8 @@ async def signup( } else: raise HTTPException(500, detail=ERROR_MESSAGES.CREATE_USER_ERROR) + except HTTPException: + raise except Exception as err: log.error(f"Signup error: {str(err)}") raise HTTPException(500, detail="An internal error occurred during signup.") @@ -954,6 +956,8 @@ async def add_user( } else: raise HTTPException(500, detail=ERROR_MESSAGES.CREATE_USER_ERROR) + except HTTPException: + raise except Exception as err: log.error(f"Add user error: {str(err)}") raise HTTPException( diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py index c1f6910ddb..ef09a6004d 100644 --- a/backend/open_webui/utils/auth.py +++ b/backend/open_webui/utils/auth.py @@ -33,6 +33,7 @@ from open_webui.env import ( ENABLE_PASSWORD_VALIDATION, OFFLINE_MODE, LICENSE_BLOB, + PASSWORD_VALIDATION_HINT, PASSWORD_VALIDATION_REGEX_PATTERN, REDIS_KEY_PREFIX, pk, @@ -173,7 +174,7 @@ def validate_password(password: str) -> bool: if ENABLE_PASSWORD_VALIDATION: if not PASSWORD_VALIDATION_REGEX_PATTERN.match(password): - raise Exception(ERROR_MESSAGES.INVALID_PASSWORD()) + raise Exception(ERROR_MESSAGES.INVALID_PASSWORD(PASSWORD_VALIDATION_HINT)) return True From 85e92fe3b062ae669985c09495f6ff1baf8176ab Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 20 Jan 2026 16:41:46 +0400 Subject: [PATCH 017/120] refac --- src/routes/(app)/workspace/tools/edit/+page.svelte | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/routes/(app)/workspace/tools/edit/+page.svelte b/src/routes/(app)/workspace/tools/edit/+page.svelte index 8714a58c70..036c210d73 100644 --- a/src/routes/(app)/workspace/tools/edit/+page.svelte +++ b/src/routes/(app)/workspace/tools/edit/+page.svelte @@ -62,6 +62,12 @@ return null; }); + if (tool && !tool.write_access) { + toast.error($i18n.t('You do not have permission to edit this tool')); + goto('/workspace/tools'); + return; + } + console.log(tool); } }); From 91faa9fd5a1cfc5d3ab531d2d91d28db52bcc702 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 20 Jan 2026 16:42:20 +0400 Subject: [PATCH 018/120] refac --- src/routes/(app)/workspace/tools/edit/+page.svelte | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/routes/(app)/workspace/tools/edit/+page.svelte b/src/routes/(app)/workspace/tools/edit/+page.svelte index 036c210d73..3584ece2d5 100644 --- a/src/routes/(app)/workspace/tools/edit/+page.svelte +++ b/src/routes/(app)/workspace/tools/edit/+page.svelte @@ -56,19 +56,22 @@ const id = $page.url.searchParams.get('id'); if (id) { - tool = await getToolById(localStorage.token, id).catch((error) => { + const res = await getToolById(localStorage.token, id).catch((error) => { toast.error(`${error}`); goto('/workspace/tools'); return null; }); - if (tool && !tool.write_access) { + if (res && !res.write_access) { toast.error($i18n.t('You do not have permission to edit this tool')); goto('/workspace/tools'); return; } - console.log(tool); + if (res) { + tool = res; + console.log(tool); + } } }); From 4615e8f92bb96471a99e84c117f372d2c083df71 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 20 Jan 2026 22:28:10 +0400 Subject: [PATCH 019/120] refac --- backend/open_webui/routers/chats.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/backend/open_webui/routers/chats.py b/backend/open_webui/routers/chats.py index 9a43234aa6..885360aadd 100644 --- a/backend/open_webui/routers/chats.py +++ b/backend/open_webui/routers/chats.py @@ -357,9 +357,7 @@ def _process_chat_for_export(chat) -> Optional[ChatStatsExport]: return None -def calculate_chat_stats( - user_id, skip=0, limit=10, filter=None, db: Optional[Session] = None -): +def calculate_chat_stats(user_id, skip=0, limit=10, filter=None): if filter is None: filter = {} @@ -368,7 +366,6 @@ def calculate_chat_stats( skip=skip, limit=limit, filter=filter, - db=db, ) chat_stats_export_list = [] @@ -424,7 +421,6 @@ async def export_chat_stats( page: Optional[int] = 1, stream: bool = False, user=Depends(get_verified_user), - db: Session = Depends(get_session), ): # Check if the user has permission to share/export chats if (user.role != "admin") and ( @@ -455,7 +451,7 @@ async def export_chat_stats( skip = (page - 1) * limit chat_stats_export_list, total = await asyncio.to_thread( - calculate_chat_stats, user.id, skip, limit, filter, db=db + calculate_chat_stats, user.id, skip, limit, filter ) return ChatStatsExportList( From ecbdef732bc71a07c21bbb679edb420f26eac181 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 21 Jan 2026 23:51:36 +0400 Subject: [PATCH 020/120] enh: PDF_LOADER_MODE --- backend/open_webui/config.py | 6 +++++ backend/open_webui/main.py | 2 ++ backend/open_webui/retrieval/loaders/main.py | 4 +++- backend/open_webui/routers/retrieval.py | 8 +++++++ .../admin/Settings/Documents.svelte | 24 +++++++++++++++++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index ed7df33ed2..c062977652 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -2809,6 +2809,12 @@ PDF_EXTRACT_IMAGES = PersistentConfig( os.environ.get("PDF_EXTRACT_IMAGES", "False").lower() == "true", ) +PDF_LOADER_MODE = PersistentConfig( + "PDF_LOADER_MODE", + "rag.pdf_loader_mode", + os.environ.get("PDF_LOADER_MODE", "page"), +) + RAG_EMBEDDING_MODEL = PersistentConfig( "RAG_EMBEDDING_MODEL", "rag.embedding_model", diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 82a87e3fd9..9d1d85060f 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -288,6 +288,7 @@ from open_webui.config import ( ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, TIKTOKEN_ENCODING_NAME, PDF_EXTRACT_IMAGES, + PDF_LOADER_MODE, YOUTUBE_LOADER_LANGUAGE, YOUTUBE_LOADER_PROXY_URL, # Retrieval (Web Search) @@ -944,6 +945,7 @@ app.state.config.RAG_OLLAMA_BASE_URL = RAG_OLLAMA_BASE_URL app.state.config.RAG_OLLAMA_API_KEY = RAG_OLLAMA_API_KEY app.state.config.PDF_EXTRACT_IMAGES = PDF_EXTRACT_IMAGES +app.state.config.PDF_LOADER_MODE = PDF_LOADER_MODE app.state.config.YOUTUBE_LOADER_LANGUAGE = YOUTUBE_LOADER_LANGUAGE app.state.config.YOUTUBE_LOADER_PROXY_URL = YOUTUBE_LOADER_PROXY_URL diff --git a/backend/open_webui/retrieval/loaders/main.py b/backend/open_webui/retrieval/loaders/main.py index bf7c7286b5..83adb8823f 100644 --- a/backend/open_webui/retrieval/loaders/main.py +++ b/backend/open_webui/retrieval/loaders/main.py @@ -361,7 +361,9 @@ class Loader: else: if file_ext == "pdf": loader = PyPDFLoader( - file_path, extract_images=self.kwargs.get("PDF_EXTRACT_IMAGES") + file_path, + extract_images=self.kwargs.get("PDF_EXTRACT_IMAGES"), + mode=self.kwargs.get("PDF_LOADER_MODE", "page"), ) elif file_ext == "csv": loader = CSVLoader(file_path, autodetect_encoding=True) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 763a9aacc3..318e7bf8ce 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -468,6 +468,7 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)): # Content extraction settings "CONTENT_EXTRACTION_ENGINE": request.app.state.config.CONTENT_EXTRACTION_ENGINE, "PDF_EXTRACT_IMAGES": request.app.state.config.PDF_EXTRACT_IMAGES, + "PDF_LOADER_MODE": request.app.state.config.PDF_LOADER_MODE, "DATALAB_MARKER_API_KEY": request.app.state.config.DATALAB_MARKER_API_KEY, "DATALAB_MARKER_API_BASE_URL": request.app.state.config.DATALAB_MARKER_API_BASE_URL, "DATALAB_MARKER_ADDITIONAL_CONFIG": request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG, @@ -659,6 +660,7 @@ class ConfigForm(BaseModel): # Content extraction settings CONTENT_EXTRACTION_ENGINE: Optional[str] = None PDF_EXTRACT_IMAGES: Optional[bool] = None + PDF_LOADER_MODE: Optional[str] = None DATALAB_MARKER_API_KEY: Optional[str] = None DATALAB_MARKER_API_BASE_URL: Optional[str] = None @@ -786,6 +788,11 @@ async def update_rag_config( if form_data.PDF_EXTRACT_IMAGES is not None else request.app.state.config.PDF_EXTRACT_IMAGES ) + request.app.state.config.PDF_LOADER_MODE = ( + form_data.PDF_LOADER_MODE + if form_data.PDF_LOADER_MODE is not None + else request.app.state.config.PDF_LOADER_MODE + ) request.app.state.config.DATALAB_MARKER_API_KEY = ( form_data.DATALAB_MARKER_API_KEY if form_data.DATALAB_MARKER_API_KEY is not None @@ -1180,6 +1187,7 @@ async def update_rag_config( # Content extraction settings "CONTENT_EXTRACTION_ENGINE": request.app.state.config.CONTENT_EXTRACTION_ENGINE, "PDF_EXTRACT_IMAGES": request.app.state.config.PDF_EXTRACT_IMAGES, + "PDF_LOADER_MODE": request.app.state.config.PDF_LOADER_MODE, "DATALAB_MARKER_API_KEY": request.app.state.config.DATALAB_MARKER_API_KEY, "DATALAB_MARKER_API_BASE_URL": request.app.state.config.DATALAB_MARKER_API_BASE_URL, "DATALAB_MARKER_ADDITIONAL_CONFIG": request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG, diff --git a/src/lib/components/admin/Settings/Documents.svelte b/src/lib/components/admin/Settings/Documents.svelte index 732d824692..3f4434084b 100644 --- a/src/lib/components/admin/Settings/Documents.svelte +++ b/src/lib/components/admin/Settings/Documents.svelte @@ -362,6 +362,30 @@
+ +
+
+
+ + {$i18n.t('PDF Loader Mode')} + +
+
+ +
+
+
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'datalab_marker'}
Date: Thu, 22 Jan 2026 03:09:04 +0400 Subject: [PATCH 021/120] refac --- backend/open_webui/models/knowledge.py | 29 ++++++++++---------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/backend/open_webui/models/knowledge.py b/backend/open_webui/models/knowledge.py index 8612842015..81aa4099d9 100644 --- a/backend/open_webui/models/knowledge.py +++ b/backend/open_webui/models/knowledge.py @@ -243,7 +243,7 @@ class KnowledgeTable: query = has_permission(db, Knowledge, query, filter) - query = query.order_by(Knowledge.updated_at.desc()) + query = query.order_by(Knowledge.updated_at.desc(), Knowledge.id.asc()) total = query.count() if skip: @@ -303,7 +303,7 @@ class KnowledgeTable: query = query.filter(File.filename.ilike(f"%{q}%")) # Order by file changes - query = query.order_by(File.updated_at.desc()) + query = query.order_by(File.updated_at.desc(), File.id.asc()) # Count before pagination total = query.count() @@ -430,6 +430,9 @@ class KnowledgeTable: .filter(KnowledgeFile.knowledge_id == knowledge_id) ) + # Default sort: updated_at descending + primary_sort = File.updated_at.desc() + if filter: query_key = filter.get("query") if query_key: @@ -443,27 +446,17 @@ class KnowledgeTable: order_by = filter.get("order_by") direction = filter.get("direction") + is_asc = direction == "asc" if order_by == "name": - if direction == "asc": - query = query.order_by(File.filename.asc()) - else: - query = query.order_by(File.filename.desc()) + primary_sort = File.filename.asc() if is_asc else File.filename.desc() elif order_by == "created_at": - if direction == "asc": - query = query.order_by(File.created_at.asc()) - else: - query = query.order_by(File.created_at.desc()) + primary_sort = File.created_at.asc() if is_asc else File.created_at.desc() elif order_by == "updated_at": - if direction == "asc": - query = query.order_by(File.updated_at.asc()) - else: - query = query.order_by(File.updated_at.desc()) - else: - query = query.order_by(File.updated_at.desc()) + primary_sort = File.updated_at.asc() if is_asc else File.updated_at.desc() - else: - query = query.order_by(File.updated_at.desc()) + # Apply sort with secondary key for deterministic pagination + query = query.order_by(primary_sort, File.id.asc()) # Count BEFORE pagination total = query.count() From 8eebc2aea63b7045e61c9689a65a2dfa9c797bcb Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 03:11:33 +0400 Subject: [PATCH 022/120] fix: mcp get_discovery_urls --- backend/open_webui/routers/configs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py index 152e2c3edc..4dee4488cf 100644 --- a/backend/open_webui/routers/configs.py +++ b/backend/open_webui/routers/configs.py @@ -224,7 +224,7 @@ async def verify_tool_servers_config( try: if form_data.type == "mcp": if form_data.auth_type == "oauth_2.1": - discovery_urls = get_discovery_urls(form_data.url) + discovery_urls = await get_discovery_urls(form_data.url) for discovery_url in discovery_urls: log.debug( f"Trying to fetch OAuth 2.1 discovery document from {discovery_url}" From 8c70453b2e3a6958437d951751e84acbbaafd9aa Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 03:18:38 +0400 Subject: [PATCH 023/120] enh: password valve type --- src/lib/components/common/Valves.svelte | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/lib/components/common/Valves.svelte b/src/lib/components/common/Valves.svelte index de1487c64f..cad66c5b7f 100644 --- a/src/lib/components/common/Valves.svelte +++ b/src/lib/components/common/Valves.svelte @@ -4,6 +4,7 @@ const i18n = getContext('i18n'); import Switch from './Switch.svelte'; + import SensitiveInput from './SensitiveInput.svelte'; import MapSelector from './Valves/MapSelector.svelte'; export let valvesSpec = null; @@ -103,7 +104,19 @@ }} /> {:else if valvesSpec.properties[property]?.input ?? null} - {#if valvesSpec.properties[property]?.input?.type === 'color'} + {#if valvesSpec.properties[property]?.input?.type === 'password'} +
+ { + dispatch('change'); + }} + /> +
+ {:else if valvesSpec.properties[property]?.input?.type === 'color'}
Date: Thu, 22 Jan 2026 03:20:59 +0400 Subject: [PATCH 024/120] refac/fix: default oauth2.1 mcp tool --- src/lib/components/workspace/Models/ToolsSelector.svelte | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/components/workspace/Models/ToolsSelector.svelte b/src/lib/components/workspace/Models/ToolsSelector.svelte index bbc484f907..d002ac6296 100644 --- a/src/lib/components/workspace/Models/ToolsSelector.svelte +++ b/src/lib/components/workspace/Models/ToolsSelector.svelte @@ -12,7 +12,13 @@ const i18n = getContext('i18n'); onMount(() => { - _tools = tools.reduce((acc, tool) => { + // Filter out OAuth2.1 MCP tools - these cannot be set as model defaults + // because OAuth authentication is per-user and would fail for users + // who haven't completed the OAuth flow. + // The `authenticated` field only exists on OAuth2.1 MCP tools. + const availableTools = tools.filter((tool) => tool.authenticated === undefined); + + _tools = availableTools.reduce((acc, tool) => { acc[tool.id] = { ...tool, selected: selectedToolIds.includes(tool.id) From 4d9a7cc6c0adea54b58046c576250a0c3ae7b512 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 03:25:23 +0400 Subject: [PATCH 025/120] refac: fr-FR priority --- src/lib/i18n/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/i18n/index.ts b/src/lib/i18n/index.ts index e5c2d183b2..d7361a5e79 100644 --- a/src/lib/i18n/index.ts +++ b/src/lib/i18n/index.ts @@ -58,6 +58,7 @@ export const initI18n = (defaultLocale?: string | undefined) => { lookupLocalStorage: 'locale' }, fallbackLng: { + fr: ['fr-FR'], default: fallbackDefaultLocale }, ns: 'translation', From 00b3583dc2fe77f7f2223ea2fa2fe4302d4cfdcd Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:36:08 +0100 Subject: [PATCH 026/120] fix: fix reindex not working due to unnecessary dupe check (#20857) * Update retrieval.py * Update knowledge.py * Update retrieval.py * Update knowledge.py --- backend/open_webui/routers/retrieval.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 318e7bf8ce..5a3a346ab7 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -1425,8 +1425,16 @@ def save_docs_to_vector_db( if result is not None and result.ids and len(result.ids) > 0: existing_doc_ids = result.ids[0] if existing_doc_ids: - log.info(f"Document with hash {metadata['hash']} already exists") - raise ValueError(ERROR_MESSAGES.DUPLICATE_CONTENT) + # Check if the existing document belongs to the same file + # If same file_id, this is a re-add/reindex - allow it + # If different file_id, this is a duplicate - block it + existing_file_id = None + if result.metadatas and result.metadatas[0]: + existing_file_id = result.metadatas[0][0].get("file_id") + + if existing_file_id != metadata.get("file_id"): + log.info(f"Document with hash {metadata['hash']} already exists") + raise ValueError(ERROR_MESSAGES.DUPLICATE_CONTENT) if split: if request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER: From 474427c67e953bb9f7d122757a756a639214e0b2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 03:55:07 +0400 Subject: [PATCH 027/120] enh: dynamic select options valve --- backend/open_webui/routers/functions.py | 11 +- backend/open_webui/routers/tools.py | 11 +- backend/open_webui/utils/plugin.py | 138 ++++++++++++++++++++++++ src/lib/components/common/Valves.svelte | 21 ++++ 4 files changed, 177 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/routers/functions.py b/backend/open_webui/routers/functions.py index ad47318911..a31b958e21 100644 --- a/backend/open_webui/routers/functions.py +++ b/backend/open_webui/routers/functions.py @@ -19,6 +19,7 @@ from open_webui.utils.plugin import ( load_function_module_by_id, replace_imports, get_function_module_from_cache, + resolve_valves_schema_options, ) from open_webui.config import CACHE_DIR from open_webui.constants import ERROR_MESSAGES @@ -446,7 +447,10 @@ async def get_function_valves_spec_by_id( if hasattr(function_module, "Valves"): Valves = function_module.Valves - return Valves.schema() + schema = Valves.schema() + # Resolve dynamic options for select dropdowns + schema = resolve_valves_schema_options(Valves, schema, user) + return schema return None else: raise HTTPException( @@ -546,7 +550,10 @@ async def get_function_user_valves_spec_by_id( if hasattr(function_module, "UserValves"): UserValves = function_module.UserValves - return UserValves.schema() + schema = UserValves.schema() + # Resolve dynamic options for select dropdowns + schema = resolve_valves_schema_options(UserValves, schema, user) + return schema return None else: raise HTTPException( diff --git a/backend/open_webui/routers/tools.py b/backend/open_webui/routers/tools.py index 03018d24a1..7f9b23c7ce 100644 --- a/backend/open_webui/routers/tools.py +++ b/backend/open_webui/routers/tools.py @@ -25,6 +25,7 @@ from open_webui.utils.plugin import ( load_tool_module_by_id, replace_imports, get_tool_module_from_cache, + resolve_valves_schema_options, ) from open_webui.utils.tools import get_tool_specs from open_webui.utils.auth import get_admin_user, get_verified_user @@ -553,7 +554,10 @@ async def get_tools_valves_spec_by_id( if hasattr(tools_module, "Valves"): Valves = tools_module.Valves - return Valves.schema() + schema = Valves.schema() + # Resolve dynamic options for select dropdowns + schema = resolve_valves_schema_options(Valves, schema, user) + return schema return None else: raise HTTPException( @@ -662,7 +666,10 @@ async def get_tools_user_valves_spec_by_id( if hasattr(tools_module, "UserValves"): UserValves = tools_module.UserValves - return UserValves.schema() + schema = UserValves.schema() + # Resolve dynamic options for select dropdowns + schema = resolve_valves_schema_options(UserValves, schema, user) + return schema return None else: raise HTTPException( diff --git a/backend/open_webui/utils/plugin.py b/backend/open_webui/utils/plugin.py index 965b0a688f..79a1c0f0dc 100644 --- a/backend/open_webui/utils/plugin.py +++ b/backend/open_webui/utils/plugin.py @@ -6,6 +6,7 @@ from importlib import util import types import tempfile import logging +from typing import Any from open_webui.env import PIP_OPTIONS, PIP_PACKAGE_INDEX_OPTIONS, OFFLINE_MODE from open_webui.models.functions import Functions @@ -14,6 +15,143 @@ from open_webui.models.tools import Tools log = logging.getLogger(__name__) +def resolve_valves_schema_options( + valves_class: type, schema: dict, user: Any = None +) -> dict: + """ + Resolve dynamic options in a Valves schema. + + For properties with `input.options`, this function handles two cases: + - List: Used directly as dropdown options + - String: Treated as method name, called to get options dynamically + + Usage in Valves: + class UserValves(BaseModel): + # Static options + priority: str = Field( + default="medium", + json_schema_extra={ + "input": { + "type": "select", + "options": ["low", "medium", "high"] + } + } + ) + + # Dynamic options (method name) + model: str = Field( + default="", + json_schema_extra={ + "input": { + "type": "select", + "options": "get_model_options" + } + } + ) + + @classmethod + def get_model_options(cls, __user__=None) -> list[dict]: + return [{"value": "gpt-4", "label": "GPT-4"}] + + Args: + valves_class: The Valves or UserValves Pydantic model class + schema: The JSON schema dict from valves_class.schema() + user: Optional user object passed to methods that accept __user__ + + Returns: + Modified schema dict with resolved options + """ + if not schema or "properties" not in schema: + return schema + + # Make a copy to avoid mutating the original + schema = dict(schema) + schema["properties"] = dict(schema.get("properties", {})) + + for prop_name, prop_schema in list(schema["properties"].items()): + # Get the original field info from the Pydantic model + if not hasattr(valves_class, "model_fields"): + continue + + field_info = valves_class.model_fields.get(prop_name) + if not field_info: + continue + + # Check json_schema_extra for options + json_schema_extra = field_info.json_schema_extra + if not json_schema_extra or not isinstance(json_schema_extra, dict): + continue + + input_config = json_schema_extra.get("input") + if not input_config or not isinstance(input_config, dict): + continue + + options = input_config.get("options") + if options is None: + continue + + resolved_options = None + + # Case 1: options is already a list - use directly + if isinstance(options, list): + resolved_options = options + + # Case 2: options is a string - treat as method name + elif isinstance(options, str) and options: + method = getattr(valves_class, options, None) + if method is None or not callable(method): + log.warning( + f"options '{options}' not found or not callable on {valves_class.__name__}" + ) + continue + + try: + import inspect + + sig = inspect.signature(method) + params = sig.parameters + + # Prepare kwargs based on what the method accepts + kwargs = {} + if "__user__" in params and user is not None: + kwargs["__user__"] = ( + user.model_dump() if hasattr(user, "model_dump") else user + ) + if "user" in params and user is not None: + kwargs["user"] = ( + user.model_dump() if hasattr(user, "model_dump") else user + ) + + resolved_options = method(**kwargs) if kwargs else method() + + # Validate return type + if not isinstance(resolved_options, list): + log.warning( + f"Method '{options}' did not return a list for {prop_name}" + ) + continue + + except Exception as e: + log.warning(f"Failed to resolve options for {prop_name}: {e}") + continue + else: + # Invalid options type - skip + continue + + # Update the schema with resolved options + schema["properties"][prop_name] = dict(prop_schema) + if "input" not in schema["properties"][prop_name]: + schema["properties"][prop_name]["input"] = {"type": "select"} + else: + schema["properties"][prop_name]["input"] = dict( + schema["properties"][prop_name].get("input", {}) + ) + schema["properties"][prop_name]["input"]["options"] = resolved_options + + return schema + + + def extract_frontmatter(content): """ Extract frontmatter as a dictionary from the provided content string. diff --git a/src/lib/components/common/Valves.svelte b/src/lib/components/common/Valves.svelte index cad66c5b7f..4557ab490c 100644 --- a/src/lib/components/common/Valves.svelte +++ b/src/lib/components/common/Valves.svelte @@ -116,6 +116,27 @@ }} />
+ {:else if valvesSpec.properties[property]?.input?.type === 'select' && valvesSpec.properties[property]?.input?.options} + {:else if valvesSpec.properties[property]?.input?.type === 'color'}
From 5d48e48e15b003874cc821d896998a01e87580a0 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 03:59:00 +0400 Subject: [PATCH 028/120] fix: ENABLE_PERSISTENT_CONFIG redis issue --- backend/open_webui/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index c062977652..e84f1fa519 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -257,7 +257,7 @@ class AppConfig: self._state[key].value = value self._state[key].save() - if self._redis: + if self._redis and ENABLE_PERSISTENT_CONFIG: redis_key = f"{self._redis_key_prefix}:config:{key}" self._redis.set(redis_key, json.dumps(self._state[key].value)) @@ -265,8 +265,8 @@ class AppConfig: if key not in self._state: raise AttributeError(f"Config key '{key}' not found") - # If Redis is available, check for an updated value - if self._redis: + # If Redis is available and persistent config is enabled, check for an updated value + if self._redis and ENABLE_PERSISTENT_CONFIG: redis_key = f"{self._redis_key_prefix}:config:{key}" redis_value = self._redis.get(redis_key) From a3600e8b219fc4c019b95258d16bd3e2827490c6 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 04:12:57 +0400 Subject: [PATCH 029/120] refac --- .../chat/MessageInput/InputMenu.svelte | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/lib/components/chat/MessageInput/InputMenu.svelte b/src/lib/components/chat/MessageInput/InputMenu.svelte index 83d6abc5a5..6e2d7724b2 100644 --- a/src/lib/components/chat/MessageInput/InputMenu.svelte +++ b/src/lib/components/chat/MessageInput/InputMenu.svelte @@ -4,7 +4,7 @@ import { fly } from 'svelte/transition'; import { flyAndScale } from '$lib/utils/transitions'; - import { config, user, tools as _tools, mobile, knowledge, chats } from '$lib/stores'; + import { config, user, tools as _tools, mobile, knowledge } from '$lib/stores'; import { getKnowledgeBases } from '$lib/apis/knowledge'; import { createPicker } from '$lib/utils/google-drive-picker'; @@ -269,37 +269,35 @@ - {#if ($chats ?? []).length > 0} - + - - {/if} + +
+ +
+
+ + {#if fileUploadEnabled} {#if $config?.features?.enable_google_drive_integration} From 886c12c5664bc2dd73313330f61c2257169da6d1 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 14:54:00 +0400 Subject: [PATCH 030/120] refac --- backend/open_webui/utils/payload.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/payload.py b/backend/open_webui/utils/payload.py index 458687b371..5094c910ca 100644 --- a/backend/open_webui/utils/payload.py +++ b/backend/open_webui/utils/payload.py @@ -287,7 +287,11 @@ def convert_payload_openai_to_ollama(openai_payload: dict) -> dict: Returns: dict: A modified payload compatible with the Ollama API. """ - openai_payload = copy.deepcopy(openai_payload) + # Shallow copy metadata separately (may contain non-picklable objects) + metadata = openai_payload.get("metadata") + openai_payload = copy.deepcopy({k: v for k, v in openai_payload.items() if k != "metadata"}) + if metadata is not None: + openai_payload["metadata"] = dict(metadata) ollama_payload = {} # Mapping basic model and message details From 1a4bdd2b30017d901b9cac1e2e10684ec1edd062 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 14:59:15 +0400 Subject: [PATCH 031/120] refac --- backend/open_webui/tools/builtin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index fcd1d4d233..874a073af8 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -892,6 +892,7 @@ async def search_chats( end_timestamp: Optional[int] = None, __request__: Request = None, __user__: dict = None, + __chat_id__: str = None, ) -> str: """ Search the user's previous chat conversations by title and message content. @@ -921,6 +922,10 @@ async def search_chats( results = [] for chat in chats: + # Skip the current chat to avoid showing it in search results + if __chat_id__ and chat.id == __chat_id__: + continue + # Apply date filters (updated_at is in seconds) if start_timestamp and chat.updated_at < start_timestamp: continue From 68b2872ed645cffb641fa5a21a784d6e9ea0d72b Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 15:03:31 +0400 Subject: [PATCH 032/120] fix/refac: file batch process issue --- backend/open_webui/routers/retrieval.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 5a3a346ab7..ce9153c8df 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -2721,7 +2721,7 @@ async def process_files_batch( for file_result in file_results: file_result.status = "failed" file_errors.append( - BatchProcessFilesResult(file_id=file_result.file_id, error=str(e)) + BatchProcessFilesResult(file_id=file_result.file_id, status="failed", error=str(e)) ) return BatchProcessFilesResponse(results=file_results, errors=file_errors) From 14f6747dfc66fb7e942b930650286012121e5262 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 15:07:14 +0400 Subject: [PATCH 033/120] refac --- backend/open_webui/utils/middleware.py | 8 ++------ backend/open_webui/utils/tools.py | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index fe2d7e5dc1..48ebddb7ef 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -1808,9 +1808,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): # Inject builtin tools for native function calling based on enabled features and model capability # Check if builtin_tools capability is enabled for this model (defaults to True if not specified) builtin_tools_enabled = ( - model.get("info", {}) - .get("meta", {}) - .get("capabilities", {}) + (model.get("info", {}).get("meta", {}).get("capabilities") or {}) .get("builtin_tools", True) ) if ( @@ -1856,9 +1854,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): # Check if file context extraction is enabled for this model (default True) file_context_enabled = ( - model.get("info", {}) - .get("meta", {}) - .get("capabilities", {}) + (model.get("info", {}).get("meta", {}).get("capabilities") or {}) .get("file_context", True) ) diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index 77f985ebbc..7984878344 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -398,9 +398,7 @@ def get_builtin_tools( # Helper to get model capabilities (defaults to True if not specified) def get_model_capability(name: str, default: bool = True) -> bool: return ( - model.get("info", {}) - .get("meta", {}) - .get("capabilities", {}) + (model.get("info", {}).get("meta", {}).get("capabilities") or {}) .get(name, default) ) From 9e5d6069fef751b4a5bdb38583cab7da00aaba11 Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Thu, 22 Jan 2026 07:07:07 -0500 Subject: [PATCH 034/120] feat: Sort Tools and Functions dropdowns alphabetically (#20871) Alphabetically sort Tools and Functions selection dropdowns in Chat Controls sidebar for easier navigation and better user experience. --- src/lib/components/chat/Controls/Valves.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Controls/Valves.svelte b/src/lib/components/chat/Controls/Valves.svelte index 83fda5ff19..a63b0d3b81 100644 --- a/src/lib/components/chat/Controls/Valves.svelte +++ b/src/lib/components/chat/Controls/Valves.svelte @@ -172,7 +172,7 @@ >{$i18n.t('Select a tool')} - {#each $tools.filter((tool) => !tool?.id?.startsWith('server:')) as tool, toolIdx} + {#each $tools.filter((tool) => !tool?.id?.startsWith('server:')).sort((a, b) => (a.name ?? '').localeCompare(b.name ?? '')) as tool, toolIdx} {/each} {:else if tab === 'functions'} @@ -180,7 +180,7 @@ >{$i18n.t('Select a function')} - {#each $functions as func, funcIdx} + {#each $functions.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? '')) as func, funcIdx} {/each} {/if} From 907dba4517903e5646e40223a0edca26a7107bc8 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 18:27:42 +0400 Subject: [PATCH 035/120] feat: easter eggs flag --- backend/open_webui/env.py | 2 ++ backend/open_webui/main.py | 2 ++ src/lib/components/chat/Settings/General.svelte | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 0bbe1b89c4..aa296da5b8 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -199,6 +199,8 @@ ENABLE_STAR_SESSIONS_MIDDLEWARE = ( os.environ.get("ENABLE_STAR_SESSIONS_MIDDLEWARE", "False").lower() == "true" ) +ENABLE_EASTER_EGGS = os.environ.get("ENABLE_EASTER_EGGS", "True").lower() == "true" + #################################### # WEBUI_BUILD_HASH #################################### diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 9d1d85060f..398a666d63 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -491,6 +491,7 @@ from open_webui.env import ( WEBUI_ADMIN_EMAIL, WEBUI_ADMIN_PASSWORD, WEBUI_ADMIN_NAME, + ENABLE_EASTER_EGGS, ) @@ -1932,6 +1933,7 @@ async def get_app_config(request: Request): "enable_websocket": ENABLE_WEBSOCKET_SUPPORT, "enable_version_update_check": ENABLE_VERSION_UPDATE_CHECK, "enable_public_active_users_count": ENABLE_PUBLIC_ACTIVE_USERS_COUNT, + "enable_easter_eggs": ENABLE_EASTER_EGGS, **( { "enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS, diff --git a/src/lib/components/chat/Settings/General.svelte b/src/lib/components/chat/Settings/General.svelte index bb8a63eedc..e65683bde6 100644 --- a/src/lib/components/chat/Settings/General.svelte +++ b/src/lib/components/chat/Settings/General.svelte @@ -210,9 +210,9 @@ - - + {#if $config?.features?.enable_easter_eggs} + + {/if}
From c7f996d593e4bb48103b91316204fe7e50e25b35 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 18:30:16 +0400 Subject: [PATCH 036/120] refac: AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL for mcp connections --- backend/open_webui/utils/mcp/client.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/mcp/client.py b/backend/open_webui/utils/mcp/client.py index 6edfca4f6c..33803648be 100644 --- a/backend/open_webui/utils/mcp/client.py +++ b/backend/open_webui/utils/mcp/client.py @@ -8,6 +8,15 @@ from mcp import ClientSession from mcp.client.auth import OAuthClientProvider, TokenStorage from mcp.client.streamable_http import streamablehttp_client from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken +import httpx +from mcp.shared._httpx_utils import create_mcp_http_client +from open_webui.env import AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL + + +def create_insecure_httpx_client(headers=None, timeout=None, auth=None): + client = create_mcp_http_client(headers=headers, timeout=timeout, auth=auth) + client.verify = False + return client class MCPClient: @@ -18,7 +27,14 @@ class MCPClient: async def connect(self, url: str, headers: Optional[dict] = None): async with AsyncExitStack() as exit_stack: try: - self._streams_context = streamablehttp_client(url, headers=headers) + if AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL: + self._streams_context = streamablehttp_client(url, headers=headers) + else: + self._streams_context = streamablehttp_client( + url, + headers=headers, + httpx_client_factory=create_insecure_httpx_client, + ) transport = await exit_stack.enter_async_context(self._streams_context) read_stream, write_stream, _ = transport From 0df561c33c105640e7f3f3d7e98033a7b1ebd657 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 18:40:54 +0400 Subject: [PATCH 037/120] refac --- src/lib/components/chat/Settings/General.svelte | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/components/chat/Settings/General.svelte b/src/lib/components/chat/Settings/General.svelte index e65683bde6..db232a5df4 100644 --- a/src/lib/components/chat/Settings/General.svelte +++ b/src/lib/components/chat/Settings/General.svelte @@ -112,6 +112,10 @@ languages = await getLanguages(); + if (!$config?.features?.enable_easter_eggs) { + languages = languages.filter((l) => l.code !== 'dg-DG'); + } + notificationEnabled = $settings.notificationEnabled ?? false; system = $settings.system ?? ''; From 9af40624c5f0f8f7f640a11356e167543b07b2bb Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 22 Jan 2026 18:58:00 +0400 Subject: [PATCH 038/120] refac --- backend/open_webui/routers/retrieval.py | 80 +++++++++++++++---------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index ce9153c8df..a37fc50b05 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -39,7 +39,7 @@ from langchain_core.documents import Document from open_webui.models.files import FileModel, FileUpdateForm, Files from open_webui.models.knowledge import Knowledges from open_webui.storage.provider import Storage -from open_webui.internal.db import get_session +from open_webui.internal.db import get_session, get_db from sqlalchemy.orm import Session @@ -1431,7 +1431,7 @@ def save_docs_to_vector_db( existing_file_id = None if result.metadatas and result.metadatas[0]: existing_file_id = result.metadatas[0][0].get("file_id") - + if existing_file_id != metadata.get("file_id"): log.info(f"Document with hash {metadata['hash']} already exists") raise ValueError(ERROR_MESSAGES.DUPLICATE_CONTENT) @@ -1602,6 +1602,9 @@ def process_file( ): """ Process a file and save its content to the vector database. + Process a file and save its content to the vector database. + Note: granular session management is used to prevent connection pool exhaustion. + The session is committed before external API calls, and updates use a fresh session. """ if user.role == "admin": file = Files.get_file_by_id(form_data.file_id, db=db) @@ -1763,6 +1766,13 @@ def process_file( } else: try: + # Release the database connection relative to the 'file' object + # to prevent holding the connection during the slow embedding step. + db.expunge(file) + db.commit() + + # External embedding API takes time (5-60s+). + # No DB connection is held here. result = save_docs_to_vector_db( request, docs=docs, @@ -1778,27 +1788,29 @@ def process_file( log.info(f"added {len(docs)} items to collection {collection_name}") if result: - Files.update_file_metadata_by_id( - file.id, - { + # Fresh session for the final update. + with get_db() as session: + Files.update_file_metadata_by_id( + file.id, + { + "collection_name": collection_name, + }, + db=session, + ) + + Files.update_file_data_by_id( + file.id, + {"status": "completed"}, + db=session, + ) + Files.update_file_hash_by_id(file.id, hash, db=session) + + return { + "status": True, "collection_name": collection_name, - }, - db=db, - ) - - Files.update_file_data_by_id( - file.id, - {"status": "completed"}, - db=db, - ) - Files.update_file_hash_by_id(file.id, hash, db=db) - - return { - "status": True, - "collection_name": collection_name, - "filename": file.filename, - "content": text_content, - } + "filename": file.filename, + "content": text_content, + } else: raise Exception("Error saving document to vector database") except Exception as e: @@ -1806,13 +1818,15 @@ def process_file( except Exception as e: log.exception(e) - Files.update_file_data_by_id( - file.id, - {"status": "failed"}, - db=db, - ) - # Clear the hash so the file can be re-uploaded after fixing the issue - Files.update_file_hash_by_id(file.id, None, db=db) + # Fresh session for error status update. + with get_db() as session: + Files.update_file_data_by_id( + file.id, + {"status": "failed"}, + db=session, + ) + # Clear the hash so the file can be re-uploaded after fixing the issue + Files.update_file_hash_by_id(file.id, None, db=session) if "No pandoc was found" in str(e): raise HTTPException( @@ -2709,9 +2723,7 @@ async def process_files_batch( # Update all files with collection name for file_update, file_result in zip(file_updates, file_results): - Files.update_file_by_id( - id=file_result.file_id, form_data=file_update - ) + Files.update_file_by_id(id=file_result.file_id, form_data=file_update) file_result.status = "completed" except Exception as e: @@ -2721,7 +2733,9 @@ async def process_files_batch( for file_result in file_results: file_result.status = "failed" file_errors.append( - BatchProcessFilesResult(file_id=file_result.file_id, status="failed", error=str(e)) + BatchProcessFilesResult( + file_id=file_result.file_id, status="failed", error=str(e) + ) ) return BatchProcessFilesResponse(results=file_results, errors=file_errors) From 5a0488bb183c2e5337762053b0b6d4567497e4ed Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Thu, 22 Jan 2026 17:30:07 +0100 Subject: [PATCH 039/120] init (#20881) --- backend/open_webui/utils/task.py | 4 ++++ src/lib/components/channel/MessageInput.svelte | 8 ++++++++ src/lib/components/chat/MessageInput.svelte | 8 ++++++++ src/lib/utils/index.ts | 17 +++++++++-------- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/backend/open_webui/utils/task.py b/backend/open_webui/utils/task.py index ecedd595a7..4acb2c3718 100644 --- a/backend/open_webui/utils/task.py +++ b/backend/open_webui/utils/task.py @@ -69,6 +69,7 @@ def prompt_template(template: str, user: Optional[Any] = None) -> str: USER_VARIABLES = { "name": str(user.get("name")), + "email": str(user.get("email")), "location": str(user_info.get("location")), "bio": str(user.get("bio")), "gender": str(user.get("gender")), @@ -92,6 +93,9 @@ def prompt_template(template: str, user: Optional[Any] = None) -> str: template = template.replace("{{CURRENT_WEEKDAY}}", formatted_weekday) template = template.replace("{{USER_NAME}}", USER_VARIABLES.get("name", "Unknown")) + template = template.replace( + "{{USER_EMAIL}}", USER_VARIABLES.get("email", "Unknown") + ) template = template.replace("{{USER_BIO}}", USER_VARIABLES.get("bio", "Unknown")) template = template.replace( "{{USER_GENDER}}", USER_VARIABLES.get("gender", "Unknown") diff --git a/src/lib/components/channel/MessageInput.svelte b/src/lib/components/channel/MessageInput.svelte index bff703c51f..2b6c2b96ff 100644 --- a/src/lib/components/channel/MessageInput.svelte +++ b/src/lib/components/channel/MessageInput.svelte @@ -147,6 +147,14 @@ text = text.replaceAll('{{USER_NAME}}', name); } + if (text.includes('{{USER_EMAIL}}')) { + const email = sessionUser?.email || ''; + + if (email) { + text = text.replaceAll('{{USER_EMAIL}}', email); + } + } + if (text.includes('{{USER_BIO}}')) { const bio = sessionUser?.bio || ''; diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index d02bda4fa9..103da88f9a 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -221,6 +221,14 @@ text = text.replaceAll('{{USER_NAME}}', name); } + if (text.includes('{{USER_EMAIL}}')) { + const email = sessionUser?.email || ''; + + if (email) { + text = text.replaceAll('{{USER_EMAIL}}', email); + } + } + if (text.includes('{{USER_BIO}}')) { const bio = sessionUser?.bio || ''; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 265c47cec2..2ea221ab82 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -357,9 +357,9 @@ export const generateInitialsImage = (name) => { const initials = sanitizedName.length > 0 ? sanitizedName[0] + - (sanitizedName.split(' ').length > 1 - ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] - : '') + (sanitizedName.split(' ').length > 1 + ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] + : '') : ''; ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); @@ -515,10 +515,10 @@ export const compareVersion = (latest, current) => { return current === '0.0.0' ? false : current.localeCompare(latest, undefined, { - numeric: true, - sensitivity: 'case', - caseFirst: 'upper' - }) < 0; + numeric: true, + sensitivity: 'case', + caseFirst: 'upper' + }) < 0; }; export const extractCurlyBraceWords = (text) => { @@ -973,9 +973,10 @@ export const blobToFile = (blob, fileName) => { return file; }; -export const getPromptVariables = (user_name, user_location) => { +export const getPromptVariables = (user_name, user_location, user_email = '') => { return { '{{USER_NAME}}': user_name, + '{{USER_EMAIL}}': user_email || 'Unknown', '{{USER_LOCATION}}': user_location || 'Unknown', '{{CURRENT_DATETIME}}': getCurrentDateTime(), '{{CURRENT_DATE}}': getFormattedDate(), From 4c6f100b5fe2145a3d676b70b5f7c0e7f07cee20 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 23 Jan 2026 00:56:50 +0400 Subject: [PATCH 040/120] refac --- src/lib/utils/index.ts | 52 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 2ea221ab82..96f290a2b7 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -32,6 +32,18 @@ function escapeRegExp(string: string): string { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } +// Replace tokens outside code blocks only +export const replaceOutsideCode = (content: string, replacer: (str: string) => string) => { + return content + .split(/(```[\s\S]*?```|`[\s\S]*?`)/) + .map((segment) => { + return segment.startsWith('```') || segment.startsWith('`') + ? segment + : replacer(segment); + }) + .join(''); +}; + export const replaceTokens = (content, char, user) => { const tokens = [ { regex: /{{char}}/gi, replacement: char }, @@ -47,20 +59,8 @@ export const replaceTokens = (content, char, user) => { } ]; - // Replace tokens outside code blocks only - const processOutsideCodeBlocks = (text, replacementFn) => { - return text - .split(/(```[\s\S]*?```|`[\s\S]*?`)/) - .map((segment) => { - return segment.startsWith('```') || segment.startsWith('`') - ? segment - : replacementFn(segment); - }) - .join(''); - }; - // Apply replacements - content = processOutsideCodeBlocks(content, (segment) => { + content = replaceOutsideCode(content, (segment) => { tokens.forEach(({ regex, replacement }) => { if (replacement !== undefined && replacement !== null) { segment = segment.replace(regex, replacement); @@ -841,19 +841,21 @@ export const cleanText = (content: string) => { }; export const removeDetails = (content, types) => { - for (const type of types) { - content = content.replace( - new RegExp(`]*>.*?<\\/details>`, 'gis'), - '' - ); - } - - return content; + return replaceOutsideCode(content, (segment) => { + for (const type of types) { + segment = segment.replace( + new RegExp(`]*>.*?<\\/details>`, 'gis'), + '' + ); + } + return segment; + }); }; export const removeAllDetails = (content) => { - content = content.replace(/]*>.*?<\/details>/gis, ''); - return content; + return replaceOutsideCode(content, (segment) => { + return segment.replace(/]*>.*?<\/details>/gis, ''); + }); }; export const processDetails = (content) => { @@ -1655,6 +1657,10 @@ export const getCodeBlockContents = (content: string): object => { } }); } else { + // Remove details tags from the content to check if there are any code blocks + // hidden in the details tags (e.g. reasoning, etc.) + content = removeAllDetails(content); + const inlineHtml = content.match(/[\s\S]*?<\/html>/gi); const inlineCss = content.match(/