Browse Source

Merge branch 'origin/dev' into sidebar-pagination [skip ci]

Aryan Kothari 9 months ago
parent
commit
6847c2fc8c
80 changed files with 3042 additions and 1779 deletions
  1. 31 0
      CHANGELOG.md
  2. 1 1
      Dockerfile
  3. 71 4
      backend/apps/audio/main.py
  4. 15 0
      backend/apps/images/main.py
  5. 165 8
      backend/apps/images/utils/comfyui.py
  6. 6 0
      backend/apps/ollama/main.py
  7. 2 4
      backend/apps/socket/main.py
  8. 225 302
      backend/apps/webui/main.py
  9. 2 10
      backend/apps/webui/models/models.py
  10. 15 2
      backend/apps/webui/routers/utils.py
  11. 39 0
      backend/config.py
  12. 22 48
      backend/main.py
  13. 2 1
      backend/requirements.txt
  14. 39 32
      backend/utils/misc.py
  15. 11 2
      package-lock.json
  16. 2 1
      package.json
  17. 30 15
      pyproject.toml
  18. 91 28
      requirements-dev.lock
  19. 91 28
      requirements.lock
  20. 4 0
      src/app.css
  21. 56 0
      src/lib/apis/audio/index.ts
  22. 56 41
      src/lib/components/admin/Settings/Audio.svelte
  23. 4 4
      src/lib/components/chat/Chat.svelte
  24. 0 4
      src/lib/components/chat/ChatControls.svelte
  25. 7 11
      src/lib/components/chat/Controls/Controls.svelte
  26. 36 38
      src/lib/components/chat/Controls/Valves.svelte
  27. 43 33
      src/lib/components/chat/MessageInput.svelte
  28. 3 1
      src/lib/components/chat/Messages/ResponseMessage.svelte
  29. 1 0
      src/lib/components/chat/Messages/UserMessage.svelte
  30. 22 9
      src/lib/components/chat/ModelSelector/Selector.svelte
  31. 47 0
      src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
  32. 31 25
      src/lib/components/chat/Settings/Audio.svelte
  33. 0 32
      src/lib/components/chat/SettingsModal.svelte
  34. 20 2
      src/lib/components/common/FileItem.svelte
  35. 12 9
      src/lib/components/common/ImagePreview.svelte
  36. 2 2
      src/lib/components/common/SensitiveInput.svelte
  37. 18 4
      src/lib/components/common/Valves.svelte
  38. 1 1
      src/lib/i18n/locales/ar-BH/translation.json
  39. 1 1
      src/lib/i18n/locales/bg-BG/translation.json
  40. 1 1
      src/lib/i18n/locales/bn-BD/translation.json
  41. 8 8
      src/lib/i18n/locales/ca-ES/translation.json
  42. 1 1
      src/lib/i18n/locales/ceb-PH/translation.json
  43. 1 1
      src/lib/i18n/locales/de-DE/translation.json
  44. 1 1
      src/lib/i18n/locales/dg-DG/translation.json
  45. 1 1
      src/lib/i18n/locales/en-GB/translation.json
  46. 1 1
      src/lib/i18n/locales/en-US/translation.json
  47. 1 1
      src/lib/i18n/locales/es-ES/translation.json
  48. 1 1
      src/lib/i18n/locales/fa-IR/translation.json
  49. 1 1
      src/lib/i18n/locales/fi-FI/translation.json
  50. 1 1
      src/lib/i18n/locales/fr-CA/translation.json
  51. 1 1
      src/lib/i18n/locales/fr-FR/translation.json
  52. 1 1
      src/lib/i18n/locales/he-IL/translation.json
  53. 1 1
      src/lib/i18n/locales/hi-IN/translation.json
  54. 1 1
      src/lib/i18n/locales/hr-HR/translation.json
  55. 1 1
      src/lib/i18n/locales/id-ID/translation.json
  56. 1 1
      src/lib/i18n/locales/it-IT/translation.json
  57. 1 1
      src/lib/i18n/locales/ja-JP/translation.json
  58. 1 1
      src/lib/i18n/locales/ka-GE/translation.json
  59. 1 1
      src/lib/i18n/locales/ko-KR/translation.json
  60. 4 0
      src/lib/i18n/locales/languages.json
  61. 1 1
      src/lib/i18n/locales/lt-LT/translation.json
  62. 214 214
      src/lib/i18n/locales/nb-NO/translation.json
  63. 1 1
      src/lib/i18n/locales/nl-NL/translation.json
  64. 1 1
      src/lib/i18n/locales/pa-IN/translation.json
  65. 1 1
      src/lib/i18n/locales/pl-PL/translation.json
  66. 698 698
      src/lib/i18n/locales/pt-BR/translation.json
  67. 1 1
      src/lib/i18n/locales/pt-PT/translation.json
  68. 715 0
      src/lib/i18n/locales/ro-RO/translation.json
  69. 1 1
      src/lib/i18n/locales/ru-RU/translation.json
  70. 1 1
      src/lib/i18n/locales/sr-RS/translation.json
  71. 1 1
      src/lib/i18n/locales/sv-SE/translation.json
  72. 1 1
      src/lib/i18n/locales/th-TH/translation.json
  73. 1 1
      src/lib/i18n/locales/tk-TW/translation.json
  74. 1 1
      src/lib/i18n/locales/tr-TR/translation.json
  75. 11 11
      src/lib/i18n/locales/uk-UA/translation.json
  76. 1 1
      src/lib/i18n/locales/vi-VN/translation.json
  77. 1 1
      src/lib/i18n/locales/zh-CN/translation.json
  78. 1 1
      src/lib/i18n/locales/zh-TW/translation.json
  79. 55 43
      src/routes/(app)/admin/+layout.svelte
  80. 80 69
      src/routes/(app)/workspace/+layout.svelte

+ 31 - 0
CHANGELOG.md

@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [0.3.11] - 2024-08-02
+
+### Added
+
+- **📊 Model Information Display**: Added visuals for model selection, including images next to model names for more intuitive navigation.
+- **🗣 ElevenLabs Voice Adaptations**: Voice enhancements including support for ElevenLabs voice ID by name for personalized vocal interactions.
+- **⌨️ Arrow Keys Model Selection**: Users can now use arrow keys for quicker model selection, enhancing accessibility.
+- **🔍 Fuzzy Search in Model Selector**: Enhanced model selector with fuzzy search to locate models swiftly, including descriptions.
+- **🕹️ ComfyUI Flux Image Generation**: Added support for the new Flux image gen model; introduces environment controls like weight precision and CLIP model options in Settings.
+- **💾 Display File Size for Uploads**: Enhanced file interface now displays file size, preparing for upcoming upload restrictions.
+- **🎚️ Advanced Params "Min P"**: Added 'Min P' parameter in the advanced settings for customized model precision control.
+- **🔒 Enhanced OAuth**: Introduced custom redirect URI support for OAuth behind reverse proxies, enabling safer authentication processes.
+- **🖥 Enhanced Latex Rendering**: Adjustments made to latex rendering processes, now accurately detecting and presenting latex inputs from text.
+- **🌐 Internationalization**: Enhanced with new Romanian and updated Vietnamese and Ukrainian translations, helping broaden accessibility for international users.
+
+### Fixed
+
+- **🔧 Tags Handling in Document Upload**: Tags are now properly sent to the upload document handler, resolving issues with missing metadata.
+- **🖥️ Sensitive Input Fields**: Corrected browser misinterpretation of secure input fields, preventing misclassification as password fields.
+- **📂 Static Path Resolution in PDF Generation**: Fixed static paths that adjust dynamically to prevent issues across various environments.
+
+### Changed
+
+- **🎨 UI/UX Styling Enhancements**: Multiple minor styling updates for a cleaner and more intuitive user interface.
+- **🚧 Refactoring Various Components**: Numerous refactoring changes across styling, file handling, and function simplifications for clarity and performance.
+- **🎛️ User Valves Management**: Moved user valves from settings to direct chat controls for more user-friendly access during interactions.
+
+### Removed
+
+- **⚙️ Health Check Logging**: Removed verbose logging from the health checking processes to declutter logs and improve backend performance.
+
 ## [0.3.10] - 2024-07-17
 
 ### Fixed

+ 1 - 1
Dockerfile

@@ -151,7 +151,7 @@ COPY --chown=$UID:$GID ./backend .
 
 EXPOSE 8080
 
-HEALTHCHECK CMD curl --silent --fail http://localhost:8080/health | jq -e '.status == true' || exit 1
+HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq -ne 'input.status == true' || exit 1
 
 USER $UID:$GID
 

+ 71 - 4
backend/apps/audio/main.py

@@ -10,12 +10,12 @@ from fastapi import (
     File,
     Form,
 )
-
 from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
 
 from fastapi.middleware.cors import CORSMiddleware
 from pydantic import BaseModel
 
+from typing import List
 import uuid
 import requests
 import hashlib
@@ -31,6 +31,7 @@ from utils.utils import (
 )
 from utils.misc import calculate_sha256
 
+
 from config import (
     SRC_LOG_LEVELS,
     CACHE_DIR,
@@ -252,15 +253,15 @@ async def speech(request: Request, user=Depends(get_verified_user)):
             )
 
     elif app.state.config.TTS_ENGINE == "elevenlabs":
-
         payload = None
         try:
             payload = json.loads(body.decode("utf-8"))
         except Exception as e:
             log.exception(e)
-            pass
+            raise HTTPException(status_code=400, detail="Invalid JSON payload")
 
-        url = f"https://api.elevenlabs.io/v1/text-to-speech/{payload['voice']}"
+        voice_id = payload.get("voice", "")
+        url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
 
         headers = {
             "Accept": "audio/mpeg",
@@ -435,3 +436,69 @@ def transcribe(
             status_code=status.HTTP_400_BAD_REQUEST,
             detail=ERROR_MESSAGES.DEFAULT(e),
         )
+
+
+def get_available_models() -> List[dict]:
+    if app.state.config.TTS_ENGINE == "openai":
+        return [{"id": "tts-1"}, {"id": "tts-1-hd"}]
+    elif app.state.config.TTS_ENGINE == "elevenlabs":
+        headers = {
+            "xi-api-key": app.state.config.TTS_API_KEY,
+            "Content-Type": "application/json",
+        }
+
+        try:
+            response = requests.get(
+                "https://api.elevenlabs.io/v1/models", headers=headers
+            )
+            response.raise_for_status()
+            models = response.json()
+            return [
+                {"name": model["name"], "id": model["model_id"]} for model in models
+            ]
+        except requests.RequestException as e:
+            log.error(f"Error fetching voices: {str(e)}")
+    return []
+
+
+@app.get("/models")
+async def get_models(user=Depends(get_verified_user)):
+    return {"models": get_available_models()}
+
+
+def get_available_voices() -> List[dict]:
+    if app.state.config.TTS_ENGINE == "openai":
+        return [
+            {"name": "alloy", "id": "alloy"},
+            {"name": "echo", "id": "echo"},
+            {"name": "fable", "id": "fable"},
+            {"name": "onyx", "id": "onyx"},
+            {"name": "nova", "id": "nova"},
+            {"name": "shimmer", "id": "shimmer"},
+        ]
+    elif app.state.config.TTS_ENGINE == "elevenlabs":
+        headers = {
+            "xi-api-key": app.state.config.TTS_API_KEY,
+            "Content-Type": "application/json",
+        }
+
+        try:
+            response = requests.get(
+                "https://api.elevenlabs.io/v1/voices", headers=headers
+            )
+            response.raise_for_status()
+            voices_data = response.json()
+
+            voices = []
+            for voice in voices_data.get("voices", []):
+                voices.append({"name": voice["name"], "id": voice["voice_id"]})
+            return voices
+        except requests.RequestException as e:
+            log.error(f"Error fetching voices: {str(e)}")
+
+    return []
+
+
+@app.get("/voices")
+async def get_voices(user=Depends(get_verified_user)):
+    return {"voices": get_available_voices()}

+ 15 - 0
backend/apps/images/main.py

@@ -42,6 +42,9 @@ from config import (
     COMFYUI_SAMPLER,
     COMFYUI_SCHEDULER,
     COMFYUI_SD3,
+    COMFYUI_FLUX,
+    COMFYUI_FLUX_WEIGHT_DTYPE,
+    COMFYUI_FLUX_FP8_CLIP,
     IMAGES_OPENAI_API_BASE_URL,
     IMAGES_OPENAI_API_KEY,
     IMAGE_GENERATION_MODEL,
@@ -85,6 +88,9 @@ app.state.config.COMFYUI_CFG_SCALE = COMFYUI_CFG_SCALE
 app.state.config.COMFYUI_SAMPLER = COMFYUI_SAMPLER
 app.state.config.COMFYUI_SCHEDULER = COMFYUI_SCHEDULER
 app.state.config.COMFYUI_SD3 = COMFYUI_SD3
+app.state.config.COMFYUI_FLUX = COMFYUI_FLUX
+app.state.config.COMFYUI_FLUX_WEIGHT_DTYPE = COMFYUI_FLUX_WEIGHT_DTYPE
+app.state.config.COMFYUI_FLUX_FP8_CLIP = COMFYUI_FLUX_FP8_CLIP
 
 
 def get_automatic1111_api_auth():
@@ -497,6 +503,15 @@ async def image_generations(
             if app.state.config.COMFYUI_SD3 is not None:
                 data["sd3"] = app.state.config.COMFYUI_SD3
 
+            if app.state.config.COMFYUI_FLUX is not None:
+                data["flux"] = app.state.config.COMFYUI_FLUX
+
+            if app.state.config.COMFYUI_FLUX_WEIGHT_DTYPE is not None:
+                data["flux_weight_dtype"] = app.state.config.COMFYUI_FLUX_WEIGHT_DTYPE
+
+            if app.state.config.COMFYUI_FLUX_FP8_CLIP is not None:
+                data["flux_fp8_clip"] = app.state.config.COMFYUI_FLUX_FP8_CLIP
+
             data = ImageGenerationPayload(**data)
 
             res = comfyui_generate_image(

+ 165 - 8
backend/apps/images/utils/comfyui.py

@@ -125,6 +125,135 @@ COMFYUI_DEFAULT_PROMPT = """
 }
 """
 
+FLUX_DEFAULT_PROMPT = """
+{
+    "5": {
+        "inputs": {
+            "width": 1024,
+            "height": 1024,
+            "batch_size": 1
+        },
+        "class_type": "EmptyLatentImage"
+    },
+    "6": {
+        "inputs": {
+            "text": "Input Text Here",
+            "clip": [
+                "11",
+                0
+            ]
+        },
+        "class_type": "CLIPTextEncode"
+    },
+    "8": {
+        "inputs": {
+            "samples": [
+                "13",
+                0
+            ],
+            "vae": [
+                "10",
+                0
+            ]
+        },
+        "class_type": "VAEDecode"
+    },
+    "9": {
+        "inputs": {
+            "filename_prefix": "ComfyUI",
+            "images": [
+                "8",
+                0
+            ]
+        },
+        "class_type": "SaveImage"
+    },
+    "10": {
+        "inputs": {
+            "vae_name": "ae.sft"
+        },
+        "class_type": "VAELoader"
+    },
+    "11": {
+        "inputs": {
+            "clip_name1": "clip_l.safetensors",
+            "clip_name2": "t5xxl_fp16.safetensors",
+            "type": "flux"
+        },
+        "class_type": "DualCLIPLoader"
+    },
+    "12": {
+        "inputs": {
+            "unet_name": "flux1-dev.sft",
+            "weight_dtype": "default"
+        },
+        "class_type": "UNETLoader"
+    },
+    "13": {
+        "inputs": {
+            "noise": [
+                "25",
+                0
+            ],
+            "guider": [
+                "22",
+                0
+            ],
+            "sampler": [
+                "16",
+                0
+            ],
+            "sigmas": [
+                "17",
+                0
+            ],
+            "latent_image": [
+                "5",
+                0
+            ]
+        },
+        "class_type": "SamplerCustomAdvanced"
+    },
+    "16": {
+        "inputs": {
+            "sampler_name": "euler"
+        },
+        "class_type": "KSamplerSelect"
+    },
+    "17": {
+        "inputs": {
+            "scheduler": "simple",
+            "steps": 20,
+            "denoise": 1,
+            "model": [
+                "12",
+                0
+            ]
+        },
+        "class_type": "BasicScheduler"
+    },
+    "22": {
+        "inputs": {
+            "model": [
+                "12",
+                0
+            ],
+            "conditioning": [
+                "6",
+                0
+            ]
+        },
+        "class_type": "BasicGuider"
+    },
+    "25": {
+        "inputs": {
+            "noise_seed": 778937779713005
+        },
+        "class_type": "RandomNoise"
+    }
+}
+"""
+
 
 def queue_prompt(prompt, client_id, base_url):
     log.info("queue_prompt")
@@ -194,6 +323,9 @@ class ImageGenerationPayload(BaseModel):
     sampler: Optional[str] = None
     scheduler: Optional[str] = None
     sd3: Optional[bool] = None
+    flux: Optional[bool] = None
+    flux_weight_dtype: Optional[str] = None
+    flux_fp8_clip: Optional[bool] = None
 
 
 def comfyui_generate_image(
@@ -215,21 +347,46 @@ def comfyui_generate_image(
     if payload.sd3:
         comfyui_prompt["5"]["class_type"] = "EmptySD3LatentImage"
 
+    if payload.steps:
+        comfyui_prompt["3"]["inputs"]["steps"] = payload.steps
+
     comfyui_prompt["4"]["inputs"]["ckpt_name"] = model
+    comfyui_prompt["7"]["inputs"]["text"] = payload.negative_prompt
+    comfyui_prompt["3"]["inputs"]["seed"] = (
+        payload.seed if payload.seed else random.randint(0, 18446744073709551614)
+    )
+
+    # as Flux uses a completely different workflow, we must treat it specially
+    if payload.flux:
+        comfyui_prompt = json.loads(FLUX_DEFAULT_PROMPT)
+        comfyui_prompt["12"]["inputs"]["unet_name"] = model
+        comfyui_prompt["25"]["inputs"]["noise_seed"] = (
+            payload.seed if payload.seed else random.randint(0, 18446744073709551614)
+        )
+
+        if payload.sampler:
+            comfyui_prompt["16"]["inputs"]["sampler_name"] = payload.sampler
+
+        if payload.steps:
+            comfyui_prompt["17"]["inputs"]["steps"] = payload.steps
+
+        if payload.scheduler:
+            comfyui_prompt["17"]["inputs"]["scheduler"] = payload.scheduler
+
+        if payload.flux_weight_dtype:
+            comfyui_prompt["12"]["inputs"]["weight_dtype"] = payload.flux_weight_dtype
+
+        if payload.flux_fp8_clip:
+            comfyui_prompt["11"]["inputs"][
+                "clip_name2"
+            ] = "t5xxl_fp8_e4m3fn.safetensors"
+
     comfyui_prompt["5"]["inputs"]["batch_size"] = payload.n
     comfyui_prompt["5"]["inputs"]["width"] = payload.width
     comfyui_prompt["5"]["inputs"]["height"] = payload.height
 
     # set the text prompt for our positive CLIPTextEncode
     comfyui_prompt["6"]["inputs"]["text"] = payload.prompt
-    comfyui_prompt["7"]["inputs"]["text"] = payload.negative_prompt
-
-    if payload.steps:
-        comfyui_prompt["3"]["inputs"]["steps"] = payload.steps
-
-    comfyui_prompt["3"]["inputs"]["seed"] = (
-        payload.seed if payload.seed else random.randint(0, 18446744073709551614)
-    )
 
     try:
         ws = websocket.WebSocket()

+ 6 - 0
backend/apps/ollama/main.py

@@ -857,6 +857,12 @@ async def generate_chat_completion(
             ):
                 payload["options"]["top_p"] = model_info.params.get("top_p", None)
 
+            if (
+                model_info.params.get("min_p", None)
+                and payload["options"].get("min_p") is None
+            ):
+                payload["options"]["min_p"] = model_info.params.get("min_p", None)
+
             if (
                 model_info.params.get("use_mmap", None)
                 and payload["options"].get("use_mmap") is None

+ 2 - 4
backend/apps/socket/main.py

@@ -52,7 +52,6 @@ async def user_join(sid, data):
             user = Users.get_user_by_id(data["id"])
 
         if user:
-
             SESSION_POOL[sid] = user.id
             if user.id in USER_POOL:
                 USER_POOL[user.id].append(sid)
@@ -80,7 +79,6 @@ def get_models_in_use():
 
 @sio.on("usage")
 async def usage(sid, data):
-
     model_id = data["model"]
 
     # Cancel previous callback if there is one
@@ -139,7 +137,7 @@ async def disconnect(sid):
         print(f"Unknown session ID {sid} disconnected")
 
 
-async def get_event_emitter(request_info):
+def get_event_emitter(request_info):
     async def __event_emitter__(event_data):
         await sio.emit(
             "chat-events",
@@ -154,7 +152,7 @@ async def get_event_emitter(request_info):
     return __event_emitter__
 
 
-async def get_event_call(request_info):
+def get_event_call(request_info):
     async def __event_call__(event_data):
         response = await sio.call(
             "chat-events",

+ 225 - 302
backend/apps/webui/main.py

@@ -1,9 +1,6 @@
-from fastapi import FastAPI, Depends
-from fastapi.routing import APIRoute
+from fastapi import FastAPI
 from fastapi.responses import StreamingResponse
 from fastapi.middleware.cors import CORSMiddleware
-from starlette.middleware.sessions import SessionMiddleware
-from sqlalchemy.orm import Session
 from apps.webui.routers import (
     auths,
     users,
@@ -22,12 +19,15 @@ from apps.webui.models.functions import Functions
 from apps.webui.models.models import Models
 from apps.webui.utils import load_function_module_by_id
 
-from utils.misc import stream_message_template
+from utils.misc import (
+    openai_chat_chunk_message_template,
+    openai_chat_completion_message_template,
+    add_or_update_system_message,
+)
 from utils.task import prompt_template
 
 
 from config import (
-    WEBUI_BUILD_HASH,
     SHOW_ADMIN_DETAILS,
     ADMIN_EMAIL,
     WEBUI_AUTH,
@@ -51,11 +51,9 @@ from config import (
 from apps.socket.main import get_event_call, get_event_emitter
 
 import inspect
-import uuid
-import time
 import json
 
-from typing import Iterator, Generator, AsyncGenerator, Optional
+from typing import Iterator, Generator, AsyncGenerator
 from pydantic import BaseModel
 
 app = FastAPI()
@@ -127,60 +125,58 @@ async def get_status():
     }
 
 
+def get_function_module(pipe_id: str):
+    # Check if function is already loaded
+    if pipe_id not in app.state.FUNCTIONS:
+        function_module, _, _ = load_function_module_by_id(pipe_id)
+        app.state.FUNCTIONS[pipe_id] = function_module
+    else:
+        function_module = app.state.FUNCTIONS[pipe_id]
+
+    if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
+        valves = Functions.get_function_valves_by_id(pipe_id)
+        function_module.valves = function_module.Valves(**(valves if valves else {}))
+    return function_module
+
+
 async def get_pipe_models():
     pipes = Functions.get_functions_by_type("pipe", active_only=True)
     pipe_models = []
 
     for pipe in pipes:
-        # Check if function is already loaded
-        if pipe.id not in app.state.FUNCTIONS:
-            function_module, function_type, frontmatter = load_function_module_by_id(
-                pipe.id
-            )
-            app.state.FUNCTIONS[pipe.id] = function_module
-        else:
-            function_module = app.state.FUNCTIONS[pipe.id]
-
-        if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
-            valves = Functions.get_function_valves_by_id(pipe.id)
-            function_module.valves = function_module.Valves(
-                **(valves if valves else {})
-            )
+        function_module = get_function_module(pipe.id)
 
         # Check if function is a manifold
-        if hasattr(function_module, "type"):
-            if function_module.type == "manifold":
-                manifold_pipes = []
-
-                # Check if pipes is a function or a list
-                if callable(function_module.pipes):
-                    manifold_pipes = function_module.pipes()
-                else:
-                    manifold_pipes = function_module.pipes
-
-                for p in manifold_pipes:
-                    manifold_pipe_id = f'{pipe.id}.{p["id"]}'
-                    manifold_pipe_name = p["name"]
-
-                    if hasattr(function_module, "name"):
-                        manifold_pipe_name = (
-                            f"{function_module.name}{manifold_pipe_name}"
-                        )
-
-                    pipe_flag = {"type": pipe.type}
-                    if hasattr(function_module, "ChatValves"):
-                        pipe_flag["valves_spec"] = function_module.ChatValves.schema()
-
-                    pipe_models.append(
-                        {
-                            "id": manifold_pipe_id,
-                            "name": manifold_pipe_name,
-                            "object": "model",
-                            "created": pipe.created_at,
-                            "owned_by": "openai",
-                            "pipe": pipe_flag,
-                        }
-                    )
+        if hasattr(function_module, "pipes"):
+            manifold_pipes = []
+
+            # Check if pipes is a function or a list
+            if callable(function_module.pipes):
+                manifold_pipes = function_module.pipes()
+            else:
+                manifold_pipes = function_module.pipes
+
+            for p in manifold_pipes:
+                manifold_pipe_id = f'{pipe.id}.{p["id"]}'
+                manifold_pipe_name = p["name"]
+
+                if hasattr(function_module, "name"):
+                    manifold_pipe_name = f"{function_module.name}{manifold_pipe_name}"
+
+                pipe_flag = {"type": pipe.type}
+                if hasattr(function_module, "ChatValves"):
+                    pipe_flag["valves_spec"] = function_module.ChatValves.schema()
+
+                pipe_models.append(
+                    {
+                        "id": manifold_pipe_id,
+                        "name": manifold_pipe_name,
+                        "object": "model",
+                        "created": pipe.created_at,
+                        "owned_by": "openai",
+                        "pipe": pipe_flag,
+                    }
+                )
         else:
             pipe_flag = {"type": "pipe"}
             if hasattr(function_module, "ChatValves"):
@@ -200,284 +196,211 @@ async def get_pipe_models():
     return pipe_models
 
 
-async def generate_function_chat_completion(form_data, user):
-    model_id = form_data.get("model")
-    model_info = Models.get_model_by_id(model_id)
+async def execute_pipe(pipe, params):
+    if inspect.iscoroutinefunction(pipe):
+        return await pipe(**params)
+    else:
+        return pipe(**params)
 
-    metadata = None
-    if "metadata" in form_data:
-        metadata = form_data["metadata"]
-        del form_data["metadata"]
 
-    __event_emitter__ = None
-    __event_call__ = None
-    __task__ = None
+async def get_message_content(res: str | Generator | AsyncGenerator) -> str:
+    if isinstance(res, str):
+        return res
+    if isinstance(res, Generator):
+        return "".join(map(str, res))
+    if isinstance(res, AsyncGenerator):
+        return "".join([str(stream) async for stream in res])
 
-    if metadata:
-        if (
-            metadata.get("session_id")
-            and metadata.get("chat_id")
-            and metadata.get("message_id")
-        ):
-            __event_emitter__ = await get_event_emitter(metadata)
-            __event_call__ = await get_event_call(metadata)
 
-        if metadata.get("task"):
-            __task__ = metadata.get("task")
+def process_line(form_data: dict, line):
+    if isinstance(line, BaseModel):
+        line = line.model_dump_json()
+        line = f"data: {line}"
+    if isinstance(line, dict):
+        line = f"data: {json.dumps(line)}"
 
-    if model_info:
-        if model_info.base_model_id:
-            form_data["model"] = model_info.base_model_id
+    try:
+        line = line.decode("utf-8")
+    except Exception:
+        pass
 
-        model_info.params = model_info.params.model_dump()
+    if line.startswith("data:"):
+        return f"{line}\n\n"
+    else:
+        line = openai_chat_chunk_message_template(form_data["model"], line)
+        return f"data: {json.dumps(line)}\n\n"
+
+
+def get_pipe_id(form_data: dict) -> str:
+    pipe_id = form_data["model"]
+    if "." in pipe_id:
+        pipe_id, _ = pipe_id.split(".", 1)
+    print(pipe_id)
+    return pipe_id
+
+
+def get_function_params(function_module, form_data, user, extra_params={}):
+    pipe_id = get_pipe_id(form_data)
+    # Get the signature of the function
+    sig = inspect.signature(function_module.pipe)
+    params = {"body": form_data}
+
+    for key, value in extra_params.items():
+        if key in sig.parameters:
+            params[key] = value
+
+    if "__user__" in sig.parameters:
+        __user__ = {
+            "id": user.id,
+            "email": user.email,
+            "name": user.name,
+            "role": user.role,
+        }
+
+        try:
+            if hasattr(function_module, "UserValves"):
+                __user__["valves"] = function_module.UserValves(
+                    **Functions.get_user_valves_by_id_and_user_id(pipe_id, user.id)
+                )
+        except Exception as e:
+            print(e)
 
-        if model_info.params:
-            if model_info.params.get("temperature", None) is not None:
-                form_data["temperature"] = float(model_info.params.get("temperature"))
+        params["__user__"] = __user__
+    return params
 
-            if model_info.params.get("top_p", None):
-                form_data["top_p"] = int(model_info.params.get("top_p", None))
 
-            if model_info.params.get("max_tokens", None):
-                form_data["max_tokens"] = int(model_info.params.get("max_tokens", None))
+# inplace function: form_data is modified
+def apply_model_params_to_body(params: dict, form_data: dict) -> dict:
+    if not params:
+        return form_data
 
-            if model_info.params.get("frequency_penalty", None):
-                form_data["frequency_penalty"] = int(
-                    model_info.params.get("frequency_penalty", None)
-                )
+    mappings = {
+        "temperature": float,
+        "top_p": int,
+        "max_tokens": int,
+        "frequency_penalty": int,
+        "seed": lambda x: x,
+        "stop": lambda x: [bytes(s, "utf-8").decode("unicode_escape") for s in x],
+    }
 
-            if model_info.params.get("seed", None):
-                form_data["seed"] = model_info.params.get("seed", None)
-
-            if model_info.params.get("stop", None):
-                form_data["stop"] = (
-                    [
-                        bytes(stop, "utf-8").decode("unicode_escape")
-                        for stop in model_info.params["stop"]
-                    ]
-                    if model_info.params.get("stop", None)
-                    else None
-                )
+    for key, cast_func in mappings.items():
+        if (value := params.get(key)) is not None:
+            form_data[key] = cast_func(value)
 
-        system = model_info.params.get("system", None)
-        if system:
-            system = prompt_template(
-                system,
-                **(
-                    {
-                        "user_name": user.name,
-                        "user_location": (
-                            user.info.get("location") if user.info else None
-                        ),
-                    }
-                    if user
-                    else {}
-                ),
-            )
-            # Check if the payload already has a system message
-            # If not, add a system message to the payload
-            if form_data.get("messages"):
-                for message in form_data["messages"]:
-                    if message.get("role") == "system":
-                        message["content"] = system + message["content"]
-                        break
-                else:
-                    form_data["messages"].insert(
-                        0,
-                        {
-                            "role": "system",
-                            "content": system,
-                        },
-                    )
+    return form_data
 
-    else:
-        pass
 
-    async def job():
-        pipe_id = form_data["model"]
-        if "." in pipe_id:
-            pipe_id, sub_pipe_id = pipe_id.split(".", 1)
-        print(pipe_id)
+# inplace function: form_data is modified
+def apply_model_system_prompt_to_body(params: dict, form_data: dict, user) -> dict:
+    system = params.get("system", None)
+    if not system:
+        return form_data
 
-        # Check if function is already loaded
-        if pipe_id not in app.state.FUNCTIONS:
-            function_module, function_type, frontmatter = load_function_module_by_id(
-                pipe_id
-            )
-            app.state.FUNCTIONS[pipe_id] = function_module
-        else:
-            function_module = app.state.FUNCTIONS[pipe_id]
+    if user:
+        template_params = {
+            "user_name": user.name,
+            "user_location": user.info.get("location") if user.info else None,
+        }
+    else:
+        template_params = {}
+    system = prompt_template(system, **template_params)
+    form_data["messages"] = add_or_update_system_message(
+        system, form_data.get("messages", [])
+    )
+    return form_data
 
-        if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
 
-            valves = Functions.get_function_valves_by_id(pipe_id)
-            function_module.valves = function_module.Valves(
-                **(valves if valves else {})
-            )
+async def generate_function_chat_completion(form_data, user):
+    model_id = form_data.get("model")
+    model_info = Models.get_model_by_id(model_id)
+    metadata = form_data.pop("metadata", None)
 
-        pipe = function_module.pipe
+    __event_emitter__ = None
+    __event_call__ = None
+    __task__ = None
 
-        # Get the signature of the function
-        sig = inspect.signature(pipe)
-        params = {"body": form_data}
+    if metadata:
+        if all(k in metadata for k in ("session_id", "chat_id", "message_id")):
+            __event_emitter__ = get_event_emitter(metadata)
+            __event_call__ = get_event_call(metadata)
+        __task__ = metadata.get("task", None)
 
-        if "__user__" in sig.parameters:
-            __user__ = {
-                "id": user.id,
-                "email": user.email,
-                "name": user.name,
-                "role": user.role,
-            }
+    if model_info:
+        if model_info.base_model_id:
+            form_data["model"] = model_info.base_model_id
 
-            try:
-                if hasattr(function_module, "UserValves"):
-                    __user__["valves"] = function_module.UserValves(
-                        **Functions.get_user_valves_by_id_and_user_id(pipe_id, user.id)
-                    )
-            except Exception as e:
-                print(e)
+        params = model_info.params.model_dump()
+        form_data = apply_model_params_to_body(params, form_data)
+        form_data = apply_model_system_prompt_to_body(params, form_data, user)
 
-            params = {**params, "__user__": __user__}
+    pipe_id = get_pipe_id(form_data)
+    function_module = get_function_module(pipe_id)
 
-        if "__event_emitter__" in sig.parameters:
-            params = {**params, "__event_emitter__": __event_emitter__}
+    pipe = function_module.pipe
+    params = get_function_params(
+        function_module,
+        form_data,
+        user,
+        {
+            "__event_emitter__": __event_emitter__,
+            "__event_call__": __event_call__,
+            "__task__": __task__,
+        },
+    )
 
-        if "__event_call__" in sig.parameters:
-            params = {**params, "__event_call__": __event_call__}
+    if form_data["stream"]:
 
-        if "__task__" in sig.parameters:
-            params = {**params, "__task__": __task__}
+        async def stream_content():
+            try:
+                res = await execute_pipe(pipe, params)
 
-        if form_data["stream"]:
+                # Directly return if the response is a StreamingResponse
+                if isinstance(res, StreamingResponse):
+                    async for data in res.body_iterator:
+                        yield data
+                    return
+                if isinstance(res, dict):
+                    yield f"data: {json.dumps(res)}\n\n"
+                    return
 
-            async def stream_content():
-                try:
-                    if inspect.iscoroutinefunction(pipe):
-                        res = await pipe(**params)
-                    else:
-                        res = pipe(**params)
+            except Exception as e:
+                print(f"Error: {e}")
+                yield f"data: {json.dumps({'error': {'detail':str(e)}})}\n\n"
+                return
 
-                    # Directly return if the response is a StreamingResponse
-                    if isinstance(res, StreamingResponse):
-                        async for data in res.body_iterator:
-                            yield data
-                        return
-                    if isinstance(res, dict):
-                        yield f"data: {json.dumps(res)}\n\n"
-                        return
+            if isinstance(res, str):
+                message = openai_chat_chunk_message_template(form_data["model"], res)
+                yield f"data: {json.dumps(message)}\n\n"
 
-                except Exception as e:
-                    print(f"Error: {e}")
-                    yield f"data: {json.dumps({'error': {'detail':str(e)}})}\n\n"
-                    return
+            if isinstance(res, Iterator):
+                for line in res:
+                    yield process_line(form_data, line)
 
-                if isinstance(res, str):
-                    message = stream_message_template(form_data["model"], res)
-                    yield f"data: {json.dumps(message)}\n\n"
-
-                if isinstance(res, Iterator):
-                    for line in res:
-                        if isinstance(line, BaseModel):
-                            line = line.model_dump_json()
-                            line = f"data: {line}"
-                        if isinstance(line, dict):
-                            line = f"data: {json.dumps(line)}"
-
-                        try:
-                            line = line.decode("utf-8")
-                        except:
-                            pass
-
-                        if line.startswith("data:"):
-                            yield f"{line}\n\n"
-                        else:
-                            line = stream_message_template(form_data["model"], line)
-                            yield f"data: {json.dumps(line)}\n\n"
-
-                if isinstance(res, str) or isinstance(res, Generator):
-                    finish_message = {
-                        "id": f"{form_data['model']}-{str(uuid.uuid4())}",
-                        "object": "chat.completion.chunk",
-                        "created": int(time.time()),
-                        "model": form_data["model"],
-                        "choices": [
-                            {
-                                "index": 0,
-                                "delta": {},
-                                "logprobs": None,
-                                "finish_reason": "stop",
-                            }
-                        ],
-                    }
+            if isinstance(res, AsyncGenerator):
+                async for line in res:
+                    yield process_line(form_data, line)
 
-                    yield f"data: {json.dumps(finish_message)}\n\n"
-                    yield f"data: [DONE]"
-
-                if isinstance(res, AsyncGenerator):
-                    async for line in res:
-                        if isinstance(line, BaseModel):
-                            line = line.model_dump_json()
-                            line = f"data: {line}"
-                        if isinstance(line, dict):
-                            line = f"data: {json.dumps(line)}"
-
-                        try:
-                            line = line.decode("utf-8")
-                        except:
-                            pass
-
-                        if line.startswith("data:"):
-                            yield f"{line}\n\n"
-                        else:
-                            line = stream_message_template(form_data["model"], line)
-                            yield f"data: {json.dumps(line)}\n\n"
-
-            return StreamingResponse(stream_content(), media_type="text/event-stream")
-        else:
+            if isinstance(res, str) or isinstance(res, Generator):
+                finish_message = openai_chat_chunk_message_template(
+                    form_data["model"], ""
+                )
+                finish_message["choices"][0]["finish_reason"] = "stop"
+                yield f"data: {json.dumps(finish_message)}\n\n"
+                yield "data: [DONE]"
 
-            try:
-                if inspect.iscoroutinefunction(pipe):
-                    res = await pipe(**params)
-                else:
-                    res = pipe(**params)
+        return StreamingResponse(stream_content(), media_type="text/event-stream")
+    else:
+        try:
+            res = await execute_pipe(pipe, params)
 
-                if isinstance(res, StreamingResponse):
-                    return res
-            except Exception as e:
-                print(f"Error: {e}")
-                return {"error": {"detail": str(e)}}
+        except Exception as e:
+            print(f"Error: {e}")
+            return {"error": {"detail": str(e)}}
 
-            if isinstance(res, dict):
-                return res
-            elif isinstance(res, BaseModel):
-                return res.model_dump()
-            else:
-                message = ""
-                if isinstance(res, str):
-                    message = res
-                elif isinstance(res, Generator):
-                    for stream in res:
-                        message = f"{message}{stream}"
-                elif isinstance(res, AsyncGenerator):
-                    async for stream in res:
-                        message = f"{message}{stream}"
-
-                return {
-                    "id": f"{form_data['model']}-{str(uuid.uuid4())}",
-                    "object": "chat.completion",
-                    "created": int(time.time()),
-                    "model": form_data["model"],
-                    "choices": [
-                        {
-                            "index": 0,
-                            "message": {
-                                "role": "assistant",
-                                "content": message,
-                            },
-                            "logprobs": None,
-                            "finish_reason": "stop",
-                        }
-                    ],
-                }
+        if isinstance(res, StreamingResponse) or isinstance(res, dict):
+            return res
+        if isinstance(res, BaseModel):
+            return res.model_dump()
 
-    return await job()
+        message = await get_message_content(res)
+        return openai_chat_completion_message_template(form_data["model"], message)

+ 2 - 10
backend/apps/webui/models/models.py

@@ -1,13 +1,11 @@
-import json
 import logging
-from typing import Optional
+from typing import Optional, List
 
 from pydantic import BaseModel, ConfigDict
-from sqlalchemy import String, Column, BigInteger, Text
+from sqlalchemy import Column, BigInteger, Text
 
 from apps.webui.internal.db import Base, JSONField, get_db
 
-from typing import List, Union, Optional
 from config import SRC_LOG_LEVELS
 
 import time
@@ -113,7 +111,6 @@ class ModelForm(BaseModel):
 
 
 class ModelsTable:
-
     def insert_new_model(
         self, form_data: ModelForm, user_id: str
     ) -> Optional[ModelModel]:
@@ -126,9 +123,7 @@ class ModelsTable:
             }
         )
         try:
-
             with get_db() as db:
-
                 result = Model(**model.model_dump())
                 db.add(result)
                 db.commit()
@@ -144,13 +139,11 @@ class ModelsTable:
 
     def get_all_models(self) -> List[ModelModel]:
         with get_db() as db:
-
             return [ModelModel.model_validate(model) for model in db.query(Model).all()]
 
     def get_model_by_id(self, id: str) -> Optional[ModelModel]:
         try:
             with get_db() as db:
-
                 model = db.get(Model, id)
                 return ModelModel.model_validate(model)
         except:
@@ -178,7 +171,6 @@ class ModelsTable:
     def delete_model_by_id(self, id: str) -> bool:
         try:
             with get_db() as db:
-
                 db.query(Model).filter_by(id=id).delete()
                 db.commit()
 

+ 15 - 2
backend/apps/webui/routers/utils.py

@@ -1,3 +1,6 @@
+from pathlib import Path
+import site
+
 from fastapi import APIRouter, UploadFile, File, Response
 from fastapi import Depends, HTTPException, status
 from starlette.responses import StreamingResponse, FileResponse
@@ -64,8 +67,18 @@ async def download_chat_as_pdf(
     pdf = FPDF()
     pdf.add_page()
 
-    STATIC_DIR = "./static"
-    FONTS_DIR = f"{STATIC_DIR}/fonts"
+    # When running in docker, workdir is /app/backend, so fonts is in /app/backend/static/fonts
+    FONTS_DIR = Path("./static/fonts")
+
+    # Non Docker Installation
+
+    # When running using `pip install` the static directory is in the site packages.
+    if not FONTS_DIR.exists():
+        FONTS_DIR = Path(site.getsitepackages()[0]) / "static/fonts"
+    # When running using `pip install -e .` the static directory is in the site packages.
+    # This path only works if `open-webui serve` is run from the root of this project.
+    if not FONTS_DIR.exists():
+        FONTS_DIR = Path("./backend/static/fonts")
 
     pdf.add_font("NotoSans", "", f"{FONTS_DIR}/NotoSans-Regular.ttf")
     pdf.add_font("NotoSans", "b", f"{FONTS_DIR}/NotoSans-Bold.ttf")

+ 39 - 0
backend/config.py

@@ -349,6 +349,12 @@ GOOGLE_OAUTH_SCOPE = PersistentConfig(
     os.environ.get("GOOGLE_OAUTH_SCOPE", "openid email profile"),
 )
 
+GOOGLE_REDIRECT_URI = PersistentConfig(
+    "GOOGLE_REDIRECT_URI",
+    "oauth.google.redirect_uri",
+    os.environ.get("GOOGLE_REDIRECT_URI", ""),
+)
+
 MICROSOFT_CLIENT_ID = PersistentConfig(
     "MICROSOFT_CLIENT_ID",
     "oauth.microsoft.client_id",
@@ -373,6 +379,12 @@ MICROSOFT_OAUTH_SCOPE = PersistentConfig(
     os.environ.get("MICROSOFT_OAUTH_SCOPE", "openid email profile"),
 )
 
+MICROSOFT_REDIRECT_URI = PersistentConfig(
+    "MICROSOFT_REDIRECT_URI",
+    "oauth.microsoft.redirect_uri",
+    os.environ.get("MICROSOFT_REDIRECT_URI", ""),
+)
+
 OAUTH_CLIENT_ID = PersistentConfig(
     "OAUTH_CLIENT_ID",
     "oauth.oidc.client_id",
@@ -391,6 +403,12 @@ OPENID_PROVIDER_URL = PersistentConfig(
     os.environ.get("OPENID_PROVIDER_URL", ""),
 )
 
+OPENID_REDIRECT_URI = PersistentConfig(
+    "OPENID_REDIRECT_URI",
+    "oauth.oidc.redirect_uri",
+    os.environ.get("OPENID_REDIRECT_URI", ""),
+)
+
 OAUTH_SCOPES = PersistentConfig(
     "OAUTH_SCOPES",
     "oauth.oidc.scopes",
@@ -424,6 +442,7 @@ def load_oauth_providers():
             "client_secret": GOOGLE_CLIENT_SECRET.value,
             "server_metadata_url": "https://accounts.google.com/.well-known/openid-configuration",
             "scope": GOOGLE_OAUTH_SCOPE.value,
+            "redirect_uri": GOOGLE_REDIRECT_URI.value,
         }
 
     if (
@@ -436,6 +455,7 @@ def load_oauth_providers():
             "client_secret": MICROSOFT_CLIENT_SECRET.value,
             "server_metadata_url": f"https://login.microsoftonline.com/{MICROSOFT_CLIENT_TENANT_ID.value}/v2.0/.well-known/openid-configuration",
             "scope": MICROSOFT_OAUTH_SCOPE.value,
+            "redirect_uri": MICROSOFT_REDIRECT_URI.value,
         }
 
     if (
@@ -449,6 +469,7 @@ def load_oauth_providers():
             "server_metadata_url": OPENID_PROVIDER_URL.value,
             "scope": OAUTH_SCOPES.value,
             "name": OAUTH_PROVIDER_NAME.value,
+            "redirect_uri": OPENID_REDIRECT_URI.value,
         }
 
 
@@ -1281,6 +1302,24 @@ COMFYUI_SD3 = PersistentConfig(
     os.environ.get("COMFYUI_SD3", "").lower() == "true",
 )
 
+COMFYUI_FLUX = PersistentConfig(
+    "COMFYUI_FLUX",
+    "image_generation.comfyui.flux",
+    os.environ.get("COMFYUI_FLUX", "").lower() == "true",
+)
+
+COMFYUI_FLUX_WEIGHT_DTYPE = PersistentConfig(
+    "COMFYUI_FLUX_WEIGHT_DTYPE",
+    "image_generation.comfyui.flux_weight_dtype",
+    os.getenv("COMFYUI_FLUX_WEIGHT_DTYPE", ""),
+)
+
+COMFYUI_FLUX_FP8_CLIP = PersistentConfig(
+    "COMFYUI_FLUX_FP8_CLIP",
+    "image_generation.comfyui.flux_fp8_clip",
+    os.getenv("COMFYUI_FLUX_FP8_CLIP", ""),
+)
+
 IMAGES_OPENAI_API_BASE_URL = PersistentConfig(
     "IMAGES_OPENAI_API_BASE_URL",
     "image_generation.openai.api_base_url",

+ 22 - 48
backend/main.py

@@ -13,8 +13,6 @@ import aiohttp
 import requests
 import mimetypes
 import shutil
-import os
-import uuid
 import inspect
 
 from fastapi import FastAPI, Request, Depends, status, UploadFile, File, Form
@@ -29,7 +27,7 @@ from starlette.middleware.sessions import SessionMiddleware
 from starlette.responses import StreamingResponse, Response, RedirectResponse
 
 
-from apps.socket.main import sio, app as socket_app, get_event_emitter, get_event_call
+from apps.socket.main import app as socket_app, get_event_emitter, get_event_call
 from apps.ollama.main import (
     app as ollama_app,
     get_all_models as get_ollama_models,
@@ -619,32 +617,15 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware):
                     content={"detail": str(e)},
                 )
 
-            # Extract valves from the request body
-            valves = None
-            if "valves" in body:
-                valves = body["valves"]
-                del body["valves"]
-
-            # Extract session_id, chat_id and message_id from the request body
-            session_id = None
-            if "session_id" in body:
-                session_id = body["session_id"]
-                del body["session_id"]
-            chat_id = None
-            if "chat_id" in body:
-                chat_id = body["chat_id"]
-                del body["chat_id"]
-            message_id = None
-            if "id" in body:
-                message_id = body["id"]
-                del body["id"]
-
-            __event_emitter__ = await get_event_emitter(
-                {"chat_id": chat_id, "message_id": message_id, "session_id": session_id}
-            )
-            __event_call__ = await get_event_call(
-                {"chat_id": chat_id, "message_id": message_id, "session_id": session_id}
-            )
+            metadata = {
+                "chat_id": body.pop("chat_id", None),
+                "message_id": body.pop("id", None),
+                "session_id": body.pop("session_id", None),
+                "valves": body.pop("valves", None),
+            }
+
+            __event_emitter__ = get_event_emitter(metadata)
+            __event_call__ = get_event_call(metadata)
 
             # Initialize data_items to store additional data to be sent to the client
             data_items = []
@@ -709,13 +690,7 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware):
             if len(citations) > 0:
                 data_items.append({"citations": citations})
 
-            body["metadata"] = {
-                "session_id": session_id,
-                "chat_id": chat_id,
-                "message_id": message_id,
-                "valves": valves,
-            }
-
+            body["metadata"] = metadata
             modified_body_bytes = json.dumps(body).encode("utf-8")
             # Replace the request body with the modified one
             request._body = modified_body_bytes
@@ -1191,13 +1166,13 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
                             status_code=r.status_code,
                             content=res,
                         )
-                except:
+                except Exception:
                     pass
 
             else:
                 pass
 
-    __event_emitter__ = await get_event_emitter(
+    __event_emitter__ = get_event_emitter(
         {
             "chat_id": data["chat_id"],
             "message_id": data["id"],
@@ -1205,7 +1180,7 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
         }
     )
 
-    __event_call__ = await get_event_call(
+    __event_call__ = get_event_call(
         {
             "chat_id": data["chat_id"],
             "message_id": data["id"],
@@ -1310,9 +1285,7 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
 
 
 @app.post("/api/chat/actions/{action_id}")
-async def chat_completed(
-    action_id: str, form_data: dict, user=Depends(get_verified_user)
-):
+async def chat_action(action_id: str, form_data: dict, user=Depends(get_verified_user)):
     if "." in action_id:
         action_id, sub_action_id = action_id.split(".")
     else:
@@ -1334,14 +1307,14 @@ async def chat_completed(
         )
     model = app.state.MODELS[model_id]
 
-    __event_emitter__ = await get_event_emitter(
+    __event_emitter__ = get_event_emitter(
         {
             "chat_id": data["chat_id"],
             "message_id": data["id"],
             "session_id": data["session_id"],
         }
     )
-    __event_call__ = await get_event_call(
+    __event_call__ = get_event_call(
         {
             "chat_id": data["chat_id"],
             "message_id": data["id"],
@@ -1770,7 +1743,6 @@ class AddPipelineForm(BaseModel):
 
 @app.post("/api/pipelines/add")
 async def add_pipeline(form_data: AddPipelineForm, user=Depends(get_admin_user)):
-
     r = None
     try:
         urlIdx = form_data.urlIdx
@@ -1813,7 +1785,6 @@ class DeletePipelineForm(BaseModel):
 
 @app.delete("/api/pipelines/delete")
 async def delete_pipeline(form_data: DeletePipelineForm, user=Depends(get_admin_user)):
-
     r = None
     try:
         urlIdx = form_data.urlIdx
@@ -1891,7 +1862,6 @@ async def get_pipeline_valves(
     models = await get_all_models()
     r = None
     try:
-
         url = openai_app.state.config.OPENAI_API_BASE_URLS[urlIdx]
         key = openai_app.state.config.OPENAI_API_KEYS[urlIdx]
 
@@ -2143,6 +2113,7 @@ for provider_name, provider_config in OAUTH_PROVIDERS.items():
         client_kwargs={
             "scope": provider_config["scope"],
         },
+        redirect_uri=provider_config["redirect_uri"],
     )
 
 # SessionMiddleware is used by authlib for oauth
@@ -2160,7 +2131,10 @@ if len(OAUTH_PROVIDERS) > 0:
 async def oauth_login(provider: str, request: Request):
     if provider not in OAUTH_PROVIDERS:
         raise HTTPException(404)
-    redirect_uri = request.url_for("oauth_callback", provider=provider)
+    # If the provider has a custom redirect URL, use that, otherwise automatically generate one
+    redirect_uri = OAUTH_PROVIDERS[provider].get("redirect_uri") or request.url_for(
+        "oauth_callback", provider=provider
+    )
     return await oauth.create_client(provider).authorize_redirect(request, redirect_uri)
 
 

+ 2 - 1
backend/requirements.txt

@@ -12,6 +12,7 @@ passlib[bcrypt]==1.7.4
 
 requests==2.32.3
 aiohttp==3.9.5
+
 sqlalchemy==2.0.31
 alembic==1.13.2
 peewee==3.17.6
@@ -19,7 +20,7 @@ peewee-migrate==1.12.2
 psycopg2-binary==2.9.9
 PyMySQL==1.1.1
 bcrypt==4.1.3
-SQLAlchemy
+
 pymongo
 redis
 boto3==1.34.110

+ 39 - 32
backend/utils/misc.py

@@ -1,6 +1,5 @@
 from pathlib import Path
 import hashlib
-import json
 import re
 from datetime import timedelta
 from typing import Optional, List, Tuple
@@ -8,37 +7,39 @@ import uuid
 import time
 
 
-def get_last_user_message_item(messages: List[dict]) -> str:
+def get_last_user_message_item(messages: List[dict]) -> Optional[dict]:
     for message in reversed(messages):
         if message["role"] == "user":
             return message
     return None
 
 
-def get_last_user_message(messages: List[dict]) -> str:
-    message = get_last_user_message_item(messages)
-
-    if message is not None:
-        if isinstance(message["content"], list):
-            for item in message["content"]:
-                if item["type"] == "text":
-                    return item["text"]
+def get_content_from_message(message: dict) -> Optional[str]:
+    if isinstance(message["content"], list):
+        for item in message["content"]:
+            if item["type"] == "text":
+                return item["text"]
+    else:
         return message["content"]
     return None
 
 
-def get_last_assistant_message(messages: List[dict]) -> str:
+def get_last_user_message(messages: List[dict]) -> Optional[str]:
+    message = get_last_user_message_item(messages)
+    if message is None:
+        return None
+
+    return get_content_from_message(message)
+
+
+def get_last_assistant_message(messages: List[dict]) -> Optional[str]:
     for message in reversed(messages):
         if message["role"] == "assistant":
-            if isinstance(message["content"], list):
-                for item in message["content"]:
-                    if item["type"] == "text":
-                        return item["text"]
-            return message["content"]
+            return get_content_from_message(message)
     return None
 
 
-def get_system_message(messages: List[dict]) -> dict:
+def get_system_message(messages: List[dict]) -> Optional[dict]:
     for message in messages:
         if message["role"] == "system":
             return message
@@ -49,7 +50,7 @@ def remove_system_message(messages: List[dict]) -> List[dict]:
     return [message for message in messages if message["role"] != "system"]
 
 
-def pop_system_message(messages: List[dict]) -> Tuple[dict, List[dict]]:
+def pop_system_message(messages: List[dict]) -> Tuple[Optional[dict], List[dict]]:
     return get_system_message(messages), remove_system_message(messages)
 
 
@@ -87,23 +88,29 @@ def add_or_update_system_message(content: str, messages: List[dict]):
     return messages
 
 
-def stream_message_template(model: str, message: str):
+def openai_chat_message_template(model: str):
     return {
         "id": f"{model}-{str(uuid.uuid4())}",
-        "object": "chat.completion.chunk",
         "created": int(time.time()),
         "model": model,
-        "choices": [
-            {
-                "index": 0,
-                "delta": {"content": message},
-                "logprobs": None,
-                "finish_reason": None,
-            }
-        ],
+        "choices": [{"index": 0, "logprobs": None, "finish_reason": None}],
     }
 
 
+def openai_chat_chunk_message_template(model: str, message: str):
+    template = openai_chat_message_template(model)
+    template["object"] = "chat.completion.chunk"
+    template["choices"][0]["delta"] = {"content": message}
+    return template
+
+
+def openai_chat_completion_message_template(model: str, message: str):
+    template = openai_chat_message_template(model)
+    template["object"] = "chat.completion"
+    template["choices"][0]["message"] = {"content": message, "role": "assistant"}
+    template["choices"][0]["finish_reason"] = "stop"
+
+
 def get_gravatar_url(email):
     # Trim leading and trailing whitespace from
     # an email address and force all characters
@@ -174,7 +181,7 @@ def extract_folders_after_data_docs(path):
     tags = []
 
     folders = parts[index_docs:-1]
-    for idx, part in enumerate(folders):
+    for idx, _ in enumerate(folders):
         tags.append("/".join(folders[: idx + 1]))
 
     return tags
@@ -270,11 +277,11 @@ def parse_ollama_modelfile(model_text):
             value = param_match.group(1)
 
             try:
-                if param_type == int:
+                if param_type is int:
                     value = int(value)
-                elif param_type == float:
+                elif param_type is float:
                     value = float(value)
-                elif param_type == bool:
+                elif param_type is bool:
                     value = value.lower() == "true"
             except Exception as e:
                 print(e)

+ 11 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
 	"name": "open-webui",
-	"version": "0.3.10",
+	"version": "0.3.11",
 	"lockfileVersion": 3,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "open-webui",
-			"version": "0.3.10",
+			"version": "0.3.11",
 			"dependencies": {
 				"@codemirror/lang-javascript": "^6.2.2",
 				"@codemirror/lang-python": "^6.1.6",
@@ -20,6 +20,7 @@
 				"dayjs": "^1.11.10",
 				"eventsource-parser": "^1.1.2",
 				"file-saver": "^2.0.5",
+				"fuse.js": "^7.0.0",
 				"highlight.js": "^11.9.0",
 				"i18next": "^23.10.0",
 				"i18next-browser-languagedetector": "^7.2.0",
@@ -4820,6 +4821,14 @@
 				"url": "https://github.com/sponsors/ljharb"
 			}
 		},
+		"node_modules/fuse.js": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
+			"integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
+			"engines": {
+				"node": ">=10"
+			}
+		},
 		"node_modules/gc-hook": {
 			"version": "0.3.1",
 			"resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.1.tgz",

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "open-webui",
-	"version": "0.3.10",
+	"version": "0.3.11",
 	"private": true,
 	"scripts": {
 		"dev": "npm run pyodide:fetch && vite dev --host",
@@ -60,6 +60,7 @@
 		"dayjs": "^1.11.10",
 		"eventsource-parser": "^1.1.2",
 		"file-saver": "^2.0.5",
+		"fuse.js": "^7.0.0",
 		"highlight.js": "^11.9.0",
 		"i18next": "^23.10.0",
 		"i18next-browser-languagedetector": "^7.2.0",

+ 30 - 15
pyproject.toml

@@ -8,50 +8,61 @@ license = { file = "LICENSE" }
 dependencies = [
     "fastapi==0.111.0",
     "uvicorn[standard]==0.22.0",
-    "pydantic==2.7.1",
+    "pydantic==2.8.2",
     "python-multipart==0.0.9",
 
     "Flask==3.0.3",
     "Flask-Cors==4.0.1",
 
-    "python-socketio==5.11.2",
+    "python-socketio==5.11.3",
     "python-jose==3.3.0",
     "passlib[bcrypt]==1.7.4",
 
-    "requests==2.32.2",
+    "requests==2.32.3",
     "aiohttp==3.9.5",
-    "peewee==3.17.5",
+
+    "sqlalchemy==2.0.31",
+    "alembic==1.13.2",
+    "peewee==3.17.6",
     "peewee-migrate==1.12.2",
     "psycopg2-binary==2.9.9",
     "PyMySQL==1.1.1",
     "bcrypt==4.1.3",
 
+    "pymongo",
+    "redis",
     "boto3==1.34.110",
 
     "argon2-cffi==23.1.0",
     "APScheduler==3.10.4",
+
+    "openai",
+    "anthropic",
     "google-generativeai==0.5.4",
+    "tiktoken",
 
-    "langchain==0.2.0",
-    "langchain-community==0.2.9",
-    "langchain-chroma==0.1.1",
+    "langchain==0.2.11",
+    "langchain-community==0.2.10",
+    "langchain-chroma==0.1.2",
 
     "fake-useragent==1.5.1",
-    "chromadb==0.5.0",
-    "sentence-transformers==2.7.0",
+    "chromadb==0.5.4",
+    "sentence-transformers==3.0.1",
     "pypdf==4.2.0",
     "docx2txt==0.8",
-    "unstructured==0.14.0",
+    "python-pptx==0.6.23",
+    "unstructured==0.15.0",
     "Markdown==3.6",
     "pypandoc==1.13",
     "pandas==2.2.2",
-    "openpyxl==3.1.2",
+    "openpyxl==3.1.5",
     "pyxlsb==1.0.10",
     "xlrd==2.0.1",
     "validators==0.28.1",
+    "psutil",
 
-    "opencv-python-headless==4.9.0.80",
-    "rapidocr-onnxruntime==1.3.22",
+    "opencv-python-headless==4.10.0.84",
+    "rapidocr-onnxruntime==1.3.24",
 
     "fpdf2==2.7.9",
     "rank-bm25==0.2.2",
@@ -62,13 +73,17 @@ dependencies = [
     "authlib==1.3.1",
 
     "black==24.4.2",
-    "langfuse==2.33.0",
+    "langfuse==2.39.2",
     "youtube-transcript-api==0.6.2",
     "pytube==15.0.0",
+
     "extract_msg",
     "pydub",
-    "duckduckgo-search~=6.1.5"
+    "duckduckgo-search~=6.2.1",
 
+    "docker~=7.1.0",
+    "pytest~=8.2.2",
+    "pytest-docker~=3.1.1"
 ]
 readme = "README.md"
 requires-python = ">= 3.11, < 3.12.0a1"

+ 91 - 28
requirements-dev.lock

@@ -16,10 +16,17 @@ aiohttp==3.9.5
     # via open-webui
 aiosignal==1.3.1
     # via aiohttp
+alembic==1.13.2
+    # via open-webui
 annotated-types==0.6.0
     # via pydantic
-anyio==4.3.0
+anthropic==0.32.0
+    # via open-webui
+anyio==4.4.0
+    # via anthropic
     # via httpx
+    # via langfuse
+    # via openai
     # via starlette
     # via watchfiles
 apscheduler==3.10.4
@@ -32,6 +39,7 @@ asgiref==3.8.1
     # via opentelemetry-instrumentation-asgi
 attrs==23.2.0
     # via aiohttp
+    # via pytest-docker
 authlib==1.3.1
     # via open-webui
 av==11.0.0
@@ -76,9 +84,9 @@ chardet==5.2.0
 charset-normalizer==3.3.2
     # via requests
     # via unstructured-client
-chroma-hnswlib==0.7.3
+chroma-hnswlib==0.7.5
     # via chromadb
-chromadb==0.5.0
+chromadb==0.5.4
     # via langchain-chroma
     # via open-webui
 click==8.1.7
@@ -102,7 +110,6 @@ cryptography==42.0.7
 ctranslate2==4.2.1
     # via faster-whisper
 dataclasses-json==0.6.6
-    # via langchain
     # via langchain-community
     # via unstructured
     # via unstructured-client
@@ -113,11 +120,17 @@ defusedxml==0.7.1
 deprecated==1.2.14
     # via opentelemetry-api
     # via opentelemetry-exporter-otlp-proto-grpc
+distro==1.9.0
+    # via anthropic
+    # via openai
 dnspython==2.6.1
     # via email-validator
+    # via pymongo
+docker==7.1.0
+    # via open-webui
 docx2txt==0.8
     # via open-webui
-duckduckgo-search==6.1.5
+duckduckgo-search==6.2.6
     # via open-webui
 easygui==0.98.3
     # via oletools
@@ -208,8 +221,11 @@ httplib2==0.22.0
 httptools==0.6.1
     # via uvicorn
 httpx==0.27.0
+    # via anthropic
+    # via chromadb
     # via fastapi
     # via langfuse
+    # via openai
 huggingface-hub==0.23.0
     # via faster-whisper
     # via sentence-transformers
@@ -229,12 +245,16 @@ importlib-metadata==7.0.0
     # via opentelemetry-api
 importlib-resources==6.4.0
     # via chromadb
+iniconfig==2.0.0
+    # via pytest
 itsdangerous==2.2.0
     # via flask
 jinja2==3.1.4
     # via fastapi
     # via flask
     # via torch
+jiter==0.5.0
+    # via anthropic
 jmespath==1.0.1
     # via boto3
     # via botocore
@@ -249,14 +269,14 @@ jsonpointer==2.4
     # via jsonpatch
 kubernetes==29.0.0
     # via chromadb
-langchain==0.2.0
+langchain==0.2.11
     # via langchain-community
     # via open-webui
-langchain-chroma==0.1.1
+langchain-chroma==0.1.2
     # via open-webui
-langchain-community==0.2.0
+langchain-community==0.2.10
     # via open-webui
-langchain-core==0.2.1
+langchain-core==0.2.28
     # via langchain
     # via langchain-chroma
     # via langchain-community
@@ -265,22 +285,26 @@ langchain-text-splitters==0.2.0
     # via langchain
 langdetect==1.0.9
     # via unstructured
-langfuse==2.33.0
+langfuse==2.39.2
     # via open-webui
-langsmith==0.1.57
+langsmith==0.1.96
     # via langchain
     # via langchain-community
     # via langchain-core
 lark==1.1.8
     # via rtfde
 lxml==5.2.2
+    # via python-pptx
     # via unstructured
+mako==1.3.5
+    # via alembic
 markdown==3.6
     # via open-webui
 markdown-it-py==3.0.0
     # via rich
 markupsafe==2.1.5
     # via jinja2
+    # via mako
     # via werkzeug
 marshmallow==3.21.2
     # via dataclasses-json
@@ -339,11 +363,13 @@ onnxruntime==1.17.3
     # via chromadb
     # via faster-whisper
     # via rapidocr-onnxruntime
+openai==1.38.0
+    # via open-webui
 opencv-python==4.9.0.80
     # via rapidocr-onnxruntime
-opencv-python-headless==4.9.0.80
+opencv-python-headless==4.10.0.84
     # via open-webui
-openpyxl==3.1.2
+openpyxl==3.1.5
     # via open-webui
 opentelemetry-api==1.24.0
     # via chromadb
@@ -380,7 +406,6 @@ ordered-set==4.1.0
     # via deepdiff
 orjson==3.10.3
     # via chromadb
-    # via duckduckgo-search
     # via fastapi
     # via langsmith
 overrides==7.7.0
@@ -393,6 +418,7 @@ packaging==23.2
     # via langfuse
     # via marshmallow
     # via onnxruntime
+    # via pytest
     # via transformers
     # via unstructured-client
 pandas==2.2.2
@@ -403,19 +429,24 @@ pathspec==0.12.1
     # via black
 pcodedmp==1.2.6
     # via oletools
-peewee==3.17.5
+peewee==3.17.6
     # via open-webui
     # via peewee-migrate
 peewee-migrate==1.12.2
     # via open-webui
 pillow==10.3.0
     # via fpdf2
+    # via python-pptx
     # via rapidocr-onnxruntime
     # via sentence-transformers
 platformdirs==4.2.1
     # via black
+pluggy==1.5.0
+    # via pytest
 posthog==3.5.0
     # via chromadb
+primp==0.5.5
+    # via duckduckgo-search
 proto-plus==1.23.0
     # via google-ai-generativelanguage
     # via google-api-core
@@ -428,6 +459,9 @@ protobuf==4.25.3
     # via onnxruntime
     # via opentelemetry-proto
     # via proto-plus
+psutil==6.0.0
+    # via open-webui
+    # via unstructured
 psycopg2-binary==2.9.9
     # via open-webui
 pyasn1==0.6.0
@@ -440,7 +474,8 @@ pyclipper==1.3.0.post5
     # via rapidocr-onnxruntime
 pycparser==2.22
     # via cffi
-pydantic==2.7.1
+pydantic==2.8.2
+    # via anthropic
     # via chromadb
     # via fastapi
     # via google-generativeai
@@ -449,7 +484,8 @@ pydantic==2.7.1
     # via langfuse
     # via langsmith
     # via open-webui
-pydantic-core==2.18.2
+    # via openai
+pydantic-core==2.20.1
     # via pydantic
 pydub==0.25.1
     # via open-webui
@@ -457,7 +493,9 @@ pygments==2.18.0
     # via rich
 pyjwt==2.8.0
     # via open-webui
-pymysql==1.1.0
+pymongo==4.8.0
+    # via open-webui
+pymysql==1.1.1
     # via open-webui
 pypandoc==1.13
     # via open-webui
@@ -471,8 +509,11 @@ pypika==0.48.9
     # via chromadb
 pyproject-hooks==1.1.0
     # via build
-pyreqwest-impersonate==0.4.7
-    # via duckduckgo-search
+pytest==8.2.2
+    # via open-webui
+    # via pytest-docker
+pytest-docker==3.1.1
+    # via open-webui
 python-dateutil==2.9.0.post0
     # via botocore
     # via kubernetes
@@ -492,7 +533,9 @@ python-magic==0.4.27
 python-multipart==0.0.9
     # via fastapi
     # via open-webui
-python-socketio==5.11.2
+python-pptx==0.6.23
+    # via open-webui
+python-socketio==5.11.3
     # via open-webui
 pytube==15.0.0
     # via open-webui
@@ -516,15 +559,18 @@ rank-bm25==0.2.2
     # via open-webui
 rapidfuzz==3.9.0
     # via unstructured
-rapidocr-onnxruntime==1.3.22
+rapidocr-onnxruntime==1.3.24
     # via open-webui
 red-black-tree-mod==1.20
     # via extract-msg
+redis==5.0.8
+    # via open-webui
 regex==2024.5.10
     # via nltk
+    # via tiktoken
     # via transformers
-requests==2.32.2
-    # via chromadb
+requests==2.32.3
+    # via docker
     # via google-api-core
     # via huggingface-hub
     # via kubernetes
@@ -534,6 +580,7 @@ requests==2.32.2
     # via open-webui
     # via posthog
     # via requests-oauthlib
+    # via tiktoken
     # via transformers
     # via unstructured
     # via unstructured-client
@@ -556,12 +603,12 @@ scikit-learn==1.4.2
 scipy==1.13.0
     # via scikit-learn
     # via sentence-transformers
-sentence-transformers==2.7.0
+sentence-transformers==3.0.1
     # via open-webui
 setuptools==69.5.1
     # via ctranslate2
     # via opentelemetry-instrumentation
-shapely==2.0.4
+shapely==2.0.5
     # via rapidocr-onnxruntime
 shellingham==1.5.4
     # via typer
@@ -577,13 +624,17 @@ six==1.16.0
     # via rapidocr-onnxruntime
     # via unstructured-client
 sniffio==1.3.1
+    # via anthropic
     # via anyio
     # via httpx
+    # via openai
 soupsieve==2.5
     # via beautifulsoup4
-sqlalchemy==2.0.30
+sqlalchemy==2.0.31
+    # via alembic
     # via langchain
     # via langchain-community
+    # via open-webui
 starlette==0.37.2
     # via fastapi
 sympy==1.12
@@ -598,7 +649,10 @@ tenacity==8.3.0
     # via langchain-core
 threadpoolctl==3.5.0
     # via scikit-learn
+tiktoken==0.7.0
+    # via open-webui
 tokenizers==0.15.2
+    # via anthropic
     # via chromadb
     # via faster-whisper
     # via transformers
@@ -609,18 +663,24 @@ tqdm==4.66.4
     # via google-generativeai
     # via huggingface-hub
     # via nltk
+    # via openai
     # via sentence-transformers
     # via transformers
+    # via unstructured
 transformers==4.39.3
     # via sentence-transformers
 typer==0.12.3
     # via chromadb
     # via fastapi-cli
 typing-extensions==4.11.0
+    # via alembic
+    # via anthropic
     # via chromadb
     # via fastapi
     # via google-generativeai
     # via huggingface-hub
+    # via langchain-core
+    # via openai
     # via opentelemetry-sdk
     # via pydantic
     # via pydantic-core
@@ -640,7 +700,7 @@ tzlocal==5.2
     # via extract-msg
 ujson==5.10.0
     # via fastapi
-unstructured==0.14.0
+unstructured==0.15.0
     # via open-webui
 unstructured-client==0.22.0
     # via unstructured
@@ -648,6 +708,7 @@ uritemplate==4.1.1
     # via google-api-python-client
 urllib3==2.2.1
     # via botocore
+    # via docker
     # via kubernetes
     # via requests
     # via unstructured-client
@@ -676,6 +737,8 @@ wsproto==1.2.0
     # via simple-websocket
 xlrd==2.0.1
     # via open-webui
+xlsxwriter==3.2.0
+    # via python-pptx
 yarl==1.9.4
     # via aiohttp
 youtube-transcript-api==0.6.2

+ 91 - 28
requirements.lock

@@ -16,10 +16,17 @@ aiohttp==3.9.5
     # via open-webui
 aiosignal==1.3.1
     # via aiohttp
+alembic==1.13.2
+    # via open-webui
 annotated-types==0.6.0
     # via pydantic
-anyio==4.3.0
+anthropic==0.32.0
+    # via open-webui
+anyio==4.4.0
+    # via anthropic
     # via httpx
+    # via langfuse
+    # via openai
     # via starlette
     # via watchfiles
 apscheduler==3.10.4
@@ -32,6 +39,7 @@ asgiref==3.8.1
     # via opentelemetry-instrumentation-asgi
 attrs==23.2.0
     # via aiohttp
+    # via pytest-docker
 authlib==1.3.1
     # via open-webui
 av==11.0.0
@@ -76,9 +84,9 @@ chardet==5.2.0
 charset-normalizer==3.3.2
     # via requests
     # via unstructured-client
-chroma-hnswlib==0.7.3
+chroma-hnswlib==0.7.5
     # via chromadb
-chromadb==0.5.0
+chromadb==0.5.4
     # via langchain-chroma
     # via open-webui
 click==8.1.7
@@ -102,7 +110,6 @@ cryptography==42.0.7
 ctranslate2==4.2.1
     # via faster-whisper
 dataclasses-json==0.6.6
-    # via langchain
     # via langchain-community
     # via unstructured
     # via unstructured-client
@@ -113,11 +120,17 @@ defusedxml==0.7.1
 deprecated==1.2.14
     # via opentelemetry-api
     # via opentelemetry-exporter-otlp-proto-grpc
+distro==1.9.0
+    # via anthropic
+    # via openai
 dnspython==2.6.1
     # via email-validator
+    # via pymongo
+docker==7.1.0
+    # via open-webui
 docx2txt==0.8
     # via open-webui
-duckduckgo-search==6.1.5
+duckduckgo-search==6.2.6
     # via open-webui
 easygui==0.98.3
     # via oletools
@@ -208,8 +221,11 @@ httplib2==0.22.0
 httptools==0.6.1
     # via uvicorn
 httpx==0.27.0
+    # via anthropic
+    # via chromadb
     # via fastapi
     # via langfuse
+    # via openai
 huggingface-hub==0.23.0
     # via faster-whisper
     # via sentence-transformers
@@ -229,12 +245,16 @@ importlib-metadata==7.0.0
     # via opentelemetry-api
 importlib-resources==6.4.0
     # via chromadb
+iniconfig==2.0.0
+    # via pytest
 itsdangerous==2.2.0
     # via flask
 jinja2==3.1.4
     # via fastapi
     # via flask
     # via torch
+jiter==0.5.0
+    # via anthropic
 jmespath==1.0.1
     # via boto3
     # via botocore
@@ -249,14 +269,14 @@ jsonpointer==2.4
     # via jsonpatch
 kubernetes==29.0.0
     # via chromadb
-langchain==0.2.0
+langchain==0.2.11
     # via langchain-community
     # via open-webui
-langchain-chroma==0.1.1
+langchain-chroma==0.1.2
     # via open-webui
-langchain-community==0.2.0
+langchain-community==0.2.10
     # via open-webui
-langchain-core==0.2.1
+langchain-core==0.2.28
     # via langchain
     # via langchain-chroma
     # via langchain-community
@@ -265,22 +285,26 @@ langchain-text-splitters==0.2.0
     # via langchain
 langdetect==1.0.9
     # via unstructured
-langfuse==2.33.0
+langfuse==2.39.2
     # via open-webui
-langsmith==0.1.57
+langsmith==0.1.96
     # via langchain
     # via langchain-community
     # via langchain-core
 lark==1.1.8
     # via rtfde
 lxml==5.2.2
+    # via python-pptx
     # via unstructured
+mako==1.3.5
+    # via alembic
 markdown==3.6
     # via open-webui
 markdown-it-py==3.0.0
     # via rich
 markupsafe==2.1.5
     # via jinja2
+    # via mako
     # via werkzeug
 marshmallow==3.21.2
     # via dataclasses-json
@@ -339,11 +363,13 @@ onnxruntime==1.17.3
     # via chromadb
     # via faster-whisper
     # via rapidocr-onnxruntime
+openai==1.38.0
+    # via open-webui
 opencv-python==4.9.0.80
     # via rapidocr-onnxruntime
-opencv-python-headless==4.9.0.80
+opencv-python-headless==4.10.0.84
     # via open-webui
-openpyxl==3.1.2
+openpyxl==3.1.5
     # via open-webui
 opentelemetry-api==1.24.0
     # via chromadb
@@ -380,7 +406,6 @@ ordered-set==4.1.0
     # via deepdiff
 orjson==3.10.3
     # via chromadb
-    # via duckduckgo-search
     # via fastapi
     # via langsmith
 overrides==7.7.0
@@ -393,6 +418,7 @@ packaging==23.2
     # via langfuse
     # via marshmallow
     # via onnxruntime
+    # via pytest
     # via transformers
     # via unstructured-client
 pandas==2.2.2
@@ -403,19 +429,24 @@ pathspec==0.12.1
     # via black
 pcodedmp==1.2.6
     # via oletools
-peewee==3.17.5
+peewee==3.17.6
     # via open-webui
     # via peewee-migrate
 peewee-migrate==1.12.2
     # via open-webui
 pillow==10.3.0
     # via fpdf2
+    # via python-pptx
     # via rapidocr-onnxruntime
     # via sentence-transformers
 platformdirs==4.2.1
     # via black
+pluggy==1.5.0
+    # via pytest
 posthog==3.5.0
     # via chromadb
+primp==0.5.5
+    # via duckduckgo-search
 proto-plus==1.23.0
     # via google-ai-generativelanguage
     # via google-api-core
@@ -428,6 +459,9 @@ protobuf==4.25.3
     # via onnxruntime
     # via opentelemetry-proto
     # via proto-plus
+psutil==6.0.0
+    # via open-webui
+    # via unstructured
 psycopg2-binary==2.9.9
     # via open-webui
 pyasn1==0.6.0
@@ -440,7 +474,8 @@ pyclipper==1.3.0.post5
     # via rapidocr-onnxruntime
 pycparser==2.22
     # via cffi
-pydantic==2.7.1
+pydantic==2.8.2
+    # via anthropic
     # via chromadb
     # via fastapi
     # via google-generativeai
@@ -449,7 +484,8 @@ pydantic==2.7.1
     # via langfuse
     # via langsmith
     # via open-webui
-pydantic-core==2.18.2
+    # via openai
+pydantic-core==2.20.1
     # via pydantic
 pydub==0.25.1
     # via open-webui
@@ -457,7 +493,9 @@ pygments==2.18.0
     # via rich
 pyjwt==2.8.0
     # via open-webui
-pymysql==1.1.0
+pymongo==4.8.0
+    # via open-webui
+pymysql==1.1.1
     # via open-webui
 pypandoc==1.13
     # via open-webui
@@ -471,8 +509,11 @@ pypika==0.48.9
     # via chromadb
 pyproject-hooks==1.1.0
     # via build
-pyreqwest-impersonate==0.4.7
-    # via duckduckgo-search
+pytest==8.2.2
+    # via open-webui
+    # via pytest-docker
+pytest-docker==3.1.1
+    # via open-webui
 python-dateutil==2.9.0.post0
     # via botocore
     # via kubernetes
@@ -492,7 +533,9 @@ python-magic==0.4.27
 python-multipart==0.0.9
     # via fastapi
     # via open-webui
-python-socketio==5.11.2
+python-pptx==0.6.23
+    # via open-webui
+python-socketio==5.11.3
     # via open-webui
 pytube==15.0.0
     # via open-webui
@@ -516,15 +559,18 @@ rank-bm25==0.2.2
     # via open-webui
 rapidfuzz==3.9.0
     # via unstructured
-rapidocr-onnxruntime==1.3.22
+rapidocr-onnxruntime==1.3.24
     # via open-webui
 red-black-tree-mod==1.20
     # via extract-msg
+redis==5.0.8
+    # via open-webui
 regex==2024.5.10
     # via nltk
+    # via tiktoken
     # via transformers
-requests==2.32.2
-    # via chromadb
+requests==2.32.3
+    # via docker
     # via google-api-core
     # via huggingface-hub
     # via kubernetes
@@ -534,6 +580,7 @@ requests==2.32.2
     # via open-webui
     # via posthog
     # via requests-oauthlib
+    # via tiktoken
     # via transformers
     # via unstructured
     # via unstructured-client
@@ -556,12 +603,12 @@ scikit-learn==1.4.2
 scipy==1.13.0
     # via scikit-learn
     # via sentence-transformers
-sentence-transformers==2.7.0
+sentence-transformers==3.0.1
     # via open-webui
 setuptools==69.5.1
     # via ctranslate2
     # via opentelemetry-instrumentation
-shapely==2.0.4
+shapely==2.0.5
     # via rapidocr-onnxruntime
 shellingham==1.5.4
     # via typer
@@ -577,13 +624,17 @@ six==1.16.0
     # via rapidocr-onnxruntime
     # via unstructured-client
 sniffio==1.3.1
+    # via anthropic
     # via anyio
     # via httpx
+    # via openai
 soupsieve==2.5
     # via beautifulsoup4
-sqlalchemy==2.0.30
+sqlalchemy==2.0.31
+    # via alembic
     # via langchain
     # via langchain-community
+    # via open-webui
 starlette==0.37.2
     # via fastapi
 sympy==1.12
@@ -598,7 +649,10 @@ tenacity==8.3.0
     # via langchain-core
 threadpoolctl==3.5.0
     # via scikit-learn
+tiktoken==0.7.0
+    # via open-webui
 tokenizers==0.15.2
+    # via anthropic
     # via chromadb
     # via faster-whisper
     # via transformers
@@ -609,18 +663,24 @@ tqdm==4.66.4
     # via google-generativeai
     # via huggingface-hub
     # via nltk
+    # via openai
     # via sentence-transformers
     # via transformers
+    # via unstructured
 transformers==4.39.3
     # via sentence-transformers
 typer==0.12.3
     # via chromadb
     # via fastapi-cli
 typing-extensions==4.11.0
+    # via alembic
+    # via anthropic
     # via chromadb
     # via fastapi
     # via google-generativeai
     # via huggingface-hub
+    # via langchain-core
+    # via openai
     # via opentelemetry-sdk
     # via pydantic
     # via pydantic-core
@@ -640,7 +700,7 @@ tzlocal==5.2
     # via extract-msg
 ujson==5.10.0
     # via fastapi
-unstructured==0.14.0
+unstructured==0.15.0
     # via open-webui
 unstructured-client==0.22.0
     # via unstructured
@@ -648,6 +708,7 @@ uritemplate==4.1.1
     # via google-api-python-client
 urllib3==2.2.1
     # via botocore
+    # via docker
     # via kubernetes
     # via requests
     # via unstructured-client
@@ -676,6 +737,8 @@ wsproto==1.2.0
     # via simple-websocket
 xlrd==2.0.1
     # via open-webui
+xlsxwriter==3.2.0
+    # via python-pptx
 yarl==1.9.4
     # via aiohttp
 youtube-transcript-api==0.6.2

+ 4 - 0
src/app.css

@@ -154,3 +154,7 @@ input[type='number'] {
 .tippy-box[data-theme~='dark'] {
 	@apply rounded-lg bg-gray-950 text-xs border border-gray-900 shadow-xl;
 }
+
+.password {
+	-webkit-text-security: disc;
+}

+ 56 - 0
src/lib/apis/audio/index.ts

@@ -131,3 +131,59 @@ export const synthesizeOpenAISpeech = async (
 
 	return res;
 };
+
+export const getModels = async (token: string = '') => {
+	let error = null;
+
+	const res = await fetch(`${AUDIO_API_BASE_URL}/models`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const getVoices = async (token: string = '') => {
+	let error = null;
+
+	const res = await fetch(`${AUDIO_API_BASE_URL}/voices`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};

+ 56 - 41
src/lib/components/admin/Settings/Audio.svelte

@@ -1,12 +1,18 @@
 <script lang="ts">
-	import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
-	import { user, settings, config } from '$lib/stores';
-	import { createEventDispatcher, onMount, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
-	import Switch from '$lib/components/common/Switch.svelte';
+	import { createEventDispatcher, onMount, getContext } from 'svelte';
+	const dispatch = createEventDispatcher();
+
 	import { getBackendConfig } from '$lib/apis';
+	import {
+		getAudioConfig,
+		updateAudioConfig,
+		getModels as _getModels,
+		getVoices as _getVoices
+	} from '$lib/apis/audio';
+	import { user, settings, config } from '$lib/stores';
+
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
-	const dispatch = createEventDispatcher();
 
 	const i18n = getContext('i18n');
 
@@ -30,30 +36,41 @@
 	let models = [];
 	let nonLocalVoices = false;
 
-	const getOpenAIVoices = () => {
-		voices = [
-			{ name: 'alloy' },
-			{ name: 'echo' },
-			{ name: 'fable' },
-			{ name: 'onyx' },
-			{ name: 'nova' },
-			{ name: 'shimmer' }
-		];
-	};
+	const getModels = async () => {
+		if (TTS_ENGINE === '') {
+			models = [];
+		} else {
+			const res = await _getModels(localStorage.token).catch((e) => {
+				toast.error(e);
+			});
 
-	const getOpenAIModels = () => {
-		models = [{ name: 'tts-1' }, { name: 'tts-1-hd' }];
+			if (res) {
+				console.log(res);
+				models = res.models;
+			}
+		}
 	};
 
-	const getWebAPIVoices = () => {
-		const getVoicesLoop = setInterval(async () => {
-			voices = await speechSynthesis.getVoices();
+	const getVoices = async () => {
+		if (TTS_ENGINE === '') {
+			const getVoicesLoop = setInterval(async () => {
+				voices = await speechSynthesis.getVoices();
+
+				// do your loop
+				if (voices.length > 0) {
+					clearInterval(getVoicesLoop);
+				}
+			}, 100);
+		} else {
+			const res = await _getVoices(localStorage.token).catch((e) => {
+				toast.error(e);
+			});
 
-			// do your loop
-			if (voices.length > 0) {
-				clearInterval(getVoicesLoop);
+			if (res) {
+				console.log(res);
+				voices = res.voices;
 			}
-		}, 100);
+		}
 	};
 
 	const updateConfigHandler = async () => {
@@ -101,12 +118,8 @@
 			STT_MODEL = res.stt.MODEL;
 		}
 
-		if (TTS_ENGINE === 'openai') {
-			getOpenAIVoices();
-			getOpenAIModels();
-		} else {
-			getWebAPIVoices();
-		}
+		await getVoices();
+		await getModels();
 	});
 </script>
 
@@ -185,13 +198,15 @@
 							class=" dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
 							bind:value={TTS_ENGINE}
 							placeholder="Select a mode"
-							on:change={(e) => {
+							on:change={async (e) => {
+								await updateConfigHandler();
+								await getVoices();
+								await getModels();
+
 								if (e.target.value === 'openai') {
-									getOpenAIVoices();
 									TTS_VOICE = 'alloy';
 									TTS_MODEL = 'tts-1';
 								} else {
-									getWebAPIVoices();
 									TTS_VOICE = '';
 									TTS_MODEL = '';
 								}
@@ -268,7 +283,7 @@
 
 									<datalist id="voice-list">
 										{#each voices as voice}
-											<option value={voice.name} />
+											<option value={voice.id}>{voice.name}</option>
 										{/each}
 									</datalist>
 								</div>
@@ -279,15 +294,15 @@
 							<div class="flex w-full">
 								<div class="flex-1">
 									<input
-										list="model-list"
+										list="tts-model-list"
 										class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
 										bind:value={TTS_MODEL}
 										placeholder="Select a model"
 									/>
 
-									<datalist id="model-list">
+									<datalist id="tts-model-list">
 										{#each models as model}
-											<option value={model.name} />
+											<option value={model.id} />
 										{/each}
 									</datalist>
 								</div>
@@ -309,7 +324,7 @@
 
 									<datalist id="voice-list">
 										{#each voices as voice}
-											<option value={voice.name} />
+											<option value={voice.id}>{voice.name}</option>
 										{/each}
 									</datalist>
 								</div>
@@ -320,15 +335,15 @@
 							<div class="flex w-full">
 								<div class="flex-1">
 									<input
-										list="model-list"
+										list="tts-model-list"
 										class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
 										bind:value={TTS_MODEL}
 										placeholder="Select a model"
 									/>
 
-									<datalist id="model-list">
+									<datalist id="tts-model-list">
 										{#each models as model}
-											<option value={model.name} />
+											<option value={model.id} />
 										{/each}
 									</datalist>
 								</div>

+ 4 - 4
src/lib/components/chat/Chat.svelte

@@ -111,7 +111,6 @@
 	};
 
 	let params = {};
-	let valves = {};
 
 	$: if (history.currentId !== null) {
 		let _messages = [];
@@ -285,6 +284,10 @@
 
 		if ($page.url.searchParams.get('q')) {
 			prompt = $page.url.searchParams.get('q') ?? '';
+			selectedToolIds = ($page.url.searchParams.get('tool_ids') ?? '')
+				.split(',')
+				.map((id) => id.trim())
+				.filter((id) => id);
 
 			if (prompt) {
 				await tick();
@@ -821,7 +824,6 @@
 			keep_alive: $settings.keepAlive ?? undefined,
 			tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
 			files: files.length > 0 ? files : undefined,
-			...(Object.keys(valves).length ? { valves } : {}),
 			session_id: $socket?.id,
 			chat_id: $chatId,
 			id: responseMessageId
@@ -1123,7 +1125,6 @@
 					max_tokens: params?.max_tokens ?? $settings?.params?.max_tokens ?? undefined,
 					tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
 					files: files.length > 0 ? files : undefined,
-					...(Object.keys(valves).length ? { valves } : {}),
 					session_id: $socket?.id,
 					chat_id: $chatId,
 					id: responseMessageId
@@ -1654,7 +1655,6 @@
 			bind:show={showControls}
 			bind:chatFiles
 			bind:params
-			bind:valves
 		/>
 	</div>
 {/if}

+ 0 - 4
src/lib/components/chat/ChatControls.svelte

@@ -9,9 +9,7 @@
 	export let models = [];
 
 	export let chatId = null;
-
 	export let chatFiles = [];
-	export let valves = {};
 	export let params = {};
 
 	let largeScreen = false;
@@ -50,7 +48,6 @@
 						}}
 						{models}
 						bind:chatFiles
-						bind:valves
 						bind:params
 					/>
 				</div>
@@ -66,7 +63,6 @@
 				}}
 				{models}
 				bind:chatFiles
-				bind:valves
 				bind:params
 			/>
 		</div>

+ 7 - 11
src/lib/components/chat/Controls/Controls.svelte

@@ -5,14 +5,13 @@
 
 	import XMark from '$lib/components/icons/XMark.svelte';
 	import AdvancedParams from '../Settings/Advanced/AdvancedParams.svelte';
-	import Valves from '$lib/components/common/Valves.svelte';
+	import Valves from '$lib/components/chat/Controls/Valves.svelte';
 	import FileItem from '$lib/components/common/FileItem.svelte';
 	import Collapsible from '$lib/components/common/Collapsible.svelte';
 
 	export let models = [];
 
 	export let chatFiles = [];
-	export let valves = {};
 	export let params = {};
 </script>
 
@@ -39,6 +38,7 @@
 							url={`${file?.url}`}
 							name={file.name}
 							type={file.type}
+							size={file?.size}
 							dismissible={true}
 							on:dismiss={() => {
 								// Remove the file from the chatFiles array
@@ -54,17 +54,13 @@
 			<hr class="my-2 border-gray-100 dark:border-gray-800" />
 		{/if}
 
-		{#if models.length === 1 && models[0]?.pipe?.valves_spec}
-			<div>
-				<div class=" font-medium">{$i18n.t('Valves')}</div>
-
-				<div>
-					<Valves valvesSpec={models[0]?.pipe?.valves_spec} bind:valves />
-				</div>
+		<Collapsible title={$i18n.t('Valves')}>
+			<div class="text-sm mt-1.5" slot="content">
+				<Valves />
 			</div>
+		</Collapsible>
 
-			<hr class="my-2 border-gray-100 dark:border-gray-800" />
-		{/if}
+		<hr class="my-2 border-gray-100 dark:border-gray-800" />
 
 		<Collapsible title={$i18n.t('System Prompt')} open={true}>
 			<div class=" mt-1.5" slot="content">

+ 36 - 38
src/lib/components/chat/Settings/Valves.svelte → src/lib/components/chat/Controls/Valves.svelte

@@ -15,18 +15,14 @@
 		updateUserValvesById as updateFunctionUserValvesById
 	} from '$lib/apis/functions';
 
-	import ManageModal from './Personalization/ManageModal.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
-	import Switch from '$lib/components/common/Switch.svelte';
 	import Valves from '$lib/components/common/Valves.svelte';
 
 	const dispatch = createEventDispatcher();
 
 	const i18n = getContext('i18n');
 
-	export let saveSettings: Function;
-
 	let tab = 'tools';
 	let selectedId = '';
 
@@ -35,6 +31,19 @@
 	let valvesSpec = null;
 	let valves = {};
 
+	let debounceTimer;
+
+	const debounceSubmitHandler = async () => {
+		if (debounceTimer) {
+			clearTimeout(debounceTimer);
+		}
+
+		// Set a new timer
+		debounceTimer = setTimeout(() => {
+			submitHandler();
+		}, 500); // 0.5 second debounce
+	};
+
 	const getUserValves = async () => {
 		loading = true;
 		if (tab === 'tools') {
@@ -112,53 +121,45 @@
 		dispatch('save');
 	}}
 >
-	<div class="flex flex-col pr-1.5 overflow-y-scroll max-h-[25rem]">
-		<div>
-			<div class="flex items-center justify-between mb-2">
-				<Tooltip content="">
-					<div class="text-sm font-medium">
-						{$i18n.t('Manage Valves')}
-					</div>
-				</Tooltip>
-
-				<div class=" self-end">
+	<div class="flex flex-col">
+		<div class="space-y-1">
+			<div class="flex gap-2">
+				<div class="flex-1">
 					<select
-						class=" dark:bg-gray-900 w-fit pr-8 rounded text-xs bg-transparent outline-none text-right"
+						class="  w-full rounded text-xs py-2 px-1 bg-transparent outline-none"
 						bind:value={tab}
 						placeholder="Select"
 					>
-						<option value="tools">{$i18n.t('Tools')}</option>
-						<option value="functions">{$i18n.t('Functions')}</option>
+						<option value="tools" class="bg-gray-100 dark:bg-gray-800">{$i18n.t('Tools')}</option>
+						<option value="functions" class="bg-gray-100 dark:bg-gray-800"
+							>{$i18n.t('Functions')}</option
+						>
 					</select>
 				</div>
-			</div>
-		</div>
 
-		<div class="space-y-1">
-			<div class="flex gap-2">
 				<div class="flex-1">
 					<select
-						class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+						class="w-full rounded py-2 px-1 text-xs bg-transparent outline-none"
 						bind:value={selectedId}
 						on:change={async () => {
 							await tick();
 						}}
 					>
 						{#if tab === 'tools'}
-							<option value="" selected disabled class="bg-gray-100 dark:bg-gray-700"
+							<option value="" selected disabled class="bg-gray-100 dark:bg-gray-800"
 								>{$i18n.t('Select a tool')}</option
 							>
 
 							{#each $tools as tool, toolIdx}
-								<option value={tool.id} class="bg-gray-100 dark:bg-gray-700">{tool.name}</option>
+								<option value={tool.id} class="bg-gray-100 dark:bg-gray-800">{tool.name}</option>
 							{/each}
 						{:else if tab === 'functions'}
-							<option value="" selected disabled class="bg-gray-100 dark:bg-gray-700"
+							<option value="" selected disabled class="bg-gray-100 dark:bg-gray-800"
 								>{$i18n.t('Select a function')}</option
 							>
 
 							{#each $functions as func, funcIdx}
-								<option value={func.id} class="bg-gray-100 dark:bg-700">{func.name}</option>
+								<option value={func.id} class="bg-gray-100 dark:bg-gray-800">{func.name}</option>
 							{/each}
 						{/if}
 					</select>
@@ -167,24 +168,21 @@
 		</div>
 
 		{#if selectedId}
-			<hr class="dark:border-gray-800 my-3 w-full" />
+			<hr class="dark:border-gray-800 my-1 w-full" />
 
-			<div>
+			<div class="my-2 text-xs">
 				{#if !loading}
-					<Valves {valvesSpec} bind:valves />
+					<Valves
+						{valvesSpec}
+						bind:valves
+						on:change={() => {
+							debounceSubmitHandler();
+						}}
+					/>
 				{:else}
 					<Spinner className="size-5" />
 				{/if}
 			</div>
 		{/if}
 	</div>
-
-	<div class="flex justify-end text-sm font-medium">
-		<button
-			class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
-			type="submit"
-		>
-			{$i18n.t('Save')}
-		</button>
-	</div>
 </form>

+ 43 - 33
src/lib/components/chat/MessageInput.svelte

@@ -98,6 +98,7 @@
 
 	const uploadFileHandler = async (file) => {
 		console.log(file);
+
 		// Check if the file is an audio file and transcribe/convert it to text file
 		if (['audio/mpeg', 'audio/wav'].includes(file['type'])) {
 			const res = await transcribeAudio(localStorage.token, file).catch((error) => {
@@ -112,40 +113,49 @@
 			}
 		}
 
-		// Upload the file to the server
-		const uploadedFile = await uploadFile(localStorage.token, file).catch((error) => {
-			toast.error(error);
-			return null;
-		});
-
-		if (uploadedFile) {
-			const fileItem = {
-				type: 'file',
-				file: uploadedFile,
-				id: uploadedFile.id,
-				url: `${WEBUI_API_BASE_URL}/files/${uploadedFile.id}`,
-				name: file.name,
-				collection_name: '',
-				status: 'uploaded',
-				error: ''
-			};
-			files = [...files, fileItem];
-
-			// TODO: Check if tools & functions have files support to skip this step to delegate file processing
-			// Default Upload to VectorDB
-			if (
-				SUPPORTED_FILE_TYPE.includes(file['type']) ||
-				SUPPORTED_FILE_EXTENSIONS.includes(file.name.split('.').at(-1))
-			) {
-				processFileItem(fileItem);
+		const fileItem = {
+			type: 'file',
+			file: '',
+			id: null,
+			url: '',
+			name: file.name,
+			collection_name: '',
+			status: '',
+			size: file.size,
+			error: ''
+		};
+		files = [...files, fileItem];
+
+		try {
+			const uploadedFile = await uploadFile(localStorage.token, file);
+
+			if (uploadedFile) {
+				fileItem.status = 'uploaded';
+				fileItem.file = uploadedFile;
+				fileItem.id = uploadedFile.id;
+				fileItem.url = `${WEBUI_API_BASE_URL}/files/${uploadedFile.id}`;
+
+				// TODO: Check if tools & functions have files support to skip this step to delegate file processing
+				// Default Upload to VectorDB
+				if (
+					SUPPORTED_FILE_TYPE.includes(file['type']) ||
+					SUPPORTED_FILE_EXTENSIONS.includes(file.name.split('.').at(-1))
+				) {
+					processFileItem(fileItem);
+				} else {
+					toast.error(
+						$i18n.t(`Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.`, {
+							file_type: file['type']
+						})
+					);
+					processFileItem(fileItem);
+				}
 			} else {
-				toast.error(
-					$i18n.t(`Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.`, {
-						file_type: file['type']
-					})
-				);
-				processFileItem(fileItem);
+				files = files.filter((item) => item.status !== null);
 			}
+		} catch (e) {
+			toast.error(e);
+			files = files.filter((item) => item.status !== null);
 		}
 	};
 
@@ -162,7 +172,6 @@
 			// Remove the failed doc from the files array
 			// files = files.filter((f) => f.id !== fileItem.id);
 			toast.error(e);
-
 			fileItem.status = 'processed';
 			files = files;
 		}
@@ -545,6 +554,7 @@
 											<FileItem
 												name={file.name}
 												type={file.type}
+												size={file?.size}
 												status={file.status}
 												dismissible={true}
 												on:dismiss={() => {

+ 3 - 1
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -253,7 +253,9 @@
 						for (const [idx, sentence] of sentences.entries()) {
 							const res = await synthesizeOpenAISpeech(
 								localStorage.token,
-								$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
+								$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
+									? $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice
+									: $config?.audio?.tts?.voice,
 								sentence
 							).catch((error) => {
 								toast.error(error);

+ 1 - 0
src/lib/components/chat/Messages/UserMessage.svelte

@@ -104,6 +104,7 @@
 									url={file.url}
 									name={file.name}
 									type={file.type}
+									size={file?.size}
 									colorClassName="bg-white dark:bg-gray-850 "
 								/>
 							{/if}

+ 22 - 9
src/lib/components/chat/ModelSelector/Selector.svelte

@@ -1,6 +1,7 @@
 <script lang="ts">
 	import { DropdownMenu } from 'bits-ui';
 	import { marked } from 'marked';
+	import Fuse from 'fuse.js';
 
 	import { flyAndScale } from '$lib/utils/transitions';
 	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
@@ -45,17 +46,29 @@
 
 	let selectedModelIdx = 0;
 
-	$: filteredItems = items.filter(
-		(item) =>
-			(searchValue
-				? item.value.toLowerCase().includes(searchValue.toLowerCase()) ||
-				  item.label.toLowerCase().includes(searchValue.toLowerCase()) ||
-				  (item.model?.info?.meta?.tags ?? []).some((tag) =>
-						tag.name.toLowerCase().includes(searchValue.toLowerCase())
-				  )
-				: true) && !(item.model?.info?.meta?.hidden ?? false)
+	const fuse = new Fuse(
+		items
+			.filter((item) => !item.model?.info?.meta?.hidden)
+			.map((item) => {
+				const _item = {
+					...item,
+					modelName: item.model?.name,
+					tags: item.model?.info?.meta?.tags?.map((tag) => tag.name).join(' '),
+					desc: item.model?.info?.meta?.description
+				};
+				return _item;
+			}),
+		{
+			keys: ['value', 'label', 'tags', 'desc', 'modelName']
+		}
 	);
 
+	$: filteredItems = searchValue
+		? fuse.search(searchValue).map((e) => {
+				return e.item;
+		  })
+		: items.filter((item) => !item.model?.info?.meta?.hidden);
+
 	const pullModelHandler = async () => {
 		const sanitizedModelTag = searchValue.trim().replace(/^ollama\s+(run|pull)\s+/, '');
 

+ 47 - 0
src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte

@@ -20,6 +20,7 @@
 		mirostat_tau: null,
 		top_k: null,
 		top_p: null,
+		min_p: null,
 		tfs_z: null,
 		num_ctx: null,
 		num_batch: null,
@@ -385,6 +386,52 @@
 		{/if}
 	</div>
 
+	<div class=" py-0.5 w-full justify-between">
+		<div class="flex w-full justify-between">
+			<div class=" self-center text-xs font-medium">{$i18n.t('Min P')}</div>
+
+			<button
+				class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
+				type="button"
+				on:click={() => {
+					params.min_p = (params?.min_p ?? null) === null ? 0.0 : null;
+				}}
+			>
+				{#if (params?.min_p ?? null) === null}
+					<span class="ml-2 self-center">{$i18n.t('Default')}</span>
+				{:else}
+					<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
+				{/if}
+			</button>
+		</div>
+
+		{#if (params?.min_p ?? null) !== null}
+			<div class="flex mt-0.5 space-x-2">
+				<div class=" flex-1">
+					<input
+						id="steps-range"
+						type="range"
+						min="0"
+						max="1"
+						step="0.05"
+						bind:value={params.min_p}
+						class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
+					/>
+				</div>
+				<div>
+					<input
+						bind:value={params.min_p}
+						type="number"
+						class=" bg-transparent text-center w-14"
+						min="0"
+						max="1"
+						step="any"
+					/>
+				</div>
+			</div>
+		{/if}
+	</div>
+
 	<div class=" py-0.5 w-full justify-between">
 		<div class="flex w-full justify-between">
 			<div class=" self-center text-xs font-medium">{$i18n.t('Frequency Penalty')}</div>

+ 31 - 25
src/lib/components/chat/Settings/Audio.svelte

@@ -1,7 +1,10 @@
 <script lang="ts">
-	import { user, settings, config } from '$lib/stores';
-	import { createEventDispatcher, onMount, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
+	import { createEventDispatcher, onMount, getContext } from 'svelte';
+
+	import { user, settings, config } from '$lib/stores';
+	import { getVoices as _getVoices } from '$lib/apis/audio';
+
 	import Switch from '$lib/components/common/Switch.svelte';
 	const dispatch = createEventDispatcher();
 
@@ -20,26 +23,26 @@
 	let voices = [];
 	let voice = '';
 
-	const getOpenAIVoices = () => {
-		voices = [
-			{ name: 'alloy' },
-			{ name: 'echo' },
-			{ name: 'fable' },
-			{ name: 'onyx' },
-			{ name: 'nova' },
-			{ name: 'shimmer' }
-		];
-	};
+	const getVoices = async () => {
+		if ($config.audio.tts.engine === '') {
+			const getVoicesLoop = setInterval(async () => {
+				voices = await speechSynthesis.getVoices();
 
-	const getWebAPIVoices = () => {
-		const getVoicesLoop = setInterval(async () => {
-			voices = await speechSynthesis.getVoices();
+				// do your loop
+				if (voices.length > 0) {
+					clearInterval(getVoicesLoop);
+				}
+			}, 100);
+		} else {
+			const res = await _getVoices(localStorage.token).catch((e) => {
+				toast.error(e);
+			});
 
-			// do your loop
-			if (voices.length > 0) {
-				clearInterval(getVoicesLoop);
+			if (res) {
+				console.log(res);
+				voices = res.voices;
 			}
-		}, 100);
+		}
 	};
 
 	const toggleResponseAutoPlayback = async () => {
@@ -58,14 +61,16 @@
 		responseAutoPlayback = $settings.responseAutoPlayback ?? false;
 
 		STTEngine = $settings?.audio?.stt?.engine ?? '';
-		voice = $settings?.audio?.tts?.voice ?? $config.audio.tts.voice ?? '';
-		nonLocalVoices = $settings.audio?.tts?.nonLocalVoices ?? false;
 
-		if ($config.audio.tts.engine === 'openai') {
-			getOpenAIVoices();
+		if ($settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice) {
+			voice = $settings?.audio?.tts?.voice ?? $config.audio.tts.voice ?? '';
 		} else {
-			getWebAPIVoices();
+			voice = $config.audio.tts.voice ?? '';
 		}
+
+		nonLocalVoices = $settings.audio?.tts?.nonLocalVoices ?? false;
+
+		await getVoices();
 	});
 </script>
 
@@ -79,6 +84,7 @@
 				},
 				tts: {
 					voice: voice !== '' ? voice : undefined,
+					defaultVoice: $config?.audio?.tts?.voice ?? '',
 					nonLocalVoices: $config.audio.tts.engine === '' ? nonLocalVoices : undefined
 				}
 			}
@@ -195,7 +201,7 @@
 
 						<datalist id="voice-list">
 							{#each voices as voice}
-								<option value={voice.name} />
+								<option value={voice.id}>{voice.name}</option>
 							{/each}
 						</datalist>
 					</div>

+ 0 - 32
src/lib/components/chat/SettingsModal.svelte

@@ -15,7 +15,6 @@
 	import Chats from './Settings/Chats.svelte';
 	import User from '../icons/User.svelte';
 	import Personalization from './Settings/Personalization.svelte';
-	import Valves from './Settings/Valves.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -188,30 +187,6 @@
 					<div class=" self-center">{$i18n.t('Audio')}</div>
 				</button>
 
-				<button
-					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
-					'valves'
-						? 'bg-gray-200 dark:bg-gray-800'
-						: ' hover:bg-gray-100 dark:hover:bg-gray-850'}"
-					on:click={() => {
-						selectedTab = 'valves';
-					}}
-				>
-					<div class=" self-center mr-2">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 24 24"
-							fill="currentColor"
-							class="size-4"
-						>
-							<path
-								d="M18.75 12.75h1.5a.75.75 0 0 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM12 6a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 6ZM12 18a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 18ZM3.75 6.75h1.5a.75.75 0 1 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM5.25 18.75h-1.5a.75.75 0 0 1 0-1.5h1.5a.75.75 0 0 1 0 1.5ZM3 12a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 3 12ZM9 3.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5ZM12.75 12a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0ZM9 15.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5Z"
-							/>
-						</svg>
-					</div>
-					<div class=" self-center">{$i18n.t('Valves')}</div>
-				</button>
-
 				<button
 					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 					'chats'
@@ -349,13 +324,6 @@
 							toast.success($i18n.t('Settings saved successfully!'));
 						}}
 					/>
-				{:else if selectedTab === 'valves'}
-					<Valves
-						{saveSettings}
-						on:save={() => {
-							toast.success($i18n.t('Settings saved successfully!'));
-						}}
-					/>
 				{:else if selectedTab === 'chats'}
 					<Chats {saveSettings} />
 				{:else if selectedTab === 'account'}

+ 20 - 2
src/lib/components/common/FileItem.svelte

@@ -15,6 +15,21 @@
 
 	export let name: string;
 	export let type: string;
+	export let size: number;
+
+	function formatSize(size) {
+		if (size == null) return 'Unknown size';
+		if (typeof size !== 'number' || size < 0) return 'Invalid size';
+		if (size === 0) return '0 B';
+		const units = ['B', 'KB', 'MB', 'GB', 'TB'];
+		let unitIndex = 0;
+
+		while (size >= 1024 && unitIndex < units.length - 1) {
+			size /= 1024;
+			unitIndex++;
+		}
+		return `${size.toFixed(1)} ${units[unitIndex]}`;
+	}
 </script>
 
 <div class="relative group">
@@ -93,11 +108,11 @@
 		</div>
 
 		<div class="flex flex-col justify-center -space-y-0.5 pl-1.5 pr-4 w-full">
-			<div class=" dark:text-gray-100 text-sm font-medium line-clamp-1">
+			<div class=" dark:text-gray-100 text-sm font-medium line-clamp-1 mb-1">
 				{name}
 			</div>
 
-			<div class=" text-gray-500 text-xs">
+			<div class=" flex justify-between text-gray-500 text-xs">
 				{#if type === 'file'}
 					{$i18n.t('File')}
 				{:else if type === 'doc'}
@@ -107,6 +122,9 @@
 				{:else}
 					<span class=" capitalize">{type}</span>
 				{/if}
+				{#if size}
+					<span class="capitalize">{formatSize(size)}</span>
+				{/if}
 			</div>
 		</div>
 	</button>

+ 12 - 9
src/lib/components/common/ImagePreview.svelte

@@ -7,6 +7,8 @@
 
 	let mounted = false;
 
+	let previewElement = null;
+
 	const downloadImage = (url, filename) => {
 		fetch(url)
 			.then((response) => response.blob())
@@ -34,14 +36,14 @@
 		mounted = true;
 	});
 
-	$: if (mounted) {
-		if (show) {
-			window.addEventListener('keydown', handleKeyDown);
-			document.body.style.overflow = 'hidden';
-		} else {
-			window.removeEventListener('keydown', handleKeyDown);
-			document.body.style.overflow = 'unset';
-		}
+	$: if (show && previewElement) {
+		document.body.appendChild(previewElement);
+		window.addEventListener('keydown', handleKeyDown);
+		document.body.style.overflow = 'hidden';
+	} else if (previewElement) {
+		window.removeEventListener('keydown', handleKeyDown);
+		document.body.removeChild(previewElement);
+		document.body.style.overflow = 'unset';
 	}
 </script>
 
@@ -49,7 +51,8 @@
 	<!-- svelte-ignore a11y-click-events-have-key-events -->
 	<!-- svelte-ignore a11y-no-static-element-interactions -->
 	<div
-		class="fixed top-0 right-0 left-0 bottom-0 bg-black text-white w-full min-h-screen h-screen flex justify-center z-50 overflow-hidden overscroll-contain"
+		bind:this={previewElement}
+		class="modal fixed top-0 right-0 left-0 bottom-0 bg-black text-white w-full min-h-screen h-screen flex justify-center z-[9999] overflow-hidden overscroll-contain"
 	>
 		<div class=" absolute left-0 w-full flex justify-between">
 			<div>

+ 2 - 2
src/lib/components/common/SensitiveInput.svelte

@@ -13,13 +13,13 @@
 
 <div class={outerClassName}>
 	<input
-		class={inputClassName}
+		class={`${inputClassName} ${show ? '' : 'password'}`}
 		{placeholder}
 		bind:value
 		required={required && !readOnly}
 		disabled={readOnly}
 		autocomplete="off"
-		{...{ type: show ? 'text' : 'password' }}
+		type="text"
 	/>
 	<button
 		class={showButtonClassName}

+ 18 - 4
src/lib/components/common/Valves.svelte

@@ -1,5 +1,6 @@
 <script>
-	import { onMount, getContext } from 'svelte';
+	import { onMount, getContext, createEventDispatcher } from 'svelte';
+	const dispatch = createEventDispatcher();
 	const i18n = getContext('i18n');
 
 	import Switch from './Switch.svelte';
@@ -8,7 +9,7 @@
 	export let valves = {};
 </script>
 
-{#if valvesSpec}
+{#if valvesSpec && Object.keys(valvesSpec?.properties ?? {}).length}
 	{#each Object.keys(valvesSpec.properties) as property, idx}
 		<div class=" py-0.5 w-full justify-between">
 			<div class="flex w-full justify-between">
@@ -28,6 +29,8 @@
 							(valves[property] ?? null) === null
 								? valvesSpec.properties[property]?.default ?? ''
 								: null;
+
+						dispatch('change');
 					}}
 				>
 					{#if (valves[property] ?? null) === null}
@@ -52,6 +55,9 @@
 							<select
 								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none border border-gray-100 dark:border-gray-800"
 								bind:value={valves[property]}
+								on:change={() => {
+									dispatch('change');
+								}}
 							>
 								{#each valvesSpec.properties[property].enum as option}
 									<option value={option} selected={option === valves[property]}>
@@ -66,7 +72,12 @@
 								</div>
 
 								<div class=" pr-2">
-									<Switch bind:state={valves[property]} />
+									<Switch
+										bind:state={valves[property]}
+										on:change={() => {
+											dispatch('change');
+										}}
+									/>
 								</div>
 							</div>
 						{:else}
@@ -77,6 +88,9 @@
 								bind:value={valves[property]}
 								autocomplete="off"
 								required
+								on:change={() => {
+									dispatch('change');
+								}}
 							/>
 						{/if}
 					</div>
@@ -91,5 +105,5 @@
 		</div>
 	{/each}
 {:else}
-	<div class="text-sm">No valves</div>
+	<div class="text-xs">No valves</div>
 {/if}

+ 1 - 1
src/lib/i18n/locales/ar-BH/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "إدارة النماذج",
 	"Manage Ollama Models": "Ollama إدارة موديلات ",
 	"Manage Pipelines": "إدارة خطوط الأنابيب",
-	"Manage Valves": "",
 	"March": "مارس",
 	"Max Tokens (num_predict)": "ماكس توكنز (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "يمكن تنزيل 3 نماذج كحد أقصى في وقت واحد. الرجاء معاودة المحاولة في وقت لاحق.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "لن تتم مشاركة الرسائل التي ترسلها بعد إنشاء الرابط الخاص بك. سيتمكن المستخدمون الذين لديهم عنوان URL من عرض الدردشة المشتركة",
+	"Min P": "",
 	"Minimum Score": "الحد الأدنى من النقاط",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/bg-BG/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Управление на Моделите",
 	"Manage Ollama Models": "Управление на Ollama Моделите",
 	"Manage Pipelines": "Управление на тръбопроводи",
-	"Manage Valves": "",
 	"March": "Март",
 	"Max Tokens (num_predict)": "Макс токени (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Максимум 3 модели могат да бъдат сваляни едновременно. Моля, опитайте отново по-късно.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Съобщенията, които изпращате след създаването на връзката, няма да бъдат споделяни. Потребителите с URL адреса ще могат да видят споделения чат.",
+	"Min P": "",
 	"Minimum Score": "Минимална оценка",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/bn-BD/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "মডেলসমূহ ব্যবস্থাপনা করুন",
 	"Manage Ollama Models": "Ollama মডেলসূহ ব্যবস্থাপনা করুন",
 	"Manage Pipelines": "পাইপলাইন পরিচালনা করুন",
-	"Manage Valves": "",
 	"March": "মার্চ",
 	"Max Tokens (num_predict)": "সর্বোচ্চ টোকেন (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "একসঙ্গে সর্বোচ্চ তিনটি মডেল ডাউনলোড করা যায়। দয়া করে পরে আবার চেষ্টা করুন।",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "আপনার লিঙ্ক তৈরি করার পরে আপনার পাঠানো বার্তাগুলি শেয়ার করা হবে না। ইউআরএল ব্যবহারকারীরা শেয়ার করা চ্যাট দেখতে পারবেন।",
+	"Min P": "",
 	"Minimum Score": "Minimum Score",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 8 - 8
src/lib/i18n/locales/ca-ES/translation.json

@@ -15,7 +15,7 @@
 	"Account": "Compte",
 	"Account Activation Pending": "Activació del compte pendent",
 	"Accurate information": "Informació precisa",
-	"Actions": "",
+	"Actions": "Accions",
 	"Active Users": "Usuaris actius",
 	"Add": "Afegir",
 	"Add a model id": "Afegeix un identificador de model",
@@ -28,7 +28,7 @@
 	"Add Memory": "Afegir memòria",
 	"Add message": "Afegir un missatge",
 	"Add Model": "Afegir un model",
-	"Add Tag": "",
+	"Add Tag": "Afegir etiqueta",
 	"Add Tags": "Afegir etiquetes",
 	"Add User": "Afegir un usuari",
 	"Adjusting these settings will apply changes universally to all users.": "Si ajustes aquesta preferència, els canvis s'aplicaran de manera universal a tots els usuaris.",
@@ -170,7 +170,7 @@
 	"Delete chat": "Eliminar xat",
 	"Delete Chat": "Eliminar xat",
 	"Delete chat?": "Eliminar el xat?",
-	"Delete Doc": "",
+	"Delete Doc": "Eliminar document",
 	"Delete function?": "Eliminar funció?",
 	"Delete prompt?": "Eliminar indicació?",
 	"delete this link": "Eliminar aquest enllaç",
@@ -214,7 +214,7 @@
 	"Edit Doc": "Editar el document",
 	"Edit Memory": "Editar la memòria",
 	"Edit User": "Editar l'usuari",
-	"ElevenLabs": "",
+	"ElevenLabs": "ElevenLabs",
 	"Email": "Correu electrònic",
 	"Embedding Batch Size": "Mida del lot d'incrustació",
 	"Embedding Model": "Model d'incrustació",
@@ -278,7 +278,7 @@
 	"File": "Arxiu",
 	"File Mode": "Mode d'arxiu",
 	"File not found.": "No s'ha trobat l'arxiu.",
-	"Files": "",
+	"Files": "Arxius",
 	"Filter is now globally disabled": "El filtre ha estat desactivat globalment",
 	"Filter is now globally enabled": "El filtre ha estat activat globalment",
 	"Filters": "Filtres",
@@ -364,7 +364,6 @@
 	"Manage Models": "Gestionar els models",
 	"Manage Ollama Models": "Gestionar els models Ollama",
 	"Manage Pipelines": "Gestionar les Pipelines",
-	"Manage Valves": "Gestionar les Valves",
 	"March": "Març",
 	"Max Tokens (num_predict)": "Nombre màxim de Tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es poden descarregar un màxim de 3 models simultàniament. Si us plau, prova-ho més tard.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Memòria eliminada correctament",
 	"Memory updated successfully": "Memòria actualitzada correctament",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Els missatges enviats després de crear el teu enllaç no es compartiran. Els usuaris amb l'URL podran veure el xat compartit.",
+	"Min P": "Min P",
 	"Minimum Score": "Puntuació mínima",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Eta de Mirostat",
@@ -504,7 +504,7 @@
 	"Save": "Desar",
 	"Save & Create": "Desar i crear",
 	"Save & Update": "Desar i actualitzar",
-	"Save Tag": "",
+	"Save Tag": "Desar l'etiqueta",
 	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Desar els registres de xat directament a l'emmagatzematge del teu navegador ja no està suportat. Si us plau, descarregr i elimina els registres de xat fent clic al botó de sota. No et preocupis, pots tornar a importar fàcilment els teus registres de xat al backend a través de",
 	"Scan": "Escanejar",
 	"Scan complete!": "Escaneigr completat!",
@@ -623,7 +623,7 @@
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Per accedir a la WebUI, poseu-vos en contacte amb l'administrador. Els administradors poden gestionar els estats dels usuaris des del tauler d'administració.",
 	"To add documents here, upload them to the \"Documents\" workspace first.": "Per afegir documents aquí, puja-ls primer a l'espai de treball \"Documents\".",
 	"to chat input.": "a l'entrada del xat.",
-	"To select actions here, add them to the \"Functions\" workspace first.": "",
+	"To select actions here, add them to the \"Functions\" workspace first.": "Per seleccionar accions aquí, afegeix-los primer a l'espai de treball \"Funcions\".",
 	"To select filters here, add them to the \"Functions\" workspace first.": "Per seleccionar filtres aquí, afegeix-los primer a l'espai de treball \"Funcions\".",
 	"To select toolkits here, add them to the \"Tools\" workspace first.": "Per seleccionar kits d'eines aquí, afegeix-los primer a l'espai de treball \"Eines\".",
 	"Today": "Avui",

+ 1 - 1
src/lib/i18n/locales/ceb-PH/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Pagdumala sa mga templates",
 	"Manage Ollama Models": "Pagdumala sa mga modelo sa Ollama",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Ang labing taas nga 3 nga mga disenyo mahimong ma-download nga dungan. ",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/de-DE/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Modelle verwalten",
 	"Manage Ollama Models": "Ollama-Modelle verwalten",
 	"Manage Pipelines": "Pipelines verwalten",
-	"Manage Valves": "Valves verwalten",
 	"March": "März",
 	"Max Tokens (num_predict)": "Maximale Tokenanzahl (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es können maximal 3 Modelle gleichzeitig heruntergeladen werden. Bitte versuchen Sie es später erneut.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Erinnerung erfolgreich gelöscht",
 	"Memory updated successfully": "Erinnerung erfolgreich aktualisiert",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Nachrichten, die Sie nach der Erstellung Ihres Links senden, werden nicht geteilt. Nutzer mit der URL können die freigegebene Unterhaltung einsehen.",
+	"Min P": "",
 	"Minimum Score": "Mindestpunktzahl",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/dg-DG/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Manage Wowdels",
 	"Manage Ollama Models": "Manage Ollama Wowdels",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maximum of 3 models can be downloaded simultaneously. Please try again later.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/en-GB/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "",
 	"Manage Ollama Models": "",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "",
 	"Mirostat": "",
 	"Mirostat Eta": "",

+ 1 - 1
src/lib/i18n/locales/en-US/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "",
 	"Manage Ollama Models": "",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "",
 	"Mirostat": "",
 	"Mirostat Eta": "",

+ 1 - 1
src/lib/i18n/locales/es-ES/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Administrar Modelos",
 	"Manage Ollama Models": "Administrar Modelos Ollama",
 	"Manage Pipelines": "Administrar Pipelines",
-	"Manage Valves": "Gestionar Valves",
 	"March": "Marzo",
 	"Max Tokens (num_predict)": "Máximo de fichas (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Se pueden descargar un máximo de 3 modelos simultáneamente. Por favor, inténtelo de nuevo más tarde.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Memoria borrada correctamente",
 	"Memory updated successfully": "Memoria actualizada correctamente",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de crear su enlace no se compartirán. Los usuarios con el enlace podrán ver el chat compartido.",
+	"Min P": "",
 	"Minimum Score": "Puntuación mínima",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/fa-IR/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "مدیریت مدل\u200cها",
 	"Manage Ollama Models": "مدیریت مدل\u200cهای اولاما",
 	"Manage Pipelines": "مدیریت خطوط لوله",
-	"Manage Valves": "",
 	"March": "مارچ",
 	"Max Tokens (num_predict)": "توکنهای بیشینه (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "حداکثر 3 مدل را می توان به طور همزمان دانلود کرد. لطفاً بعداً دوباره امتحان کنید.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "پیام های شما بعد از ایجاد لینک شما به اشتراک نمی گردد. کاربران با لینک URL می توانند چت اشتراک را مشاهده کنند.",
+	"Min P": "",
 	"Minimum Score": "نماد کمینه",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/fi-FI/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Hallitse malleja",
 	"Manage Ollama Models": "Hallitse Ollama-malleja",
 	"Manage Pipelines": "Hallitse putkia",
-	"Manage Valves": "",
 	"March": "maaliskuu",
 	"Max Tokens (num_predict)": "Tokenien enimmäismäärä (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Enintään 3 mallia voidaan ladata samanaikaisesti. Yritä myöhemmin uudelleen.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"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ämiäsi viestejä ei jaeta. Käyttäjät, joilla on URL-osoite, voivat tarkastella jaettua keskustelua.",
+	"Min P": "",
 	"Minimum Score": "Vähimmäispisteet",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/fr-CA/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Gérer les Modèles",
 	"Manage Ollama Models": "Gérer les modèles Ollama",
 	"Manage Pipelines": "Gérer les pipelines",
-	"Manage Valves": "Gérer les vannes",
 	"March": "Mars",
 	"Max Tokens (num_predict)": "Tokens maximaux (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Un maximum de 3 modèles peut être téléchargé en même temps. Veuillez réessayer ultérieurement.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "La mémoire a été supprimée avec succès",
 	"Memory updated successfully": "La mémoire a été mise à jour avec succès",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Les messages que vous envoyez après avoir créé votre lien ne seront pas partagés. Les utilisateurs disposant de l'URL pourront voir le chat partagé.",
+	"Min P": "",
 	"Minimum Score": "Score minimal",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/fr-FR/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Gérer les Modèles",
 	"Manage Ollama Models": "Gérer les modèles Ollama",
 	"Manage Pipelines": "Gérer les pipelines",
-	"Manage Valves": "Gérer les vannes",
 	"March": "Mars",
 	"Max Tokens (num_predict)": "Tokens maximaux (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Un maximum de 3 modèles peut être téléchargé en même temps. Veuillez réessayer ultérieurement.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "La mémoire a été supprimée avec succès",
 	"Memory updated successfully": "La mémoire a été mise à jour avec succès",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Les messages que vous envoyez après avoir créé votre lien ne seront pas partagés. Les utilisateurs disposant de l'URL pourront voir le chat partagé.",
+	"Min P": "",
 	"Minimum Score": "Score minimal",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/he-IL/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "נהל מודלים",
 	"Manage Ollama Models": "נהל מודלים של Ollama",
 	"Manage Pipelines": "ניהול צינורות",
-	"Manage Valves": "",
 	"March": "מרץ",
 	"Max Tokens (num_predict)": "מקסימום אסימונים (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "ניתן להוריד מקסימום 3 מודלים בו זמנית. אנא נסה שוב מאוחר יותר.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "הודעות שתשלח לאחר יצירת הקישור לא ישותפו. משתמשים עם כתובת האתר יוכלו לצפות בצ'אט המשותף.",
+	"Min P": "",
 	"Minimum Score": "ציון מינימלי",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/hi-IN/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "मॉडल प्रबंधित करें",
 	"Manage Ollama Models": "Ollama मॉडल प्रबंधित करें",
 	"Manage Pipelines": "पाइपलाइनों का प्रबंधन करें",
-	"Manage Valves": "",
 	"March": "मार्च",
 	"Max Tokens (num_predict)": "अधिकतम टोकन (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "अधिकतम 3 मॉडल एक साथ डाउनलोड किये जा सकते हैं। कृपया बाद में पुन: प्रयास करें।",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "अपना लिंक बनाने के बाद आपके द्वारा भेजे गए संदेश साझा नहीं किए जाएंगे। यूआरएल वाले यूजर्स शेयर की गई चैट देख पाएंगे।",
+	"Min P": "",
 	"Minimum Score": "न्यूनतम स्कोर",
 	"Mirostat": "मिरोस्टा",
 	"Mirostat Eta": "मिरोस्टा ईटा",

+ 1 - 1
src/lib/i18n/locales/hr-HR/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Upravljanje modelima",
 	"Manage Ollama Models": "Upravljanje Ollama modelima",
 	"Manage Pipelines": "Upravljanje cjevovodima",
-	"Manage Valves": "",
 	"March": "Ožujak",
 	"Max Tokens (num_predict)": "Maksimalan broj tokena (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maksimalno 3 modela se mogu preuzeti istovremeno. Pokušajte ponovo kasnije.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Poruke koje pošaljete nakon stvaranja veze neće se dijeliti. Korisnici s URL-om moći će vidjeti zajednički chat.",
+	"Min P": "",
 	"Minimum Score": "Minimalna ocjena",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/id-ID/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Kelola Model",
 	"Manage Ollama Models": "Mengelola Model Ollama",
 	"Manage Pipelines": "Mengelola Saluran Pipa",
-	"Manage Valves": "Kelola Katup",
 	"March": "Maret",
 	"Max Tokens (num_predict)": "Token Maksimal (num_prediksi)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maksimal 3 model dapat diunduh secara bersamaan. Silakan coba lagi nanti.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Memori berhasil dihapus",
 	"Memory updated successfully": "Memori berhasil diperbarui",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Pesan yang Anda kirim setelah membuat tautan tidak akan dibagikan. Pengguna yang memiliki URL tersebut akan dapat melihat obrolan yang dibagikan.",
+	"Min P": "",
 	"Minimum Score": "Skor Minimum",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/it-IT/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Gestisci modelli",
 	"Manage Ollama Models": "Gestisci modelli Ollama",
 	"Manage Pipelines": "Gestire le pipeline",
-	"Manage Valves": "",
 	"March": "Marzo",
 	"Max Tokens (num_predict)": "Numero massimo di gettoni (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "È possibile scaricare un massimo di 3 modelli contemporaneamente. Riprova più tardi.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "I messaggi inviati dopo la creazione del link non verranno condivisi. Gli utenti con l'URL saranno in grado di visualizzare la chat condivisa.",
+	"Min P": "",
 	"Minimum Score": "Punteggio minimo",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/ja-JP/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "モデルを管理",
 	"Manage Ollama Models": "Ollama モデルを管理",
 	"Manage Pipelines": "パイプラインの管理",
-	"Manage Valves": "",
 	"March": "3月",
 	"Max Tokens (num_predict)": "最大トークン数 (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "同時にダウンロードできるモデルは最大 3 つです。後でもう一度お試しください。",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "リンクを作成した後、送信したメッセージは共有されません。URL を持つユーザーは共有チャットを閲覧できます。",
+	"Min P": "",
 	"Minimum Score": "最低スコア",
 	"Mirostat": "ミロスタット",
 	"Mirostat Eta": "ミロスタット Eta",

+ 1 - 1
src/lib/i18n/locales/ka-GE/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "მოდელების მართვა",
 	"Manage Ollama Models": "Ollama მოდელების მართვა",
 	"Manage Pipelines": "მილსადენების მართვა",
-	"Manage Valves": "",
 	"March": "მარტივი",
 	"Max Tokens (num_predict)": "მაქს ტოკენსი (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "მაქსიმუმ 3 მოდელის ჩამოტვირთვა შესაძლებელია ერთდროულად. Გთხოვთ სცადოთ მოგვიანებით.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "შეტყობინებები, რომელსაც თქვენ აგზავნით თქვენი ბმულის შექმნის შემდეგ, არ იქნება გაზიარებული. URL– ის მქონე მომხმარებლებს შეეძლებათ ნახონ საერთო ჩატი.",
+	"Min P": "",
 	"Minimum Score": "მინიმალური ქულა",
 	"Mirostat": "მიროსტატი",
 	"Mirostat Eta": "მიროსტატი ეტა",

+ 1 - 1
src/lib/i18n/locales/ko-KR/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "모델 관리",
 	"Manage Ollama Models": "Ollama 모델 관리",
 	"Manage Pipelines": "파이프라인 관리",
-	"Manage Valves": "",
 	"March": "3월",
 	"Max Tokens (num_predict)": "최대 토큰(num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "최대 3개의 모델을 동시에 다운로드할 수 있습니다. 나중에 다시 시도하세요.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "링크 생성 후에 보낸 메시지는 공유되지 않습니다. URL이 있는 사용자는 공유된 채팅을 볼 수 있습니다.",
+	"Min P": "",
 	"Minimum Score": "최소 점수",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 4 - 0
src/lib/i18n/locales/languages.json

@@ -111,6 +111,10 @@
 		"code": "pt-PT",
 		"title": "Portuguese (Portugal)"
 	},
+	{
+		"code": "ro-RO",
+		"title": "Romanian (Romania)"
+	},
 	{
 		"code": "ru-RU",
 		"title": "Russian (Russia)"

+ 1 - 1
src/lib/i18n/locales/lt-LT/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Tvarkyti modelius",
 	"Manage Ollama Models": "Tvarkyti Ollama modelius",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "Kovas",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Daugiausiai trys modeliai gali būti parsisiunčiami vienu metu.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "Minimalus rezultatas",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 214 - 214
src/lib/i18n/locales/nb-NO/translation.json

@@ -1,22 +1,22 @@
 {
 	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 't', 'd', 'u' eller '-1' for ingen utløp.",
 	"(Beta)": "(Beta)",
-	"(e.g. `sh webui.sh --api --api-auth username_password`)": "",
+	"(e.g. `sh webui.sh --api --api-auth username_password`)": "(f.eks. `sh webui.sh --api --api-auth brukernavn_passord`)",
 	"(e.g. `sh webui.sh --api`)": "(f.eks. `sh webui.sh --api`)",
 	"(latest)": "(siste)",
 	"{{ models }}": "{{ modeller }}",
 	"{{ owner }}: You cannot delete a base model": "{{ eier }}: Du kan ikke slette en grunnmodell",
 	"{{modelName}} is thinking...": "{{modelName}} tenker...",
-	"{{user}}'s Chats": "{{user}}'s chatter",
+	"{{user}}'s Chats": "{{user}}s samtaler",
 	"{{webUIName}} Backend Required": "{{webUIName}} Backend kreves",
-	"A task model is used when performing tasks such as generating titles for chats and web search queries": "En oppgavemodell brukes når du utfører oppgaver som å generere titler for chatter og websøkeforespørsler",
+	"A task model is used when performing tasks such as generating titles for chats and web search queries": "En oppgavemodell brukes når du utfører oppgaver som å generere titler for samtaler og websøkeforespørsler",
 	"a user": "en bruker",
 	"About": "Om",
 	"Account": "Konto",
-	"Account Activation Pending": "",
+	"Account Activation Pending": "Venter på kontoaktivering",
 	"Accurate information": "Nøyaktig informasjon",
-	"Actions": "",
-	"Active Users": "",
+	"Actions": "Handlinger",
+	"Active Users": "Aktive brukere",
 	"Add": "Legg til",
 	"Add a model id": "Legg til en modell-ID",
 	"Add a short description about what this model does": "Legg til en kort beskrivelse av hva denne modellen gjør",
@@ -28,15 +28,15 @@
 	"Add Memory": "Legg til minne",
 	"Add message": "Legg til melding",
 	"Add Model": "Legg til modell",
-	"Add Tag": "",
+	"Add Tag": "Legg til tag",
 	"Add Tags": "Legg til tagger",
 	"Add User": "Legg til bruker",
-	"Adjusting these settings will apply changes universally to all users.": "Justering av disse innstillingene vil gjelde universelt for alle brukere.",
+	"Adjusting these settings will apply changes universally to all users.": "Endringer i disse innstillingene vil gjelde for alle brukere uten unntak.",
 	"admin": "administrator",
-	"Admin": "",
+	"Admin": "Administrator",
 	"Admin Panel": "Administrasjonspanel",
 	"Admin Settings": "Administrasjonsinnstillinger",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorer har alltid tilgang til alle verktøy, mens brukere må få tildelt verktøy for hver enkelt modell i arbeidsområdet.",
 	"Advanced Parameters": "Avanserte parametere",
 	"Advanced Params": "Avanserte parametere",
 	"all": "alle",
@@ -45,8 +45,8 @@
 	"Allow": "Tillat",
 	"Allow Chat Deletion": "Tillat sletting av chatter",
 	"Allow non-local voices": "Tillat ikke-lokale stemmer",
-	"Allow User Location": "",
-	"Allow Voice Interruption in Call": "",
+	"Allow User Location": "Aktiver stedstjenester",
+	"Allow Voice Interruption in Call": "Muliggjør stemmeavbrytelse i samtale",
 	"alphanumeric characters and hyphens": "alfanumeriske tegn og bindestreker",
 	"Already have an account?": "Har du allerede en konto?",
 	"an assistant": "en assistent",
@@ -56,19 +56,19 @@
 	"API Key": "API-nøkkel",
 	"API Key created.": "API-nøkkel opprettet.",
 	"API keys": "API-nøkler",
-	"April": "April",
+	"April": "april",
 	"Archive": "Arkiv",
 	"Archive All Chats": "Arkiver alle chatter",
 	"Archived Chats": "Arkiverte chatter",
 	"are allowed - Activate this command by typing": "er tillatt - Aktiver denne kommandoen ved å skrive",
 	"Are you sure?": "Er du sikker?",
 	"Attach file": "Legg ved fil",
-	"Attention to detail": "Oppmerksomhet på detaljer",
+	"Attention to detail": "Sans for detaljer",
 	"Audio": "Lyd",
-	"Audio settings updated successfully": "",
-	"August": "August",
+	"Audio settings updated successfully": "Lydinnstillingene ble oppdatert",
+	"August": "august",
 	"Auto-playback response": "Automatisk avspilling av svar",
-	"AUTOMATIC1111 Api Auth String": "",
+	"AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Autentiseringsstreng",
 	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Grunn-URL",
 	"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Grunn-URL kreves.",
 	"available!": "tilgjengelig!",
@@ -76,21 +76,21 @@
 	"Bad Response": "Dårlig svar",
 	"Banners": "Bannere",
 	"Base Model (From)": "Grunnmodell (Fra)",
-	"Batch Size (num_batch)": "",
+	"Batch Size (num_batch)": "Batchstørrelse (num_batch)",
 	"before": "før",
 	"Being lazy": "Er lat",
 	"Brave Search API Key": "Brave Search API-nøkkel",
 	"Bypass SSL verification for Websites": "Omgå SSL-verifisering for nettsteder",
-	"Call": "",
-	"Call feature is not supported when using Web STT engine": "",
-	"Camera": "",
+	"Call": "Ring",
+	"Call feature is not supported when using Web STT engine": "Ringefunksjonen støttes ikke når du bruker Web STT-motoren",
+	"Camera": "Kamera",
 	"Cancel": "Avbryt",
 	"Capabilities": "Muligheter",
 	"Change Password": "Endre passord",
 	"Chat": "Chat",
-	"Chat Background Image": "",
+	"Chat Background Image": "Bakgrunnsbilde for chat",
 	"Chat Bubble UI": "Chat-boble UI",
-	"Chat Controls": "",
+	"Chat Controls": "Chat-kontroller",
 	"Chat direction": "Chat-retning",
 	"Chat History": "Chat-historikk",
 	"Chat History is off for this browser.": "Chat-historikk er av for denne nettleseren.",
@@ -103,37 +103,37 @@
 	"Chunk Params": "Chunk-parametere",
 	"Chunk Size": "Chunk-størrelse",
 	"Citation": "Sitering",
-	"Clear memory": "",
+	"Clear memory": "Tøm minnet",
 	"Click here for help.": "Klikk her for hjelp.",
 	"Click here to": "Klikk her for å",
-	"Click here to download user import template file.": "",
+	"Click here to download user import template file.": "Klikk her for å hente ned importmal for brukere.",
 	"Click here to select": "Klikk her for å velge",
 	"Click here to select a csv file.": "Klikk her for å velge en csv-fil.",
-	"Click here to select a py file.": "",
+	"Click here to select a py file.": "Klikk her for å velge en py-fil.",
 	"Click here to select documents.": "Klikk her for å velge dokumenter.",
 	"click here.": "klikk her.",
 	"Click on the user role button to change a user's role.": "Klikk på brukerrolle-knappen for å endre en brukers rolle.",
-	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Skrivetilgang til utklippstavlen ble avslått. Kontroller nettleserinnstillingene for å gi nødvendig tillatelse.",
 	"Clone": "Klon",
 	"Close": "Lukk",
-	"Code formatted successfully": "",
+	"Code formatted successfully": "Koden ble formatert",
 	"Collection": "Samling",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI Base URL": "ComfyUI Grunn-URL",
 	"ComfyUI Base URL is required.": "ComfyUI Grunn-URL kreves.",
 	"Command": "Kommando",
 	"Concurrent Requests": "Samtidige forespørsler",
-	"Confirm": "",
+	"Confirm": "Bekreft",
 	"Confirm Password": "Bekreft passord",
-	"Confirm your action": "",
+	"Confirm your action": "Bekreft din handling",
 	"Connections": "Tilkoblinger",
-	"Contact Admin for WebUI Access": "",
+	"Contact Admin for WebUI Access": "Kontakt administrator for WebUI-tilgang",
 	"Content": "Innhold",
-	"Content Extraction": "",
+	"Content Extraction": "Uthenting av innhold",
 	"Context Length": "Kontekstlengde",
 	"Continue Response": "Fortsett svar",
-	"Continue with {{provider}}": "",
-	"Controls": "",
+	"Continue with {{provider}}": "Fortsett med {{provider}}",
+	"Controls": "Kontroller",
 	"Copied shared chat URL to clipboard!": "Kopiert delt chat-URL til utklippstavlen!",
 	"Copy": "Kopier",
 	"Copy last code block": "Kopier siste kodeblokk",
@@ -146,16 +146,16 @@
 	"Create new secret key": "Lag ny hemmelig nøkkel",
 	"Created at": "Opprettet",
 	"Created At": "Opprettet",
-	"Created by": "",
-	"CSV Import": "",
+	"Created by": "Opprettet av",
+	"CSV Import": "CSV-import",
 	"Current Model": "Nåværende modell",
 	"Current Password": "Nåværende passord",
 	"Custom": "Tilpasset",
 	"Customize models for a specific purpose": "Tilpass modeller for et spesifikt formål",
 	"Dark": "Mørk",
-	"Dashboard": "",
+	"Dashboard": "Instrumentbord",
 	"Database": "Database",
-	"December": "Desember",
+	"December": "desember",
 	"Default": "Standard",
 	"Default (Automatic1111)": "Standard (Automatic1111)",
 	"Default (SentenceTransformers)": "Standard (SentenceTransformers)",
@@ -169,42 +169,42 @@
 	"Delete All Chats": "Slett alle chatter",
 	"Delete chat": "Slett chat",
 	"Delete Chat": "Slett chat",
-	"Delete chat?": "",
-	"Delete Doc": "",
-	"Delete function?": "",
-	"Delete prompt?": "",
+	"Delete chat?": "Slett chat?",
+	"Delete Doc": "Slett dokument",
+	"Delete function?": "Slett funksjon?",
+	"Delete prompt?": "Slett prompt?",
 	"delete this link": "slett denne lenken",
-	"Delete tool?": "",
+	"Delete tool?": "Slett verktøy?",
 	"Delete User": "Slett bruker",
 	"Deleted {{deleteModelTag}}": "Slettet {{deleteModelTag}}",
 	"Deleted {{name}}": "Slettet {{name}}",
 	"Description": "Beskrivelse",
 	"Didn't fully follow instructions": "Fulgte ikke instruksjonene fullt ut",
-	"Disabled": "",
-	"Discover a function": "",
+	"Disabled": "Deaktivert",
+	"Discover a function": "Oppdag en funksjon",
 	"Discover a model": "Oppdag en modell",
 	"Discover a prompt": "Oppdag en prompt",
-	"Discover a tool": "",
-	"Discover, download, and explore custom functions": "",
+	"Discover a tool": "Oppdag et verktøy",
+	"Discover, download, and explore custom functions": "Oppdag, last ned og utforsk egendefinerte funksjoner",
 	"Discover, download, and explore custom prompts": "Oppdag, last ned og utforsk egendefinerte prompts",
-	"Discover, download, and explore custom tools": "",
+	"Discover, download, and explore custom tools": "Oppdag, last ned og utforsk egendefinerte verktøy",
 	"Discover, download, and explore model presets": "Oppdag, last ned og utforsk modellforhåndsinnstillinger",
-	"Dismissible": "",
-	"Display Emoji in Call": "",
+	"Dismissible": "Kan lukkes",
+	"Display Emoji in Call": "Vis emoji i samtale",
 	"Display the username instead of You in the Chat": "Vis brukernavnet i stedet for Du i chatten",
-	"Do not install functions from sources you do not fully trust.": "",
-	"Do not install tools from sources you do not fully trust.": "",
+	"Do not install functions from sources you do not fully trust.": "Ikke installer funksjoner fra kilder du ikke fullt ut stoler på.",
+	"Do not install tools from sources you do not fully trust.": "Ikke installer verktøy fra kilder du ikke fullt ut stoler på.",
 	"Document": "Dokument",
 	"Document Settings": "Dokumentinnstillinger",
 	"Documentation": "Dokumentasjon",
 	"Documents": "Dokumenter",
-	"does not make any external connections, and your data stays securely on your locally hosted server.": "lager ingen eksterne tilkoblinger, og dataene dine forblir trygt på din lokalt hostede server.",
+	"does not make any external connections, and your data stays securely on your locally hosted server.": "har ingen tilkobling til eksterne tjenester, og dataene dine blir værende sikkert på din lokale tjener.",
 	"Don't Allow": "Ikke tillat",
 	"Don't have an account?": "Har du ikke en konto?",
-	"don't install random functions from sources you don't trust.": "",
-	"don't install random tools from sources you don't trust.": "",
+	"don't install random functions from sources you don't trust.": "ikke installer tilfeldige funksjoner fra kilder du ikke stoler på.",
+	"don't install random tools from sources you don't trust.": "ikke installer tilfeldige verktøy fra kilder du ikke stoler på.",
 	"Don't like the style": "Liker ikke stilen",
-	"Done": "",
+	"Done": "Ferdig",
 	"Download": "Last ned",
 	"Download canceled": "Nedlasting avbrutt",
 	"Download Database": "Last ned database",
@@ -212,9 +212,9 @@
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "f.eks. '30s','10m'. Gyldige tidsenheter er 's', 'm', 't'.",
 	"Edit": "Rediger",
 	"Edit Doc": "Rediger dokument",
-	"Edit Memory": "",
+	"Edit Memory": "Rediger minne",
 	"Edit User": "Rediger bruker",
-	"ElevenLabs": "",
+	"ElevenLabs": "ElevenLabs",
 	"Email": "E-post",
 	"Embedding Batch Size": "Batch-størrelse for embedding",
 	"Embedding Model": "Embedding-modell",
@@ -224,12 +224,12 @@
 	"Enable Community Sharing": "Aktiver deling i fellesskap",
 	"Enable New Sign Ups": "Aktiver nye registreringer",
 	"Enable Web Search": "Aktiver websøk",
-	"Enabled": "",
-	"Engine": "",
+	"Enabled": "Aktivert",
+	"Engine": "Motor",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Sørg for at CSV-filen din inkluderer 4 kolonner i denne rekkefølgen: Navn, E-post, Passord, Rolle.",
 	"Enter {{role}} message here": "Skriv inn {{role}} melding her",
-	"Enter a detail about yourself for your LLMs to recall": "Skriv inn en detalj om deg selv som LLM-ene dine kan huske",
-	"Enter api auth string (e.g. username:password)": "",
+	"Enter a detail about yourself for your LLMs to recall": "Skriv inn en detalj om deg selv som språkmodellene dine kan huske",
+	"Enter api auth string (e.g. username:password)": "Skriv inn api-autentiseringsstreng (f.eks. brukernavn:passord)",
 	"Enter Brave Search API Key": "Skriv inn Brave Search API-nøkkel",
 	"Enter Chunk Overlap": "Skriv inn Chunk Overlap",
 	"Enter Chunk Size": "Skriv inn Chunk-størrelse",
@@ -243,18 +243,18 @@
 	"Enter Score": "Skriv inn poengsum",
 	"Enter Searxng Query URL": "Skriv inn Searxng forespørsels-URL",
 	"Enter Serper API Key": "Skriv inn Serper API-nøkkel",
-	"Enter Serply API Key": "",
+	"Enter Serply API Key": "Skriv inn Serply API-nøkkel",
 	"Enter Serpstack API Key": "Skriv inn Serpstack API-nøkkel",
 	"Enter stop sequence": "Skriv inn stoppsekvens",
-	"Enter system prompt": "",
-	"Enter Tavily API Key": "",
-	"Enter Tika Server URL": "",
+	"Enter system prompt": "Skriv inn systemprompt",
+	"Enter Tavily API Key": "Skriv inn Tavily API-nøkkel",
+	"Enter Tika Server URL": "Skriv inn Tika Server-URL",
 	"Enter Top K": "Skriv inn Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Skriv inn URL (f.eks. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Skriv inn URL (f.eks. http://localhost:11434)",
 	"Enter Your Email": "Skriv inn din e-post",
 	"Enter Your Full Name": "Skriv inn ditt fulle navn",
-	"Enter your message": "",
+	"Enter your message": "Skriv inn meldingen din",
 	"Enter Your Password": "Skriv inn ditt passord",
 	"Enter Your Role": "Skriv inn din rolle",
 	"Error": "Feil",
@@ -264,50 +264,50 @@
 	"Export chat (.json)": "Eksporter chat (.json)",
 	"Export Chats": "Eksporter chatter",
 	"Export Documents Mapping": "Eksporter dokumentkartlegging",
-	"Export Functions": "",
-	"Export LiteLLM config.yaml": "",
+	"Export Functions": "Eksporter funksjoner",
+	"Export LiteLLM config.yaml": "Eksporter LiteLLM config.yaml",
 	"Export Models": "Eksporter modeller",
 	"Export Prompts": "Eksporter prompts",
-	"Export Tools": "",
-	"External Models": "",
+	"Export Tools": "Eksporter verktøy",
+	"External Models": "Eksterne modeller",
 	"Failed to create API Key.": "Kunne ikke opprette API-nøkkel.",
 	"Failed to read clipboard contents": "Kunne ikke lese utklippstavleinnhold",
 	"Failed to update settings": "Kunne ikke oppdatere innstillinger",
-	"February": "Februar",
-	"Feel free to add specific details": "Føl deg fri til å legge til spesifikke detaljer",
-	"File": "",
+	"February": "februar",
+	"Feel free to add specific details": "Legg gjerne til spesifikke detaljer",
+	"File": "Fil",
 	"File Mode": "Filmodus",
 	"File not found.": "Fil ikke funnet.",
-	"Files": "",
-	"Filter is now globally disabled": "",
-	"Filter is now globally enabled": "",
-	"Filters": "",
+	"Files": "Filer",
+	"Filter is now globally disabled": "Filteret er nå deaktivert på systemnivå",
+	"Filter is now globally enabled": "Filteret er nå aktivert på systemnivå",
+	"Filters": "Filtere",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrykk-spoofing oppdaget: Kan ikke bruke initialer som avatar. Bruker standard profilbilde.",
-	"Fluidly stream large external response chunks": "Strøm store eksterne svarchunks flytende",
+	"Fluidly stream large external response chunks": "Flytende strømming av store eksterne responsbiter",
 	"Focus chat input": "Fokuser chatinput",
 	"Followed instructions perfectly": "Fulgte instruksjonene perfekt",
-	"Form": "",
+	"Form": "Form",
 	"Format your variables using square brackets like this:": "Formatér variablene dine med hakeparenteser som dette:",
 	"Frequency Penalty": "Frekvensstraff",
-	"Function created successfully": "",
-	"Function deleted successfully": "",
-	"Function Description (e.g. A filter to remove profanity from text)": "",
-	"Function ID (e.g. my_filter)": "",
-	"Function is now globally disabled": "",
-	"Function is now globally enabled": "",
-	"Function Name (e.g. My Filter)": "",
-	"Function updated successfully": "",
-	"Functions": "",
-	"Functions allow arbitrary code execution": "",
-	"Functions allow arbitrary code execution.": "",
-	"Functions imported successfully": "",
+	"Function created successfully": "Funksjonen ble opprettet",
+	"Function deleted successfully": "Funksjonen ble slettet",
+	"Function Description (e.g. A filter to remove profanity from text)": "Funksjonsbeskrivelse (f.eks. Et filter for å fjerne banning fra tekst)",
+	"Function ID (e.g. my_filter)": "Funksjons-id (f.eks. my_filter)",
+	"Function is now globally disabled": "Funksjonen er nå deaktivert på systemnivå",
+	"Function is now globally enabled": "Funksjonen er nå aktivert på systemnivå",
+	"Function Name (e.g. My Filter)": "Funksjonsnavn (f.eks. Mitt Filter)",
+	"Function updated successfully": "Funksjonen ble oppdatert",
+	"Functions": "Funksjoner",
+	"Functions allow arbitrary code execution": "Funksjoner tillater vilkårlig kodeeksekvering",
+	"Functions allow arbitrary code execution.": "Funksjoner tillater vilkårlig kodeeksekvering.",
+	"Functions imported successfully": "Funksjoner importert",
 	"General": "Generelt",
 	"General Settings": "Generelle innstillinger",
-	"Generate Image": "",
+	"Generate Image": "Generer bilde",
 	"Generating search query": "Genererer søkeforespørsel",
 	"Generation Info": "Generasjonsinfo",
-	"Get up and running with": "",
-	"Global": "",
+	"Get up and running with": "Kom i gang med",
+	"Global": "Systemnivå",
 	"Good Response": "Godt svar",
 	"Google PSE API Key": "Google PSE API-nøkkel",
 	"Google PSE Engine Id": "Google PSE Motor-ID",
@@ -316,84 +316,84 @@
 	"Hello, {{name}}": "Hei, {{name}}",
 	"Help": "Hjelp",
 	"Hide": "Skjul",
-	"Hide Model": "",
+	"Hide Model": "Skjul modell",
 	"How can I help you today?": "Hvordan kan jeg hjelpe deg i dag?",
 	"Hybrid Search": "Hybrid-søk",
-	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "",
+	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Jeg bekrefter at jeg har lest og forstår konsekvensene av min handling. Jeg er klar over risikoen forbundet med å kjøre vilkårlig kode, og jeg har verifisert kildens pålitelighet.",
 	"Image Generation (Experimental)": "Bildegenerering (Eksperimentell)",
 	"Image Generation Engine": "Bildegenereringsmotor",
 	"Image Settings": "Bildeinnstillinger",
 	"Images": "Bilder",
 	"Import Chats": "Importer chatter",
 	"Import Documents Mapping": "Importer dokumentkartlegging",
-	"Import Functions": "",
+	"Import Functions": "Funksjoner",
 	"Import Models": "Importer modeller",
 	"Import Prompts": "Importer prompts",
-	"Import Tools": "",
-	"Include `--api-auth` flag when running stable-diffusion-webui": "",
+	"Import Tools": "Importer verktøy",
+	"Include `--api-auth` flag when running stable-diffusion-webui": "Inkluder `--api-auth`-flagget når du kjører stable-diffusion-webui",
 	"Include `--api` flag when running stable-diffusion-webui": "Inkluder `--api`-flagget når du kjører stable-diffusion-webui",
 	"Info": "Info",
 	"Input commands": "Inntast kommandoer",
 	"Install from Github URL": "Installer fra Github-URL",
-	"Instant Auto-Send After Voice Transcription": "",
+	"Instant Auto-Send After Voice Transcription": "Direkte autosending etter stemmegjenkjenning",
 	"Interface": "Grensesnitt",
 	"Invalid Tag": "Ugyldig tag",
-	"January": "Januar",
+	"January": "januar",
 	"join our Discord for help.": "bli med i vår Discord for hjelp.",
 	"JSON": "JSON",
 	"JSON Preview": "JSON-forhåndsvisning",
-	"July": "Juli",
-	"June": "Juni",
+	"July": "juli",
+	"June": "juni",
 	"JWT Expiration": "JWT-utløp",
 	"JWT Token": "JWT-token",
 	"Keep Alive": "Hold i live",
 	"Keyboard shortcuts": "Hurtigtaster",
-	"Knowledge": "",
+	"Knowledge": "Kunnskap",
 	"Language": "Språk",
-	"large language models, locally.": "",
+	"large language models, locally.": "Store språkmodeller, lokalt.",
 	"Last Active": "Sist aktiv",
-	"Last Modified": "",
+	"Last Modified": "Sist endret",
 	"Light": "Lys",
-	"Listening...": "",
-	"LLMs can make mistakes. Verify important information.": "LLM-er kan gjøre feil. Verifiser viktig informasjon.",
-	"Local Models": "",
+	"Listening...": "Lytter ...",
+	"LLMs can make mistakes. Verify important information.": "Språkmodeller kan gjøre feil. Verifiser viktige opplysninger.",
+	"Local Models": "Lokale modeller",
 	"LTR": "LTR",
 	"Made by OpenWebUI Community": "Laget av OpenWebUI-fellesskapet",
 	"Make sure to enclose them with": "Sørg for å omslutte dem med",
-	"Manage": "",
+	"Manage": "Administrer",
 	"Manage Models": "Administrer modeller",
 	"Manage Ollama Models": "Administrer Ollama-modeller",
 	"Manage Pipelines": "Administrer pipelines",
-	"Manage Valves": "",
-	"March": "Mars",
+	"March": "mars",
 	"Max Tokens (num_predict)": "Maks antall tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maksimalt 3 modeller kan lastes ned samtidig. Vennligst prøv igjen senere.",
-	"May": "Mai",
-	"Memories accessible by LLMs will be shown here.": "Minner tilgjengelige for LLM-er vil vises her.",
+	"May": "mai",
+	"Memories accessible by LLMs will be shown here.": "Minner tilgjengelige for språkmodeller vil vises her.",
 	"Memory": "Minne",
-	"Memory added successfully": "",
-	"Memory cleared successfully": "",
-	"Memory deleted successfully": "",
-	"Memory updated successfully": "",
+	"Memory added successfully": "Minne lagt til",
+	"Memory cleared successfully": "Minne tømt",
+	"Memory deleted successfully": "Minne slettet",
+	"Memory updated successfully": "Minne oppdatert",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meldinger du sender etter at du har opprettet lenken din vil ikke bli delt. Brukere med URL-en vil kunne se den delte chatten.",
+	"Min P": "",
 	"Minimum Score": "Minimum poengsum",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Tau": "Mirostat Tau",
 	"MMMM DD, YYYY": "MMMM DD, YYYY",
 	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
-	"MMMM DD, YYYY hh:mm:ss A": "",
+	"MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A",
 	"Model '{{modelName}}' has been successfully downloaded.": "Modellen '{{modelName}}' er lastet ned.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Modellen '{{modelTag}}' er allerede i nedlastingskøen.",
 	"Model {{modelId}} not found": "Modellen {{modelId}} ble ikke funnet",
 	"Model {{modelName}} is not vision capable": "Modellen {{modelName}} er ikke visjonsdyktig",
 	"Model {{name}} is now {{status}}": "Modellen {{name}} er nå {{status}}",
-	"Model created successfully!": "",
+	"Model created successfully!": "Modellen ble opprettet!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Modellens filsystemsti oppdaget. Modellens kortnavn er påkrevd for oppdatering, kan ikke fortsette.",
 	"Model ID": "Modell-ID",
 	"Model not selected": "Modell ikke valgt",
 	"Model Params": "Modellparametere",
-	"Model updated successfully": "",
+	"Model updated successfully": "Modell oppdatert",
 	"Model Whitelisting": "Modell hvitlisting",
 	"Model(s) Whitelisted": "Modell(er) hvitlistet",
 	"Modelfile Content": "Modellfilinnhold",
@@ -404,39 +404,39 @@
 	"Name your model": "Gi modellen din et navn",
 	"New Chat": "Ny chat",
 	"New Password": "Nytt passord",
-	"No content to speak": "",
-	"No documents found": "",
-	"No file selected": "",
+	"No content to speak": "Mangler innhold for tale",
+	"No documents found": "Ingen dokumenter funnet",
+	"No file selected": "Ingen fil valgt",
 	"No results found": "Ingen resultater funnet",
 	"No search query generated": "Ingen søkeforespørsel generert",
 	"No source available": "Ingen kilde tilgjengelig",
-	"No valves to update": "",
+	"No valves to update": "Ingen ventiler å oppdatere",
 	"None": "Ingen",
-	"Not factually correct": "Ikke faktuelt korrekt",
+	"Not factually correct": "Uriktig informasjon",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Merk: Hvis du setter en minimums poengsum, vil søket kun returnere dokumenter med en poengsum som er større enn eller lik minimums poengsummen.",
 	"Notifications": "Varsler",
-	"November": "November",
+	"November": "november",
 	"num_thread (Ollama)": "num_thread (Ollama)",
-	"OAuth ID": "",
-	"October": "Oktober",
+	"OAuth ID": "OAuth-ID",
+	"October": "oktober",
 	"Off": "Av",
 	"Okay, Let's Go!": "Ok, la oss gå!",
 	"OLED Dark": "OLED mørk",
 	"Ollama": "Ollama",
 	"Ollama API": "Ollama API",
 	"Ollama API disabled": "Ollama API deaktivert",
-	"Ollama API is disabled": "",
+	"Ollama API is disabled": "Ollama API er deaktivert",
 	"Ollama Version": "Ollama versjon",
 	"On": "På",
 	"Only": "Kun",
 	"Only alphanumeric characters and hyphens are allowed in the command string.": "Kun alfanumeriske tegn og bindestreker er tillatt i kommandostrengen.",
 	"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oops! Hold deg fast! Filene dine er fortsatt i prosesseringsovnen. Vi tilbereder dem til perfeksjon. Vennligst vær tålmodig, vi gir beskjed når de er klare.",
 	"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Ser ut som URL-en er ugyldig. Vennligst dobbeltsjekk og prøv igjen.",
-	"Oops! There was an error in the previous response. Please try again or contact admin.": "",
+	"Oops! There was an error in the previous response. Please try again or contact admin.": "Oops! Det oppstod en feil i forrige svar. Prøv igjen eller kontakt administrator",
 	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! Du bruker en ikke-støttet metode (kun frontend). Vennligst server WebUI fra backend.",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Åpne ny chat",
-	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "Open WebUI-versjon (v{{OPEN_WEBUI_VERSION}}) er lavere enn nødvendig versjon (v{{REQUIRED_VERSION}})",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API-konfigurasjon",
@@ -448,20 +448,20 @@
 	"PDF document (.pdf)": "PDF-dokument (.pdf)",
 	"PDF Extract Images (OCR)": "PDF-ekstraktbilder (OCR)",
 	"pending": "avventer",
-	"Permission denied when accessing media devices": "",
-	"Permission denied when accessing microphone": "",
+	"Permission denied when accessing media devices": "Tillatelse nektet ved tilgang til medieenheter",
+	"Permission denied when accessing microphone": "Tillatelse nektet ved tilgang til mikrofon",
 	"Permission denied when accessing microphone: {{error}}": "Tillatelse nektet ved tilgang til mikrofon: {{error}}",
 	"Personalization": "Personalisering",
-	"Pin": "",
-	"Pinned": "",
-	"Pipeline deleted successfully": "",
-	"Pipeline downloaded successfully": "",
+	"Pin": "Fest",
+	"Pinned": "Festet",
+	"Pipeline deleted successfully": "Pipeline slettet",
+	"Pipeline downloaded successfully": "Pipeline lastet ned",
 	"Pipelines": "Pipelines",
-	"Pipelines Not Detected": "",
+	"Pipelines Not Detected": "Pipelines ikke oppdaget",
 	"Pipelines Valves": "Pipeline-ventiler",
 	"Plain text (.txt)": "Ren tekst (.txt)",
 	"Playground": "Lekeplass",
-	"Please carefully review the following warnings:": "",
+	"Please carefully review the following warnings:": "Vær vennlig å lese gjennom følgende advarsler grundig:",
 	"Positive attitude": "Positiv holdning",
 	"Previous 30 days": "Forrige 30 dager",
 	"Previous 7 days": "Forrige 7 dager",
@@ -478,7 +478,7 @@
 	"Read Aloud": "Les høyt",
 	"Record voice": "Ta opp stemme",
 	"Redirecting you to OpenWebUI Community": "Omdirigerer deg til OpenWebUI-fellesskapet",
-	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Omtal deg selv som \"Bruker\" (f.eks. \"Bruker lærer spansk\")",
 	"Refused when it shouldn't have": "Avvist når det ikke skulle ha vært det",
 	"Regenerate": "Regenerer",
 	"Release Notes": "Utgivelsesnotater",
@@ -490,21 +490,21 @@
 	"Reranking Model": "Reranking-modell",
 	"Reranking model disabled": "Reranking-modell deaktivert",
 	"Reranking model set to \"{{reranking_model}}\"": "Reranking-modell satt til \"{{reranking_model}}\"",
-	"Reset": "",
-	"Reset Upload Directory": "",
+	"Reset": "Tilbakestill",
+	"Reset Upload Directory": "Tilbakestill opplastingskatalog",
 	"Reset Vector Storage": "Tilbakestill vektorlagring",
 	"Response AutoCopy to Clipboard": "Respons auto-kopi til utklippstavle",
-	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "",
+	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "Respons-varsler kan ikke aktiveres da nettstedsrettighetene er nektet. Vennligst se nettleserinnstillingene dine for å gi nødvendig tilgang.",
 	"Role": "Rolle",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"RTL": "RTL",
-	"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
-	"Running": "",
+	"Run Llama 2, Code Llama, and other models. Customize and create your own.": "Kjør Llama 2, Code Llama og andre modeller. Tilpass og lag egne versjoner.",
+	"Running": "Kjører",
 	"Save": "Lagre",
 	"Save & Create": "Lagre og opprett",
 	"Save & Update": "Lagre og oppdater",
-	"Save Tag": "",
+	"Save Tag": "Lagre tag",
 	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Lagring av chatlogger direkte til nettleserens lagring støttes ikke lenger. Vennligst ta et øyeblikk for å laste ned og slette chatloggene dine ved å klikke på knappen nedenfor. Ikke bekymre deg, du kan enkelt re-importere chatloggene dine til backend via",
 	"Scan": "Skann",
 	"Scan complete!": "Skanning fullført!",
@@ -513,39 +513,39 @@
 	"Search a model": "Søk en modell",
 	"Search Chats": "Søk chatter",
 	"Search Documents": "Søk dokumenter",
-	"Search Functions": "",
+	"Search Functions": "Søk funksjoner",
 	"Search Models": "Søk modeller",
 	"Search Prompts": "Søk prompter",
-	"Search Query Generation Prompt": "",
-	"Search Query Generation Prompt Length Threshold": "",
+	"Search Query Generation Prompt": "Instruksjon for å lage søkeord",
+	"Search Query Generation Prompt Length Threshold": "Lengdegrense for prompt til generering av søkeforespørsel",
 	"Search Result Count": "Antall søkeresultater",
-	"Search Tools": "",
+	"Search Tools": "Søkeverktøy",
 	"Searched {{count}} sites_one": "Søkte på {{count}} side",
 	"Searched {{count}} sites_other": "Søkte på {{count}} sider",
-	"Searching \"{{searchQuery}}\"": "",
+	"Searching \"{{searchQuery}}\"": "Søker etter \"{{searchQuery}}\"",
 	"Searxng Query URL": "Searxng forespørsels-URL",
 	"See readme.md for instructions": "Se readme.md for instruksjoner",
 	"See what's new": "Se hva som er nytt",
 	"Seed": "Seed",
 	"Select a base model": "Velg en grunnmodell",
-	"Select a engine": "",
-	"Select a function": "",
+	"Select a engine": "Velg en motor",
+	"Select a function": "Velg en funksjon",
 	"Select a mode": "Velg en modus",
 	"Select a model": "Velg en modell",
 	"Select a pipeline": "Velg en pipeline",
 	"Select a pipeline url": "Velg en pipeline-URL",
-	"Select a tool": "",
+	"Select a tool": "Velg et verktøy",
 	"Select an Ollama instance": "Velg en Ollama-instans",
-	"Select Documents": "",
+	"Select Documents": "Velg dokumenter",
 	"Select model": "Velg modell",
-	"Select only one model to call": "",
+	"Select only one model to call": "Velg kun én modell å kalle",
 	"Selected model(s) do not support image inputs": "Valgte modell(er) støtter ikke bildeforslag",
 	"Send": "Send",
 	"Send a Message": "Send en melding",
 	"Send message": "Send melding",
-	"September": "September",
+	"September": "september",
 	"Serper API Key": "Serper API-nøkkel",
-	"Serply API Key": "",
+	"Serply API Key": "Serply API-nøkkel",
 	"Serpstack API Key": "Serpstack API-nøkkel",
 	"Server connection verified": "Servertilkobling bekreftet",
 	"Set as default": "Sett som standard",
@@ -565,9 +565,9 @@
 	"short-summary": "kort sammendrag",
 	"Show": "Vis",
 	"Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i ventende kontooverlay",
-	"Show Model": "",
+	"Show Model": "Vis modell",
 	"Show shortcuts": "Vis snarveier",
-	"Show your support!": "",
+	"Show your support!": "Vis din støtte!",
 	"Showcased creativity": "Vist frem kreativitet",
 	"Sign in": "Logg inn",
 	"Sign Out": "Logg ut",
@@ -577,20 +577,20 @@
 	"Speech recognition error: {{error}}": "Feil ved talegjenkjenning: {{error}}",
 	"Speech-to-Text Engine": "Tale-til-tekst-motor",
 	"Stop Sequence": "Stoppsekvens",
-	"STT Model": "",
+	"STT Model": "STT-modell",
 	"STT Settings": "STT-innstillinger",
 	"Submit": "Send inn",
 	"Subtitle (e.g. about the Roman Empire)": "Undertittel (f.eks. om Romerriket)",
 	"Success": "Suksess",
 	"Successfully updated.": "Oppdatert.",
 	"Suggested": "Foreslått",
-	"Support": "",
-	"Support this plugin:": "",
+	"Support": "Bidra",
+	"Support this plugin:": "Bidra til denne utvidelsen:",
 	"System": "System",
 	"System Prompt": "Systemprompt",
 	"Tags": "Tagger",
-	"Tap to interrupt": "",
-	"Tavily API Key": "",
+	"Tap to interrupt": "Berør for å avbryte",
+	"Tavily API Key": "Tavily API-nøkkel",
 	"Tell us more:": "Fortell oss mer:",
 	"Temperature": "Temperatur",
 	"Template": "Mal",
@@ -598,68 +598,68 @@
 	"Text-to-Speech Engine": "Tekst-til-tale-motor",
 	"Tfs Z": "Tfs Z",
 	"Thanks for your feedback!": "Takk for tilbakemeldingen!",
-	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "",
+	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Utviklerne bak denne utvidelsen er lidenskapelige frivillige fra fellesskapet. Hvis du finner denne utvidelsen nyttig, vennligst vurder å bidra til utviklingen.",
 	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Poengsummen skal være en verdi mellom 0,0 (0%) og 1,0 (100%).",
 	"Theme": "Tema",
-	"Thinking...": "",
-	"This action cannot be undone. Do you wish to continue?": "",
+	"Thinking...": "Tenker ...",
+	"This action cannot be undone. Do you wish to continue?": "Denne handlingen kan ikke angres. Ønsker du å fortsette?",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dette sikrer at dine verdifulle samtaler er trygt lagret i backend-databasen din. Takk!",
-	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dette er en eksperimentell funksjon, det er mulig den ikke fungerer som forventet og kan endres når som helst.",
 	"This setting does not sync across browsers or devices.": "Denne innstillingen synkroniseres ikke mellom nettlesere eller enheter.",
-	"This will delete": "",
+	"This will delete": "Dette vil slette",
 	"Thorough explanation": "Grundig forklaring",
-	"Tika": "",
-	"Tika Server URL required.": "",
+	"Tika": "Tika",
+	"Tika Server URL required.": "Tika Server-URL kreves.",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Oppdater flere variabelplasser etter hverandre ved å trykke på tab-tasten i chatinputen etter hver erstatning.",
 	"Title": "Tittel",
-	"Title (e.g. Tell me a fun fact)": "Tittel (f.eks. Fortell meg en morsom fakta)",
+	"Title (e.g. Tell me a fun fact)": "Tittel (f.eks. Fortell meg et morsomt faktum)",
 	"Title Auto-Generation": "Automatisk tittelgenerering",
 	"Title cannot be an empty string.": "Tittelen kan ikke være en tom streng.",
 	"Title Generation Prompt": "Tittelgenereringsprompt",
 	"to": "til",
 	"To access the available model names for downloading,": "For å få tilgang til tilgjengelige modelnavn for nedlasting,",
 	"To access the GGUF models available for downloading,": "For å få tilgang til GGUF-modellene som er tilgjengelige for nedlasting,",
-	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
-	"To add documents here, upload them to the \"Documents\" workspace first.": "",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "For å få tilgang til WebUI, vennligst kontakt administratoren. Administratorer kan administrere brukerstatus fra Admin-panelet.",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "For å legge til dokumenter her, last dem opp til \"Dokumenter\"-arbeidsområdet først.",
 	"to chat input.": "til chatinput.",
-	"To select actions here, add them to the \"Functions\" workspace first.": "",
-	"To select filters here, add them to the \"Functions\" workspace first.": "",
-	"To select toolkits here, add them to the \"Tools\" workspace first.": "",
+	"To select actions here, add them to the \"Functions\" workspace first.": "For å velge handlinger her, legg dem til i \"Funksjoner\"-arbeidsområdet først.",
+	"To select filters here, add them to the \"Functions\" workspace first.": "For å velge filtre her, legg dem til i \"Funksjoner\"-arbeidsområdet først.",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "For å velge verktøysett her, legg dem til i \"Verktøy\"-arbeidsområdet først.",
 	"Today": "I dag",
 	"Toggle settings": "Veksle innstillinger",
 	"Toggle sidebar": "Veksle sidefelt",
-	"Tokens To Keep On Context Refresh (num_keep)": "",
-	"Tool created successfully": "",
-	"Tool deleted successfully": "",
-	"Tool imported successfully": "",
-	"Tool updated successfully": "",
-	"Toolkit Description (e.g. A toolkit for performing various operations)": "",
-	"Toolkit ID (e.g. my_toolkit)": "",
-	"Toolkit Name (e.g. My ToolKit)": "",
-	"Tools": "",
-	"Tools are a function calling system with arbitrary code execution": "",
-	"Tools have a function calling system that allows arbitrary code execution": "",
-	"Tools have a function calling system that allows arbitrary code execution.": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "Tokens å beholde ved kontekstoppdatering (num_keep)",
+	"Tool created successfully": "Verktøy opprettet",
+	"Tool deleted successfully": "Verktøy slettet",
+	"Tool imported successfully": "Verktøy importert",
+	"Tool updated successfully": "Verktøy oppdatert",
+	"Toolkit Description (e.g. A toolkit for performing various operations)": "Verktøysettbeskrivelse (f.eks. Et verktøysett for å utføre ulike operasjoner)",
+	"Toolkit ID (e.g. my_toolkit)": "Verktøysett-ID (f.eks. my_toolkit)",
+	"Toolkit Name (e.g. My ToolKit)": "Verktøysett-navn (f.eks. Mitt verktøysett)",
+	"Tools": "Verktøy",
+	"Tools are a function calling system with arbitrary code execution": "Vertkøy er et funksjonskallssystem med vilkårlig kodeeksekvering",
+	"Tools have a function calling system that allows arbitrary code execution": "Verktøy har et funksjonskallssystem som tillater vilkårlig kodeeksekvering",
+	"Tools have a function calling system that allows arbitrary code execution.": "Verktøy har et funksjonskallssystem som tillater vilkårlig kodeeksekvering.",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemer med tilgang til Ollama?",
-	"TTS Model": "",
+	"TTS Model": "TTS-modell",
 	"TTS Settings": "TTS-innstillinger",
-	"TTS Voice": "",
+	"TTS Voice": "TTS-stemme",
 	"Type": "Type",
 	"Type Hugging Face Resolve (Download) URL": "Skriv inn Hugging Face Resolve (nedlasting) URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Oops! Det oppsto et problem med tilkoblingen til {{provider}}.",
-	"UI": "",
-	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
-	"Unpin": "",
-	"Update": "",
+	"UI": "UI",
+	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Ukjent filtype '{{file_type}}'. Fortsetter likevel med filopplastingen.",
+	"Unpin": "Løsne",
+	"Update": "Oppdater",
 	"Update and Copy Link": "Oppdater og kopier lenke",
 	"Update password": "Oppdater passord",
-	"Updated at": "",
-	"Upload": "",
+	"Updated at": "Oppdatert",
+	"Upload": "Last opp",
 	"Upload a GGUF model": "Last opp en GGUF-modell",
 	"Upload Files": "Last opp filer",
-	"Upload Pipeline": "",
+	"Upload Pipeline": "Last opp pipeline",
 	"Upload Progress": "Opplastingsfremdrift",
 	"URL Mode": "URL-modus",
 	"Use '#' in the prompt input to load and select your documents.": "Bruk '#' i prompt-input for å laste og velge dokumentene dine.",
@@ -668,23 +668,23 @@
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "bruker",
-	"User location successfully retrieved.": "",
+	"User location successfully retrieved.": "Brukerlokasjon hentet",
 	"User Permissions": "Brukertillatelser",
 	"Users": "Brukere",
 	"Utilize": "Utnytt",
 	"Valid time units:": "Gyldige tidsenheter:",
-	"Valves": "",
-	"Valves updated": "",
-	"Valves updated successfully": "",
+	"Valves": "Ventiler",
+	"Valves updated": "Ventiler oppdatert",
+	"Valves updated successfully": "Ventiler oppdatert",
 	"variable": "variabel",
 	"variable to have them replaced with clipboard content.": "variabel for å få dem erstattet med utklippstavleinnhold.",
 	"Version": "Versjon",
-	"Voice": "",
+	"Voice": "Stemme",
 	"Warning": "Advarsel",
-	"Warning:": "",
+	"Warning:": "Advarsel:",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Advarsel: Hvis du oppdaterer eller endrer embedding-modellen din, må du re-importere alle dokumenter.",
 	"Web": "Web",
-	"Web API": "",
+	"Web API": "Web-API",
 	"Web Loader Settings": "Web-lasterinnstillinger",
 	"Web Params": "Web-parametere",
 	"Web Search": "Websøk",
@@ -694,21 +694,21 @@
 	"WebUI will make requests to": "WebUI vil gjøre forespørsler til",
 	"What’s New in": "Hva er nytt i",
 	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Når historikken er slått av, vil nye chatter på denne nettleseren ikke vises i historikken din på noen av enhetene dine.",
-	"Whisper (Local)": "",
-	"Widescreen Mode": "",
+	"Whisper (Local)": "Whisper (Lokal)",
+	"Widescreen Mode": "Bredskjermmodus",
 	"Workspace": "Arbeidsområde",
 	"Write a prompt suggestion (e.g. Who are you?)": "Skriv et promptforslag (f.eks. Hvem er du?)",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Skriv et sammendrag på 50 ord som oppsummerer [emne eller nøkkelord].",
 	"Yesterday": "I går",
 	"You": "Du",
-	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Du kan tilpasse interaksjonene dine med språkmodeller ved å legge til minner gjennom 'Administrer'-knappen nedenfor, slik at de blir mer hjelpsomme og tilpasset deg.",
 	"You cannot clone a base model": "Du kan ikke klone en grunnmodell",
 	"You have no archived conversations.": "Du har ingen arkiverte samtaler.",
 	"You have shared this chat": "Du har delt denne chatten",
 	"You're a helpful assistant.": "Du er en hjelpsom assistent.",
 	"You're now logged in.": "Du er nå logget inn.",
-	"Your account status is currently pending activation.": "",
-	"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.": "",
+	"Your account status is currently pending activation.": "Din konto venter for øyeblikket på aktivering.",
+	"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.": "Hele beløpet du gir går uavkortet til utvikleren av tillegget; Open WebUI tar ikke noe av dette. Den valgte finansieringsplattformen kan derimot ha egne gebyrer.",
 	"Youtube": "Youtube",
-	"Youtube Loader Settings": "Youtube-lasterinnstillinger"
+	"Youtube Loader Settings": "Innstillinger for YouTube-laster"
 }

+ 1 - 1
src/lib/i18n/locales/nl-NL/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Beheer Modellen",
 	"Manage Ollama Models": "Beheer Ollama Modellen",
 	"Manage Pipelines": "Pijplijnen beheren",
-	"Manage Valves": "",
 	"March": "Maart",
 	"Max Tokens (num_predict)": "Max Tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maximaal 3 modellen kunnen tegelijkertijd worden gedownload. Probeer het later opnieuw.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Berichten die u verzendt nadat u uw link hebt gemaakt, worden niet gedeeld. Gebruikers met de URL kunnen de gedeelde chat bekijken.",
+	"Min P": "",
 	"Minimum Score": "Minimale Score",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/pa-IN/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "ਮਾਡਲਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ",
 	"Manage Ollama Models": "ਓਲਾਮਾ ਮਾਡਲਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ",
 	"Manage Pipelines": "ਪਾਈਪਲਾਈਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ",
-	"Manage Valves": "",
 	"March": "ਮਾਰਚ",
 	"Max Tokens (num_predict)": "ਮੈਕਸ ਟੋਕਨ (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "ਇੱਕ ਸਮੇਂ ਵਿੱਚ ਵੱਧ ਤੋਂ ਵੱਧ 3 ਮਾਡਲ ਡਾਊਨਲੋਡ ਕੀਤੇ ਜਾ ਸਕਦੇ ਹਨ। ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ਤੁਹਾਡਾ ਲਿੰਕ ਬਣਾਉਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡੇ ਵੱਲੋਂ ਭੇਜੇ ਗਏ ਸੁਨੇਹੇ ਸਾਂਝੇ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ। URL ਵਾਲੇ ਉਪਭੋਗਤਾ ਸਾਂਝੀ ਚੈਟ ਨੂੰ ਵੇਖ ਸਕਣਗੇ।",
+	"Min P": "",
 	"Minimum Score": "ਘੱਟੋ-ਘੱਟ ਸਕੋਰ",
 	"Mirostat": "ਮਿਰੋਸਟੈਟ",
 	"Mirostat Eta": "ਮਿਰੋਸਟੈਟ ਈਟਾ",

+ 1 - 1
src/lib/i18n/locales/pl-PL/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Zarządzaj modelami",
 	"Manage Ollama Models": "Zarządzaj modelami Ollama",
 	"Manage Pipelines": "Zarządzanie potokami",
-	"Manage Valves": "",
 	"March": "Marzec",
 	"Max Tokens (num_predict)": "Maksymalna liczba żetonów (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maksymalnie 3 modele można pobierać jednocześnie. Spróbuj ponownie później.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Wiadomości wysyłane po utworzeniu linku nie będą udostępniane. Użytkownicy z adresem URL będą mogli wyświetlić udostępniony czat.",
+	"Min P": "",
 	"Minimum Score": "Minimalny wynik",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 698 - 698
src/lib/i18n/locales/pt-BR/translation.json

@@ -1,715 +1,715 @@
 {
 	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' ou '-1' para sem expiração.",
-    "(Beta)": "(Beta)",
-    "(e.g. `sh webui.sh --api --api-auth username_password`)": "(por exemplo, `sh webui.sh --api --api-auth username_password`)",
-    "(e.g. `sh webui.sh --api`)": "(por exemplo, `sh webui.sh --api`)",
-    "(latest)": "(último)",
-    "{{ models }}": "{{ models }}",
-    "{{ owner }}: You cannot delete a base model": "{{ owner }}: Você não pode deletar um modelo base",
-    "{{modelName}} is thinking...": "{{modelName}} está pensando...",
-    "{{user}}'s Chats": "Chats de {{user}}",
-    "{{webUIName}} Backend Required": "Backend {{webUIName}} necessário",
-    "A task model is used when performing tasks such as generating titles for chats and web search queries": "Um modelo de tarefa é usado ao realizar tarefas como gerar títulos para chats e consultas de pesquisa na web",
-    "a user": "um usuário",
-    "About": "Sobre",
-    "Account": "Conta",
-    "Account Activation Pending": "Ativação da Conta Pendente",
-    "Accurate information": "Informação precisa",
-    "Actions": "",
-    "Active Users": "Usuários Ativos",
-    "Add": "Adicionar",
-    "Add a model id": "Adicionar um ID de modelo",
-    "Add a short description about what this model does": "Adicione uma descrição curta sobre o que este modelo faz",
-    "Add a short title for this prompt": "Adicione um título curto para este prompt",
-    "Add a tag": "Adicionar uma tag",
-    "Add custom prompt": "Adicionar prompt personalizado",
-    "Add Docs": "Adicionar Documentos",
-    "Add Files": "Adicionar Arquivos",
-    "Add Memory": "Adicionar Memória",
-    "Add message": "Adicionar mensagem",
-    "Add Model": "Adicionar Modelo",
-    "Add Tag": "Adicionar Tag",
-    "Add Tags": "Adicionar Tags",
-    "Add User": "Adicionar Usuário",
-    "Adjusting these settings will apply changes universally to all users.": "Ajustar essas configurações aplicará mudanças universalmente a todos os usuários.",
-    "admin": "admin",
-    "Admin": "Admin",
-    "Admin Panel": "Painel do Admin",
-    "Admin Settings": "Configurações do Admin",
-    "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Os admins têm acesso a todas as ferramentas o tempo todo; os usuários precisam de ferramentas atribuídas por modelo no workspace.",
-    "Advanced Parameters": "Parâmetros Avançados",
-    "Advanced Params": "Parâmetros Avançados",
-    "all": "todos",
-    "All Documents": "Todos os Documentos",
-    "All Users": "Todos os Usuários",
-    "Allow": "Permitir",
-    "Allow Chat Deletion": "Permitir Exclusão de Chats",
-    "Allow non-local voices": "Permitir vozes não locais",
-    "Allow User Location": "Permitir Localização do Usuário",
-    "Allow Voice Interruption in Call": "Permitir Interrupção de Voz na Chamada",
-    "alphanumeric characters and hyphens": "caracteres alfanuméricos e hífens",
-    "Already have an account?": "Já tem uma conta?",
-    "an assistant": "um assistente",
+	"(Beta)": "(Beta)",
+	"(e.g. `sh webui.sh --api --api-auth username_password`)": "(por exemplo, `sh webui.sh --api --api-auth username_password`)",
+	"(e.g. `sh webui.sh --api`)": "(por exemplo, `sh webui.sh --api`)",
+	"(latest)": "(último)",
+	"{{ models }}": "{{ models }}",
+	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Você não pode deletar um modelo base",
+	"{{modelName}} is thinking...": "{{modelName}} está pensando...",
+	"{{user}}'s Chats": "Chats de {{user}}",
+	"{{webUIName}} Backend Required": "Backend {{webUIName}} necessário",
+	"A task model is used when performing tasks such as generating titles for chats and web search queries": "Um modelo de tarefa é usado ao realizar tarefas como gerar títulos para chats e consultas de pesquisa na web",
+	"a user": "um usuário",
+	"About": "Sobre",
+	"Account": "Conta",
+	"Account Activation Pending": "Ativação da Conta Pendente",
+	"Accurate information": "Informação precisa",
+	"Actions": "",
+	"Active Users": "Usuários Ativos",
+	"Add": "Adicionar",
+	"Add a model id": "Adicionar um ID de modelo",
+	"Add a short description about what this model does": "Adicione uma descrição curta sobre o que este modelo faz",
+	"Add a short title for this prompt": "Adicione um título curto para este prompt",
+	"Add a tag": "Adicionar uma tag",
+	"Add custom prompt": "Adicionar prompt personalizado",
+	"Add Docs": "Adicionar Documentos",
+	"Add Files": "Adicionar Arquivos",
+	"Add Memory": "Adicionar Memória",
+	"Add message": "Adicionar mensagem",
+	"Add Model": "Adicionar Modelo",
+	"Add Tag": "Adicionar Tag",
+	"Add Tags": "Adicionar Tags",
+	"Add User": "Adicionar Usuário",
+	"Adjusting these settings will apply changes universally to all users.": "Ajustar essas configurações aplicará mudanças universalmente a todos os usuários.",
+	"admin": "admin",
+	"Admin": "Admin",
+	"Admin Panel": "Painel do Admin",
+	"Admin Settings": "Configurações do Admin",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Os admins têm acesso a todas as ferramentas o tempo todo; os usuários precisam de ferramentas atribuídas por modelo no workspace.",
+	"Advanced Parameters": "Parâmetros Avançados",
+	"Advanced Params": "Parâmetros Avançados",
+	"all": "todos",
+	"All Documents": "Todos os Documentos",
+	"All Users": "Todos os Usuários",
+	"Allow": "Permitir",
+	"Allow Chat Deletion": "Permitir Exclusão de Chats",
+	"Allow non-local voices": "Permitir vozes não locais",
+	"Allow User Location": "Permitir Localização do Usuário",
+	"Allow Voice Interruption in Call": "Permitir Interrupção de Voz na Chamada",
+	"alphanumeric characters and hyphens": "caracteres alfanuméricos e hífens",
+	"Already have an account?": "Já tem uma conta?",
+	"an assistant": "um assistente",
 	"and": "e",
-    "and create a new shared link.": "e criar um novo link compartilhado.",
-    "API Base URL": "URL Base da API",
-    "API Key": "Chave API",
-    "API Key created.": "Chave API criada.",
-    "API keys": "Chaves API",
-    "April": "Abril",
-    "Archive": "Arquivar",
-    "Archive All Chats": "Arquivar Todos os Chats",
-    "Archived Chats": "Chats Arquivados",
-    "are allowed - Activate this command by typing": "são permitidos - Ative este comando digitando",
-    "Are you sure?": "Você tem certeza?",
-    "Attach file": "Anexar arquivo",
-    "Attention to detail": "Atenção aos detalhes",
-    "Audio": "Áudio",
-    "Audio settings updated successfully": "Configurações de áudio atualizadas com sucesso",
-    "August": "Agosto",
-    "Auto-playback response": "Resposta de reprodução automática",
-    "AUTOMATIC1111 Api Auth String": "String de Autenticação da API AUTOMATIC1111",
-    "AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111",
-    "AUTOMATIC1111 Base URL is required.": "URL Base AUTOMATIC1111 é necessária.",
-    "available!": "disponível!",
-    "Back": "Voltar",
-    "Bad Response": "Resposta Ruim",
-    "Banners": "Banners",
-    "Base Model (From)": "Modelo Base (From)",
-    "Batch Size (num_batch)": "Tamanho do Lote (num_batch)",
-    "before": "antes",
-    "Being lazy": "Sendo preguiçoso",
-    "Brave Search API Key": "Chave API do Brave Search",
-    "Bypass SSL verification for Websites": "Ignorar verificação SSL para Sites",
-    "Call": "Chamada",
-    "Call feature is not supported when using Web STT engine": "O recurso de chamada não é suportado ao usar o mecanismo Web STT",
-    "Camera": "Câmera",
-    "Cancel": "Cancelar",
-    "Capabilities": "Capacidades",
-    "Change Password": "Mudar Senha",
-    "Chat": "Chat",
-    "Chat Background Image": "Imagem de Fundo do Chat",
-    "Chat Bubble UI": "Interface de Bolha de Chat",
-    "Chat Controls": "Controles de Chat",
-    "Chat direction": "Direção do Chat",
-    "Chat History": "Histórico de Chat",
-    "Chat History is off for this browser.": "O Histórico de Chat está desativado para este navegador.",
-    "Chats": "Chats",
-    "Check Again": "Verificar Novamente",
-    "Check for updates": "Verificar atualizações",
-    "Checking for updates...": "Verificando atualizações...",
-    "Choose a model before saving...": "Escolha um modelo antes de salvar...",
-    "Chunk Overlap": "Sobreposição de Chunk",
+	"and create a new shared link.": "e criar um novo link compartilhado.",
+	"API Base URL": "URL Base da API",
+	"API Key": "Chave API",
+	"API Key created.": "Chave API criada.",
+	"API keys": "Chaves API",
+	"April": "Abril",
+	"Archive": "Arquivar",
+	"Archive All Chats": "Arquivar Todos os Chats",
+	"Archived Chats": "Chats Arquivados",
+	"are allowed - Activate this command by typing": "são permitidos - Ative este comando digitando",
+	"Are you sure?": "Você tem certeza?",
+	"Attach file": "Anexar arquivo",
+	"Attention to detail": "Atenção aos detalhes",
+	"Audio": "Áudio",
+	"Audio settings updated successfully": "Configurações de áudio atualizadas com sucesso",
+	"August": "Agosto",
+	"Auto-playback response": "Resposta de reprodução automática",
+	"AUTOMATIC1111 Api Auth String": "String de Autenticação da API AUTOMATIC1111",
+	"AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111",
+	"AUTOMATIC1111 Base URL is required.": "URL Base AUTOMATIC1111 é necessária.",
+	"available!": "disponível!",
+	"Back": "Voltar",
+	"Bad Response": "Resposta Ruim",
+	"Banners": "Banners",
+	"Base Model (From)": "Modelo Base (From)",
+	"Batch Size (num_batch)": "Tamanho do Lote (num_batch)",
+	"before": "antes",
+	"Being lazy": "Sendo preguiçoso",
+	"Brave Search API Key": "Chave API do Brave Search",
+	"Bypass SSL verification for Websites": "Ignorar verificação SSL para Sites",
+	"Call": "Chamada",
+	"Call feature is not supported when using Web STT engine": "O recurso de chamada não é suportado ao usar o mecanismo Web STT",
+	"Camera": "Câmera",
+	"Cancel": "Cancelar",
+	"Capabilities": "Capacidades",
+	"Change Password": "Mudar Senha",
+	"Chat": "Chat",
+	"Chat Background Image": "Imagem de Fundo do Chat",
+	"Chat Bubble UI": "Interface de Bolha de Chat",
+	"Chat Controls": "Controles de Chat",
+	"Chat direction": "Direção do Chat",
+	"Chat History": "Histórico de Chat",
+	"Chat History is off for this browser.": "O Histórico de Chat está desativado para este navegador.",
+	"Chats": "Chats",
+	"Check Again": "Verificar Novamente",
+	"Check for updates": "Verificar atualizações",
+	"Checking for updates...": "Verificando atualizações...",
+	"Choose a model before saving...": "Escolha um modelo antes de salvar...",
+	"Chunk Overlap": "Sobreposição de Chunk",
 	"Chunk Params": "Parâmetros de Chunk",
-    "Chunk Size": "Tamanho do Chunk",
-    "Citation": "Citação",
-    "Clear memory": "Limpar memória",
-    "Click here for help.": "Clique aqui para obter ajuda.",
-    "Click here to": "Clique aqui para",
-    "Click here to download user import template file.": "Clique aqui para baixar o arquivo de modelo de importação de usuários.",
-    "Click here to select": "Clique aqui para enviar",
-    "Click here to select a csv file.": "Clique aqui para enviar um arquivo csv.",
-    "Click here to select a py file.": "Clique aqui para enviar um arquivo py.",
-    "Click here to select documents.": "Clique aqui para enviar documentos.",
-    "click here.": "clique aqui.",
-    "Click on the user role button to change a user's role.": "Clique no botão de função do usuário para alterar a função de um usuário.",
-    "Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permissão de escrita na área de transferência negada. Verifique as configurações do seu navegador para conceder o acesso necessário.",
-    "Clone": "Clonar",
-    "Close": "Fechar",
-    "Code formatted successfully": "Código formatado com sucesso",
-    "Collection": "Coleção",
-    "ComfyUI": "ComfyUI",
-    "ComfyUI Base URL": "URL Base do ComfyUI",
-    "ComfyUI Base URL is required.": "URL Base do ComfyUI é necessária.",
-    "Command": "Comando",
-    "Concurrent Requests": "Solicitações Concomitantes",
-    "Confirm": "Confirmar",
-    "Confirm Password": "Confirmar Senha",
-    "Confirm your action": "Confirme sua ação",
-    "Connections": "Conexões",
-    "Contact Admin for WebUI Access": "Contate o Admin para Acesso ao WebUI",
-    "Content": "Conteúdo",
-    "Content Extraction": "Extração de Conteúdo",
-    "Context Length": "Context Length",
-    "Continue Response": "Continuar Resposta",
-    "Continue with {{provider}}": "Continuar com {{provider}}",
-    "Controls": "Controles",
-    "Copied shared chat URL to clipboard!": "URL de chat compartilhado copiado para a área de transferência!",
-    "Copy": "Copiar",
-    "Copy last code block": "Copiar último bloco de código",
-    "Copy last response": "Copiar última resposta",
-    "Copy Link": "Copiar Link",
-    "Copying to clipboard was successful!": "Cópia para a área de transferência bem-sucedida!",
-    "Create a model": "Criar um modelo",
-    "Create Account": "Criar Conta",
-    "Create new key": "Criar nova chave",
-    "Create new secret key": "Criar nova chave secreta",
-    "Created at": "Criado em",
-    "Created At": "Criado Em",
-    "Created by": "Criado por",
-    "CSV Import": "Importação CSV",
-    "Current Model": "Modelo Atual",
-    "Current Password": "Senha Atual",
+	"Chunk Size": "Tamanho do Chunk",
+	"Citation": "Citação",
+	"Clear memory": "Limpar memória",
+	"Click here for help.": "Clique aqui para obter ajuda.",
+	"Click here to": "Clique aqui para",
+	"Click here to download user import template file.": "Clique aqui para baixar o arquivo de modelo de importação de usuários.",
+	"Click here to select": "Clique aqui para enviar",
+	"Click here to select a csv file.": "Clique aqui para enviar um arquivo csv.",
+	"Click here to select a py file.": "Clique aqui para enviar um arquivo py.",
+	"Click here to select documents.": "Clique aqui para enviar documentos.",
+	"click here.": "clique aqui.",
+	"Click on the user role button to change a user's role.": "Clique no botão de função do usuário para alterar a função de um usuário.",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permissão de escrita na área de transferência negada. Verifique as configurações do seu navegador para conceder o acesso necessário.",
+	"Clone": "Clonar",
+	"Close": "Fechar",
+	"Code formatted successfully": "Código formatado com sucesso",
+	"Collection": "Coleção",
+	"ComfyUI": "ComfyUI",
+	"ComfyUI Base URL": "URL Base do ComfyUI",
+	"ComfyUI Base URL is required.": "URL Base do ComfyUI é necessária.",
+	"Command": "Comando",
+	"Concurrent Requests": "Solicitações Concomitantes",
+	"Confirm": "Confirmar",
+	"Confirm Password": "Confirmar Senha",
+	"Confirm your action": "Confirme sua ação",
+	"Connections": "Conexões",
+	"Contact Admin for WebUI Access": "Contate o Admin para Acesso ao WebUI",
+	"Content": "Conteúdo",
+	"Content Extraction": "Extração de Conteúdo",
+	"Context Length": "Context Length",
+	"Continue Response": "Continuar Resposta",
+	"Continue with {{provider}}": "Continuar com {{provider}}",
+	"Controls": "Controles",
+	"Copied shared chat URL to clipboard!": "URL de chat compartilhado copiado para a área de transferência!",
+	"Copy": "Copiar",
+	"Copy last code block": "Copiar último bloco de código",
+	"Copy last response": "Copiar última resposta",
+	"Copy Link": "Copiar Link",
+	"Copying to clipboard was successful!": "Cópia para a área de transferência bem-sucedida!",
+	"Create a model": "Criar um modelo",
+	"Create Account": "Criar Conta",
+	"Create new key": "Criar nova chave",
+	"Create new secret key": "Criar nova chave secreta",
+	"Created at": "Criado em",
+	"Created At": "Criado Em",
+	"Created by": "Criado por",
+	"CSV Import": "Importação CSV",
+	"Current Model": "Modelo Atual",
+	"Current Password": "Senha Atual",
 	"Custom": "Personalizado",
-    "Customize models for a specific purpose": "Personalize modelos para um propósito específico",
-    "Dark": "Escuro",
-    "Dashboard": "Dashboard",
-    "Database": "Banco de Dados",
-    "December": "Dezembro",
-    "Default": "Padrão",
-    "Default (Automatic1111)": "Padrão (Automatic1111)",
-    "Default (SentenceTransformers)": "Padrão (SentenceTransformers)",
-    "Default Model": "Modelo Padrão",
-    "Default model updated": "Modelo padrão atualizado",
-    "Default Prompt Suggestions": "Sugestões de Prompt Padrão",
-    "Default User Role": "Função de Usuário Padrão",
-    "delete": "deletar",
-    "Delete": "Deletar",
-    "Delete a model": "Deletar um modelo",
-    "Delete All Chats": "Deletar Todos os Chats",
-    "Delete chat": "Deletar chat",
-    "Delete Chat": "Deletar Chat",
-    "Delete chat?": "Deletar chat?",
-    "Delete Doc": "Deletar Documento",
-    "Delete function?": "Deletar função?",
-    "Delete prompt?": "Deletar prompt?",
-    "delete this link": "deletar este link",
-    "Delete tool?": "Deletar ferramenta?",
-    "Delete User": "Deletar Usuário",
-    "Deleted {{deleteModelTag}}": "Deletado {{deleteModelTag}}",
-    "Deleted {{name}}": "Deletado {{name}}",
-    "Description": "Descrição",
-    "Didn't fully follow instructions": "Não seguiu completamente as instruções",
-    "Disabled": "Desativado",
-    "Discover a function": "Descubra uma função",
-    "Discover a model": "Descubra um modelo",
-    "Discover a prompt": "Descubra um prompt",
-    "Discover a tool": "Descubra uma ferramenta",
-    "Discover, download, and explore custom functions": "Descubra, baixe e explore funções personalizadas",
-    "Discover, download, and explore custom prompts": "Descubra, baixe e explore prompts personalizados",
-    "Discover, download, and explore custom tools": "Descubra, baixe e explore ferramentas personalizadas",
-    "Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelos",
-    "Dismissible": "Descartável",
-    "Display Emoji in Call": "Exibir Emoji na Chamada",
-    "Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Chat",
-    "Do not install functions from sources you do not fully trust.": "Não instale funções de fontes que você não confia totalmente.",
-    "Do not install tools from sources you do not fully trust.": "Não instale ferramentas de fontes que você não confia totalmente.",
-    "Document": "Documento",
-    "Document Settings": "Configurações de Documento",
-    "Documentation": "Documentação",
-    "Documents": "Documentos",
-    "does not make any external connections, and your data stays securely on your locally hosted server.": "não faz nenhuma conexão externa, e seus dados permanecem seguros no seu servidor local.",
-    "Don't Allow": "Não Permitir",
-    "Don't have an account?": "Não tem uma conta?",
+	"Customize models for a specific purpose": "Personalize modelos para um propósito específico",
+	"Dark": "Escuro",
+	"Dashboard": "Dashboard",
+	"Database": "Banco de Dados",
+	"December": "Dezembro",
+	"Default": "Padrão",
+	"Default (Automatic1111)": "Padrão (Automatic1111)",
+	"Default (SentenceTransformers)": "Padrão (SentenceTransformers)",
+	"Default Model": "Modelo Padrão",
+	"Default model updated": "Modelo padrão atualizado",
+	"Default Prompt Suggestions": "Sugestões de Prompt Padrão",
+	"Default User Role": "Função de Usuário Padrão",
+	"delete": "deletar",
+	"Delete": "Deletar",
+	"Delete a model": "Deletar um modelo",
+	"Delete All Chats": "Deletar Todos os Chats",
+	"Delete chat": "Deletar chat",
+	"Delete Chat": "Deletar Chat",
+	"Delete chat?": "Deletar chat?",
+	"Delete Doc": "Deletar Documento",
+	"Delete function?": "Deletar função?",
+	"Delete prompt?": "Deletar prompt?",
+	"delete this link": "deletar este link",
+	"Delete tool?": "Deletar ferramenta?",
+	"Delete User": "Deletar Usuário",
+	"Deleted {{deleteModelTag}}": "Deletado {{deleteModelTag}}",
+	"Deleted {{name}}": "Deletado {{name}}",
+	"Description": "Descrição",
+	"Didn't fully follow instructions": "Não seguiu completamente as instruções",
+	"Disabled": "Desativado",
+	"Discover a function": "Descubra uma função",
+	"Discover a model": "Descubra um modelo",
+	"Discover a prompt": "Descubra um prompt",
+	"Discover a tool": "Descubra uma ferramenta",
+	"Discover, download, and explore custom functions": "Descubra, baixe e explore funções personalizadas",
+	"Discover, download, and explore custom prompts": "Descubra, baixe e explore prompts personalizados",
+	"Discover, download, and explore custom tools": "Descubra, baixe e explore ferramentas personalizadas",
+	"Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelos",
+	"Dismissible": "Descartável",
+	"Display Emoji in Call": "Exibir Emoji na Chamada",
+	"Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Chat",
+	"Do not install functions from sources you do not fully trust.": "Não instale funções de fontes que você não confia totalmente.",
+	"Do not install tools from sources you do not fully trust.": "Não instale ferramentas de fontes que você não confia totalmente.",
+	"Document": "Documento",
+	"Document Settings": "Configurações de Documento",
+	"Documentation": "Documentação",
+	"Documents": "Documentos",
+	"does not make any external connections, and your data stays securely on your locally hosted server.": "não faz nenhuma conexão externa, e seus dados permanecem seguros no seu servidor local.",
+	"Don't Allow": "Não Permitir",
+	"Don't have an account?": "Não tem uma conta?",
 	"don't install random functions from sources you don't trust.": "não instale funções aleatórias de fontes que você não confia.",
-    "don't install random tools from sources you don't trust.": "não instale ferramentas aleatórias de fontes que você não confia.",
-    "Don't like the style": "Não gosta do estilo",
-    "Done": "Concluído",
-    "Download": "Baixar",
-    "Download canceled": "Download cancelado",
-    "Download Database": "Baixar Banco de Dados",
-    "Drop any files here to add to the conversation": "Solte qualquer arquivo aqui para adicionar à conversa",
-    "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "por exemplo, '30s', '10m'. Unidades de tempo válidas são 's', 'm', 'h'.",
-    "Edit": "Editar",
-    "Edit Doc": "Editar Documento",
-    "Edit Memory": "Editar Memória",
-    "Edit User": "Editar Usuário",
-    "ElevenLabs": "",
-    "Email": "Email",
-    "Embedding Batch Size": "Tamanho do Lote de Embedding",
-    "Embedding Model": "Modelo de Embedding",
-    "Embedding Model Engine": "Motor do Modelo de Embedding",
-    "Embedding model set to \"{{embedding_model}}\"": "Modelo de embedding definido para \"{{embedding_model}}\"",
-    "Enable Chat History": "Ativar Histórico de Chat",
-    "Enable Community Sharing": "Ativar Compartilhamento Comunitário",
-    "Enable New Sign Ups": "Ativar Novos Cadastros",
-    "Enable Web Search": "Ativar Pesquisa na Web",
-    "Enabled": "Ativado",
-    "Engine": "Motor",
-    "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Certifique-se de que seu arquivo CSV inclua 4 colunas nesta ordem: Nome, Email, Senha, Função.",
-    "Enter {{role}} message here": "Digite a mensagem de {{role}} aqui",
-    "Enter a detail about yourself for your LLMs to recall": "Digite um detalhe sobre você para seus LLMs lembrarem",
-    "Enter api auth string (e.g. username:password)": "Digite a string de autenticação da API (por exemplo, username:password)",
-    "Enter Brave Search API Key": "Digite a Chave API do Brave Search",
-    "Enter Chunk Overlap": "Digite a Sobreposição de Chunk",
-    "Enter Chunk Size": "Digite o Tamanho do Chunk",
-    "Enter Github Raw URL": "Digite a URL bruta do Github",
-    "Enter Google PSE API Key": "Digite a Chave API do Google PSE",
-    "Enter Google PSE Engine Id": "Digite o ID do Motor do Google PSE",
-    "Enter Image Size (e.g. 512x512)": "Digite o Tamanho da Imagem (por exemplo, 512x512)",
-    "Enter language codes": "Digite os códigos de idioma",
-    "Enter model tag (e.g. {{modelTag}})": "Digite a tag do modelo (por exemplo, {{modelTag}})",
-    "Enter Number of Steps (e.g. 50)": "Digite o Número de Passos (por exemplo, 50)",
-    "Enter Score": "Digite a Pontuação",
-    "Enter Searxng Query URL": "Digite a URL de Consulta do Searxng",
-    "Enter Serper API Key": "Digite a Chave API do Serper",
-    "Enter Serply API Key": "Digite a Chave API do Serply",
-    "Enter Serpstack API Key": "Digite a Chave API do Serpstack",
-    "Enter stop sequence": "Digite a sequência de parada",
-    "Enter system prompt": "Digite o prompt do sistema",
-    "Enter Tavily API Key": "Digite a Chave API do Tavily",
-    "Enter Tika Server URL": "Digite a URL do Servidor Tika",
-    "Enter Top K": "Digite o Top K",
-    "Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)",
-    "Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)",
+	"don't install random tools from sources you don't trust.": "não instale ferramentas aleatórias de fontes que você não confia.",
+	"Don't like the style": "Não gosta do estilo",
+	"Done": "Concluído",
+	"Download": "Baixar",
+	"Download canceled": "Download cancelado",
+	"Download Database": "Baixar Banco de Dados",
+	"Drop any files here to add to the conversation": "Solte qualquer arquivo aqui para adicionar à conversa",
+	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "por exemplo, '30s', '10m'. Unidades de tempo válidas são 's', 'm', 'h'.",
+	"Edit": "Editar",
+	"Edit Doc": "Editar Documento",
+	"Edit Memory": "Editar Memória",
+	"Edit User": "Editar Usuário",
+	"ElevenLabs": "",
+	"Email": "Email",
+	"Embedding Batch Size": "Tamanho do Lote de Embedding",
+	"Embedding Model": "Modelo de Embedding",
+	"Embedding Model Engine": "Motor do Modelo de Embedding",
+	"Embedding model set to \"{{embedding_model}}\"": "Modelo de embedding definido para \"{{embedding_model}}\"",
+	"Enable Chat History": "Ativar Histórico de Chat",
+	"Enable Community Sharing": "Ativar Compartilhamento Comunitário",
+	"Enable New Sign Ups": "Ativar Novos Cadastros",
+	"Enable Web Search": "Ativar Pesquisa na Web",
+	"Enabled": "Ativado",
+	"Engine": "Motor",
+	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Certifique-se de que seu arquivo CSV inclua 4 colunas nesta ordem: Nome, Email, Senha, Função.",
+	"Enter {{role}} message here": "Digite a mensagem de {{role}} aqui",
+	"Enter a detail about yourself for your LLMs to recall": "Digite um detalhe sobre você para seus LLMs lembrarem",
+	"Enter api auth string (e.g. username:password)": "Digite a string de autenticação da API (por exemplo, username:password)",
+	"Enter Brave Search API Key": "Digite a Chave API do Brave Search",
+	"Enter Chunk Overlap": "Digite a Sobreposição de Chunk",
+	"Enter Chunk Size": "Digite o Tamanho do Chunk",
+	"Enter Github Raw URL": "Digite a URL bruta do Github",
+	"Enter Google PSE API Key": "Digite a Chave API do Google PSE",
+	"Enter Google PSE Engine Id": "Digite o ID do Motor do Google PSE",
+	"Enter Image Size (e.g. 512x512)": "Digite o Tamanho da Imagem (por exemplo, 512x512)",
+	"Enter language codes": "Digite os códigos de idioma",
+	"Enter model tag (e.g. {{modelTag}})": "Digite a tag do modelo (por exemplo, {{modelTag}})",
+	"Enter Number of Steps (e.g. 50)": "Digite o Número de Passos (por exemplo, 50)",
+	"Enter Score": "Digite a Pontuação",
+	"Enter Searxng Query URL": "Digite a URL de Consulta do Searxng",
+	"Enter Serper API Key": "Digite a Chave API do Serper",
+	"Enter Serply API Key": "Digite a Chave API do Serply",
+	"Enter Serpstack API Key": "Digite a Chave API do Serpstack",
+	"Enter stop sequence": "Digite a sequência de parada",
+	"Enter system prompt": "Digite o prompt do sistema",
+	"Enter Tavily API Key": "Digite a Chave API do Tavily",
+	"Enter Tika Server URL": "Digite a URL do Servidor Tika",
+	"Enter Top K": "Digite o Top K",
+	"Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)",
+	"Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)",
 	"Enter Your Email": "Digite Seu Email",
-    "Enter Your Full Name": "Digite Seu Nome Completo",
-    "Enter your message": "Digite sua mensagem",
-    "Enter Your Password": "Digite Sua Senha",
-    "Enter Your Role": "Digite Sua Função",
-    "Error": "Erro",
-    "Experimental": "Experimental",
-    "Export": "Exportar",
-    "Export All Chats (All Users)": "Exportar Todos os Chats (Todos os Usuários)",
-    "Export chat (.json)": "Exportar chat (.json)",
-    "Export Chats": "Exportar Chats",
-    "Export Documents Mapping": "Exportar Mapeamento de Documentos",
-    "Export Functions": "Exportar Funções",
-    "Export LiteLLM config.yaml": "Exportar config.yaml do LiteLLM",
-    "Export Models": "Exportar Modelos",
-    "Export Prompts": "Exportar Prompts",
-    "Export Tools": "Exportar Ferramentas",
-    "External Models": "Modelos Externos",
-    "Failed to create API Key.": "Falha ao criar a Chave API.",
-    "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência",
-    "Failed to update settings": "Falha ao atualizar as configurações",
-    "February": "Fevereiro",
-    "Feel free to add specific details": "Sinta-se à vontade para adicionar detalhes específicos",
-    "File": "Arquivo",
-    "File Mode": "Modo de Arquivo",
-    "File not found.": "Arquivo não encontrado.",
-    "Files": "Arquivos",
-    "Filter is now globally disabled": "O filtro está agora desativado globalmente",
-    "Filter is now globally enabled": "O filtro está agora ativado globalmente",
-    "Filters": "Filtros",
-    "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Falsificação de impressão digital detectada: Não foi possível usar as iniciais como avatar. Usando a imagem de perfil padrão.",
-    "Fluidly stream large external response chunks": "Transmitir fluentemente grandes blocos de respostas externas",
-    "Focus chat input": "Focar entrada de chat",
-    "Followed instructions perfectly": "Seguiu as instruções perfeitamente",
-    "Form": "Formulário",
-    "Format your variables using square brackets like this:": "Formate suas variáveis usando colchetes assim:",
-    "Frequency Penalty": "Frequency Penalty",
-    "Function created successfully": "Função criada com sucesso",
-    "Function deleted successfully": "Função deletada com sucesso",
-    "Function Description (e.g. A filter to remove profanity from text)": "Descrição da Função (por exemplo, Um filtro para remover palavrões do texto)",
-    "Function ID (e.g. my_filter)": "ID da Função (por exemplo, my_filter)",
-    "Function is now globally disabled": "A função está agora desativada globalmente",
-    "Function is now globally enabled": "A função está agora ativada globalmente",
-    "Function Name (e.g. My Filter)": "Nome da Função (por exemplo, My Filter)",
-    "Function updated successfully": "Função atualizada com sucesso",
-    "Functions": "Funções",
-    "Functions allow arbitrary code execution": "Funções permitem a execução arbitrária de código",
-    "Functions allow arbitrary code execution.": "Funções permitem a execução arbitrária de código.",
-    "Functions imported successfully": "Funções importadas com sucesso",
-    "General": "Geral",
+	"Enter Your Full Name": "Digite Seu Nome Completo",
+	"Enter your message": "Digite sua mensagem",
+	"Enter Your Password": "Digite Sua Senha",
+	"Enter Your Role": "Digite Sua Função",
+	"Error": "Erro",
+	"Experimental": "Experimental",
+	"Export": "Exportar",
+	"Export All Chats (All Users)": "Exportar Todos os Chats (Todos os Usuários)",
+	"Export chat (.json)": "Exportar chat (.json)",
+	"Export Chats": "Exportar Chats",
+	"Export Documents Mapping": "Exportar Mapeamento de Documentos",
+	"Export Functions": "Exportar Funções",
+	"Export LiteLLM config.yaml": "Exportar config.yaml do LiteLLM",
+	"Export Models": "Exportar Modelos",
+	"Export Prompts": "Exportar Prompts",
+	"Export Tools": "Exportar Ferramentas",
+	"External Models": "Modelos Externos",
+	"Failed to create API Key.": "Falha ao criar a Chave API.",
+	"Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência",
+	"Failed to update settings": "Falha ao atualizar as configurações",
+	"February": "Fevereiro",
+	"Feel free to add specific details": "Sinta-se à vontade para adicionar detalhes específicos",
+	"File": "Arquivo",
+	"File Mode": "Modo de Arquivo",
+	"File not found.": "Arquivo não encontrado.",
+	"Files": "Arquivos",
+	"Filter is now globally disabled": "O filtro está agora desativado globalmente",
+	"Filter is now globally enabled": "O filtro está agora ativado globalmente",
+	"Filters": "Filtros",
+	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Falsificação de impressão digital detectada: Não foi possível usar as iniciais como avatar. Usando a imagem de perfil padrão.",
+	"Fluidly stream large external response chunks": "Transmitir fluentemente grandes blocos de respostas externas",
+	"Focus chat input": "Focar entrada de chat",
+	"Followed instructions perfectly": "Seguiu as instruções perfeitamente",
+	"Form": "Formulário",
+	"Format your variables using square brackets like this:": "Formate suas variáveis usando colchetes assim:",
+	"Frequency Penalty": "Frequency Penalty",
+	"Function created successfully": "Função criada com sucesso",
+	"Function deleted successfully": "Função deletada com sucesso",
+	"Function Description (e.g. A filter to remove profanity from text)": "Descrição da Função (por exemplo, Um filtro para remover palavrões do texto)",
+	"Function ID (e.g. my_filter)": "ID da Função (por exemplo, my_filter)",
+	"Function is now globally disabled": "A função está agora desativada globalmente",
+	"Function is now globally enabled": "A função está agora ativada globalmente",
+	"Function Name (e.g. My Filter)": "Nome da Função (por exemplo, My Filter)",
+	"Function updated successfully": "Função atualizada com sucesso",
+	"Functions": "Funções",
+	"Functions allow arbitrary code execution": "Funções permitem a execução arbitrária de código",
+	"Functions allow arbitrary code execution.": "Funções permitem a execução arbitrária de código.",
+	"Functions imported successfully": "Funções importadas com sucesso",
+	"General": "Geral",
 	"General Settings": "Configurações Gerais",
-    "Generate Image": "Gerar Imagem",
-    "Generating search query": "Gerando consulta de pesquisa",
-    "Generation Info": "Informações de Geração",
-    "Get up and running with": "Comece e esteja em funcionamento com",
-    "Global": "Global",
-    "Good Response": "Boa Resposta",
-    "Google PSE API Key": "Chave API do Google PSE",
-    "Google PSE Engine Id": "ID do Motor do Google PSE",
-    "h:mm a": "h:mm a",
-    "has no conversations.": "não tem conversas.",
-    "Hello, {{name}}": "Olá, {{name}}",
-    "Help": "Ajuda",
-    "Hide": "Ocultar",
-    "Hide Model": "Ocultar Modelo",
-    "How can I help you today?": "Como posso ajudar você hoje?",
-    "Hybrid Search": "Pesquisa Híbrida",
-    "I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Eu reconheço que li e entendi as implicações da minha ação. Estou ciente dos riscos associados à execução de código arbitrário e verifiquei a confiabilidade da fonte.",
-    "Image Generation (Experimental)": "Geração de Imagem (Experimental)",
-    "Image Generation Engine": "Motor de Geração de Imagem",
-    "Image Settings": "Configurações de Imagem",
-    "Images": "Imagens",
-    "Import Chats": "Importar Chats",
-    "Import Documents Mapping": "Importar Mapeamento de Documentos",
-    "Import Functions": "Importar Funções",
-    "Import Models": "Importar Modelos",
-    "Import Prompts": "Importar Prompts",
-    "Import Tools": "Importar Ferramentas",
-    "Include `--api-auth` flag when running stable-diffusion-webui": "Incluir a flag `--api-auth` ao executar stable-diffusion-webui",
-    "Include `--api` flag when running stable-diffusion-webui": "Incluir a flag `--api` ao executar stable-diffusion-webui",
-    "Info": "Informação",
-    "Input commands": "Comandos de entrada",
-    "Install from Github URL": "Instalar da URL do Github",
-    "Instant Auto-Send After Voice Transcription": "Envio Automático Instantâneo Após Transcrição de Voz",
-    "Interface": "Interface",
-    "Invalid Tag": "Tag Inválida",
-    "January": "Janeiro",
-    "join our Discord for help.": "junte-se ao nosso Discord para ajuda.",
-    "JSON": "JSON",
-    "JSON Preview": "Pré-visualização JSON",
-    "July": "Julho",
-    "June": "Junho",
-    "JWT Expiration": "Expiração do JWT",
-    "JWT Token": "Token JWT",
-    "Keep Alive": "Manter Vivo",
-    "Keyboard shortcuts": "Atalhos de Teclado",
-    "Knowledge": "Conhecimento",
-    "Language": "Idioma",
-    "large language models, locally.": "grandes modelos de linguagem, localmente.",
-    "Last Active": "Última Atividade",
-    "Last Modified": "Última Modificação",
+	"Generate Image": "Gerar Imagem",
+	"Generating search query": "Gerando consulta de pesquisa",
+	"Generation Info": "Informações de Geração",
+	"Get up and running with": "Comece e esteja em funcionamento com",
+	"Global": "Global",
+	"Good Response": "Boa Resposta",
+	"Google PSE API Key": "Chave API do Google PSE",
+	"Google PSE Engine Id": "ID do Motor do Google PSE",
+	"h:mm a": "h:mm a",
+	"has no conversations.": "não tem conversas.",
+	"Hello, {{name}}": "Olá, {{name}}",
+	"Help": "Ajuda",
+	"Hide": "Ocultar",
+	"Hide Model": "Ocultar Modelo",
+	"How can I help you today?": "Como posso ajudar você hoje?",
+	"Hybrid Search": "Pesquisa Híbrida",
+	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Eu reconheço que li e entendi as implicações da minha ação. Estou ciente dos riscos associados à execução de código arbitrário e verifiquei a confiabilidade da fonte.",
+	"Image Generation (Experimental)": "Geração de Imagem (Experimental)",
+	"Image Generation Engine": "Motor de Geração de Imagem",
+	"Image Settings": "Configurações de Imagem",
+	"Images": "Imagens",
+	"Import Chats": "Importar Chats",
+	"Import Documents Mapping": "Importar Mapeamento de Documentos",
+	"Import Functions": "Importar Funções",
+	"Import Models": "Importar Modelos",
+	"Import Prompts": "Importar Prompts",
+	"Import Tools": "Importar Ferramentas",
+	"Include `--api-auth` flag when running stable-diffusion-webui": "Incluir a flag `--api-auth` ao executar stable-diffusion-webui",
+	"Include `--api` flag when running stable-diffusion-webui": "Incluir a flag `--api` ao executar stable-diffusion-webui",
+	"Info": "Informação",
+	"Input commands": "Comandos de entrada",
+	"Install from Github URL": "Instalar da URL do Github",
+	"Instant Auto-Send After Voice Transcription": "Envio Automático Instantâneo Após Transcrição de Voz",
+	"Interface": "Interface",
+	"Invalid Tag": "Tag Inválida",
+	"January": "Janeiro",
+	"join our Discord for help.": "junte-se ao nosso Discord para ajuda.",
+	"JSON": "JSON",
+	"JSON Preview": "Pré-visualização JSON",
+	"July": "Julho",
+	"June": "Junho",
+	"JWT Expiration": "Expiração do JWT",
+	"JWT Token": "Token JWT",
+	"Keep Alive": "Manter Vivo",
+	"Keyboard shortcuts": "Atalhos de Teclado",
+	"Knowledge": "Conhecimento",
+	"Language": "Idioma",
+	"large language models, locally.": "grandes modelos de linguagem, localmente.",
+	"Last Active": "Última Atividade",
+	"Last Modified": "Última Modificação",
 	"Light": "Claro",
-    "Listening...": "Escutando...",
-    "LLMs can make mistakes. Verify important information.": "LLMs podem cometer erros. Verifique informações importantes.",
-    "Local Models": "Modelos Locais",
-    "LTR": "LTR",
-    "Made by OpenWebUI Community": "Feito pela Comunidade OpenWebUI",
-    "Make sure to enclose them with": "Certifique-se de encerrá-los com",
-    "Manage": "Gerenciar",
-    "Manage Models": "Gerenciar Modelos",
-    "Manage Ollama Models": "Gerenciar Modelos Ollama",
-    "Manage Pipelines": "Gerenciar Pipelines",
-    "Manage Valves": "Gerenciar Válvulas",
-    "March": "Março",
-    "Max Tokens (num_predict)": "Máximo de Tokens (num_predict)",
-    "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Máximo de 3 modelos podem ser baixados simultaneamente. Por favor, tente novamente mais tarde.",
-    "May": "Maio",
-    "Memories accessible by LLMs will be shown here.": "Memórias acessíveis por LLMs serão mostradas aqui.",
-    "Memory": "Memória",
-    "Memory added successfully": "Memória adicionada com sucesso",
-    "Memory cleared successfully": "Memória limpa com sucesso",
-    "Memory deleted successfully": "Memória excluída com sucesso",
-    "Memory updated successfully": "Memória atualizada com sucesso",
-    "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens enviadas após criar seu link não serão compartilhadas. Usuários com o URL poderão visualizar o chat compartilhado.",
-    "Minimum Score": "Pontuação Mínima",
-    "Mirostat": "Mirostat",
-    "Mirostat Eta": "Mirostat Eta",
-    "Mirostat Tau": "Mirostat Tau",
-    "MMMM DD, YYYY": "MMMM DD, YYYY",
-    "MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
-    "MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A",
-    "Model '{{modelName}}' has been successfully downloaded.": "Modelo '{{modelName}}' foi baixado com sucesso.",
-    "Model '{{modelTag}}' is already in queue for downloading.": "Modelo '{{modelTag}}' já está na fila para download.",
-    "Model {{modelId}} not found": "Modelo {{modelId}} não encontrado",
-    "Model {{modelName}} is not vision capable": "Modelo {{modelName}} não é capaz de visão",
-    "Model {{name}} is now {{status}}": "Modelo {{name}} está agora {{status}}",
-    "Model created successfully!": "Modelo criado com sucesso!",
-    "Model filesystem path detected. Model shortname is required for update, cannot continue.": "Caminho do sistema de arquivos do modelo detectado. Nome curto do modelo é necessário para atualização, não é possível continuar.",
-    "Model ID": "ID do Modelo",
-    "Model not selected": "Modelo não selecionado",
-    "Model Params": "Parâmetros do Modelo",
-    "Model updated successfully": "Modelo atualizado com sucesso",
-    "Model Whitelisting": "Lista Branca de Modelos",
-    "Model(s) Whitelisted": "Modelo(s) na Lista Branca",
-    "Modelfile Content": "Conteúdo do Arquivo do Modelo",
-    "Models": "Modelos",
-    "More": "Mais",
-    "Name": "Nome",
-    "Name Tag": "Nome da Tag",
-    "Name your model": "Nomeie seu modelo",
-    "New Chat": "Novo Chat",
+	"Listening...": "Escutando...",
+	"LLMs can make mistakes. Verify important information.": "LLMs podem cometer erros. Verifique informações importantes.",
+	"Local Models": "Modelos Locais",
+	"LTR": "LTR",
+	"Made by OpenWebUI Community": "Feito pela Comunidade OpenWebUI",
+	"Make sure to enclose them with": "Certifique-se de encerrá-los com",
+	"Manage": "Gerenciar",
+	"Manage Models": "Gerenciar Modelos",
+	"Manage Ollama Models": "Gerenciar Modelos Ollama",
+	"Manage Pipelines": "Gerenciar Pipelines",
+	"March": "Março",
+	"Max Tokens (num_predict)": "Máximo de Tokens (num_predict)",
+	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Máximo de 3 modelos podem ser baixados simultaneamente. Por favor, tente novamente mais tarde.",
+	"May": "Maio",
+	"Memories accessible by LLMs will be shown here.": "Memórias acessíveis por LLMs serão mostradas aqui.",
+	"Memory": "Memória",
+	"Memory added successfully": "Memória adicionada com sucesso",
+	"Memory cleared successfully": "Memória limpa com sucesso",
+	"Memory deleted successfully": "Memória excluída com sucesso",
+	"Memory updated successfully": "Memória atualizada com sucesso",
+	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens enviadas após criar seu link não serão compartilhadas. Usuários com o URL poderão visualizar o chat compartilhado.",
+	"Min P": "",
+	"Minimum Score": "Pontuação Mínima",
+	"Mirostat": "Mirostat",
+	"Mirostat Eta": "Mirostat Eta",
+	"Mirostat Tau": "Mirostat Tau",
+	"MMMM DD, YYYY": "MMMM DD, YYYY",
+	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
+	"MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A",
+	"Model '{{modelName}}' has been successfully downloaded.": "Modelo '{{modelName}}' foi baixado com sucesso.",
+	"Model '{{modelTag}}' is already in queue for downloading.": "Modelo '{{modelTag}}' já está na fila para download.",
+	"Model {{modelId}} not found": "Modelo {{modelId}} não encontrado",
+	"Model {{modelName}} is not vision capable": "Modelo {{modelName}} não é capaz de visão",
+	"Model {{name}} is now {{status}}": "Modelo {{name}} está agora {{status}}",
+	"Model created successfully!": "Modelo criado com sucesso!",
+	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Caminho do sistema de arquivos do modelo detectado. Nome curto do modelo é necessário para atualização, não é possível continuar.",
+	"Model ID": "ID do Modelo",
+	"Model not selected": "Modelo não selecionado",
+	"Model Params": "Parâmetros do Modelo",
+	"Model updated successfully": "Modelo atualizado com sucesso",
+	"Model Whitelisting": "Lista Branca de Modelos",
+	"Model(s) Whitelisted": "Modelo(s) na Lista Branca",
+	"Modelfile Content": "Conteúdo do Arquivo do Modelo",
+	"Models": "Modelos",
+	"More": "Mais",
+	"Name": "Nome",
+	"Name Tag": "Nome da Tag",
+	"Name your model": "Nomeie seu modelo",
+	"New Chat": "Novo Chat",
 	"New Password": "Nova Senha",
-    "No content to speak": "Sem conteúdo para falar",
-    "No documents found": "Nenhum documento encontrado",
-    "No file selected": "Nenhum arquivo selecionado",
-    "No results found": "Nenhum resultado encontrado",
-    "No search query generated": "Nenhuma consulta de pesquisa gerada",
-    "No source available": "Nenhuma fonte disponível",
-    "No valves to update": "Nenhuma válvula para atualizar",
-    "None": "Nenhum",
-    "Not factually correct": "Não está factualmente correto",
-    "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Se você definir uma pontuação mínima, a pesquisa retornará apenas documentos com pontuação igual ou superior à pontuação mínima.",
-    "Notifications": "Notificações",
-    "November": "Novembro",
-    "num_thread (Ollama)": "num_thread (Ollama)",
-    "OAuth ID": "OAuth ID",
-    "October": "Outubro",
-    "Off": "Desligado",
-    "Okay, Let's Go!": "Ok, Vamos Lá!",
-    "OLED Dark": "OLED Escuro",
-    "Ollama": "Ollama",
-    "Ollama API": "API Ollama",
-    "Ollama API disabled": "API Ollama desativada",
-    "Ollama API is disabled": "API Ollama está desativada",
-    "Ollama Version": "Versão Ollama",
-    "On": "Ligado",
-    "Only": "Apenas",
-    "Only alphanumeric characters and hyphens are allowed in the command string.": "Apenas caracteres alfanuméricos e hífens são permitidos na string de comando.",
-    "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ops! Aguarde! Seus arquivos ainda estão no forno de processamento. Estamos preparando-os com perfeição. Por favor, seja paciente e avisaremos quando estiverem prontos.",
-    "Oops! Looks like the URL is invalid. Please double-check and try again.": "Ops! Parece que a URL é inválida. Por favor, verifique novamente e tente de novo.",
-    "Oops! There was an error in the previous response. Please try again or contact admin.": "Ops! Houve um erro na resposta anterior. Por favor, tente novamente ou entre em contato com o administrador.",
-    "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Ops! Você está usando um método não suportado (somente frontend). Por favor, sirva a WebUI a partir do backend.",
-    "Open AI (Dall-E)": "Open AI (Dall-E)",
-    "Open new chat": "Abrir novo chat",
-    "Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "A versão do Open WebUI (v{{OPEN_WEBUI_VERSION}}) é inferior à versão necessária (v{{REQUIRED_VERSION}})",
-    "OpenAI": "OpenAI",
-    "OpenAI API": "API OpenAI",
-    "OpenAI API Config": "Configuração da API OpenAI",
-    "OpenAI API Key is required.": "Chave API OpenAI é necessária.",
-    "OpenAI URL/Key required.": "URL/Chave OpenAI necessária.",
-    "or": "ou",
-    "Other": "Outro",
-    "Password": "Senha",
-    "PDF document (.pdf)": "Documento PDF (.pdf)",
-    "PDF Extract Images (OCR)": "Extrair Imagens do PDF (OCR)",
-    "pending": "pendente",
-    "Permission denied when accessing media devices": "Permissão negada ao acessar dispositivos de mídia",
-    "Permission denied when accessing microphone": "Permissão negada ao acessar o microfone",
-    "Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}",
-    "Personalization": "Personalização",
-    "Pin": "Fixar",
+	"No content to speak": "Sem conteúdo para falar",
+	"No documents found": "Nenhum documento encontrado",
+	"No file selected": "Nenhum arquivo selecionado",
+	"No results found": "Nenhum resultado encontrado",
+	"No search query generated": "Nenhuma consulta de pesquisa gerada",
+	"No source available": "Nenhuma fonte disponível",
+	"No valves to update": "Nenhuma válvula para atualizar",
+	"None": "Nenhum",
+	"Not factually correct": "Não está factualmente correto",
+	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Se você definir uma pontuação mínima, a pesquisa retornará apenas documentos com pontuação igual ou superior à pontuação mínima.",
+	"Notifications": "Notificações",
+	"November": "Novembro",
+	"num_thread (Ollama)": "num_thread (Ollama)",
+	"OAuth ID": "OAuth ID",
+	"October": "Outubro",
+	"Off": "Desligado",
+	"Okay, Let's Go!": "Ok, Vamos Lá!",
+	"OLED Dark": "OLED Escuro",
+	"Ollama": "Ollama",
+	"Ollama API": "API Ollama",
+	"Ollama API disabled": "API Ollama desativada",
+	"Ollama API is disabled": "API Ollama está desativada",
+	"Ollama Version": "Versão Ollama",
+	"On": "Ligado",
+	"Only": "Apenas",
+	"Only alphanumeric characters and hyphens are allowed in the command string.": "Apenas caracteres alfanuméricos e hífens são permitidos na string de comando.",
+	"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ops! Aguarde! Seus arquivos ainda estão no forno de processamento. Estamos preparando-os com perfeição. Por favor, seja paciente e avisaremos quando estiverem prontos.",
+	"Oops! Looks like the URL is invalid. Please double-check and try again.": "Ops! Parece que a URL é inválida. Por favor, verifique novamente e tente de novo.",
+	"Oops! There was an error in the previous response. Please try again or contact admin.": "Ops! Houve um erro na resposta anterior. Por favor, tente novamente ou entre em contato com o administrador.",
+	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Ops! Você está usando um método não suportado (somente frontend). Por favor, sirva a WebUI a partir do backend.",
+	"Open AI (Dall-E)": "Open AI (Dall-E)",
+	"Open new chat": "Abrir novo chat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "A versão do Open WebUI (v{{OPEN_WEBUI_VERSION}}) é inferior à versão necessária (v{{REQUIRED_VERSION}})",
+	"OpenAI": "OpenAI",
+	"OpenAI API": "API OpenAI",
+	"OpenAI API Config": "Configuração da API OpenAI",
+	"OpenAI API Key is required.": "Chave API OpenAI é necessária.",
+	"OpenAI URL/Key required.": "URL/Chave OpenAI necessária.",
+	"or": "ou",
+	"Other": "Outro",
+	"Password": "Senha",
+	"PDF document (.pdf)": "Documento PDF (.pdf)",
+	"PDF Extract Images (OCR)": "Extrair Imagens do PDF (OCR)",
+	"pending": "pendente",
+	"Permission denied when accessing media devices": "Permissão negada ao acessar dispositivos de mídia",
+	"Permission denied when accessing microphone": "Permissão negada ao acessar o microfone",
+	"Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}",
+	"Personalization": "Personalização",
+	"Pin": "Fixar",
 	"Pinned": "Fixado",
-    "Pipeline deleted successfully": "Pipeline excluído com sucesso",
-    "Pipeline downloaded successfully": "Pipeline baixado com sucesso",
-    "Pipelines": "Pipelines",
-    "Pipelines Not Detected": "Pipelines Não Detectados",
-    "Pipelines Valves": "Válvulas de Pipelines",
-    "Plain text (.txt)": "Texto simples (.txt)",
-    "Playground": "Playground",
-    "Please carefully review the following warnings:": "Por favor, revise cuidadosamente os seguintes avisos:",
-    "Positive attitude": "Atitude positiva",
-    "Previous 30 days": "Últimos 30 dias",
-    "Previous 7 days": "Últimos 7 dias",
-    "Profile Image": "Imagem de Perfil",
-    "Prompt": "Prompt",
-    "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (por exemplo, Diga-me um fato divertido sobre o Império Romano)",
-    "Prompt Content": "Conteúdo do Prompt",
-    "Prompt suggestions": "Sugestões de Prompt",
-    "Prompts": "Prompts",
-    "Pull \"{{searchValue}}\" from Ollama.com": "Obter \"{{searchValue}}\" de Ollama.com",
-    "Pull a model from Ollama.com": "Obter um modelo de Ollama.com",
-    "Query Params": "Parâmetros de Consulta",
-    "RAG Template": "Modelo RAG",
-    "Read Aloud": "Ler em Voz Alta",
-    "Record voice": "Gravar voz",
-    "Redirecting you to OpenWebUI Community": "Redirecionando você para a Comunidade OpenWebUI",
-    "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refira-se como \"Usuário\" (por exemplo, \"Usuário está aprendendo espanhol\")",
-    "Refused when it shouldn't have": "Recusado quando não deveria",
-    "Regenerate": "Regenerar",
-    "Release Notes": "Notas de Lançamento",
-    "Remove": "Remover",
-    "Remove Model": "Remover Modelo",
-    "Rename": "Renomear",
-    "Repeat Last N": "Repetir Último N",
-    "Request Mode": "Modo de Solicitação",
-    "Reranking Model": "Modelo de Reclassificação",
-    "Reranking model disabled": "Modelo de Reclassificação desativado",
-    "Reranking model set to \"{{reranking_model}}\"": "Modelo de Reclassificação definido como \"{{reranking_model}}\"",
-    "Reset": "Redefinir",
-    "Reset Upload Directory": "Redefinir Diretório de Upload",
-    "Reset Vector Storage": "Redefinir Armazenamento de Vetores",
-    "Response AutoCopy to Clipboard": "Cópia Automática da Resposta para a Área de Transferência",
-    "Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "Notificações de resposta não podem ser ativadas pois as permissões do site foram negadas. Por favor, visite as configurações do seu navegador para conceder o acesso necessário.",
-    "Role": "Função",
-    "Rosé Pine": "Rosé Pine",
-    "Rosé Pine Dawn": "Rosé Pine Dawn",
-    "RTL": "RTL",
-    "Run Llama 2, Code Llama, and other models. Customize and create your own.": "Execute Llama 2, Code Llama e outros modelos. Personalize e crie os seus próprios.",
-    "Running": "Executando",
-    "Save": "Salvar",
+	"Pipeline deleted successfully": "Pipeline excluído com sucesso",
+	"Pipeline downloaded successfully": "Pipeline baixado com sucesso",
+	"Pipelines": "Pipelines",
+	"Pipelines Not Detected": "Pipelines Não Detectados",
+	"Pipelines Valves": "Válvulas de Pipelines",
+	"Plain text (.txt)": "Texto simples (.txt)",
+	"Playground": "Playground",
+	"Please carefully review the following warnings:": "Por favor, revise cuidadosamente os seguintes avisos:",
+	"Positive attitude": "Atitude positiva",
+	"Previous 30 days": "Últimos 30 dias",
+	"Previous 7 days": "Últimos 7 dias",
+	"Profile Image": "Imagem de Perfil",
+	"Prompt": "Prompt",
+	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (por exemplo, Diga-me um fato divertido sobre o Império Romano)",
+	"Prompt Content": "Conteúdo do Prompt",
+	"Prompt suggestions": "Sugestões de Prompt",
+	"Prompts": "Prompts",
+	"Pull \"{{searchValue}}\" from Ollama.com": "Obter \"{{searchValue}}\" de Ollama.com",
+	"Pull a model from Ollama.com": "Obter um modelo de Ollama.com",
+	"Query Params": "Parâmetros de Consulta",
+	"RAG Template": "Modelo RAG",
+	"Read Aloud": "Ler em Voz Alta",
+	"Record voice": "Gravar voz",
+	"Redirecting you to OpenWebUI Community": "Redirecionando você para a Comunidade OpenWebUI",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refira-se como \"Usuário\" (por exemplo, \"Usuário está aprendendo espanhol\")",
+	"Refused when it shouldn't have": "Recusado quando não deveria",
+	"Regenerate": "Regenerar",
+	"Release Notes": "Notas de Lançamento",
+	"Remove": "Remover",
+	"Remove Model": "Remover Modelo",
+	"Rename": "Renomear",
+	"Repeat Last N": "Repetir Último N",
+	"Request Mode": "Modo de Solicitação",
+	"Reranking Model": "Modelo de Reclassificação",
+	"Reranking model disabled": "Modelo de Reclassificação desativado",
+	"Reranking model set to \"{{reranking_model}}\"": "Modelo de Reclassificação definido como \"{{reranking_model}}\"",
+	"Reset": "Redefinir",
+	"Reset Upload Directory": "Redefinir Diretório de Upload",
+	"Reset Vector Storage": "Redefinir Armazenamento de Vetores",
+	"Response AutoCopy to Clipboard": "Cópia Automática da Resposta para a Área de Transferência",
+	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "Notificações de resposta não podem ser ativadas pois as permissões do site foram negadas. Por favor, visite as configurações do seu navegador para conceder o acesso necessário.",
+	"Role": "Função",
+	"Rosé Pine": "Rosé Pine",
+	"Rosé Pine Dawn": "Rosé Pine Dawn",
+	"RTL": "RTL",
+	"Run Llama 2, Code Llama, and other models. Customize and create your own.": "Execute Llama 2, Code Llama e outros modelos. Personalize e crie os seus próprios.",
+	"Running": "Executando",
+	"Save": "Salvar",
 	"Save & Create": "Salvar e Criar",
-    "Save & Update": "Salvar e Atualizar",
-    "Save Tag": "Salvar Tag",
-    "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvar registros de chat diretamente no armazenamento do seu navegador não é mais suportado. Por favor, reserve um momento para baixar e excluir seus registros de chat clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar seus registros de chat para o backend através de",
-    "Scan": "Escanear",
-    "Scan complete!": "Escaneamento concluído!",
-    "Scan for documents from {{path}}": "Escanear documentos de {{path}}",
-    "Search": "Pesquisar",
-    "Search a model": "Pesquisar um modelo",
-    "Search Chats": "Pesquisar Chats",
-    "Search Documents": "Pesquisar Documentos",
-    "Search Functions": "Pesquisar Funções",
-    "Search Models": "Pesquisar Modelos",
-    "Search Prompts": "Pesquisar Prompts",
-    "Search Query Generation Prompt": "Prompt de Geração de Consulta de Pesquisa",
-    "Search Query Generation Prompt Length Threshold": "Limiar de Comprimento do Prompt de Geração de Consulta de Pesquisa",
-    "Search Result Count": "Contagem de Resultados da Pesquisa",
-    "Search Tools": "Pesquisar Ferramentas",
-    "Searched {{count}} sites_one": "Pesquisou {{count}} sites_one",
-    "Searched {{count}} sites_many": "Pesquisou {{count}} sites_many",
-    "Searched {{count}} sites_other": "Pesquisou {{count}} sites_other",
-    "Searching \"{{searchQuery}}\"": "Pesquisando \"{{searchQuery}}\"",
-    "Searxng Query URL": "URL da Consulta Searxng",
-    "See readme.md for instructions": "Veja readme.md para instruções",
-    "See what's new": "Veja o que há de novo",
-    "Seed": "Seed",
-    "Select a base model": "Selecione um modelo base",
-    "Select a engine": "Selecione um motor",
-    "Select a function": "Selecione uma função",
-    "Select a mode": "Selecione um modo",
-    "Select a model": "Selecione um modelo",
-    "Select a pipeline": "Selecione um pipeline",
-    "Select a pipeline url": "Selecione uma URL de pipeline",
-    "Select a tool": "Selecione uma ferramenta",
-    "Select an Ollama instance": "Selecione uma instância Ollama",
-    "Select Documents": "Selecionar Documentos",
-    "Select model": "Selecionar modelo",
-    "Select only one model to call": "Selecione apenas um modelo para chamar",
-    "Selected model(s) do not support image inputs": "Modelo(s) selecionado(s) não suportam entradas de imagem",
-    "Send": "Enviar",
-    "Send a Message": "Enviar uma Mensagem",
-    "Send message": "Enviar mensagem",
-    "September": "Setembro",
-    "Serper API Key": "Chave da API Serper",
-    "Serply API Key": "Chave da API Serply",
-    "Serpstack API Key": "Chave da API Serpstack",
-    "Server connection verified": "Conexão com o servidor verificada",
-    "Set as default": "Definir como padrão",
-    "Set Default Model": "Definir Modelo Padrão",
-    "Set embedding model (e.g. {{model}})": "Definir modelo de embedding (por exemplo, {{model}})",
-    "Set Image Size": "Definir Tamanho da Imagem",
-    "Set reranking model (e.g. {{model}})": "Definir modelo de reclassificação (por exemplo, {{model}})",
-    "Set Steps": "Definir Etapas",
-    "Set Task Model": "Definir Modelo de Tarefa",
-    "Set Voice": "Definir Voz",
-    "Settings": "Configurações",
-    "Settings saved successfully!": "Configurações salvas com sucesso!",
-    "Settings updated successfully": "Configurações atualizadas com sucesso",
-    "Share": "Compartilhar",
-    "Share Chat": "Compartilhar Chat",
-    "Share to OpenWebUI Community": "Compartilhar com a Comunidade OpenWebUI",
-    "short-summary": "resumo-curto",
-    "Show": "Mostrar",
-    "Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na Sobreposição de Conta Pendentes",
-    "Show Model": "Mostrar Modelo",
-    "Show shortcuts": "Mostrar atalhos",
-    "Show your support!": "Mostre seu apoio!",
-    "Showcased creativity": "Criatividade exibida",
-    "Sign in": "Entrar",
-    "Sign Out": "Sair",
-    "Sign up": "Inscrever-se",
-    "Signing in": "Entrando",
-    "Source": "Fonte",
-    "Speech recognition error: {{error}}": "Erro de reconhecimento de fala: {{error}}",
-    "Speech-to-Text Engine": "Motor de Transcrição de Fala",
+	"Save & Update": "Salvar e Atualizar",
+	"Save Tag": "Salvar Tag",
+	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvar registros de chat diretamente no armazenamento do seu navegador não é mais suportado. Por favor, reserve um momento para baixar e excluir seus registros de chat clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar seus registros de chat para o backend através de",
+	"Scan": "Escanear",
+	"Scan complete!": "Escaneamento concluído!",
+	"Scan for documents from {{path}}": "Escanear documentos de {{path}}",
+	"Search": "Pesquisar",
+	"Search a model": "Pesquisar um modelo",
+	"Search Chats": "Pesquisar Chats",
+	"Search Documents": "Pesquisar Documentos",
+	"Search Functions": "Pesquisar Funções",
+	"Search Models": "Pesquisar Modelos",
+	"Search Prompts": "Pesquisar Prompts",
+	"Search Query Generation Prompt": "Prompt de Geração de Consulta de Pesquisa",
+	"Search Query Generation Prompt Length Threshold": "Limiar de Comprimento do Prompt de Geração de Consulta de Pesquisa",
+	"Search Result Count": "Contagem de Resultados da Pesquisa",
+	"Search Tools": "Pesquisar Ferramentas",
+	"Searched {{count}} sites_one": "Pesquisou {{count}} sites_one",
+	"Searched {{count}} sites_many": "Pesquisou {{count}} sites_many",
+	"Searched {{count}} sites_other": "Pesquisou {{count}} sites_other",
+	"Searching \"{{searchQuery}}\"": "Pesquisando \"{{searchQuery}}\"",
+	"Searxng Query URL": "URL da Consulta Searxng",
+	"See readme.md for instructions": "Veja readme.md para instruções",
+	"See what's new": "Veja o que há de novo",
+	"Seed": "Seed",
+	"Select a base model": "Selecione um modelo base",
+	"Select a engine": "Selecione um motor",
+	"Select a function": "Selecione uma função",
+	"Select a mode": "Selecione um modo",
+	"Select a model": "Selecione um modelo",
+	"Select a pipeline": "Selecione um pipeline",
+	"Select a pipeline url": "Selecione uma URL de pipeline",
+	"Select a tool": "Selecione uma ferramenta",
+	"Select an Ollama instance": "Selecione uma instância Ollama",
+	"Select Documents": "Selecionar Documentos",
+	"Select model": "Selecionar modelo",
+	"Select only one model to call": "Selecione apenas um modelo para chamar",
+	"Selected model(s) do not support image inputs": "Modelo(s) selecionado(s) não suportam entradas de imagem",
+	"Send": "Enviar",
+	"Send a Message": "Enviar uma Mensagem",
+	"Send message": "Enviar mensagem",
+	"September": "Setembro",
+	"Serper API Key": "Chave da API Serper",
+	"Serply API Key": "Chave da API Serply",
+	"Serpstack API Key": "Chave da API Serpstack",
+	"Server connection verified": "Conexão com o servidor verificada",
+	"Set as default": "Definir como padrão",
+	"Set Default Model": "Definir Modelo Padrão",
+	"Set embedding model (e.g. {{model}})": "Definir modelo de embedding (por exemplo, {{model}})",
+	"Set Image Size": "Definir Tamanho da Imagem",
+	"Set reranking model (e.g. {{model}})": "Definir modelo de reclassificação (por exemplo, {{model}})",
+	"Set Steps": "Definir Etapas",
+	"Set Task Model": "Definir Modelo de Tarefa",
+	"Set Voice": "Definir Voz",
+	"Settings": "Configurações",
+	"Settings saved successfully!": "Configurações salvas com sucesso!",
+	"Settings updated successfully": "Configurações atualizadas com sucesso",
+	"Share": "Compartilhar",
+	"Share Chat": "Compartilhar Chat",
+	"Share to OpenWebUI Community": "Compartilhar com a Comunidade OpenWebUI",
+	"short-summary": "resumo-curto",
+	"Show": "Mostrar",
+	"Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na Sobreposição de Conta Pendentes",
+	"Show Model": "Mostrar Modelo",
+	"Show shortcuts": "Mostrar atalhos",
+	"Show your support!": "Mostre seu apoio!",
+	"Showcased creativity": "Criatividade exibida",
+	"Sign in": "Entrar",
+	"Sign Out": "Sair",
+	"Sign up": "Inscrever-se",
+	"Signing in": "Entrando",
+	"Source": "Fonte",
+	"Speech recognition error: {{error}}": "Erro de reconhecimento de fala: {{error}}",
+	"Speech-to-Text Engine": "Motor de Transcrição de Fala",
 	"Stop Sequence": "Sequência de Parada",
-    "STT Model": "Modelo STT",
-    "STT Settings": "Configurações STT",
-    "Submit": "Enviar",
-    "Subtitle (e.g. about the Roman Empire)": "Legenda (por exemplo, sobre o Império Romano)",
-    "Success": "Sucesso",
-    "Successfully updated.": "Atualizado com sucesso.",
-    "Suggested": "Sugerido",
-    "Support": "Suporte",
-    "Support this plugin:": "Apoie este plugin:",
-    "System": "Sistema",
-    "System Prompt": "Prompt do Sistema",
-    "Tags": "Tags",
-    "Tap to interrupt": "Toque para interromper",
-    "Tavily API Key": "Chave da API Tavily",
-    "Tell us more:": "Conte-nos mais:",
-    "Temperature": "Temperatura",
-    "Template": "Modelo",
-    "Text Completion": "Conclusão de Texto",
-    "Text-to-Speech Engine": "Motor de Texto para Fala",
-    "Tfs Z": "Tfs Z",
-    "Thanks for your feedback!": "Obrigado pelo seu feedback!",
-    "The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Os desenvolvedores por trás deste plugin são voluntários apaixonados da comunidade. Se você achar este plugin útil, considere contribuir para o seu desenvolvimento.",
-    "The score should be a value between 0.0 (0%) and 1.0 (100%).": "A pontuação deve ser um valor entre 0.0 (0%) e 1.0 (100%).",
-    "Theme": "Tema",
-    "Thinking...": "Pensando...",
-    "This action cannot be undone. Do you wish to continue?": "Esta ação não pode ser desfeita. Você deseja continuar?",
+	"STT Model": "Modelo STT",
+	"STT Settings": "Configurações STT",
+	"Submit": "Enviar",
+	"Subtitle (e.g. about the Roman Empire)": "Legenda (por exemplo, sobre o Império Romano)",
+	"Success": "Sucesso",
+	"Successfully updated.": "Atualizado com sucesso.",
+	"Suggested": "Sugerido",
+	"Support": "Suporte",
+	"Support this plugin:": "Apoie este plugin:",
+	"System": "Sistema",
+	"System Prompt": "Prompt do Sistema",
+	"Tags": "Tags",
+	"Tap to interrupt": "Toque para interromper",
+	"Tavily API Key": "Chave da API Tavily",
+	"Tell us more:": "Conte-nos mais:",
+	"Temperature": "Temperatura",
+	"Template": "Modelo",
+	"Text Completion": "Conclusão de Texto",
+	"Text-to-Speech Engine": "Motor de Texto para Fala",
+	"Tfs Z": "Tfs Z",
+	"Thanks for your feedback!": "Obrigado pelo seu feedback!",
+	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Os desenvolvedores por trás deste plugin são voluntários apaixonados da comunidade. Se você achar este plugin útil, considere contribuir para o seu desenvolvimento.",
+	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "A pontuação deve ser um valor entre 0.0 (0%) e 1.0 (100%).",
+	"Theme": "Tema",
+	"Thinking...": "Pensando...",
+	"This action cannot be undone. Do you wish to continue?": "Esta ação não pode ser desfeita. Você deseja continuar?",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Isso garante que suas conversas valiosas sejam salvas com segurança no banco de dados do backend. Obrigado!",
-    "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Esta é uma funcionalidade experimental, pode não funcionar como esperado e está sujeita a alterações a qualquer momento.",
-    "This setting does not sync across browsers or devices.": "Esta configuração não sincroniza entre navegadores ou dispositivos.",
-    "This will delete": "Isso vai excluir",
-    "Thorough explanation": "Explicação detalhada",
-    "Tika": "Tika",
-    "Tika Server URL required.": "URL do servidor Tika necessária.",
-    "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada de chat após cada substituição.",
-    "Title": "Título",
-    "Title (e.g. Tell me a fun fact)": "Título (por exemplo, Conte-me um fato divertido)",
-    "Title Auto-Generation": "Geração Automática de Título",
-    "Title cannot be an empty string.": "O Título não pode ser uma string vazia.",
-    "Title Generation Prompt": "Prompt de Geração de Título",
-    "to": "para",
-    "To access the available model names for downloading,": "Para acessar os nomes de modelos disponíveis para download,",
-    "To access the GGUF models available for downloading,": "Para acessar os modelos GGUF disponíveis para download,",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Esta é uma funcionalidade experimental, pode não funcionar como esperado e está sujeita a alterações a qualquer momento.",
+	"This setting does not sync across browsers or devices.": "Esta configuração não sincroniza entre navegadores ou dispositivos.",
+	"This will delete": "Isso vai excluir",
+	"Thorough explanation": "Explicação detalhada",
+	"Tika": "Tika",
+	"Tika Server URL required.": "URL do servidor Tika necessária.",
+	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada de chat após cada substituição.",
+	"Title": "Título",
+	"Title (e.g. Tell me a fun fact)": "Título (por exemplo, Conte-me um fato divertido)",
+	"Title Auto-Generation": "Geração Automática de Título",
+	"Title cannot be an empty string.": "O Título não pode ser uma string vazia.",
+	"Title Generation Prompt": "Prompt de Geração de Título",
+	"to": "para",
+	"To access the available model names for downloading,": "Para acessar os nomes de modelos disponíveis para download,",
+	"To access the GGUF models available for downloading,": "Para acessar os modelos GGUF disponíveis para download,",
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Para acessar a WebUI, entre em contato com o administrador. Os administradores podem gerenciar os status dos usuários no Painel de Administração.",
-    "To add documents here, upload them to the \"Documents\" workspace first.": "Para adicionar documentos aqui, faça o upload para o espaço de trabalho \"Documentos\" primeiro.",
-    "to chat input.": "para entrada de chat.",
-    "To select actions here, add them to the \"Functions\" workspace first.": "Para selecionar ações aqui, adicione-os ao espaço de trabalho \"Ações\" primeiro.",
-    "To select filters here, add them to the \"Functions\" workspace first.": "Para selecionar filtros aqui, adicione-os ao espaço de trabalho \"Funções\" primeiro.",
-    "To select toolkits here, add them to the \"Tools\" workspace first.": "Para selecionar kits de ferramentas aqui, adicione-os ao espaço de trabalho \"Ferramentas\" primeiro.",
-    "Today": "Hoje",
-    "Toggle settings": "Alternar configurações",
-    "Toggle sidebar": "Alternar barra lateral",
-    "Tokens To Keep On Context Refresh (num_keep)": "Tokens a Manter na Atualização do Contexto (num_keep)",
-    "Tool created successfully": "Ferramenta criada com sucesso",
-    "Tool deleted successfully": "Ferramenta excluída com sucesso",
-    "Tool imported successfully": "Ferramenta importada com sucesso",
-    "Tool updated successfully": "Ferramenta atualizada com sucesso",
-    "Toolkit Description (e.g. A toolkit for performing various operations)": "Descrição do Kit de Ferramentas (por exemplo, Um kit de ferramentas para realizar várias operações)",
-    "Toolkit ID (e.g. my_toolkit)": "ID do Kit de Ferramentas (por exemplo, my_toolkit)",
-    "Toolkit Name (e.g. My ToolKit)": "Nome do Kit de Ferramentas (por exemplo, Meu Kit de Ferramentas)",
-    "Tools": "Ferramentas",
-    "Tools are a function calling system with arbitrary code execution": "Ferramentas são um sistema de chamada de funções com execução de código arbitrário",
-    "Tools have a function calling system that allows arbitrary code execution": "Ferramentas possuem um sistema de chamada de funções que permite a execução de código arbitrário",
-    "Tools have a function calling system that allows arbitrary code execution.": "Ferramentas possuem um sistema de chamada de funções que permite a execução de código arbitrário.",
-    "Top K": "Top K",
-    "Top P": "Top P",
-    "Trouble accessing Ollama?": "Problemas para acessar o Ollama?",
-    "TTS Model": "Modelo TTS",
-    "TTS Settings": "Configurações TTS",
-    "TTS Voice": "Voz TTS",
-    "Type": "Tipo",
-    "Type Hugging Face Resolve (Download) URL": "Digite o URL de download do Hugging Face",
-    "Uh-oh! There was an issue connecting to {{provider}}.": "Ops! Houve um problema ao conectar-se ao {{provider}}.",
-    "UI": "Interface",
-    "Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipo de arquivo desconhecido '{{file_type}}'. Prosseguindo com o upload do arquivo de qualquer maneira.",
-    "Unpin": "Desfixar",
-    "Update": "Atualizar",
-    "Update and Copy Link": "Atualizar e Copiar Link",
-    "Update password": "Atualizar senha",
-    "Updated at": "Atualizado em",
-    "Upload": "Fazer upload",
-    "Upload a GGUF model": "Fazer upload de um modelo GGUF",
-    "Upload Files": "Fazer upload de Arquivos",
-    "Upload Pipeline": "Fazer upload de Pipeline",
-    "Upload Progress": "Progresso do Upload",
-    "URL Mode": "Modo URL",
-    "Use '#' in the prompt input to load and select your documents.": "Use '#' na entrada de prompt para carregar e selecionar seus documentos.",
-    "Use Gravatar": "Usar Gravatar",
-    "Use Initials": "Usar Iniciais",
-    "use_mlock (Ollama)": "use_mlock (Ollama)",
-    "use_mmap (Ollama)": "use_mmap (Ollama)",
-    "user": "usuário",
-    "User location successfully retrieved.": "Localização do usuário recuperada com sucesso.",
-    "User Permissions": "Permissões do Usuário",
-    "Users": "Usuários",
-    "Utilize": "Utilizar",
-    "Valid time units:": "Unidades de tempo válidas:",
-    "Valves": "Válvulas",
-    "Valves updated": "Válvulas atualizadas",
-    "Valves updated successfully": "Válvulas atualizadas com sucesso",
-    "variable": "variável",
-    "variable to have them replaced with clipboard content.": "variável para ser substituída pelo conteúdo da área de transferência.",
-    "Version": "Versão",
-    "Voice": "Voz",
-    "Warning": "Aviso",
-    "Warning:": "Aviso:",
-    "Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar seu modelo de incorporação, será necessário reimportar todos os documentos.",
-    "Web": "Web",
-    "Web API": "API Web",
-    "Web Loader Settings": "Configurações do Carregador Web",
-    "Web Params": "Parâmetros Web",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "Para adicionar documentos aqui, faça o upload para o espaço de trabalho \"Documentos\" primeiro.",
+	"to chat input.": "para entrada de chat.",
+	"To select actions here, add them to the \"Functions\" workspace first.": "Para selecionar ações aqui, adicione-os ao espaço de trabalho \"Ações\" primeiro.",
+	"To select filters here, add them to the \"Functions\" workspace first.": "Para selecionar filtros aqui, adicione-os ao espaço de trabalho \"Funções\" primeiro.",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "Para selecionar kits de ferramentas aqui, adicione-os ao espaço de trabalho \"Ferramentas\" primeiro.",
+	"Today": "Hoje",
+	"Toggle settings": "Alternar configurações",
+	"Toggle sidebar": "Alternar barra lateral",
+	"Tokens To Keep On Context Refresh (num_keep)": "Tokens a Manter na Atualização do Contexto (num_keep)",
+	"Tool created successfully": "Ferramenta criada com sucesso",
+	"Tool deleted successfully": "Ferramenta excluída com sucesso",
+	"Tool imported successfully": "Ferramenta importada com sucesso",
+	"Tool updated successfully": "Ferramenta atualizada com sucesso",
+	"Toolkit Description (e.g. A toolkit for performing various operations)": "Descrição do Kit de Ferramentas (por exemplo, Um kit de ferramentas para realizar várias operações)",
+	"Toolkit ID (e.g. my_toolkit)": "ID do Kit de Ferramentas (por exemplo, my_toolkit)",
+	"Toolkit Name (e.g. My ToolKit)": "Nome do Kit de Ferramentas (por exemplo, Meu Kit de Ferramentas)",
+	"Tools": "Ferramentas",
+	"Tools are a function calling system with arbitrary code execution": "Ferramentas são um sistema de chamada de funções com execução de código arbitrário",
+	"Tools have a function calling system that allows arbitrary code execution": "Ferramentas possuem um sistema de chamada de funções que permite a execução de código arbitrário",
+	"Tools have a function calling system that allows arbitrary code execution.": "Ferramentas possuem um sistema de chamada de funções que permite a execução de código arbitrário.",
+	"Top K": "Top K",
+	"Top P": "Top P",
+	"Trouble accessing Ollama?": "Problemas para acessar o Ollama?",
+	"TTS Model": "Modelo TTS",
+	"TTS Settings": "Configurações TTS",
+	"TTS Voice": "Voz TTS",
+	"Type": "Tipo",
+	"Type Hugging Face Resolve (Download) URL": "Digite o URL de download do Hugging Face",
+	"Uh-oh! There was an issue connecting to {{provider}}.": "Ops! Houve um problema ao conectar-se ao {{provider}}.",
+	"UI": "Interface",
+	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipo de arquivo desconhecido '{{file_type}}'. Prosseguindo com o upload do arquivo de qualquer maneira.",
+	"Unpin": "Desfixar",
+	"Update": "Atualizar",
+	"Update and Copy Link": "Atualizar e Copiar Link",
+	"Update password": "Atualizar senha",
+	"Updated at": "Atualizado em",
+	"Upload": "Fazer upload",
+	"Upload a GGUF model": "Fazer upload de um modelo GGUF",
+	"Upload Files": "Fazer upload de Arquivos",
+	"Upload Pipeline": "Fazer upload de Pipeline",
+	"Upload Progress": "Progresso do Upload",
+	"URL Mode": "Modo URL",
+	"Use '#' in the prompt input to load and select your documents.": "Use '#' na entrada de prompt para carregar e selecionar seus documentos.",
+	"Use Gravatar": "Usar Gravatar",
+	"Use Initials": "Usar Iniciais",
+	"use_mlock (Ollama)": "use_mlock (Ollama)",
+	"use_mmap (Ollama)": "use_mmap (Ollama)",
+	"user": "usuário",
+	"User location successfully retrieved.": "Localização do usuário recuperada com sucesso.",
+	"User Permissions": "Permissões do Usuário",
+	"Users": "Usuários",
+	"Utilize": "Utilizar",
+	"Valid time units:": "Unidades de tempo válidas:",
+	"Valves": "Válvulas",
+	"Valves updated": "Válvulas atualizadas",
+	"Valves updated successfully": "Válvulas atualizadas com sucesso",
+	"variable": "variável",
+	"variable to have them replaced with clipboard content.": "variável para ser substituída pelo conteúdo da área de transferência.",
+	"Version": "Versão",
+	"Voice": "Voz",
+	"Warning": "Aviso",
+	"Warning:": "Aviso:",
+	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar seu modelo de incorporação, será necessário reimportar todos os documentos.",
+	"Web": "Web",
+	"Web API": "API Web",
+	"Web Loader Settings": "Configurações do Carregador Web",
+	"Web Params": "Parâmetros Web",
 	"Web Search": "Pesquisa na Web",
 	"Web Search Engine": "Mecanismo de Busca na Web",
-    "Webhook URL": "URL do Webhook",
-    "WebUI Settings": "Configurações da WebUI",
-    "WebUI will make requests to": "A WebUI fará solicitações para",
-    "What’s New in": "O que há de novo em",
-    "When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando o histórico está desativado, novos chats neste navegador não aparecerão no seu histórico em nenhum dos seus dispositivos.",
-    "Whisper (Local)": "Whisper (Local)",
-    "Widescreen Mode": "Modo Tela Cheia",
-    "Workspace": "Espaço de Trabalho",
-    "Write a prompt suggestion (e.g. Who are you?)": "Escreva uma sugestão de prompt (por exemplo, Quem é você?)",
-    "Write a summary in 50 words that summarizes [topic or keyword].": "Escreva um resumo em 50 palavras que resuma [tópico ou palavra-chave].",
-    "Yesterday": "Ontem",
-    "You": "Você",
-    "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Você pode personalizar suas interações com LLMs adicionando memórias através do botão 'Gerenciar' abaixo, tornando-as mais úteis e adaptadas a você.",
-    "You cannot clone a base model": "Você não pode clonar um modelo base",
-    "You have no archived conversations.": "Você não tem conversas arquivadas.",
-    "You have shared this chat": "Você compartilhou este chat",
-    "You're a helpful assistant.": "Você é um assistente útil.",
-    "You're now logged in.": "Você agora está logado.",
-    "Your account status is currently pending activation.": "O status da sua conta está atualmente aguardando ativação.",
-    "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.": "Toda a sua contribuição irá diretamente para o desenvolvedor do plugin; o Open WebUI não retém nenhuma porcentagem. No entanto, a plataforma de financiamento escolhida pode ter suas próprias taxas.",
-    "Youtube": "Youtube",
-    "Youtube Loader Settings": "Configurações do Carregador Youtube"
-}
+	"Webhook URL": "URL do Webhook",
+	"WebUI Settings": "Configurações da WebUI",
+	"WebUI will make requests to": "A WebUI fará solicitações para",
+	"What’s New in": "O que há de novo em",
+	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando o histórico está desativado, novos chats neste navegador não aparecerão no seu histórico em nenhum dos seus dispositivos.",
+	"Whisper (Local)": "Whisper (Local)",
+	"Widescreen Mode": "Modo Tela Cheia",
+	"Workspace": "Espaço de Trabalho",
+	"Write a prompt suggestion (e.g. Who are you?)": "Escreva uma sugestão de prompt (por exemplo, Quem é você?)",
+	"Write a summary in 50 words that summarizes [topic or keyword].": "Escreva um resumo em 50 palavras que resuma [tópico ou palavra-chave].",
+	"Yesterday": "Ontem",
+	"You": "Você",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Você pode personalizar suas interações com LLMs adicionando memórias através do botão 'Gerenciar' abaixo, tornando-as mais úteis e adaptadas a você.",
+	"You cannot clone a base model": "Você não pode clonar um modelo base",
+	"You have no archived conversations.": "Você não tem conversas arquivadas.",
+	"You have shared this chat": "Você compartilhou este chat",
+	"You're a helpful assistant.": "Você é um assistente útil.",
+	"You're now logged in.": "Você agora está logado.",
+	"Your account status is currently pending activation.": "O status da sua conta está atualmente aguardando ativação.",
+	"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.": "Toda a sua contribuição irá diretamente para o desenvolvedor do plugin; o Open WebUI não retém nenhuma porcentagem. No entanto, a plataforma de financiamento escolhida pode ter suas próprias taxas.",
+	"Youtube": "Youtube",
+	"Youtube Loader Settings": "Configurações do Carregador Youtube"
+}

+ 1 - 1
src/lib/i18n/locales/pt-PT/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Gerir Modelos",
 	"Manage Ollama Models": "Gerir Modelos Ollama",
 	"Manage Pipelines": "Gerir pipelines",
-	"Manage Valves": "",
 	"March": "Março",
 	"Max Tokens (num_predict)": "Máx Tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "O máximo de 3 modelos podem ser descarregados simultaneamente. Tente novamente mais tarde.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens que você enviar após criar o seu link não serão partilhadas. Os utilizadores com o URL poderão visualizar a conversa partilhada.",
+	"Min P": "",
 	"Minimum Score": "Mínimo de Pontuação",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 715 - 0
src/lib/i18n/locales/ro-RO/translation.json

@@ -0,0 +1,715 @@
+{
+	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' sau '-1' fără expirare.",
+	"(Beta)": "(Beta)",
+	"(e.g. `sh webui.sh --api --api-auth username_password`)": "(de ex. `sh webui.sh --api --api-auth username_password`)",
+	"(e.g. `sh webui.sh --api`)": "(de ex. `sh webui.sh --api`)",
+	"(latest)": "(ultimul)",
+	"{{ models }}": "{{ modele }}",
+	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Nu puteți șterge un model de bază",
+	"{{modelName}} is thinking...": "{{modelName}} gândește...",
+	"{{user}}'s Chats": "Conversațiile lui {{user}}",
+	"{{webUIName}} Backend Required": "Este necesar backend-ul {{webUIName}}",
+	"A task model is used when performing tasks such as generating titles for chats and web search queries": "Un model de sarcină este utilizat pentru realizarea unor sarcini precum generarea de titluri pentru conversații și interogări de căutare pe web",
+	"a user": "un utilizator",
+	"About": "Despre",
+	"Account": "Cont",
+	"Account Activation Pending": "Activarea contului în așteptare",
+	"Accurate information": "Informații precise",
+	"Actions": "Acțiuni",
+	"Active Users": "Utilizatori activi",
+	"Add": "Adaugă",
+	"Add a model id": "Adaugă un id de model",
+	"Add a short description about what this model does": "Adaugă o scurtă descriere despre ce face acest model",
+	"Add a short title for this prompt": "Adaugă un titlu scurt pentru acest prompt",
+	"Add a tag": "Adaugă o etichetă",
+	"Add custom prompt": "Adaugă prompt personalizat",
+	"Add Docs": "Adaugă Documente",
+	"Add Files": "Adaugă Fișiere",
+	"Add Memory": "Adaugă Memorie",
+	"Add message": "Adaugă mesaj",
+	"Add Model": "Adaugă Model",
+	"Add Tag": "Adaugă Etichetă",
+	"Add Tags": "Adaugă Etichete",
+	"Add User": "Adaugă Utilizator",
+	"Adjusting these settings will apply changes universally to all users.": "Ajustarea acestor setări va aplica modificările universal pentru toți utilizatorii.",
+	"admin": "administrator",
+	"Admin": "Administrator",
+	"Admin Panel": "Panoul de Administrare",
+	"Admin Settings": "Setări de Administrator",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorii au acces la toate instrumentele în orice moment; utilizatorii au nevoie de instrumente asignate pe model în spațiul de lucru.",
+	"Advanced Parameters": "Parametri Avansați",
+	"Advanced Params": "Parametri Avansați",
+	"all": "toate",
+	"All Documents": "Toate Documentele",
+	"All Users": "Toți Utilizatorii",
+	"Allow": "Permite",
+	"Allow Chat Deletion": "Permite Ștergerea Conversațiilor",
+	"Allow non-local voices": "Permite voci non-locale",
+	"Allow User Location": "Permite Localizarea Utilizatorului",
+	"Allow Voice Interruption in Call": "Permite Întreruperea Vocii în Apel",
+	"alphanumeric characters and hyphens": "caractere alfanumerice și cratime",
+	"Already have an account?": "Deja ai un cont?",
+	"an assistant": "un asistent",
+	"and": "și",
+	"and create a new shared link.": "și creează un nou link partajat.",
+	"API Base URL": "URL Bază API",
+	"API Key": "Cheie API",
+	"API Key created.": "Cheie API creată.",
+	"API keys": "Chei API",
+	"April": "Aprilie",
+	"Archive": "Arhivează",
+	"Archive All Chats": "Arhivează Toate Conversațiile",
+	"Archived Chats": "Conversații Arhivate",
+	"are allowed - Activate this command by typing": "sunt permise - Activează această comandă tastând",
+	"Are you sure?": "Ești sigur?",
+	"Attach file": "Atașează fișier",
+	"Attention to detail": "Atenție la detalii",
+	"Audio": "Audio",
+	"Audio settings updated successfully": "Setările audio au fost actualizate cu succes",
+	"August": "August",
+	"Auto-playback response": "Redare automată a răspunsului",
+	"AUTOMATIC1111 Api Auth String": "Șir de Autentificare API AUTOMATIC1111",
+	"AUTOMATIC1111 Base URL": "URL Bază AUTOMATIC1111",
+	"AUTOMATIC1111 Base URL is required.": "Este necesar URL-ul Bază AUTOMATIC1111.",
+	"available!": "disponibil!",
+	"Back": "Înapoi",
+	"Bad Response": "Răspuns Greșit",
+	"Banners": "Bannere",
+	"Base Model (From)": "Model de Bază (De la)",
+	"Batch Size (num_batch)": "Dimensiune Lot (num_batch)",
+	"before": "înainte",
+	"Being lazy": "Fiind leneș",
+	"Brave Search API Key": "Cheie API Brave Search",
+	"Bypass SSL verification for Websites": "Ocolește verificarea SSL pentru site-uri web",
+	"Call": "Apel",
+	"Call feature is not supported when using Web STT engine": "Funcția de apel nu este suportată când se utilizează motorul Web STT",
+	"Camera": "Cameră",
+	"Cancel": "Anulează",
+	"Capabilities": "Capabilități",
+	"Change Password": "Schimbă Parola",
+	"Chat": "Conversație",
+	"Chat Background Image": "Imagine de Fundal pentru Conversație",
+	"Chat Bubble UI": "Interfață cu Bule de Conversație",
+	"Chat Controls": "Controale pentru Conversație",
+	"Chat direction": "Direcția conversației",
+	"Chat History": "Istoricul conversațiilor",
+	"Chat History is off for this browser.": "Istoricul conversațiilor este dezactivat pentru acest browser.",
+	"Chats": "Conversații",
+	"Check Again": "Verifică din Nou",
+	"Check for updates": "Verifică actualizări",
+	"Checking for updates...": "Se verifică actualizările...",
+	"Choose a model before saving...": "Alege un model înainte de a salva...",
+	"Chunk Overlap": "Suprapunere Bloc",
+	"Chunk Params": "Parametri Bloc",
+	"Chunk Size": "Dimensiune Bloc",
+	"Citation": "Citație",
+	"Clear memory": "Șterge memoria",
+	"Click here for help.": "Apasă aici pentru ajutor.",
+	"Click here to": "Apasă aici pentru",
+	"Click here to download user import template file.": "Apasă aici pentru a descărca fișierul șablon de import utilizator.",
+	"Click here to select": "Apasă aici pentru a selecta",
+	"Click here to select a csv file.": "Apasă aici pentru a selecta un fișier csv.",
+	"Click here to select a py file.": "Apasă aici pentru a selecta un fișier py.",
+	"Click here to select documents.": "Apasă aici pentru a selecta documente.",
+	"click here.": "apasă aici.",
+	"Click on the user role button to change a user's role.": "Apasă pe butonul rolului utilizatorului pentru a schimba rolul unui utilizator.",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permisiunea de scriere în clipboard a fost refuzată. Vă rugăm să verificați setările browserului pentru a acorda accesul necesar.",
+	"Clone": "Clonează",
+	"Close": "Închide",
+	"Code formatted successfully": "Cod formatat cu succes",
+	"Collection": "Colecție",
+	"ComfyUI": "ComfyUI",
+	"ComfyUI Base URL": "URL De Bază ComfyUI",
+	"ComfyUI Base URL is required.": "Este necesar URL-ul De Bază ComfyUI.",
+	"Command": "Comandă",
+	"Concurrent Requests": "Cereri Concurente",
+	"Confirm": "Confirmă",
+	"Confirm Password": "Confirmă Parola",
+	"Confirm your action": "Confirmă acțiunea ta",
+	"Connections": "Conexiuni",
+	"Contact Admin for WebUI Access": "Contactează administratorul pentru acces WebUI",
+	"Content": "Conținut",
+	"Content Extraction": "Extragere Conținut",
+	"Context Length": "Lungime Context",
+	"Continue Response": "Continuă Răspunsul",
+	"Continue with {{provider}}": "Continuă cu {{provider}}",
+	"Controls": "Controale",
+	"Copied shared chat URL to clipboard!": "URL-ul conversației partajate a fost copiat în clipboard!",
+	"Copy": "Copiază",
+	"Copy last code block": "Copiază ultimul bloc de cod",
+	"Copy last response": "Copiază ultimul răspuns",
+	"Copy Link": "Copiază Link",
+	"Copying to clipboard was successful!": "Copierea în clipboard a fost realizată cu succes!",
+	"Create a model": "Creează un model",
+	"Create Account": "Creează Cont",
+	"Create new key": "Creează cheie nouă",
+	"Create new secret key": "Creează cheie secretă nouă",
+	"Created at": "Creat la",
+	"Created At": "Creat La",
+	"Created by": "Creat de",
+	"CSV Import": "Import CSV",
+	"Current Model": "Model Curent",
+	"Current Password": "Parola Curentă",
+	"Custom": "Personalizat",
+	"Customize models for a specific purpose": "Personalizează modele pentru un scop specific",
+	"Dark": "Întunecat",
+	"Dashboard": "Tablou de Bord",
+	"Database": "Bază de Date",
+	"December": "Decembrie",
+	"Default": "Implicit",
+	"Default (Automatic1111)": "Implicit (Automatic1111)",
+	"Default (SentenceTransformers)": "Implicit (SentenceTransformers)",
+	"Default Model": "Model Implicit",
+	"Default model updated": "Modelul implicit a fost actualizat",
+	"Default Prompt Suggestions": "Sugestii de Prompt Implicite",
+	"Default User Role": "Rolul Implicit al Utilizatorului",
+	"delete": "șterge",
+	"Delete": "Șterge",
+	"Delete a model": "Șterge un model",
+	"Delete All Chats": "Șterge Toate Conversațiile",
+	"Delete chat": "Șterge conversația",
+	"Delete Chat": "Șterge Conversația",
+	"Delete chat?": "Șterge conversația?",
+	"Delete Doc": "Șterge document",
+	"Delete function?": "Șterge funcția?",
+	"Delete prompt?": "Șterge promptul?",
+	"delete this link": "șterge acest link",
+	"Delete tool?": "Șterge instrumentul?",
+	"Delete User": "Șterge Utilizatorul",
+	"Deleted {{deleteModelTag}}": "{{deleteModelTag}} șters",
+	"Deleted {{name}}": "{{name}} șters",
+	"Description": "Descriere",
+	"Didn't fully follow instructions": "Nu a urmat complet instrucțiunile",
+	"Disabled": "Dezactivat",
+	"Discover a function": "Descoperă o funcție",
+	"Discover a model": "Descoperă un model",
+	"Discover a prompt": "Descoperă un prompt",
+	"Discover a tool": "Descoperă un instrument",
+	"Discover, download, and explore custom functions": "Descoperă, descarcă și explorează funcții personalizate",
+	"Discover, download, and explore custom prompts": "Descoperă, descarcă și explorează prompturi personalizate",
+	"Discover, download, and explore custom tools": "Descoperă, descarcă și explorează instrumente personalizate",
+	"Discover, download, and explore model presets": "Descoperă, descarcă și explorează presetări de model",
+	"Dismissible": "Ignorabil",
+	"Display Emoji in Call": "Afișează Emoji în Apel",
+	"Display the username instead of You in the Chat": "Afișează numele utilizatorului în loc de Tu în Conversație",
+	"Do not install functions from sources you do not fully trust.": "Nu instalați funcții din surse în care nu aveți încredere completă.",
+	"Do not install tools from sources you do not fully trust.": "Nu instalați instrumente din surse în care nu aveți încredere completă.",
+	"Document": "Document",
+	"Document Settings": "Setări Document",
+	"Documentation": "Documentație",
+	"Documents": "Documente",
+	"does not make any external connections, and your data stays securely on your locally hosted server.": "nu face nicio conexiune externă, iar datele tale rămân în siguranță pe serverul găzduit local.",
+	"Don't Allow": "Nu Permite",
+	"Don't have an account?": "Nu ai un cont?",
+	"don't install random functions from sources you don't trust.": "nu instala funcții aleatorii din surse în care nu ai încredere.",
+	"don't install random tools from sources you don't trust.": "nu instala instrumente aleatorii din surse în care nu ai încredere.",
+	"Don't like the style": "Nu îți place stilul",
+	"Done": "Gata",
+	"Download": "Descarcă",
+	"Download canceled": "Descărcare anulată",
+	"Download Database": "Descarcă Baza de Date",
+	"Drop any files here to add to the conversation": "Plasează orice fișiere aici pentru a le adăuga la conversație",
+	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "de ex. '30s', '10m'. Unitățile de timp valide sunt 's', 'm', 'h'.",
+	"Edit": "Editează",
+	"Edit Doc": "Editează Document",
+	"Edit Memory": "Editează Memorie",
+	"Edit User": "Editează Utilizator",
+	"ElevenLabs": "ElevenLabs",
+	"Email": "Email",
+	"Embedding Batch Size": "Dimensiune Lot de Încapsulare",
+	"Embedding Model": "Model de Încapsulare",
+	"Embedding Model Engine": "Motor de Model de Încapsulare",
+	"Embedding model set to \"{{embedding_model}}\"": "Modelul de încapsulare setat la \"{{embedding_model}}\"",
+	"Enable Chat History": "Activează Istoricul Conversațiilor",
+	"Enable Community Sharing": "Activează Partajarea Comunitară",
+	"Enable New Sign Ups": "Activează Înscrierile Noi",
+	"Enable Web Search": "Activează Căutarea pe Web",
+	"Enabled": "Activat",
+	"Engine": "Motor",
+	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Asigurați-vă că fișierul CSV include 4 coloane în această ordine: Nume, Email, Parolă, Rol.",
+	"Enter {{role}} message here": "Introduceți mesajul pentru {{role}} aici",
+	"Enter a detail about yourself for your LLMs to recall": "Introduceți un detaliu despre dvs. pe care LLM-urile să-l rețină",
+	"Enter api auth string (e.g. username:password)": "Introduceți șirul de autentificare API (de ex. username:password)",
+	"Enter Brave Search API Key": "Introduceți Cheia API Brave Search",
+	"Enter Chunk Overlap": "Introduceți Suprapunerea Blocului",
+	"Enter Chunk Size": "Introduceți Dimensiunea Blocului",
+	"Enter Github Raw URL": "Introduceți URL-ul Raw de pe Github",
+	"Enter Google PSE API Key": "Introduceți Cheia API Google PSE",
+	"Enter Google PSE Engine Id": "Introduceți ID-ul Motorului Google PSE",
+	"Enter Image Size (e.g. 512x512)": "Introduceți Dimensiunea Imaginii (de ex. 512x512)",
+	"Enter language codes": "Introduceți codurile limbilor",
+	"Enter model tag (e.g. {{modelTag}})": "Introduceți eticheta modelului (de ex. {{modelTag}})",
+	"Enter Number of Steps (e.g. 50)": "Introduceți Numărul de Pași (de ex. 50)",
+	"Enter Score": "Introduceți Scorul",
+	"Enter Searxng Query URL": "Introduceți URL-ul Interogării Searxng",
+	"Enter Serper API Key": "Introduceți Cheia API Serper",
+	"Enter Serply API Key": "Introduceți Cheia API Serply",
+	"Enter Serpstack API Key": "Introduceți Cheia API Serpstack",
+	"Enter stop sequence": "Introduceți secvența de oprire",
+	"Enter system prompt": "Introduceți promptul de sistem",
+	"Enter Tavily API Key": "Introduceți Cheia API Tavily",
+	"Enter Tika Server URL": "Introduceți URL-ul Serverului Tika",
+	"Enter Top K": "Introduceți Top K",
+	"Enter URL (e.g. http://127.0.0.1:7860/)": "Introduceți URL-ul (de ex. http://127.0.0.1:7860/)",
+	"Enter URL (e.g. http://localhost:11434)": "Introduceți URL-ul (de ex. http://localhost:11434)",
+	"Enter Your Email": "Introduceți Email-ul Dvs.",
+	"Enter Your Full Name": "Introduceți Numele Dvs. Complet",
+	"Enter your message": "Introduceți mesajul dvs.",
+	"Enter Your Password": "Introduceți Parola Dvs.",
+	"Enter Your Role": "Introduceți Rolul Dvs.",
+	"Error": "Eroare",
+	"Experimental": "Experimental",
+	"Export": "Exportă",
+	"Export All Chats (All Users)": "Exportă Toate Conversațiile (Toți Utilizatorii)",
+	"Export chat (.json)": "Exportă conversația (.json)",
+	"Export Chats": "Exportă Conversațiile",
+	"Export Documents Mapping": "Exportă Maparea Documentelor",
+	"Export Functions": "Exportă Funcțiile",
+	"Export LiteLLM config.yaml": "Exportă Configurația LiteLLM config.yaml",
+	"Export Models": "Exportă Modelele",
+	"Export Prompts": "Exportă Prompturile",
+	"Export Tools": "Exportă Instrumentele",
+	"External Models": "Modele Externe",
+	"Failed to create API Key.": "Crearea cheii API a eșuat.",
+	"Failed to read clipboard contents": "Citirea conținutului clipboard-ului a eșuat",
+	"Failed to update settings": "Actualizarea setărilor a eșuat",
+	"February": "Februarie",
+	"Feel free to add specific details": "Adăugați detalii specifice fără nicio ezitare",
+	"File": "Fișier",
+	"File Mode": "Mod Fișier",
+	"File not found.": "Fișierul nu a fost găsit.",
+	"Files": "Fișiere",
+	"Filter is now globally disabled": "Filtrul este acum dezactivat global",
+	"Filter is now globally enabled": "Filtrul este acum activat global",
+	"Filters": "Filtre",
+	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Detectată falsificarea amprentelor: Nu se pot folosi inițialele ca avatar. Se utilizează imaginea de profil implicită.",
+	"Fluidly stream large external response chunks": "Transmite fluent blocuri mari de răspuns extern",
+	"Focus chat input": "Focalizează câmpul de intrare pentru conversație",
+	"Followed instructions perfectly": "A urmat instrucțiunile perfect",
+	"Form": "Formular",
+	"Format your variables using square brackets like this:": "Formatează variabilele folosind paranteze pătrate astfel:",
+	"Frequency Penalty": "Penalizare de Frecvență",
+	"Function created successfully": "Funcția a fost creată cu succes",
+	"Function deleted successfully": "Funcția a fost ștearsă cu succes",
+	"Function Description (e.g. A filter to remove profanity from text)": "Descrierea Funcției (de ex. Un filtru pentru a elimina profanitatea din text)",
+	"Function ID (e.g. my_filter)": "ID Funcție (de ex. my_filter)",
+	"Function is now globally disabled": "Funcția este acum dezactivată global",
+	"Function is now globally enabled": "Funcția este acum activată global",
+	"Function Name (e.g. My Filter)": "Nume Funcție (de ex. My Filter)",
+	"Function updated successfully": "Funcția a fost actualizată cu succes",
+	"Functions": "Funcții",
+	"Functions allow arbitrary code execution": "Funcțiile permit executarea arbitrară a codului",
+	"Functions allow arbitrary code execution.": "Funcțiile permit executarea arbitrară a codului.",
+	"Functions imported successfully": "Funcțiile au fost importate cu succes",
+	"General": "General",
+	"General Settings": "Setări Generale",
+	"Generate Image": "Generează Imagine",
+	"Generating search query": "Se generează interogarea de căutare",
+	"Generation Info": "Informații Generare",
+	"Get up and running with": "Începeți și rulați cu",
+	"Global": "Global",
+	"Good Response": "Răspuns Bun",
+	"Google PSE API Key": "Cheie API Google PSE",
+	"Google PSE Engine Id": "ID Motor Google PSE",
+	"h:mm a": "h:mm a",
+	"has no conversations.": "nu are conversații.",
+	"Hello, {{name}}": "Salut, {{name}}",
+	"Help": "Ajutor",
+	"Hide": "Ascunde",
+	"Hide Model": "Ascunde Modelul",
+	"How can I help you today?": "Cum te pot ajuta astăzi?",
+	"Hybrid Search": "Căutare Hibridă",
+	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Recunosc că am citit și înțeleg implicațiile acțiunii mele. Sunt conștient de riscurile asociate cu executarea codului arbitrar și am verificat fiabilitatea sursei.",
+	"Image Generation (Experimental)": "Generare Imagine (Experimental)",
+	"Image Generation Engine": "Motor de Generare a Imaginilor",
+	"Image Settings": "Setări Imagine",
+	"Images": "Imagini",
+	"Import Chats": "Importă Conversațiile",
+	"Import Documents Mapping": "Importă Maparea Documentelor",
+	"Import Functions": "Importă Funcțiile",
+	"Import Models": "Importă Modelele",
+	"Import Prompts": "Importă Prompturile",
+	"Import Tools": "Importă Instrumentele",
+	"Include `--api-auth` flag when running stable-diffusion-webui": "Includeți flag-ul `--api-auth` când rulați stable-diffusion-webui",
+	"Include `--api` flag when running stable-diffusion-webui": "Includeți flag-ul `--api` când rulați stable-diffusion-webui",
+	"Info": "Informații",
+	"Input commands": "Comenzi de intrare",
+	"Install from Github URL": "Instalează de la URL-ul Github",
+	"Instant Auto-Send After Voice Transcription": "Trimitere Automată Instantanee După Transcrierea Vocii",
+	"Interface": "Interfață",
+	"Invalid Tag": "Etichetă Invalidă",
+	"January": "Ianuarie",
+	"join our Discord for help.": "alătură-te Discord-ului nostru pentru ajutor.",
+	"JSON": "JSON",
+	"JSON Preview": "Previzualizare JSON",
+	"July": "Iulie",
+	"June": "Iunie",
+	"JWT Expiration": "Expirarea JWT",
+	"JWT Token": "Token JWT",
+	"Keep Alive": "Menține Activ",
+	"Keyboard shortcuts": "Scurtături de la Tastatură",
+	"Knowledge": "Cunoștințe",
+	"Language": "Limbă",
+	"large language models, locally.": "modele mari de limbaj, local.",
+	"Last Active": "Ultima Activitate",
+	"Last Modified": "Ultima Modificare",
+	"Light": "Luminos",
+	"Listening...": "Ascult...",
+	"LLMs can make mistakes. Verify important information.": "LLM-urile pot face greșeli. Verificați informațiile importante.",
+	"Local Models": "Modele Locale",
+	"LTR": "LTR",
+	"Made by OpenWebUI Community": "Realizat de Comunitatea OpenWebUI",
+	"Make sure to enclose them with": "Asigurați-vă că le închideți cu",
+	"Manage": "Gestionează",
+	"Manage Models": "Gestionează Modelele",
+	"Manage Ollama Models": "Gestionează Modelele Ollama",
+	"Manage Pipelines": "Gestionează Conductele",
+	"March": "Martie",
+	"Max Tokens (num_predict)": "Număr Maxim de Tokeni (num_predict)",
+	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maxim 3 modele pot fi descărcate simultan. Vă rugăm să încercați din nou mai târziu.",
+	"May": "Mai",
+	"Memories accessible by LLMs will be shown here.": "Memoriile accesibile de LLM-uri vor fi afișate aici.",
+	"Memory": "Memorie",
+	"Memory added successfully": "Memoria a fost adăugată cu succes",
+	"Memory cleared successfully": "Memoria a fost ștearsă cu succes",
+	"Memory deleted successfully": "Memoria a fost ștearsă cu succes",
+	"Memory updated successfully": "Memoria a fost actualizată cu succes",
+	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mesajele pe care le trimiteți după crearea link-ului dvs. nu vor fi partajate. Utilizatorii cu URL-ul vor putea vizualiza conversația partajată.",
+	"Min P": "",
+	"Minimum Score": "Scor Minim",
+	"Mirostat": "Mirostat",
+	"Mirostat Eta": "Mirostat Eta",
+	"Mirostat Tau": "Mirostat Tau",
+	"MMMM DD, YYYY": "MMMM DD, YYYY",
+	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
+	"MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A",
+	"Model '{{modelName}}' has been successfully downloaded.": "Modelul '{{modelName}}' a fost descărcat cu succes.",
+	"Model '{{modelTag}}' is already in queue for downloading.": "Modelul '{{modelTag}}' este deja în coada de descărcare.",
+	"Model {{modelId}} not found": "Modelul {{modelId}} nu a fost găsit",
+	"Model {{modelName}} is not vision capable": "Modelul {{modelName}} nu are capacități de viziune",
+	"Model {{name}} is now {{status}}": "Modelul {{name}} este acum {{status}}",
+	"Model created successfully!": "Modelul a fost creat cu succes!",
+	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Calea sistemului de fișiere al modelului detectată. Este necesar numele scurt al modelului pentru actualizare, nu se poate continua.",
+	"Model ID": "ID Model",
+	"Model not selected": "Modelul nu a fost selectat",
+	"Model Params": "Parametri Model",
+	"Model updated successfully": "Modelul a fost actualizat cu succes",
+	"Model Whitelisting": "Model pe Lista Albă",
+	"Model(s) Whitelisted": "Model(e) pe Lista Albă",
+	"Modelfile Content": "Conținutul Fișierului Model",
+	"Models": "Modele",
+	"More": "Mai multe",
+	"Name": "Nume",
+	"Name Tag": "Etichetă Nume",
+	"Name your model": "Denumirea modelului",
+	"New Chat": "Conversație Nouă",
+	"New Password": "Parolă Nouă",
+	"No content to speak": "Nu există conținut de vorbit",
+	"No documents found": "Nu au fost găsite documente",
+	"No file selected": "Nu a fost selectat niciun fișier",
+	"No results found": "Nu au fost găsite rezultate",
+	"No search query generated": "Nu a fost generată nicio interogare de căutare",
+	"No source available": "Nicio sursă disponibilă",
+	"No valves to update": "Nu există valve de actualizat",
+	"None": "Niciunul",
+	"Not factually correct": "Nu este corect din punct de vedere factual",
+	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Notă: Dacă setați un scor minim, căutarea va returna doar documente cu un scor mai mare sau egal cu scorul minim.",
+	"Notifications": "Notificări",
+	"November": "Noiembrie",
+	"num_thread (Ollama)": "num_thread (Ollama)",
+	"OAuth ID": "ID OAuth",
+	"October": "Octombrie",
+	"Off": "Dezactivat",
+	"Okay, Let's Go!": "Ok, Să Începem!",
+	"OLED Dark": "Întunecat OLED",
+	"Ollama": "Ollama",
+	"Ollama API": "API Ollama",
+	"Ollama API disabled": "API Ollama dezactivat",
+	"Ollama API is disabled": "API Ollama este dezactivat",
+	"Ollama Version": "Versiune Ollama",
+	"On": "Activat",
+	"Only": "Doar",
+	"Only alphanumeric characters and hyphens are allowed in the command string.": "Doar caracterele alfanumerice și cratimele sunt permise în șirul de comandă.",
+	"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oops! Țineți-vă bine! Fișierele dvs. sunt încă în cuptorul de procesare. Le pregătim la perfecțiune. Vă rugăm să aveți răbdare și vă vom anunța odată ce sunt gata.",
+	"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Se pare că URL-ul este invalid. Vă rugăm să verificați din nou și să încercați din nou.",
+	"Oops! There was an error in the previous response. Please try again or contact admin.": "Oops! A apărut o eroare în răspunsul anterior. Vă rugăm să încercați din nou sau să contactați administratorul.",
+	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! Utilizați o metodă nesuportată (doar frontend). Vă rugăm să serviți WebUI din backend.",
+	"Open AI (Dall-E)": "Open AI (Dall-E)",
+	"Open new chat": "Deschide conversație nouă",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "Versiunea Open WebUI (v{{OPEN_WEBUI_VERSION}}) este mai mică decât versiunea necesară (v{{REQUIRED_VERSION}})",
+	"OpenAI": "OpenAI",
+	"OpenAI API": "API OpenAI",
+	"OpenAI API Config": "Configurația API OpenAI",
+	"OpenAI API Key is required.": "Este necesară cheia API OpenAI.",
+	"OpenAI URL/Key required.": "Este necesar URL-ul/Cheia OpenAI.",
+	"or": "sau",
+	"Other": "Altele",
+	"Password": "Parolă",
+	"PDF document (.pdf)": "Document PDF (.pdf)",
+	"PDF Extract Images (OCR)": "Extrage Imagini PDF (OCR)",
+	"pending": "în așteptare",
+	"Permission denied when accessing media devices": "Permisiunea refuzată la accesarea dispozitivelor media",
+	"Permission denied when accessing microphone": "Permisiunea refuzată la accesarea microfonului",
+	"Permission denied when accessing microphone: {{error}}": "Permisiunea refuzată la accesarea microfonului: {{error}}",
+	"Personalization": "Personalizare",
+	"Pin": "Fixează",
+	"Pinned": "Fixat",
+	"Pipeline deleted successfully": "Conducta a fost ștearsă cu succes",
+	"Pipeline downloaded successfully": "Conducta a fost descărcată cu succes",
+	"Pipelines": "Conducte",
+	"Pipelines Not Detected": "Conducte Nedetectate",
+	"Pipelines Valves": "Valvele Conductelor",
+	"Plain text (.txt)": "Text simplu (.txt)",
+	"Playground": "Teren de Joacă",
+	"Please carefully review the following warnings:": "Vă rugăm să revizuiți cu atenție următoarele avertismente:",
+	"Positive attitude": "Atitudine pozitivă",
+	"Previous 30 days": "Ultimele 30 de zile",
+	"Previous 7 days": "Ultimele 7 zile",
+	"Profile Image": "Imagine de Profil",
+	"Prompt": "Prompt",
+	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (de ex. Spune-mi un fapt amuzant despre Imperiul Roman)",
+	"Prompt Content": "Conținut Prompt",
+	"Prompt suggestions": "Sugestii de Prompt",
+	"Prompts": "Prompturi",
+	"Pull \"{{searchValue}}\" from Ollama.com": "Extrage \"{{searchValue}}\" de pe Ollama.com",
+	"Pull a model from Ollama.com": "Extrage un model de pe Ollama.com",
+	"Query Params": "Parametri Interogare",
+	"RAG Template": "Șablon RAG",
+	"Read Aloud": "Citește cu Voce Tare",
+	"Record voice": "Înregistrează vocea",
+	"Redirecting you to OpenWebUI Community": "Vă redirecționăm către Comunitatea OpenWebUI",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referiți-vă la dvs. ca \"Utilizator\" (de ex., \"Utilizatorul învață spaniolă\")",
+	"Refused when it shouldn't have": "Refuzat când nu ar fi trebuit",
+	"Regenerate": "Regenerare",
+	"Release Notes": "Note de Lansare",
+	"Remove": "Înlătură",
+	"Remove Model": "Înlătură Modelul",
+	"Rename": "Redenumește",
+	"Repeat Last N": "Repetă Ultimele N",
+	"Request Mode": "Mod de Cerere",
+	"Reranking Model": "Model de Rearanjare",
+	"Reranking model disabled": "Modelul de Rearanjare este dezactivat",
+	"Reranking model set to \"{{reranking_model}}\"": "Modelul de Rearanjare setat la \"{{reranking_model}}\"",
+	"Reset": "Resetează",
+	"Reset Upload Directory": "Resetează Directorul de Încărcare",
+	"Reset Vector Storage": "Resetează Stocarea Vectorilor",
+	"Response AutoCopy to Clipboard": "Copiere Automată a Răspunsului în Clipboard",
+	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "Notificările de răspuns nu pot fi activate deoarece permisiunile site-ului au fost refuzate. Vă rugăm să vizitați setările browserului pentru a acorda accesul necesar.",
+	"Role": "Rol",
+	"Rosé Pine": "Rosé Pine",
+	"Rosé Pine Dawn": "Rosé Pine Dawn",
+	"RTL": "RTL",
+	"Run Llama 2, Code Llama, and other models. Customize and create your own.": "Rulați Llama 2, Code Llama și alte modele. Personalizați și creați-vă propriile modele.",
+	"Running": "Rulare",
+	"Save": "Salvează",
+	"Save & Create": "Salvează & Creează",
+	"Save & Update": "Salvează & Actualizează",
+	"Save Tag": "Salvează Eticheta",
+	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvarea jurnalelor de conversație direct în stocarea browserului dvs. nu mai este suportată. Vă rugăm să luați un moment pentru a descărca și a șterge jurnalele de conversație făcând clic pe butonul de mai jos. Nu vă faceți griji, puteți reimporta ușor jurnalele de conversație în backend prin",
+	"Scan": "Scanează",
+	"Scan complete!": "Scanare completă!",
+	"Scan for documents from {{path}}": "Scanează pentru documente din {{path}}",
+	"Search": "Caută",
+	"Search a model": "Caută un model",
+	"Search Chats": "Caută în Conversații",
+	"Search Documents": "Caută în Documente",
+	"Search Functions": "Caută Funcții",
+	"Search Models": "Caută Modele",
+	"Search Prompts": "Caută Prompturi",
+	"Search Query Generation Prompt": "Prompt de Generare Interogare de Căutare",
+	"Search Query Generation Prompt Length Threshold": "Prag Lungime Prompt de Generare Interogare de Căutare",
+	"Search Result Count": "Număr Rezultate Căutare",
+	"Search Tools": "Caută Instrumente",
+	"Searched {{count}} sites_one": "{{count}} site căutat",
+	"Searched {{count}} sites_few": "",
+	"Searched {{count}} sites_other": "{{count}} alte site-uri căutate",
+	"Searching \"{{searchQuery}}\"": "Căutare \"{{searchQuery}}\"",
+	"Searxng Query URL": "URL Interogare Searxng",
+	"See readme.md for instructions": "Consultați readme.md pentru instrucțiuni",
+	"See what's new": "Vezi ce e nou",
+	"Seed": "Sămânță",
+	"Select a base model": "Selectează un model de bază",
+	"Select a engine": "Selectează un motor",
+	"Select a function": "Selectează o funcție",
+	"Select a mode": "Selectează un mod",
+	"Select a model": "Selectează un model",
+	"Select a pipeline": "Selectează o conductă",
+	"Select a pipeline url": "Selectează un URL de conductă",
+	"Select a tool": "Selectează un instrument",
+	"Select an Ollama instance": "Selectează o instanță Ollama",
+	"Select Documents": "Selectează Documente",
+	"Select model": "Selectează model",
+	"Select only one model to call": "Selectează doar un singur model pentru apel",
+	"Selected model(s) do not support image inputs": "Modelul(e) selectat(e) nu suportă intrări de imagine",
+	"Send": "Trimite",
+	"Send a Message": "Trimite un Mesaj",
+	"Send message": "Trimite mesajul",
+	"September": "Septembrie",
+	"Serper API Key": "Cheie API Serper",
+	"Serply API Key": "Cheie API Serply",
+	"Serpstack API Key": "Cheie API Serpstack",
+	"Server connection verified": "Conexiunea la server a fost verificată",
+	"Set as default": "Setează ca implicit",
+	"Set Default Model": "Setează Modelul Implicit",
+	"Set embedding model (e.g. {{model}})": "Setează modelul de încapsulare (de ex. {{model}})",
+	"Set Image Size": "Setează Dimensiunea Imaginilor",
+	"Set reranking model (e.g. {{model}})": "Setează modelul de rearanjare (de ex. {{model}})",
+	"Set Steps": "Setează Pași",
+	"Set Task Model": "Setează Model de Sarcină",
+	"Set Voice": "Setează Voce",
+	"Settings": "Setări",
+	"Settings saved successfully!": "Setările au fost salvate cu succes!",
+	"Settings updated successfully": "Setările au fost actualizate cu succes",
+	"Share": "Partajează",
+	"Share Chat": "Partajează Conversația",
+	"Share to OpenWebUI Community": "Partajează cu Comunitatea OpenWebUI",
+	"short-summary": "scurt-sumar",
+	"Show": "Afișează",
+	"Show Admin Details in Account Pending Overlay": "Afișează Detaliile Administratorului în Suprapunerea Contului În Așteptare",
+	"Show Model": "Afișează Modelul",
+	"Show shortcuts": "Afișează scurtături",
+	"Show your support!": "Arată-ți susținerea!",
+	"Showcased creativity": "Creativitate expusă",
+	"Sign in": "Autentificare",
+	"Sign Out": "Deconectare",
+	"Sign up": "Înregistrare",
+	"Signing in": "Autentificare",
+	"Source": "Sursă",
+	"Speech recognition error: {{error}}": "Eroare de recunoaștere vocală: {{error}}",
+	"Speech-to-Text Engine": "Motor de Conversie a Vocii în Text",
+	"Stop Sequence": "Oprește Secvența",
+	"STT Model": "Model STT",
+	"STT Settings": "Setări STT",
+	"Submit": "Trimite",
+	"Subtitle (e.g. about the Roman Empire)": "Subtitlu (de ex. despre Imperiul Roman)",
+	"Success": "Succes",
+	"Successfully updated.": "Actualizat cu succes.",
+	"Suggested": "Sugerat",
+	"Support": "Suport",
+	"Support this plugin:": "Susține acest plugin:",
+	"System": "Sistem",
+	"System Prompt": "Prompt de Sistem",
+	"Tags": "Etichete",
+	"Tap to interrupt": "Apasă pentru a întrerupe",
+	"Tavily API Key": "Cheie API Tavily",
+	"Tell us more:": "Spune-ne mai multe:",
+	"Temperature": "Temperatură",
+	"Template": "Șablon",
+	"Text Completion": "Completare Text",
+	"Text-to-Speech Engine": "Motor de Conversie a Textului în Vorbire",
+	"Tfs Z": "Tfs Z",
+	"Thanks for your feedback!": "Mulțumim pentru feedback!",
+	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Dezvoltatorii din spatele acestui plugin sunt voluntari pasionați din comunitate. Dacă considerați acest plugin util, vă rugăm să luați în considerare contribuția la dezvoltarea sa.",
+	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Scorul ar trebui să fie o valoare între 0.0 (0%) și 1.0 (100%).",
+	"Theme": "Temă",
+	"Thinking...": "Gândește...",
+	"This action cannot be undone. Do you wish to continue?": "Această acțiune nu poate fi anulată. Doriți să continuați?",
+	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Acest lucru asigură că conversațiile dvs. valoroase sunt salvate în siguranță în baza de date a backend-ului dvs. Mulțumim!",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Aceasta este o funcție experimentală, poate să nu funcționeze așa cum vă așteptați și este supusă schimbării în orice moment.",
+	"This setting does not sync across browsers or devices.": "Această setare nu se sincronizează între browsere sau dispozitive.",
+	"This will delete": "Aceasta va șterge",
+	"Thorough explanation": "Explicație detaliată",
+	"Tika": "Tika",
+	"Tika Server URL required.": "Este necesar URL-ul serverului Tika.",
+	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Sfat: Actualizați mai multe sloturi de variabile consecutiv apăsând tasta tab în câmpul de intrare al conversației după fiecare înlocuire.",
+	"Title": "Titlu",
+	"Title (e.g. Tell me a fun fact)": "Titlu (de ex. Spune-mi un fapt amuzant)",
+	"Title Auto-Generation": "Generare Automată a Titlului",
+	"Title cannot be an empty string.": "Titlul nu poate fi un șir gol.",
+	"Title Generation Prompt": "Prompt de Generare a Titlului",
+	"to": "către",
+	"To access the available model names for downloading,": "Pentru a accesa numele modelelor disponibile pentru descărcare,",
+	"To access the GGUF models available for downloading,": "Pentru a accesa modelele GGUF disponibile pentru descărcare,",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Pentru a accesa WebUI, vă rugăm să contactați administratorul. Administratorii pot gestiona statusurile utilizatorilor din Panoul de Administrare.",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "Pentru a adăuga documente aici, încărcați-le mai întâi în spațiul de lucru \"Documente\".",
+	"to chat input.": "către câmpul de intrare al conversației.",
+	"To select actions here, add them to the \"Functions\" workspace first.": "Pentru a selecta acțiuni aici, adăugați-le mai întâi în spațiul de lucru \"Funcții\".",
+	"To select filters here, add them to the \"Functions\" workspace first.": "Pentru a selecta filtrele aici, adăugați-le mai întâi în spațiul de lucru \"Funcții\".",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "Pentru a selecta kiturile de instrumente aici, adăugați-le mai întâi în spațiul de lucru \"Instrumente\".",
+	"Today": "Astăzi",
+	"Toggle settings": "Comută setările",
+	"Toggle sidebar": "Comută bara laterală",
+	"Tokens To Keep On Context Refresh (num_keep)": "Tokeni de Păstrat la Reîmprospătarea Contextului (num_keep)",
+	"Tool created successfully": "Instrumentul a fost creat cu succes",
+	"Tool deleted successfully": "Instrumentul a fost șters cu succes",
+	"Tool imported successfully": "Instrumentul a fost importat cu succes",
+	"Tool updated successfully": "Instrumentul a fost actualizat cu succes",
+	"Toolkit Description (e.g. A toolkit for performing various operations)": "Descrierea Kiturilor de Instrumente (de ex. Un kit de instrumente pentru efectuarea diferitelor operațiuni)",
+	"Toolkit ID (e.g. my_toolkit)": "ID Kit de Instrumente (de ex. my_toolkit)",
+	"Toolkit Name (e.g. My ToolKit)": "Nume Kit de Instrumente (de ex. My ToolKit)",
+	"Tools": "Instrumente",
+	"Tools are a function calling system with arbitrary code execution": "Instrumentele sunt un sistem de apelare a funcțiilor cu executare arbitrară a codului",
+	"Tools have a function calling system that allows arbitrary code execution": "Instrumentele au un sistem de apelare a funcțiilor care permite executarea arbitrară a codului",
+	"Tools have a function calling system that allows arbitrary code execution.": "Instrumentele au un sistem de apelare a funcțiilor care permite executarea arbitrară a codului.",
+	"Top K": "Top K",
+	"Top P": "Top P",
+	"Trouble accessing Ollama?": "Probleme la accesarea Ollama?",
+	"TTS Model": "Model TTS",
+	"TTS Settings": "Setări TTS",
+	"TTS Voice": "Voce TTS",
+	"Type": "Tip",
+	"Type Hugging Face Resolve (Download) URL": "Introduceți URL-ul de Rezolvare (Descărcare) Hugging Face",
+	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! A apărut o problemă la conectarea la {{provider}}.",
+	"UI": "Interfață Utilizator",
+	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tip de fișier necunoscut '{{file_type}}'. Se continuă totuși cu încărcarea fișierului.",
+	"Unpin": "Anulează Fixarea",
+	"Update": "Actualizează",
+	"Update and Copy Link": "Actualizează și Copiază Link-ul",
+	"Update password": "Actualizează parola",
+	"Updated at": "Actualizat la",
+	"Upload": "Încărcare",
+	"Upload a GGUF model": "Încarcă un model GGUF",
+	"Upload Files": "Încarcă Fișiere",
+	"Upload Pipeline": "Încarcă Conducta",
+	"Upload Progress": "Progres Încărcare",
+	"URL Mode": "Mod URL",
+	"Use '#' in the prompt input to load and select your documents.": "Folosiți '#' în câmpul de intrare al promptului pentru a încărca și selecta documentele dvs.",
+	"Use Gravatar": "Folosește Gravatar",
+	"Use Initials": "Folosește Inițialele",
+	"use_mlock (Ollama)": "use_mlock (Ollama)",
+	"use_mmap (Ollama)": "use_mmap (Ollama)",
+	"user": "utilizator",
+	"User location successfully retrieved.": "Localizarea utilizatorului a fost preluată cu succes.",
+	"User Permissions": "Permisiuni Utilizator",
+	"Users": "Utilizatori",
+	"Utilize": "Utilizează",
+	"Valid time units:": "Unități de timp valide:",
+	"Valves": "Valve",
+	"Valves updated": "Valve actualizate",
+	"Valves updated successfully": "Valve actualizate cu succes",
+	"variable": "variabilă",
+	"variable to have them replaced with clipboard content.": "variabilă pentru a fi înlocuite cu conținutul clipboard-ului.",
+	"Version": "Versiune",
+	"Voice": "Voce",
+	"Warning": "Avertisment",
+	"Warning:": "Avertisment:",
+	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avertisment: Dacă actualizați sau schimbați modelul de încapsulare, va trebui să reimportați toate documentele.",
+	"Web": "Web",
+	"Web API": "API Web",
+	"Web Loader Settings": "Setări Încărcător Web",
+	"Web Params": "Parametri Web",
+	"Web Search": "Căutare Web",
+	"Web Search Engine": "Motor de Căutare Web",
+	"Webhook URL": "URL Webhook",
+	"WebUI Settings": "Setări WebUI",
+	"WebUI will make requests to": "WebUI va face cereri către",
+	"What’s New in": "Ce e Nou în",
+	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Când istoricul este dezactivat, conversațiile noi din acest browser nu vor apărea în istoricul dvs. pe niciunul dintre dispozitivele dvs.",
+	"Whisper (Local)": "Whisper (Local)",
+	"Widescreen Mode": "Mod Ecran Larg",
+	"Workspace": "Spațiu de Lucru",
+	"Write a prompt suggestion (e.g. Who are you?)": "Scrieți o sugestie de prompt (de ex. Cine ești?)",
+	"Write a summary in 50 words that summarizes [topic or keyword].": "Scrieți un rezumat în 50 de cuvinte care rezumă [subiect sau cuvânt cheie].",
+	"Yesterday": "Ieri",
+	"You": "Tu",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Puteți personaliza interacțiunile dvs. cu LLM-urile adăugând amintiri prin butonul 'Gestionează' de mai jos, făcându-le mai utile și adaptate la dvs.",
+	"You cannot clone a base model": "Nu puteți clona un model de bază",
+	"You have no archived conversations.": "Nu aveți conversații arhivate.",
+	"You have shared this chat": "Ați partajat această conversație",
+	"You're a helpful assistant.": "Ești un asistent util.",
+	"You're now logged in.": "Acum ești autentificat.",
+	"Your account status is currently pending activation.": "Statusul contului dvs. este în așteptare pentru activare.",
+	"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.": "Întreaga dvs. contribuție va merge direct la dezvoltatorul plugin-ului; Open WebUI nu ia niciun procent. Cu toate acestea, platforma de finanțare aleasă ar putea avea propriile taxe.",
+	"Youtube": "Youtube",
+	"Youtube Loader Settings": "Setări Încărcător Youtube"
+}

+ 1 - 1
src/lib/i18n/locales/ru-RU/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Управление моделями",
 	"Manage Ollama Models": "Управление моделями Ollama",
 	"Manage Pipelines": "Управление конвейерами",
-	"Manage Valves": "",
 	"March": "Март",
 	"Max Tokens (num_predict)": "Максимальное количество жетонов (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Максимальное количество моделей для загрузки одновременно - 3. Пожалуйста, попробуйте позже.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Сообщения, которые вы отправляете после создания ссылки, не будут распространяться. Пользователи с URL смогут просматривать общий чат.",
+	"Min P": "",
 	"Minimum Score": "Минимальный балл",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/sr-RS/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Управљај моделима",
 	"Manage Ollama Models": "Управљај Ollama моделима",
 	"Manage Pipelines": "Управљање цевоводима",
-	"Manage Valves": "",
 	"March": "Март",
 	"Max Tokens (num_predict)": "Маx Токенс (нум_предицт)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Највише 3 модела могу бити преузета истовремено. Покушајте поново касније.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Поруке које пошаљете након стварања ваше везе неће бити подељене. Корисници са URL-ом ће моћи да виде дељено ћаскање.",
+	"Min P": "",
 	"Minimum Score": "Најмањи резултат",
 	"Mirostat": "Миростат",
 	"Mirostat Eta": "Миростат Ета",

+ 1 - 1
src/lib/i18n/locales/sv-SE/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Hantera modeller",
 	"Manage Ollama Models": "Hantera Ollama-modeller",
 	"Manage Pipelines": "Hantera rörledningar",
-	"Manage Valves": "",
 	"March": "mars",
 	"Max Tokens (num_predict)": "Maximalt antal tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Högst 3 modeller kan laddas ner samtidigt. Vänligen försök igen senare.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meddelanden du skickar efter att ha skapat din länk kommer inte att delas. Användare med URL:en kommer att kunna se delad chatt.",
+	"Min P": "",
 	"Minimum Score": "Tröskel",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/th-TH/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "จัดการโมเดล",
 	"Manage Ollama Models": "จัดการโมเดล Ollama",
 	"Manage Pipelines": "จัดการไปป์ไลน์",
-	"Manage Valves": "จัดการวาล์ว",
 	"March": "มีนาคม",
 	"Max Tokens (num_predict)": "โทเค็นสูงสุด (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "สามารถดาวน์โหลดโมเดลได้สูงสุด 3 โมเดลในเวลาเดียวกัน โปรดลองอีกครั้งในภายหลัง",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "ลบโมเดลสำเร็จ",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ข้อความที่คุณส่งหลังจากสร้างลิงก์ของคุณแล้วจะไม่ถูกแชร์ ผู้ใช้ที่มี URL จะสามารถดูแชทที่แชร์ได้",
+	"Min P": "",
 	"Minimum Score": "คะแนนขั้นต่ำ",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/tk-TW/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "",
 	"Manage Ollama Models": "",
 	"Manage Pipelines": "",
-	"Manage Valves": "",
 	"March": "",
 	"Max Tokens (num_predict)": "",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "",
+	"Min P": "",
 	"Minimum Score": "",
 	"Mirostat": "",
 	"Mirostat Eta": "",

+ 1 - 1
src/lib/i18n/locales/tr-TR/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Modelleri Yönet",
 	"Manage Ollama Models": "Ollama Modellerini Yönet",
 	"Manage Pipelines": "Pipelineları Yönet",
-	"Manage Valves": "Valvleri Yönet",
 	"March": "Mart",
 	"Max Tokens (num_predict)": "Maksimum Token (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Aynı anda en fazla 3 model indirilebilir. Lütfen daha sonra tekrar deneyin.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Bellek başarıyla silindi",
 	"Memory updated successfully": "Bellek başarıyla güncellendi",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Bağlantınızı oluşturduktan sonra gönderdiğiniz mesajlar paylaşılmayacaktır. URL'ye sahip kullanıcılar paylaşılan sohbeti görüntüleyebilecektir.",
+	"Min P": "",
 	"Minimum Score": "Minimum Skor",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 11 - 11
src/lib/i18n/locales/uk-UA/translation.json

@@ -15,7 +15,7 @@
 	"Account": "Обліковий запис",
 	"Account Activation Pending": "Очікування активації облікового запису",
 	"Accurate information": "Точна інформація",
-	"Actions": "",
+	"Actions": "Дії",
 	"Active Users": "Активні користувачі",
 	"Add": "Додати",
 	"Add a model id": "Додайте id моделі",
@@ -28,8 +28,8 @@
 	"Add Memory": "Додати пам'ять",
 	"Add message": "Додати повідомлення",
 	"Add Model": "Додати модель",
-	"Add Tag": "",
-	"Add Tags": "додати теги",
+	"Add Tag": "Додати тег",
+	"Add Tags": "Додати теги",
 	"Add User": "Додати користувача",
 	"Adjusting these settings will apply changes universally to all users.": "Зміни в цих налаштуваннях будуть застосовані для всіх користувачів.",
 	"admin": "адмін",
@@ -170,7 +170,7 @@
 	"Delete chat": "Видалити чат",
 	"Delete Chat": "Видалити чат",
 	"Delete chat?": "Видалити чат?",
-	"Delete Doc": "",
+	"Delete Doc": "Видалити док",
 	"Delete function?": "Видалити функцію?",
 	"Delete prompt?": "Видалити промт?",
 	"delete this link": "видалити це посилання",
@@ -214,8 +214,8 @@
 	"Edit Doc": "Редагувати документ",
 	"Edit Memory": "Редагувати пам'ять",
 	"Edit User": "Редагувати користувача",
-	"ElevenLabs": "",
-	"Email": "Електронна пошта",
+	"ElevenLabs": "ElevenLabs",
+	"Email": "Ел. пошта",
 	"Embedding Batch Size": "Розмір пакету під час вбудовування",
 	"Embedding Model": "Модель вбудовування",
 	"Embedding Model Engine": "Рушій моделі вбудовування ",
@@ -252,7 +252,7 @@
 	"Enter Top K": "Введіть Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введіть URL-адресу (напр., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Введіть URL-адресу (напр., http://localhost:11434)",
-	"Enter Your Email": "Введіть вашу електронну пошту",
+	"Enter Your Email": "Введіть вашу ел. пошту",
 	"Enter Your Full Name": "Введіть ваше ім'я",
 	"Enter your message": "Введіть повідомлення ",
 	"Enter Your Password": "Введіть ваш пароль",
@@ -278,7 +278,7 @@
 	"File": "Файл",
 	"File Mode": "Файловий режим",
 	"File not found.": "Файл не знайдено.",
-	"Files": "",
+	"Files": "Файли",
 	"Filter is now globally disabled": "Фільтр глобально вимкнено",
 	"Filter is now globally enabled": "Фільтр увімкнено глобально",
 	"Filters": "Фільтри",
@@ -364,7 +364,6 @@
 	"Manage Models": "Керування моделями",
 	"Manage Ollama Models": "Керування моделями Ollama",
 	"Manage Pipelines": "Керування конвеєрами",
-	"Manage Valves": "Керування клапанами",
 	"March": "Березень",
 	"Max Tokens (num_predict)": "Макс токенів (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Максимум 3 моделі можна завантажити одночасно. Будь ласка, спробуйте пізніше.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Пам'ять успішно видалено",
 	"Memory updated successfully": "Пам'ять успішно оновлено",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Повідомлення, які ви надішлете після створення посилання, не будуть доступні для інших. Користувачі, які мають URL, зможуть переглядати спільний чат.",
+	"Min P": "",
 	"Minimum Score": "Мінімальний бал",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
@@ -504,7 +504,7 @@
 	"Save": "Зберегти",
 	"Save & Create": "Зберегти та створити",
 	"Save & Update": "Зберегти та оновити",
-	"Save Tag": "",
+	"Save Tag": "Зберегти тег",
 	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Збереження журналів чату безпосередньо в сховище вашого браузера більше не підтримується. Будь ласка, завантажте та видаліть журнали чату, натиснувши кнопку нижче. Не хвилюйтеся, ви можете легко повторно імпортувати журнали чату до бекенду через",
 	"Scan": "Сканування",
 	"Scan complete!": "Сканування завершено!",
@@ -624,7 +624,7 @@
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Щоб отримати доступ до веб-інтерфейсу, зверніться до адміністратора. Адміністратори можуть керувати статусами користувачів з Панелі адміністратора.",
 	"To add documents here, upload them to the \"Documents\" workspace first.": "Щоб додати документи сюди, спочатку завантажте їх до робочої області \"Документи\".",
 	"to chat input.": "в чаті.",
-	"To select actions here, add them to the \"Functions\" workspace first.": "",
+	"To select actions here, add them to the \"Functions\" workspace first.": "Щоб вибрати дії тут, спочатку додайте їх до робочої області \"Функції\".",
 	"To select filters here, add them to the \"Functions\" workspace first.": "Щоб обрати фільтри тут, спочатку додайте їх до робочої області \"Функції\".",
 	"To select toolkits here, add them to the \"Tools\" workspace first.": "Щоб обрати тут набори інструментів, спочатку додайте їх до робочої області \"Інструменти\".",
 	"Today": "Сьогодні",

+ 1 - 1
src/lib/i18n/locales/vi-VN/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "Quản lý mô hình",
 	"Manage Ollama Models": "Quản lý mô hình với Ollama",
 	"Manage Pipelines": "Quản lý Pipelines",
-	"Manage Valves": "Quản lý Valves",
 	"March": "Tháng 3",
 	"Max Tokens (num_predict)": "Tokens tối đa (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Tối đa 3 mô hình có thể được tải xuống cùng lúc. Vui lòng thử lại sau.",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "Memory đã bị loại bỏ",
 	"Memory updated successfully": "Memory đã cập nhật thành công",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Tin nhắn bạn gửi sau khi tạo liên kết sẽ không được chia sẻ. Người dùng có URL sẽ có thể xem cuộc trò chuyện được chia sẻ.",
+	"Min P": "",
 	"Minimum Score": "Score tối thiểu",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/zh-CN/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "管理模型",
 	"Manage Ollama Models": "管理 Ollama 模型",
 	"Manage Pipelines": "管理 Pipeline",
-	"Manage Valves": "管理值",
 	"March": "三月",
 	"Max Tokens (num_predict)": "最多 Token (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "最多可以同时下载 3 个模型,请稍后重试。",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "记忆删除成功",
 	"Memory updated successfully": "记忆更新成功",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "创建链接后发送的消息不会被共享。具有 URL 的用户将能够查看共享对话。",
+	"Min P": "",
 	"Minimum Score": "最低分",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 1 - 1
src/lib/i18n/locales/zh-TW/translation.json

@@ -364,7 +364,6 @@
 	"Manage Models": "管理模型",
 	"Manage Ollama Models": "管理 Ollama 模型",
 	"Manage Pipelines": "管理管線",
-	"Manage Valves": "",
 	"March": "3 月",
 	"Max Tokens (num_predict)": "最大 Token(num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "最多可以同時下載 3 個模型。請稍後再試。",
@@ -376,6 +375,7 @@
 	"Memory deleted successfully": "",
 	"Memory updated successfully": "",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "建立連結後傳送的訊息將不會被共享。具有 URL 的使用者將會能夠檢視共享的聊天。",
+	"Min P": "",
 	"Minimum Score": "最低分數",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",

+ 55 - 43
src/routes/(app)/admin/+layout.svelte

@@ -1,11 +1,21 @@
 <script lang="ts">
 	import { onMount, getContext } from 'svelte';
+	import { goto } from '$app/navigation';
 
-	import { WEBUI_NAME, showSidebar } from '$lib/stores';
+	import { WEBUI_NAME, showSidebar, user } from '$lib/stores';
 	import MenuLines from '$lib/components/icons/MenuLines.svelte';
 	import { page } from '$app/stores';
 
 	const i18n = getContext('i18n');
+
+	let loaded = false;
+
+	onMount(async () => {
+		if ($user?.role !== 'admin') {
+			await goto('/');
+		}
+		loaded = true;
+	});
 </script>
 
 <svelte:head>
@@ -14,49 +24,50 @@
 	</title>
 </svelte:head>
 
-<div
-	class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
-		? 'md:max-w-[calc(100%-260px)]'
-		: ''}"
->
-	<div class=" px-4 pt-3 mt-0.5 mb-1">
-		<div class=" flex items-center gap-1">
-			<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
-				<button
-					id="sidebar-toggle-button"
-					class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
-					on:click={() => {
-						showSidebar.set(!$showSidebar);
-					}}
-				>
-					<div class=" m-auto self-center">
-						<MenuLines />
-					</div>
-				</button>
+{#if loaded}
+	<div
+		class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
+			? 'md:max-w-[calc(100%-260px)]'
+			: ''}"
+	>
+		<div class=" px-4 pt-3 mt-0.5 mb-1">
+			<div class=" flex items-center gap-1">
+				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
+					<button
+						id="sidebar-toggle-button"
+						class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+						on:click={() => {
+							showSidebar.set(!$showSidebar);
+						}}
+					>
+						<div class=" m-auto self-center">
+							<MenuLines />
+						</div>
+					</button>
+				</div>
+				<div class="flex items-center text-xl font-semibold">{$i18n.t('Admin Panel')}</div>
 			</div>
-			<div class="flex items-center text-xl font-semibold">{$i18n.t('Admin Panel')}</div>
 		</div>
-	</div>
 
-	<div class="px-4 my-1">
-		<div
-			class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
-		>
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {['/admin', '/admin/'].includes($page.url.pathname)
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/admin">{$i18n.t('Dashboard')}</a
+		<div class="px-4 my-1">
+			<div
+				class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
 			>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {['/admin', '/admin/'].includes($page.url.pathname)
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/admin">{$i18n.t('Dashboard')}</a
+				>
 
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/admin/settings')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/admin/settings">{$i18n.t('Settings')}</a
-			>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/admin/settings')
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/admin/settings">{$i18n.t('Settings')}</a
+				>
 
-			<!-- <a
+				<!-- <a
 				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/documents')
 					? 'bg-gray-50 dark:bg-gray-850'
 					: ''} transition"
@@ -71,12 +82,13 @@
 					: ''} transition"
 				href="/workspace/playground">{$i18n.t('Playground')}</a
 			> -->
+			</div>
 		</div>
-	</div>
 
-	<hr class=" my-2 dark:border-gray-850" />
+		<hr class=" my-2 dark:border-gray-850" />
 
-	<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
-		<slot />
+		<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
+			<slot />
+		</div>
 	</div>
-</div>
+{/if}

+ 80 - 69
src/routes/(app)/workspace/+layout.svelte

@@ -1,15 +1,20 @@
 <script lang="ts">
 	import { onMount, getContext } from 'svelte';
+	import { WEBUI_NAME, showSidebar, functions, user } from '$lib/stores';
+	import { page } from '$app/stores';
+	import { goto } from '$app/navigation';
 
-	import { WEBUI_NAME, showSidebar, functions } from '$lib/stores';
 	import MenuLines from '$lib/components/icons/MenuLines.svelte';
-	import { page } from '$app/stores';
-	import { getFunctions } from '$lib/apis/functions';
 
 	const i18n = getContext('i18n');
 
+	let loaded = false;
+
 	onMount(async () => {
-		// functions.set(await getFunctions(localStorage.token));
+		if ($user?.role !== 'admin') {
+			await goto('/');
+		}
+		loaded = true;
 	});
 </script>
 
@@ -19,80 +24,86 @@
 	</title>
 </svelte:head>
 
-<div
-	class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
-		? 'md:max-w-[calc(100%-260px)]'
-		: ''}"
->
-	<div class=" px-4 pt-3 mt-0.5 mb-1">
-		<div class=" flex items-center gap-1">
-			<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
-				<button
-					id="sidebar-toggle-button"
-					class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
-					on:click={() => {
-						showSidebar.set(!$showSidebar);
-					}}
-				>
-					<div class=" m-auto self-center">
-						<MenuLines />
-					</div>
-				</button>
+{#if loaded}
+	<div
+		class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
+			? 'md:max-w-[calc(100%-260px)]'
+			: ''}"
+	>
+		<div class=" px-4 pt-3 mt-0.5 mb-1">
+			<div class=" flex items-center gap-1">
+				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
+					<button
+						id="sidebar-toggle-button"
+						class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+						on:click={() => {
+							showSidebar.set(!$showSidebar);
+						}}
+					>
+						<div class=" m-auto self-center">
+							<MenuLines />
+						</div>
+					</button>
+				</div>
+				<div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div>
 			</div>
-			<div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div>
 		</div>
-	</div>
 
-	<div class="px-4 my-1">
-		<div
-			class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
-		>
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/models')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/workspace/models">{$i18n.t('Models')}</a
+		<div class="px-4 my-1">
+			<div
+				class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
 			>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/models')
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/workspace/models">{$i18n.t('Models')}</a
+				>
 
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/prompts')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/workspace/prompts">{$i18n.t('Prompts')}</a
-			>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/prompts')
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/workspace/prompts">{$i18n.t('Prompts')}</a
+				>
 
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/documents')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/workspace/documents"
-			>
-				{$i18n.t('Documents')}
-			</a>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes(
+						'/workspace/documents'
+					)
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/workspace/documents"
+				>
+					{$i18n.t('Documents')}
+				</a>
 
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/tools')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/workspace/tools"
-			>
-				{$i18n.t('Tools')}
-			</a>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/tools')
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/workspace/tools"
+				>
+					{$i18n.t('Tools')}
+				</a>
 
-			<a
-				class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/functions')
-					? 'bg-gray-50 dark:bg-gray-850'
-					: ''} transition"
-				href="/workspace/functions"
-			>
-				{$i18n.t('Functions')}
-			</a>
+				<a
+					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes(
+						'/workspace/functions'
+					)
+						? 'bg-gray-50 dark:bg-gray-850'
+						: ''} transition"
+					href="/workspace/functions"
+				>
+					{$i18n.t('Functions')}
+				</a>
+			</div>
 		</div>
-	</div>
 
-	<hr class=" my-2 dark:border-gray-850" />
+		<hr class=" my-2 dark:border-gray-850" />
 
-	<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
-		<slot />
+		<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
+			<slot />
+		</div>
 	</div>
-</div>
+{/if}