Merge branch 'dev' into main

This commit is contained in:
seiran 2025-06-08 05:58:24 +08:00 committed by GitHub
commit e97394958e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
117 changed files with 2735 additions and 786 deletions

48
.gitattributes vendored
View file

@ -1 +1,49 @@
# TypeScript
*.ts text eol=lf
*.tsx text eol=lf
# JavaScript
*.js text eol=lf
*.jsx text eol=lf
*.mjs text eol=lf
*.cjs text eol=lf
# Svelte
*.svelte text eol=lf
# HTML/CSS
*.html text eol=lf
*.css text eol=lf
*.scss text eol=lf
*.less text eol=lf
# Config files and JSON
*.json text eol=lf
*.jsonc text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.toml text eol=lf
# Shell scripts
*.sh text eol=lf
# Markdown & docs
*.md text eol=lf
*.mdx text eol=lf
*.txt text eol=lf
# Git-related
.gitattributes text eol=lf
.gitignore text eol=lf
# Prettier and other dotfiles
.prettierrc text eol=lf
.prettierignore text eol=lf
.eslintrc text eol=lf
.eslintignore text eol=lf
.stylelintrc text eol=lf
.editorconfig text eol=lf
# Misc
*.env text eol=lf
*.lock text eol=lf

View file

@ -14,16 +14,18 @@ env:
jobs:
build-main-image:
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
# GitHub Packages requires the entire repository name to be in lowercase
@ -111,16 +113,18 @@ jobs:
retention-days: 1
build-cuda-image:
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
# GitHub Packages requires the entire repository name to be in lowercase
@ -210,17 +214,122 @@ jobs:
if-no-files-found: error
retention-days: 1
build-ollama-image:
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
build-cuda126-image:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker images (cuda126 tag)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha,prefix=git-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
flavor: |
latest=${{ github.ref == 'refs/heads/main' }}
suffix=-cuda126,onlatest=true
- name: Extract metadata for Docker cache
id: cache-meta
uses: docker/metadata-action@v5
with:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
flavor: |
prefix=cache-cuda126-${{ matrix.platform }}-
latest=false
- name: Build Docker image (cuda126)
uses: docker/build-push-action@v5
id: build
with:
context: .
push: true
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
build-args: |
BUILD_HASH=${{ github.sha }}
USE_CUDA=true
USE_CUDA_VER=cu126
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-cuda126-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
build-ollama-image:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
# GitHub Packages requires the entire repository name to be in lowercase
@ -420,6 +529,62 @@ jobs:
run: |
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
merge-cuda126-images:
runs-on: ubuntu-latest
needs: [build-cuda126-image]
steps:
# GitHub Packages requires the entire repository name to be in lowercase
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
- name: Set repository and image name to lowercase
run: |
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
env:
IMAGE_NAME: '${{ github.repository }}'
- name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digests-cuda126-*
path: /tmp/digests
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker images (default latest tag)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.FULL_IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha,prefix=git-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
flavor: |
latest=${{ github.ref == 'refs/heads/main' }}
suffix=-cuda126,onlatest=true
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
merge-ollama-images:
runs-on: ubuntu-latest
needs: [build-ollama-image]

View file

@ -5,5 +5,6 @@
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }],
"endOfLine": "lf"
}

View file

@ -79,7 +79,7 @@ Want to learn more about Open WebUI's features? Check out our [Open WebUI docume
<tr>
<td>
<a href="https://warp.dev/open-webui" target="_blank">
<img src="https://docs.openwebui.com/sponsors/logos/warp.png" alt="n8n" style="width: 8rem; height: 8rem; border-radius: .75rem;" />
<img src="https://docs.openwebui.com/sponsors/logos/warp.png" alt="Warp" style="width: 8rem; height: 8rem; border-radius: .75rem;" />
</a>
</td>
<td>

View file

@ -901,9 +901,7 @@ TOOL_SERVER_CONNECTIONS = PersistentConfig(
####################################
WEBUI_URL = PersistentConfig(
"WEBUI_URL", "webui.url", os.environ.get("WEBUI_URL", "http://localhost:3000")
)
WEBUI_URL = PersistentConfig("WEBUI_URL", "webui.url", os.environ.get("WEBUI_URL", ""))
ENABLE_SIGNUP = PersistentConfig(
@ -1413,6 +1411,35 @@ Strictly return in JSON format:
{{MESSAGES:END:6}}
</chat_history>"""
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = PersistentConfig(
"FOLLOW_UP_GENERATION_PROMPT_TEMPLATE",
"task.follow_up.prompt_template",
os.environ.get("FOLLOW_UP_GENERATION_PROMPT_TEMPLATE", ""),
)
DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = """### Task:
Suggest 3-5 relevant follow-up questions or prompts that the user might naturally ask next in this conversation as a **user**, based on the chat history, to help continue or deepen the discussion.
### Guidelines:
- Write all follow-up questions from the users point of view, directed to the assistant.
- Make questions concise, clear, and directly related to the discussed topic(s).
- Only suggest follow-ups that make sense given the chat content and do not repeat what was already covered.
- If the conversation is very short or not specific, suggest more general (but relevant) follow-ups the user might ask.
- Use the conversation's primary language; default to English if multilingual.
- Response must be a JSON array of strings, no extra text or formatting.
### Output:
JSON format: { "follow_ups": ["Question 1?", "Question 2?", "Question 3?"] }
### Chat History:
<chat_history>
{{MESSAGES:END:6}}
</chat_history>"""
ENABLE_FOLLOW_UP_GENERATION = PersistentConfig(
"ENABLE_FOLLOW_UP_GENERATION",
"task.follow_up.enable",
os.environ.get("ENABLE_FOLLOW_UP_GENERATION", "True").lower() == "true",
)
ENABLE_TAGS_GENERATION = PersistentConfig(
"ENABLE_TAGS_GENERATION",
"task.tags.enable",
@ -2444,6 +2471,18 @@ PERPLEXITY_API_KEY = PersistentConfig(
os.getenv("PERPLEXITY_API_KEY", ""),
)
PERPLEXITY_MODEL = PersistentConfig(
"PERPLEXITY_MODEL",
"rag.web.search.perplexity_model",
os.getenv("PERPLEXITY_MODEL", "sonar"),
)
PERPLEXITY_SEARCH_CONTEXT_USAGE = PersistentConfig(
"PERPLEXITY_SEARCH_CONTEXT_USAGE",
"rag.web.search.perplexity_search_context_usage",
os.getenv("PERPLEXITY_SEARCH_CONTEXT_USAGE", "medium"),
)
SOUGOU_API_SID = PersistentConfig(
"SOUGOU_API_SID",
"rag.web.search.sougou_api_sid",

View file

@ -111,6 +111,7 @@ class TASKS(str, Enum):
DEFAULT = lambda task="": f"{task if task else 'generation'}"
TITLE_GENERATION = "title_generation"
FOLLOW_UP_GENERATION = "follow_up_generation"
TAGS_GENERATION = "tags_generation"
EMOJI_GENERATION = "emoji_generation"
QUERY_GENERATION = "query_generation"

View file

@ -25,6 +25,7 @@ from open_webui.socket.main import (
)
from open_webui.models.users import UserModel
from open_webui.models.functions import Functions
from open_webui.models.models import Models
@ -227,12 +228,7 @@ async def generate_function_chat_completion(
"__task__": __task__,
"__task_body__": __task_body__,
"__files__": files,
"__user__": {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
},
"__user__": user.model_dump() if isinstance(user, UserModel) else {},
"__metadata__": metadata,
"__request__": request,
}

View file

@ -37,7 +37,7 @@ from fastapi import (
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, RedirectResponse
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from starlette_compress import CompressMiddleware
@ -268,6 +268,8 @@ from open_webui.config import (
BRAVE_SEARCH_API_KEY,
EXA_API_KEY,
PERPLEXITY_API_KEY,
PERPLEXITY_MODEL,
PERPLEXITY_SEARCH_CONTEXT_USAGE,
SOUGOU_API_SID,
SOUGOU_API_SK,
KAGI_SEARCH_API_KEY,
@ -359,10 +361,12 @@ from open_webui.config import (
TASK_MODEL_EXTERNAL,
ENABLE_TAGS_GENERATION,
ENABLE_TITLE_GENERATION,
ENABLE_FOLLOW_UP_GENERATION,
ENABLE_SEARCH_QUERY_GENERATION,
ENABLE_RETRIEVAL_QUERY_GENERATION,
ENABLE_AUTOCOMPLETE_GENERATION,
TITLE_GENERATION_PROMPT_TEMPLATE,
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
TAGS_GENERATION_PROMPT_TEMPLATE,
IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
@ -411,6 +415,7 @@ from open_webui.utils.chat import (
chat_completed as chat_completed_handler,
chat_action as chat_action_handler,
)
from open_webui.utils.embeddings import generate_embeddings
from open_webui.utils.middleware import process_chat_payload, process_chat_response
from open_webui.utils.access_control import has_access
@ -771,6 +776,8 @@ app.state.config.BING_SEARCH_V7_ENDPOINT = BING_SEARCH_V7_ENDPOINT
app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = BING_SEARCH_V7_SUBSCRIPTION_KEY
app.state.config.EXA_API_KEY = EXA_API_KEY
app.state.config.PERPLEXITY_API_KEY = PERPLEXITY_API_KEY
app.state.config.PERPLEXITY_MODEL = PERPLEXITY_MODEL
app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = PERPLEXITY_SEARCH_CONTEXT_USAGE
app.state.config.SOUGOU_API_SID = SOUGOU_API_SID
app.state.config.SOUGOU_API_SK = SOUGOU_API_SK
app.state.config.EXTERNAL_WEB_SEARCH_URL = EXTERNAL_WEB_SEARCH_URL
@ -959,6 +966,7 @@ app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = ENABLE_RETRIEVAL_QUERY_GENE
app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = ENABLE_AUTOCOMPLETE_GENERATION
app.state.config.ENABLE_TAGS_GENERATION = ENABLE_TAGS_GENERATION
app.state.config.ENABLE_TITLE_GENERATION = ENABLE_TITLE_GENERATION
app.state.config.ENABLE_FOLLOW_UP_GENERATION = ENABLE_FOLLOW_UP_GENERATION
app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = TITLE_GENERATION_PROMPT_TEMPLATE
@ -966,6 +974,9 @@ app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = TAGS_GENERATION_PROMPT_TEMPLA
app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = (
IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
)
app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = (
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
)
app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = (
TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE
@ -1197,6 +1208,37 @@ async def get_base_models(request: Request, user=Depends(get_admin_user)):
return {"data": models}
##################################
# Embeddings
##################################
@app.post("/api/embeddings")
async def embeddings(
request: Request, form_data: dict, user=Depends(get_verified_user)
):
"""
OpenAI-compatible embeddings endpoint.
This handler:
- Performs user/model checks and dispatches to the correct backend.
- Supports OpenAI, Ollama, arena models, pipelines, and any compatible provider.
Args:
request (Request): Request context.
form_data (dict): OpenAI-like payload (e.g., {"model": "...", "input": [...]})
user (UserModel): Authenticated user.
Returns:
dict: OpenAI-compatible embeddings response.
"""
# Make sure models are loaded in app state
if not request.app.state.MODELS:
await get_all_models(request, user=user)
# Use generic dispatcher in utils.embeddings
return await generate_embeddings(request, form_data, user)
@app.post("/api/chat/completions")
async def chat_completion(
request: Request,
@ -1628,7 +1670,20 @@ async def healthcheck_with_db():
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
app.mount("/cache", StaticFiles(directory=CACHE_DIR), name="cache")
@app.get("/cache/{path:path}")
async def serve_cache_file(
path: str,
user=Depends(get_verified_user),
):
file_path = os.path.abspath(os.path.join(CACHE_DIR, path))
# prevent path traversal
if not file_path.startswith(os.path.abspath(CACHE_DIR)):
raise HTTPException(status_code=404, detail="File not found")
if not os.path.isfile(file_path):
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(file_path)
def swagger_ui_html(*args, **kwargs):

View file

@ -95,6 +95,7 @@ class UserRoleUpdateForm(BaseModel):
class UserUpdateForm(BaseModel):
role: str
name: str
email: str
profile_image_url: str

View file

@ -76,7 +76,6 @@ known_source_ext = [
"swift",
"vue",
"svelte",
"msg",
"ex",
"exs",
"erl",
@ -147,15 +146,12 @@ class DoclingLoader:
)
}
params = {
"image_export_mode": "placeholder",
"table_mode": "accurate",
}
params = {"image_export_mode": "placeholder", "table_mode": "accurate"}
if self.params:
if self.params.get("do_picture_classification"):
params["do_picture_classification"] = self.params.get(
"do_picture_classification"
if self.params.get("do_picture_description"):
params["do_picture_description"] = self.params.get(
"do_picture_description"
)
if self.params.get("ocr_engine") and self.params.get("ocr_lang"):
@ -292,7 +288,7 @@ class Loader:
params={
"ocr_engine": self.kwargs.get("DOCLING_OCR_ENGINE"),
"ocr_lang": self.kwargs.get("DOCLING_OCR_LANG"),
"do_picture_classification": self.kwargs.get(
"do_picture_description": self.kwargs.get(
"DOCLING_DO_PICTURE_DESCRIPTION"
),
},

View file

@ -20,6 +20,14 @@ class MistralLoader:
"""
Enhanced Mistral OCR loader with both sync and async support.
Loads documents by processing them through the Mistral OCR API.
Performance Optimizations:
- Differentiated timeouts for different operations
- Intelligent retry logic with exponential backoff
- Memory-efficient file streaming for large files
- Connection pooling and keepalive optimization
- Semaphore-based concurrency control for batch processing
- Enhanced error handling with retryable error classification
"""
BASE_API_URL = "https://api.mistral.ai/v1"
@ -53,17 +61,40 @@ class MistralLoader:
self.max_retries = max_retries
self.debug = enable_debug_logging
# Pre-compute file info for performance
# PERFORMANCE OPTIMIZATION: Differentiated timeouts for different operations
# This prevents long-running OCR operations from affecting quick operations
# and improves user experience by failing fast on operations that should be quick
self.upload_timeout = min(
timeout, 120
) # Cap upload at 2 minutes - prevents hanging on large files
self.url_timeout = (
30 # URL requests should be fast - fail quickly if API is slow
)
self.ocr_timeout = (
timeout # OCR can take the full timeout - this is the heavy operation
)
self.cleanup_timeout = (
30 # Cleanup should be quick - don't hang on file deletion
)
# PERFORMANCE OPTIMIZATION: Pre-compute file info to avoid repeated filesystem calls
# This avoids multiple os.path.basename() and os.path.getsize() calls during processing
self.file_name = os.path.basename(file_path)
self.file_size = os.path.getsize(file_path)
# ENHANCEMENT: Added User-Agent for better API tracking and debugging
self.headers = {
"Authorization": f"Bearer {self.api_key}",
"User-Agent": "OpenWebUI-MistralLoader/2.0",
"User-Agent": "OpenWebUI-MistralLoader/2.0", # Helps API provider track usage
}
def _debug_log(self, message: str, *args) -> None:
"""Conditional debug logging for performance."""
"""
PERFORMANCE OPTIMIZATION: Conditional debug logging for performance.
Only processes debug messages when debug mode is enabled, avoiding
string formatting overhead in production environments.
"""
if self.debug:
log.debug(message, *args)
@ -115,53 +146,118 @@ class MistralLoader:
log.error(f"Unexpected error processing response: {e}")
raise
def _is_retryable_error(self, error: Exception) -> bool:
"""
ENHANCEMENT: Intelligent error classification for retry logic.
Determines if an error is retryable based on its type and status code.
This prevents wasting time retrying errors that will never succeed
(like authentication errors) while ensuring transient errors are retried.
Retryable errors:
- Network connection errors (temporary network issues)
- Timeouts (server might be temporarily overloaded)
- Server errors (5xx status codes - server-side issues)
- Rate limiting (429 status - temporary throttling)
Non-retryable errors:
- Authentication errors (401, 403 - won't fix with retry)
- Bad request errors (400 - malformed request)
- Not found errors (404 - resource doesn't exist)
"""
if isinstance(error, requests.exceptions.ConnectionError):
return True # Network issues are usually temporary
if isinstance(error, requests.exceptions.Timeout):
return True # Timeouts might resolve on retry
if isinstance(error, requests.exceptions.HTTPError):
# Only retry on server errors (5xx) or rate limits (429)
if hasattr(error, "response") and error.response is not None:
status_code = error.response.status_code
return status_code >= 500 or status_code == 429
return False
if isinstance(
error, (aiohttp.ClientConnectionError, aiohttp.ServerTimeoutError)
):
return True # Async network/timeout errors are retryable
if isinstance(error, aiohttp.ClientResponseError):
return error.status >= 500 or error.status == 429
return False # All other errors are non-retryable
def _retry_request_sync(self, request_func, *args, **kwargs):
"""Synchronous retry logic with exponential backoff."""
"""
ENHANCEMENT: Synchronous retry logic with intelligent error classification.
Uses exponential backoff with jitter to avoid thundering herd problems.
The wait time increases exponentially but is capped at 30 seconds to
prevent excessive delays. Only retries errors that are likely to succeed
on subsequent attempts.
"""
for attempt in range(self.max_retries):
try:
return request_func(*args, **kwargs)
except (requests.exceptions.RequestException, Exception) as e:
if attempt == self.max_retries - 1:
except Exception as e:
if attempt == self.max_retries - 1 or not self._is_retryable_error(e):
raise
wait_time = (2**attempt) + 0.5
# PERFORMANCE OPTIMIZATION: Exponential backoff with cap
# Prevents overwhelming the server while ensuring reasonable retry delays
wait_time = min((2**attempt) + 0.5, 30) # Cap at 30 seconds
log.warning(
f"Request failed (attempt {attempt + 1}/{self.max_retries}): {e}. Retrying in {wait_time}s..."
f"Retryable error (attempt {attempt + 1}/{self.max_retries}): {e}. "
f"Retrying in {wait_time}s..."
)
time.sleep(wait_time)
async def _retry_request_async(self, request_func, *args, **kwargs):
"""Async retry logic with exponential backoff."""
"""
ENHANCEMENT: Async retry logic with intelligent error classification.
Async version of retry logic that doesn't block the event loop during
wait periods. Uses the same exponential backoff strategy as sync version.
"""
for attempt in range(self.max_retries):
try:
return await request_func(*args, **kwargs)
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
if attempt == self.max_retries - 1:
except Exception as e:
if attempt == self.max_retries - 1 or not self._is_retryable_error(e):
raise
wait_time = (2**attempt) + 0.5
# PERFORMANCE OPTIMIZATION: Non-blocking exponential backoff
wait_time = min((2**attempt) + 0.5, 30) # Cap at 30 seconds
log.warning(
f"Request failed (attempt {attempt + 1}/{self.max_retries}): {e}. Retrying in {wait_time}s..."
f"Retryable error (attempt {attempt + 1}/{self.max_retries}): {e}. "
f"Retrying in {wait_time}s..."
)
await asyncio.sleep(wait_time)
await asyncio.sleep(wait_time) # Non-blocking wait
def _upload_file(self) -> str:
"""Uploads the file to Mistral for OCR processing (sync version)."""
"""
PERFORMANCE OPTIMIZATION: Enhanced file upload with streaming consideration.
Uploads the file to Mistral for OCR processing (sync version).
Uses context manager for file handling to ensure proper resource cleanup.
Although streaming is not enabled for this endpoint, the file is opened
in a context manager to minimize memory usage duration.
"""
log.info("Uploading file to Mistral API")
url = f"{self.BASE_API_URL}/files"
file_name = os.path.basename(self.file_path)
def upload_request():
# MEMORY OPTIMIZATION: Use context manager to minimize file handle lifetime
# This ensures the file is closed immediately after reading, reducing memory usage
with open(self.file_path, "rb") as f:
files = {"file": (file_name, f, "application/pdf")}
files = {"file": (self.file_name, f, "application/pdf")}
data = {"purpose": "ocr"}
# NOTE: stream=False is required for this endpoint
# The Mistral API doesn't support chunked uploads for this endpoint
response = requests.post(
url,
headers=self.headers,
files=files,
data=data,
timeout=self.timeout,
timeout=self.upload_timeout, # Use specialized upload timeout
stream=False, # Keep as False for this endpoint
)
return self._handle_response(response)
@ -209,7 +305,7 @@ class MistralLoader:
url,
data=writer,
headers=self.headers,
timeout=aiohttp.ClientTimeout(total=self.timeout),
timeout=aiohttp.ClientTimeout(total=self.upload_timeout),
) as response:
return await self._handle_response_async(response)
@ -231,7 +327,7 @@ class MistralLoader:
def url_request():
response = requests.get(
url, headers=signed_url_headers, params=params, timeout=self.timeout
url, headers=signed_url_headers, params=params, timeout=self.url_timeout
)
return self._handle_response(response)
@ -261,7 +357,7 @@ class MistralLoader:
url,
headers=headers,
params=params,
timeout=aiohttp.ClientTimeout(total=self.timeout),
timeout=aiohttp.ClientTimeout(total=self.url_timeout),
) as response:
return await self._handle_response_async(response)
@ -294,7 +390,7 @@ class MistralLoader:
def ocr_request():
response = requests.post(
url, headers=ocr_headers, json=payload, timeout=self.timeout
url, headers=ocr_headers, json=payload, timeout=self.ocr_timeout
)
return self._handle_response(response)
@ -336,7 +432,7 @@ class MistralLoader:
url,
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=self.timeout),
timeout=aiohttp.ClientTimeout(total=self.ocr_timeout),
) as response:
ocr_response = await self._handle_response_async(response)
@ -353,7 +449,9 @@ class MistralLoader:
url = f"{self.BASE_API_URL}/files/{file_id}"
try:
response = requests.delete(url, headers=self.headers, timeout=30)
response = requests.delete(
url, headers=self.headers, timeout=self.cleanup_timeout
)
delete_response = self._handle_response(response)
log.info(f"File deleted successfully: {delete_response}")
except Exception as e:
@ -372,7 +470,7 @@ class MistralLoader:
url=f"{self.BASE_API_URL}/files/{file_id}",
headers=self.headers,
timeout=aiohttp.ClientTimeout(
total=30
total=self.cleanup_timeout
), # Shorter timeout for cleanup
) as response:
return await self._handle_response_async(response)
@ -388,29 +486,39 @@ class MistralLoader:
async def _get_session(self):
"""Context manager for HTTP session with optimized settings."""
connector = aiohttp.TCPConnector(
limit=10, # Total connection limit
limit_per_host=5, # Per-host connection limit
ttl_dns_cache=300, # DNS cache TTL
limit=20, # Increased total connection limit for better throughput
limit_per_host=10, # Increased per-host limit for API endpoints
ttl_dns_cache=600, # Longer DNS cache TTL (10 minutes)
use_dns_cache=True,
keepalive_timeout=30,
keepalive_timeout=60, # Increased keepalive for connection reuse
enable_cleanup_closed=True,
force_close=False, # Allow connection reuse
resolver=aiohttp.AsyncResolver(), # Use async DNS resolver
)
timeout = aiohttp.ClientTimeout(
total=self.timeout,
connect=30, # Connection timeout
sock_read=60, # Socket read timeout
)
async with aiohttp.ClientSession(
connector=connector,
timeout=aiohttp.ClientTimeout(total=self.timeout),
timeout=timeout,
headers={"User-Agent": "OpenWebUI-MistralLoader/2.0"},
raise_for_status=False, # We handle status codes manually
) as session:
yield session
def _process_results(self, ocr_response: Dict[str, Any]) -> List[Document]:
"""Process OCR results into Document objects with enhanced metadata."""
"""Process OCR results into Document objects with enhanced metadata and memory efficiency."""
pages_data = ocr_response.get("pages")
if not pages_data:
log.warning("No pages found in OCR response.")
return [
Document(
page_content="No text content found", metadata={"error": "no_pages"}
page_content="No text content found",
metadata={"error": "no_pages", "file_name": self.file_name},
)
]
@ -418,41 +526,44 @@ class MistralLoader:
total_pages = len(pages_data)
skipped_pages = 0
# Process pages in a memory-efficient way
for page_data in pages_data:
page_content = page_data.get("markdown")
page_index = page_data.get("index") # API uses 0-based index
if page_content is not None and page_index is not None:
# Clean up content efficiently
cleaned_content = (
page_content.strip()
if isinstance(page_content, str)
else str(page_content)
if page_content is None or page_index is None:
skipped_pages += 1
self._debug_log(
f"Skipping page due to missing 'markdown' or 'index'. Data keys: {list(page_data.keys())}"
)
continue
if cleaned_content: # Only add non-empty pages
# Clean up content efficiently with early exit for empty content
if isinstance(page_content, str):
cleaned_content = page_content.strip()
else:
cleaned_content = str(page_content).strip()
if not cleaned_content:
skipped_pages += 1
self._debug_log(f"Skipping empty page {page_index}")
continue
# Create document with optimized metadata
documents.append(
Document(
page_content=cleaned_content,
metadata={
"page": page_index, # 0-based index from API
"page_label": page_index
+ 1, # 1-based label for convenience
"page_label": page_index + 1, # 1-based label for convenience
"total_pages": total_pages,
"file_name": self.file_name,
"file_size": self.file_size,
"processing_engine": "mistral-ocr",
"content_length": len(cleaned_content),
},
)
)
else:
skipped_pages += 1
self._debug_log(f"Skipping empty page {page_index}")
else:
skipped_pages += 1
self._debug_log(
f"Skipping page due to missing 'markdown' or 'index'. Data: {page_data}"
)
if skipped_pages > 0:
log.info(
@ -467,7 +578,11 @@ class MistralLoader:
return [
Document(
page_content="No valid text content found in document",
metadata={"error": "no_valid_pages", "total_pages": total_pages},
metadata={
"error": "no_valid_pages",
"total_pages": total_pages,
"file_name": self.file_name,
},
)
]
@ -585,12 +700,14 @@ class MistralLoader:
@staticmethod
async def load_multiple_async(
loaders: List["MistralLoader"],
max_concurrent: int = 5, # Limit concurrent requests
) -> List[List[Document]]:
"""
Process multiple files concurrently for maximum performance.
Process multiple files concurrently with controlled concurrency.
Args:
loaders: List of MistralLoader instances
max_concurrent: Maximum number of concurrent requests
Returns:
List of document lists, one for each loader
@ -598,11 +715,20 @@ class MistralLoader:
if not loaders:
return []
log.info(f"Starting concurrent processing of {len(loaders)} files")
log.info(
f"Starting concurrent processing of {len(loaders)} files with max {max_concurrent} concurrent"
)
start_time = time.time()
# Process all files concurrently
tasks = [loader.load_async() for loader in loaders]
# Use semaphore to control concurrency
semaphore = asyncio.Semaphore(max_concurrent)
async def process_with_semaphore(loader: "MistralLoader") -> List[Document]:
async with semaphore:
return await loader.load_async()
# Process all files with controlled concurrency
tasks = [process_with_semaphore(loader) for loader in loaders]
results = await asyncio.gather(*tasks, return_exceptions=True)
# Handle any exceptions in results
@ -624,10 +750,18 @@ class MistralLoader:
else:
processed_results.append(result)
# MONITORING: Log comprehensive batch processing statistics
total_time = time.time() - start_time
total_docs = sum(len(docs) for docs in processed_results)
success_count = sum(
1 for result in results if not isinstance(result, Exception)
)
failure_count = len(results) - success_count
log.info(
f"Batch processing completed in {total_time:.2f}s, produced {total_docs} total documents"
f"Batch processing completed in {total_time:.2f}s: "
f"{success_count} files succeeded, {failure_count} files failed, "
f"produced {total_docs} total documents"
)
return processed_results

View file

@ -3,10 +3,19 @@ import logging
import time # for measuring elapsed time
from pinecone import Pinecone, ServerlessSpec
# Add gRPC support for better performance (Pinecone best practice)
try:
from pinecone.grpc import PineconeGRPC
GRPC_AVAILABLE = True
except ImportError:
GRPC_AVAILABLE = False
import asyncio # for async upserts
import functools # for partial binding in async tasks
import concurrent.futures # for parallel batch upserts
import random # for jitter in retry backoff
from open_webui.retrieval.vector.main import (
VectorDBBase,
@ -47,7 +56,24 @@ class PineconeClient(VectorDBBase):
self.cloud = PINECONE_CLOUD
# Initialize Pinecone client for improved performance
self.client = Pinecone(api_key=self.api_key)
if GRPC_AVAILABLE:
# Use gRPC client for better performance (Pinecone recommendation)
self.client = PineconeGRPC(
api_key=self.api_key,
pool_threads=20, # Improved connection pool size
timeout=30, # Reasonable timeout for operations
)
self.using_grpc = True
log.info("Using Pinecone gRPC client for optimal performance")
else:
# Fallback to HTTP client with enhanced connection pooling
self.client = Pinecone(
api_key=self.api_key,
pool_threads=20, # Improved connection pool size
timeout=30, # Reasonable timeout for operations
)
self.using_grpc = False
log.info("Using Pinecone HTTP client (gRPC not available)")
# Persistent executor for batch operations
self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
@ -91,12 +117,53 @@ class PineconeClient(VectorDBBase):
log.info(f"Using existing Pinecone index '{self.index_name}'")
# Connect to the index
self.index = self.client.Index(self.index_name)
self.index = self.client.Index(
self.index_name,
pool_threads=20, # Enhanced connection pool for index operations
)
except Exception as e:
log.error(f"Failed to initialize Pinecone index: {e}")
raise RuntimeError(f"Failed to initialize Pinecone index: {e}")
def _retry_pinecone_operation(self, operation_func, max_retries=3):
"""Retry Pinecone operations with exponential backoff for rate limits and network issues."""
for attempt in range(max_retries):
try:
return operation_func()
except Exception as e:
error_str = str(e).lower()
# Check if it's a retryable error (rate limits, network issues, timeouts)
is_retryable = any(
keyword in error_str
for keyword in [
"rate limit",
"quota",
"timeout",
"network",
"connection",
"unavailable",
"internal error",
"429",
"500",
"502",
"503",
"504",
]
)
if not is_retryable or attempt == max_retries - 1:
# Don't retry for non-retryable errors or on final attempt
raise
# Exponential backoff with jitter
delay = (2**attempt) + random.uniform(0, 1)
log.warning(
f"Pinecone operation failed (attempt {attempt + 1}/{max_retries}), "
f"retrying in {delay:.2f}s: {e}"
)
time.sleep(delay)
def _create_points(
self, items: List[VectorItem], collection_name_with_prefix: str
) -> List[Dict[str, Any]]:
@ -223,7 +290,8 @@ class PineconeClient(VectorDBBase):
elapsed = time.time() - start_time
log.debug(f"Insert of {len(points)} vectors took {elapsed:.2f} seconds")
log.info(
f"Successfully inserted {len(points)} vectors in parallel batches into '{collection_name_with_prefix}'"
f"Successfully inserted {len(points)} vectors in parallel batches "
f"into '{collection_name_with_prefix}'"
)
def upsert(self, collection_name: str, items: List[VectorItem]) -> None:
@ -254,7 +322,8 @@ class PineconeClient(VectorDBBase):
elapsed = time.time() - start_time
log.debug(f"Upsert of {len(points)} vectors took {elapsed:.2f} seconds")
log.info(
f"Successfully upserted {len(points)} vectors in parallel batches into '{collection_name_with_prefix}'"
f"Successfully upserted {len(points)} vectors in parallel batches "
f"into '{collection_name_with_prefix}'"
)
async def insert_async(self, collection_name: str, items: List[VectorItem]) -> None:
@ -285,7 +354,8 @@ class PineconeClient(VectorDBBase):
log.error(f"Error in async insert batch: {result}")
raise result
log.info(
f"Successfully async inserted {len(points)} vectors in batches into '{collection_name_with_prefix}'"
f"Successfully async inserted {len(points)} vectors in batches "
f"into '{collection_name_with_prefix}'"
)
async def upsert_async(self, collection_name: str, items: List[VectorItem]) -> None:
@ -316,7 +386,8 @@ class PineconeClient(VectorDBBase):
log.error(f"Error in async upsert batch: {result}")
raise result
log.info(
f"Successfully async upserted {len(points)} vectors in batches into '{collection_name_with_prefix}'"
f"Successfully async upserted {len(points)} vectors in batches "
f"into '{collection_name_with_prefix}'"
)
def search(
@ -457,10 +528,12 @@ class PineconeClient(VectorDBBase):
# This is a limitation of Pinecone - be careful with ID uniqueness
self.index.delete(ids=batch_ids)
log.debug(
f"Deleted batch of {len(batch_ids)} vectors by ID from '{collection_name_with_prefix}'"
f"Deleted batch of {len(batch_ids)} vectors by ID "
f"from '{collection_name_with_prefix}'"
)
log.info(
f"Successfully deleted {len(ids)} vectors by ID from '{collection_name_with_prefix}'"
f"Successfully deleted {len(ids)} vectors by ID "
f"from '{collection_name_with_prefix}'"
)
elif filter:

View file

@ -1,10 +1,20 @@
import logging
from typing import Optional, List
from typing import Optional, Literal
import requests
from open_webui.retrieval.web.main import SearchResult, get_filtered_results
from open_webui.env import SRC_LOG_LEVELS
MODELS = Literal[
"sonar",
"sonar-pro",
"sonar-reasoning",
"sonar-reasoning-pro",
"sonar-deep-research",
]
SEARCH_CONTEXT_USAGE_LEVELS = Literal["low", "medium", "high"]
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
@ -14,6 +24,8 @@ def search_perplexity(
query: str,
count: int,
filter_list: Optional[list[str]] = None,
model: MODELS = "sonar",
search_context_usage: SEARCH_CONTEXT_USAGE_LEVELS = "medium",
) -> list[SearchResult]:
"""Search using Perplexity API and return the results as a list of SearchResult objects.
@ -21,6 +33,9 @@ def search_perplexity(
api_key (str): A Perplexity API key
query (str): The query to search for
count (int): Maximum number of results to return
filter_list (Optional[list[str]]): List of domains to filter results
model (str): The Perplexity model to use (sonar, sonar-pro)
search_context_usage (str): Search context usage level (low, medium, high)
"""
@ -33,7 +48,7 @@ def search_perplexity(
# Create payload for the API call
payload = {
"model": "sonar",
"model": model,
"messages": [
{
"role": "system",
@ -43,6 +58,9 @@ def search_perplexity(
],
"temperature": 0.2, # Lower temperature for more factual responses
"stream": False,
"web_search_options": {
"search_context_usage": search_context_usage,
},
}
headers = {

View file

@ -124,9 +124,8 @@ async def get_note_by_id(request: Request, id: str, user=Depends(get_verified_us
status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND
)
if (
user.role != "admin"
and user.id != note.user_id
if user.role != "admin" or (
user.id != note.user_id
and not has_access(user.id, type="read", access_control=note.access_control)
):
raise HTTPException(
@ -159,9 +158,8 @@ async def update_note_by_id(
status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND
)
if (
user.role != "admin"
and user.id != note.user_id
if user.role != "admin" or (
user.id != note.user_id
and not has_access(user.id, type="write", access_control=note.access_control)
):
raise HTTPException(
@ -199,9 +197,8 @@ async def delete_note_by_id(request: Request, id: str, user=Depends(get_verified
status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND
)
if (
user.role != "admin"
and user.id != note.user_id
if user.role != "admin" or (
user.id != note.user_id
and not has_access(user.id, type="write", access_control=note.access_control)
):
raise HTTPException(

View file

@ -887,6 +887,88 @@ async def generate_chat_completion(
await session.close()
async def embeddings(request: Request, form_data: dict, user):
"""
Calls the embeddings endpoint for OpenAI-compatible providers.
Args:
request (Request): The FastAPI request context.
form_data (dict): OpenAI-compatible embeddings payload.
user (UserModel): The authenticated user.
Returns:
dict: OpenAI-compatible embeddings response.
"""
idx = 0
# Prepare payload/body
body = json.dumps(form_data)
# Find correct backend url/key based on model
await get_all_models(request, user=user)
model_id = form_data.get("model")
models = request.app.state.OPENAI_MODELS
if model_id in models:
idx = models[model_id]["urlIdx"]
url = request.app.state.config.OPENAI_API_BASE_URLS[idx]
key = request.app.state.config.OPENAI_API_KEYS[idx]
r = None
session = None
streaming = False
try:
session = aiohttp.ClientSession(trust_env=True)
r = await session.request(
method="POST",
url=f"{url}/embeddings",
data=body,
headers={
"Authorization": f"Bearer {key}",
"Content-Type": "application/json",
**(
{
"X-OpenWebUI-User-Name": user.name,
"X-OpenWebUI-User-Id": user.id,
"X-OpenWebUI-User-Email": user.email,
"X-OpenWebUI-User-Role": user.role,
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
),
},
)
r.raise_for_status()
if "text/event-stream" in r.headers.get("Content-Type", ""):
streaming = True
return StreamingResponse(
r.content,
status_code=r.status,
headers=dict(r.headers),
background=BackgroundTask(
cleanup_response, response=r, session=session
),
)
else:
response_data = await r.json()
return response_data
except Exception as e:
log.exception(e)
detail = None
if r is not None:
try:
res = await r.json()
if "error" in res:
detail = f"External: {res['error']['message'] if 'message' in res['error'] else res['error']}"
except Exception:
detail = f"External: {e}"
raise HTTPException(
status_code=r.status if r else 500,
detail=detail if detail else "Open WebUI: Server Connection Error",
)
finally:
if not streaming and session:
if r:
r.close()
await session.close()
@router.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
"""

View file

@ -467,6 +467,8 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
"BING_SEARCH_V7_SUBSCRIPTION_KEY": request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY,
"EXA_API_KEY": request.app.state.config.EXA_API_KEY,
"PERPLEXITY_API_KEY": request.app.state.config.PERPLEXITY_API_KEY,
"PERPLEXITY_MODEL": request.app.state.config.PERPLEXITY_MODEL,
"PERPLEXITY_SEARCH_CONTEXT_USAGE": request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE,
"SOUGOU_API_SID": request.app.state.config.SOUGOU_API_SID,
"SOUGOU_API_SK": request.app.state.config.SOUGOU_API_SK,
"WEB_LOADER_ENGINE": request.app.state.config.WEB_LOADER_ENGINE,
@ -520,6 +522,8 @@ class WebConfig(BaseModel):
BING_SEARCH_V7_SUBSCRIPTION_KEY: Optional[str] = None
EXA_API_KEY: Optional[str] = None
PERPLEXITY_API_KEY: Optional[str] = None
PERPLEXITY_MODEL: Optional[str] = None
PERPLEXITY_SEARCH_CONTEXT_USAGE: Optional[str] = None
SOUGOU_API_SID: Optional[str] = None
SOUGOU_API_SK: Optional[str] = None
WEB_LOADER_ENGINE: Optional[str] = None
@ -907,6 +911,10 @@ async def update_rag_config(
)
request.app.state.config.EXA_API_KEY = form_data.web.EXA_API_KEY
request.app.state.config.PERPLEXITY_API_KEY = form_data.web.PERPLEXITY_API_KEY
request.app.state.config.PERPLEXITY_MODEL = form_data.web.PERPLEXITY_MODEL
request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = (
form_data.web.PERPLEXITY_SEARCH_CONTEXT_USAGE
)
request.app.state.config.SOUGOU_API_SID = form_data.web.SOUGOU_API_SID
request.app.state.config.SOUGOU_API_SK = form_data.web.SOUGOU_API_SK
@ -1030,6 +1038,8 @@ async def update_rag_config(
"BING_SEARCH_V7_SUBSCRIPTION_KEY": request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY,
"EXA_API_KEY": request.app.state.config.EXA_API_KEY,
"PERPLEXITY_API_KEY": request.app.state.config.PERPLEXITY_API_KEY,
"PERPLEXITY_MODEL": request.app.state.config.PERPLEXITY_MODEL,
"PERPLEXITY_SEARCH_CONTEXT_USAGE": request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE,
"SOUGOU_API_SID": request.app.state.config.SOUGOU_API_SID,
"SOUGOU_API_SK": request.app.state.config.SOUGOU_API_SK,
"WEB_LOADER_ENGINE": request.app.state.config.WEB_LOADER_ENGINE,
@ -1740,19 +1750,14 @@ def search_web(request: Request, engine: str, query: str) -> list[SearchResult]:
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
)
elif engine == "exa":
return search_exa(
request.app.state.config.EXA_API_KEY,
query,
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
)
elif engine == "perplexity":
return search_perplexity(
request.app.state.config.PERPLEXITY_API_KEY,
query,
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
model=request.app.state.config.PERPLEXITY_MODEL,
search_context_usage=request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE,
)
elif engine == "sougou":
if (

View file

@ -9,6 +9,7 @@ import re
from open_webui.utils.chat import generate_chat_completion
from open_webui.utils.task import (
title_generation_template,
follow_up_generation_template,
query_generation_template,
image_prompt_generation_template,
autocomplete_generation_template,
@ -25,6 +26,7 @@ from open_webui.utils.task import get_task_model_id
from open_webui.config import (
DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE,
DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE,
DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE,
@ -58,6 +60,8 @@ async def get_task_config(request: Request, user=Depends(get_verified_user)):
"ENABLE_AUTOCOMPLETE_GENERATION": request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
"AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH": request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
"TAGS_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE,
"FOLLOW_UP_GENERATION_PROMPT_TEMPLATE": request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
"ENABLE_FOLLOW_UP_GENERATION": request.app.state.config.ENABLE_FOLLOW_UP_GENERATION,
"ENABLE_TAGS_GENERATION": request.app.state.config.ENABLE_TAGS_GENERATION,
"ENABLE_TITLE_GENERATION": request.app.state.config.ENABLE_TITLE_GENERATION,
"ENABLE_SEARCH_QUERY_GENERATION": request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION,
@ -76,6 +80,8 @@ class TaskConfigForm(BaseModel):
ENABLE_AUTOCOMPLETE_GENERATION: bool
AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH: int
TAGS_GENERATION_PROMPT_TEMPLATE: str
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE: str
ENABLE_FOLLOW_UP_GENERATION: bool
ENABLE_TAGS_GENERATION: bool
ENABLE_SEARCH_QUERY_GENERATION: bool
ENABLE_RETRIEVAL_QUERY_GENERATION: bool
@ -94,6 +100,13 @@ async def update_task_config(
form_data.TITLE_GENERATION_PROMPT_TEMPLATE
)
request.app.state.config.ENABLE_FOLLOW_UP_GENERATION = (
form_data.ENABLE_FOLLOW_UP_GENERATION
)
request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = (
form_data.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
)
request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = (
form_data.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
)
@ -133,6 +146,8 @@ async def update_task_config(
"AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH": request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
"TAGS_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE,
"ENABLE_TAGS_GENERATION": request.app.state.config.ENABLE_TAGS_GENERATION,
"ENABLE_FOLLOW_UP_GENERATION": request.app.state.config.ENABLE_FOLLOW_UP_GENERATION,
"FOLLOW_UP_GENERATION_PROMPT_TEMPLATE": request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
"ENABLE_SEARCH_QUERY_GENERATION": request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION,
"ENABLE_RETRIEVAL_QUERY_GENERATION": request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION,
"QUERY_GENERATION_PROMPT_TEMPLATE": request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE,
@ -231,6 +246,86 @@ async def generate_title(
)
@router.post("/follow_up/completions")
async def generate_follow_ups(
request: Request, form_data: dict, user=Depends(get_verified_user)
):
if not request.app.state.config.ENABLE_FOLLOW_UP_GENERATION:
return JSONResponse(
status_code=status.HTTP_200_OK,
content={"detail": "Follow-up generation is disabled"},
)
if getattr(request.state, "direct", False) and hasattr(request.state, "model"):
models = {
request.state.model["id"]: request.state.model,
}
else:
models = request.app.state.MODELS
model_id = form_data["model"]
if model_id not in models:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Model not found",
)
# Check if the user has a custom task model
# If the user has a custom task model, use that model
task_model_id = get_task_model_id(
model_id,
request.app.state.config.TASK_MODEL,
request.app.state.config.TASK_MODEL_EXTERNAL,
models,
)
log.debug(
f"generating chat title using model {task_model_id} for user {user.email} "
)
if request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE != "":
template = request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
else:
template = DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
content = follow_up_generation_template(
template,
form_data["messages"],
{
"name": user.name,
"location": user.info.get("location") if user.info else None,
},
)
payload = {
"model": task_model_id,
"messages": [{"role": "user", "content": content}],
"stream": False,
"metadata": {
**(request.state.metadata if hasattr(request.state, "metadata") else {}),
"task": str(TASKS.FOLLOW_UP_GENERATION),
"task_body": form_data,
"chat_id": form_data.get("chat_id", None),
},
}
# Process the payload through the pipeline
try:
payload = await process_pipeline_inlet_filter(request, payload, user, models)
except Exception as e:
raise e
try:
return await generate_chat_completion(request, form_data=payload, user=user)
except Exception as e:
log.error("Exception occurred", exc_info=True)
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": "An internal error has occurred."},
)
@router.post("/tags/completions")
async def generate_chat_tags(
request: Request, form_data: dict, user=Depends(get_verified_user)

View file

@ -165,22 +165,6 @@ async def update_default_user_permissions(
return request.app.state.config.USER_PERMISSIONS
############################
# UpdateUserRole
############################
@router.post("/update/role", response_model=Optional[UserModel])
async def update_user_role(form_data: UserRoleUpdateForm, user=Depends(get_admin_user)):
if user.id != form_data.id and form_data.id != Users.get_first_user().id:
return Users.update_user_role_by_id(form_data.id, form_data.role)
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACTION_PROHIBITED,
)
############################
# GetUserSettingsBySessionUser
############################
@ -333,11 +317,22 @@ async def update_user_by_id(
# Prevent modification of the primary admin user by other admins
try:
first_user = Users.get_first_user()
if first_user and user_id == first_user.id and session_user.id != user_id:
if first_user:
if user_id == first_user.id:
if session_user.id != user_id:
# If the user trying to update is the primary admin, and they are not the primary admin themselves
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACTION_PROHIBITED,
)
if form_data.role != "admin":
# If the primary admin is trying to change their own role, prevent it
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACTION_PROHIBITED,
)
except Exception as e:
log.error(f"Error checking primary admin status: {e}")
raise HTTPException(
@ -365,6 +360,7 @@ async def update_user_by_id(
updated_user = Users.update_user_by_id(
user_id,
{
"role": form_data.role,
"name": form_data.name,
"email": form_data.email.lower(),
"profile_image_url": form_data.profile_image_url,

View file

@ -320,12 +320,7 @@ async def chat_completed(request: Request, form_data: dict, user: Any):
extra_params = {
"__event_emitter__": get_event_emitter(metadata),
"__event_call__": get_event_call(metadata),
"__user__": {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
},
"__user__": user.model_dump() if isinstance(user, UserModel) else {},
"__metadata__": metadata,
"__request__": request,
"__model__": model,
@ -424,12 +419,7 @@ async def chat_action(request: Request, action_id: str, form_data: dict, user: A
params[key] = value
if "__user__" in sig.parameters:
__user__ = {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
}
__user__ = (user.model_dump() if isinstance(user, UserModel) else {},)
try:
if hasattr(function_module, "UserValves"):

View file

@ -0,0 +1,90 @@
import random
import logging
import sys
from fastapi import Request
from open_webui.models.users import UserModel
from open_webui.models.models import Models
from open_webui.utils.models import check_model_access
from open_webui.env import SRC_LOG_LEVELS, GLOBAL_LOG_LEVEL, BYPASS_MODEL_ACCESS_CONTROL
from open_webui.routers.openai import embeddings as openai_embeddings
from open_webui.routers.ollama import (
embeddings as ollama_embeddings,
GenerateEmbeddingsForm,
)
from open_webui.utils.payload import convert_embedding_payload_openai_to_ollama
from open_webui.utils.response import convert_embedding_response_ollama_to_openai
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
async def generate_embeddings(
request: Request,
form_data: dict,
user: UserModel,
bypass_filter: bool = False,
):
"""
Dispatch and handle embeddings generation based on the model type (OpenAI, Ollama).
Args:
request (Request): The FastAPI request context.
form_data (dict): The input data sent to the endpoint.
user (UserModel): The authenticated user.
bypass_filter (bool): If True, disables access filtering (default False).
Returns:
dict: The embeddings response, following OpenAI API compatibility.
"""
if BYPASS_MODEL_ACCESS_CONTROL:
bypass_filter = True
# Attach extra metadata from request.state if present
if hasattr(request.state, "metadata"):
if "metadata" not in form_data:
form_data["metadata"] = request.state.metadata
else:
form_data["metadata"] = {
**form_data["metadata"],
**request.state.metadata,
}
# If "direct" flag present, use only that model
if getattr(request.state, "direct", False) and hasattr(request.state, "model"):
models = {
request.state.model["id"]: request.state.model,
}
else:
models = request.app.state.MODELS
model_id = form_data.get("model")
if model_id not in models:
raise Exception("Model not found")
model = models[model_id]
# Access filtering
if not getattr(request.state, "direct", False):
if not bypass_filter and user.role == "user":
check_model_access(user, model)
# Ollama backend
if model.get("owned_by") == "ollama":
ollama_payload = convert_embedding_payload_openai_to_ollama(form_data)
response = await ollama_embeddings(
request=request,
form_data=GenerateEmbeddingsForm(**ollama_payload),
user=user,
)
return convert_embedding_response_ollama_to_openai(response)
# Default: OpenAI or compatible backend
return await openai_embeddings(
request=request,
form_data=form_data,
user=user,
)

View file

@ -32,6 +32,7 @@ from open_webui.socket.main import (
from open_webui.routers.tasks import (
generate_queries,
generate_title,
generate_follow_ups,
generate_image_prompt,
generate_chat_tags,
)
@ -726,12 +727,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
extra_params = {
"__event_emitter__": event_emitter,
"__event_call__": event_call,
"__user__": {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
},
"__user__": user.model_dump() if isinstance(user, UserModel) else {},
"__metadata__": metadata,
"__request__": request,
"__model__": model,
@ -1048,6 +1044,59 @@ async def process_chat_response(
)
if tasks and messages:
if (
TASKS.FOLLOW_UP_GENERATION in tasks
and tasks[TASKS.FOLLOW_UP_GENERATION]
):
res = await generate_follow_ups(
request,
{
"model": message["model"],
"messages": messages,
"message_id": metadata["message_id"],
"chat_id": metadata["chat_id"],
},
user,
)
if res and isinstance(res, dict):
if len(res.get("choices", [])) == 1:
follow_ups_string = (
res.get("choices", [])[0]
.get("message", {})
.get("content", "")
)
else:
follow_ups_string = ""
follow_ups_string = follow_ups_string[
follow_ups_string.find("{") : follow_ups_string.rfind("}")
+ 1
]
try:
follow_ups = json.loads(follow_ups_string).get(
"follow_ups", []
)
Chats.upsert_message_to_chat_by_id_and_message_id(
metadata["chat_id"],
metadata["message_id"],
{
"followUps": follow_ups,
},
)
await event_emitter(
{
"type": "chat:message:follow_ups",
"data": {
"follow_ups": follow_ups,
},
}
)
except Exception as e:
pass
if TASKS.TITLE_GENERATION in tasks:
if tasks[TASKS.TITLE_GENERATION]:
res = await generate_title(
@ -1273,12 +1322,7 @@ async def process_chat_response(
extra_params = {
"__event_emitter__": event_emitter,
"__event_call__": event_caller,
"__user__": {
"id": user.id,
"email": user.email,
"name": user.name,
"role": user.role,
},
"__user__": user.model_dump() if isinstance(user, UserModel) else {},
"__metadata__": metadata,
"__request__": request,
"__model__": model,

View file

@ -538,7 +538,7 @@ class OAuthManager:
# Redirect back to the frontend with the JWT token
redirect_base_url = request.app.state.config.WEBUI_URL or request.base_url
if redirect_base_url.endswith("/"):
if isinstance(redirect_base_url, str) and redirect_base_url.endswith("/"):
redirect_base_url = redirect_base_url[:-1]
redirect_url = f"{redirect_base_url}/auth#token={jwt_token}"

View file

@ -329,3 +329,32 @@ def convert_payload_openai_to_ollama(openai_payload: dict) -> dict:
ollama_payload["format"] = format
return ollama_payload
def convert_embedding_payload_openai_to_ollama(openai_payload: dict) -> dict:
"""
Convert an embeddings request payload from OpenAI format to Ollama format.
Args:
openai_payload (dict): The original payload designed for OpenAI API usage.
Returns:
dict: A payload compatible with the Ollama API embeddings endpoint.
"""
ollama_payload = {"model": openai_payload.get("model")}
input_value = openai_payload.get("input")
# Ollama expects 'input' as a list, and 'prompt' as a single string.
if isinstance(input_value, list):
ollama_payload["input"] = input_value
ollama_payload["prompt"] = "\n".join(str(x) for x in input_value)
else:
ollama_payload["input"] = [input_value]
ollama_payload["prompt"] = str(input_value)
# Optionally forward other fields if present
for optional_key in ("options", "truncate", "keep_alive"):
if optional_key in openai_payload:
ollama_payload[optional_key] = openai_payload[optional_key]
return ollama_payload

View file

@ -125,3 +125,64 @@ async def convert_streaming_response_ollama_to_openai(ollama_streaming_response)
yield line
yield "data: [DONE]\n\n"
def convert_embedding_response_ollama_to_openai(response) -> dict:
"""
Convert the response from Ollama embeddings endpoint to the OpenAI-compatible format.
Args:
response (dict): The response from the Ollama API,
e.g. {"embedding": [...], "model": "..."}
or {"embeddings": [{"embedding": [...], "index": 0}, ...], "model": "..."}
Returns:
dict: Response adapted to OpenAI's embeddings API format.
e.g. {
"object": "list",
"data": [
{"object": "embedding", "embedding": [...], "index": 0},
...
],
"model": "...",
}
"""
# Ollama batch-style output
if isinstance(response, dict) and "embeddings" in response:
openai_data = []
for i, emb in enumerate(response["embeddings"]):
openai_data.append(
{
"object": "embedding",
"embedding": emb.get("embedding"),
"index": emb.get("index", i),
}
)
return {
"object": "list",
"data": openai_data,
"model": response.get("model"),
}
# Ollama single output
elif isinstance(response, dict) and "embedding" in response:
return {
"object": "list",
"data": [
{
"object": "embedding",
"embedding": response["embedding"],
"index": 0,
}
],
"model": response.get("model"),
}
# Already OpenAI-compatible?
elif (
isinstance(response, dict)
and "data" in response
and isinstance(response["data"], list)
):
return response
# Fallback: return as is if unrecognized
return response

View file

@ -207,6 +207,24 @@ def title_generation_template(
return template
def follow_up_generation_template(
template: str, messages: list[dict], user: Optional[dict] = None
) -> str:
prompt = get_last_user_message(messages)
template = replace_prompt_variable(template, prompt)
template = replace_messages_variable(template, messages)
template = prompt_template(
template,
**(
{"user_name": user.get("name"), "user_location": user.get("location")}
if user
else {}
),
)
return template
def tags_generation_template(
template: str, messages: list[dict], user: Optional[dict] = None
) -> str:

View file

@ -1,5 +1,5 @@
fastapi==0.115.7
uvicorn[standard]==0.34.0
uvicorn[standard]==0.34.2
pydantic==2.10.6
python-multipart==0.0.20
@ -76,13 +76,13 @@ pandas==2.2.3
openpyxl==3.1.5
pyxlsb==1.0.10
xlrd==2.0.1
validators==0.34.0
validators==0.35.0
psutil
sentencepiece
soundfile==0.13.1
azure-ai-documentintelligence==1.0.0
azure-ai-documentintelligence==1.0.2
pillow==11.1.0
pillow==11.2.1
opencv-python-headless==4.11.0.86
rapidocr-onnxruntime==1.4.4
rank-bm25==0.2.2

8
package-lock.json generated
View file

@ -51,7 +51,7 @@
"idb": "^7.1.1",
"js-sha256": "^0.10.1",
"jspdf": "^3.0.0",
"katex": "^0.16.21",
"katex": "^0.16.22",
"kokoro-js": "^1.1.1",
"marked": "^9.1.0",
"mermaid": "^11.6.0",
@ -7930,9 +7930,9 @@
}
},
"node_modules/katex": {
"version": "0.16.21",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz",
"integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==",
"version": "0.16.22",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz",
"integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"

View file

@ -95,7 +95,7 @@
"idb": "^7.1.1",
"js-sha256": "^0.10.1",
"jspdf": "^3.0.0",
"katex": "^0.16.21",
"katex": "^0.16.22",
"kokoro-js": "^1.1.1",
"marked": "^9.1.0",
"mermaid": "^11.6.0",

View file

@ -44,6 +44,10 @@ code {
font-family: 'InstrumentSerif', sans-serif;
}
.marked a {
@apply underline;
}
math {
margin-top: 1rem;
}

View file

@ -336,7 +336,7 @@ export const userSignOut = async () => {
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res;
return res.json();
})
.catch((err) => {
console.error(err);

View file

@ -612,6 +612,78 @@ export const generateTitle = async (
}
};
export const generateFollowUps = async (
token: string = '',
model: string,
messages: string,
chat_id?: string
) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/v1/tasks/follow_ups/completions`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
model: model,
messages: messages,
...(chat_id && { chat_id: chat_id })
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.error(err);
if ('detail' in err) {
error = err.detail;
}
return null;
});
if (error) {
throw error;
}
try {
// Step 1: Safely extract the response string
const response = res?.choices[0]?.message?.content ?? '';
// Step 2: Attempt to fix common JSON format issues like single quotes
const sanitizedResponse = response.replace(/['`]/g, '"'); // Convert single quotes to double quotes for valid JSON
// Step 3: Find the relevant JSON block within the response
const jsonStartIndex = sanitizedResponse.indexOf('{');
const jsonEndIndex = sanitizedResponse.lastIndexOf('}');
// Step 4: Check if we found a valid JSON block (with both `{` and `}`)
if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1);
// Step 5: Parse the JSON block
const parsed = JSON.parse(jsonResponse);
// Step 6: If there's a "follow_ups" key, return the follow_ups array; otherwise, return an empty array
if (parsed && parsed.follow_ups) {
return Array.isArray(parsed.follow_ups) ? parsed.follow_ups : [];
} else {
return [];
}
}
// If no valid JSON block found, return an empty array
return [];
} catch (e) {
// Catch and safely return empty array on any parsing errors
console.error('Failed to parse response: ', e);
return [];
}
};
export const generateTags = async (
token: string = '',
model: string,

View file

@ -393,6 +393,7 @@ export const updateUserById = async (token: string, userId: string, user: UserUp
},
body: JSON.stringify({
profile_image_url: user.profile_image_url,
role: user.role,
email: user.email,
name: user.name,
password: user.password !== '' ? user.password : undefined

View file

@ -49,6 +49,9 @@
let loading = false;
const verifyOllamaHandler = async () => {
// remove trailing slash from url
url = url.replace(/\/$/, '');
const res = await verifyOllamaConnection(localStorage.token, {
url,
key
@ -62,6 +65,9 @@
};
const verifyOpenAIHandler = async () => {
// remove trailing slash from url
url = url.replace(/\/$/, '');
const res = await verifyOpenAIConnection(
localStorage.token,
{

View file

@ -1,6 +1,8 @@
<script>
import { getContext, tick, onMount } from 'svelte';
import { toast } from 'svelte-sonner';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import Leaderboard from './Evaluations/Leaderboard.svelte';
import Feedbacks from './Evaluations/Feedbacks.svelte';
@ -8,7 +10,24 @@
const i18n = getContext('i18n');
let selectedTab = 'leaderboard';
let selectedTab;
$: {
const pathParts = $page.url.pathname.split('/');
const tabFromPath = pathParts[pathParts.length - 1];
selectedTab = ['leaderboard', 'feedbacks'].includes(tabFromPath) ? tabFromPath : 'leaderboard';
}
$: if (selectedTab) {
// scroll to selectedTab
scrollToTab(selectedTab);
}
const scrollToTab = (tabId) => {
const tabElement = document.getElementById(tabId);
if (tabElement) {
tabElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
}
};
let loaded = false;
let feedbacks = [];
@ -27,6 +46,9 @@
}
});
}
// Scroll to the selected tab on mount
scrollToTab(selectedTab);
});
</script>
@ -37,12 +59,13 @@
class="tabs flex flex-row overflow-x-auto gap-2.5 max-w-full lg:gap-1 lg:flex-col lg:flex-none lg:w-40 dark:text-gray-200 text-sm font-medium text-left scrollbar-none"
>
<button
id="leaderboard"
class="px-0.5 py-1 min-w-fit rounded-lg lg:flex-none flex text-right transition {selectedTab ===
'leaderboard'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'leaderboard';
goto('/admin/evaluations/leaderboard');
}}
>
<div class=" self-center mr-2">
@ -63,12 +86,13 @@
</button>
<button
id="feedbacks"
class="px-0.5 py-1 min-w-fit rounded-lg lg:flex-none flex text-right transition {selectedTab ===
'feedbacks'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'feedbacks';
goto('/admin/evaluations/feedbacks');
}}
>
<div class=" self-center mr-2">

View file

@ -1,5 +1,7 @@
<script>
import { getContext, tick, onMount } from 'svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { toast } from 'svelte-sonner';
import { config } from '$lib/stores';
@ -26,6 +28,41 @@
let selectedTab = 'general';
// Get current tab from URL pathname, default to 'general'
$: {
const pathParts = $page.url.pathname.split('/');
const tabFromPath = pathParts[pathParts.length - 1];
selectedTab = [
'general',
'connections',
'models',
'evaluations',
'tools',
'documents',
'web',
'code-execution',
'interface',
'audio',
'images',
'pipelines',
'db'
].includes(tabFromPath)
? tabFromPath
: 'general';
}
$: if (selectedTab) {
// scroll to selectedTab
scrollToTab(selectedTab);
}
const scrollToTab = (tabId) => {
const tabElement = document.getElementById(tabId);
if (tabElement) {
tabElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
}
};
onMount(() => {
const containerElement = document.getElementById('admin-settings-tabs-container');
@ -37,6 +74,9 @@
}
});
}
// Scroll to the selected tab on mount
scrollToTab(selectedTab);
});
</script>
@ -46,12 +86,13 @@
class="tabs flex flex-row overflow-x-auto gap-2.5 max-w-full lg:gap-1 lg:flex-col lg:flex-none lg:w-40 dark:text-gray-200 text-sm font-medium text-left scrollbar-none"
>
<button
id="general"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 lg:flex-none flex text-right transition {selectedTab ===
'general'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'general';
goto('/admin/settings/general');
}}
>
<div class=" self-center mr-2">
@ -72,12 +113,13 @@
</button>
<button
id="connections"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'connections'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'connections';
goto('/admin/settings/connections');
}}
>
<div class=" self-center mr-2">
@ -96,12 +138,13 @@
</button>
<button
id="models"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'models'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'models';
goto('/admin/settings/models');
}}
>
<div class=" self-center mr-2">
@ -122,12 +165,13 @@
</button>
<button
id="evaluations"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'evaluations'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'evaluations';
goto('/admin/settings/evaluations');
}}
>
<div class=" self-center mr-2">
@ -137,12 +181,13 @@
</button>
<button
id="tools"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'tools'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'tools';
goto('/admin/settings/tools');
}}
>
<div class=" self-center mr-2">
@ -163,12 +208,13 @@
</button>
<button
id="documents"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'documents'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'documents';
goto('/admin/settings/documents');
}}
>
<div class=" self-center mr-2">
@ -193,12 +239,13 @@
</button>
<button
id="web"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'web'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'web';
goto('/admin/settings/web');
}}
>
<div class=" self-center mr-2">
@ -217,12 +264,13 @@
</button>
<button
id="code-execution"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'code-execution'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'code-execution';
goto('/admin/settings/code-execution');
}}
>
<div class=" self-center mr-2">
@ -243,12 +291,13 @@
</button>
<button
id="interface"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'interface'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'interface';
goto('/admin/settings/interface');
}}
>
<div class=" self-center mr-2">
@ -269,12 +318,13 @@
</button>
<button
id="audio"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'audio'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'audio';
goto('/admin/settings/audio');
}}
>
<div class=" self-center mr-2">
@ -296,12 +346,13 @@
</button>
<button
id="images"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'images'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'images';
goto('/admin/settings/images');
}}
>
<div class=" self-center mr-2">
@ -322,12 +373,13 @@
</button>
<button
id="pipelines"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'pipelines'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'pipelines';
goto('/admin/settings/pipelines');
}}
>
<div class=" self-center mr-2">
@ -352,12 +404,13 @@
</button>
<button
id="db"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'db'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'db';
goto('/admin/settings/db');
}}
>
<div class=" self-center mr-2">

View file

@ -31,6 +31,8 @@
TASK_MODEL_EXTERNAL: '',
ENABLE_TITLE_GENERATION: true,
TITLE_GENERATION_PROMPT_TEMPLATE: '',
ENABLE_FOLLOW_UP_GENERATION: true,
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE: '',
IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE: '',
ENABLE_AUTOCOMPLETE_GENERATION: true,
AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH: -1,
@ -235,6 +237,32 @@
</div>
{/if}
<div class="mb-2.5 flex w-full items-center justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Follow Up Generation')}
</div>
<Switch bind:state={taskConfig.ENABLE_FOLLOW_UP_GENERATION} />
</div>
{#if taskConfig.ENABLE_FOLLOW_UP_GENERATION}
<div class="mb-2.5">
<div class=" mb-1 text-xs font-medium">{$i18n.t('Follow Up Generation Prompt')}</div>
<Tooltip
content={$i18n.t('Leave empty to use the default prompt, or enter a custom prompt')}
placement="top-start"
>
<Textarea
bind:value={taskConfig.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE}
placeholder={$i18n.t(
'Leave empty to use the default prompt, or enter a custom prompt'
)}
/>
</Tooltip>
</div>
{/if}
<div class="mb-2.5 flex w-full items-center justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Tags Generation')}

View file

@ -446,6 +446,7 @@
</div>
</div>
{:else if webConfig.WEB_SEARCH_ENGINE === 'perplexity'}
<div class="mb-2.5 flex w-full flex-col">
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Perplexity API Key')}
@ -456,6 +457,44 @@
bind:value={webConfig.PERPLEXITY_API_KEY}
/>
</div>
</div>
<div class="mb-2.5 flex w-full flex-col">
<div>
<div class="self-center text-xs font-medium mb-1">
{$i18n.t('Perplexity Model')}
</div>
<input
list="perplexity-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-hidden"
bind:value={webConfig.PERPLEXITY_MODEL}
/>
<datalist id="perplexity-model-list">
<option value="sonar">Sonar</option>
<option value="sonar-pro">Sonar Pro</option>
<option value="sonar-reasoning">Sonar Reasoning</option>
<option value="sonar-reasoning-pro">Sonar Reasoning Pro</option>
<option value="sonar-deep-research">Sonar Deep Research</option>
</datalist>
</div>
</div>
<div class="mb-2.5 flex w-full flex-col">
<div>
<div class=" self-center text-xs font-medium mb-1">
{$i18n.t('Perplexity Search Context Usage')}
</div>
<select
class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
bind:value={webConfig.PERPLEXITY_SEARCH_CONTEXT_USAGE}
>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
</div>
</div>
{:else if webConfig.WEB_SEARCH_ENGINE === 'sougou'}
<div class="mb-2.5 flex w-full flex-col">
<div>

View file

@ -4,13 +4,32 @@
import { goto } from '$app/navigation';
import { user } from '$lib/stores';
import { page } from '$app/stores';
import UserList from './Users/UserList.svelte';
import Groups from './Users/Groups.svelte';
const i18n = getContext('i18n');
let selectedTab = 'overview';
let selectedTab;
$: {
const pathParts = $page.url.pathname.split('/');
const tabFromPath = pathParts[pathParts.length - 1];
selectedTab = ['overview', 'groups'].includes(tabFromPath) ? tabFromPath : 'overview';
}
$: if (selectedTab) {
// scroll to selectedTab
scrollToTab(selectedTab);
}
const scrollToTab = (tabId) => {
const tabElement = document.getElementById(tabId);
if (tabElement) {
tabElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
}
};
let loaded = false;
onMount(async () => {
@ -30,6 +49,9 @@
}
});
}
// Scroll to the selected tab on mount
scrollToTab(selectedTab);
});
</script>
@ -39,12 +61,13 @@
class=" flex flex-row overflow-x-auto gap-2.5 max-w-full lg:gap-1 lg:flex-col lg:flex-none lg:w-40 dark:text-gray-200 text-sm font-medium text-left scrollbar-none"
>
<button
id="overview"
class="px-0.5 py-1 min-w-fit rounded-lg lg:flex-none flex text-right transition {selectedTab ===
'overview'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'overview';
goto('/admin/users/overview');
}}
>
<div class=" self-center mr-2">
@ -63,12 +86,13 @@
</button>
<button
id="groups"
class="px-0.5 py-1 min-w-fit rounded-lg lg:flex-none flex text-right transition {selectedTab ===
'groups'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
on:click={() => {
selectedTab = 'groups';
goto('/admin/users/groups');
}}
>
<div class=" self-center mr-2">

View file

@ -52,27 +52,6 @@
let showUserChatsModal = false;
let showEditUserModal = false;
let showUpdateRoleModal = false;
const onUpdateRole = (user) => {
if (user.role === 'user') {
updateRoleHandler(user.id, 'admin');
} else if (user.role === 'pending') {
updateRoleHandler(user.id, 'user');
} else {
updateRoleHandler(user.id, 'pending');
}
};
const updateRoleHandler = async (id, role) => {
const res = await updateUserRole(localStorage.token, id, role).catch((error) => {
toast.error(`${error}`);
return null;
});
if (res) {
getUserList();
}
};
const deleteUserHandler = async (id) => {
const res = await deleteUserById(localStorage.token, id).catch((error) => {
@ -133,21 +112,6 @@
}}
/>
<RoleUpdateConfirmDialog
bind:show={showUpdateRoleModal}
on:confirm={() => {
onUpdateRole(selectedUser);
}}
message={$i18n.t(`Are you sure you want to update this user\'s role to **{{ROLE}}**?`, {
ROLE:
selectedUser?.role === 'user'
? 'admin'
: selectedUser?.role === 'pending'
? 'user'
: 'pending'
})}
/>
{#key selectedUser}
<EditUserModal
bind:show={showEditUserModal}
@ -415,7 +379,7 @@
class=" translate-y-0.5"
on:click={() => {
selectedUser = user;
showUpdateRoleModal = true;
showEditUserModal = !showEditUserModal;
}}
>
<Badge

View file

@ -19,6 +19,7 @@
let _user = {
profile_image_url: '',
role: 'pending',
name: '',
email: '',
password: ''
@ -95,6 +96,23 @@
<div class=" px-5 pt-3 pb-5">
<div class=" flex flex-col space-y-1.5">
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Role')}</div>
<div class="flex-1">
<select
class="w-full rounded-sm text-sm bg-transparent disabled:text-gray-500 dark:disabled:text-gray-500 outline-hidden"
bind:value={_user.role}
disabled={_user.id == sessionUser.id}
required
>
<option value="admin">{$i18n.t('Admin')}</option>
<option value="user">{$i18n.t('User')}</option>
<option value="pending">{$i18n.t('Pending')}</option>
</select>
</div>
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Email')}</div>

View file

@ -239,6 +239,8 @@
};
const showMessage = async (message) => {
await tick();
const _chatId = JSON.parse(JSON.stringify($chatId));
let _messageId = JSON.parse(JSON.stringify(message.id));
@ -298,6 +300,12 @@
message.content = data.content;
} else if (type === 'chat:message:files' || type === 'files') {
message.files = data.files;
} else if (type === 'chat:message:follow_ups') {
message.followUps = data.follow_ups;
if (autoScroll) {
scrollToBottom('smooth');
}
} else if (type === 'chat:title') {
chatTitle.set(data);
currentChatPage.set(1);
@ -774,6 +782,7 @@
autoScroll = true;
resetInput();
await chatId.set('');
await chatTitle.set('');
@ -911,10 +920,13 @@
}
};
const scrollToBottom = async () => {
const scrollToBottom = async (behavior = 'auto') => {
await tick();
if (messagesContainerElement) {
messagesContainerElement.scrollTop = messagesContainerElement.scrollHeight;
messagesContainerElement.scrollTo({
top: messagesContainerElement.scrollHeight,
behavior
});
}
};
const chatCompletedHandler = async (chatId, modelId, responseMessageId, messages) => {
@ -1676,6 +1688,7 @@
chat_id: $chatId,
id: responseMessageId,
background_tasks: {
...(!$temporaryChatEnabled &&
(messages.length == 1 ||
(messages.length == 2 &&
@ -1683,12 +1696,12 @@
messages.at(1)?.role === 'user')) &&
(selectedModels[0] === model.id || atSelectedModel !== undefined)
? {
background_tasks: {
title_generation: $settings?.title?.auto ?? true,
tags_generation: $settings?.autoTags ?? true
}
}
: {}),
follow_up_generation: $settings?.autoFollowUps ?? true
},
...(stream && (model.info?.meta?.capabilities?.usage ?? false)
? {
@ -2072,7 +2085,7 @@
</div>
</div>
<div class=" pb-[1rem]">
<div class=" pb-2">
<MessageInput
{history}
{taskIds}

View file

@ -1,5 +1,9 @@
<script lang="ts">
import DOMPurify from 'dompurify';
import { marked } from 'marked';
import { toast } from 'svelte-sonner';
import { v4 as uuidv4 } from 'uuid';
import { createPicker, getAuthToken } from '$lib/utils/google-drive-picker';
import { pickAndDownloadFile } from '$lib/utils/onedrive-file-picker';
@ -595,7 +599,7 @@
/>
{:else}
<form
class="w-full flex gap-1.5"
class="w-full flex flex-col gap-1.5"
on:submit|preventDefault={() => {
// check if selectedModels support image input
dispatch('submit', prompt);
@ -1520,6 +1524,14 @@
</div>
</div>
</div>
{#if $config?.license_metadata?.input_footer}
<div class=" text-xs text-gray-500 text-center line-clamp-1 marked">
{@html DOMPurify.sanitize(marked($config?.license_metadata?.input_footer))}
</div>
{:else}
<div class="mb-1" />
{/if}
</form>
{/if}
</div>

View file

@ -205,8 +205,10 @@
return;
}
const mineTypes = ['audio/webm; codecs=opus', 'audio/mp4'];
mediaRecorder = new MediaRecorder(stream, {
mimeType: 'audio/webm; codecs=opus'
mimeType: mineTypes.find((type) => MediaRecorder.isTypeSupported(type))
});
mediaRecorder.onstart = () => {

View file

@ -28,7 +28,7 @@
<!-- svelte-ignore a11y-media-has-caption -->
<video
class="w-full my-2"
src={videoSrc}
src={videoSrc.replaceAll('&amp;', '&')}
title="Video player"
frameborder="0"
referrerpolicy="strict-origin-when-cross-origin"

View file

@ -15,7 +15,7 @@
src.startsWith('/')
? src
: `/user.png`}
class=" {className} object-cover rounded-full -translate-y-[1px]"
class=" {className} object-cover rounded-full"
alt="profile"
draggable="false"
/>

View file

@ -48,6 +48,9 @@
import ContentRenderer from './ContentRenderer.svelte';
import { KokoroWorker } from '$lib/workers/KokoroWorker';
import FileItem from '$lib/components/common/FileItem.svelte';
import FollowUps from './ResponseMessage/FollowUps.svelte';
import { fade } from 'svelte/transition';
import { flyAndScale } from '$lib/utils/transitions';
interface MessageType {
id: string;
@ -606,7 +609,7 @@
/>
</div>
<div class="flex-auto w-0 pl-1 relative">
<div class="flex-auto w-0 pl-1 relative -translate-y-0.5">
<Name>
<Tooltip content={model?.name ?? message.model} placement="top-start">
<span class="line-clamp-1 text-black dark:text-white">
@ -866,12 +869,14 @@
{#if siblings.length > 1}
<div class="flex self-center min-w-fit" dir="ltr">
<button
aria-label={$i18n.t('Previous message')}
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
@ -937,10 +942,12 @@
on:click={() => {
showNextMessage(message);
}}
aria-label={$i18n.t('Next message')}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
aria-hidden="true"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
@ -961,6 +968,7 @@
{#if $user?.role === 'user' ? ($user?.permissions?.chat?.edit ?? true) : true}
<Tooltip content={$i18n.t('Edit')} placement="bottom">
<button
aria-label={$i18n.t('Edit')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
@ -973,6 +981,7 @@
fill="none"
viewBox="0 0 24 24"
stroke-width="2.3"
aria-hidden="true"
stroke="currentColor"
class="w-4 h-4"
>
@ -989,6 +998,7 @@
<Tooltip content={$i18n.t('Copy')} placement="bottom">
<button
aria-label={$i18n.t('Copy')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition copy-response-button"
@ -999,6 +1009,7 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2.3"
stroke="currentColor"
@ -1016,6 +1027,7 @@
{#if $user?.role === 'admin' || ($user?.permissions?.chat?.tts ?? true)}
<Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
<button
aria-label={$i18n.t('Read Aloud')}
id="speak-button-{message.id}"
class="{isLastMessage
? 'visible'
@ -1031,6 +1043,7 @@
class=" w-4 h-4"
fill="currentColor"
viewBox="0 0 24 24"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
>
<style>
@ -1063,6 +1076,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
aria-hidden="true"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
@ -1078,6 +1092,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
aria-hidden="true"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
@ -1096,6 +1111,7 @@
{#if $config?.features.enable_image_generation && ($user?.role === 'admin' || $user?.permissions?.features?.image_generation) && !readOnly}
<Tooltip content={$i18n.t('Generate Image')} placement="bottom">
<button
aria-label={$i18n.t('Generate Image')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
@ -1107,6 +1123,7 @@
>
{#if generatingImage}
<svg
aria-hidden="true"
class=" w-4 h-4"
fill="currentColor"
viewBox="0 0 24 24"
@ -1141,6 +1158,7 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2.3"
stroke="currentColor"
@ -1173,6 +1191,7 @@
placement="bottom"
>
<button
aria-hidden="true"
class=" {isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition whitespace-pre-wrap"
@ -1182,6 +1201,7 @@
id="info-{message.id}"
>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
@ -1203,6 +1223,7 @@
{#if !$temporaryChatEnabled && ($config?.features.enable_message_rating ?? true)}
<Tooltip content={$i18n.t('Good Response')} placement="bottom">
<button
aria-label={$i18n.t('Good Response')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg {(
@ -1221,6 +1242,7 @@
}}
>
<svg
aria-hidden="true"
stroke="currentColor"
fill="none"
stroke-width="2.3"
@ -1239,6 +1261,7 @@
<Tooltip content={$i18n.t('Bad Response')} placement="bottom">
<button
aria-label={$i18n.t('Bad Response')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg {(
@ -1257,6 +1280,7 @@
}}
>
<svg
aria-hidden="true"
stroke="currentColor"
fill="none"
stroke-width="2.3"
@ -1277,6 +1301,7 @@
{#if isLastMessage}
<Tooltip content={$i18n.t('Continue Response')} placement="bottom">
<button
aria-label={$i18n.t('Continue Response')}
type="button"
id="continue-response-button"
class="{isLastMessage
@ -1287,6 +1312,7 @@
}}
>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
@ -1312,6 +1338,7 @@
<Tooltip content={$i18n.t('Regenerate')} placement="bottom">
<button
type="button"
aria-label={$i18n.t('Regenerate')}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition regenerate-response-button"
@ -1337,6 +1364,7 @@
fill="none"
viewBox="0 0 24 24"
stroke-width="2.3"
aria-hidden="true"
stroke="currentColor"
class="w-4 h-4"
>
@ -1353,6 +1381,7 @@
<Tooltip content={$i18n.t('Delete')} placement="bottom">
<button
type="button"
aria-label={$i18n.t('Delete')}
id="delete-response-button"
class="{isLastMessage
? 'visible'
@ -1367,6 +1396,7 @@
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
aria-hidden="true"
class="w-4 h-4"
>
<path
@ -1384,6 +1414,7 @@
<Tooltip content={action.name} placement="bottom">
<button
type="button"
aria-label={action.name}
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
@ -1425,6 +1456,17 @@
}}
/>
{/if}
{#if isLastMessage && message.done && !readOnly && (message?.followUps ?? []).length > 0}
<div class="mt-2.5" in:fade={{ duration: 100 }}>
<FollowUps
followUps={message?.followUps}
onClick={(prompt) => {
submitMessage(message?.id, prompt);
}}
/>
</div>
{/if}
{/if}
</div>

View file

@ -0,0 +1,36 @@
<script lang="ts">
import ArrowTurnDownRight from '$lib/components/icons/ArrowTurnDownRight.svelte';
import { onMount, tick, getContext } from 'svelte';
const i18n = getContext('i18n');
export let followUps: string[] = [];
export let onClick: (followUp: string) => void = () => {};
</script>
<div class="mt-4">
<div class="text-sm font-medium">
{$i18n.t('Follow up')}
</div>
<div class="flex flex-col text-left gap-1 mt-1.5">
{#each followUps as followUp, idx (idx)}
<button
class=" mr-2 py-1.5 bg-transparent text-left text-sm flex items-center gap-2 px-1.5 text-gray-500 dark:text-gray-400 hover:text-black dark:hover:text-white transition"
on:click={() => onClick(followUp)}
title={followUp}
aria-label={followUp}
>
<ArrowTurnDownRight className="size-3.5" />
<div class="line-clamp-1">
{followUp}
</div>
</button>
{#if idx < followUps.length - 1}
<hr class="border-gray-100 dark:border-gray-850" />
{/if}
{/each}
</div>
</div>

View file

@ -17,6 +17,7 @@
// Addons
let titleAutoGenerate = true;
let autoFollowUps = true;
let autoTags = true;
let responseAutoCopy = false;
@ -197,6 +198,11 @@
});
};
const toggleAutoFollowUps = async () => {
autoFollowUps = !autoFollowUps;
saveSettings({ autoFollowUps });
};
const toggleAutoTags = async () => {
autoTags = !autoTags;
saveSettings({ autoTags });
@ -287,6 +293,7 @@
onMount(async () => {
titleAutoGenerate = $settings?.title?.auto ?? true;
autoTags = $settings.autoTags ?? true;
autoFollowUps = $settings.autoFollowUps ?? true;
highContrastMode = $settings.highContrastMode ?? false;
@ -619,6 +626,26 @@
</div>
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs">{$i18n.t('Follow-Up Auto-Generation')}</div>
<button
class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => {
toggleAutoFollowUps();
}}
type="button"
>
{#if autoFollowUps === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs">{$i18n.t('Chat Tags Auto-Generation')}</div>

View file

@ -34,93 +34,160 @@
id: 'general',
title: 'General',
keywords: [
'general',
'theme',
'language',
'notifications',
'system',
'systemprompt',
'prompt',
'advanced',
'settings',
'defaultsettings',
'advancedparams',
'advancedparameters',
'advanced params',
'advanced parameters',
'configuration',
'systemsettings',
'notificationsettings',
'systempromptconfig',
'languageoptions',
'defaultparameters',
'systemparameters'
'default parameters',
'defaultsettings',
'default settings',
'general',
'keepalive',
'keep alive',
'languages',
'notifications',
'requestmode',
'request mode',
'systemparameters',
'system parameters',
'systemprompt',
'system prompt',
'systemsettings',
'system settings',
'theme',
'translate',
'webuisettings',
'webui settings'
]
},
{
id: 'interface',
title: 'Interface',
keywords: [
'defaultmodel',
'selectmodel',
'ui',
'userinterface',
'display',
'layout',
'design',
'landingpage',
'landingpagemode',
'default',
'chat',
'chatbubble',
'chatui',
'username',
'showusername',
'displayusername',
'widescreen',
'widescreenmode',
'fullscreen',
'expandmode',
'allow user location',
'allow voice interruption in call',
'allowuserlocation',
'allowvoiceinterruptionincall',
'always collapse codeblocks',
'always collapse code blocks',
'always expand details',
'always on web search',
'always play notification sound',
'alwayscollapsecodeblocks',
'alwaysexpanddetails',
'alwaysonwebsearch',
'alwaysplaynotificationsound',
'android',
'auto chat tags',
'auto copy response to clipboard',
'auto title',
'autochattags',
'autocopyresponsetoclipboard',
'autotitle',
'beta',
'call',
'chat background image',
'chat bubble ui',
'chat direction',
'chat tags autogen',
'chat tags autogeneration',
'chat ui',
'chatbackgroundimage',
'chatbubbleui',
'chatdirection',
'chat tags autogeneration',
'chattagsautogeneration',
'chatui',
'copy formatted text',
'copyformattedtext',
'default model',
'defaultmodel',
'design',
'detect artifacts automatically',
'detectartifactsautomatically',
'display emoji in call',
'display username',
'displayemojiincall',
'displayusername',
'enter key behavior',
'enterkeybehavior',
'expand mode',
'expandmode',
'file',
'followup autogeneration',
'followupautogeneration',
'fullscreen',
'fullwidthmode',
'full width mode',
'haptic feedback',
'hapticfeedback',
'high contrast mode',
'highcontrastmode',
'iframe sandbox allow forms',
'iframe sandbox allow same origin',
'iframesandboxallowforms',
'iframesandboxallowsameorigin',
'imagecompression',
'image compression',
'imagemaxcompressionsize',
'image max compression size',
'interface customization',
'interface options',
'interfacecustomization',
'interfaceoptions',
'landing page mode',
'landingpagemode',
'layout',
'left to right',
'left-to-right',
'lefttoright',
'ltr',
'paste large text as file',
'pastelargetextasfile',
'reset background',
'resetbackground',
'response auto copy',
'responseautocopy',
'rich text input for chat',
'richtextinputforchat',
'right to left',
'right-to-left',
'righttoleft',
'rtl',
'notifications',
'toast',
'toastnotifications',
'largechunks',
'streamlargechunks',
'scroll',
'scrollonbranchchange',
'scroll behavior',
'scroll on branch change',
'scrollbehavior',
'richtext',
'richtextinput',
'background',
'chatbackground',
'chatbackgroundimage',
'backgroundimage',
'uploadbackground',
'resetbackground',
'titleautogen',
'scrollonbranchchange',
'select model',
'selectmodel',
'settings',
'show username',
'showusername',
'stream large chunks',
'streamlargechunks',
'stylized pdf export',
'stylizedpdfexport',
'title autogeneration',
'titleautogeneration',
'autotitle',
'chattags',
'autochattags',
'responseautocopy',
'clipboard',
'location',
'userlocation',
'toast notifications for new updates',
'toastnotificationsfornewupdates',
'upload background',
'uploadbackground',
'user interface',
'user location access',
'userinterface',
'userlocationaccess',
'haptic',
'hapticfeedback',
'vibration',
'voice',
'voice control',
'voicecontrol',
'voiceinterruption',
'call',
'emojis',
'displayemoji',
'save',
'interfaceoptions',
'interfacecustomization',
'alwaysonwebsearch'
'widescreen mode',
'widescreenmode',
'whatsnew',
'whats new',
'websearchinchat',
'web search in chat'
]
},
...($user?.role === 'admin' ||
@ -129,7 +196,15 @@
{
id: 'connections',
title: 'Connections',
keywords: []
keywords: [
'addconnection',
'add connection',
'manageconnections',
'manage connections',
'manage direct connections',
'managedirectconnections',
'settings'
]
}
]
: []),
@ -140,7 +215,15 @@
{
id: 'tools',
title: 'Tools',
keywords: []
keywords: [
'addconnection',
'add connection',
'managetools',
'manage tools',
'manage tool servers',
'managetoolservers',
'settings'
]
}
]
: []),
@ -149,159 +232,233 @@
id: 'personalization',
title: 'Personalization',
keywords: [
'personalization',
'memory',
'personalize',
'preferences',
'profile',
'personalsettings',
'account preferences',
'account settings',
'accountpreferences',
'accountsettings',
'custom settings',
'customsettings',
'userpreferences',
'accountpreferences'
'experimental',
'memories',
'memory',
'personalization',
'personalize',
'personal settings',
'personalsettings',
'profile',
'user preferences',
'userpreferences'
]
},
{
id: 'audio',
title: 'Audio',
keywords: [
'audio',
'sound',
'soundsettings',
'audiocontrol',
'volume',
'speech',
'speechrecognition',
'stt',
'speechtotext',
'tts',
'texttospeech',
'playback',
'playbackspeed',
'voiceplayback',
'speechplayback',
'audiooutput',
'speechengine',
'voicecontrol',
'audioplayback',
'transcription',
'autotranscribe',
'autosend',
'speechsettings',
'audiovoice',
'voiceoptions',
'setvoice',
'nonlocalvoices',
'savesettings',
'audio config',
'audio control',
'audio features',
'audio input',
'audio output',
'audio playback',
'audio voice',
'audioconfig',
'speechconfig',
'voicerecognition',
'speechsynthesis',
'speechmode',
'voicespeed',
'speechrate',
'speechspeed',
'audioinput',
'audiocontrol',
'audiofeatures',
'voicemodes'
'audioinput',
'audiooutput',
'audioplayback',
'audiovoice',
'auto playback response',
'autoplaybackresponse',
'auto transcribe',
'autotranscribe',
'instant auto send after voice transcription',
'instantautosendaftervoicetranscription',
'language',
'non local voices',
'nonlocalvoices',
'save settings',
'savesettings',
'set voice',
'setvoice',
'sound settings',
'soundsettings',
'speech config',
'speech mode',
'speech playback speed',
'speech rate',
'speech recognition',
'speech settings',
'speech speed',
'speech synthesis',
'speech to text engine',
'speechconfig',
'speechmode',
'speechplaybackspeed',
'speechrate',
'speechrecognition',
'speechsettings',
'speechspeed',
'speechsynthesis',
'speechtotextengine',
'speedch playback rate',
'speedchplaybackrate',
'stt settings',
'sttsettings',
'text to speech engine',
'text to speech',
'textospeechengine',
'texttospeech',
'texttospeechvoice',
'text to speech voice',
'voice control',
'voice modes',
'voice options',
'voice playback',
'voice recognition',
'voice speed',
'voicecontrol',
'voicemodes',
'voiceoptions',
'voiceplayback',
'voicerecognition',
'voicespeed',
'volume'
]
},
{
id: 'chats',
title: 'Chats',
keywords: [
'chat',
'messages',
'conversations',
'chatsettings',
'history',
'archive all chats',
'archive chats',
'archiveallchats',
'archivechats',
'archived chats',
'archivedchats',
'chat activity',
'chat history',
'chat settings',
'chatactivity',
'chathistory',
'messagehistory',
'messagearchive',
'convo',
'chats',
'chatsettings',
'conversation activity',
'conversation history',
'conversationactivity',
'conversationhistory',
'exportmessages',
'chatactivity'
'conversations',
'convos',
'delete all chats',
'delete chats',
'deleteallchats',
'deletechats',
'export chats',
'exportchats',
'import chats',
'importchats',
'message activity',
'message archive',
'message history',
'messagearchive',
'messagehistory'
]
},
{
id: 'account',
title: 'Account',
keywords: [
'account',
'profile',
'security',
'privacy',
'settings',
'account preferences',
'account settings',
'accountpreferences',
'accountsettings',
'api keys',
'apikeys',
'change password',
'changepassword',
'jwt token',
'jwttoken',
'login',
'new password',
'newpassword',
'notification webhook url',
'notificationwebhookurl',
'personal settings',
'personalsettings',
'privacy settings',
'privacysettings',
'profileavatar',
'profile avatar',
'profile details',
'profile image',
'profile picture',
'profiledetails',
'profileimage',
'profilepicture',
'security settings',
'securitysettings',
'update account',
'update password',
'updateaccount',
'updatepassword',
'user account',
'user data',
'user preferences',
'user profile',
'useraccount',
'userdata',
'api',
'apikey',
'username',
'userpreferences',
'userprofile',
'profiledetails',
'accountsettings',
'accountpreferences',
'securitysettings',
'privacysettings'
]
},
{
id: 'admin',
title: 'Admin',
keywords: [
'admin',
'administrator',
'adminsettings',
'adminpanel',
'systemadmin',
'administratoraccess',
'systemcontrol',
'manage',
'management',
'admincontrols',
'adminfeatures',
'usercontrol',
'arenamodel',
'evaluations',
'websearch',
'database',
'pipelines',
'images',
'audio',
'documents',
'rag',
'models',
'ollama',
'openai',
'users'
'webhook url',
'webhookurl'
]
},
{
id: 'about',
title: 'About',
keywords: [
'about',
'info',
'information',
'version',
'documentation',
'help',
'support',
'details',
'aboutus',
'softwareinfo',
'timothyjaeryangbaek',
'openwebui',
'release',
'updates',
'updateinfo',
'versioninfo',
'about app',
'about me',
'about open webui',
'about page',
'about us',
'aboutapp',
'terms',
'termsandconditions',
'aboutme',
'aboutopenwebui',
'aboutpage',
'aboutus',
'check for updates',
'checkforupdates',
'contact',
'aboutpage'
'copyright',
'details',
'discord',
'documentation',
'github',
'help',
'information',
'license',
'redistributions',
'release',
'see whats new',
'seewhatsnew',
'settings',
'software info',
'softwareinfo',
'support',
'terms and conditions',
'terms of use',
'termsandconditions',
'termsofuse',
'timothy jae ryang baek',
'timothy j baek',
'timothyjaeryangbaek',
'timothyjbaek',
'twitter',
'update info',
'updateinfo',
'version info',
'versioninfo'
]
}
];
@ -405,7 +562,7 @@
<div class="flex flex-col md:flex-row w-full px-4 pt-1 pb-4 md:space-x-4">
<div
id="settings-tabs-container"
class="tabs flex flex-row overflow-x-auto gap-2.5 md:gap-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-sm font-medium text-left mb-1 md:mb-0 -translate-y-1"
class="tabs flex flex-row overflow-x-auto gap-2.5 md:gap-1 md:flex-col flex-1 md:flex-none md:w-40 md:min-h-[32rem] md:max-h-[32rem] dark:text-gray-200 text-sm font-medium text-left mb-1 md:mb-0 -translate-y-1"
>
<div class="hidden md:flex w-full rounded-xl -mb-1 px-0.5 gap-2" id="settings-search">
<div class="self-center rounded-l-xl bg-transparent">
@ -647,13 +804,17 @@
</div>
<div class=" self-center">{$i18n.t('About')}</div>
</button>
{:else if tabId === 'admin'}
{/if}
{/each}
{:else}
<div class="text-center text-gray-500 mt-4">
{$i18n.t('No results found')}
</div>
{/if}
{#if $user?.role === 'admin'}
<button
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
'admin'
? ''
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white mt-auto"
on:click={async () => {
await goto('/admin/settings');
show = false;
@ -676,13 +837,6 @@
<div class=" self-center">{$i18n.t('Admin Settings')}</div>
</button>
{/if}
{/if}
{/each}
{:else}
<div class="text-center text-gray-500 mt-4">
{$i18n.t('No results found')}
</div>
{/if}
</div>
<div class="flex-1 md:min-h-[32rem] max-h-[32rem]">
{#if selectedTab === 'general'}
@ -763,6 +917,7 @@
}
input[type='number'] {
appearance: textfield;
-moz-appearance: textfield; /* Firefox */
}
</style>

View file

@ -13,6 +13,9 @@
dayjs.extend(relativeTime);
async function loadLocale(locales) {
if (!locales || !Array.isArray(locales)) {
return;
}
for (const locale of locales) {
try {
dayjs.locale(locale);

View file

@ -33,7 +33,9 @@
});
onDestroy(() => {
if (observer) {
observer.disconnect();
}
if (intervalId) {
clearInterval(intervalId);

View file

@ -2,10 +2,8 @@
import DOMPurify from 'dompurify';
import { onDestroy } from 'svelte';
import { marked } from 'marked';
import tippy from 'tippy.js';
import { roundArrow } from 'tippy.js';
export let placement = 'top';
export let content = `I'm a tooltip!`;
@ -47,6 +45,6 @@
});
</script>
<div bind:this={tooltipElement} aria-label={DOMPurify.sanitize(content)} class={className}>
<div bind:this={tooltipElement} class={className}>
<slot />
</div>

View file

@ -0,0 +1,12 @@
<script lang="ts">
export let className = 'size-4';
export let strokeWidth = '1.5';
</script>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class={className}>
<path
fill-rule="evenodd"
d="M2.75 2a.75.75 0 0 1 .75.75v6.5h7.94l-.97-.97a.75.75 0 0 1 1.06-1.06l2.25 2.25a.75.75 0 0 1 0 1.06l-2.25 2.25a.75.75 0 1 1-1.06-1.06l.97-.97H2.75A.75.75 0 0 1 2 10V2.75A.75.75 0 0 1 2.75 2Z"
clip-rule="evenodd"
/>
</svg>

View file

@ -785,7 +785,7 @@
<div
class="ml-3 pl-1 mt-[1px] flex flex-col overflow-y-auto scrollbar-hidden border-s border-gray-100 dark:border-gray-900"
>
{#each $pinnedChats as chat, idx}
{#each $pinnedChats as chat, idx (`pinned-chat-${chat?.id ?? idx}`)}
<ChatItem
className=""
id={chat.id}
@ -831,7 +831,7 @@
<div class=" flex-1 flex flex-col overflow-y-auto scrollbar-hidden">
<div class="pt-1.5">
{#if $chats}
{#each $chats as chat, idx}
{#each $chats as chat, idx (`chat-${chat?.id ?? idx}`)}
{#if idx === 0 || (idx > 0 && chat.time_range !== $chats[idx - 1].time_range)}
<div
class="w-full pl-2.5 text-xs text-gray-500 dark:text-gray-500 font-medium {idx ===

View file

@ -204,9 +204,10 @@
const chatTitleInputKeydownHandler = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
editChatTitle(id, chatTitle);
confirmEdit = false;
chatTitle = '';
setTimeout(() => {
const input = document.getElementById(`chat-title-input-${id}`);
if (input) input.blur();
}, 0);
} else if (e.key === 'Escape') {
e.preventDefault();
confirmEdit = false;

View file

@ -22,7 +22,7 @@
import ChevronRight from '../icons/ChevronRight.svelte';
import Spinner from '../common/Spinner.svelte';
import Tooltip from '../common/Tooltip.svelte';
import { capitalizeFirstLetter } from '$lib/utils';
import { capitalizeFirstLetter, slugify } from '$lib/utils';
import XMark from '../icons/XMark.svelte';
const i18n = getContext('i18n');
@ -68,7 +68,15 @@
};
const cloneHandler = async (prompt) => {
sessionStorage.prompt = JSON.stringify(prompt);
const clonedPrompt = { ...prompt };
clonedPrompt.title = `${clonedPrompt.title} (Clone)`;
const baseCommand = clonedPrompt.command.startsWith('/')
? clonedPrompt.command.substring(1)
: clonedPrompt.command;
clonedPrompt.command = slugify(`${baseCommand} clone`);
sessionStorage.prompt = JSON.stringify(clonedPrompt);
goto('/workspace/prompts/create');
};

View file

@ -13,6 +13,7 @@
export let onSubmit: Function;
export let edit = false;
export let prompt = null;
export let clone = false;
const i18n = getContext('i18n');

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "هل أنت متأكد ؟",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "اتبعت التعليمات على أكمل وجه",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "كلمة المرور الجديدة",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ملف (.pdf)",
"PDF Extract Images (OCR)": "PDF أستخرج الصور (OCR)",
"pending": "قيد الانتظار",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "التخصيص",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "أخر 30 يوم",
"Previous 7 days": "أخر 7 أيام",
"Previous message": "",
"Private": "",
"Profile Image": "صورة الملف الشخصي",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "هل أنت متأكد من رغبتك في حذف هذه القناة؟",
"Are you sure you want to delete this message?": "هل أنت متأكد من رغبتك في حذف هذه الرسالة؟",
"Are you sure you want to unarchive all archived chats?": "هل أنت متأكد من رغبتك في إلغاء أرشفة جميع المحادثات المؤرشفة؟",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "هل أنت متأكد؟",
"Arena Models": "نماذج الساحة",
"Artifacts": "القطع الأثرية",
@ -611,6 +610,10 @@
"Folder deleted successfully": "تم حذف المجلد بنجاح",
"Folder name cannot be empty.": "لا يمكن أن يكون اسم المجلد فارغًا.",
"Folder name updated successfully": "تم تحديث اسم المجلد بنجاح",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "اتبعت التعليمات على أكمل وجه",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "كلمة المرور الجديدة",
"New Tool": "",
"new-channel": "قناة جديدة",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ملف (.pdf)",
"PDF Extract Images (OCR)": "PDF أستخرج الصور (OCR)",
"pending": "قيد الانتظار",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "تم رفض الإذن عند محاولة الوصول إلى أجهزة الوسائط",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ",
"Permissions": "الأذونات",
"Perplexity API Key": "مفتاح API لـ Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "التخصيص",
"Pin": "تثبيت",
"Pinned": "مثبت",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "أخر 30 يوم",
"Previous 7 days": "أخر 7 أيام",
"Previous message": "",
"Private": "",
"Profile Image": "صورة الملف الشخصي",
"Prompt": "التوجيه",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Сигурни ли сте, че искате да изтриете този канал?",
"Are you sure you want to delete this message?": "Сигурни ли сте, че искате да изтриете това съобщение?",
"Are you sure you want to unarchive all archived chats?": "Сигурни ли сте, че искате да разархивирате всички архивирани чатове?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Сигурни ли сте?",
"Arena Models": "Арена Модели",
"Artifacts": "Артефакти",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Папката е изтрита успешно",
"Folder name cannot be empty.": "Името на папката не може да бъде празно.",
"Folder name updated successfully": "Името на папката е актуализирано успешно",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Следвайте инструкциите перфектно",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Нова парола",
"New Tool": "",
"new-channel": "нов-канал",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "Без съдържание",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF документ (.pdf)",
"PDF Extract Images (OCR)": "Извличане на изображения от PDF (OCR)",
"pending": "в очакване",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Отказан достъп при опит за достъп до медийни устройства",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Отказан достъп при опит за достъп до микрофона: {{error}}",
"Permissions": "Разрешения",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Персонализация",
"Pin": "Закачи",
"Pinned": "Закачено",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Предишните 30 дни",
"Previous 7 days": "Предишните 7 дни",
"Previous message": "",
"Private": "",
"Profile Image": "Профилна снимка",
"Prompt": "Промпт",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "আপনি নিশ্চিত?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "নির্দেশাবলী নিখুঁতভাবে অনুসরণ করা হয়েছে",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "নতুন পাসওয়ার্ড",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ডকুমেন্ট (.pdf)",
"PDF Extract Images (OCR)": "পিডিএফ এর ছবি থেকে লেখা বের করুন (OCR)",
"pending": "অপেক্ষমান",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "মাইক্রোফোন ব্যবহারের অনুমতি পাওয়া যায়নি: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "ডিজিটাল বাংলা",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "পূর্ব ৩০ দিন",
"Previous 7 days": "পূর্ব দিন",
"Previous message": "",
"Private": "",
"Profile Image": "প্রোফাইল ইমেজ",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "ཁྱེད་ཀྱིས་བགྲོ་གླེང་འདི་བསུབ་འདོད་ངེས་ཡིན་ནམ།",
"Are you sure you want to delete this message?": "འཕྲིན་འདི་བསུབ་འདོད་ངེས་ཡིན་ནམ།",
"Are you sure you want to unarchive all archived chats?": "ཁྱེད་ཀྱིས་ཡིག་མཛོད་དུ་བཞག་པའི་ཁ་བརྡ་ཡོངས་རྫོགས་ཕྱིར་འདོན་འདོད་ངེས་ཡིན་ནམ།",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "ཁྱོད་ངེས་པ་ཡིན་ནམ།",
"Arena Models": "Arena དཔེ་དབྱིབས།",
"Artifacts": "རྫས་རྟེན།",
@ -611,6 +610,10 @@
"Folder deleted successfully": "ཡིག་སྣོད་ལེགས་པར་བསུབས་ཟིན།",
"Folder name cannot be empty.": "ཡིག་སྣོད་ཀྱི་མིང་སྟོང་པ་ཡིན་མི་ཆོག",
"Folder name updated successfully": "ཡིག་སྣོད་ཀྱི་མིང་ལེགས་པར་གསར་སྒྱུར་བྱས་ཟིན།",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "ལམ་སྟོན་ཡང་དག་པར་བསྒྲུབས།",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "གསང་གྲངས་གསར་པ།",
"New Tool": "",
"new-channel": "བགྲོ་གླེང་གསར་པ།",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ཡིག་ཆ། (.pdf)",
"PDF Extract Images (OCR)": "PDF པར་འདོན་སྤེལ། (OCR)",
"pending": "སྒུག་བཞིན་པ།",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "བརྒྱུད་ལམ་སྒྲིག་ཆས་འཛུལ་སྤྱོད་སྐབས་དབང་ཚད་ཁས་མ་བླངས།",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "སྐད་སྒྲ་འཛིན་ཆས་འཛུལ་སྤྱོད་སྐབས་དབང་ཚད་ཁས་མ་བླངས།: {{error}}",
"Permissions": "དབང་ཚད།",
"Perplexity API Key": "Perplexity API ལྡེ་མིག",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "སྒེར་སྤྱོད་ཅན།",
"Pin": "གདབ་པ།",
"Pinned": "གདབ་ཟིན།",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "ཉིན་ ༣༠ སྔོན་མ།",
"Previous 7 days": "ཉིན་ ༧ སྔོན་མ།",
"Previous message": "",
"Private": "སྒེར།",
"Profile Image": "སྤྱི་ཐག་པར།",
"Prompt": "འགུལ་སློང་།",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Estàs segur que vols eliminar aquest canal?",
"Are you sure you want to delete this message?": "Estàs segur que vols eliminar aquest missatge?",
"Are you sure you want to unarchive all archived chats?": "Estàs segur que vols desarxivar tots els xats arxivats?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "Estàs segur que vols actualitzar el rol de l'usuari a **{{ROLE}}**?",
"Are you sure?": "Estàs segur?",
"Arena Models": "Models de l'Arena",
"Artifacts": "Artefactes",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Carpeta eliminada correctament",
"Folder name cannot be empty.": "El nom de la carpeta no pot ser buit.",
"Folder name updated successfully": "Nom de la carpeta actualitzat correctament",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "S'han seguit les instruccions perfectament",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nova contrasenya",
"New Tool": "",
"new-channel": "nou-canal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "No hi ha contingut",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Document PDF (.pdf)",
"PDF Extract Images (OCR)": "Extreu imatges del PDF (OCR)",
"pending": "pendent",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Permís denegat en accedir a dispositius multimèdia",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
"Permissions": "Permisos",
"Perplexity API Key": "Clau API de Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalització",
"Pin": "Fixar",
"Pinned": "Fixat",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 dies anteriors",
"Previous 7 days": "7 dies anteriors",
"Previous message": "",
"Private": "Privat",
"Profile Image": "Imatge de perfil",
"Prompt": "Indicació",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Sigurado ka ?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Bag-ong Password",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "PDF Image Extraction (OCR)",
"pending": "gipugngan",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Gidili ang pagtugot sa dihang nag-access sa mikropono: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "",
"Previous 7 days": "",
"Previous message": "",
"Private": "",
"Profile Image": "",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Jste si jistý?",
"Arena Models": "Arena modely",
"Artifacts": "Artefakty",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Složka byla úspěšně smazána",
"Folder name cannot be empty.": "Název složky nesmí být prázdný.",
"Folder name updated successfully": "Název složky byl úspěšně aktualizován.",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Dodržel pokyny dokonale.",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nové heslo",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokument (.pdf)",
"PDF Extract Images (OCR)": "Extrahování obrázků z PDF (OCR)",
"pending": "čeká na vyřízení",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Odmítnutí povolení při přístupu k mediálním zařízením",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Oprávnění zamítnuto při přístupu k mikrofonu: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizace",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Předchozích 30 dnů",
"Previous 7 days": "Předchozích 7 dní",
"Previous message": "",
"Private": "",
"Profile Image": "Profilový obrázek",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Er du sikker på du vil slette denne kanal?",
"Are you sure you want to delete this message?": "Er du sikker på du vil slette denne besked?",
"Are you sure you want to unarchive all archived chats?": "Er du sikker på du vil fjerne alle arkiverede chats?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Er du sikker?",
"Arena Models": "Arena Modeller",
"Artifacts": "Artifakter",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Mappe fjernet.",
"Folder name cannot be empty.": "Mappenavn kan ikke være tom.",
"Folder name updated successfully": "Mappenavn opdateret.",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Fulgte instruktionerne perfekt",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Ny adgangskode",
"New Tool": "",
"new-channel": "",
"Next message": "Næste besked",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "Intet indhold",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF-dokument (.pdf)",
"PDF Extract Images (OCR)": "Udtræk billeder fra PDF (OCR)",
"pending": "afventer",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Tilladelse nægtet ved adgang til medieenheder",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Tilladelse nægtet ved adgang til mikrofon: {{error}}",
"Permissions": "Tilladelser",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalisering",
"Pin": "Fastgør",
"Pinned": "Fastgjort",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Seneste 30 dage",
"Previous 7 days": "Seneste 7 dage",
"Previous message": "Forrige besked",
"Private": "Privat",
"Profile Image": "Profilbillede",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Sind Sie sicher, dass Sie diesen Kanal löschen möchten?",
"Are you sure you want to delete this message?": "Sind Sie sicher, dass Sie diese Nachricht löschen möchten?",
"Are you sure you want to unarchive all archived chats?": "Sind Sie sicher, dass Sie alle archivierten Chats wiederherstellen möchten?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "Sind Sie sicher, dass Sie die Rolle dieses Benutzers auf **{{ROLE}}** ändern möchten?",
"Are you sure?": "Sind Sie sicher?",
"Arena Models": "Arena-Modelle",
"Artifacts": "Artefakte",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Ordner erfolgreich gelöscht",
"Folder name cannot be empty.": "Ordnername darf nicht leer sein.",
"Folder name updated successfully": "Ordnername erfolgreich aktualisiert",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Anweisungen perfekt befolgt",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Neues Passwort",
"New Tool": "",
"new-channel": "neuer-kanal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "Kein Inhalt",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF-Dokument (.pdf)",
"PDF Extract Images (OCR)": "Text von Bildern aus PDFs extrahieren (OCR)",
"pending": "ausstehend",
"Pending": "",
"Pending User Overlay Content": "Inhalt des Overlays 'Ausstehende Kontoaktivierung'",
"Pending User Overlay Title": "Titel des Overlays 'Ausstehende Kontoaktivierung'",
"Permission denied when accessing media devices": "Zugriff auf Mediengeräte verweigert",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Zugriff auf das Mikrofon verweigert: {{error}}",
"Permissions": "Berechtigungen",
"Perplexity API Key": "Perplexity API-Schlüssel",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalisierung",
"Pin": "Anheften",
"Pinned": "Angeheftet",
@ -965,6 +972,7 @@
"Preview": "Vorschau",
"Previous 30 days": "Vorherige 30 Tage",
"Previous 7 days": "Vorherige 7 Tage",
"Previous message": "",
"Private": "Privat",
"Profile Image": "Profilbild",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Such certainty?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "New Barkword",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "PDF Extract Wowmages (OCR)",
"pending": "pending",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalization",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "",
"Previous 7 days": "",
"Previous message": "",
"Private": "",
"Profile Image": "",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "Είστε σίγουροι ότι θέλετε να απο-αρχειοθετήσετε όλες τις αρχειοθετημένες συνομιλίες;",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Είστε σίγουροι;",
"Arena Models": "Μοντέλα Arena",
"Artifacts": "Αρχεία",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Ο φάκελος διαγράφηκε με επιτυχία",
"Folder name cannot be empty.": "Το όνομα του φακέλου δεν μπορεί να είναι κενό.",
"Folder name updated successfully": "Το όνομα του φακέλου ενημερώθηκε με επιτυχία",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Ακολούθησε τις οδηγίες τέλεια",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Νέος Κωδικός",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Έγγραφο PDF (.pdf)",
"PDF Extract Images (OCR)": "Εξαγωγή Εικόνων PDF (OCR)",
"pending": "εκκρεμεί",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Άρνηση δικαιώματος κατά την πρόσβαση σε μέσα συσκευές",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Άρνηση δικαιώματος κατά την πρόσβαση σε μικρόφωνο: {{error}}",
"Permissions": "Δικαιώματα",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Προσωποποίηση",
"Pin": "Καρφίτσωμα",
"Pinned": "Καρφιτσωμένο",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Προηγούμενες 30 ημέρες",
"Previous 7 days": "Προηγούμενες 7 ημέρες",
"Previous message": "",
"Private": "",
"Profile Image": "Εικόνα Προφίλ",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "",
"pending": "",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "",
"Previous 7 days": "",
"Previous message": "",
"Private": "",
"Profile Image": "",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "",
"New Tool": "",
"new-channel": "",
"Next message": "Next message",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "",
"PDF Extract Images (OCR)": "",
"pending": "",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "",
"Previous 7 days": "",
"Previous message": "Previous message",
"Private": "",
"Profile Image": "",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "¿Seguro de que quieres eliminar este canal?",
"Are you sure you want to delete this message?": "¿Seguro de que quieres eliminar este mensaje? ",
"Are you sure you want to unarchive all archived chats?": "¿Seguro de que quieres desarchivar todos los chats archivados?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "¿Estás seguro?",
"Arena Models": "Arena de Modelos",
"Artifacts": "Artefactos",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Carpeta eliminada correctamente",
"Folder name cannot be empty.": "El nombre de la carpeta no puede estar vacío",
"Folder name updated successfully": "Nombre de la carpeta actualizado correctamente",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Siguió las instrucciones perfectamente",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nueva Contraseña",
"New Tool": "",
"new-channel": "nuevo-canal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Documento PDF (.pdf)",
"PDF Extract Images (OCR)": "Extraer imágenes del PDF (OCR)",
"pending": "pendiente",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Permiso denegado accediendo a los dispositivos",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permiso denegado accediendo al micrófono: {{error}}",
"Permissions": "Permisos",
"Perplexity API Key": "Clave API de Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalización",
"Pin": "Fijar",
"Pinned": "Fijado",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 días previos",
"Previous 7 days": "7 días previos",
"Previous message": "",
"Private": "Privado",
"Profile Image": "Imagen del Perfil",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Kas olete kindel, et soovite selle kanali kustutada?",
"Are you sure you want to delete this message?": "Kas olete kindel, et soovite selle sõnumi kustutada?",
"Are you sure you want to unarchive all archived chats?": "Kas olete kindel, et soovite kõik arhiveeritud vestlused arhiivist eemaldada?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Kas olete kindel?",
"Arena Models": "Areena mudelid",
"Artifacts": "Tekkinud objektid",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Kaust edukalt kustutatud",
"Folder name cannot be empty.": "Kausta nimi ei saa olla tühi.",
"Folder name updated successfully": "Kausta nimi edukalt uuendatud",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Järgis juhiseid täiuslikult",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Uus parool",
"New Tool": "",
"new-channel": "uus-kanal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokument (.pdf)",
"PDF Extract Images (OCR)": "PDF-ist piltide väljavõtmine (OCR)",
"pending": "ootel",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Juurdepääs meediumiseadmetele keelatud",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Juurdepääs mikrofonile keelatud: {{error}}",
"Permissions": "Õigused",
"Perplexity API Key": "Perplexity API võti",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Isikupärastamine",
"Pin": "Kinnita",
"Pinned": "Kinnitatud",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Eelmised 30 päeva",
"Previous 7 days": "Eelmised 7 päeva",
"Previous message": "",
"Private": "",
"Profile Image": "Profiilipilt",
"Prompt": "Vihje",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "Ziur zaude artxibatutako txat guztiak desartxibatu nahi dituzula?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Ziur zaude?",
"Arena Models": "Arena Ereduak",
"Artifacts": "Artefaktuak",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Karpeta ongi ezabatu da",
"Folder name cannot be empty.": "Karpetaren izena ezin da hutsik egon.",
"Folder name updated successfully": "Karpetaren izena ongi eguneratu da",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Jarraibideak perfektuki jarraitu ditu",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Pasahitz berria",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokumentua (.pdf)",
"PDF Extract Images (OCR)": "PDF irudiak erauzi (OCR)",
"pending": "zain",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Baimena ukatu da multimedia gailuak atzitzean",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Baimena ukatu da mikrofonoa atzitzean: {{error}}",
"Permissions": "Baimenak",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Pertsonalizazioa",
"Pin": "Ainguratu",
"Pinned": "Ainguratuta",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Aurreko 30 egunak",
"Previous 7 days": "Aurreko 7 egunak",
"Previous message": "",
"Private": "",
"Profile Image": "Profil irudia",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "آیا مطمئن هستید که می\u200cخواهید این کانال را حذف کنید؟",
"Are you sure you want to delete this message?": "آیا مطمئن هستید که می\u200cخواهید این پیام را حذف کنید؟",
"Are you sure you want to unarchive all archived chats?": "آیا مطمئن هستید که می\u200cخواهید همه گفتگوهای بایگانی شده را از بایگانی خارج کنید؟",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "مطمئنید؟",
"Arena Models": "مدل\u200cهای آرنا",
"Artifacts": "مصنوعات",
@ -611,6 +610,10 @@
"Folder deleted successfully": "پوشه با موفقیت حذف شد",
"Folder name cannot be empty.": "نام پوشه نمی\u200cتواند خالی باشد.",
"Folder name updated successfully": "نام پوشه با موفقیت به\u200cروز شد",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "دستورالعمل ها را کاملا دنبال کرد",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "رمز عبور جدید",
"New Tool": "",
"new-channel": "کانال-جدید",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF سند (.pdf)",
"PDF Extract Images (OCR)": "استخراج تصاویر از PDF (OCR)",
"pending": "در انتظار",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "دسترسی به دستگاه\u200cهای رسانه رد شد",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "هنگام دسترسی به میکروفون، اجازه داده نشد: {{error}}",
"Permissions": "مجوزها",
"Perplexity API Key": "کلید API پرپلکسیتی",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "شخصی سازی",
"Pin": "پین کردن",
"Pinned": "پین شده",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 روز قبل",
"Previous 7 days": "7 روز قبل",
"Previous message": "",
"Private": "خصوصی",
"Profile Image": "تصویر پروفایل",
"Prompt": "پرامپت",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Haluatko varmasti poistaa tämän kanavan?",
"Are you sure you want to delete this message?": "Haluatko varmasti poistaa tämän viestin?",
"Are you sure you want to unarchive all archived chats?": "Haluatko varmasti purkaa kaikkien arkistoitujen keskustelujen arkistoinnin?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "Haluatko varmasti päivittää tämän käyttäjän roolin **{{ROLE}}** tähän?",
"Are you sure?": "Oletko varma?",
"Arena Models": "Arena-mallit",
"Artifacts": "Artefaktit",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Kansio poistettu onnistuneesti",
"Folder name cannot be empty.": "Kansion nimi ei voi olla tyhjä.",
"Folder name updated successfully": "Kansion nimi päivitetty onnistuneesti",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Noudatti ohjeita täydellisesti",
"Force OCR": "Pakota OCR",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "Pakota OCR:n käyttö kaikilla PDF-sivuilla. Tämä voi johtaa huonompiin tuloksiin jos PDF:n tekstisisältö on laadukasta. Oletusarvo, ei käytöstä.",
@ -846,6 +849,7 @@
"New Password": "Uusi salasana",
"New Tool": "Uusi työkalu",
"new-channel": "uusi-kanava",
"Next message": "",
"No chats found for this user.": "Käyttäjän keskusteluja ei löytynyt.",
"No chats found.": "Keskusteluja ei löytynyt",
"No content": "Ei sisältöä",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF-asiakirja (.pdf)",
"PDF Extract Images (OCR)": "Poimi kuvat PDF:stä (OCR)",
"pending": "odottaa",
"Pending": "",
"Pending User Overlay Content": "Odottavien käyttäjien sisältö",
"Pending User Overlay Title": "Odottavien käyttäjien otsikko",
"Permission denied when accessing media devices": "Käyttöoikeus evätty media-laitteille",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Käyttöoikeus evätty mikrofonille: {{error}}",
"Permissions": "Käyttöoikeudet",
"Perplexity API Key": "Perplexity API-avain",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personointi",
"Pin": "Kiinnitä",
"Pinned": "Kiinnitetty",
@ -965,6 +972,7 @@
"Preview": "Esikatselu",
"Previous 30 days": "Edelliset 30 päivää",
"Previous 7 days": "Edelliset 7 päivää",
"Previous message": "",
"Private": "Yksityinen",
"Profile Image": "Profiilikuva",
"Prompt": "Kehote",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Êtes-vous certain ?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "A parfaitement suivi les instructions",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nouveau mot de passe",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Document au format PDF (.pdf)",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Accès aux appareils multimédias refusé",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personnalisation",
"Pin": "Épingler",
"Pinned": "Épinglé",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 derniers jours",
"Previous 7 days": "7 derniers jours",
"Previous message": "",
"Private": "",
"Profile Image": "Image de profil",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Êtes-vous sûr de vouloir supprimer ce canal ?",
"Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?",
"Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations archivées?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Êtes-vous certain ?",
"Arena Models": "Modèles d'arène",
"Artifacts": "Artéfacts",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Dossier supprimé avec succès",
"Folder name cannot be empty.": "Le nom du dossier ne peut pas être vide.",
"Folder name updated successfully": "Le nom du dossier a été mis à jour avec succès",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "A parfaitement suivi les instructions",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nouveau mot de passe",
"New Tool": "",
"new-channel": "nouveau-canal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Document au format PDF (.pdf)",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Accès aux appareils multimédias refusé",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Accès au microphone refusé : {{error}}",
"Permissions": "Permissions",
"Perplexity API Key": "Clé d'API de Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personnalisation",
"Pin": "Épingler",
"Pinned": "Épinglé",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 derniers jours",
"Previous 7 days": "7 derniers jours",
"Previous message": "",
"Private": "Privé",
"Profile Image": "Image de profil",
"Prompt": "Prompt",

View file

@ -5,7 +5,7 @@
"(e.g. `sh webui.sh --api`)": "(למשל `sh webui.sh --api`)",
"(latest)": "(האחרון)",
"(leave blank for to use commercial endpoint)": "",
"{{ models }}": "{{ דגמים }}",
"{{ models }}": "{{ מודלים }}",
"{{COUNT}} Available Tools": "",
"{{COUNT}} hidden lines": "",
"{{COUNT}} Replies": "",
@ -17,39 +17,39 @@
"a user": "משתמש",
"About": "אודות",
"Accept autocomplete generation / Jump to prompt variable": "",
"Access": "",
"Access Control": "",
"Access": "גישה",
"Access Control": "בקרת גישה",
"Accessible to all users": "",
"Account": "חשבון",
"Account Activation Pending": "",
"Accurate information": "מידע מדויק",
"Actions": "",
"Actions": "פעולה",
"Activate": "",
"Activate this command by typing \"/{{COMMAND}}\" to chat input.": "",
"Active Users": "",
"Active Users": "משתמשים מחוברים",
"Add": "הוסף",
"Add a model ID": "",
"Add a short description about what this model does": "הוסף תיאור קצר אודות אופן הפעולה של מודל זה",
"Add a tag": "הוסף תג",
"Add Arena Model": "",
"Add Connection": "",
"Add Content": "",
"Add content here": "",
"Add Content": "הוסף תוכן",
"Add content here": "הוסף תוכן כאן",
"Add Custom Parameter": "",
"Add custom prompt": "הוסף פקודה מותאמת אישית",
"Add Files": "הוסף קבצים",
"Add Group": "",
"Add Group": "הוסף קבוצה",
"Add Memory": "הוסף זיכרון",
"Add Model": "הוסף מודל",
"Add Reaction": "",
"Add Tag": "",
"Add Tag": "הוסף תג",
"Add Tags": "הוסף תגים",
"Add text content": "",
"Add User": "הוסף משתמש",
"Add User Group": "",
"Adjusting these settings will apply changes universally to all users.": "התאמת הגדרות אלו תחול על כל המשתמשים.",
"admin": "מנהל",
"Admin": "",
"Admin": "מנהל",
"Admin Panel": "לוח בקרה למנהל",
"Admin Settings": "הגדרות מנהל",
"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
@ -57,15 +57,15 @@
"Advanced Params": "פרמטרים מתקדמים",
"All": "",
"All Documents": "כל המסמכים",
"All models deleted successfully": "",
"All models deleted successfully": "כל המודלים נמחקו בהצלחה",
"Allow Call": "",
"Allow Chat Controls": "",
"Allow Chat Delete": "",
"Allow Chat Deletion": "אפשר מחיקת צ'אט",
"Allow Chat Edit": "",
"Allow Chat Edit": "אפשר עריכת צ'אט",
"Allow Chat Export": "",
"Allow Chat Share": "",
"Allow File Upload": "",
"Allow Chat Share": "אפשר שיתוף צ'אט",
"Allow File Upload": "אפשר העלאת קובץ",
"Allow Multiple Models in Chat": "",
"Allow non-local voices": "",
"Allow Speech to Text": "",
@ -78,11 +78,11 @@
"Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "",
"Already have an account?": "כבר יש לך חשבון?",
"Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "",
"Always": "",
"Always": "תמיד",
"Always Collapse Code Blocks": "",
"Always Expand Details": "",
"Always Play Notification Sound": "",
"Amazing": "",
"Amazing": "מדהים",
"an assistant": "עוזר",
"Analyzed": "",
"Analyzing...": "",
@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "האם אתה בטוח?",
"Arena Models": "",
"Artifacts": "",
@ -124,7 +123,7 @@
"Auth": "",
"Authenticate": "",
"Authentication": "",
"Auto": "",
"Auto": "אוטומטי",
"Auto-Copy Response to Clipboard": "העתקה אוטומטית של תגובה ללוח",
"Auto-playback response": "תגובת השמעה אוטומטית",
"Autocomplete Generation": "",
@ -134,7 +133,7 @@
"AUTOMATIC1111 Base URL": "כתובת URL בסיסית של AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "נדרשת כתובת URL בסיסית של AUTOMATIC1111",
"Available list": "",
"Available Tools": "",
"Available Tools": "כלים זמינים",
"available!": "זמין!",
"Awful": "",
"Azure AI Speech": "",
@ -145,7 +144,7 @@
"Base Model (From)": "דגם בסיס (מ)",
"before": "לפני",
"Being lazy": "להיות עצלן",
"Beta": "",
"Beta": "בטא",
"Bing Search V7 Endpoint": "",
"Bing Search V7 Subscription Key": "",
"Bocha Search API Key": "",
@ -155,10 +154,10 @@
"By {{name}}": "",
"Bypass Embedding and Retrieval": "",
"Bypass Web Loader": "",
"Calendar": "",
"Calendar": "לוח שנה",
"Call": "",
"Call feature is not supported when using Web STT engine": "",
"Camera": "",
"Camera": "מצלמה",
"Cancel": "בטל",
"Capabilities": "יכולות",
"Capture": "",
@ -188,18 +187,18 @@
"Ciphers": "",
"Citation": "ציטוט",
"Citations": "",
"Clear memory": "",
"Clear Memory": "",
"click here": "",
"Clear memory": "נקה זיכרון",
"Clear Memory": "נקה",
"click here": "לחץ פה",
"Click here for filter guides.": "",
"Click here for help.": "לחץ כאן לעזרה.",
"Click here to": "לחץ כאן כדי",
"Click here to download user import template file.": "",
"Click here to learn more about faster-whisper and see the available models.": "",
"Click here to see available models.": "",
"Click here to learn more about faster-whisper and see the available models.": "לחץ כאן כדי ללמוד עוד על faster-whisper ולראות מודלים זמינים",
"Click here to see available models.": "לחץ כאן כדי לראות מודלים זמינים",
"Click here to select": "לחץ כאן לבחירה",
"Click here to select a csv file.": "לחץ כאן לבחירת קובץ csv.",
"Click here to select a py file.": "",
"Click here to select a py file.": "לחץ כאן כדי לבחירת קובץ py",
"Click here to upload a workflow.json file.": "",
"click here.": "לחץ כאן.",
"Click on the user role button to change a user's role.": "לחץ על כפתור תפקיד המשתמש כדי לשנות את תפקיד המשתמש.",
@ -208,9 +207,9 @@
"Clone Chat": "",
"Clone of {{TITLE}}": "",
"Close": "סגור",
"Code execution": "",
"Code Execution": "",
"Code Execution Engine": "",
"Code execution": "הרצת קוד",
"Code Execution": "הרצת קוד",
"Code Execution Engine": "מנוע הרצת קוד",
"Code Execution Timeout": "",
"Code formatted successfully": "",
"Code Interpreter": "",
@ -218,9 +217,9 @@
"Code Interpreter Prompt Template": "",
"Collapse": "",
"Collection": "אוסף",
"Color": "",
"Color": "צבע",
"ComfyUI": "ComfyUI",
"ComfyUI API Key": "",
"ComfyUI API Key": "מפתח API כל ComfyUI",
"ComfyUI Base URL": "כתובת URL בסיסית של ComfyUI",
"ComfyUI Base URL is required.": "נדרשת כתובת URL בסיסית של ComfyUI",
"ComfyUI Workflow": "",
@ -231,31 +230,31 @@
"Configure": "",
"Confirm": "",
"Confirm Password": "אשר סיסמה",
"Confirm your action": "",
"Confirm your new password": "",
"Confirm your action": "אשר את הפעולה שלך",
"Confirm your new password": "אשר את הסיסמה החדשה שלך",
"Connect to your own OpenAI compatible API endpoints.": "",
"Connect to your own OpenAPI compatible external tool servers.": "",
"Connection failed": "",
"Connection successful": "",
"Connection Type": "",
"Connection failed": "החיבור נכשל",
"Connection successful": "החיבור הצליח",
"Connection Type": "סוג חיבור",
"Connections": "חיבורים",
"Connections saved successfully": "",
"Connections saved successfully": "החיבור נשמר בהצלחה",
"Constrains effort on reasoning for reasoning models. Only applicable to reasoning models from specific providers that support reasoning effort.": "",
"Contact Admin for WebUI Access": "",
"Content": "תוכן",
"Content Extraction Engine": "",
"Continue Response": "המשך תגובה",
"Continue with {{provider}}": "",
"Continue with Email": "",
"Continue with LDAP": "",
"Continue with {{provider}}": "המשך עם {{provider}}",
"Continue with Email": "המשך עם מייל",
"Continue with LDAP": "המשך עם LDAP",
"Control how message text is split for TTS requests. 'Punctuation' splits into sentences, 'paragraphs' splits into paragraphs, and 'none' keeps the message as a single string.": "",
"Control the repetition of token sequences in the generated text. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 1.1) will be more lenient. At 1, it is disabled.": "",
"Controls": "",
"Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text.": "",
"Copied": "",
"Copied": "הועתק",
"Copied link to clipboard": "",
"Copied shared chat URL to clipboard!": "העתקת כתובת URL של צ'אט משותף ללוח!",
"Copied to clipboard": "",
"Copied to clipboard": "הועתק ללוח",
"Copy": "העתק",
"Copy Formatted Text": "",
"Copy last code block": "העתק את בלוק הקוד האחרון",
@ -270,11 +269,11 @@
"Create Account": "צור חשבון",
"Create Admin Account": "",
"Create Channel": "",
"Create Group": "",
"Create Group": "יצירת קבוצה",
"Create Knowledge": "",
"Create new key": "צור מפתח חדש",
"Create new secret key": "צור מפתח סודי חדש",
"Create Note": "",
"Create Note": "יצירת פתק",
"Create your first note by clicking on the plus button below.": "",
"Created at": "נוצר ב",
"Created At": "נוצר ב",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "עקב אחר ההוראות במושלמות",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -642,10 +645,10 @@
"Generate Image": "",
"Generate prompt pair": "",
"Generating search query": "יצירת שאילתת חיפוש",
"Generating...": "",
"Generating...": "מג'נרט...",
"Get started": "",
"Get started with {{WEBUI_NAME}}": "",
"Global": "",
"Global": "גלובלי",
"Good Response": "תגובה טובה",
"Google Drive": "",
"Google PSE API Key": "מפתח API של Google PSE",
@ -655,7 +658,7 @@
"Group Description": "",
"Group Name": "",
"Group updated successfully": "",
"Groups": "",
"Groups": "קבוצות",
"Haptic Feedback": "",
"Hello, {{name}}": "שלום, {{name}}",
"Help": "עזרה",
@ -663,9 +666,9 @@
"Hex Color": "",
"Hex Color - Leave empty for default color": "",
"Hide": "הסתר",
"Hide Model": "",
"Hide Model": "הסתר מודל",
"High Contrast Mode": "",
"Home": "",
"Home": "בית",
"Host": "",
"How can I help you today?": "כיצד אוכל לעזור לך היום?",
"How would you rate this response?": "",
@ -676,7 +679,7 @@
"iframe Sandbox Allow Forms": "",
"iframe Sandbox Allow Same Origin": "",
"Ignite curiosity": "",
"Image": "",
"Image": "תמונה",
"Image Compression": "",
"Image Generation": "",
"Image Generation (Experimental)": "יצירת תמונות (ניסיוני)",
@ -692,11 +695,11 @@
"Import From Link": "",
"Import Functions": "",
"Import Models": "ייבוא דגמים",
"Import Notes": "",
"Import Notes": "ייבוא פתקים",
"Import Presets": "",
"Import Prompt Suggestions": "",
"Import Prompts": "יבוא פקודות",
"Import Tools": "",
"Import Prompts": "ייבוא פקודות",
"Import Tools": "ייבוא כלים",
"Include": "",
"Include `--api-auth` flag when running stable-diffusion-webui": "",
"Include `--api` flag when running stable-diffusion-webui": "כלול את הדגל `--api` בעת הרצת stable-diffusion-webui",
@ -713,7 +716,7 @@
"Invalid JSON file": "",
"Invalid JSON schema": "",
"Invalid Tag": "תג לא חוקי",
"is typing...": "",
"is typing...": "מקליד...",
"January": "ינואר",
"Jina API Key": "",
"join our Discord for help.": "הצטרף ל-Discord שלנו לעזרה.",
@ -757,7 +760,7 @@
"Leave empty to include all models or select specific models": "",
"Leave empty to use the default prompt, or enter a custom prompt": "",
"Leave model field empty to use the default model.": "",
"License": "",
"License": "רישיון",
"Light": "בהיר",
"Listening...": "",
"Llama.cpp": "",
@ -795,7 +798,7 @@
"Memory updated successfully": "",
"Merge Responses": "",
"Merged Response": "תגובה ממוזגת",
"Message rating should be enabled to use this feature": "",
"Message rating should be enabled to use this feature": "דירוג הודעות צריך להיות מאופשר כדי להשתמש בפיצ'ר הזה",
"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "הודעות שתשלח לאחר יצירת הקישור לא ישותפו. משתמשים עם כתובת האתר יוכלו לצפות בצ'אט המשותף.",
"Microsoft OneDrive": "",
"Microsoft OneDrive (personal)": "",
@ -820,9 +823,9 @@
"Model Filtering": "",
"Model ID": "מזהה דגם",
"Model IDs": "",
"Model Name": "",
"Model Name": "שם המודל",
"Model not selected": "לא נבחר מודל",
"Model Params": "פרמס מודל",
"Model Params": "פרמטרי המודל",
"Model Permissions": "",
"Model unloaded successfully": "",
"Model updated successfully": "",
@ -835,22 +838,23 @@
"Mojeek Search API Key": "",
"more": "",
"More": "עוד",
"My Notes": "",
"My Notes": "הפתקים שלי",
"Name": "שם",
"Name your knowledge base": "",
"Native": "",
"New Chat": "צ'אט חדש",
"New Folder": "",
"New Function": "",
"New Note": "",
"New Folder": "תיקייה חדשה",
"New Function": "פונקציה חדשה",
"New Note": "פתק חדש",
"New Password": "סיסמה חדשה",
"New Tool": "",
"New Tool": "כלי חדש",
"new-channel": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
"No content found": "",
"No content found in file.": "",
"Next message": "",
"No chats found for this user.": "לא נמצאו צ'אטים ליוזר הזה.",
"No chats found.": "לא נמצאו צ'אטים",
"No content": "אין תוכן",
"No content found": "תוכן לא נמצא",
"No content found in file.": "לא נמצא תוכן בקובץ.",
"No content to speak": "",
"No distance available": "",
"No feedbacks found": "",
@ -867,14 +871,14 @@
"No results found": "לא נמצאו תוצאות",
"No search query generated": "לא נוצרה שאילתת חיפוש",
"No source available": "אין מקור זמין",
"No users were found.": "",
"No users were found.": "לא נמצאו יוזרים",
"No valves to update": "",
"None": "ללא",
"Not factually correct": "לא נכון מבחינה עובדתית",
"Not helpful": "",
"Note deleted successfully": "",
"Note deleted successfully": "פתק נמחק בהצלחה",
"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "הערה: אם תקבע ציון מינימלי, החיפוש יחזיר רק מסמכים עם ציון שגבוה או שווה לציון המינימלי.",
"Notes": "",
"Notes": "פתקים",
"Notification Sound": "",
"Notification Webhook": "",
"Notifications": "התראות",
@ -920,7 +924,7 @@
"Output format": "",
"Output Format": "",
"Overview": "",
"page": "",
"page": "עמוד",
"Paginate": "",
"Parameters": "",
"Password": "סיסמה",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "מסמך PDF (.pdf)",
"PDF Extract Images (OCR)": "חילוץ תמונות מ-PDF (OCR)",
"pending": "ממתין",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "ההרשאה נדחתה בעת גישה למיקרופון: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "תאור",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 הימים הקודמים",
"Previous 7 days": "7 הימים הקודמים",
"Previous message": "",
"Private": "",
"Profile Image": "תמונת פרופיל",
"Prompt": "",
@ -1068,7 +1076,7 @@
"Select a model": "בחר מודל",
"Select a pipeline": "בחר קו צינור",
"Select a pipeline url": "בחר כתובת URL של קו צינור",
"Select a tool": "",
"Select a tool": "בחר כלי",
"Select an auth method": "",
"Select an Ollama instance": "",
"Select Engine": "",
@ -1188,7 +1196,7 @@
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "ציון צריך להיות ערך בין 0.0 (0%) ל-1.0 (100%)",
"The temperature of the model. Increasing the temperature will make the model answer more creatively.": "",
"Theme": "נושא",
"Thinking...": "",
"Thinking...": "חושב...",
"This action cannot be undone. Do you wish to continue?": "",
"This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "",
"This chat wont appear in history and your messages will not be saved.": "",
@ -1216,7 +1224,7 @@
"Title Auto-Generation": "יצירת שם אוטומטית",
"Title cannot be an empty string.": "שם לא יכול להיות מחרוזת ריקה.",
"Title Generation": "",
"Title Generation Prompt": "שאלה ליצירת שם",
"Title Generation Prompt": "פרומפט ליצירת כותרת",
"TLS": "",
"To access the available model names for downloading,": "כדי לגשת לשמות הדגמים הזמינים להורדה,",
"To access the GGUF models available for downloading,": "כדי לגשת לדגמי GGUF הזמינים להורדה,",
@ -1242,7 +1250,7 @@
"Tool Name": "",
"Tool Servers": "",
"Tool updated successfully": "",
"Tools": "",
"Tools": "כלים",
"Tools Access": "",
"Tools are a function calling system with arbitrary code execution": "",
"Tools Function Calling Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "क्या आपको यकीन है?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "निर्देशों का पूर्णतः पालन किया",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "नया पासवर्ड",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF दस्तावेज़ (.pdf)",
"PDF Extract Images (OCR)": "PDF छवियाँ निकालें (OCR)",
"pending": "लंबित",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "माइक्रोफ़ोन तक पहुँचने पर अनुमति अस्वीकृत: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "पेरसनलाइज़मेंट",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "पिछले 30 दिन",
"Previous 7 days": "पिछले 7 दिन",
"Previous message": "",
"Private": "",
"Profile Image": "प्रोफ़ाइल छवि",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Jeste li sigurni?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Savršeno slijedio upute",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nova lozinka",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokument (.pdf)",
"PDF Extract Images (OCR)": "PDF izdvajanje slika (OCR)",
"pending": "u tijeku",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Dopuštenje je odbijeno prilikom pristupa medijskim uređajima",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Pristup mikrofonu odbijen: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Prilagodba",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Prethodnih 30 dana",
"Previous 7 days": "Prethodnih 7 dana",
"Previous message": "",
"Private": "",
"Profile Image": "Profilna slika",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Biztosan törölni szeretnéd ezt a csatornát?",
"Are you sure you want to delete this message?": "Biztosan törölni szeretnéd ezt az üzenetet?",
"Are you sure you want to unarchive all archived chats?": "Biztosan vissza szeretnéd állítani az összes archivált csevegést?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Biztos vagy benne?",
"Arena Models": "Arena modellek",
"Artifacts": "Műtermékek",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Mappa sikeresen törölve",
"Folder name cannot be empty.": "A mappa neve nem lehet üres.",
"Folder name updated successfully": "Mappa neve sikeresen frissítve",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Tökéletesen követte az utasításokat",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Új jelszó",
"New Tool": "",
"new-channel": "új csatorna",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokumentum (.pdf)",
"PDF Extract Images (OCR)": "PDF képek kinyerése (OCR)",
"pending": "függőben",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Hozzáférés megtagadva a médiaeszközökhöz",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Hozzáférés megtagadva a mikrofonhoz: {{error}}",
"Permissions": "Engedélyek",
"Perplexity API Key": "Perplexity API kulcs",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Személyre szabás",
"Pin": "Rögzítés",
"Pinned": "Rögzítve",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Előző 30 nap",
"Previous 7 days": "Előző 7 nap",
"Previous message": "",
"Private": "Privát",
"Profile Image": "Profilkép",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Apakah Anda yakin?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Mengikuti instruksi dengan sempurna",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Kata Sandi Baru",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Dokumen PDF (.pdf)",
"PDF Extract Images (OCR)": "Ekstrak Gambar PDF (OCR)",
"pending": "tertunda",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Izin ditolak saat mengakses perangkat media",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Izin ditolak saat mengakses mikrofon: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalisasi",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 hari sebelumnya",
"Previous 7 days": "7 hari sebelumnya",
"Previous message": "",
"Private": "",
"Profile Image": "Gambar Profil",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "An bhfuil tú cinnte gur mhaith leat an cainéal seo a scriosadh?",
"Are you sure you want to delete this message?": "An bhfuil tú cinnte gur mhaith leat an teachtaireacht seo a scriosadh?",
"Are you sure you want to unarchive all archived chats?": "An bhfuil tú cinnte gur mhaith leat gach comhrá cartlainne a dhíchartlannú?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "An bhfuil tú cinnte?",
"Arena Models": "Múnlaí Airéine",
"Artifacts": "Déantáin",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Scriosadh an fillteán go rathúil",
"Folder name cannot be empty.": "Ní féidir ainm fillteáin a bheith folamh.",
"Folder name updated successfully": "D'éirigh le hainm an fhillteáin a nuashonrú",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Lean treoracha go foirfe",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Pasfhocal Nua",
"New Tool": "",
"new-channel": "nua-chainéil",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Doiciméad PDF (.pdf)",
"PDF Extract Images (OCR)": "Íomhánna Sliocht PDF (OCR)",
"pending": "ar feitheamh",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Cead diúltaithe nuair a bhíonn rochtain agat",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Cead diúltaithe agus tú ag teacht ar mhicreafón: {{error}}",
"Permissions": "Ceadanna",
"Perplexity API Key": "Eochair API Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Pearsantú",
"Pin": "Bioráin",
"Pinned": "Pinneáilte",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 lá roimhe seo",
"Previous 7 days": "7 lá roimhe seo",
"Previous message": "",
"Private": "Príobháideach",
"Profile Image": "Íomhá Próifíl",
"Prompt": "Leid",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Sei sicuro di voler eliminare questo canale?",
"Are you sure you want to delete this message?": "Sei sicuro di voler eliminare questo messaggio?",
"Are you sure you want to unarchive all archived chats?": "Sei sicuro di voler disarchiviare tutte le chat archiviate?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "Sei sicuro di voler aggiornare il ruolo di questo utente in **{{ROLE}}**?",
"Are you sure?": "Sei sicuro?",
"Arena Models": "Modelli Arena",
"Artifacts": "Artefatti",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Cartella rimossa con successo",
"Folder name cannot be empty.": "Il nome della cartella non può essere vuoto.",
"Folder name updated successfully": "Nome cartella aggiornato con successo",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Ha seguito le istruzioni alla perfezione",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nuova password",
"New Tool": "",
"new-channel": "nuovo-canale",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "Nessun contenuto",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Documento PDF (.pdf)",
"PDF Extract Images (OCR)": "Estrazione Immagini PDF (OCR)",
"pending": "in sospeso",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Autorizzazione negata durante l'accesso ai dispositivi multimediali",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Autorizzazione negata durante l'accesso al microfono: {{error}}",
"Permissions": "Permessi",
"Perplexity API Key": "Chiave API Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizzazione",
"Pin": "Fissa",
"Pinned": "Fissato",
@ -965,6 +972,7 @@
"Preview": "Anteprima",
"Previous 30 days": "Ultimi 30 giorni",
"Previous 7 days": "Ultimi 7 giorni",
"Previous message": "",
"Private": "Privato",
"Profile Image": "Immagine del Profilo",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "このチャンネルを削除しますか?",
"Are you sure you want to delete this message?": "このメッセージを削除しますか?",
"Are you sure you want to unarchive all archived chats?": "すべてのアーカイブされたチャットをアンアーカイブしますか?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "このユーザーの役割を **{{ROLE}}** に更新しますか?",
"Are you sure?": "よろしいですか?",
"Arena Models": "Arenaモデル",
"Artifacts": "アーティファクト",
@ -611,6 +610,10 @@
"Folder deleted successfully": "フォルダー削除が成功しました。",
"Folder name cannot be empty.": "フォルダー名を入力してください。",
"Folder name updated successfully": "フォルダー名更新が成功しました。",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "完全に指示に従った",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "新しいパスワード",
"New Tool": "",
"new-channel": "新しいチャンネル",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "内容がありません",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ドキュメント (.pdf)",
"PDF Extract Images (OCR)": "PDF 画像抽出 (OCR)",
"pending": "保留中",
"Pending": "",
"Pending User Overlay Content": "保留中のユーザー情報オーバーレイの内容",
"Pending User Overlay Title": "保留中のユーザー情報オーバーレイのタイトル",
"Permission denied when accessing media devices": "メディアデバイスへのアクセス時に権限が拒否されました",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "マイクへのアクセス時に権限が拒否されました: {{error}}",
"Permissions": "許可",
"Perplexity API Key": "Perplexity API キー",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "個人化",
"Pin": "ピン留め",
"Pinned": "ピン留めされています",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "前の30日間",
"Previous 7 days": "前の7日間",
"Previous message": "",
"Private": "プライベート",
"Profile Image": "プロフィール画像",
"Prompt": "プロンプト",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "დარწმუნებული ბრძანდებით?",
"Arena Models": "არენის მოდელები",
"Artifacts": "არტეფაქტები",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "ინსტრუქციების ზუსტად მიჰყევით",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "ახალი პაროლი",
"New Tool": "",
"new-channel": "new-channel",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF დოკუმენტი (.pdf)",
"PDF Extract Images (OCR)": "PDF იდან ამოღებული სურათები (OCR)",
"pending": "დარჩენილი",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "ნებართვა უარყოფილია მიკროფონზე წვდომისას: {{error}}",
"Permissions": "ნებართვები",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "პერსონალიზაცია",
"Pin": "მიმაგრება",
"Pinned": "მიმაგრებულია",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "წინა 30 დღე",
"Previous 7 days": "წინა 7 დღე",
"Previous message": "",
"Private": "",
"Profile Image": "პროფილის სურათი",
"Prompt": "ბრძანების შეყვანის შეხსენება",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "정말 이 채널을 삭제하시겠습니까?",
"Are you sure you want to delete this message?": "정말 이 메세지를 삭제하시겠습니까?",
"Are you sure you want to unarchive all archived chats?": "정말 보관된 모든 채팅을 보관 해제하시겠습니까?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "확실합니까?",
"Arena Models": "Arena 모델",
"Artifacts": "아티팩트",
@ -611,6 +610,10 @@
"Folder deleted successfully": "성공적으로 폴터가 생성되었습니다",
"Folder name cannot be empty.": "폴더 이름을 작성해주세요",
"Folder name updated successfully": "성공적으로 폴더 이름이 저장되었습니다",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "명령을 완벽히 수행함",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "새 비밀번호",
"New Tool": "",
"new-channel": "새 채널",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "내용 없음",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF 문서(.pdf)",
"PDF Extract Images (OCR)": "PDF 이미지 추출(OCR)",
"pending": "보류 중",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "미디어 장치 접근 권한이 거부되었습니다.",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "마이크 접근 권환이 거부되었습니다: {{error}}",
"Permissions": "권한",
"Perplexity API Key": "Perplexity API 키",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "개인화",
"Pin": "고정",
"Pinned": "고정됨",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "이전 30일",
"Previous 7 days": "이전 7일",
"Previous message": "",
"Private": "비공개",
"Profile Image": "프로필 이미지",
"Prompt": "프롬프트",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Are esate tikri?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Tobulai sekė instrukcijas",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Naujas slaptažodis",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokumentas (.pdf)",
"PDF Extract Images (OCR)": "PDF paveikslėlių skaitymas (OCR)",
"pending": "laukiama",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Leidimas atmestas bandant prisijungti prie medijos įrenginių",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Leidimas naudoti mikrofoną atmestas: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizacija",
"Pin": "Smeigtukas",
"Pinned": "Įsmeigta",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Paskutinės 30 dienų",
"Previous 7 days": "Paskutinės 7 dienos",
"Previous message": "",
"Private": "",
"Profile Image": "Profilio nuotrauka",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Adakah anda pasti",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Mengikut arahan dengan sempurna",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Kata Laluan Baru",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Dokumen PDF (.pdf)",
"PDF Extract Images (OCR)": "Imej Ekstrak PDF (OCR)",
"pending": "tertunda",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Tidak mendapat kebenaran apabila cuba mengakses peranti media",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Tidak mendapat kebenaran apabila cuba mengakses mikrofon: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalisasi",
"Pin": "Pin",
"Pinned": "Disemat",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "30 hari sebelumnya",
"Previous 7 days": "7 hari sebelumnya",
"Previous message": "",
"Private": "",
"Profile Image": "Imej Profail",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Er du sikker på at du vil slette denne kanalen?",
"Are you sure you want to delete this message?": "Er du sikker på at du vil slette denne meldingen?",
"Are you sure you want to unarchive all archived chats?": "Er du sikker på at du vil oppheve arkiveringen av alle arkiverte chatter?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Er du sikker?",
"Arena Models": "Arena-modeller",
"Artifacts": "Artifakter",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Mappe slettet",
"Folder name cannot be empty.": "Mappenavn kan ikke være tomt.",
"Folder name updated successfully": "Mappenavn oppdatert",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Fulgte instruksjonene perfekt",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nytt passord",
"New Tool": "",
"new-channel": "ny-kanal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF-dokument (.pdf)",
"PDF Extract Images (OCR)": "Uthenting av PDF-bilder (OCR)",
"pending": "avventer",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Tilgang avslått ved bruk av medieenheter",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Tilgang avslått ved bruk av mikrofonen: {{error}}",
"Permissions": "Tillatelser",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Tilpassing",
"Pin": "Fest",
"Pinned": "Festet",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Siste 30 dager",
"Previous 7 days": "Siste 7 dager",
"Previous message": "",
"Private": "",
"Profile Image": "Profilbilde",
"Prompt": "Ledetekst",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Weet je zeker dat je dit kanaal wil verwijderen?",
"Are you sure you want to delete this message?": "Weet je zeker dat je dit bericht wil verwijderen?",
"Are you sure you want to unarchive all archived chats?": "Weet je zeker dat je alle gearchiveerde chats wil onarchiveren?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Weet je het zeker?",
"Arena Models": "Arenamodellen",
"Artifacts": "Artefacten",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Map succesvol verwijderd",
"Folder name cannot be empty.": "Mapnaam kan niet leeg zijn",
"Folder name updated successfully": "Mapnaam succesvol aangepast",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Volgde instructies perfect",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nieuw Wachtwoord",
"New Tool": "",
"new-channel": "nieuw-kanaal",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF document (.pdf)",
"PDF Extract Images (OCR)": "PDF extraheer afbeeldingen (OCR)",
"pending": "wachtend",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Toegang geweigerd bij het toegang krijgen tot media-apparaten",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Toestemming geweigerd bij toegang tot microfoon: {{error}}",
"Permissions": "Toestemmingen",
"Perplexity API Key": "Perplexity API-sleutel",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalisatie",
"Pin": "Zet vast",
"Pinned": "Vastgezet",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Afgelopen 30 dagen",
"Previous 7 days": "Afgelopen 7 dagen",
"Previous message": "",
"Private": "Privé",
"Profile Image": "Profielafbeelding",
"Prompt": "Prompt",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਹੋ?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "ਹਦਾਇਤਾਂ ਨੂੰ ਬਿਲਕੁਲ ਫਾਲੋ ਕੀਤਾ",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "ਨਵਾਂ ਪਾਸਵਰਡ",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF ਡਾਕੂਮੈਂਟ (.pdf)",
"PDF Extract Images (OCR)": "PDF ਚਿੱਤਰ ਕੱਢੋ (OCR)",
"pending": "ਬਕਾਇਆ",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚਣ ਸਮੇਂ ਆਗਿਆ ਰੱਦ ਕੀਤੀ ਗਈ: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "ਪਰਸੋਨਲਿਸ਼ਮ",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "ਪਿਛਲੇ 30 ਦਿਨ",
"Previous 7 days": "ਪਿਛਲੇ 7 ਦਿਨ",
"Previous message": "",
"Private": "",
"Profile Image": "ਪ੍ਰੋਫਾਈਲ ਚਿੱਤਰ",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Czy na pewno chcesz usunąć ten kanał?",
"Are you sure you want to delete this message?": "Czy na pewno chcesz usunąć tę wiadomość?",
"Are you sure you want to unarchive all archived chats?": "Czy na pewno chcesz przywrócić wszystkie zapisane rozmowy?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Czy jesteś pewien?",
"Arena Models": "Modele Areny",
"Artifacts": "Artefakty",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Folder został usunięty pomyślnie",
"Folder name cannot be empty.": "Nazwa folderu nie może być pusta.",
"Folder name updated successfully": "Nazwa folderu została zaktualizowana pomyślnie",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Wykonał instrukcje idealnie",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nowe hasło",
"New Tool": "",
"new-channel": "nowy-kanał",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Dokument PDF (.pdf)",
"PDF Extract Images (OCR)": "PDF Ekstrahuj obrazy (OCR)",
"pending": "oczekiwanie",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Odmowa dostępu podczas uzyskiwania dostępu do urządzeń multimedialnych",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Odmowa dostępu do mikrofonu: {{error}}",
"Permissions": "Uprawnienia",
"Perplexity API Key": "Klucz API Perplexity",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizacja",
"Pin": "Przypnij",
"Pinned": "Przypięty",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Ostatnie 30 dni",
"Previous 7 days": "Ostatnie 7 dni",
"Previous message": "",
"Private": "",
"Profile Image": "Zdjęcie profilowe",
"Prompt": "Wprowadź prompt: ",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "Você tem certeza que deseja desarquivar todos os chats arquivados?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Você tem certeza?",
"Arena Models": "Arena de Modelos",
"Artifacts": "Artefatos",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Pasta excluída com sucesso",
"Folder name cannot be empty.": "Nome da pasta não pode estar vazio.",
"Folder name updated successfully": "Nome da pasta atualizado com sucesso",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Seguiu as instruções perfeitamente",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nova Senha",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Documento PDF (.pdf)",
"PDF Extract Images (OCR)": "Extrair Imagens do PDF (OCR)",
"pending": "pendente",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Permissão negada ao acessar dispositivos de mídia",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}",
"Permissions": "Permissões",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalização",
"Pin": "Fixar",
"Pinned": "Fixado",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Últimos 30 dias",
"Previous 7 days": "Últimos 7 dias",
"Previous message": "",
"Private": "",
"Profile Image": "Imagem de Perfil",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Tem a certeza?",
"Arena Models": "",
"Artifacts": "",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Seguiu instruções perfeitamente",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nova Senha",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Documento PDF (.pdf)",
"PDF Extract Images (OCR)": "Extrair Imagens de PDF (OCR)",
"pending": "pendente",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "A permissão foi negada ao aceder aos dispositivos de media",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "A permissão foi negada ao aceder o microfone: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalização",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Últimos 30 dias",
"Previous 7 days": "Últimos 7 dias",
"Previous message": "",
"Private": "",
"Profile Image": "Imagem de Perfil",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Ești sigur că vrei să ștergi acest canal?",
"Are you sure you want to delete this message?": "Ești sigur că vrei să ștergi acest mesaj?",
"Are you sure you want to unarchive all archived chats?": "Ești sigur că vrei să dezarhivezi toate conversațiile arhivate?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Ești sigur?",
"Arena Models": "Arena Models",
"Artifacts": "Artefacte",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Folder șters cu succes",
"Folder name cannot be empty.": "Numele folderului nu poate fi gol.",
"Folder name updated successfully": "Numele folderului a fost actualizat cu succes",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "A urmat instrucțiunile perfect",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Parolă Nouă",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "Document PDF (.pdf)",
"PDF Extract Images (OCR)": "Extrage Imagini PDF (OCR)",
"pending": "în așteptare",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Permisiunea refuzată la accesarea dispozitivelor media",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Permisiunea refuzată la accesarea microfonului: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizare",
"Pin": "Fixează",
"Pinned": "Fixat",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Ultimele 30 de zile",
"Previous 7 days": "Ultimele 7 zile",
"Previous message": "",
"Private": "",
"Profile Image": "Imagine de Profil",
"Prompt": "",

View file

@ -35,7 +35,7 @@
"Add Connection": "Добавить соединение",
"Add Content": "Добавить контент",
"Add content here": "Добавить контент сюда",
"Add Custom Parameter": "",
"Add Custom Parameter": "Добавить пользовательский параметр",
"Add custom prompt": "Добавьте пользовательский промпт",
"Add Files": "Добавить файлы",
"Add Group": "Добавить группу",
@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Вы уверены, что хотите удалить этот канал?",
"Are you sure you want to delete this message?": "Вы уверены, что хотите удалить это сообщение?",
"Are you sure you want to unarchive all archived chats?": "Вы уверены, что хотите разархивировать все заархивированные чаты?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "Вы уверены, что хотите изменить роль этого пользователя на **{{ROLE}}**?",
"Are you sure?": "Вы уверены?",
"Arena Models": "Арена моделей",
"Artifacts": "Артефакты",
@ -284,18 +283,18 @@
"Current Model": "Текущая модель",
"Current Password": "Текущий пароль",
"Custom": "Пользовательский",
"Custom Parameter Name": "",
"Custom Parameter Value": "",
"Custom Parameter Name": "Название пользовательского параметра",
"Custom Parameter Value": "Значение пользовательского параметра",
"Danger Zone": "Опасная зона",
"Dark": "Темная",
"Database": "База данных",
"Datalab Marker API": "",
"Datalab Marker API Key required.": "",
"Datalab Marker API Key required.": "Требуется API-ключ Datalab Marker.",
"December": "Декабрь",
"Default": "По умолчанию",
"Default (Open AI)": "По умолчанию (Open AI)",
"Default (SentenceTransformers)": "По умолчанию (SentenceTransformers)",
"Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the models built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Режим по умолчанию работает с более широким спектром моделей, вызывая инструменты один раз перед выполнением. Режим Native использует встроенные в модель возможности вызова инструментов, но требует, чтобы модель изначально поддерживала эту функцию.",
"Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the models built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Режим по умолчанию работает с более широким спектром моделей, вызывая инструменты один раз перед выполнением. Режим Нативно использует встроенные в модель возможности вызова инструментов, но требует, чтобы модель изначально поддерживала эту функцию.",
"Default Model": "Модель по умолчанию",
"Default model updated": "Модель по умолчанию обновлена",
"Default Models": "Модели по умолчанию",
@ -325,7 +324,7 @@
"Deleted {{deleteModelTag}}": "Удалено {{deleteModelTag}}",
"Deleted {{name}}": "Удалено {{name}}",
"Deleted User": "Удалённый пользователь",
"Deployment names are required for Azure OpenAI": "Для Azure OpenAI требуются имена развертываний",
"Deployment names are required for Azure OpenAI": "Для Azure OpenAI требуются названия развертываний",
"Describe Pictures in Documents": "Опишите изображения в документах",
"Describe your knowledge base and objectives": "Опишите свою базу знаний и цели",
"Description": "Описание",
@ -337,8 +336,8 @@
"Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Прямые подключения позволяют пользователям подключаться к своим собственным конечным точкам API, совместимым с OpenAI.",
"Direct Connections settings updated": "Настройки прямых подключений обновлены",
"Direct Tool Servers": "Доступ к серверам инструментов",
"Disable Image Extraction": "",
"Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "",
"Disable Image Extraction": "Отключить извлечение изображений",
"Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Отключить извлечение изображений из PDF. Если включена параметр Использовать LLM, изображения будут подписаны автоматически. По умолчанию установлено значение Выкл.",
"Disabled": "Отключено",
"Discover a function": "Найти функцию",
"Discover a model": "Найти модель",
@ -393,7 +392,7 @@
"e.g., 3, 4, 5 (leave blank for default)": "например, 3, 4, 5 (оставьте поле пустым по умолчанию)",
"e.g., en-US,ja-JP (leave blank for auto-detect)": "например, en-US,ja-JP (оставьте поле пустым для автоматического определения)",
"e.g., westus (leave blank for eastus)": "например, западный (оставьте пустым для восточного)",
"e.g.) en,fr,de": "",
"e.g.) en,fr,de": "например) en,fr,de",
"Edit": "Редактировать",
"Edit Arena Model": "Изменить модель арены",
"Edit Channel": "Редактировать канал",
@ -428,7 +427,7 @@
"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Убедитесь, что ваш CSV-файл включает в себя 4 столбца в следующем порядке: Имя, Электронная почта, Пароль, Роль.",
"Enter {{role}} message here": "Введите сообщение {{role}} здесь",
"Enter a detail about yourself for your LLMs to recall": "Введите детали о себе, чтобы LLMs могли запомнить",
"Enter a title for the pending user info overlay. Leave empty for default.": "Введите заголовок для ожидаемого отображения информации о пользователе. Оставьте поле пустым для параметра по умолчанию.",
"Enter a title for the pending user info overlay. Leave empty for default.": "Введите заголовок информационного оверлея для ожидающего пользователя. Оставьте поле пустым для параметра по умолчанию.",
"Enter a watermark for the response. Leave empty for none.": "Укажите водяной знак для ответа. Оставьте пустым чтобы не было никакого.",
"Enter api auth string (e.g. username:password)": "Введите строку авторизации api (например, username:password)",
"Enter Application DN": "Введите ND приложения",
@ -443,8 +442,8 @@
"Enter Chunk Overlap": "Введите перекрытие фрагмента",
"Enter Chunk Size": "Введите размер фрагмента",
"Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Введите пары \"token:bias_value\", разделенные запятыми (пример: 5432:100, 413:-100).",
"Enter content for the pending user info overlay. Leave empty for default.": "Введите содержимое для отложенного отображения информации о пользователе. Оставьте поле пустым для параметра по умолчанию.",
"Enter Datalab Marker API Key": "",
"Enter content for the pending user info overlay. Leave empty for default.": "Введите содержимое информационного оверлея для ожидающего пользователя. Оставьте поле пустым для параметра по умолчанию.",
"Enter Datalab Marker API Key": "Введите API-ключ Datalab Marker",
"Enter description": "Введите описание",
"Enter Docling OCR Engine": "Введите Docling OCR Engine",
"Enter Docling OCR Language(s)": "Введите языки для Docling OCR",
@ -476,7 +475,7 @@
"Enter Model ID": "Введите ID модели",
"Enter model tag (e.g. {{modelTag}})": "Введите тег модели (например, {{modelTag}})",
"Enter Mojeek Search API Key": "Введите ключ API поиска Mojeek",
"Enter name": "Введите название",
"Enter name": "Введите имя",
"Enter New Password": "Введите новый пароль",
"Enter Number of Steps (e.g. 50)": "Введите количество шагов (например, 50)",
"Enter Perplexity API Key": "Введите ключ API Perplexity",
@ -508,7 +507,7 @@
"Enter Tavily Extract Depth": "Укажите глубину извлечения Tavily",
"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Введите общедоступный URL вашего WebUI. Этот URL будет использоваться для создания ссылок в уведомлениях.",
"Enter the URL of the function to import": "Введите URL-адрес функции для импорта",
"Enter the URL to import": "",
"Enter the URL to import": "Введите URL-адрес для импорта",
"Enter Tika Server URL": "Введите URL-адрес сервера Tika",
"Enter timeout in seconds": "Введите время ожидания в секундах",
"Enter to Send": "Enter для отправки",
@ -609,11 +608,15 @@
"Fluidly stream large external response chunks": "Плавная потоковая передача больших фрагментов внешних ответов",
"Focus chat input": "Фокус ввода чата",
"Folder deleted successfully": "Папка успешно удалена",
"Folder name cannot be empty.": "Имя папки не может быть пустым.",
"Folder name updated successfully": "Имя папки успешно обновлено",
"Followed instructions perfectly": "Идеально соответствует инструкциям",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
"Folder name cannot be empty.": "Название папки не может быть пустым.",
"Folder name updated successfully": "Название папки успешно обновлено",
"Follow up": "Продолжить",
"Follow Up Generation": "Генерация продолжения",
"Follow Up Generation Prompt": "Промпт генерации продолжения",
"Follow-Up Auto-Generation": "Автоматическая генерация продолжения",
"Followed instructions perfectly": "В точности следовал инструкциям",
"Force OCR": "Принудительное OCR",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "Принудительное OCR на всех страницах PDF-файла. Это может привести к ухудшению результатов, если в ваших PDF-файлах есть хороший текст. По умолчанию установлено значение Выкл.",
"Forge new paths": "Прокладывайте новые пути",
"Form": "Форма",
"Format your variables using brackets like this:": "Отформатируйте переменные, используя такие : скобки",
@ -625,10 +628,10 @@
"Function deleted successfully": "Функция успешно удалена",
"Function Description": "Описание Функции",
"Function ID": "ID Функции",
"Function imported successfully": "",
"Function imported successfully": "Функция успешно импортирована",
"Function is now globally disabled": "Функция теперь глобально отключена",
"Function is now globally enabled": "Функция теперь глобально включена",
"Function Name": "Имя Функции",
"Function Name": "Название Функции",
"Function updated successfully": "Функция успешно обновлена",
"Functions": "Функции",
"Functions allow arbitrary code execution.": "Функции позволяют выполнять произвольный код.",
@ -742,7 +745,7 @@
"Landing Page Mode": "Режим целевой страницы",
"Language": "Язык",
"Language Locales": "Языковые особенности",
"Languages": "",
"Languages": "Языки",
"Last Active": "Последняя активность",
"Last Modified": "Последнее изменение",
"Last reply": "Последний ответ",
@ -820,7 +823,7 @@
"Model Filtering": "Фильтрация Моделей",
"Model ID": "ID Модели",
"Model IDs": "IDs Модели",
"Model Name": "Имя Модели",
"Model Name": "Название Модели",
"Model not selected": "Модель не выбрана",
"Model Params": "Параметры модели",
"Model Permissions": "Разрешения Модели",
@ -844,8 +847,9 @@
"New Function": "Новая функция",
"New Note": "Новая заметка",
"New Password": "Новый пароль",
"New Tool": "",
"New Tool": "Новый инструмент",
"new-channel": "",
"Next message": "Следующее сообщение",
"No chats found for this user.": "Для этого пользователя не найдено ни одного чата.",
"No chats found.": "Не найдено ни одного чата",
"No content": "Нет контента",
@ -918,23 +922,26 @@
"Other": "Прочее",
"OUTPUT": "",
"Output format": "Формат вывода",
"Output Format": "",
"Output Format": "Формат Вывода",
"Overview": "Обзор",
"page": "страница",
"Paginate": "",
"Paginate": "Разбивка на страницы",
"Parameters": "Параметры",
"Password": "Пароль",
"Paste Large Text as File": "Вставить большой текст как файл",
"PDF document (.pdf)": "PDF-документ (.pdf)",
"PDF Extract Images (OCR)": "Извлечение изображений из PDF (OCR)",
"pending": "ожидающий",
"Pending User Overlay Content": "Ожидание контента пользовательского оверлея",
"Pending User Overlay Title": "Ожидание заголовка пользовательского оверлея",
"Pending": "Ожидающий",
"Pending User Overlay Content": "Содержимое оверлея ожидающего пользователя",
"Pending User Overlay Title": "Заголовк оверлея ожидающего пользователя",
"Permission denied when accessing media devices": "Отказано в разрешении на доступ к мультимедийным устройствам",
"Permission denied when accessing microphone": "Отказано в разрешении на доступ к микрофону",
"Permission denied when accessing microphone: {{error}}": "Отказано в разрешении на доступ к микрофону: {{error}}",
"Permissions": "Разрешения",
"Perplexity API Key": "Ключ API для Perplexity",
"Perplexity Model": "Модель Perplexity",
"Perplexity Search Context Usage": "Использование контекста поиска Perplexity",
"Personalization": "Персонализация",
"Pin": "Закрепить",
"Pinned": "Закреплено",
@ -965,6 +972,7 @@
"Preview": "Предпросмотр",
"Previous 30 days": "Предыдущие 30 дней",
"Previous 7 days": "Предыдущие 7 дней",
"Previous message": "Предыдущее сообщение",
"Private": "Частное",
"Profile Image": "Изображение профиля",
"Prompt": "Промпт",
@ -986,7 +994,7 @@
"Re-rank models by topic similarity": "Повторное ранжирование моделей по сходству тем",
"Read": "Прочитать",
"Read Aloud": "Прочитать вслух",
"Reasoning Effort": "Усилие рассуждения",
"Reasoning Effort": "",
"Record": "Запись",
"Record voice": "Записать голос",
"Redirecting you to Open WebUI Community": "Перенаправляем вас в сообщество OpenWebUI",
@ -1060,7 +1068,7 @@
"Searxng Query URL": "URL-адрес запроса Searxng",
"See readme.md for instructions": "Смотрите readme.md для инструкций",
"See what's new": "Посмотреть, что нового",
"Seed": "Сид",
"Seed": "",
"Select a base model": "Выберите базовую модель",
"Select a engine": "Выберите движок",
"Select a function": "Выберите функцию",
@ -1128,11 +1136,11 @@
"Sign Out": "Выйти",
"Sign up": "Зарегистрироваться",
"Sign up to {{WEBUI_NAME}}": "Регистрация в {{WEBUI_NAME}}",
"Significantly improves accuracy by using an LLM to enhance tables, forms, inline math, and layout detection. Will increase latency. Defaults to True.": "",
"Significantly improves accuracy by using an LLM to enhance tables, forms, inline math, and layout detection. Will increase latency. Defaults to True.": "Значительно повышает точность за счет использования LLM для улучшения работы с таблицами, формами, встроенной математикой и распознавания макета. Увеличивает задержку. По умолчанию установлено значение Вкл.",
"Signing in to {{WEBUI_NAME}}": "Зарегистрироваться в {{WEBUI_NAME}}",
"sk-1234": "",
"Skip Cache": "",
"Skip the cache and re-run the inference. Defaults to False.": "",
"Skip Cache": "Пропустить кэширование",
"Skip the cache and re-run the inference. Defaults to False.": "Пропустить кэширование и перезапустить вывод. По умолчанию установлено значение Выкл.",
"Sougou Search API sID": "",
"Sougou Search API SK": "",
"Source": "Источник",
@ -1140,10 +1148,10 @@
"Speech recognition error: {{error}}": "Ошибка распознавания речи: {{error}}",
"Speech-to-Text Engine": "Система распознавания речи",
"Stop": "Остановить",
"Stop Sequence": "Последовательность остановки",
"Stop Sequence": "",
"Stream Chat Response": "Потоковый вывод ответа",
"Strip Existing OCR": "",
"Strip existing OCR text from the PDF and re-run OCR. Ignored if Force OCR is enabled. Defaults to False.": "",
"Strip Existing OCR": "Удалять существующие OCR",
"Strip existing OCR text from the PDF and re-run OCR. Ignored if Force OCR is enabled. Defaults to False.": "Удалять существующий текст OCR из PDF и перезапустить OCR. Игнорируется если Принудительное OCR включено. По умолчанию установлено значение Выкл.",
"STT Model": "Модель распознавания речи",
"STT Settings": "Настройки распознавания речи",
"Stylized PDF Export": "Стилизованный экспорт в формате PDF",
@ -1168,7 +1176,7 @@
"Tavily API Key": "Ключ API Tavily",
"Tavily Extract Depth": "Глубина извлечения Tavily",
"Tell us more:": "Пожалуйста, расскажите нам больше:",
"Temperature": "Температура",
"Temperature": "",
"Temporary Chat": "Временный чат",
"Text Splitter": "Разделитель текста",
"Text-to-Speech Engine": "Система синтеза речи",
@ -1184,7 +1192,7 @@
"The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "В настоящее время таблица лидеров находится в стадии бета-тестирования, и мы можем скорректировать расчеты рейтинга по мере доработки алгоритма.",
"The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Максимальный размер файла в МБ. Если размер файла превысит это ограничение, файл не будет загружен.",
"The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Максимальное количество файлов, которые могут быть использованы одновременно в чате. Если количество файлов превысит это ограничение, файлы не будут загружены.",
"The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "",
"The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Формат вывода текста. Может быть 'json', 'markdown', или 'html'. По умолчанию 'markdown'.",
"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Оценка должна быть значением между 0,0 (0%) и 1,0 (100%).",
"The temperature of the model. Increasing the temperature will make the model answer more creatively.": "Температура модели. При повышении температуры модель будет отвечать более творчески.",
"Theme": "Тема",
@ -1206,7 +1214,7 @@
"This will reset the knowledge base and sync all files. Do you wish to continue?": "Это сбросит базу знаний и синхронизирует все файлы. Хотите продолжить?",
"Thorough explanation": "Подробное объяснение",
"Thought for {{DURATION}}": "Рассуждаю {{DURATION}}",
"Thought for {{DURATION}} seconds": "Рассуждал {{DURATION}} секунд(ы)",
"Thought for {{DURATION}} seconds": "Рассуждение заняло {{DURATION}} секунд(ы)",
"Tika": "Tika",
"Tika Server URL required.": "Требуется URL-адрес сервера Tika.",
"Tiktoken": "",
@ -1218,7 +1226,7 @@
"Title Generation": "Генерация заголовка",
"Title Generation Prompt": "Промпт для генерации заголовка",
"TLS": "",
"To access the available model names for downloading,": "Чтобы получить доступ к доступным для загрузки именам моделей,",
"To access the available model names for downloading,": "Чтобы получить доступ к доступным для загрузки названиям моделей,",
"To access the GGUF models available for downloading,": "Чтобы получить доступ к моделям GGUF, доступным для загрузки,",
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Чтобы получить доступ к WebUI, пожалуйста, обратитесь к администратору. Администраторы могут управлять статусами пользователей из панели администратора.",
"To attach knowledge base here, add them to the \"Knowledge\" workspace first.": "Чтобы прикрепить сюда базу знаний, сначала добавьте её в \"Знания\" рабочего пространства.",
@ -1239,7 +1247,7 @@
"Tool Description": "Описание Инструмента",
"Tool ID": "ID Инструмента",
"Tool imported successfully": "Инструмент успешно импортирован",
"Tool Name": "Имя Инструмента",
"Tool Name": "Название Инструмента",
"Tool Servers": "Сервер Инструмента",
"Tool updated successfully": "Инструмент успешно обновлен",
"Tools": "Инструменты",
@ -1292,7 +1300,7 @@
"Use Gravatar": "Использовать Gravatar",
"Use groups to group your users and assign permissions.": "Используйте группы, чтобы группировать пользователей и назначать разрешения.",
"Use Initials": "Использовать инициалы",
"Use LLM": "",
"Use LLM": "Использовать LLM",
"Use no proxy to fetch page contents.": "Не используйте прокси-сервер для получения содержимого страницы.",
"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Используйте прокси-сервер, обозначенный переменными окружения http_proxy и https_proxy, для получения содержимого страницы.",
"user": "пользователь",
@ -1343,8 +1351,8 @@
"What are you working on?": "Над чем вы работаете?",
"Whats New in": "Что нового в",
"When enabled, the model will respond to each chat message in real-time, generating a response as soon as the user sends a message. This mode is useful for live chat applications, but may impact performance on slower hardware.": "Если эта функция включена, модель будет отвечать на каждое сообщение чата в режиме реального времени, генерируя ответ, как только пользователь отправит сообщение. Этот режим полезен для приложений живого чата, но может повлиять на производительность на более медленном оборудовании.",
"wherever you are": "где бы ты ни был",
"Whether to paginate the output. Each page will be separated by a horizontal rule and page number. Defaults to False.": "",
"wherever you are": "где бы вы ни были",
"Whether to paginate the output. Each page will be separated by a horizontal rule and page number. Defaults to False.": "Следует ли разбивать выходные данные на страницы. Каждая страница будет разделена горизонтальной линией и номером страницы. По умолчанию установлено значение Выкл.",
"Whisper (Local)": "Whisper (Локально)",
"Why?": "Почему?",
"Widescreen Mode": "Широкоэкранный режим",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "",
"Are you sure you want to delete this message?": "",
"Are you sure you want to unarchive all archived chats?": "",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Ste si istý?",
"Arena Models": "Arena modely",
"Artifacts": "Artefakty",
@ -611,6 +610,10 @@
"Folder deleted successfully": "Priečinok bol úspešne vymazaný",
"Folder name cannot be empty.": "Názov priečinka nesmie byť prázdny.",
"Folder name updated successfully": "Názov priečinka bol úspešne aktualizovaný.",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Dodržal pokyny dokonale.",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Nové heslo",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF dokument (.pdf)",
"PDF Extract Images (OCR)": "Extrahovanie obrázkov z PDF (OCR)",
"pending": "čaká na vybavenie",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Odmietnutie povolenia pri prístupe k mediálnym zariadeniam",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Oprávnenie zamietnuté pri prístupe k mikrofónu: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Personalizácia",
"Pin": "",
"Pinned": "",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Predchádzajúcich 30 dní",
"Previous 7 days": "Predchádzajúcich 7 dní",
"Previous message": "",
"Private": "",
"Profile Image": "Profilový obrázok",
"Prompt": "",

View file

@ -108,7 +108,6 @@
"Are you sure you want to delete this channel?": "Да ли сигурно желите обрисати овај канал?",
"Are you sure you want to delete this message?": "Да ли сигурно желите обрисати ову поруку?",
"Are you sure you want to unarchive all archived chats?": "Да ли сигурно желите деархивирати све архиве?",
"Are you sure you want to update this user's role to **{{ROLE}}**?": "",
"Are you sure?": "Да ли сте сигурни?",
"Arena Models": "Модели са Арене",
"Artifacts": "Артефакти",
@ -611,6 +610,10 @@
"Folder deleted successfully": "",
"Folder name cannot be empty.": "",
"Folder name updated successfully": "",
"Follow up": "",
"Follow Up Generation": "",
"Follow Up Generation Prompt": "",
"Follow-Up Auto-Generation": "",
"Followed instructions perfectly": "Упутства су савршено праћена",
"Force OCR": "",
"Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "",
@ -846,6 +849,7 @@
"New Password": "Нова лозинка",
"New Tool": "",
"new-channel": "",
"Next message": "",
"No chats found for this user.": "",
"No chats found.": "",
"No content": "",
@ -928,6 +932,7 @@
"PDF document (.pdf)": "PDF документ (.pdf)",
"PDF Extract Images (OCR)": "Извлачење PDF слика (OCR)",
"pending": "на чекању",
"Pending": "",
"Pending User Overlay Content": "",
"Pending User Overlay Title": "",
"Permission denied when accessing media devices": "Приступ медијским уређајима одбијен",
@ -935,6 +940,8 @@
"Permission denied when accessing microphone: {{error}}": "Приступ микрофону је одбијен: {{error}}",
"Permissions": "",
"Perplexity API Key": "",
"Perplexity Model": "",
"Perplexity Search Context Usage": "",
"Personalization": "Прилагођавање",
"Pin": "Закачи",
"Pinned": "Закачено",
@ -965,6 +972,7 @@
"Preview": "",
"Previous 30 days": "Претходних 30 дана",
"Previous 7 days": "Претходних 7 дана",
"Previous message": "",
"Private": "",
"Profile Image": "Слика профила",
"Prompt": "",

Some files were not shown because too many files have changed in this diff Show more