1
0
Эх сурвалжийг харах

Merge branch 'dev' into searxng

Que Nguyen 10 сар өмнө
parent
commit
a02ba52de8
72 өөрчлөгдсөн 2104 нэмэгдсэн , 1062 устгасан
  1. 1 1
      README.md
  2. 4 0
      TROUBLESHOOTING.md
  3. 12 1
      backend/apps/ollama/main.py
  4. 17 1
      backend/apps/rag/main.py
  5. 39 0
      backend/apps/rag/search/tavily.py
  6. 14 0
      backend/apps/webui/models/memories.py
  7. 32 0
      backend/apps/webui/routers/memories.py
  8. 6 0
      backend/config.py
  9. 68 0
      backend/main.py
  10. 4 0
      src/app.css
  11. 48 0
      src/lib/apis/index.ts
  12. 32 1
      src/lib/apis/memories/index.ts
  13. 78 191
      src/lib/components/admin/Settings/Documents.svelte
  14. 17 7
      src/lib/components/admin/Settings/Models.svelte
  15. 20 1
      src/lib/components/admin/Settings/WebSearch.svelte
  16. 201 106
      src/lib/components/chat/Chat.svelte
  17. 3 4
      src/lib/components/chat/MessageInput.svelte
  18. 447 298
      src/lib/components/chat/MessageInput/CallOverlay.svelte
  19. 1 1
      src/lib/components/chat/Messages.svelte
  20. 9 2
      src/lib/components/chat/Messages/Placeholder.svelte
  21. 7 3
      src/lib/components/chat/ModelSelector/Selector.svelte
  22. 94 0
      src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
  23. 4 0
      src/lib/components/chat/Settings/General.svelte
  24. 32 0
      src/lib/components/chat/Settings/Interface.svelte
  25. 4 3
      src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte
  26. 136 0
      src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte
  27. 46 3
      src/lib/components/chat/Settings/Personalization/ManageModal.svelte
  28. 5 2
      src/lib/components/common/ConfirmDialog.svelte
  29. 2 0
      src/lib/components/common/Tooltip.svelte
  30. 58 284
      src/lib/components/layout/Sidebar.svelte
  31. 281 0
      src/lib/components/layout/Sidebar/ChatItem.svelte
  32. 13 1
      src/lib/components/workspace/Models.svelte
  33. 5 0
      src/lib/i18n/locales/ar-BH/translation.json
  34. 5 0
      src/lib/i18n/locales/bg-BG/translation.json
  35. 5 0
      src/lib/i18n/locales/bn-BD/translation.json
  36. 5 0
      src/lib/i18n/locales/ca-ES/translation.json
  37. 5 0
      src/lib/i18n/locales/ceb-PH/translation.json
  38. 5 0
      src/lib/i18n/locales/de-DE/translation.json
  39. 5 0
      src/lib/i18n/locales/dg-DG/translation.json
  40. 7 0
      src/lib/i18n/locales/en-GB/translation.json
  41. 5 0
      src/lib/i18n/locales/en-US/translation.json
  42. 5 0
      src/lib/i18n/locales/es-ES/translation.json
  43. 5 0
      src/lib/i18n/locales/fa-IR/translation.json
  44. 5 0
      src/lib/i18n/locales/fi-FI/translation.json
  45. 5 0
      src/lib/i18n/locales/fr-CA/translation.json
  46. 5 0
      src/lib/i18n/locales/fr-FR/translation.json
  47. 5 0
      src/lib/i18n/locales/he-IL/translation.json
  48. 5 0
      src/lib/i18n/locales/hi-IN/translation.json
  49. 5 0
      src/lib/i18n/locales/hr-HR/translation.json
  50. 5 0
      src/lib/i18n/locales/it-IT/translation.json
  51. 5 0
      src/lib/i18n/locales/ja-JP/translation.json
  52. 5 0
      src/lib/i18n/locales/ka-GE/translation.json
  53. 5 0
      src/lib/i18n/locales/ko-KR/translation.json
  54. 5 0
      src/lib/i18n/locales/lt-LT/translation.json
  55. 5 0
      src/lib/i18n/locales/nb-NO/translation.json
  56. 5 0
      src/lib/i18n/locales/nl-NL/translation.json
  57. 5 0
      src/lib/i18n/locales/pa-IN/translation.json
  58. 5 0
      src/lib/i18n/locales/pl-PL/translation.json
  59. 5 0
      src/lib/i18n/locales/pt-BR/translation.json
  60. 5 0
      src/lib/i18n/locales/pt-PT/translation.json
  61. 5 0
      src/lib/i18n/locales/ru-RU/translation.json
  62. 5 0
      src/lib/i18n/locales/sr-RS/translation.json
  63. 150 145
      src/lib/i18n/locales/sv-SE/translation.json
  64. 5 0
      src/lib/i18n/locales/tk-TW/translation.json
  65. 5 0
      src/lib/i18n/locales/tr-TR/translation.json
  66. 5 0
      src/lib/i18n/locales/uk-UA/translation.json
  67. 5 0
      src/lib/i18n/locales/vi-VN/translation.json
  68. 10 5
      src/lib/i18n/locales/zh-CN/translation.json
  69. 5 0
      src/lib/i18n/locales/zh-TW/translation.json
  70. 2 0
      src/lib/stores/index.ts
  71. 19 1
      src/lib/utils/index.ts
  72. 11 1
      src/routes/(app)/admin/+page.svelte

+ 1 - 1
README.md

@@ -37,7 +37,7 @@ Open WebUI is an [extensible](https://github.com/open-webui/pipelines), feature-
 
 
 - 📚 **Local RAG Integration**: Dive into the future of chat interactions with groundbreaking Retrieval Augmented Generation (RAG) support. This feature seamlessly integrates document interactions into your chat experience. You can load documents directly into the chat or add files to your document library, effortlessly accessing them using the `#` command before a query.
 - 📚 **Local RAG Integration**: Dive into the future of chat interactions with groundbreaking Retrieval Augmented Generation (RAG) support. This feature seamlessly integrates document interactions into your chat experience. You can load documents directly into the chat or add files to your document library, effortlessly accessing them using the `#` command before a query.
 
 
-- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, `serper`, and `Serply` and inject the results directly into your chat experience.
+- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, `serper`, `Serply`, `DuckDuckGo` and `TavilySearch` and inject the results directly into your chat experience.
 
 
 - 🌐 **Web Browsing Capability**: Seamlessly integrate websites into your chat experience using the `#` command followed by a URL. This feature allows you to incorporate web content directly into your conversations, enhancing the richness and depth of your interactions.
 - 🌐 **Web Browsing Capability**: Seamlessly integrate websites into your chat experience using the `#` command followed by a URL. This feature allows you to incorporate web content directly into your conversations, enhancing the richness and depth of your interactions.
 
 

+ 4 - 0
TROUBLESHOOTING.md

@@ -18,6 +18,10 @@ If you're experiencing connection issues, it’s often due to the WebUI docker c
 docker run -d --network=host -v open-webui:/app/backend/data -e OLLAMA_BASE_URL=http://127.0.0.1:11434 --name open-webui --restart always ghcr.io/open-webui/open-webui:main
 docker run -d --network=host -v open-webui:/app/backend/data -e OLLAMA_BASE_URL=http://127.0.0.1:11434 --name open-webui --restart always ghcr.io/open-webui/open-webui:main
 ```
 ```
 
 
+### Error on Slow Reponses for Ollama
+
+Open WebUI has a default timeout of 5 minutes for Ollama to finish generating the response. If needed, this can be adjusted via the environment variable AIOHTTP_CLIENT_TIMEOUT, which sets the timeout in seconds.
+
 ### General Connection Errors
 ### General Connection Errors
 
 
 **Ensure Ollama Version is Up-to-Date**: Always start by checking that you have the latest version of Ollama. Visit [Ollama's official site](https://ollama.com/) for the latest updates.
 **Ensure Ollama Version is Up-to-Date**: Always start by checking that you have the latest version of Ollama. Visit [Ollama's official site](https://ollama.com/) for the latest updates.

+ 12 - 1
backend/apps/ollama/main.py

@@ -46,6 +46,7 @@ from config import (
     SRC_LOG_LEVELS,
     SRC_LOG_LEVELS,
     OLLAMA_BASE_URLS,
     OLLAMA_BASE_URLS,
     ENABLE_OLLAMA_API,
     ENABLE_OLLAMA_API,
+    AIOHTTP_CLIENT_TIMEOUT,
     ENABLE_MODEL_FILTER,
     ENABLE_MODEL_FILTER,
     MODEL_FILTER_LIST,
     MODEL_FILTER_LIST,
     UPLOAD_DIR,
     UPLOAD_DIR,
@@ -154,7 +155,9 @@ async def cleanup_response(
 async def post_streaming_url(url: str, payload: str):
 async def post_streaming_url(url: str, payload: str):
     r = None
     r = None
     try:
     try:
-        session = aiohttp.ClientSession(trust_env=True)
+        session = aiohttp.ClientSession(
+            trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT)
+        )
         r = await session.post(url, data=payload)
         r = await session.post(url, data=payload)
         r.raise_for_status()
         r.raise_for_status()
 
 
@@ -751,6 +754,14 @@ async def generate_chat_completion(
             if model_info.params.get("num_ctx", None):
             if model_info.params.get("num_ctx", None):
                 payload["options"]["num_ctx"] = model_info.params.get("num_ctx", None)
                 payload["options"]["num_ctx"] = model_info.params.get("num_ctx", None)
 
 
+            if model_info.params.get("num_batch", None):
+                payload["options"]["num_batch"] = model_info.params.get(
+                    "num_batch", None
+                )
+
+            if model_info.params.get("num_keep", None):
+                payload["options"]["num_keep"] = model_info.params.get("num_keep", None)
+
             if model_info.params.get("repeat_last_n", None):
             if model_info.params.get("repeat_last_n", None):
                 payload["options"]["repeat_last_n"] = model_info.params.get(
                 payload["options"]["repeat_last_n"] = model_info.params.get(
                     "repeat_last_n", None
                     "repeat_last_n", None

+ 17 - 1
backend/apps/rag/main.py

@@ -73,6 +73,7 @@ from apps.rag.search.serper import search_serper
 from apps.rag.search.serpstack import search_serpstack
 from apps.rag.search.serpstack import search_serpstack
 from apps.rag.search.serply import search_serply
 from apps.rag.search.serply import search_serply
 from apps.rag.search.duckduckgo import search_duckduckgo
 from apps.rag.search.duckduckgo import search_duckduckgo
+from apps.rag.search.tavily import search_tavily
 
 
 from utils.misc import (
 from utils.misc import (
     calculate_sha256,
     calculate_sha256,
@@ -120,6 +121,7 @@ from config import (
     SERPSTACK_HTTPS,
     SERPSTACK_HTTPS,
     SERPER_API_KEY,
     SERPER_API_KEY,
     SERPLY_API_KEY,
     SERPLY_API_KEY,
+    TAVILY_API_KEY,
     RAG_WEB_SEARCH_RESULT_COUNT,
     RAG_WEB_SEARCH_RESULT_COUNT,
     RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
     RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
     RAG_EMBEDDING_OPENAI_BATCH_SIZE,
     RAG_EMBEDDING_OPENAI_BATCH_SIZE,
@@ -174,6 +176,7 @@ app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY
 app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
 app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
 app.state.config.SERPER_API_KEY = SERPER_API_KEY
 app.state.config.SERPER_API_KEY = SERPER_API_KEY
 app.state.config.SERPLY_API_KEY = SERPLY_API_KEY
 app.state.config.SERPLY_API_KEY = SERPLY_API_KEY
+app.state.config.TAVILY_API_KEY = TAVILY_API_KEY
 app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = RAG_WEB_SEARCH_RESULT_COUNT
 app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = RAG_WEB_SEARCH_RESULT_COUNT
 app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = RAG_WEB_SEARCH_CONCURRENT_REQUESTS
 app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = RAG_WEB_SEARCH_CONCURRENT_REQUESTS
 
 
@@ -402,6 +405,7 @@ async def get_rag_config(user=Depends(get_admin_user)):
                 "serpstack_https": app.state.config.SERPSTACK_HTTPS,
                 "serpstack_https": app.state.config.SERPSTACK_HTTPS,
                 "serper_api_key": app.state.config.SERPER_API_KEY,
                 "serper_api_key": app.state.config.SERPER_API_KEY,
                 "serply_api_key": app.state.config.SERPLY_API_KEY,
                 "serply_api_key": app.state.config.SERPLY_API_KEY,
+                "tavily_api_key": app.state.config.TAVILY_API_KEY,
                 "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
                 "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
                 "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
                 "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
             },
             },
@@ -430,6 +434,7 @@ class WebSearchConfig(BaseModel):
     serpstack_https: Optional[bool] = None
     serpstack_https: Optional[bool] = None
     serper_api_key: Optional[str] = None
     serper_api_key: Optional[str] = None
     serply_api_key: Optional[str] = None
     serply_api_key: Optional[str] = None
+    tavily_api_key: Optional[str] = None
     result_count: Optional[int] = None
     result_count: Optional[int] = None
     concurrent_requests: Optional[int] = None
     concurrent_requests: Optional[int] = None
 
 
@@ -481,6 +486,7 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
         app.state.config.SERPSTACK_HTTPS = form_data.web.search.serpstack_https
         app.state.config.SERPSTACK_HTTPS = form_data.web.search.serpstack_https
         app.state.config.SERPER_API_KEY = form_data.web.search.serper_api_key
         app.state.config.SERPER_API_KEY = form_data.web.search.serper_api_key
         app.state.config.SERPLY_API_KEY = form_data.web.search.serply_api_key
         app.state.config.SERPLY_API_KEY = form_data.web.search.serply_api_key
+        app.state.config.TAVILY_API_KEY = form_data.web.search.tavily_api_key
         app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = form_data.web.search.result_count
         app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = form_data.web.search.result_count
         app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = (
         app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = (
             form_data.web.search.concurrent_requests
             form_data.web.search.concurrent_requests
@@ -510,6 +516,7 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
                 "serpstack_https": app.state.config.SERPSTACK_HTTPS,
                 "serpstack_https": app.state.config.SERPSTACK_HTTPS,
                 "serper_api_key": app.state.config.SERPER_API_KEY,
                 "serper_api_key": app.state.config.SERPER_API_KEY,
                 "serply_api_key": app.state.config.SERPLY_API_KEY,
                 "serply_api_key": app.state.config.SERPLY_API_KEY,
+                "tavily_api_key": app.state.config.TAVILY_API_KEY,
                 "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
                 "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
                 "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
                 "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
             },
             },
@@ -758,7 +765,7 @@ def search_web(engine: str, query: str) -> list[SearchResult]:
     - SERPSTACK_API_KEY
     - SERPSTACK_API_KEY
     - SERPER_API_KEY
     - SERPER_API_KEY
     - SERPLY_API_KEY
     - SERPLY_API_KEY
-
+    - TAVILY_API_KEY
     Args:
     Args:
         query (str): The query to search for
         query (str): The query to search for
     """
     """
@@ -833,6 +840,15 @@ def search_web(engine: str, query: str) -> list[SearchResult]:
             raise Exception("No SERPLY_API_KEY found in environment variables")
             raise Exception("No SERPLY_API_KEY found in environment variables")
     elif engine == "duckduckgo":
     elif engine == "duckduckgo":
         return search_duckduckgo(query, app.state.config.RAG_WEB_SEARCH_RESULT_COUNT, app.state.config.RAG_WEB_SEARCH_WHITE_LIST_DOMAINS)
         return search_duckduckgo(query, app.state.config.RAG_WEB_SEARCH_RESULT_COUNT, app.state.config.RAG_WEB_SEARCH_WHITE_LIST_DOMAINS)
+    elif engine == "tavily":
+        if app.state.config.TAVILY_API_KEY:
+            return search_tavily(
+                app.state.config.TAVILY_API_KEY,
+                query,
+                app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
+            )
+        else:
+            raise Exception("No TAVILY_API_KEY found in environment variables")
     else:
     else:
         raise Exception("No search engine API key found in environment variables")
         raise Exception("No search engine API key found in environment variables")
 
 

+ 39 - 0
backend/apps/rag/search/tavily.py

@@ -0,0 +1,39 @@
+import logging
+
+import requests
+
+from apps.rag.search.main import SearchResult
+from config import SRC_LOG_LEVELS
+
+log = logging.getLogger(__name__)
+log.setLevel(SRC_LOG_LEVELS["RAG"])
+
+
+def search_tavily(api_key: str, query: str, count: int) -> list[SearchResult]:
+    """Search using Tavily's Search API and return the results as a list of SearchResult objects.
+
+    Args:
+        api_key (str): A Tavily Search API key
+        query (str): The query to search for
+
+    Returns:
+        List[SearchResult]: A list of search results
+    """
+    url = "https://api.tavily.com/search"
+    data = {"query": query, "api_key": api_key}
+
+    response = requests.post(url, json=data)
+    response.raise_for_status()
+
+    json_response = response.json()
+
+    raw_search_results = json_response.get("results", [])
+
+    return [
+        SearchResult(
+            link=result["url"],
+            title=result.get("title", ""),
+            snippet=result.get("content"),
+        )
+        for result in raw_search_results[:count]
+    ]

+ 14 - 0
backend/apps/webui/models/memories.py

@@ -65,6 +65,20 @@ class MemoriesTable:
         else:
         else:
             return None
             return None
 
 
+    def update_memory_by_id(
+        self,
+        id: str,
+        content: str,
+    ) -> Optional[MemoryModel]:
+        try:
+            memory = Memory.get(Memory.id == id)
+            memory.content = content
+            memory.updated_at = int(time.time())
+            memory.save()
+            return MemoryModel(**model_to_dict(memory))
+        except:
+            return None
+
     def get_memories(self) -> List[MemoryModel]:
     def get_memories(self) -> List[MemoryModel]:
         try:
         try:
             memories = Memory.select()
             memories = Memory.select()

+ 32 - 0
backend/apps/webui/routers/memories.py

@@ -44,6 +44,10 @@ class AddMemoryForm(BaseModel):
     content: str
     content: str
 
 
 
 
+class MemoryUpdateModel(BaseModel):
+    content: Optional[str] = None
+
+
 @router.post("/add", response_model=Optional[MemoryModel])
 @router.post("/add", response_model=Optional[MemoryModel])
 async def add_memory(
 async def add_memory(
     request: Request, form_data: AddMemoryForm, user=Depends(get_verified_user)
     request: Request, form_data: AddMemoryForm, user=Depends(get_verified_user)
@@ -62,6 +66,34 @@ async def add_memory(
     return memory
     return memory
 
 
 
 
+@router.post("/{memory_id}/update", response_model=Optional[MemoryModel])
+async def update_memory_by_id(
+    memory_id: str,
+    request: Request,
+    form_data: MemoryUpdateModel,
+    user=Depends(get_verified_user),
+):
+    memory = Memories.update_memory_by_id(memory_id, form_data.content)
+    if memory is None:
+        raise HTTPException(status_code=404, detail="Memory not found")
+
+    if form_data.content is not None:
+        memory_embedding = request.app.state.EMBEDDING_FUNCTION(form_data.content)
+        collection = CHROMA_CLIENT.get_or_create_collection(
+            name=f"user-memory-{user.id}"
+        )
+        collection.upsert(
+            documents=[form_data.content],
+            ids=[memory.id],
+            embeddings=[memory_embedding],
+            metadatas=[
+                {"created_at": memory.created_at, "updated_at": memory.updated_at}
+            ],
+        )
+
+    return memory
+
+
 ############################
 ############################
 # QueryMemory
 # QueryMemory
 ############################
 ############################

+ 6 - 0
backend/config.py

@@ -425,6 +425,7 @@ OLLAMA_API_BASE_URL = os.environ.get(
 )
 )
 
 
 OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "")
 OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "")
+AIOHTTP_CLIENT_TIMEOUT = int(os.environ.get("AIOHTTP_CLIENT_TIMEOUT", "300"))
 K8S_FLAG = os.environ.get("K8S_FLAG", "")
 K8S_FLAG = os.environ.get("K8S_FLAG", "")
 USE_OLLAMA_DOCKER = os.environ.get("USE_OLLAMA_DOCKER", "false")
 USE_OLLAMA_DOCKER = os.environ.get("USE_OLLAMA_DOCKER", "false")
 
 
@@ -951,6 +952,11 @@ SERPLY_API_KEY = PersistentConfig(
     os.getenv("SERPLY_API_KEY", ""),
     os.getenv("SERPLY_API_KEY", ""),
 )
 )
 
 
+TAVILY_API_KEY = PersistentConfig(
+    "TAVILY_API_KEY",
+    "rag.web.search.tavily_api_key",
+    os.getenv("TAVILY_API_KEY", ""),
+)
 
 
 RAG_WEB_SEARCH_RESULT_COUNT = PersistentConfig(
 RAG_WEB_SEARCH_RESULT_COUNT = PersistentConfig(
     "RAG_WEB_SEARCH_RESULT_COUNT",
     "RAG_WEB_SEARCH_RESULT_COUNT",

+ 68 - 0
backend/main.py

@@ -494,6 +494,9 @@ def filter_pipeline(payload, user):
         if "title" in payload:
         if "title" in payload:
             del payload["title"]
             del payload["title"]
 
 
+        if "task" in payload:
+            del payload["task"]
+
     return payload
     return payload
 
 
 
 
@@ -835,6 +838,71 @@ async def generate_search_query(form_data: dict, user=Depends(get_verified_user)
         "messages": [{"role": "user", "content": content}],
         "messages": [{"role": "user", "content": content}],
         "stream": False,
         "stream": False,
         "max_tokens": 30,
         "max_tokens": 30,
+        "task": True,
+    }
+
+    print(payload)
+
+    try:
+        payload = filter_pipeline(payload, user)
+    except Exception as e:
+        return JSONResponse(
+            status_code=e.args[0],
+            content={"detail": e.args[1]},
+        )
+
+    if model["owned_by"] == "ollama":
+        return await generate_ollama_chat_completion(
+            OpenAIChatCompletionForm(**payload), user=user
+        )
+    else:
+        return await generate_openai_chat_completion(payload, user=user)
+
+
+@app.post("/api/task/emoji/completions")
+async def generate_emoji(form_data: dict, user=Depends(get_verified_user)):
+    print("generate_emoji")
+
+    model_id = form_data["model"]
+    if model_id not in app.state.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
+    if app.state.MODELS[model_id]["owned_by"] == "ollama":
+        if app.state.config.TASK_MODEL:
+            task_model_id = app.state.config.TASK_MODEL
+            if task_model_id in app.state.MODELS:
+                model_id = task_model_id
+    else:
+        if app.state.config.TASK_MODEL_EXTERNAL:
+            task_model_id = app.state.config.TASK_MODEL_EXTERNAL
+            if task_model_id in app.state.MODELS:
+                model_id = task_model_id
+
+    print(model_id)
+    model = app.state.MODELS[model_id]
+
+    template = '''
+Your task is to reflect the speaker's likely facial expression through a fitting emoji. Interpret emotions from the message and reflect their facial expression using fitting, diverse emojis (e.g., 😊, 😢, 😡, 😱).
+
+Message: """{{prompt}}"""
+'''
+
+    content = title_generation_template(
+        template, form_data["prompt"], user.model_dump()
+    )
+
+    payload = {
+        "model": model_id,
+        "messages": [{"role": "user", "content": content}],
+        "stream": False,
+        "max_tokens": 4,
+        "chat_id": form_data.get("chat_id", None),
+        "task": True,
     }
     }
 
 
     print(payload)
     print(payload)

+ 4 - 0
src/app.css

@@ -28,6 +28,10 @@ math {
 	@apply rounded-lg;
 	@apply rounded-lg;
 }
 }
 
 
+.markdown a {
+	@apply underline;
+}
+
 ol > li {
 ol > li {
 	counter-increment: list-number;
 	counter-increment: list-number;
 	display: block;
 	display: block;

+ 48 - 0
src/lib/apis/index.ts

@@ -205,6 +205,54 @@ export const generateTitle = async (
 	return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? 'New Chat';
 	return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? 'New Chat';
 };
 };
 
 
+export const generateEmoji = async (
+	token: string = '',
+	model: string,
+	prompt: string,
+	chat_id?: string
+) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_BASE_URL}/api/task/emoji/completions`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			model: model,
+			prompt: prompt,
+			...(chat_id && { chat_id: chat_id })
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			if ('detail' in err) {
+				error = err.detail;
+			}
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	const response = res?.choices[0]?.message?.content.replace(/["']/g, '') ?? null;
+
+	if (response) {
+		if (/\p{Extended_Pictographic}/u.test(response)) {
+			return response.match(/\p{Extended_Pictographic}/gu)[0];
+		}
+	}
+
+	return null;
+};
+
 export const generateSearchQuery = async (
 export const generateSearchQuery = async (
 	token: string = '',
 	token: string = '',
 	model: string,
 	model: string,

+ 32 - 1
src/lib/apis/memories/index.ts

@@ -3,7 +3,7 @@ import { WEBUI_API_BASE_URL } from '$lib/constants';
 export const getMemories = async (token: string) => {
 export const getMemories = async (token: string) => {
 	let error = null;
 	let error = null;
 
 
-	const res = await fetch(`${WEBUI_API_BASE_URL}/memories`, {
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/`, {
 		method: 'GET',
 		method: 'GET',
 		headers: {
 		headers: {
 			Accept: 'application/json',
 			Accept: 'application/json',
@@ -59,6 +59,37 @@ export const addNewMemory = async (token: string, content: string) => {
 	return res;
 	return res;
 };
 };
 
 
+export const updateMemoryById = async (token: string, id: string, content: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/${id}/update`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			content: content
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const queryMemory = async (token: string, content: string) => {
 export const queryMemory = async (token: string, content: string) => {
 	let error = null;
 	let error = null;
 
 

+ 78 - 191
src/lib/components/admin/Settings/Documents.svelte

@@ -13,6 +13,8 @@
 		getRAGConfig,
 		getRAGConfig,
 		updateRAGConfig
 		updateRAGConfig
 	} from '$lib/apis/rag';
 	} from '$lib/apis/rag';
+	import ResetUploadDirConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
+	import ResetVectorDBConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
 
 
 	import { documents, models } from '$lib/stores';
 	import { documents, models } from '$lib/stores';
 	import { onMount, getContext } from 'svelte';
 	import { onMount, getContext } from 'svelte';
@@ -213,6 +215,34 @@
 	});
 	});
 </script>
 </script>
 
 
+<ResetUploadDirConfirmDialog
+	bind:show={showResetUploadDirConfirm}
+	on:confirm={() => {
+		const res = resetUploadDir(localStorage.token).catch((error) => {
+			toast.error(error);
+			return null;
+		});
+
+		if (res) {
+			toast.success($i18n.t('Success'));
+		}
+	}}
+/>
+
+<ResetVectorDBConfirmDialog
+	bind:show={showResetConfirm}
+	on:confirm={() => {
+		const res = resetVectorDB(localStorage.token).catch((error) => {
+			toast.error(error);
+			return null;
+		});
+
+		if (res) {
+			toast.success($i18n.t('Success'));
+		}
+	}}
+/>
+
 <form
 <form
 	class="flex flex-col h-full justify-between space-y-3 text-sm"
 	class="flex flex-col h-full justify-between space-y-3 text-sm"
 	on:submit|preventDefault={() => {
 	on:submit|preventDefault={() => {
@@ -640,199 +670,56 @@
 		<hr class=" dark:border-gray-850" />
 		<hr class=" dark:border-gray-850" />
 
 
 		<div>
 		<div>
-			{#if showResetUploadDirConfirm}
-				<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
-					<div class="flex items-center space-x-3">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 24 24"
-							fill="currentColor"
-							class="size-4"
-						>
-							<path
-								fill-rule="evenodd"
-								d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM9.75 14.25a.75.75 0 0 0 0 1.5H15a.75.75 0 0 0 0-1.5H9.75Z"
-								clip-rule="evenodd"
-							/>
-							<path
-								d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
-							/>
-						</svg>
-						<span>{$i18n.t('Are you sure?')}</span>
-					</div>
-
-					<div class="flex space-x-1.5 items-center">
-						<button
-							class="hover:text-white transition"
-							on:click={() => {
-								const res = resetUploadDir(localStorage.token).catch((error) => {
-									toast.error(error);
-									return null;
-								});
-
-								if (res) {
-									toast.success($i18n.t('Success'));
-								}
-
-								showResetUploadDirConfirm = false;
-							}}
-							type="button"
-						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								viewBox="0 0 20 20"
-								fill="currentColor"
-								class="w-4 h-4"
-							>
-								<path
-									fill-rule="evenodd"
-									d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
-									clip-rule="evenodd"
-								/>
-							</svg>
-						</button>
-						<button
-							class="hover:text-white transition"
-							type="button"
-							on:click={() => {
-								showResetUploadDirConfirm = false;
-							}}
-						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								viewBox="0 0 20 20"
-								fill="currentColor"
-								class="w-4 h-4"
-							>
-								<path
-									d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
-								/>
-							</svg>
-						</button>
-					</div>
+			<button
+				class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
+				on:click={() => {
+					showResetUploadDirConfirm = true;
+				}}
+				type="button"
+			>
+				<div class=" self-center mr-3">
+					<svg
+						xmlns="http://www.w3.org/2000/svg"
+						viewBox="0 0 24 24"
+						fill="currentColor"
+						class="size-4"
+					>
+						<path
+							fill-rule="evenodd"
+							d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM9.75 14.25a.75.75 0 0 0 0 1.5H15a.75.75 0 0 0 0-1.5H9.75Z"
+							clip-rule="evenodd"
+						/>
+						<path
+							d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
+						/>
+					</svg>
 				</div>
 				</div>
-			{:else}
-				<button
-					class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
-					on:click={() => {
-						showResetUploadDirConfirm = true;
-					}}
-					type="button"
-				>
-					<div class=" self-center mr-3">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 24 24"
-							fill="currentColor"
-							class="size-4"
-						>
-							<path
-								fill-rule="evenodd"
-								d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM9.75 14.25a.75.75 0 0 0 0 1.5H15a.75.75 0 0 0 0-1.5H9.75Z"
-								clip-rule="evenodd"
-							/>
-							<path
-								d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
-							/>
-						</svg>
-					</div>
-					<div class=" self-center text-sm font-medium">{$i18n.t('Reset Upload Directory')}</div>
-				</button>
-			{/if}
-
-			{#if showResetConfirm}
-				<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
-					<div class="flex items-center space-x-3">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 16 16"
-							fill="currentColor"
-							class="w-4 h-4"
-						>
-							<path
-								fill-rule="evenodd"
-								d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
-								clip-rule="evenodd"
-							/>
-						</svg>
-						<span>{$i18n.t('Are you sure?')}</span>
-					</div>
-
-					<div class="flex space-x-1.5 items-center">
-						<button
-							class="hover:text-white transition"
-							on:click={() => {
-								const res = resetVectorDB(localStorage.token).catch((error) => {
-									toast.error(error);
-									return null;
-								});
-
-								if (res) {
-									toast.success($i18n.t('Success'));
-								}
-
-								showResetConfirm = false;
-							}}
-							type="button"
-						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								viewBox="0 0 20 20"
-								fill="currentColor"
-								class="w-4 h-4"
-							>
-								<path
-									fill-rule="evenodd"
-									d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
-									clip-rule="evenodd"
-								/>
-							</svg>
-						</button>
-						<button
-							class="hover:text-white transition"
-							on:click={() => {
-								showResetConfirm = false;
-							}}
-							type="button"
-						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								viewBox="0 0 20 20"
-								fill="currentColor"
-								class="w-4 h-4"
-							>
-								<path
-									d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
-								/>
-							</svg>
-						</button>
-					</div>
+				<div class=" self-center text-sm font-medium">{$i18n.t('Reset Upload Directory')}</div>
+			</button>
+
+			<button
+				class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
+				on:click={() => {
+					showResetConfirm = true;
+				}}
+				type="button"
+			>
+				<div class=" self-center mr-3">
+					<svg
+						xmlns="http://www.w3.org/2000/svg"
+						viewBox="0 0 16 16"
+						fill="currentColor"
+						class="w-4 h-4"
+					>
+						<path
+							fill-rule="evenodd"
+							d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
+							clip-rule="evenodd"
+						/>
+					</svg>
 				</div>
 				</div>
-			{:else}
-				<button
-					class=" flex rounded-xl py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
-					on:click={() => {
-						showResetConfirm = true;
-					}}
-					type="button"
-				>
-					<div class=" self-center mr-3">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 16 16"
-							fill="currentColor"
-							class="w-4 h-4"
-						>
-							<path
-								fill-rule="evenodd"
-								d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
-								clip-rule="evenodd"
-							/>
-						</svg>
-					</div>
-					<div class=" self-center text-sm font-medium">{$i18n.t('Reset Vector Storage')}</div>
-				</button>
-			{/if}
+				<div class=" self-center text-sm font-medium">{$i18n.t('Reset Vector Storage')}</div>
+			</button>
 		</div>
 		</div>
 	</div>
 	</div>
 	<div class="flex justify-end pt-3 text-sm font-medium">
 	<div class="flex justify-end pt-3 text-sm font-medium">

+ 17 - 7
src/lib/components/admin/Settings/Models.svelte

@@ -1,5 +1,10 @@
 <script lang="ts">
 <script lang="ts">
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
+	import { onMount, getContext } from 'svelte';
+
+	import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
+	import { WEBUI_NAME, models, MODEL_DOWNLOAD_POOL, user, config } from '$lib/stores';
+	import { splitStream } from '$lib/utils';
 
 
 	import {
 	import {
 		createModel,
 		createModel,
@@ -11,15 +16,11 @@
 		uploadModel,
 		uploadModel,
 		getOllamaConfig
 		getOllamaConfig
 	} from '$lib/apis/ollama';
 	} from '$lib/apis/ollama';
-
-	import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
-	import { WEBUI_NAME, models, MODEL_DOWNLOAD_POOL, user, config } from '$lib/stores';
-	import { splitStream } from '$lib/utils';
-	import { onMount, getContext } from 'svelte';
+	import { getModels as _getModels } from '$lib/apis';
 
 
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
-	import { getModels as _getModels } from '$lib/apis';
+	import ModelDeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -29,6 +30,8 @@
 
 
 	let modelUploadInputElement: HTMLInputElement;
 	let modelUploadInputElement: HTMLInputElement;
 
 
+	let showModelDeleteConfirm = false;
+
 	// Models
 	// Models
 
 
 	let ollamaEnabled = null;
 	let ollamaEnabled = null;
@@ -549,6 +552,13 @@
 	});
 	});
 </script>
 </script>
 
 
+<ModelDeleteConfirmDialog
+	bind:show={showModelDeleteConfirm}
+	on:confirm={() => {
+		deleteModelHandler();
+	}}
+/>
+
 <div class="flex flex-col h-full justify-between text-sm">
 <div class="flex flex-col h-full justify-between text-sm">
 	<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
 	<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
 		{#if ollamaEnabled}
 		{#if ollamaEnabled}
@@ -763,7 +773,7 @@
 								<button
 								<button
 									class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 									class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
 									on:click={() => {
 									on:click={() => {
-										deleteModelHandler();
+										showModelDeleteConfirm = true;
 									}}
 									}}
 								>
 								>
 									<svg
 									<svg

+ 20 - 1
src/lib/components/admin/Settings/WebSearch.svelte

@@ -18,7 +18,8 @@
 		'serpstack',
 		'serpstack',
 		'serper',
 		'serper',
 		'serply',
 		'serply',
-		'duckduckgo'
+		'duckduckgo',
+		'tavily'
 	];
 	];
 
 
 	let youtubeLanguage = 'en';
 	let youtubeLanguage = 'en';
@@ -214,6 +215,24 @@
 									</div>
 									</div>
 								</div>
 								</div>
 							</div>
 							</div>
+						{:else if webConfig.search.engine === 'tavily'}
+							<div>
+								<div class=" self-center text-xs font-medium mb-1">
+									{$i18n.t('Tavily API Key')}
+								</div>
+
+								<div class="flex w-full">
+									<div class="flex-1">
+										<input
+											class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+											type="text"
+											placeholder={$i18n.t('Enter Tavily API Key')}
+											bind:value={webConfig.search.tavily_api_key}
+											autocomplete="off"
+										/>
+									</div>
+								</div>
+							</div>
 						{/if}
 						{/if}
 					</div>
 					</div>
 				{/if}
 				{/if}

+ 201 - 106
src/lib/components/chat/Chat.svelte

@@ -30,6 +30,7 @@
 	import {
 	import {
 		convertMessagesToHistory,
 		convertMessagesToHistory,
 		copyToClipboard,
 		copyToClipboard,
+		extractSentencesForAudio,
 		promptTemplate,
 		promptTemplate,
 		splitStream
 		splitStream
 	} from '$lib/utils';
 	} from '$lib/utils';
@@ -64,6 +65,8 @@
 	export let chatIdProp = '';
 	export let chatIdProp = '';
 	let loaded = false;
 	let loaded = false;
 
 
+	const eventTarget = new EventTarget();
+
 	let stopResponseFlag = false;
 	let stopResponseFlag = false;
 	let autoScroll = true;
 	let autoScroll = true;
 	let processing = '';
 	let processing = '';
@@ -108,7 +111,8 @@
 
 
 	$: if (chatIdProp) {
 	$: if (chatIdProp) {
 		(async () => {
 		(async () => {
-			if (await loadChat()) {
+			console.log(chatIdProp);
+			if (chatIdProp && (await loadChat())) {
 				await tick();
 				await tick();
 				loaded = true;
 				loaded = true;
 
 
@@ -123,7 +127,11 @@
 
 
 	onMount(async () => {
 	onMount(async () => {
 		if (!$chatId) {
 		if (!$chatId) {
-			await initNewChat();
+			chatId.subscribe(async (value) => {
+				if (!value) {
+					await initNewChat();
+				}
+			});
 		} else {
 		} else {
 			if (!($settings.saveChatHistory ?? true)) {
 			if (!($settings.saveChatHistory ?? true)) {
 				await goto('/');
 				await goto('/');
@@ -300,7 +308,7 @@
 	// Chat functions
 	// Chat functions
 	//////////////////////////
 	//////////////////////////
 
 
-	const submitPrompt = async (userPrompt, _user = null) => {
+	const submitPrompt = async (userPrompt, { _raw = false } = {}) => {
 		let _responses = [];
 		let _responses = [];
 		console.log('submitPrompt', $chatId);
 		console.log('submitPrompt', $chatId);
 
 
@@ -344,7 +352,6 @@
 				parentId: messages.length !== 0 ? messages.at(-1).id : null,
 				parentId: messages.length !== 0 ? messages.at(-1).id : null,
 				childrenIds: [],
 				childrenIds: [],
 				role: 'user',
 				role: 'user',
-				user: _user ?? undefined,
 				content: userPrompt,
 				content: userPrompt,
 				files: _files.length > 0 ? _files : undefined,
 				files: _files.length > 0 ? _files : undefined,
 				timestamp: Math.floor(Date.now() / 1000), // Unix epoch
 				timestamp: Math.floor(Date.now() / 1000), // Unix epoch
@@ -362,15 +369,13 @@
 
 
 			// Wait until history/message have been updated
 			// Wait until history/message have been updated
 			await tick();
 			await tick();
-
-			// Send prompt
-			_responses = await sendPrompt(userPrompt, userMessageId);
+			_responses = await sendPrompt(userPrompt, userMessageId, { newChat: true });
 		}
 		}
 
 
 		return _responses;
 		return _responses;
 	};
 	};
 
 
-	const sendPrompt = async (prompt, parentId, modelId = null, newChat = true) => {
+	const sendPrompt = async (prompt, parentId, { modelId = null, newChat = false } = {}) => {
 		let _responses = [];
 		let _responses = [];
 
 
 		// If modelId is provided, use it, else use selected model
 		// If modelId is provided, use it, else use selected model
@@ -490,7 +495,6 @@
 					responseMessage.userContext = userContext;
 					responseMessage.userContext = userContext;
 
 
 					const chatEventEmitter = await getChatEventEmitter(model.id, _chatId);
 					const chatEventEmitter = await getChatEventEmitter(model.id, _chatId);
-
 					if (webSearchEnabled) {
 					if (webSearchEnabled) {
 						await getWebSearchResults(model.id, parentId, responseMessageId);
 						await getWebSearchResults(model.id, parentId, responseMessageId);
 					}
 					}
@@ -503,8 +507,6 @@
 					}
 					}
 					_responses.push(_response);
 					_responses.push(_response);
 
 
-					console.log('chatEventEmitter', chatEventEmitter);
-
 					if (chatEventEmitter) clearInterval(chatEventEmitter);
 					if (chatEventEmitter) clearInterval(chatEventEmitter);
 				} else {
 				} else {
 					toast.error($i18n.t(`Model {{modelId}} not found`, { modelId }));
 					toast.error($i18n.t(`Model {{modelId}} not found`, { modelId }));
@@ -513,88 +515,9 @@
 		);
 		);
 
 
 		await chats.set(await getChatList(localStorage.token));
 		await chats.set(await getChatList(localStorage.token));
-
 		return _responses;
 		return _responses;
 	};
 	};
 
 
-	const getWebSearchResults = async (model: string, parentId: string, responseId: string) => {
-		const responseMessage = history.messages[responseId];
-
-		responseMessage.statusHistory = [
-			{
-				done: false,
-				action: 'web_search',
-				description: $i18n.t('Generating search query')
-			}
-		];
-		messages = messages;
-
-		const prompt = history.messages[parentId].content;
-		let searchQuery = await generateSearchQuery(localStorage.token, model, messages, prompt).catch(
-			(error) => {
-				console.log(error);
-				return prompt;
-			}
-		);
-
-		if (!searchQuery) {
-			toast.warning($i18n.t('No search query generated'));
-			responseMessage.statusHistory.push({
-				done: true,
-				error: true,
-				action: 'web_search',
-				description: 'No search query generated'
-			});
-
-			messages = messages;
-		}
-
-		responseMessage.statusHistory.push({
-			done: false,
-			action: 'web_search',
-			description: $i18n.t(`Searching "{{searchQuery}}"`, { searchQuery })
-		});
-		messages = messages;
-
-		const results = await runWebSearch(localStorage.token, searchQuery).catch((error) => {
-			console.log(error);
-			toast.error(error);
-
-			return null;
-		});
-
-		if (results) {
-			responseMessage.statusHistory.push({
-				done: true,
-				action: 'web_search',
-				description: $i18n.t('Searched {{count}} sites', { count: results.filenames.length }),
-				query: searchQuery,
-				urls: results.filenames
-			});
-
-			if (responseMessage?.files ?? undefined === undefined) {
-				responseMessage.files = [];
-			}
-
-			responseMessage.files.push({
-				collection_name: results.collection_name,
-				name: searchQuery,
-				type: 'web_search_results',
-				urls: results.filenames
-			});
-
-			messages = messages;
-		} else {
-			responseMessage.statusHistory.push({
-				done: true,
-				error: true,
-				action: 'web_search',
-				description: 'No search results found'
-			});
-			messages = messages;
-		}
-	};
-
 	const sendPromptOllama = async (model, userPrompt, responseMessageId, _chatId) => {
 	const sendPromptOllama = async (model, userPrompt, responseMessageId, _chatId) => {
 		let _response = null;
 		let _response = null;
 
 
@@ -676,6 +599,16 @@
 				array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index
 				array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index
 		);
 		);
 
 
+		eventTarget.dispatchEvent(
+			new CustomEvent('chat:start', {
+				detail: {
+					id: responseMessageId
+				}
+			})
+		);
+
+		await tick();
+
 		const [res, controller] = await generateChatCompletion(localStorage.token, {
 		const [res, controller] = await generateChatCompletion(localStorage.token, {
 			model: model.id,
 			model: model.id,
 			messages: messagesBody,
 			messages: messagesBody,
@@ -745,6 +678,23 @@
 									continue;
 									continue;
 								} else {
 								} else {
 									responseMessage.content += data.message.content;
 									responseMessage.content += data.message.content;
+
+									const sentences = extractSentencesForAudio(responseMessage.content);
+									sentences.pop();
+
+									// dispatch only last sentence and make sure it hasn't been dispatched before
+									if (
+										sentences.length > 0 &&
+										sentences[sentences.length - 1] !== responseMessage.lastSentence
+									) {
+										responseMessage.lastSentence = sentences[sentences.length - 1];
+										eventTarget.dispatchEvent(
+											new CustomEvent('chat', {
+												detail: { id: responseMessageId, content: sentences[sentences.length - 1] }
+											})
+										);
+									}
+
 									messages = messages;
 									messages = messages;
 								}
 								}
 							} else {
 							} else {
@@ -771,21 +721,13 @@
 								messages = messages;
 								messages = messages;
 
 
 								if ($settings.notificationEnabled && !document.hasFocus()) {
 								if ($settings.notificationEnabled && !document.hasFocus()) {
-									const notification = new Notification(
-										selectedModelfile
-											? `${
-													selectedModelfile.title.charAt(0).toUpperCase() +
-													selectedModelfile.title.slice(1)
-											  }`
-											: `${model.id}`,
-										{
-											body: responseMessage.content,
-											icon: selectedModelfile?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`
-										}
-									);
+									const notification = new Notification(`${model.id}`, {
+										body: responseMessage.content,
+										icon: `${WEBUI_BASE_URL}/static/favicon.png`
+									});
 								}
 								}
 
 
-								if ($settings.responseAutoCopy) {
+								if ($settings?.responseAutoCopy ?? false) {
 									copyToClipboard(responseMessage.content);
 									copyToClipboard(responseMessage.content);
 								}
 								}
 
 
@@ -847,6 +789,23 @@
 		stopResponseFlag = false;
 		stopResponseFlag = false;
 		await tick();
 		await tick();
 
 
+		let lastSentence = extractSentencesForAudio(responseMessage.content)?.at(-1) ?? '';
+		if (lastSentence) {
+			eventTarget.dispatchEvent(
+				new CustomEvent('chat', {
+					detail: { id: responseMessageId, content: lastSentence }
+				})
+			);
+		}
+		eventTarget.dispatchEvent(
+			new CustomEvent('chat:finish', {
+				detail: {
+					id: responseMessageId,
+					content: responseMessage.content
+				}
+			})
+		);
+
 		if (autoScroll) {
 		if (autoScroll) {
 			scrollToBottom();
 			scrollToBottom();
 		}
 		}
@@ -887,6 +846,15 @@
 
 
 		scrollToBottom();
 		scrollToBottom();
 
 
+		eventTarget.dispatchEvent(
+			new CustomEvent('chat:start', {
+				detail: {
+					id: responseMessageId
+				}
+			})
+		);
+		await tick();
+
 		try {
 		try {
 			const [res, controller] = await generateOpenAIChatCompletion(
 			const [res, controller] = await generateOpenAIChatCompletion(
 				localStorage.token,
 				localStorage.token,
@@ -1007,6 +975,23 @@
 						continue;
 						continue;
 					} else {
 					} else {
 						responseMessage.content += value;
 						responseMessage.content += value;
+
+						const sentences = extractSentencesForAudio(responseMessage.content);
+						sentences.pop();
+
+						// dispatch only last sentence and make sure it hasn't been dispatched before
+						if (
+							sentences.length > 0 &&
+							sentences[sentences.length - 1] !== responseMessage.lastSentence
+						) {
+							responseMessage.lastSentence = sentences[sentences.length - 1];
+							eventTarget.dispatchEvent(
+								new CustomEvent('chat', {
+									detail: { id: responseMessageId, content: sentences[sentences.length - 1] }
+								})
+							);
+						}
+
 						messages = messages;
 						messages = messages;
 					}
 					}
 
 
@@ -1057,6 +1042,24 @@
 		stopResponseFlag = false;
 		stopResponseFlag = false;
 		await tick();
 		await tick();
 
 
+		let lastSentence = extractSentencesForAudio(responseMessage.content)?.at(-1) ?? '';
+		if (lastSentence) {
+			eventTarget.dispatchEvent(
+				new CustomEvent('chat', {
+					detail: { id: responseMessageId, content: lastSentence }
+				})
+			);
+		}
+
+		eventTarget.dispatchEvent(
+			new CustomEvent('chat:finish', {
+				detail: {
+					id: responseMessageId,
+					content: responseMessage.content
+				}
+			})
+		);
+
 		if (autoScroll) {
 		if (autoScroll) {
 			scrollToBottom();
 			scrollToBottom();
 		}
 		}
@@ -1123,9 +1126,12 @@
 			let userPrompt = userMessage.content;
 			let userPrompt = userMessage.content;
 
 
 			if ((userMessage?.models ?? [...selectedModels]).length == 1) {
 			if ((userMessage?.models ?? [...selectedModels]).length == 1) {
-				await sendPrompt(userPrompt, userMessage.id, undefined, false);
+				// If user message has only one model selected, sendPrompt automatically selects it for regeneration
+				await sendPrompt(userPrompt, userMessage.id);
 			} else {
 			} else {
-				await sendPrompt(userPrompt, userMessage.id, message.model, false);
+				// If there are multiple models selected, use the model of the response message for regeneration
+				// e.g. many model chat
+				await sendPrompt(userPrompt, userMessage.id, { modelId: message.model });
 			}
 			}
 		}
 		}
 	};
 	};
@@ -1191,6 +1197,84 @@
 		}
 		}
 	};
 	};
 
 
+	const getWebSearchResults = async (model: string, parentId: string, responseId: string) => {
+		const responseMessage = history.messages[responseId];
+
+		responseMessage.statusHistory = [
+			{
+				done: false,
+				action: 'web_search',
+				description: $i18n.t('Generating search query')
+			}
+		];
+		messages = messages;
+
+		const prompt = history.messages[parentId].content;
+		let searchQuery = await generateSearchQuery(localStorage.token, model, messages, prompt).catch(
+			(error) => {
+				console.log(error);
+				return prompt;
+			}
+		);
+
+		if (!searchQuery) {
+			toast.warning($i18n.t('No search query generated'));
+			responseMessage.statusHistory.push({
+				done: true,
+				error: true,
+				action: 'web_search',
+				description: 'No search query generated'
+			});
+
+			messages = messages;
+		}
+
+		responseMessage.statusHistory.push({
+			done: false,
+			action: 'web_search',
+			description: $i18n.t(`Searching "{{searchQuery}}"`, { searchQuery })
+		});
+		messages = messages;
+
+		const results = await runWebSearch(localStorage.token, searchQuery).catch((error) => {
+			console.log(error);
+			toast.error(error);
+
+			return null;
+		});
+
+		if (results) {
+			responseMessage.statusHistory.push({
+				done: true,
+				action: 'web_search',
+				description: $i18n.t('Searched {{count}} sites', { count: results.filenames.length }),
+				query: searchQuery,
+				urls: results.filenames
+			});
+
+			if (responseMessage?.files ?? undefined === undefined) {
+				responseMessage.files = [];
+			}
+
+			responseMessage.files.push({
+				collection_name: results.collection_name,
+				name: searchQuery,
+				type: 'web_search_results',
+				urls: results.filenames
+			});
+
+			messages = messages;
+		} else {
+			responseMessage.statusHistory.push({
+				done: true,
+				error: true,
+				action: 'web_search',
+				description: 'No search results found'
+			});
+			messages = messages;
+		}
+	};
+
 	const getTags = async () => {
 	const getTags = async () => {
 		return await getTagsById(localStorage.token, $chatId).catch(async (error) => {
 		return await getTagsById(localStorage.token, $chatId).catch(async (error) => {
 			return [];
 			return [];
@@ -1206,7 +1290,18 @@
 	</title>
 	</title>
 </svelte:head>
 </svelte:head>
 
 
-<CallOverlay {submitPrompt} bind:files />
+<audio id="audioElement" src="" style="display: none;" />
+
+{#if $showCallOverlay}
+	<CallOverlay
+		{submitPrompt}
+		{stopResponse}
+		bind:files
+		modelId={selectedModelIds?.at(0) ?? null}
+		chatId={$chatId}
+		{eventTarget}
+	/>
+{/if}
 
 
 {#if !chatIdProp || (loaded && chatIdProp)}
 {#if !chatIdProp || (loaded && chatIdProp)}
 	<div
 	<div

+ 3 - 4
src/lib/components/chat/MessageInput.svelte

@@ -348,7 +348,6 @@
 				<Models
 				<Models
 					bind:this={modelsElement}
 					bind:this={modelsElement}
 					bind:prompt
 					bind:prompt
-					bind:user
 					bind:chatInputPlaceholder
 					bind:chatInputPlaceholder
 					{messages}
 					{messages}
 					on:select={(e) => {
 					on:select={(e) => {
@@ -467,7 +466,7 @@
 							document.getElementById('chat-textarea')?.focus();
 							document.getElementById('chat-textarea')?.focus();
 
 
 							if ($settings?.speechAutoSend ?? false) {
 							if ($settings?.speechAutoSend ?? false) {
-								submitPrompt(prompt, user);
+								submitPrompt(prompt);
 							}
 							}
 						}}
 						}}
 					/>
 					/>
@@ -476,7 +475,7 @@
 						class="w-full flex gap-1.5"
 						class="w-full flex gap-1.5"
 						on:submit|preventDefault={() => {
 						on:submit|preventDefault={() => {
 							// check if selectedModels support image input
 							// check if selectedModels support image input
-							submitPrompt(prompt, user);
+							submitPrompt(prompt);
 						}}
 						}}
 					>
 					>
 						<div
 						<div
@@ -718,7 +717,7 @@
 
 
 											// Submit the prompt when Enter key is pressed
 											// Submit the prompt when Enter key is pressed
 											if (prompt !== '' && e.key === 'Enter' && !e.shiftKey) {
 											if (prompt !== '' && e.key === 'Enter' && !e.shiftKey) {
-												submitPrompt(prompt, user);
+												submitPrompt(prompt);
 											}
 											}
 										}
 										}
 									}}
 									}}

+ 447 - 298
src/lib/components/chat/MessageInput/CallOverlay.svelte

@@ -2,40 +2,238 @@
 	import { config, settings, showCallOverlay } from '$lib/stores';
 	import { config, settings, showCallOverlay } from '$lib/stores';
 	import { onMount, tick, getContext } from 'svelte';
 	import { onMount, tick, getContext } from 'svelte';
 
 
-	import { blobToFile, calculateSHA256, extractSentences, findWordIndices } from '$lib/utils';
+	import {
+		blobToFile,
+		calculateSHA256,
+		extractSentencesForAudio,
+		findWordIndices
+	} from '$lib/utils';
+	import { generateEmoji } from '$lib/apis';
 	import { synthesizeOpenAISpeech, transcribeAudio } from '$lib/apis/audio';
 	import { synthesizeOpenAISpeech, transcribeAudio } from '$lib/apis/audio';
+
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
 
 
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import VideoInputMenu from './CallOverlay/VideoInputMenu.svelte';
 	import VideoInputMenu from './CallOverlay/VideoInputMenu.svelte';
-	import { get } from 'svelte/store';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
+	export let eventTarget: EventTarget;
+
 	export let submitPrompt: Function;
 	export let submitPrompt: Function;
+	export let stopResponse: Function;
+
 	export let files;
 	export let files;
 
 
+	export let chatId;
+	export let modelId;
+
 	let loading = false;
 	let loading = false;
 	let confirmed = false;
 	let confirmed = false;
+	let interrupted = false;
+
+	let emoji = null;
 
 
 	let camera = false;
 	let camera = false;
 	let cameraStream = null;
 	let cameraStream = null;
 
 
-	let assistantSpeaking = false;
-	let assistantAudio = {};
-	let assistantAudioIdx = null;
+	let chatStreaming = false;
 
 
 	let rmsLevel = 0;
 	let rmsLevel = 0;
 	let hasStartedSpeaking = false;
 	let hasStartedSpeaking = false;
-
-	let currentUtterance = null;
-
 	let mediaRecorder;
 	let mediaRecorder;
 	let audioChunks = [];
 	let audioChunks = [];
 
 
-	const MIN_DECIBELS = -45;
+	let videoInputDevices = [];
+	let selectedVideoInputDeviceId = null;
+
+	const getVideoInputDevices = async () => {
+		const devices = await navigator.mediaDevices.enumerateDevices();
+		videoInputDevices = devices.filter((device) => device.kind === 'videoinput');
+
+		if (!!navigator.mediaDevices.getDisplayMedia) {
+			videoInputDevices = [
+				...videoInputDevices,
+				{
+					deviceId: 'screen',
+					label: 'Screen Share'
+				}
+			];
+		}
+
+		console.log(videoInputDevices);
+		if (selectedVideoInputDeviceId === null && videoInputDevices.length > 0) {
+			selectedVideoInputDeviceId = videoInputDevices[0].deviceId;
+		}
+	};
+
+	const startCamera = async () => {
+		await getVideoInputDevices();
+
+		if (cameraStream === null) {
+			camera = true;
+			await tick();
+			try {
+				await startVideoStream();
+			} catch (err) {
+				console.error('Error accessing webcam: ', err);
+			}
+		}
+	};
+
+	const startVideoStream = async () => {
+		const video = document.getElementById('camera-feed');
+		if (video) {
+			if (selectedVideoInputDeviceId === 'screen') {
+				cameraStream = await navigator.mediaDevices.getDisplayMedia({
+					video: {
+						cursor: 'always'
+					},
+					audio: false
+				});
+			} else {
+				cameraStream = await navigator.mediaDevices.getUserMedia({
+					video: {
+						deviceId: selectedVideoInputDeviceId ? { exact: selectedVideoInputDeviceId } : undefined
+					}
+				});
+			}
+
+			if (cameraStream) {
+				await getVideoInputDevices();
+				video.srcObject = cameraStream;
+				await video.play();
+			}
+		}
+	};
+
+	const stopVideoStream = async () => {
+		if (cameraStream) {
+			const tracks = cameraStream.getTracks();
+			tracks.forEach((track) => track.stop());
+		}
+
+		cameraStream = null;
+	};
+
+	const takeScreenshot = () => {
+		const video = document.getElementById('camera-feed');
+		const canvas = document.getElementById('camera-canvas');
+
+		if (!canvas) {
+			return;
+		}
+
+		const context = canvas.getContext('2d');
+
+		// Make the canvas match the video dimensions
+		canvas.width = video.videoWidth;
+		canvas.height = video.videoHeight;
+
+		// Draw the image from the video onto the canvas
+		context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
+
+		// Convert the canvas to a data base64 URL and console log it
+		const dataURL = canvas.toDataURL('image/png');
+		console.log(dataURL);
+
+		return dataURL;
+	};
+
+	const stopCamera = async () => {
+		await stopVideoStream();
+		camera = false;
+	};
+
+	const MIN_DECIBELS = -55;
 	const VISUALIZER_BUFFER_LENGTH = 300;
 	const VISUALIZER_BUFFER_LENGTH = 300;
 
 
+	const transcribeHandler = async (audioBlob) => {
+		// Create a blob from the audio chunks
+
+		await tick();
+		const file = blobToFile(audioBlob, 'recording.wav');
+
+		const res = await transcribeAudio(localStorage.token, file).catch((error) => {
+			toast.error(error);
+			return null;
+		});
+
+		if (res) {
+			console.log(res.text);
+
+			if (res.text !== '') {
+				const _responses = await submitPrompt(res.text, { _raw: true });
+				console.log(_responses);
+			}
+		}
+	};
+
+	const stopRecordingCallback = async (_continue = true) => {
+		if ($showCallOverlay) {
+			console.log('%c%s', 'color: red; font-size: 20px;', '🚨 stopRecordingCallback 🚨');
+
+			// deep copy the audioChunks array
+			const _audioChunks = audioChunks.slice(0);
+
+			audioChunks = [];
+			mediaRecorder = false;
+
+			if (_continue) {
+				startRecording();
+			}
+
+			if (confirmed) {
+				loading = true;
+				emoji = null;
+
+				if (cameraStream) {
+					const imageUrl = takeScreenshot();
+
+					files = [
+						{
+							type: 'image',
+							url: imageUrl
+						}
+					];
+				}
+
+				const audioBlob = new Blob(_audioChunks, { type: 'audio/wav' });
+				await transcribeHandler(audioBlob);
+
+				confirmed = false;
+				loading = false;
+			}
+		} else {
+			audioChunks = [];
+			mediaRecorder = false;
+		}
+	};
+
+	const startRecording = async () => {
+		const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+		mediaRecorder = new MediaRecorder(stream);
+
+		mediaRecorder.onstart = () => {
+			console.log('Recording started');
+			audioChunks = [];
+			analyseAudio(stream);
+		};
+
+		mediaRecorder.ondataavailable = (event) => {
+			if (hasStartedSpeaking) {
+				audioChunks.push(event.data);
+			}
+		};
+
+		mediaRecorder.onstop = (e) => {
+			console.log('Recording stopped', e);
+			stopRecordingCallback();
+		};
+
+		mediaRecorder.start();
+	};
+
 	// Function to calculate the RMS level from time domain data
 	// Function to calculate the RMS level from time domain data
 	const calculateRMS = (data: Uint8Array) => {
 	const calculateRMS = (data: Uint8Array) => {
 		let sumSquares = 0;
 		let sumSquares = 0;
@@ -46,15 +244,6 @@
 		return Math.sqrt(sumSquares / data.length);
 		return Math.sqrt(sumSquares / data.length);
 	};
 	};
 
 
-	const normalizeRMS = (rms) => {
-		rms = rms * 10;
-		const exp = 1.5; // Adjust exponent value; values greater than 1 expand larger numbers more and compress smaller numbers more
-		const scaledRMS = Math.pow(rms, exp);
-
-		// Scale between 0.01 (1%) and 1.0 (100%)
-		return Math.min(1.0, Math.max(0.01, scaledRMS));
-	};
-
 	const analyseAudio = (stream) => {
 	const analyseAudio = (stream) => {
 		const audioContext = new AudioContext();
 		const audioContext = new AudioContext();
 		const audioStreamSource = audioContext.createMediaStreamSource(stream);
 		const audioStreamSource = audioContext.createMediaStreamSource(stream);
@@ -71,15 +260,14 @@
 		let lastSoundTime = Date.now();
 		let lastSoundTime = Date.now();
 		hasStartedSpeaking = false;
 		hasStartedSpeaking = false;
 
 
+		console.log('🔊 Sound detection started', lastSoundTime, hasStartedSpeaking);
+
 		const detectSound = () => {
 		const detectSound = () => {
 			const processFrame = () => {
 			const processFrame = () => {
 				if (!mediaRecorder || !$showCallOverlay) {
 				if (!mediaRecorder || !$showCallOverlay) {
-					if (mediaRecorder) {
-						mediaRecorder.stop();
-					}
-
 					return;
 					return;
 				}
 				}
+
 				analyser.getByteTimeDomainData(timeDomainData);
 				analyser.getByteTimeDomainData(timeDomainData);
 				analyser.getByteFrequencyData(domainData);
 				analyser.getByteFrequencyData(domainData);
 
 
@@ -89,8 +277,14 @@
 				// Check if initial speech/noise has started
 				// Check if initial speech/noise has started
 				const hasSound = domainData.some((value) => value > 0);
 				const hasSound = domainData.some((value) => value > 0);
 				if (hasSound) {
 				if (hasSound) {
-					stopAllAudio();
-					hasStartedSpeaking = true;
+					// BIG RED TEXT
+					console.log('%c%s', 'color: red; font-size: 20px;', '🔊 Sound detected');
+
+					if (!hasStartedSpeaking) {
+						hasStartedSpeaking = true;
+						stopAllAudio();
+					}
+
 					lastSoundTime = Date.now();
 					lastSoundTime = Date.now();
 				}
 				}
 
 
@@ -100,7 +294,9 @@
 						confirmed = true;
 						confirmed = true;
 
 
 						if (mediaRecorder) {
 						if (mediaRecorder) {
+							console.log('%c%s', 'color: red; font-size: 20px;', '🔇 Silence detected');
 							mediaRecorder.stop();
 							mediaRecorder.stop();
+							return;
 						}
 						}
 					}
 					}
 				}
 				}
@@ -114,348 +310,288 @@
 		detectSound();
 		detectSound();
 	};
 	};
 
 
-	const stopAllAudio = () => {
-		if (currentUtterance) {
-			speechSynthesis.cancel();
-			currentUtterance = null;
-		}
-		if (assistantAudio[assistantAudioIdx]) {
-			assistantAudio[assistantAudioIdx].pause();
-			assistantAudio[assistantAudioIdx].currentTime = 0;
-		}
+	let finishedMessages = {};
+	let currentMessageId = null;
+	let currentUtterance = null;
 
 
-		const audioElement = document.getElementById('audioElement');
-		audioElement.pause();
-		audioElement.currentTime = 0;
+	const speakSpeechSynthesisHandler = (content) => {
+		if ($showCallOverlay) {
+			return new Promise((resolve) => {
+				let voices = [];
+				const getVoicesLoop = setInterval(async () => {
+					voices = await speechSynthesis.getVoices();
+					if (voices.length > 0) {
+						clearInterval(getVoicesLoop);
+
+						const voice =
+							voices
+								?.filter(
+									(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
+								)
+								?.at(0) ?? undefined;
+
+						currentUtterance = new SpeechSynthesisUtterance(content);
+
+						if (voice) {
+							currentUtterance.voice = voice;
+						}
 
 
-		assistantSpeaking = false;
+						speechSynthesis.speak(currentUtterance);
+						currentUtterance.onend = async (e) => {
+							await new Promise((r) => setTimeout(r, 200));
+							resolve(e);
+						};
+					}
+				}, 100);
+			});
+		} else {
+			return Promise.resolve();
+		}
 	};
 	};
 
 
-	const playAudio = (idx) => {
+	const playAudio = (audio) => {
 		if ($showCallOverlay) {
 		if ($showCallOverlay) {
-			return new Promise((res) => {
-				assistantAudioIdx = idx;
+			return new Promise((resolve) => {
 				const audioElement = document.getElementById('audioElement');
 				const audioElement = document.getElementById('audioElement');
-				const audio = assistantAudio[idx];
 
 
-				audioElement.src = audio.src; // Assume `assistantAudio` has objects with a `src` property
-
-				audioElement.muted = true;
-
-				audioElement
-					.play()
-					.then(() => {
-						audioElement.muted = false;
-					})
-					.catch((error) => {
-						toast.error(error);
-					});
-
-				audioElement.onended = async (e) => {
-					await new Promise((r) => setTimeout(r, 300));
-
-					if (Object.keys(assistantAudio).length - 1 === idx) {
-						assistantSpeaking = false;
-					}
-
-					res(e);
-				};
+				if (audioElement) {
+					audioElement.src = audio.src;
+					audioElement.muted = true;
+
+					audioElement
+						.play()
+						.then(() => {
+							audioElement.muted = false;
+						})
+						.catch((error) => {
+							console.error(error);
+						});
+
+					audioElement.onended = async (e) => {
+						await new Promise((r) => setTimeout(r, 100));
+						resolve(e);
+					};
+				}
 			});
 			});
 		} else {
 		} else {
 			return Promise.resolve();
 			return Promise.resolve();
 		}
 		}
 	};
 	};
 
 
-	const getOpenAISpeech = async (text) => {
-		const res = await synthesizeOpenAISpeech(
-			localStorage.token,
-			$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
-			text
-		).catch((error) => {
-			toast.error(error);
-			assistantSpeaking = false;
-			return null;
-		});
+	const stopAllAudio = async () => {
+		interrupted = true;
 
 
-		if (res) {
-			const blob = await res.blob();
-			const blobUrl = URL.createObjectURL(blob);
-			const audio = new Audio(blobUrl);
-			assistantAudio = audio;
+		if (chatStreaming) {
+			stopResponse();
 		}
 		}
-	};
 
 
-	const transcribeHandler = async (audioBlob) => {
-		// Create a blob from the audio chunks
+		if (currentUtterance) {
+			speechSynthesis.cancel();
+			currentUtterance = null;
+		}
 
 
-		await tick();
-		const file = blobToFile(audioBlob, 'recording.wav');
+		const audioElement = document.getElementById('audioElement');
+		if (audioElement) {
+			audioElement.muted = true;
+			audioElement.pause();
+			audioElement.currentTime = 0;
+		}
+	};
 
 
-		const res = await transcribeAudio(localStorage.token, file).catch((error) => {
-			toast.error(error);
-			return null;
-		});
+	let audioAbortController = new AbortController();
 
 
-		if (res) {
-			console.log(res.text);
+	// Audio cache map where key is the content and value is the Audio object.
+	const audioCache = new Map();
+	const emojiCache = new Map();
 
 
-			if (res.text !== '') {
-				const _responses = await submitPrompt(res.text);
-				console.log(_responses);
+	const fetchAudio = async (content) => {
+		if (!audioCache.has(content)) {
+			try {
+				// Set the emoji for the content if needed
+				if ($settings?.showEmojiInCall ?? false) {
+					const emoji = await generateEmoji(localStorage.token, modelId, content, chatId);
+					if (emoji) {
+						emojiCache.set(content, emoji);
+					}
+				}
 
 
-				if (_responses.at(0)) {
-					const content = _responses[0];
-					if ((content ?? '').trim() !== '') {
-						assistantSpeakingHandler(content);
+				if ($config.audio.tts.engine !== '') {
+					const res = await synthesizeOpenAISpeech(
+						localStorage.token,
+						$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
+						content
+					).catch((error) => {
+						console.error(error);
+						return null;
+					});
+
+					if (res) {
+						const blob = await res.blob();
+						const blobUrl = URL.createObjectURL(blob);
+						audioCache.set(content, new Audio(blobUrl));
 					}
 					}
+				} else {
+					audioCache.set(content, true);
 				}
 				}
+			} catch (error) {
+				console.error('Error synthesizing speech:', error);
 			}
 			}
 		}
 		}
-	};
 
 
-	const assistantSpeakingHandler = async (content) => {
-		assistantSpeaking = true;
+		return audioCache.get(content);
+	};
 
 
-		if (($config.audio.tts.engine ?? '') == '') {
-			let voices = [];
-			const getVoicesLoop = setInterval(async () => {
-				voices = await speechSynthesis.getVoices();
-				if (voices.length > 0) {
-					clearInterval(getVoicesLoop);
+	let messages = {};
 
 
-					const voice =
-						voices
-							?.filter(
-								(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
-							)
-							?.at(0) ?? undefined;
+	const monitorAndPlayAudio = async (id, signal) => {
+		while (!signal.aborted) {
+			if (messages[id] && messages[id].length > 0) {
+				// Retrieve the next content string from the queue
+				const content = messages[id].shift(); // Dequeues the content for playing
 
 
-					currentUtterance = new SpeechSynthesisUtterance(content);
+				if (audioCache.has(content)) {
+					// If content is available in the cache, play it
 
 
-					if (voice) {
-						currentUtterance.voice = voice;
+					// Set the emoji for the content if available
+					if (($settings?.showEmojiInCall ?? false) && emojiCache.has(content)) {
+						emoji = emojiCache.get(content);
+					} else {
+						emoji = null;
 					}
 					}
 
 
-					speechSynthesis.speak(currentUtterance);
-				}
-			}, 100);
-		} else if ($config.audio.tts.engine === 'openai') {
-			console.log('openai');
-
-			const sentences = extractSentences(content).reduce((mergedTexts, currentText) => {
-				const lastIndex = mergedTexts.length - 1;
-				if (lastIndex >= 0) {
-					const previousText = mergedTexts[lastIndex];
-					const wordCount = previousText.split(/\s+/).length;
-					if (wordCount < 2) {
-						mergedTexts[lastIndex] = previousText + ' ' + currentText;
+					if ($config.audio.tts.engine !== '') {
+						try {
+							console.log(
+								'%c%s',
+								'color: red; font-size: 20px;',
+								`Playing audio for content: ${content}`
+							);
+
+							const audio = audioCache.get(content);
+							await playAudio(audio); // Here ensure that playAudio is indeed correct method to execute
+							console.log(`Played audio for content: ${content}`);
+							await new Promise((resolve) => setTimeout(resolve, 200)); // Wait before retrying to reduce tight loop
+						} catch (error) {
+							console.error('Error playing audio:', error);
+						}
 					} else {
 					} else {
-						mergedTexts.push(currentText);
+						await speakSpeechSynthesisHandler(content);
 					}
 					}
 				} else {
 				} else {
-					mergedTexts.push(currentText);
-				}
-				return mergedTexts;
-			}, []);
-
-			console.log(sentences);
-
-			let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
-
-			for (const [idx, sentence] of sentences.entries()) {
-				const res = await synthesizeOpenAISpeech(
-					localStorage.token,
-					$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
-					sentence
-				).catch((error) => {
-					toast.error(error);
-
-					assistantSpeaking = false;
-					return null;
-				});
-
-				if (res) {
-					const blob = await res.blob();
-					const blobUrl = URL.createObjectURL(blob);
-					const audio = new Audio(blobUrl);
-					assistantAudio[idx] = audio;
-					lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+					// If not available in the cache, push it back to the queue and delay
+					messages[id].unshift(content); // Re-queue the content at the start
+					console.log(`Audio for "${content}" not yet available in the cache, re-queued...`);
+					await new Promise((resolve) => setTimeout(resolve, 200)); // Wait before retrying to reduce tight loop
 				}
 				}
+			} else if (finishedMessages[id] && messages[id] && messages[id].length === 0) {
+				// If the message is finished and there are no more messages to process, break the loop
+				break;
+			} else {
+				// No messages to process, sleep for a bit
+				await new Promise((resolve) => setTimeout(resolve, 200));
 			}
 			}
 		}
 		}
+		console.log(`Audio monitoring and playing stopped for message ID ${id}`);
 	};
 	};
 
 
-	const stopRecordingCallback = async () => {
-		if ($showCallOverlay) {
-			if (confirmed) {
-				loading = true;
-
-				if (cameraStream) {
-					const imageUrl = takeScreenshot();
+	onMount(async () => {
+		startRecording();
 
 
-					files = [
-						{
-							type: 'image',
-							url: imageUrl
-						}
-					];
-				}
+		const chatStartHandler = async (e) => {
+			const { id } = e.detail;
 
 
-				const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
-				await transcribeHandler(audioBlob);
+			chatStreaming = true;
 
 
-				confirmed = false;
-				loading = false;
-			}
-			audioChunks = [];
-			mediaRecorder = false;
+			if (currentMessageId !== id) {
+				console.log(`Received chat start event for message ID ${id}`);
 
 
-			startRecording();
-		} else {
-			audioChunks = [];
-			mediaRecorder = false;
-		}
-	};
+				currentMessageId = id;
+				if (audioAbortController) {
+					audioAbortController.abort();
+				}
+				audioAbortController = new AbortController();
 
 
-	const startRecording = async () => {
-		const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
-		mediaRecorder = new MediaRecorder(stream);
-		mediaRecorder.onstart = () => {
-			console.log('Recording started');
-			audioChunks = [];
-			analyseAudio(stream);
-		};
-		mediaRecorder.ondataavailable = (event) => {
-			if (hasStartedSpeaking) {
-				audioChunks.push(event.data);
+				// Start monitoring and playing audio for the message ID
+				monitorAndPlayAudio(id, audioAbortController.signal);
 			}
 			}
 		};
 		};
-		mediaRecorder.onstop = async () => {
-			console.log('Recording stopped');
-
-			await stopRecordingCallback();
-		};
-		mediaRecorder.start();
-	};
 
 
-	let videoInputDevices = [];
-	let selectedVideoInputDeviceId = null;
+		const chatEventHandler = async (e) => {
+			const { id, content } = e.detail;
+			// "id" here is message id
+			// if "id" is not the same as "currentMessageId" then do not process
+			// "content" here is a sentence from the assistant,
+			// there will be many sentences for the same "id"
 
 
-	const getVideoInputDevices = async () => {
-		const devices = await navigator.mediaDevices.enumerateDevices();
-		videoInputDevices = devices.filter((device) => device.kind === 'videoinput');
+			if (currentMessageId === id) {
+				console.log(`Received chat event for message ID ${id}: ${content}`);
 
 
-		if (!!navigator.mediaDevices.getDisplayMedia) {
-			videoInputDevices = [
-				...videoInputDevices,
-				{
-					deviceId: 'screen',
-					label: 'Screen Share'
-				}
-			];
-		}
-
-		console.log(videoInputDevices);
-		if (selectedVideoInputDeviceId === null && videoInputDevices.length > 0) {
-			selectedVideoInputDeviceId = videoInputDevices[0].deviceId;
-		}
-	};
-
-	const startCamera = async () => {
-		await getVideoInputDevices();
-
-		if (cameraStream === null) {
-			camera = true;
-			await tick();
-			try {
-				await startVideoStream();
-			} catch (err) {
-				console.error('Error accessing webcam: ', err);
-			}
-		}
-	};
-
-	const startVideoStream = async () => {
-		const video = document.getElementById('camera-feed');
-		if (video) {
-			if (selectedVideoInputDeviceId === 'screen') {
-				cameraStream = await navigator.mediaDevices.getDisplayMedia({
-					video: {
-						cursor: 'always'
-					},
-					audio: false
-				});
-			} else {
-				cameraStream = await navigator.mediaDevices.getUserMedia({
-					video: {
-						deviceId: selectedVideoInputDeviceId ? { exact: selectedVideoInputDeviceId } : undefined
+				try {
+					if (messages[id] === undefined) {
+						messages[id] = [content];
+					} else {
+						messages[id].push(content);
 					}
 					}
-				});
-			}
 
 
-			if (cameraStream) {
-				await getVideoInputDevices();
-				video.srcObject = cameraStream;
-				await video.play();
-			}
-		}
-	};
+					console.log(content);
 
 
-	const stopVideoStream = async () => {
-		if (cameraStream) {
-			const tracks = cameraStream.getTracks();
-			tracks.forEach((track) => track.stop());
-		}
-
-		cameraStream = null;
-	};
-
-	const takeScreenshot = () => {
-		const video = document.getElementById('camera-feed');
-		const canvas = document.getElementById('camera-canvas');
-
-		if (!canvas) {
-			return;
-		}
+					fetchAudio(content);
+				} catch (error) {
+					console.error('Failed to fetch or play audio:', error);
+				}
+			}
+		};
 
 
-		const context = canvas.getContext('2d');
+		const chatFinishHandler = async (e) => {
+			const { id, content } = e.detail;
+			// "content" here is the entire message from the assistant
 
 
-		// Make the canvas match the video dimensions
-		canvas.width = video.videoWidth;
-		canvas.height = video.videoHeight;
+			chatStreaming = false;
+			finishedMessages[id] = true;
+		};
 
 
-		// Draw the image from the video onto the canvas
-		context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
+		eventTarget.addEventListener('chat:start', chatStartHandler);
+		eventTarget.addEventListener('chat', chatEventHandler);
+		eventTarget.addEventListener('chat:finish', chatFinishHandler);
 
 
-		// Convert the canvas to a data base64 URL and console log it
-		const dataURL = canvas.toDataURL('image/png');
-		console.log(dataURL);
+		return async () => {
+			eventTarget.removeEventListener('chat:start', chatStartHandler);
+			eventTarget.removeEventListener('chat', chatEventHandler);
+			eventTarget.removeEventListener('chat:finish', chatFinishHandler);
 
 
-		return dataURL;
-	};
+			audioAbortController.abort();
+			await tick();
 
 
-	const stopCamera = async () => {
-		await stopVideoStream();
-		camera = false;
-	};
+			await stopAllAudio();
 
 
-	$: if ($showCallOverlay) {
-		startRecording();
-	} else {
-		stopCamera();
-	}
+			await stopRecordingCallback(false);
+			await stopCamera();
+		};
+	});
 </script>
 </script>
 
 
 {#if $showCallOverlay}
 {#if $showCallOverlay}
-	<audio id="audioElement" src="" style="display: none;" />
 	<div class=" absolute w-full h-screen max-h-[100dvh] flex z-[999] overflow-hidden">
 	<div class=" absolute w-full h-screen max-h-[100dvh] flex z-[999] overflow-hidden">
 		<div
 		<div
 			class="absolute w-full h-screen max-h-[100dvh] bg-white text-gray-700 dark:bg-black dark:text-gray-300 flex justify-center"
 			class="absolute w-full h-screen max-h-[100dvh] bg-white text-gray-700 dark:bg-black dark:text-gray-300 flex justify-center"
 		>
 		>
 			<div class="max-w-lg w-full h-screen max-h-[100dvh] flex flex-col justify-between p-3 md:p-6">
 			<div class="max-w-lg w-full h-screen max-h-[100dvh] flex flex-col justify-between p-3 md:p-6">
 				{#if camera}
 				{#if camera}
-					<div class="flex justify-center items-center w-full min-h-20">
-						{#if loading}
+					<div class="flex justify-center items-center w-full h-20 min-h-20">
+						{#if emoji}
+							<div
+								class="  transition-all rounded-full"
+								style="font-size:{rmsLevel * 100 > 4
+									? '4.5'
+									: rmsLevel * 100 > 2
+									? '4.25'
+									: rmsLevel * 100 > 1
+									? '3.75'
+									: '3.5'}rem;width: 100%; text-align:center;"
+							>
+								{emoji}
+							</div>
+						{:else if loading}
 							<svg
 							<svg
 								class="size-12 text-gray-900 dark:text-gray-400"
 								class="size-12 text-gray-900 dark:text-gray-400"
 								viewBox="0 0 24 24"
 								viewBox="0 0 24 24"
@@ -509,7 +645,20 @@
 
 
 				<div class="flex justify-center items-center flex-1 h-full w-full max-h-full">
 				<div class="flex justify-center items-center flex-1 h-full w-full max-h-full">
 					{#if !camera}
 					{#if !camera}
-						{#if loading}
+						{#if emoji}
+							<div
+								class="  transition-all rounded-full"
+								style="font-size:{rmsLevel * 100 > 4
+									? '13'
+									: rmsLevel * 100 > 2
+									? '12'
+									: rmsLevel * 100 > 1
+									? '11.5'
+									: '11'}rem;width:100%;text-align:center;"
+							>
+								{emoji}
+							</div>
+						{:else if loading}
 							<svg
 							<svg
 								class="size-44 text-gray-900 dark:text-gray-400"
 								class="size-44 text-gray-900 dark:text-gray-400"
 								viewBox="0 0 24 24"
 								viewBox="0 0 24 24"

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

@@ -79,7 +79,7 @@
 		history.currentId = userMessageId;
 		history.currentId = userMessageId;
 
 
 		await tick();
 		await tick();
-		await sendPrompt(userPrompt, userMessageId, undefined, false);
+		await sendPrompt(userPrompt, userMessageId);
 	};
 	};
 
 
 	const updateChatMessages = async () => {
 	const updateChatMessages = async () => {

+ 9 - 2
src/lib/components/chat/Messages/Placeholder.svelte

@@ -1,11 +1,14 @@
 <script lang="ts">
 <script lang="ts">
 	import { WEBUI_BASE_URL } from '$lib/constants';
 	import { WEBUI_BASE_URL } from '$lib/constants';
+	import { marked } from 'marked';
+
 	import { config, user, models as _models } from '$lib/stores';
 	import { config, user, models as _models } from '$lib/stores';
 	import { onMount, getContext } from 'svelte';
 	import { onMount, getContext } from 'svelte';
 
 
 	import { blur, fade } from 'svelte/transition';
 	import { blur, fade } from 'svelte/transition';
 
 
 	import Suggestions from '../MessageInput/Suggestions.svelte';
 	import Suggestions from '../MessageInput/Suggestions.svelte';
+	import { sanitizeResponseContent } from '$lib/utils';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -65,8 +68,12 @@
 
 
 				<div in:fade={{ duration: 200, delay: 200 }}>
 				<div in:fade={{ duration: 200, delay: 200 }}>
 					{#if models[selectedModelIdx]?.info?.meta?.description ?? null}
 					{#if models[selectedModelIdx]?.info?.meta?.description ?? null}
-						<div class="mt-0.5 text-base font-normal text-gray-500 dark:text-gray-400 line-clamp-3">
-							{models[selectedModelIdx]?.info?.meta?.description}
+						<div
+							class="mt-0.5 text-base font-normal text-gray-500 dark:text-gray-400 line-clamp-3 markdown"
+						>
+							{@html marked.parse(
+								sanitizeResponseContent(models[selectedModelIdx]?.info?.meta?.description)
+							)}
 						</div>
 						</div>
 						{#if models[selectedModelIdx]?.info?.meta?.user}
 						{#if models[selectedModelIdx]?.info?.meta?.user}
 							<div class="mt-0.5 text-sm font-normal text-gray-400 dark:text-gray-500">
 							<div class="mt-0.5 text-sm font-normal text-gray-400 dark:text-gray-500">

+ 7 - 3
src/lib/components/chat/ModelSelector/Selector.svelte

@@ -1,5 +1,6 @@
 <script lang="ts">
 <script lang="ts">
 	import { DropdownMenu } from 'bits-ui';
 	import { DropdownMenu } from 'bits-ui';
+	import { marked } from 'marked';
 
 
 	import { flyAndScale } from '$lib/utils/transitions';
 	import { flyAndScale } from '$lib/utils/transitions';
 	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
 	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
@@ -333,9 +334,12 @@
 
 
 								{#if item.model?.info?.meta?.description}
 								{#if item.model?.info?.meta?.description}
 									<Tooltip
 									<Tooltip
-										content={`${sanitizeResponseContent(
-											item.model?.info?.meta?.description
-										).replaceAll('\n', '<br>')}`}
+										content={`${marked.parse(
+											sanitizeResponseContent(item.model?.info?.meta?.description).replaceAll(
+												'\n',
+												'<br>'
+											)
+										)}`}
 									>
 									>
 										<div class="">
 										<div class="">
 											<svg
 											<svg

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

@@ -21,6 +21,8 @@
 		top_p: null,
 		top_p: null,
 		tfs_z: null,
 		tfs_z: null,
 		num_ctx: null,
 		num_ctx: null,
+		num_batch: null,
+		num_keep: null,
 		max_tokens: null,
 		max_tokens: null,
 		use_mmap: null,
 		use_mmap: null,
 		use_mlock: null,
 		use_mlock: null,
@@ -565,6 +567,98 @@
 		{/if}
 		{/if}
 	</div>
 	</div>
 
 
+	<div class=" py-0.5 w-full justify-between">
+		<div class="flex w-full justify-between">
+			<div class=" self-center text-xs font-medium">{$i18n.t('Batch Size (num_batch)')}</div>
+
+			<button
+				class="p-1 px-3 text-xs flex rounded transition"
+				type="button"
+				on:click={() => {
+					params.num_batch = (params?.num_batch ?? null) === null ? 512 : null;
+				}}
+			>
+				{#if (params?.num_batch ?? null) === null}
+					<span class="ml-2 self-center">{$i18n.t('Default')}</span>
+				{:else}
+					<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
+				{/if}
+			</button>
+		</div>
+
+		{#if (params?.num_batch ?? null) !== null}
+			<div class="flex mt-0.5 space-x-2">
+				<div class=" flex-1">
+					<input
+						id="steps-range"
+						type="range"
+						min="256"
+						max="8192"
+						step="256"
+						bind:value={params.num_batch}
+						class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
+					/>
+				</div>
+				<div class="">
+					<input
+						bind:value={params.num_batch}
+						type="number"
+						class=" bg-transparent text-center w-14"
+						min="256"
+						step="256"
+					/>
+				</div>
+			</div>
+		{/if}
+	</div>
+
+	<div class=" py-0.5 w-full justify-between">
+		<div class="flex w-full justify-between">
+			<div class=" self-center text-xs font-medium">
+				{$i18n.t('Tokens To Keep On Context Refresh (num_keep)')}
+			</div>
+
+			<button
+				class="p-1 px-3 text-xs flex rounded transition"
+				type="button"
+				on:click={() => {
+					params.num_keep = (params?.num_keep ?? null) === null ? 24 : null;
+				}}
+			>
+				{#if (params?.num_keep ?? null) === null}
+					<span class="ml-2 self-center">{$i18n.t('Default')}</span>
+				{:else}
+					<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
+				{/if}
+			</button>
+		</div>
+
+		{#if (params?.num_keep ?? null) !== null}
+			<div class="flex mt-0.5 space-x-2">
+				<div class=" flex-1">
+					<input
+						id="steps-range"
+						type="range"
+						min="-1"
+						max="10240000"
+						step="1"
+						bind:value={params.num_keep}
+						class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
+					/>
+				</div>
+				<div class="">
+					<input
+						bind:value={params.num_keep}
+						type="number"
+						class=" bg-transparent text-center w-14"
+						min="-1"
+						step="1"
+					/>
+				</div>
+			</div>
+		{/if}
+	</div>
+
 	<div class=" py-0.5 w-full justify-between">
 	<div class=" py-0.5 w-full justify-between">
 		<div class="flex w-full justify-between">
 		<div class="flex w-full justify-between">
 			<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div>
 			<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div>

+ 4 - 0
src/lib/components/chat/Settings/General.svelte

@@ -55,6 +55,8 @@
 		stop: null,
 		stop: null,
 		tfs_z: null,
 		tfs_z: null,
 		num_ctx: null,
 		num_ctx: null,
+		num_batch: null,
+		num_keep: null,
 		max_tokens: null
 		max_tokens: null
 	};
 	};
 
 
@@ -308,6 +310,8 @@
 						top_p: params.top_p !== null ? params.top_p : undefined,
 						top_p: params.top_p !== null ? params.top_p : undefined,
 						tfs_z: params.tfs_z !== null ? params.tfs_z : undefined,
 						tfs_z: params.tfs_z !== null ? params.tfs_z : undefined,
 						num_ctx: params.num_ctx !== null ? params.num_ctx : undefined,
 						num_ctx: params.num_ctx !== null ? params.num_ctx : undefined,
+						num_batch: params.num_batch !== null ? params.num_batch : undefined,
+						num_keep: params.num_keep !== null ? params.num_keep : undefined,
 						max_tokens: params.max_tokens !== null ? params.max_tokens : undefined,
 						max_tokens: params.max_tokens !== null ? params.max_tokens : undefined,
 						use_mmap: params.use_mmap !== null ? params.use_mmap : undefined,
 						use_mmap: params.use_mmap !== null ? params.use_mmap : undefined,
 						use_mlock: params.use_mlock !== null ? params.use_mlock : undefined,
 						use_mlock: params.use_mlock !== null ? params.use_mlock : undefined,

+ 32 - 0
src/lib/components/chat/Settings/Interface.svelte

@@ -20,9 +20,12 @@
 	// Interface
 	// Interface
 	let defaultModelId = '';
 	let defaultModelId = '';
 	let showUsername = false;
 	let showUsername = false;
+
 	let chatBubble = true;
 	let chatBubble = true;
 	let chatDirection: 'LTR' | 'RTL' = 'LTR';
 	let chatDirection: 'LTR' | 'RTL' = 'LTR';
 
 
+	let showEmojiInCall = false;
+
 	const toggleSplitLargeChunks = async () => {
 	const toggleSplitLargeChunks = async () => {
 		splitLargeChunks = !splitLargeChunks;
 		splitLargeChunks = !splitLargeChunks;
 		saveSettings({ splitLargeChunks: splitLargeChunks });
 		saveSettings({ splitLargeChunks: splitLargeChunks });
@@ -43,6 +46,11 @@
 		saveSettings({ showUsername: showUsername });
 		saveSettings({ showUsername: showUsername });
 	};
 	};
 
 
+	const toggleEmojiInCall = async () => {
+		showEmojiInCall = !showEmojiInCall;
+		saveSettings({ showEmojiInCall: showEmojiInCall });
+	};
+
 	const toggleTitleAutoGenerate = async () => {
 	const toggleTitleAutoGenerate = async () => {
 		titleAutoGenerate = !titleAutoGenerate;
 		titleAutoGenerate = !titleAutoGenerate;
 		saveSettings({
 		saveSettings({
@@ -88,8 +96,12 @@
 
 
 	onMount(async () => {
 	onMount(async () => {
 		titleAutoGenerate = $settings?.title?.auto ?? true;
 		titleAutoGenerate = $settings?.title?.auto ?? true;
+
 		responseAutoCopy = $settings.responseAutoCopy ?? false;
 		responseAutoCopy = $settings.responseAutoCopy ?? false;
 		showUsername = $settings.showUsername ?? false;
 		showUsername = $settings.showUsername ?? false;
+
+		showEmojiInCall = $settings.showEmojiInCall ?? false;
+
 		chatBubble = $settings.chatBubble ?? true;
 		chatBubble = $settings.chatBubble ?? true;
 		widescreenMode = $settings.widescreenMode ?? false;
 		widescreenMode = $settings.widescreenMode ?? false;
 		splitLargeChunks = $settings.splitLargeChunks ?? false;
 		splitLargeChunks = $settings.splitLargeChunks ?? false;
@@ -192,6 +204,26 @@
 				</div>
 				</div>
 			</div>
 			</div>
 
 
+			<div>
+				<div class=" py-0.5 flex w-full justify-between">
+					<div class=" self-center text-xs font-medium">{$i18n.t('Display Emoji in Call')}</div>
+
+					<button
+						class="p-1 px-3 text-xs flex rounded transition"
+						on:click={() => {
+							toggleEmojiInCall();
+						}}
+						type="button"
+					>
+						{#if showEmojiInCall === 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>
+
 			{#if !$settings.chatBubble}
 			{#if !$settings.chatBubble}
 				<div>
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
 					<div class=" py-0.5 flex w-full justify-between">

+ 4 - 3
src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte

@@ -2,13 +2,12 @@
 	import { createEventDispatcher, getContext } from 'svelte';
 	import { createEventDispatcher, getContext } from 'svelte';
 
 
 	import Modal from '$lib/components/common/Modal.svelte';
 	import Modal from '$lib/components/common/Modal.svelte';
-	import { addNewMemory } from '$lib/apis/memories';
+	import { addNewMemory, updateMemoryById } from '$lib/apis/memories';
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
 
 
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
 
 
 	export let show;
 	export let show;
-
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
 	let loading = false;
 	let loading = false;
@@ -38,7 +37,9 @@
 <Modal bind:show size="sm">
 <Modal bind:show size="sm">
 	<div>
 	<div>
 		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
 		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
-			<div class=" text-lg font-medium self-center">{$i18n.t('Add Memory')}</div>
+			<div class=" text-lg font-medium self-center">
+				{$i18n.t('Add Memory')}
+			</div>
 			<button
 			<button
 				class="self-center"
 				class="self-center"
 				on:click={() => {
 				on:click={() => {

+ 136 - 0
src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte

@@ -0,0 +1,136 @@
+<script>
+	import { createEventDispatcher, getContext } from 'svelte';
+	import { toast } from 'svelte-sonner';
+
+	import { updateMemoryById } from '$lib/apis/memories';
+
+	import Modal from '$lib/components/common/Modal.svelte';
+
+	const dispatch = createEventDispatcher();
+
+	export let show;
+	export let memory = {};
+
+	const i18n = getContext('i18n');
+
+	let loading = false;
+	let content = '';
+
+	$: if (show) {
+		setContent();
+	}
+
+	const setContent = () => {
+		content = memory.content;
+	};
+
+	const submitHandler = async () => {
+		loading = true;
+
+		const res = await updateMemoryById(localStorage.token, memory.id, content).catch((error) => {
+			toast.error(error);
+
+			return null;
+		});
+
+		if (res) {
+			console.log(res);
+			toast.success('Memory updated successfully');
+			dispatch('save');
+			show = false;
+		}
+
+		loading = false;
+	};
+</script>
+
+<Modal bind:show size="sm">
+	<div>
+		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
+			<div class=" text-lg font-medium self-center">
+				{$i18n.t('Edit Memory')}
+			</div>
+			<button
+				class="self-center"
+				on:click={() => {
+					show = false;
+				}}
+			>
+				<svg
+					xmlns="http://www.w3.org/2000/svg"
+					viewBox="0 0 20 20"
+					fill="currentColor"
+					class="w-5 h-5"
+				>
+					<path
+						d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+					/>
+				</svg>
+			</button>
+		</div>
+
+		<div class="flex flex-col md:flex-row w-full px-5 pb-4 md:space-x-4 dark:text-gray-200">
+			<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
+				<form
+					class="flex flex-col w-full"
+					on:submit|preventDefault={() => {
+						submitHandler();
+					}}
+				>
+					<div class="">
+						<textarea
+							bind:value={content}
+							class=" bg-transparent w-full text-sm resize-none rounded-xl p-3 outline outline-1 outline-gray-100 dark:outline-gray-800"
+							rows="3"
+							placeholder={$i18n.t('Enter a detail about yourself for your LLMs to recall')}
+						/>
+
+						<div class="text-xs text-gray-500">
+							ⓘ {$i18n.t('Refer to yourself as "User" (e.g., "User is learning Spanish")')}
+						</div>
+					</div>
+
+					<div class="flex justify-end pt-1 text-sm font-medium">
+						<button
+							class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-3xl flex flex-row space-x-1 items-center {loading
+								? ' cursor-not-allowed'
+								: ''}"
+							type="submit"
+							disabled={loading}
+						>
+							{$i18n.t('Update')}
+
+							{#if loading}
+								<div class="ml-2 self-center">
+									<svg
+										class=" w-4 h-4"
+										viewBox="0 0 24 24"
+										fill="currentColor"
+										xmlns="http://www.w3.org/2000/svg"
+										><style>
+											.spinner_ajPY {
+												transform-origin: center;
+												animation: spinner_AtaB 0.75s infinite linear;
+											}
+											@keyframes spinner_AtaB {
+												100% {
+													transform: rotate(360deg);
+												}
+											}
+										</style><path
+											d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
+											opacity=".25"
+										/><path
+											d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
+											class="spinner_ajPY"
+										/></svg
+									>
+								</div>
+							{/if}
+						</button>
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+</Modal>

+ 46 - 3
src/lib/components/chat/Settings/Personalization/ManageModal.svelte

@@ -10,18 +10,24 @@
 	import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
 	import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import { error } from '@sveltejs/kit';
 	import { error } from '@sveltejs/kit';
+	import EditMemoryModal from './EditMemoryModal.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
 	export let show = false;
 	export let show = false;
 
 
 	let memories = [];
 	let memories = [];
+	let loading = true;
 
 
 	let showAddMemoryModal = false;
 	let showAddMemoryModal = false;
+	let showEditMemoryModal = false;
 
 
-	$: if (show) {
+	let selectedMemory = null;
+
+	$: if (show && memories.length === 0 && loading) {
 		(async () => {
 		(async () => {
 			memories = await getMemories(localStorage.token);
 			memories = await getMemories(localStorage.token);
+			loading = false;
 		})();
 		})();
 	}
 	}
 </script>
 </script>
@@ -62,7 +68,9 @@
 								>
 								>
 									<tr>
 									<tr>
 										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
 										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
-										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created At')} </th>
+										<th scope="col" class="px-3 py-2 hidden md:flex">
+											{$i18n.t('Last Modified')}
+										</th>
 										<th scope="col" class="px-3 py-2 text-right" />
 										<th scope="col" class="px-3 py-2 text-right" />
 									</tr>
 									</tr>
 								</thead>
 								</thead>
@@ -76,11 +84,38 @@
 											</td>
 											</td>
 											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
 											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
 												<div class="my-auto whitespace-nowrap">
 												<div class="my-auto whitespace-nowrap">
-													{dayjs(memory.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
+													{dayjs(memory.updated_at * 1000).format(
+														$i18n.t('MMMM DD, YYYY hh:mm:ss A')
+													)}
 												</div>
 												</div>
 											</td>
 											</td>
 											<td class="px-3 py-1">
 											<td class="px-3 py-1">
 												<div class="flex justify-end w-full">
 												<div class="flex justify-end w-full">
+													<Tooltip content="Edit">
+														<button
+															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
+															on:click={() => {
+																selectedMemory = memory;
+																showEditMemoryModal = true;
+															}}
+														>
+															<svg
+																xmlns="http://www.w3.org/2000/svg"
+																fill="none"
+																viewBox="0 0 24 24"
+																stroke-width="1.5"
+																stroke="currentColor"
+																class="w-4 h-4 s-FoVA_WMOgxUD"
+																><path
+																	stroke-linecap="round"
+																	stroke-linejoin="round"
+																	d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
+																	class="s-FoVA_WMOgxUD"
+																/></svg
+															>
+														</button>
+													</Tooltip>
+
 													<Tooltip content="Delete">
 													<Tooltip content="Delete">
 														<button
 														<button
 															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
@@ -163,3 +198,11 @@
 		memories = await getMemories(localStorage.token);
 		memories = await getMemories(localStorage.token);
 	}}
 	}}
 />
 />
+
+<EditMemoryModal
+	bind:show={showEditMemoryModal}
+	memory={selectedMemory}
+	on:save={async () => {
+		memories = await getMemories(localStorage.token);
+	}}
+/>

+ 5 - 2
src/lib/components/common/ConfirmDialog.svelte

@@ -9,6 +9,9 @@
 	export let title = 'Confirm your action';
 	export let title = 'Confirm your action';
 	export let message = 'This action cannot be undone. Do you wish to continue?';
 	export let message = 'This action cannot be undone. Do you wish to continue?';
 
 
+	export let cancelLabel = 'Cancel';
+	export let confirmLabel = 'Confirm';
+
 	export let show = false;
 	export let show = false;
 	let modalElement = null;
 	let modalElement = null;
 	let mounted = false;
 	let mounted = false;
@@ -70,7 +73,7 @@
 						}}
 						}}
 						type="button"
 						type="button"
 					>
 					>
-						Cancel
+						{cancelLabel}
 					</button>
 					</button>
 					<button
 					<button
 						class="bg-gray-900 hover:bg-gray-850 text-gray-100 dark:bg-gray-100 dark:hover:bg-white dark:text-gray-800 font-medium w-full py-2.5 rounded-lg transition"
 						class="bg-gray-900 hover:bg-gray-850 text-gray-100 dark:bg-gray-100 dark:hover:bg-white dark:text-gray-800 font-medium w-full py-2.5 rounded-lg transition"
@@ -80,7 +83,7 @@
 						}}
 						}}
 						type="button"
 						type="button"
 					>
 					>
-						Confirm
+						{confirmLabel}
 					</button>
 					</button>
 				</div>
 				</div>
 			</div>
 			</div>

+ 2 - 0
src/lib/components/common/Tooltip.svelte

@@ -1,5 +1,7 @@
 <script lang="ts">
 <script lang="ts">
 	import { onDestroy } from 'svelte';
 	import { onDestroy } from 'svelte';
+	import { marked } from 'marked';
+
 	import tippy from 'tippy.js';
 	import tippy from 'tippy.js';
 
 
 	export let placement = 'top';
 	export let placement = 'top';

+ 58 - 284
src/lib/components/layout/Sidebar.svelte

@@ -1,4 +1,5 @@
 <script lang="ts">
 <script lang="ts">
+	import { toast } from 'svelte-sonner';
 	import { goto } from '$app/navigation';
 	import { goto } from '$app/navigation';
 	import {
 	import {
 		user,
 		user,
@@ -11,10 +12,11 @@
 		mobile,
 		mobile,
 		showArchivedChats
 		showArchivedChats
 	} from '$lib/stores';
 	} from '$lib/stores';
-	import { onMount, getContext } from 'svelte';
+	import { onMount, getContext, tick } from 'svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
+	import { updateUserSettings } from '$lib/apis/users';
 	import {
 	import {
 		deleteChatById,
 		deleteChatById,
 		getChatList,
 		getChatList,
@@ -25,37 +27,25 @@
 		archiveChatById,
 		archiveChatById,
 		cloneChatById
 		cloneChatById
 	} from '$lib/apis/chats';
 	} from '$lib/apis/chats';
-	import { toast } from 'svelte-sonner';
-	import { fade, slide } from 'svelte/transition';
 	import { WEBUI_BASE_URL } from '$lib/constants';
 	import { WEBUI_BASE_URL } from '$lib/constants';
-	import Tooltip from '../common/Tooltip.svelte';
-	import ChatMenu from './Sidebar/ChatMenu.svelte';
-	import ShareChatModal from '../chat/ShareChatModal.svelte';
-	import ArchiveBox from '../icons/ArchiveBox.svelte';
+
 	import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
 	import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
 	import UserMenu from './Sidebar/UserMenu.svelte';
 	import UserMenu from './Sidebar/UserMenu.svelte';
-	import { updateUserSettings } from '$lib/apis/users';
+	import ChatItem from './Sidebar/ChatItem.svelte';
+	import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
 
 
 	const BREAKPOINT = 768;
 	const BREAKPOINT = 768;
 
 
-	let show = false;
 	let navElement;
 	let navElement;
-
-	let title: string = 'UI';
 	let search = '';
 	let search = '';
 
 
-	let shareChatId = null;
+	let shiftKey = false;
 
 
 	let selectedChatId = null;
 	let selectedChatId = null;
+	let deleteChat = null;
 
 
-	let chatDeleteId = null;
-	let chatTitleEditId = null;
-	let chatTitle = '';
-
-	let showShareChatModal = false;
+	let showDeleteConfirm = false;
 	let showDropdown = false;
 	let showDropdown = false;
-	let isEditing = false;
-
 	let filteredChatList = [];
 	let filteredChatList = [];
 
 
 	$: filteredChatList = $chats.filter((chat) => {
 	$: filteredChatList = $chats.filter((chat) => {
@@ -78,13 +68,6 @@
 		}
 		}
 	});
 	});
 
 
-	mobile;
-	const onResize = () => {
-		if ($showSidebar && window.innerWidth < BREAKPOINT) {
-			showSidebar.set(false);
-		}
-	};
-
 	onMount(async () => {
 	onMount(async () => {
 		mobile.subscribe((e) => {
 		mobile.subscribe((e) => {
 			if ($showSidebar && e) {
 			if ($showSidebar && e) {
@@ -125,10 +108,28 @@
 			checkDirection();
 			checkDirection();
 		};
 		};
 
 
+		const onKeyDown = (e) => {
+			if (e.key === 'Shift') {
+				shiftKey = true;
+			}
+		};
+
+		const onKeyUp = (e) => {
+			if (e.key === 'Shift') {
+				shiftKey = false;
+			}
+		};
+
+		document.addEventListener('keydown', onKeyDown);
+		document.addEventListener('keyup', onKeyUp);
+
 		window.addEventListener('touchstart', onTouchStart);
 		window.addEventListener('touchstart', onTouchStart);
 		window.addEventListener('touchend', onTouchEnd);
 		window.addEventListener('touchend', onTouchEnd);
 
 
 		return () => {
 		return () => {
+			window.removeEventListener('keydown', onKeyDown);
+			window.removeEventListener('keyup', onKeyUp);
+
 			window.removeEventListener('touchstart', onTouchStart);
 			window.removeEventListener('touchstart', onTouchStart);
 			window.removeEventListener('touchend', onTouchEnd);
 			window.removeEventListener('touchend', onTouchEnd);
 		};
 		};
@@ -149,69 +150,29 @@
 		await chats.set(enrichedChats);
 		await chats.set(enrichedChats);
 	};
 	};
 
 
-	const loadChat = async (id) => {
-		goto(`/c/${id}`);
-	};
-
-	const editChatTitle = async (id, _title) => {
-		if (_title === '') {
-			toast.error($i18n.t('Title cannot be an empty string.'));
-		} else {
-			title = _title;
-
-			await updateChatById(localStorage.token, id, {
-				title: _title
-			});
-			await chats.set(await getChatList(localStorage.token));
-		}
+	const saveSettings = async (updated) => {
+		await settings.set({ ...$settings, ...updated });
+		await updateUserSettings(localStorage.token, { ui: $settings });
+		location.href = '/';
 	};
 	};
 
 
-	const deleteChat = async (id) => {
+	const deleteChatHandler = async (id) => {
 		const res = await deleteChatById(localStorage.token, id).catch((error) => {
 		const res = await deleteChatById(localStorage.token, id).catch((error) => {
 			toast.error(error);
 			toast.error(error);
-			chatDeleteId = null;
-
 			return null;
 			return null;
 		});
 		});
 
 
 		if (res) {
 		if (res) {
 			if ($chatId === id) {
 			if ($chatId === id) {
+				await chatId.set('');
+				await tick();
 				goto('/');
 				goto('/');
 			}
 			}
-
 			await chats.set(await getChatList(localStorage.token));
 			await chats.set(await getChatList(localStorage.token));
 		}
 		}
 	};
 	};
-
-	const cloneChatHandler = async (id) => {
-		const res = await cloneChatById(localStorage.token, id).catch((error) => {
-			toast.error(error);
-			return null;
-		});
-
-		if (res) {
-			goto(`/c/${res.id}`);
-			await chats.set(await getChatList(localStorage.token));
-		}
-	};
-
-	const saveSettings = async (updated) => {
-		await settings.set({ ...$settings, ...updated });
-		await updateUserSettings(localStorage.token, { ui: $settings });
-		location.href = '/';
-	};
-
-	const archiveChatHandler = async (id) => {
-		await archiveChatById(localStorage.token, id);
-		await chats.set(await getChatList(localStorage.token));
-	};
-
-	const focusEdit = async (node: HTMLInputElement) => {
-		node.focus();
-	};
 </script>
 </script>
 
 
-<ShareChatModal bind:show={showShareChatModal} chatId={shareChatId} />
 <ArchivedChatsModal
 <ArchivedChatsModal
 	bind:show={$showArchivedChats}
 	bind:show={$showArchivedChats}
 	on:change={async () => {
 	on:change={async () => {
@@ -219,6 +180,18 @@
 	}}
 	}}
 />
 />
 
 
+<DeleteConfirmDialog
+	bind:show={showDeleteConfirm}
+	title="Delete chat?"
+	on:confirm={() => {
+		deleteChatHandler(deleteChat.id);
+	}}
+>
+	<div class=" text-sm text-gray-500">
+		This will delete <span class="  font-semibold">{deleteChat.title}</span>.
+	</div>
+</DeleteConfirmDialog>
+
 <!-- svelte-ignore a11y-no-static-element-interactions -->
 <!-- svelte-ignore a11y-no-static-element-interactions -->
 
 
 {#if $showSidebar}
 {#if $showSidebar}
@@ -252,12 +225,10 @@
 				draggable="false"
 				draggable="false"
 				on:click={async () => {
 				on:click={async () => {
 					selectedChatId = null;
 					selectedChatId = null;
-
 					await goto('/');
 					await goto('/');
 					const newChatButton = document.getElementById('new-chat-button');
 					const newChatButton = document.getElementById('new-chat-button');
 					setTimeout(() => {
 					setTimeout(() => {
 						newChatButton?.click();
 						newChatButton?.click();
-
 						if ($mobile) {
 						if ($mobile) {
 							showSidebar.set(false);
 							showSidebar.set(false);
 						}
 						}
@@ -486,215 +457,18 @@
 						</div>
 						</div>
 					{/if}
 					{/if}
 
 
-					<div class=" w-full pr-2 relative group">
-						{#if chatTitleEditId === chat.id}
-							<div
-								class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
-								chat.id === chatTitleEditId ||
-								chat.id === chatDeleteId
-									? 'bg-gray-200 dark:bg-gray-900'
-									: chat.id === selectedChatId
-									? 'bg-gray-100 dark:bg-gray-950'
-									: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'}  whitespace-nowrap text-ellipsis"
-							>
-								<input
-									use:focusEdit
-									bind:value={chatTitle}
-									class=" bg-transparent w-full outline-none mr-10"
-								/>
-							</div>
-						{:else}
-							<a
-								class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
-								chat.id === chatTitleEditId ||
-								chat.id === chatDeleteId
-									? 'bg-gray-200 dark:bg-gray-900'
-									: chat.id === selectedChatId
-									? 'bg-gray-100 dark:bg-gray-950'
-									: ' group-hover:bg-gray-100 dark:group-hover:bg-gray-950'}  whitespace-nowrap text-ellipsis"
-								href="/c/{chat.id}"
-								on:click={() => {
-									selectedChatId = chat.id;
-									if ($mobile) {
-										showSidebar.set(false);
-									}
-								}}
-								on:dblclick={() => {
-									chatTitle = chat.title;
-									chatTitleEditId = chat.id;
-								}}
-								draggable="false"
-							>
-								<div class=" flex self-center flex-1 w-full">
-									<div class=" text-left self-center overflow-hidden w-full h-[20px]">
-										{chat.title}
-									</div>
-								</div>
-							</a>
-						{/if}
-
-						<div
-							class="
-
-							{chat.id === $chatId || chat.id === chatTitleEditId || chat.id === chatDeleteId
-								? 'from-gray-200 dark:from-gray-900'
-								: chat.id === selectedChatId
-								? 'from-gray-100 dark:from-gray-950'
-								: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
-								absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
-
-								  to-transparent"
-						>
-							{#if chatTitleEditId === chat.id}
-								<div class="flex self-center space-x-1.5 z-10">
-									<button
-										class=" self-center dark:hover:text-white transition"
-										on:click={() => {
-											editChatTitle(chat.id, chatTitle);
-											chatTitleEditId = null;
-											chatTitle = '';
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											viewBox="0 0 20 20"
-											fill="currentColor"
-											class="w-4 h-4"
-										>
-											<path
-												fill-rule="evenodd"
-												d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
-												clip-rule="evenodd"
-											/>
-										</svg>
-									</button>
-									<button
-										class=" self-center dark:hover:text-white transition"
-										on:click={() => {
-											chatTitleEditId = null;
-											chatTitle = '';
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											viewBox="0 0 20 20"
-											fill="currentColor"
-											class="w-4 h-4"
-										>
-											<path
-												d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
-											/>
-										</svg>
-									</button>
-								</div>
-							{:else if chatDeleteId === chat.id}
-								<div class="flex self-center space-x-1.5 z-10">
-									<button
-										class=" self-center dark:hover:text-white transition"
-										on:click={() => {
-											deleteChat(chat.id);
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											viewBox="0 0 20 20"
-											fill="currentColor"
-											class="w-4 h-4"
-										>
-											<path
-												fill-rule="evenodd"
-												d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
-												clip-rule="evenodd"
-											/>
-										</svg>
-									</button>
-									<button
-										class=" self-center dark:hover:text-white transition"
-										on:click={() => {
-											chatDeleteId = null;
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											viewBox="0 0 20 20"
-											fill="currentColor"
-											class="w-4 h-4"
-										>
-											<path
-												d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
-											/>
-										</svg>
-									</button>
-								</div>
-							{:else}
-								<div class="flex self-center space-x-1 z-10">
-									<ChatMenu
-										chatId={chat.id}
-										cloneChatHandler={() => {
-											cloneChatHandler(chat.id);
-										}}
-										shareHandler={() => {
-											shareChatId = selectedChatId;
-											showShareChatModal = true;
-										}}
-										archiveChatHandler={() => {
-											archiveChatHandler(chat.id);
-										}}
-										renameHandler={() => {
-											chatTitle = chat.title;
-											chatTitleEditId = chat.id;
-										}}
-										deleteHandler={() => {
-											chatDeleteId = chat.id;
-										}}
-										onClose={() => {
-											selectedChatId = null;
-										}}
-									>
-										<button
-											aria-label="Chat Menu"
-											class=" self-center dark:hover:text-white transition"
-											on:click={() => {
-												selectedChatId = chat.id;
-											}}
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
-											>
-												<path
-													d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
-												/>
-											</svg>
-										</button>
-									</ChatMenu>
-
-									{#if chat.id === $chatId}
-										<button
-											id="delete-chat-button"
-											class="hidden"
-											on:click={() => {
-												chatDeleteId = chat.id;
-											}}
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
-											>
-												<path
-													d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
-												/>
-											</svg>
-										</button>
-									{/if}
-								</div>
-							{/if}
-						</div>
-					</div>
+					<ChatItem
+						{chat}
+						{shiftKey}
+						selected={selectedChatId === chat.id}
+						on:select={() => {
+							selectedChatId = chat.id;
+						}}
+						on:delete={() => {
+							deleteChat = chat;
+							showDeleteConfirm = true;
+						}}
+					/>
 				{/each}
 				{/each}
 			</div>
 			</div>
 		</div>
 		</div>

+ 281 - 0
src/lib/components/layout/Sidebar/ChatItem.svelte

@@ -0,0 +1,281 @@
+<script lang="ts">
+	import { toast } from 'svelte-sonner';
+	import { goto, invalidate, invalidateAll } from '$app/navigation';
+	import { onMount, getContext, createEventDispatcher, tick } from 'svelte';
+	const i18n = getContext('i18n');
+
+	const dispatch = createEventDispatcher();
+
+	import {
+		archiveChatById,
+		cloneChatById,
+		deleteChatById,
+		getChatList,
+		updateChatById
+	} from '$lib/apis/chats';
+	import { chatId, chats, mobile, showSidebar } from '$lib/stores';
+
+	import ChatMenu from './ChatMenu.svelte';
+	import ShareChatModal from '$lib/components/chat/ShareChatModal.svelte';
+	import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
+
+	export let chat;
+	export let selected = false;
+	export let shiftKey = false;
+
+	let mouseOver = false;
+
+	let showShareChatModal = false;
+	let confirmEdit = false;
+
+	let chatTitle = chat.title;
+
+	const editChatTitle = async (id, _title) => {
+		if (_title === '') {
+			toast.error($i18n.t('Title cannot be an empty string.'));
+		} else {
+			await updateChatById(localStorage.token, id, {
+				title: _title
+			});
+			await chats.set(await getChatList(localStorage.token));
+		}
+	};
+
+	const cloneChatHandler = async (id) => {
+		const res = await cloneChatById(localStorage.token, id).catch((error) => {
+			toast.error(error);
+			return null;
+		});
+
+		if (res) {
+			goto(`/c/${res.id}`);
+			await chats.set(await getChatList(localStorage.token));
+		}
+	};
+
+	const archiveChatHandler = async (id) => {
+		await archiveChatById(localStorage.token, id);
+		await chats.set(await getChatList(localStorage.token));
+	};
+
+	const focusEdit = async (node: HTMLInputElement) => {
+		node.focus();
+	};
+</script>
+
+<ShareChatModal bind:show={showShareChatModal} chatId={chat.id} />
+
+<div class=" w-full pr-2 relative group">
+	{#if confirmEdit}
+		<div
+			class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId || confirmEdit
+				? 'bg-gray-200 dark:bg-gray-900'
+				: selected
+				? 'bg-gray-100 dark:bg-gray-950'
+				: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'}  whitespace-nowrap text-ellipsis"
+		>
+			<input
+				use:focusEdit
+				bind:value={chatTitle}
+				class=" bg-transparent w-full outline-none mr-10"
+			/>
+		</div>
+	{:else}
+		<a
+			class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId || confirmEdit
+				? 'bg-gray-200 dark:bg-gray-900'
+				: selected
+				? 'bg-gray-100 dark:bg-gray-950'
+				: ' group-hover:bg-gray-100 dark:group-hover:bg-gray-950'}  whitespace-nowrap text-ellipsis"
+			href="/c/{chat.id}"
+			on:click={() => {
+				dispatch('select');
+
+				if ($mobile) {
+					showSidebar.set(false);
+				}
+			}}
+			on:dblclick={() => {
+				chatTitle = chat.title;
+				confirmEdit = true;
+			}}
+			on:mouseenter={(e) => {
+				mouseOver = true;
+			}}
+			on:mouseleave={(e) => {
+				mouseOver = false;
+			}}
+			on:focus={(e) => {}}
+			draggable="false"
+		>
+			<div class=" flex self-center flex-1 w-full">
+				<div class=" text-left self-center overflow-hidden w-full h-[20px]">
+					{chat.title}
+				</div>
+			</div>
+		</a>
+	{/if}
+
+	<!-- svelte-ignore a11y-no-static-element-interactions -->
+	<div
+		class="
+        {chat.id === $chatId || confirmEdit
+			? 'from-gray-200 dark:from-gray-900'
+			: selected
+			? 'from-gray-100 dark:from-gray-950'
+			: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
+            absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
+
+              to-transparent"
+		on:mouseenter={(e) => {
+			mouseOver = true;
+		}}
+		on:mouseleave={(e) => {
+			mouseOver = false;
+		}}
+	>
+		{#if confirmEdit}
+			<div class="flex self-center space-x-1.5 z-10">
+				<Tooltip content="Confirm">
+					<button
+						class=" self-center dark:hover:text-white transition"
+						on:click={() => {
+							editChatTitle(chat.id, chatTitle);
+							confirmEdit = false;
+							chatTitle = '';
+						}}
+					>
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 20 20"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								fill-rule="evenodd"
+								d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+					</button>
+				</Tooltip>
+
+				<Tooltip content="Cancel">
+					<button
+						class=" self-center dark:hover:text-white transition"
+						on:click={() => {
+							confirmEdit = false;
+							chatTitle = '';
+						}}
+					>
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 20 20"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+							/>
+						</svg>
+					</button>
+				</Tooltip>
+			</div>
+		{:else if shiftKey && mouseOver}
+			<div class=" flex items-center self-center space-x-1.5">
+				<Tooltip content="Archive" className="flex items-center">
+					<button
+						class=" self-center dark:hover:text-white transition"
+						on:click={() => {
+							archiveChatHandler(chat.id);
+						}}
+						type="button"
+					>
+						<ArchiveBox className="size-4  translate-y-[0.5px]" strokeWidth="2" />
+					</button>
+				</Tooltip>
+
+				<Tooltip content="Delete">
+					<button
+						class=" self-center dark:hover:text-white transition"
+						on:click={() => {
+							deleteChat(chat.id);
+						}}
+						type="button"
+					>
+						<GarbageBin strokeWidth="2" />
+					</button>
+				</Tooltip>
+			</div>
+		{:else}
+			<div class="flex self-center space-x-1 z-10">
+				<ChatMenu
+					chatId={chat.id}
+					cloneChatHandler={() => {
+						cloneChatHandler(chat.id);
+					}}
+					shareHandler={() => {
+						showShareChatModal = true;
+					}}
+					archiveChatHandler={() => {
+						archiveChatHandler(chat.id);
+					}}
+					renameHandler={() => {
+						chatTitle = chat.title;
+
+						confirmEdit = true;
+					}}
+					deleteHandler={() => {
+						dispatch('delete');
+					}}
+					onClose={() => {
+						selected = false;
+					}}
+				>
+					<button
+						aria-label="Chat Menu"
+						class=" self-center dark:hover:text-white transition"
+						on:click={() => {
+							dispatch('select');
+						}}
+					>
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
+							/>
+						</svg>
+					</button>
+				</ChatMenu>
+
+				{#if chat.id === $chatId}
+					<!-- Shortcut support using "delete-chat-button" id -->
+					<button
+						id="delete-chat-button"
+						class="hidden"
+						on:click={() => {
+							dispatch('delete');
+						}}
+					>
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
+							/>
+						</svg>
+					</button>
+				{/if}
+			</div>
+		{/if}
+	</div>
+</div>

+ 13 - 1
src/lib/components/workspace/Models.svelte

@@ -17,15 +17,19 @@
 
 
 	import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
 	import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
 	import ModelMenu from './Models/ModelMenu.svelte';
 	import ModelMenu from './Models/ModelMenu.svelte';
+	import ModelDeleteConfirmDialog from '../common/ConfirmDialog.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
+	let showModelDeleteConfirm = false;
+
 	let localModelfiles = [];
 	let localModelfiles = [];
 
 
 	let importFiles;
 	let importFiles;
 	let modelsImportInputElement: HTMLInputElement;
 	let modelsImportInputElement: HTMLInputElement;
 
 
 	let _models = [];
 	let _models = [];
+	let selectedModel = null;
 
 
 	let sortable = null;
 	let sortable = null;
 	let searchValue = '';
 	let searchValue = '';
@@ -199,6 +203,13 @@
 	</title>
 	</title>
 </svelte:head>
 </svelte:head>
 
 
+<ModelDeleteConfirmDialog
+	bind:show={showModelDeleteConfirm}
+	on:confirm={() => {
+		deleteModelHandler(selectedModel);
+	}}
+/>
+
 <div class=" text-lg font-semibold mb-3">{$i18n.t('Models')}</div>
 <div class=" text-lg font-semibold mb-3">{$i18n.t('Models')}</div>
 
 
 <div class=" flex w-full space-x-2">
 <div class=" flex w-full space-x-2">
@@ -339,7 +350,8 @@
 						hideModelHandler(model);
 						hideModelHandler(model);
 					}}
 					}}
 					deleteHandler={() => {
 					deleteHandler={() => {
-						deleteModelHandler(model);
+						selectedModel = model;
+						showModelDeleteConfirm = true;
 					}}
 					}}
 					onClose={() => {}}
 					onClose={() => {}}
 				>
 				>

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

@@ -69,6 +69,7 @@
 	"Bad Response": "استجابة خطاء",
 	"Bad Response": "استجابة خطاء",
 	"Banners": "لافتات",
 	"Banners": "لافتات",
 	"Base Model (From)": "النموذج الأساسي (من)",
 	"Base Model (From)": "النموذج الأساسي (من)",
+	"Batch Size (num_batch)": "",
 	"before": "قبل",
 	"before": "قبل",
 	"Being lazy": "كون كسول",
 	"Being lazy": "كون كسول",
 	"Brave Search API Key": "مفتاح واجهة برمجة تطبيقات البحث الشجاع",
 	"Brave Search API Key": "مفتاح واجهة برمجة تطبيقات البحث الشجاع",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "اكتشاف وتنزيل واستكشاف المطالبات المخصصة",
 	"Discover, download, and explore custom prompts": "اكتشاف وتنزيل واستكشاف المطالبات المخصصة",
 	"Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج",
 	"Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة",
 	"Display the username instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة",
 	"Document": "المستند",
 	"Document": "المستند",
 	"Document Settings": "أعدادات المستند",
 	"Document Settings": "أعدادات المستند",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serpstack",
 	"Enter Serpstack API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serpstack",
 	"Enter stop sequence": "أدخل تسلسل التوقف",
 	"Enter stop sequence": "أدخل تسلسل التوقف",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "أدخل Top K",
 	"Enter Top K": "أدخل Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "الرابط (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "الرابط (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL (e.g. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "URL (e.g. http://localhost:11434)",
@@ -492,6 +495,7 @@
 	"System": "النظام",
 	"System": "النظام",
 	"System Prompt": "محادثة النظام",
 	"System Prompt": "محادثة النظام",
 	"Tags": "الوسوم",
 	"Tags": "الوسوم",
+	"Tavily API Key": "",
 	"Tell us more:": "أخبرنا المزيد:",
 	"Tell us more:": "أخبرنا المزيد:",
 	"Temperature": "درجة حرارة",
 	"Temperature": "درجة حرارة",
 	"Template": "نموذج",
 	"Template": "نموذج",
@@ -522,6 +526,7 @@
 	"Today": "اليوم",
 	"Today": "اليوم",
 	"Toggle settings": "فتح وأغلاق الاعدادات",
 	"Toggle settings": "فتح وأغلاق الاعدادات",
 	"Toggle sidebar": "فتح وأغلاق الشريط الجانبي",
 	"Toggle sidebar": "فتح وأغلاق الشريط الجانبي",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Невалиден отговор от API",
 	"Bad Response": "Невалиден отговор от API",
 	"Banners": "Банери",
 	"Banners": "Банери",
 	"Base Model (From)": "Базов модел (от)",
 	"Base Model (From)": "Базов модел (от)",
+	"Batch Size (num_batch)": "",
 	"before": "преди",
 	"before": "преди",
 	"Being lazy": "Да бъдеш мързелив",
 	"Being lazy": "Да бъдеш мързелив",
 	"Brave Search API Key": "Смел ключ за API за търсене",
 	"Brave Search API Key": "Смел ключ за API за търсене",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Откриване, сваляне и преглед на персонализирани промптове",
 	"Discover, download, and explore custom prompts": "Откриване, сваляне и преглед на персонализирани промптове",
 	"Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели",
 	"Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Показване на потребителското име вместо Вие в чата",
 	"Display the username instead of You in the Chat": "Показване на потребителското име вместо Вие в чата",
 	"Document": "Документ",
 	"Document": "Документ",
 	"Document Settings": "Документ Настройки",
 	"Document Settings": "Документ Настройки",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Въведете Serpstack API ключ",
 	"Enter Serpstack API Key": "Въведете Serpstack API ключ",
 	"Enter stop sequence": "Въведете стоп последователност",
 	"Enter stop sequence": "Въведете стоп последователност",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Въведете Top K",
 	"Enter Top K": "Въведете Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Въведете URL (напр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Въведете URL (напр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Въведете URL (напр. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Въведете URL (напр. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "Система",
 	"System": "Система",
 	"System Prompt": "Системен Промпт",
 	"System Prompt": "Системен Промпт",
 	"Tags": "Тагове",
 	"Tags": "Тагове",
+	"Tavily API Key": "",
 	"Tell us more:": "Повече информация:",
 	"Tell us more:": "Повече информация:",
 	"Temperature": "Температура",
 	"Temperature": "Температура",
 	"Template": "Шаблон",
 	"Template": "Шаблон",
@@ -518,6 +522,7 @@
 	"Today": "днес",
 	"Today": "днес",
 	"Toggle settings": "Toggle settings",
 	"Toggle settings": "Toggle settings",
 	"Toggle sidebar": "Toggle sidebar",
 	"Toggle sidebar": "Toggle sidebar",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "খারাপ প্রতিক্রিয়া",
 	"Bad Response": "খারাপ প্রতিক্রিয়া",
 	"Banners": "ব্যানার",
 	"Banners": "ব্যানার",
 	"Base Model (From)": "বেস মডেল (থেকে)",
 	"Base Model (From)": "বেস মডেল (থেকে)",
+	"Batch Size (num_batch)": "",
 	"before": "পূর্ববর্তী",
 	"before": "পূর্ববর্তী",
 	"Being lazy": "অলস হওয়া",
 	"Being lazy": "অলস হওয়া",
 	"Brave Search API Key": "সাহসী অনুসন্ধান API কী",
 	"Brave Search API Key": "সাহসী অনুসন্ধান API কী",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "কাস্টম প্রম্পটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
 	"Discover, download, and explore custom prompts": "কাস্টম প্রম্পটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
 	"Discover, download, and explore model presets": "মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
 	"Discover, download, and explore model presets": "মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান",
 	"Display the username instead of You in the Chat": "চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান",
 	"Document": "ডকুমেন্ট",
 	"Document": "ডকুমেন্ট",
 	"Document Settings": "ডকুমেন্ট সেটিংসমূহ",
 	"Document Settings": "ডকুমেন্ট সেটিংসমূহ",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Serpstack API কী লিখুন",
 	"Enter Serpstack API Key": "Serpstack API কী লিখুন",
 	"Enter stop sequence": "স্টপ সিকোয়েন্স লিখুন",
 	"Enter stop sequence": "স্টপ সিকোয়েন্স লিখুন",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Top K লিখুন",
 	"Enter Top K": "Top K লিখুন",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "ইউআরএল দিন (যেমন http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "ইউআরএল দিন (যেমন http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "ইউআরএল দিন (যেমন http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "ইউআরএল দিন (যেমন http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "সিস্টেম",
 	"System": "সিস্টেম",
 	"System Prompt": "সিস্টেম প্রম্পট",
 	"System Prompt": "সিস্টেম প্রম্পট",
 	"Tags": "ট্যাগসমূহ",
 	"Tags": "ট্যাগসমূহ",
+	"Tavily API Key": "",
 	"Tell us more:": "আরও বলুন:",
 	"Tell us more:": "আরও বলুন:",
 	"Temperature": "তাপমাত্রা",
 	"Temperature": "তাপমাত্রা",
 	"Template": "টেম্পলেট",
 	"Template": "টেম্পলেট",
@@ -518,6 +522,7 @@
 	"Today": "আজ",
 	"Today": "আজ",
 	"Toggle settings": "সেটিংস টোগল",
 	"Toggle settings": "সেটিংস টোগল",
 	"Toggle sidebar": "সাইডবার টোগল",
 	"Toggle sidebar": "সাইডবার টোগল",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Resposta Erroni",
 	"Bad Response": "Resposta Erroni",
 	"Banners": "Banners",
 	"Banners": "Banners",
 	"Base Model (From)": "Model base (des de)",
 	"Base Model (From)": "Model base (des de)",
+	"Batch Size (num_batch)": "",
 	"before": "abans",
 	"before": "abans",
 	"Being lazy": "Ser l'estupidez",
 	"Being lazy": "Ser l'estupidez",
 	"Brave Search API Key": "Clau API Brave Search",
 	"Brave Search API Key": "Clau API Brave Search",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Descobreix, descarrega i explora prompts personalitzats",
 	"Discover, download, and explore custom prompts": "Descobreix, descarrega i explora prompts personalitzats",
 	"Discover, download, and explore model presets": "Descobreix, descarrega i explora presets de models",
 	"Discover, download, and explore model presets": "Descobreix, descarrega i explora presets de models",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Mostra el nom d'usuari en lloc de 'Tu' al Xat",
 	"Display the username instead of You in the Chat": "Mostra el nom d'usuari en lloc de 'Tu' al Xat",
 	"Document": "Document",
 	"Document": "Document",
 	"Document Settings": "Configuració de Documents",
 	"Document Settings": "Configuració de Documents",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Introduïu la clau de l'API Serpstack",
 	"Enter Serpstack API Key": "Introduïu la clau de l'API Serpstack",
 	"Enter stop sequence": "Introdueix la seqüència de parada",
 	"Enter stop sequence": "Introdueix la seqüència de parada",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Introdueix Top K",
 	"Enter Top K": "Introdueix Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt del Sistema",
 	"System Prompt": "Prompt del Sistema",
 	"Tags": "Etiquetes",
 	"Tags": "Etiquetes",
+	"Tavily API Key": "",
 	"Tell us more:": "Dóna'ns més informació:",
 	"Tell us more:": "Dóna'ns més informació:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Plantilla",
 	"Template": "Plantilla",
@@ -519,6 +523,7 @@
 	"Today": "Avui",
 	"Today": "Avui",
 	"Toggle settings": "Commuta configuracions",
 	"Toggle settings": "Commuta configuracions",
 	"Toggle sidebar": "Commuta barra lateral",
 	"Toggle sidebar": "Commuta barra lateral",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "",
 	"Bad Response": "",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "",
 	"before": "",
 	"Being lazy": "",
 	"Being lazy": "",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Pagdiskubre, pag-download ug pagsuhid sa mga naandan nga pag-aghat",
 	"Discover, download, and explore custom prompts": "Pagdiskubre, pag-download ug pagsuhid sa mga naandan nga pag-aghat",
 	"Discover, download, and explore model presets": "Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template",
 	"Discover, download, and explore model presets": "Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan",
 	"Display the username instead of You in the Chat": "Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan",
 	"Document": "Dokumento",
 	"Document": "Dokumento",
 	"Document Settings": "Mga Setting sa Dokumento",
 	"Document Settings": "Mga Setting sa Dokumento",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Pagsulod sa katapusan nga han-ay",
 	"Enter stop sequence": "Pagsulod sa katapusan nga han-ay",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Pagsulod sa Top K",
 	"Enter Top K": "Pagsulod sa Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Pagsulod sa URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Pagsulod sa URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -488,6 +491,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Madasig nga Sistema",
 	"System Prompt": "Madasig nga Sistema",
 	"Tags": "Mga tag",
 	"Tags": "Mga tag",
+	"Tavily API Key": "",
 	"Tell us more:": "",
 	"Tell us more:": "",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Modelo",
 	"Template": "Modelo",
@@ -518,6 +522,7 @@
 	"Today": "",
 	"Today": "",
 	"Toggle settings": "I-toggle ang mga setting",
 	"Toggle settings": "I-toggle ang mga setting",
 	"Toggle sidebar": "I-toggle ang sidebar",
 	"Toggle sidebar": "I-toggle ang sidebar",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Ibabaw nga P",
 	"Top P": "Ibabaw nga P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Schlechte Antwort",
 	"Bad Response": "Schlechte Antwort",
 	"Banners": "Banner",
 	"Banners": "Banner",
 	"Base Model (From)": "Basismodell (von)",
 	"Base Model (From)": "Basismodell (von)",
+	"Batch Size (num_batch)": "",
 	"before": "bereits geteilt",
 	"before": "bereits geteilt",
 	"Being lazy": "Faul sein",
 	"Being lazy": "Faul sein",
 	"Brave Search API Key": "API-Schlüssel für die Brave-Suche",
 	"Brave Search API Key": "API-Schlüssel für die Brave-Suche",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden",
 	"Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden",
 	"Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden",
 	"Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden",
 	"Dismissible": "ausblendbar",
 	"Dismissible": "ausblendbar",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Den Benutzernamen anstelle von 'du' im Chat anzeigen",
 	"Display the username instead of You in the Chat": "Den Benutzernamen anstelle von 'du' im Chat anzeigen",
 	"Document": "Dokument",
 	"Document": "Dokument",
 	"Document Settings": "Dokumenteinstellungen",
 	"Document Settings": "Dokumenteinstellungen",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Geben Sie den Serpstack-API-Schlüssel ein",
 	"Enter Serpstack API Key": "Geben Sie den Serpstack-API-Schlüssel ein",
 	"Enter stop sequence": "Stop-Sequenz eingeben",
 	"Enter stop sequence": "Stop-Sequenz eingeben",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Gib Top K ein",
 	"Enter Top K": "Gib Top K ein",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Gib die URL ein (z.B. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Gib die URL ein (z.B. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Gib die URL ein (z.B. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Gib die URL ein (z.B. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "System",
 	"System": "System",
 	"System Prompt": "System-Prompt",
 	"System Prompt": "System-Prompt",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "Erzähl uns mehr",
 	"Tell us more:": "Erzähl uns mehr",
 	"Temperature": "Temperatur",
 	"Temperature": "Temperatur",
 	"Template": "Vorlage",
 	"Template": "Vorlage",
@@ -518,6 +522,7 @@
 	"Today": "Heute",
 	"Today": "Heute",
 	"Toggle settings": "Einstellungen umschalten",
 	"Toggle settings": "Einstellungen umschalten",
 	"Toggle sidebar": "Seitenleiste umschalten",
 	"Toggle sidebar": "Seitenleiste umschalten",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "",
 	"Bad Response": "",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "",
 	"before": "",
 	"Being lazy": "",
 	"Being lazy": "",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Discover, download, and explore custom prompts",
 	"Discover, download, and explore custom prompts": "Discover, download, and explore custom prompts",
 	"Discover, download, and explore model presets": "Discover, download, and explore model presets",
 	"Discover, download, and explore model presets": "Discover, download, and explore model presets",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Display username instead of You in Chat",
 	"Display the username instead of You in the Chat": "Display username instead of You in Chat",
 	"Document": "Document",
 	"Document": "Document",
 	"Document Settings": "Document Settings",
 	"Document Settings": "Document Settings",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Enter stop bark",
 	"Enter stop sequence": "Enter stop bark",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Enter Top Wow",
 	"Enter Top K": "Enter Top Wow",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Enter URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Enter URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -488,6 +491,7 @@
 	"System": "System very system",
 	"System": "System very system",
 	"System Prompt": "System Prompt much prompt",
 	"System Prompt": "System Prompt much prompt",
 	"Tags": "Tags very tags",
 	"Tags": "Tags very tags",
+	"Tavily API Key": "",
 	"Tell us more:": "",
 	"Tell us more:": "",
 	"Temperature": "Temperature very temp",
 	"Temperature": "Temperature very temp",
 	"Template": "Template much template",
 	"Template": "Template much template",
@@ -518,6 +522,7 @@
 	"Today": "",
 	"Today": "",
 	"Toggle settings": "Toggle settings much toggle",
 	"Toggle settings": "Toggle settings much toggle",
 	"Toggle sidebar": "Toggle sidebar much toggle",
 	"Toggle sidebar": "Toggle sidebar much toggle",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K very top",
 	"Top K": "Top K very top",
 	"Top P": "Top P very top",
 	"Top P": "Top P very top",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "",
 	"Bad Response": "",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "",
 	"before": "",
 	"Being lazy": "",
 	"Being lazy": "",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore model presets": "",
 	"Discover, download, and explore model presets": "",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "",
 	"Display the username instead of You in the Chat": "",
 	"Document": "",
 	"Document": "",
 	"Document Settings": "",
 	"Document Settings": "",
@@ -176,6 +178,7 @@
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "",
 	"Edit": "",
 	"Edit": "",
 	"Edit Doc": "",
 	"Edit Doc": "",
+	"Edit Memory": "",
 	"Edit User": "",
 	"Edit User": "",
 	"Email": "",
 	"Email": "",
 	"Embedding Batch Size": "",
 	"Embedding Batch Size": "",
@@ -205,6 +208,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter stop sequence": "",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -280,6 +284,7 @@
 	"Knowledge": "",
 	"Knowledge": "",
 	"Language": "",
 	"Language": "",
 	"Last Active": "",
 	"Last Active": "",
+	"Last Modified": "",
 	"Light": "",
 	"Light": "",
 	"Listening...": "",
 	"Listening...": "",
 	"LLMs can make mistakes. Verify important information.": "",
 	"LLMs can make mistakes. Verify important information.": "",
@@ -488,6 +493,7 @@
 	"System": "",
 	"System": "",
 	"System Prompt": "",
 	"System Prompt": "",
 	"Tags": "",
 	"Tags": "",
+	"Tavily API Key": "",
 	"Tell us more:": "",
 	"Tell us more:": "",
 	"Temperature": "",
 	"Temperature": "",
 	"Template": "",
 	"Template": "",
@@ -518,6 +524,7 @@
 	"Today": "",
 	"Today": "",
 	"Toggle settings": "",
 	"Toggle settings": "",
 	"Toggle sidebar": "",
 	"Toggle sidebar": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "",
 	"Top K": "",
 	"Top P": "",
 	"Top P": "",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "",
 	"Bad Response": "",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "",
 	"before": "",
 	"Being lazy": "",
 	"Being lazy": "",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore model presets": "",
 	"Discover, download, and explore model presets": "",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "",
 	"Display the username instead of You in the Chat": "",
 	"Document": "",
 	"Document": "",
 	"Document Settings": "",
 	"Document Settings": "",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter stop sequence": "",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -488,6 +491,7 @@
 	"System": "",
 	"System": "",
 	"System Prompt": "",
 	"System Prompt": "",
 	"Tags": "",
 	"Tags": "",
+	"Tavily API Key": "",
 	"Tell us more:": "",
 	"Tell us more:": "",
 	"Temperature": "",
 	"Temperature": "",
 	"Template": "",
 	"Template": "",
@@ -518,6 +522,7 @@
 	"Today": "",
 	"Today": "",
 	"Toggle settings": "",
 	"Toggle settings": "",
 	"Toggle sidebar": "",
 	"Toggle sidebar": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "",
 	"Top K": "",
 	"Top P": "",
 	"Top P": "",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Respuesta incorrecta",
 	"Bad Response": "Respuesta incorrecta",
 	"Banners": "Banners",
 	"Banners": "Banners",
 	"Base Model (From)": "Modelo base (desde)",
 	"Base Model (From)": "Modelo base (desde)",
+	"Batch Size (num_batch)": "",
 	"before": "antes",
 	"before": "antes",
 	"Being lazy": "Ser perezoso",
 	"Being lazy": "Ser perezoso",
 	"Brave Search API Key": "Clave de API de Brave Search",
 	"Brave Search API Key": "Clave de API de Brave Search",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
 	"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
 	"Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos",
 	"Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
 	"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
 	"Document": "Documento",
 	"Document": "Documento",
 	"Document Settings": "Configuración del Documento",
 	"Document Settings": "Configuración del Documento",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Ingrese la clave API de Serpstack",
 	"Enter Serpstack API Key": "Ingrese la clave API de Serpstack",
 	"Enter stop sequence": "Ingrese la secuencia de parada",
 	"Enter stop sequence": "Ingrese la secuencia de parada",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Ingrese el Top K",
 	"Enter Top K": "Ingrese el Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ingrese la URL (p.ej., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ingrese la URL (p.ej., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Ingrese la URL (p.ej., http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Ingrese la URL (p.ej., http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt del sistema",
 	"System Prompt": "Prompt del sistema",
 	"Tags": "Etiquetas",
 	"Tags": "Etiquetas",
+	"Tavily API Key": "",
 	"Tell us more:": "Dinos más:",
 	"Tell us more:": "Dinos más:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Plantilla",
 	"Template": "Plantilla",
@@ -519,6 +523,7 @@
 	"Today": "Hoy",
 	"Today": "Hoy",
 	"Toggle settings": "Alternar configuración",
 	"Toggle settings": "Alternar configuración",
 	"Toggle sidebar": "Alternar barra lateral",
 	"Toggle sidebar": "Alternar barra lateral",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "پاسخ خوب نیست",
 	"Bad Response": "پاسخ خوب نیست",
 	"Banners": "بنر",
 	"Banners": "بنر",
 	"Base Model (From)": "مدل پایه (از)",
 	"Base Model (From)": "مدل پایه (از)",
+	"Batch Size (num_batch)": "",
 	"before": "قبل",
 	"before": "قبل",
 	"Being lazy": "حالت سازنده",
 	"Being lazy": "حالت سازنده",
 	"Brave Search API Key": "کلید API جستجوی شجاع",
 	"Brave Search API Key": "کلید API جستجوی شجاع",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "پرامپت\u200cهای سفارشی را کشف، دانلود و کاوش کنید",
 	"Discover, download, and explore custom prompts": "پرامپت\u200cهای سفارشی را کشف، دانلود و کاوش کنید",
 	"Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید",
 	"Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت",
 	"Display the username instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت",
 	"Document": "سند",
 	"Document": "سند",
 	"Document Settings": "تنظیمات سند",
 	"Document Settings": "تنظیمات سند",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "کلید API Serpstack را وارد کنید",
 	"Enter Serpstack API Key": "کلید API Serpstack را وارد کنید",
 	"Enter stop sequence": "توالی توقف را وارد کنید",
 	"Enter stop sequence": "توالی توقف را وارد کنید",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "مقدار Top K را وارد کنید",
 	"Enter Top K": "مقدار Top K را وارد کنید",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "مقدار URL را وارد کنید (مثال http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "مقدار URL را وارد کنید (مثال http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "مقدار URL را وارد کنید (مثال http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "مقدار URL را وارد کنید (مثال http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "سیستم",
 	"System": "سیستم",
 	"System Prompt": "پرامپت سیستم",
 	"System Prompt": "پرامپت سیستم",
 	"Tags": "تگ\u200cها",
 	"Tags": "تگ\u200cها",
+	"Tavily API Key": "",
 	"Tell us more:": "بیشتر بگویید:",
 	"Tell us more:": "بیشتر بگویید:",
 	"Temperature": "دما",
 	"Temperature": "دما",
 	"Template": "الگو",
 	"Template": "الگو",
@@ -518,6 +522,7 @@
 	"Today": "امروز",
 	"Today": "امروز",
 	"Toggle settings": "نمایش/عدم نمایش تنظیمات",
 	"Toggle settings": "نمایش/عدم نمایش تنظیمات",
 	"Toggle sidebar": "نمایش/عدم نمایش نوار کناری",
 	"Toggle sidebar": "نمایش/عدم نمایش نوار کناری",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Epäkelpo vastaus",
 	"Bad Response": "Epäkelpo vastaus",
 	"Banners": "Bannerit",
 	"Banners": "Bannerit",
 	"Base Model (From)": "Perusmalli (alkaen)",
 	"Base Model (From)": "Perusmalli (alkaen)",
+	"Batch Size (num_batch)": "",
 	"before": "ennen",
 	"before": "ennen",
 	"Being lazy": "Oli laiska",
 	"Being lazy": "Oli laiska",
 	"Brave Search API Key": "Brave Search API -avain",
 	"Brave Search API Key": "Brave Search API -avain",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Löydä ja lataa mukautettuja kehotteita",
 	"Discover, download, and explore custom prompts": "Löydä ja lataa mukautettuja kehotteita",
 	"Discover, download, and explore model presets": "Löydä ja lataa mallien esiasetuksia",
 	"Discover, download, and explore model presets": "Löydä ja lataa mallien esiasetuksia",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Näytä käyttäjänimi keskustelussa",
 	"Display the username instead of You in the Chat": "Näytä käyttäjänimi keskustelussa",
 	"Document": "Asiakirja",
 	"Document": "Asiakirja",
 	"Document Settings": "Asiakirja-asetukset",
 	"Document Settings": "Asiakirja-asetukset",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Anna Serpstack API -avain",
 	"Enter Serpstack API Key": "Anna Serpstack API -avain",
 	"Enter stop sequence": "Syötä lopetussekvenssi",
 	"Enter stop sequence": "Syötä lopetussekvenssi",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Syötä Top K",
 	"Enter Top K": "Syötä Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Syötä URL (esim. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Syötä URL (esim. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Syötä URL (esim. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Syötä URL (esim. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "Järjestelmä",
 	"System": "Järjestelmä",
 	"System Prompt": "Järjestelmäkehote",
 	"System Prompt": "Järjestelmäkehote",
 	"Tags": "Tagit",
 	"Tags": "Tagit",
+	"Tavily API Key": "",
 	"Tell us more:": "Kerro lisää:",
 	"Tell us more:": "Kerro lisää:",
 	"Temperature": "Lämpötila",
 	"Temperature": "Lämpötila",
 	"Template": "Malline",
 	"Template": "Malline",
@@ -518,6 +522,7 @@
 	"Today": "Tänään",
 	"Today": "Tänään",
 	"Toggle settings": "Kytke asetukset",
 	"Toggle settings": "Kytke asetukset",
 	"Toggle sidebar": "Kytke sivupalkki",
 	"Toggle sidebar": "Kytke sivupalkki",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Mauvaise réponse",
 	"Bad Response": "Mauvaise réponse",
 	"Banners": "Bannières",
 	"Banners": "Bannières",
 	"Base Model (From)": "Modèle de base (à partir de)",
 	"Base Model (From)": "Modèle de base (à partir de)",
+	"Batch Size (num_batch)": "",
 	"before": "avant",
 	"before": "avant",
 	"Being lazy": "En manque de temps",
 	"Being lazy": "En manque de temps",
 	"Brave Search API Key": "Clé d’API de recherche brave",
 	"Brave Search API Key": "Clé d’API de recherche brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
 	"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
 	"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
 	"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans la Discussion",
 	"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans la Discussion",
 	"Document": "Document",
 	"Document": "Document",
 	"Document Settings": "Paramètres du document",
 	"Document Settings": "Paramètres du document",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Entrez dans la clé API Serpstack",
 	"Enter Serpstack API Key": "Entrez dans la clé API Serpstack",
 	"Enter stop sequence": "Entrez la séquence de fin",
 	"Enter stop sequence": "Entrez la séquence de fin",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Entrez Top K",
 	"Enter Top K": "Entrez Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Entrez l'URL (p. ex. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Entrez l'URL (p. ex. http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Système",
 	"System": "Système",
 	"System Prompt": "Prompt Système",
 	"System Prompt": "Prompt Système",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "Donnez-nous plus:",
 	"Tell us more:": "Donnez-nous plus:",
 	"Temperature": "Température",
 	"Temperature": "Température",
 	"Template": "Modèle",
 	"Template": "Modèle",
@@ -519,6 +523,7 @@
 	"Today": "Aujourd'hui",
 	"Today": "Aujourd'hui",
 	"Toggle settings": "Basculer les paramètres",
 	"Toggle settings": "Basculer les paramètres",
 	"Toggle sidebar": "Basculer la barre latérale",
 	"Toggle sidebar": "Basculer la barre latérale",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Mauvaise Réponse",
 	"Bad Response": "Mauvaise Réponse",
 	"Banners": "Bannières",
 	"Banners": "Bannières",
 	"Base Model (From)": "Modèle de Base (De)",
 	"Base Model (From)": "Modèle de Base (De)",
+	"Batch Size (num_batch)": "",
 	"before": "avant",
 	"before": "avant",
 	"Being lazy": "Est paresseux",
 	"Being lazy": "Est paresseux",
 	"Brave Search API Key": "Clé API Brave Search",
 	"Brave Search API Key": "Clé API Brave Search",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
 	"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
 	"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
 	"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans le Chat",
 	"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans le Chat",
 	"Document": "Document",
 	"Document": "Document",
 	"Document Settings": "Paramètres du document",
 	"Document Settings": "Paramètres du document",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Entrez la clé API Serpstack",
 	"Enter Serpstack API Key": "Entrez la clé API Serpstack",
 	"Enter stop sequence": "Entrez la séquence de fin",
 	"Enter stop sequence": "Entrez la séquence de fin",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Entrez Top K",
 	"Enter Top K": "Entrez Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Entrez l'URL (p. ex. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Entrez l'URL (p. ex. http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Système",
 	"System": "Système",
 	"System Prompt": "Prompt du Système",
 	"System Prompt": "Prompt du Système",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "Dites-nous en plus :",
 	"Tell us more:": "Dites-nous en plus :",
 	"Temperature": "Température",
 	"Temperature": "Température",
 	"Template": "Modèle",
 	"Template": "Modèle",
@@ -519,6 +523,7 @@
 	"Today": "Aujourd'hui",
 	"Today": "Aujourd'hui",
 	"Toggle settings": "Basculer les paramètres",
 	"Toggle settings": "Basculer les paramètres",
 	"Toggle sidebar": "Basculer la barre latérale",
 	"Toggle sidebar": "Basculer la barre latérale",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "תגובה שגויה",
 	"Bad Response": "תגובה שגויה",
 	"Banners": "באנרים",
 	"Banners": "באנרים",
 	"Base Model (From)": "דגם בסיס (מ)",
 	"Base Model (From)": "דגם בסיס (מ)",
+	"Batch Size (num_batch)": "",
 	"before": "לפני",
 	"before": "לפני",
 	"Being lazy": "להיות עצלן",
 	"Being lazy": "להיות עצלן",
 	"Brave Search API Key": "מפתח API של חיפוש אמיץ",
 	"Brave Search API Key": "מפתח API של חיפוש אמיץ",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "גלה, הורד, וחקור פקודות מותאמות אישית",
 	"Discover, download, and explore custom prompts": "גלה, הורד, וחקור פקודות מותאמות אישית",
 	"Discover, download, and explore model presets": "גלה, הורד, וחקור הגדרות מודל מוגדרות מראש",
 	"Discover, download, and explore model presets": "גלה, הורד, וחקור הגדרות מודל מוגדרות מראש",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "הצג את שם המשתמש במקום 'אתה' בצ'אט",
 	"Display the username instead of You in the Chat": "הצג את שם המשתמש במקום 'אתה' בצ'אט",
 	"Document": "מסמך",
 	"Document": "מסמך",
 	"Document Settings": "הגדרות מסמך",
 	"Document Settings": "הגדרות מסמך",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "הזן מפתח API של Serpstack",
 	"Enter Serpstack API Key": "הזן מפתח API של Serpstack",
 	"Enter stop sequence": "הזן רצף עצירה",
 	"Enter stop sequence": "הזן רצף עצירה",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "הזן Top K",
 	"Enter Top K": "הזן Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "הזן כתובת URL (למשל http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "הזן כתובת URL (למשל http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "הזן כתובת URL (למשל http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "הזן כתובת URL (למשל http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "מערכת",
 	"System": "מערכת",
 	"System Prompt": "תגובת מערכת",
 	"System Prompt": "תגובת מערכת",
 	"Tags": "תגיות",
 	"Tags": "תגיות",
+	"Tavily API Key": "",
 	"Tell us more:": "תרשמו יותר:",
 	"Tell us more:": "תרשמו יותר:",
 	"Temperature": "טמפרטורה",
 	"Temperature": "טמפרטורה",
 	"Template": "תבנית",
 	"Template": "תבנית",
@@ -519,6 +523,7 @@
 	"Today": "היום",
 	"Today": "היום",
 	"Toggle settings": "החלפת מצב של הגדרות",
 	"Toggle settings": "החלפת מצב של הגדרות",
 	"Toggle sidebar": "החלפת מצב של סרגל הצד",
 	"Toggle sidebar": "החלפת מצב של סרגל הצד",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "ख़राब प्रतिक्रिया",
 	"Bad Response": "ख़राब प्रतिक्रिया",
 	"Banners": "बैनर",
 	"Banners": "बैनर",
 	"Base Model (From)": "बेस मॉडल (से)",
 	"Base Model (From)": "बेस मॉडल (से)",
+	"Batch Size (num_batch)": "",
 	"before": "पहले",
 	"before": "पहले",
 	"Being lazy": "आलसी होना",
 	"Being lazy": "आलसी होना",
 	"Brave Search API Key": "Brave सर्च एपीआई कुंजी",
 	"Brave Search API Key": "Brave सर्च एपीआई कुंजी",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "कस्टम प्रॉम्प्ट को खोजें, डाउनलोड करें और एक्सप्लोर करें",
 	"Discover, download, and explore custom prompts": "कस्टम प्रॉम्प्ट को खोजें, डाउनलोड करें और एक्सप्लोर करें",
 	"Discover, download, and explore model presets": "मॉडल प्रीसेट खोजें, डाउनलोड करें और एक्सप्लोर करें",
 	"Discover, download, and explore model presets": "मॉडल प्रीसेट खोजें, डाउनलोड करें और एक्सप्लोर करें",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "चैट में 'आप' के स्थान पर उपयोगकर्ता नाम प्रदर्शित करें",
 	"Display the username instead of You in the Chat": "चैट में 'आप' के स्थान पर उपयोगकर्ता नाम प्रदर्शित करें",
 	"Document": "दस्तावेज़",
 	"Document": "दस्तावेज़",
 	"Document Settings": "दस्तावेज़ सेटिंग्स",
 	"Document Settings": "दस्तावेज़ सेटिंग्स",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "सर्पस्टैक एपीआई कुंजी दर्ज करें",
 	"Enter Serpstack API Key": "सर्पस्टैक एपीआई कुंजी दर्ज करें",
 	"Enter stop sequence": "स्टॉप अनुक्रम दर्ज करें",
 	"Enter stop sequence": "स्टॉप अनुक्रम दर्ज करें",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "शीर्ष K दर्ज करें",
 	"Enter Top K": "शीर्ष K दर्ज करें",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "यूआरएल दर्ज करें (उदा. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "यूआरएल दर्ज करें (उदा. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "यूआरएल दर्ज करें (उदा. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "यूआरएल दर्ज करें (उदा. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "सिस्टम",
 	"System": "सिस्टम",
 	"System Prompt": "सिस्टम प्रॉम्प्ट",
 	"System Prompt": "सिस्टम प्रॉम्प्ट",
 	"Tags": "टैग",
 	"Tags": "टैग",
+	"Tavily API Key": "",
 	"Tell us more:": "हमें और अधिक बताएँ:",
 	"Tell us more:": "हमें और अधिक बताएँ:",
 	"Temperature": "टेंपेरेचर",
 	"Temperature": "टेंपेरेचर",
 	"Template": "टेम्पलेट",
 	"Template": "टेम्पलेट",
@@ -518,6 +522,7 @@
 	"Today": "आज",
 	"Today": "आज",
 	"Toggle settings": "सेटिंग्स टॉगल करें",
 	"Toggle settings": "सेटिंग्स टॉगल करें",
 	"Toggle sidebar": "साइडबार टॉगल करें",
 	"Toggle sidebar": "साइडबार टॉगल करें",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "शीर्ष  K",
 	"Top K": "शीर्ष  K",
 	"Top P": "शीर्ष  P",
 	"Top P": "शीर्ष  P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Loš odgovor",
 	"Bad Response": "Loš odgovor",
 	"Banners": "Baneri",
 	"Banners": "Baneri",
 	"Base Model (From)": "Osnovni model (Od)",
 	"Base Model (From)": "Osnovni model (Od)",
+	"Batch Size (num_batch)": "",
 	"before": "prije",
 	"before": "prije",
 	"Being lazy": "Biti lijen",
 	"Being lazy": "Biti lijen",
 	"Brave Search API Key": "Brave tražilica - API ključ",
 	"Brave Search API Key": "Brave tražilica - API ključ",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Otkrijte, preuzmite i istražite prilagođene prompte",
 	"Discover, download, and explore custom prompts": "Otkrijte, preuzmite i istražite prilagođene prompte",
 	"Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele",
 	"Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele",
 	"Dismissible": "Odbaciti",
 	"Dismissible": "Odbaciti",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru",
 	"Display the username instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru",
 	"Document": "Dokument",
 	"Document": "Dokument",
 	"Document Settings": "Postavke dokumenta",
 	"Document Settings": "Postavke dokumenta",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "Unesite Serply API ključ",
 	"Enter Serply API Key": "Unesite Serply API ključ",
 	"Enter Serpstack API Key": "Unesite Serpstack API ključ",
 	"Enter Serpstack API Key": "Unesite Serpstack API ključ",
 	"Enter stop sequence": "Unesite sekvencu zaustavljanja",
 	"Enter stop sequence": "Unesite sekvencu zaustavljanja",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Unesite Top K",
 	"Enter Top K": "Unesite Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Unesite URL (npr. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Unesite URL (npr. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Unesite URL (npr. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Unesite URL (npr. http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sustav",
 	"System": "Sustav",
 	"System Prompt": "Sistemski prompt",
 	"System Prompt": "Sistemski prompt",
 	"Tags": "Oznake",
 	"Tags": "Oznake",
+	"Tavily API Key": "",
 	"Tell us more:": "Recite nam više:",
 	"Tell us more:": "Recite nam više:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Predložak",
 	"Template": "Predložak",
@@ -519,6 +523,7 @@
 	"Today": "Danas",
 	"Today": "Danas",
 	"Toggle settings": "Prebaci postavke",
 	"Toggle settings": "Prebaci postavke",
 	"Toggle sidebar": "Prebaci bočnu traku",
 	"Toggle sidebar": "Prebaci bočnu traku",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "Alati",
 	"Tools": "Alati",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Risposta non valida",
 	"Bad Response": "Risposta non valida",
 	"Banners": "Banner",
 	"Banners": "Banner",
 	"Base Model (From)": "Modello base (da)",
 	"Base Model (From)": "Modello base (da)",
+	"Batch Size (num_batch)": "",
 	"before": "prima",
 	"before": "prima",
 	"Being lazy": "Essere pigri",
 	"Being lazy": "Essere pigri",
 	"Brave Search API Key": "Chiave API di ricerca Brave",
 	"Brave Search API Key": "Chiave API di ricerca Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Scopri, scarica ed esplora prompt personalizzati",
 	"Discover, download, and explore custom prompts": "Scopri, scarica ed esplora prompt personalizzati",
 	"Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset del modello",
 	"Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset del modello",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat",
 	"Display the username instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat",
 	"Document": "Documento",
 	"Document": "Documento",
 	"Document Settings": "Impostazioni documento",
 	"Document Settings": "Impostazioni documento",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Inserisci la chiave API Serpstack",
 	"Enter Serpstack API Key": "Inserisci la chiave API Serpstack",
 	"Enter stop sequence": "Inserisci la sequenza di arresto",
 	"Enter stop sequence": "Inserisci la sequenza di arresto",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Inserisci Top K",
 	"Enter Top K": "Inserisci Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Inserisci URL (ad esempio http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Inserisci URL (ad esempio http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Inserisci URL (ad esempio http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Inserisci URL (ad esempio http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt di sistema",
 	"System Prompt": "Prompt di sistema",
 	"Tags": "Tag",
 	"Tags": "Tag",
+	"Tavily API Key": "",
 	"Tell us more:": "Raccontaci di più:",
 	"Tell us more:": "Raccontaci di più:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Modello",
 	"Template": "Modello",
@@ -519,6 +523,7 @@
 	"Today": "Oggi",
 	"Today": "Oggi",
 	"Toggle settings": "Attiva/disattiva impostazioni",
 	"Toggle settings": "Attiva/disattiva impostazioni",
 	"Toggle sidebar": "Attiva/disattiva barra laterale",
 	"Toggle sidebar": "Attiva/disattiva barra laterale",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "応答が悪い",
 	"Bad Response": "応答が悪い",
 	"Banners": "バナー",
 	"Banners": "バナー",
 	"Base Model (From)": "ベースモデル(From)",
 	"Base Model (From)": "ベースモデル(From)",
+	"Batch Size (num_batch)": "",
 	"before": "より前",
 	"before": "より前",
 	"Being lazy": "怠惰な",
 	"Being lazy": "怠惰な",
 	"Brave Search API Key": "Brave Search APIキー",
 	"Brave Search API Key": "Brave Search APIキー",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "カスタムプロンプトを見つけて、ダウンロードして、探索",
 	"Discover, download, and explore custom prompts": "カスタムプロンプトを見つけて、ダウンロードして、探索",
 	"Discover, download, and explore model presets": "モデルプリセットを見つけて、ダウンロードして、探索",
 	"Discover, download, and explore model presets": "モデルプリセットを見つけて、ダウンロードして、探索",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示",
 	"Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示",
 	"Document": "ドキュメント",
 	"Document": "ドキュメント",
 	"Document Settings": "ドキュメント設定",
 	"Document Settings": "ドキュメント設定",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Serpstack APIキーの入力",
 	"Enter Serpstack API Key": "Serpstack APIキーの入力",
 	"Enter stop sequence": "ストップシーケンスを入力してください",
 	"Enter stop sequence": "ストップシーケンスを入力してください",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "トップ K を入力してください",
 	"Enter Top K": "トップ K を入力してください",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL を入力してください (例: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL を入力してください (例: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL を入力してください (例: http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "URL を入力してください (例: http://localhost:11434)",
@@ -487,6 +490,7 @@
 	"System": "システム",
 	"System": "システム",
 	"System Prompt": "システムプロンプト",
 	"System Prompt": "システムプロンプト",
 	"Tags": "タグ",
 	"Tags": "タグ",
+	"Tavily API Key": "",
 	"Tell us more:": "もっと話してください:",
 	"Tell us more:": "もっと話してください:",
 	"Temperature": "温度",
 	"Temperature": "温度",
 	"Template": "テンプレート",
 	"Template": "テンプレート",
@@ -517,6 +521,7 @@
 	"Today": "今日",
 	"Today": "今日",
 	"Toggle settings": "設定を切り替え",
 	"Toggle settings": "設定を切り替え",
 	"Toggle sidebar": "サイドバーを切り替え",
 	"Toggle sidebar": "サイドバーを切り替え",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "トップ K",
 	"Top K": "トップ K",
 	"Top P": "トップ P",
 	"Top P": "トップ P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "ხარვეზი",
 	"Bad Response": "ხარვეზი",
 	"Banners": "რეკლამა",
 	"Banners": "რეკლამა",
 	"Base Model (From)": "საბაზო მოდელი (-დან)",
 	"Base Model (From)": "საბაზო მოდელი (-დან)",
+	"Batch Size (num_batch)": "",
 	"before": "ადგილზე",
 	"before": "ადგილზე",
 	"Being lazy": "ჩაიტყვევა",
 	"Being lazy": "ჩაიტყვევა",
 	"Brave Search API Key": "Brave Search API გასაღები",
 	"Brave Search API Key": "Brave Search API გასაღები",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მორგებული მოთხოვნები",
 	"Discover, download, and explore custom prompts": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მორგებული მოთხოვნები",
 	"Discover, download, and explore model presets": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მოდელის წინასწარ პარამეტრები",
 	"Discover, download, and explore model presets": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მოდელის წინასწარ პარამეტრები",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "ჩატში აჩვენე მომხმარებლის სახელი თქვენს ნაცვლად",
 	"Display the username instead of You in the Chat": "ჩატში აჩვენე მომხმარებლის სახელი თქვენს ნაცვლად",
 	"Document": "დოკუმენტი",
 	"Document": "დოკუმენტი",
 	"Document Settings": "დოკუმენტის პარამეტრები",
 	"Document Settings": "დოკუმენტის პარამეტრები",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "შეიყვანეთ Serpstack API Key",
 	"Enter Serpstack API Key": "შეიყვანეთ Serpstack API Key",
 	"Enter stop sequence": "შეიყვანეთ ტოპ თანმიმდევრობა",
 	"Enter stop sequence": "შეიყვანეთ ტოპ თანმიმდევრობა",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "შეიყვანეთ Top K",
 	"Enter Top K": "შეიყვანეთ Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "შეიყვანეთ მისამართი (მაგალითად http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "შეიყვანეთ მისამართი (მაგალითად http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "შეიყვანეთ მისამართი (მაგალითად http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "შეიყვანეთ მისამართი (მაგალითად http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "სისტემა",
 	"System": "სისტემა",
 	"System Prompt": "სისტემური მოთხოვნა",
 	"System Prompt": "სისტემური მოთხოვნა",
 	"Tags": "ტეგები",
 	"Tags": "ტეგები",
+	"Tavily API Key": "",
 	"Tell us more:": "ჩვენთან დავუკავშირდით",
 	"Tell us more:": "ჩვენთან დავუკავშირდით",
 	"Temperature": "ტემპერატურა",
 	"Temperature": "ტემპერატურა",
 	"Template": "შაბლონი",
 	"Template": "შაბლონი",
@@ -518,6 +522,7 @@
 	"Today": "დღეს",
 	"Today": "დღეს",
 	"Toggle settings": "პარამეტრების გადართვა",
 	"Toggle settings": "პარამეტრების გადართვა",
 	"Toggle sidebar": "გვერდითი ზოლის გადართვა",
 	"Toggle sidebar": "გვერდითი ზოლის გადართვა",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "ტოპ K",
 	"Top K": "ტოპ K",
 	"Top P": "ტოპ P",
 	"Top P": "ტოპ P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "응답이 좋지 않습니다.",
 	"Bad Response": "응답이 좋지 않습니다.",
 	"Banners": "배너",
 	"Banners": "배너",
 	"Base Model (From)": "기본 모델(시작)",
 	"Base Model (From)": "기본 모델(시작)",
+	"Batch Size (num_batch)": "",
 	"before": "이전",
 	"before": "이전",
 	"Being lazy": "게으름 피우기",
 	"Being lazy": "게으름 피우기",
 	"Brave Search API Key": "Brave Search API 키",
 	"Brave Search API Key": "Brave Search API 키",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "사용자 정의 프롬프트 검색, 다운로드 및 탐색",
 	"Discover, download, and explore custom prompts": "사용자 정의 프롬프트 검색, 다운로드 및 탐색",
 	"Discover, download, and explore model presets": "모델 사전 설정 검색, 다운로드 및 탐색",
 	"Discover, download, and explore model presets": "모델 사전 설정 검색, 다운로드 및 탐색",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "채팅에서 'You' 대신 사용자 이름 표시",
 	"Display the username instead of You in the Chat": "채팅에서 'You' 대신 사용자 이름 표시",
 	"Document": "문서",
 	"Document": "문서",
 	"Document Settings": "문서 설정",
 	"Document Settings": "문서 설정",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Serpstack API Key 입력",
 	"Enter Serpstack API Key": "Serpstack API Key 입력",
 	"Enter stop sequence": "중지 시퀀스 입력",
 	"Enter stop sequence": "중지 시퀀스 입력",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Top K 입력",
 	"Enter Top K": "Top K 입력",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL 입력(예: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL 입력(예: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL 입력(예: http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "URL 입력(예: http://localhost:11434)",
@@ -487,6 +490,7 @@
 	"System": "시스템",
 	"System": "시스템",
 	"System Prompt": "시스템 프롬프트",
 	"System Prompt": "시스템 프롬프트",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "더 알려주세요:",
 	"Tell us more:": "더 알려주세요:",
 	"Temperature": "Temperature",
 	"Temperature": "Temperature",
 	"Template": "Template",
 	"Template": "Template",
@@ -517,6 +521,7 @@
 	"Today": "오늘",
 	"Today": "오늘",
 	"Toggle settings": "설정 전환",
 	"Toggle settings": "설정 전환",
 	"Toggle sidebar": "사이드바 전환",
 	"Toggle sidebar": "사이드바 전환",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Neteisingas atsakymas",
 	"Bad Response": "Neteisingas atsakymas",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "prieš",
 	"before": "prieš",
 	"Being lazy": "Būvimas tingiu",
 	"Being lazy": "Būvimas tingiu",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Atrasti ir parsisiųsti užklausas",
 	"Discover, download, and explore custom prompts": "Atrasti ir parsisiųsti užklausas",
 	"Discover, download, and explore model presets": "Atrasti ir parsisiųsti modelių konfigūracija",
 	"Discover, download, and explore model presets": "Atrasti ir parsisiųsti modelių konfigūracija",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Rodyti naudotojo vardą vietoje žodžio Jūs pokalbyje",
 	"Display the username instead of You in the Chat": "Rodyti naudotojo vardą vietoje žodžio Jūs pokalbyje",
 	"Document": "Dokumentas",
 	"Document": "Dokumentas",
 	"Document Settings": "Dokumento nuostatos",
 	"Document Settings": "Dokumento nuostatos",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Įveskite pabaigos sekvenciją",
 	"Enter stop sequence": "Įveskite pabaigos sekvenciją",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Įveskite Top K",
 	"Enter Top K": "Įveskite Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Įveskite nuorodą (pvz. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Įveskite nuorodą (pvz. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Įveskite nuorododą (pvz. http://localhost:11434",
 	"Enter URL (e.g. http://localhost:11434)": "Įveskite nuorododą (pvz. http://localhost:11434",
@@ -490,6 +493,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Sistemos užklausa",
 	"System Prompt": "Sistemos užklausa",
 	"Tags": "Žymos",
 	"Tags": "Žymos",
+	"Tavily API Key": "",
 	"Tell us more:": "Papasakokite daugiau",
 	"Tell us more:": "Papasakokite daugiau",
 	"Temperature": "Temperatūra",
 	"Temperature": "Temperatūra",
 	"Template": "Modelis",
 	"Template": "Modelis",
@@ -520,6 +524,7 @@
 	"Today": "Šiandien",
 	"Today": "Šiandien",
 	"Toggle settings": "Atverti/užverti parametrus",
 	"Toggle settings": "Atverti/užverti parametrus",
 	"Toggle sidebar": "Atverti/užverti šoninį meniu",
 	"Toggle sidebar": "Atverti/užverti šoninį meniu",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Dårlig svar",
 	"Bad Response": "Dårlig svar",
 	"Banners": "Bannere",
 	"Banners": "Bannere",
 	"Base Model (From)": "Grunnmodell (Fra)",
 	"Base Model (From)": "Grunnmodell (Fra)",
+	"Batch Size (num_batch)": "",
 	"before": "før",
 	"before": "før",
 	"Being lazy": "Er lat",
 	"Being lazy": "Er lat",
 	"Brave Search API Key": "Brave Search API-nøkkel",
 	"Brave Search API Key": "Brave Search API-nøkkel",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Oppdag, last ned og utforsk egendefinerte prompts",
 	"Discover, download, and explore custom prompts": "Oppdag, last ned og utforsk egendefinerte prompts",
 	"Discover, download, and explore model presets": "Oppdag, last ned og utforsk modellforhåndsinnstillinger",
 	"Discover, download, and explore model presets": "Oppdag, last ned og utforsk modellforhåndsinnstillinger",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Vis brukernavnet i stedet for Du i chatten",
 	"Display the username instead of You in the Chat": "Vis brukernavnet i stedet for Du i chatten",
 	"Document": "Dokument",
 	"Document": "Dokument",
 	"Document Settings": "Dokumentinnstillinger",
 	"Document Settings": "Dokumentinnstillinger",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Skriv inn Serpstack API-nøkkel",
 	"Enter Serpstack API Key": "Skriv inn Serpstack API-nøkkel",
 	"Enter stop sequence": "Skriv inn stoppsekvens",
 	"Enter stop sequence": "Skriv inn stoppsekvens",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Skriv inn Top K",
 	"Enter Top K": "Skriv inn Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Skriv inn URL (f.eks. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Skriv inn URL (f.eks. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Skriv inn URL (f.eks. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Skriv inn URL (f.eks. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "System",
 	"System": "System",
 	"System Prompt": "Systemprompt",
 	"System Prompt": "Systemprompt",
 	"Tags": "Tagger",
 	"Tags": "Tagger",
+	"Tavily API Key": "",
 	"Tell us more:": "Fortell oss mer:",
 	"Tell us more:": "Fortell oss mer:",
 	"Temperature": "Temperatur",
 	"Temperature": "Temperatur",
 	"Template": "Mal",
 	"Template": "Mal",
@@ -518,6 +522,7 @@
 	"Today": "I dag",
 	"Today": "I dag",
 	"Toggle settings": "Veksle innstillinger",
 	"Toggle settings": "Veksle innstillinger",
 	"Toggle sidebar": "Veksle sidefelt",
 	"Toggle sidebar": "Veksle sidefelt",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Ongeldig antwoord",
 	"Bad Response": "Ongeldig antwoord",
 	"Banners": "Banners",
 	"Banners": "Banners",
 	"Base Model (From)": "Basismodel (vanaf)",
 	"Base Model (From)": "Basismodel (vanaf)",
+	"Batch Size (num_batch)": "",
 	"before": "voor",
 	"before": "voor",
 	"Being lazy": "Lustig zijn",
 	"Being lazy": "Lustig zijn",
 	"Brave Search API Key": "Brave Search API-sleutel",
 	"Brave Search API Key": "Brave Search API-sleutel",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Ontdek, download en verken aangepaste prompts",
 	"Discover, download, and explore custom prompts": "Ontdek, download en verken aangepaste prompts",
 	"Discover, download, and explore model presets": "Ontdek, download en verken model presets",
 	"Discover, download, and explore model presets": "Ontdek, download en verken model presets",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Toon de gebruikersnaam in plaats van Jij in de Chat",
 	"Display the username instead of You in the Chat": "Toon de gebruikersnaam in plaats van Jij in de Chat",
 	"Document": "Document",
 	"Document": "Document",
 	"Document Settings": "Document Instellingen",
 	"Document Settings": "Document Instellingen",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Voer de Serpstack API-sleutel in",
 	"Enter Serpstack API Key": "Voer de Serpstack API-sleutel in",
 	"Enter stop sequence": "Zet stop sequentie",
 	"Enter stop sequence": "Zet stop sequentie",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Voeg Top K toe",
 	"Enter Top K": "Voeg Top K toe",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Zet URL (Bijv. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Zet URL (Bijv. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Zet URL (Bijv. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Zet URL (Bijv. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "Systeem",
 	"System": "Systeem",
 	"System Prompt": "Systeem Prompt",
 	"System Prompt": "Systeem Prompt",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "Vertel ons meer:",
 	"Tell us more:": "Vertel ons meer:",
 	"Temperature": "Temperatuur",
 	"Temperature": "Temperatuur",
 	"Template": "Template",
 	"Template": "Template",
@@ -518,6 +522,7 @@
 	"Today": "Vandaag",
 	"Today": "Vandaag",
 	"Toggle settings": "Wissel instellingen",
 	"Toggle settings": "Wissel instellingen",
 	"Toggle sidebar": "Wissel sidebar",
 	"Toggle sidebar": "Wissel sidebar",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "ਖਰਾਬ ਜਵਾਬ",
 	"Bad Response": "ਖਰਾਬ ਜਵਾਬ",
 	"Banners": "ਬੈਨਰ",
 	"Banners": "ਬੈਨਰ",
 	"Base Model (From)": "ਬੇਸ ਮਾਡਲ (ਤੋਂ)",
 	"Base Model (From)": "ਬੇਸ ਮਾਡਲ (ਤੋਂ)",
+	"Batch Size (num_batch)": "",
 	"before": "ਪਹਿਲਾਂ",
 	"before": "ਪਹਿਲਾਂ",
 	"Being lazy": "ਆਲਸੀ ਹੋਣਾ",
 	"Being lazy": "ਆਲਸੀ ਹੋਣਾ",
 	"Brave Search API Key": "ਬਹਾਦਰ ਖੋਜ API ਕੁੰਜੀ",
 	"Brave Search API Key": "ਬਹਾਦਰ ਖੋਜ API ਕੁੰਜੀ",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "ਕਸਟਮ ਪ੍ਰੰਪਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ",
 	"Discover, download, and explore custom prompts": "ਕਸਟਮ ਪ੍ਰੰਪਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ",
 	"Discover, download, and explore model presets": "ਮਾਡਲ ਪ੍ਰੀਸੈਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ",
 	"Discover, download, and explore model presets": "ਮਾਡਲ ਪ੍ਰੀਸੈਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "ਗੱਲਬਾਤ 'ਚ ਤੁਹਾਡੇ ਸਥਾਨ 'ਤੇ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਓ",
 	"Display the username instead of You in the Chat": "ਗੱਲਬਾਤ 'ਚ ਤੁਹਾਡੇ ਸਥਾਨ 'ਤੇ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਓ",
 	"Document": "ਡਾਕੂਮੈਂਟ",
 	"Document": "ਡਾਕੂਮੈਂਟ",
 	"Document Settings": "ਡਾਕੂਮੈਂਟ ਸੈਟਿੰਗਾਂ",
 	"Document Settings": "ਡਾਕੂਮੈਂਟ ਸੈਟਿੰਗਾਂ",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Serpstack API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ",
 	"Enter Serpstack API Key": "Serpstack API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ",
 	"Enter stop sequence": "ਰੋਕਣ ਦਾ ਕ੍ਰਮ ਦਰਜ ਕਰੋ",
 	"Enter stop sequence": "ਰੋਕਣ ਦਾ ਕ੍ਰਮ ਦਰਜ ਕਰੋ",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "ਸਿਖਰ K ਦਰਜ ਕਰੋ",
 	"Enter Top K": "ਸਿਖਰ K ਦਰਜ ਕਰੋ",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "ਸਿਸਟਮ",
 	"System": "ਸਿਸਟਮ",
 	"System Prompt": "ਸਿਸਟਮ ਪ੍ਰੰਪਟ",
 	"System Prompt": "ਸਿਸਟਮ ਪ੍ਰੰਪਟ",
 	"Tags": "ਟੈਗ",
 	"Tags": "ਟੈਗ",
+	"Tavily API Key": "",
 	"Tell us more:": "ਸਾਨੂੰ ਹੋਰ ਦੱਸੋ:",
 	"Tell us more:": "ਸਾਨੂੰ ਹੋਰ ਦੱਸੋ:",
 	"Temperature": "ਤਾਪਮਾਨ",
 	"Temperature": "ਤਾਪਮਾਨ",
 	"Template": "ਟੈਮਪਲੇਟ",
 	"Template": "ਟੈਮਪਲੇਟ",
@@ -518,6 +522,7 @@
 	"Today": "ਅੱਜ",
 	"Today": "ਅੱਜ",
 	"Toggle settings": "ਸੈਟਿੰਗਾਂ ਟੌਗਲ ਕਰੋ",
 	"Toggle settings": "ਸੈਟਿੰਗਾਂ ਟੌਗਲ ਕਰੋ",
 	"Toggle sidebar": "ਸਾਈਡਬਾਰ ਟੌਗਲ ਕਰੋ",
 	"Toggle sidebar": "ਸਾਈਡਬਾਰ ਟੌਗਲ ਕਰੋ",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "ਸਿਖਰ K",
 	"Top K": "ਸਿਖਰ K",
 	"Top P": "ਸਿਖਰ P",
 	"Top P": "ਸਿਖਰ P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Zła odpowiedź",
 	"Bad Response": "Zła odpowiedź",
 	"Banners": "Banery",
 	"Banners": "Banery",
 	"Base Model (From)": "Model podstawowy (od)",
 	"Base Model (From)": "Model podstawowy (od)",
+	"Batch Size (num_batch)": "",
 	"before": "przed",
 	"before": "przed",
 	"Being lazy": "Jest leniwy",
 	"Being lazy": "Jest leniwy",
 	"Brave Search API Key": "Klucz API wyszukiwania Brave",
 	"Brave Search API Key": "Klucz API wyszukiwania Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Odkryj, pobierz i eksploruj niestandardowe prompty",
 	"Discover, download, and explore custom prompts": "Odkryj, pobierz i eksploruj niestandardowe prompty",
 	"Discover, download, and explore model presets": "Odkryj, pobierz i eksploruj ustawienia modeli",
 	"Discover, download, and explore model presets": "Odkryj, pobierz i eksploruj ustawienia modeli",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Wyświetl nazwę użytkownika zamiast Ty w czacie",
 	"Display the username instead of You in the Chat": "Wyświetl nazwę użytkownika zamiast Ty w czacie",
 	"Document": "Dokument",
 	"Document": "Dokument",
 	"Document Settings": "Ustawienia dokumentu",
 	"Document Settings": "Ustawienia dokumentu",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Wprowadź klucz API Serpstack",
 	"Enter Serpstack API Key": "Wprowadź klucz API Serpstack",
 	"Enter stop sequence": "Wprowadź sekwencję zatrzymania",
 	"Enter stop sequence": "Wprowadź sekwencję zatrzymania",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Wprowadź Top K",
 	"Enter Top K": "Wprowadź Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Wprowadź adres URL (np. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Wprowadź adres URL (np. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Wprowadź adres URL (np. http://localhost:11434/)",
 	"Enter URL (e.g. http://localhost:11434)": "Wprowadź adres URL (np. http://localhost:11434/)",
@@ -490,6 +493,7 @@
 	"System": "System",
 	"System": "System",
 	"System Prompt": "Prompt systemowy",
 	"System Prompt": "Prompt systemowy",
 	"Tags": "Tagi",
 	"Tags": "Tagi",
+	"Tavily API Key": "",
 	"Tell us more:": "Powiedz nam więcej",
 	"Tell us more:": "Powiedz nam więcej",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Szablon",
 	"Template": "Szablon",
@@ -520,6 +524,7 @@
 	"Today": "Dzisiaj",
 	"Today": "Dzisiaj",
 	"Toggle settings": "Przełącz ustawienia",
 	"Toggle settings": "Przełącz ustawienia",
 	"Toggle sidebar": "Przełącz panel boczny",
 	"Toggle sidebar": "Przełącz panel boczny",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Najlepsze K",
 	"Top K": "Najlepsze K",
 	"Top P": "Najlepsze P",
 	"Top P": "Najlepsze P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Resposta ruim",
 	"Bad Response": "Resposta ruim",
 	"Banners": "Banners",
 	"Banners": "Banners",
 	"Base Model (From)": "Modelo Base (De)",
 	"Base Model (From)": "Modelo Base (De)",
+	"Batch Size (num_batch)": "",
 	"before": "antes",
 	"before": "antes",
 	"Being lazy": "Ser preguiçoso",
 	"Being lazy": "Ser preguiçoso",
 	"Brave Search API Key": "Chave da API de pesquisa do Brave",
 	"Brave Search API Key": "Chave da API de pesquisa do Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Descubra, baixe e explore prompts personalizados",
 	"Discover, download, and explore custom prompts": "Descubra, baixe e explore prompts personalizados",
 	"Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelo",
 	"Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelo",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Bate-papo",
 	"Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Bate-papo",
 	"Document": "Documento",
 	"Document": "Documento",
 	"Document Settings": "Configurações de Documento",
 	"Document Settings": "Configurações de Documento",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Digite a chave da API Serpstack",
 	"Enter Serpstack API Key": "Digite a chave da API Serpstack",
 	"Enter stop sequence": "Digite a sequência de parada",
 	"Enter stop sequence": "Digite a sequência de parada",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Digite o Top K",
 	"Enter Top K": "Digite o Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt do Sistema",
 	"System Prompt": "Prompt do Sistema",
 	"Tags": "Tags",
 	"Tags": "Tags",
+	"Tavily API Key": "",
 	"Tell us more:": "Dê-nos mais:",
 	"Tell us more:": "Dê-nos mais:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Modelo",
 	"Template": "Modelo",
@@ -519,6 +523,7 @@
 	"Today": "Hoje",
 	"Today": "Hoje",
 	"Toggle settings": "Alternar configurações",
 	"Toggle settings": "Alternar configurações",
 	"Toggle sidebar": "Alternar barra lateral",
 	"Toggle sidebar": "Alternar barra lateral",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Resposta má",
 	"Bad Response": "Resposta má",
 	"Banners": "Estandartes",
 	"Banners": "Estandartes",
 	"Base Model (From)": "Modelo Base (De)",
 	"Base Model (From)": "Modelo Base (De)",
+	"Batch Size (num_batch)": "",
 	"before": "antes",
 	"before": "antes",
 	"Being lazy": "Ser preguiçoso",
 	"Being lazy": "Ser preguiçoso",
 	"Brave Search API Key": "Chave da API de Pesquisa Brave",
 	"Brave Search API Key": "Chave da API de Pesquisa Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Descubra, descarregue e explore prompts personalizados",
 	"Discover, download, and explore custom prompts": "Descubra, descarregue e explore prompts personalizados",
 	"Discover, download, and explore model presets": "Descubra, descarregue e explore predefinições de modelo",
 	"Discover, download, and explore model presets": "Descubra, descarregue e explore predefinições de modelo",
 	"Dismissible": "Dispensável",
 	"Dismissible": "Dispensável",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Exibir o nome de utilizador em vez de Você na Conversa",
 	"Display the username instead of You in the Chat": "Exibir o nome de utilizador em vez de Você na Conversa",
 	"Document": "Documento",
 	"Document": "Documento",
 	"Document Settings": "Configurações de Documento",
 	"Document Settings": "Configurações de Documento",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Escreva a chave da API Serpstack",
 	"Enter Serpstack API Key": "Escreva a chave da API Serpstack",
 	"Enter stop sequence": "Escreva a sequência de paragem",
 	"Enter stop sequence": "Escreva a sequência de paragem",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Escreva o Top K",
 	"Enter Top K": "Escreva o Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Escreva o URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Escreva o URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Escreva o URL (por exemplo, http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Escreva o URL (por exemplo, http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt do Sistema",
 	"System Prompt": "Prompt do Sistema",
 	"Tags": "Etiquetas",
 	"Tags": "Etiquetas",
+	"Tavily API Key": "",
 	"Tell us more:": "Diga-nos mais:",
 	"Tell us more:": "Diga-nos mais:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Modelo",
 	"Template": "Modelo",
@@ -519,6 +523,7 @@
 	"Today": "Hoje",
 	"Today": "Hoje",
 	"Toggle settings": "Alternar configurações",
 	"Toggle settings": "Alternar configurações",
 	"Toggle sidebar": "Alternar barra lateral",
 	"Toggle sidebar": "Alternar barra lateral",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Недопустимый ответ",
 	"Bad Response": "Недопустимый ответ",
 	"Banners": "Баннеры",
 	"Banners": "Баннеры",
 	"Base Model (From)": "Базовая модель (от)",
 	"Base Model (From)": "Базовая модель (от)",
+	"Batch Size (num_batch)": "",
 	"before": "до",
 	"before": "до",
 	"Being lazy": "ленивый",
 	"Being lazy": "ленивый",
 	"Brave Search API Key": "Ключ API поиска Brave",
 	"Brave Search API Key": "Ключ API поиска Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Находите, загружайте и исследуйте настраиваемые промты",
 	"Discover, download, and explore custom prompts": "Находите, загружайте и исследуйте настраиваемые промты",
 	"Discover, download, and explore model presets": "Находите, загружайте и исследуйте предустановки модели",
 	"Discover, download, and explore model presets": "Находите, загружайте и исследуйте предустановки модели",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Отображать имя пользователя вместо 'Вы' в чате",
 	"Display the username instead of You in the Chat": "Отображать имя пользователя вместо 'Вы' в чате",
 	"Document": "Документ",
 	"Document": "Документ",
 	"Document Settings": "Настройки документа",
 	"Document Settings": "Настройки документа",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Введите ключ API Serpstack",
 	"Enter Serpstack API Key": "Введите ключ API Serpstack",
 	"Enter stop sequence": "Введите последовательность остановки",
 	"Enter stop sequence": "Введите последовательность остановки",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Введите Top K",
 	"Enter Top K": "Введите Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введите URL-адрес (например, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введите URL-адрес (например, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Введите URL-адрес (например, http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Введите URL-адрес (например, http://localhost:11434)",
@@ -490,6 +493,7 @@
 	"System": "Система",
 	"System": "Система",
 	"System Prompt": "Системный промпт",
 	"System Prompt": "Системный промпт",
 	"Tags": "Теги",
 	"Tags": "Теги",
+	"Tavily API Key": "",
 	"Tell us more:": "Пожалуйста, расскажите нам больше:",
 	"Tell us more:": "Пожалуйста, расскажите нам больше:",
 	"Temperature": "Температура",
 	"Temperature": "Температура",
 	"Template": "Шаблон",
 	"Template": "Шаблон",
@@ -520,6 +524,7 @@
 	"Today": "Сегодня",
 	"Today": "Сегодня",
 	"Toggle settings": "Переключить настройки",
 	"Toggle settings": "Переключить настройки",
 	"Toggle sidebar": "Переключить боковую панель",
 	"Toggle sidebar": "Переключить боковую панель",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Лош одговор",
 	"Bad Response": "Лош одговор",
 	"Banners": "Барјаке",
 	"Banners": "Барјаке",
 	"Base Model (From)": "Основни модел (од)",
 	"Base Model (From)": "Основни модел (од)",
+	"Batch Size (num_batch)": "",
 	"before": "пре",
 	"before": "пре",
 	"Being lazy": "Бити лењ",
 	"Being lazy": "Бити лењ",
 	"Brave Search API Key": "Апи кључ за храбру претрагу",
 	"Brave Search API Key": "Апи кључ за храбру претрагу",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Откријте, преузмите и истражите прилагођене упите",
 	"Discover, download, and explore custom prompts": "Откријте, преузмите и истражите прилагођене упите",
 	"Discover, download, and explore model presets": "Откријте, преузмите и истражите образце модела",
 	"Discover, download, and explore model presets": "Откријте, преузмите и истражите образце модела",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Прикажи корисничко име уместо Ти у чату",
 	"Display the username instead of You in the Chat": "Прикажи корисничко име уместо Ти у чату",
 	"Document": "Документ",
 	"Document": "Документ",
 	"Document Settings": "Подешавања документа",
 	"Document Settings": "Подешавања документа",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Унесите Серпстацк АПИ кључ",
 	"Enter Serpstack API Key": "Унесите Серпстацк АПИ кључ",
 	"Enter stop sequence": "Унесите секвенцу заустављања",
 	"Enter stop sequence": "Унесите секвенцу заустављања",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Унесите Топ К",
 	"Enter Top K": "Унесите Топ К",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Унесите адресу (нпр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Унесите адресу (нпр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Унесите адресу (нпр. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Унесите адресу (нпр. http://localhost:11434)",
@@ -489,6 +492,7 @@
 	"System": "Систем",
 	"System": "Систем",
 	"System Prompt": "Системски упит",
 	"System Prompt": "Системски упит",
 	"Tags": "Ознаке",
 	"Tags": "Ознаке",
+	"Tavily API Key": "",
 	"Tell us more:": "Реците нам више:",
 	"Tell us more:": "Реците нам више:",
 	"Temperature": "Температура",
 	"Temperature": "Температура",
 	"Template": "Шаблон",
 	"Template": "Шаблон",
@@ -519,6 +523,7 @@
 	"Today": "Данас",
 	"Today": "Данас",
 	"Toggle settings": "Пребаци подешавања",
 	"Toggle settings": "Пребаци подешавања",
 	"Toggle sidebar": "Пребаци бочну траку",
 	"Toggle sidebar": "Пребаци бочну траку",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Топ К",
 	"Top K": "Топ К",
 	"Top P": "Топ П",
 	"Top P": "Топ П",

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

@@ -1,5 +1,5 @@
 {
 {
-	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' eller '-1' för ingen utgång.",
+	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' eller '-1' för inget utgångsdatum",
 	"(Beta)": "(Beta)",
 	"(Beta)": "(Beta)",
 	"(e.g. `sh webui.sh --api`)": "(t.ex. `sh webui.sh --api`)",
 	"(e.g. `sh webui.sh --api`)": "(t.ex. `sh webui.sh --api`)",
 	"(latest)": "(senaste)",
 	"(latest)": "(senaste)",
@@ -12,15 +12,15 @@
 	"a user": "en användare",
 	"a user": "en användare",
 	"About": "Om",
 	"About": "Om",
 	"Account": "Konto",
 	"Account": "Konto",
-	"Account Activation Pending": "",
+	"Account Activation Pending": "Kontoaktivering väntar",
 	"Accurate information": "Exakt information",
 	"Accurate information": "Exakt information",
-	"Active Users": "",
+	"Active Users": "Aktiva användare",
 	"Add": "Lägg till",
 	"Add": "Lägg till",
 	"Add a model id": "Lägga till ett modell-ID",
 	"Add a model id": "Lägga till ett modell-ID",
 	"Add a short description about what this model does": "Lägg till en kort beskrivning av vad den här modellen gör",
 	"Add a short description about what this model does": "Lägg till en kort beskrivning av vad den här modellen gör",
-	"Add a short title for this prompt": "Lägg till en kort titel för denna prompt",
+	"Add a short title for this prompt": "Lägg till en kort titel för denna instruktion",
 	"Add a tag": "Lägg till en tagg",
 	"Add a tag": "Lägg till en tagg",
-	"Add custom prompt": "Lägg till en anpassad prompt",
+	"Add custom prompt": "Lägg till en anpassad instruktion",
 	"Add Docs": "Lägg till dokument",
 	"Add Docs": "Lägg till dokument",
 	"Add Files": "Lägg till filer",
 	"Add Files": "Lägg till filer",
 	"Add Memory": "Lägg till minne",
 	"Add Memory": "Lägg till minne",
@@ -30,10 +30,10 @@
 	"Add User": "Lägg till användare",
 	"Add User": "Lägg till användare",
 	"Adjusting these settings will apply changes universally to all users.": "Justering av dessa inställningar kommer att tillämpa ändringar universellt för alla användare.",
 	"Adjusting these settings will apply changes universally to all users.": "Justering av dessa inställningar kommer att tillämpa ändringar universellt för alla användare.",
 	"admin": "administratör",
 	"admin": "administratör",
-	"Admin": "",
+	"Admin": "Admin",
 	"Admin Panel": "Administrationspanel",
 	"Admin Panel": "Administrationspanel",
 	"Admin Settings": "Administratörsinställningar",
 	"Admin Settings": "Administratörsinställningar",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratörer har tillgång till alla verktyg hela tiden, medan användare behöver verktyg som tilldelas per modell i arbetsytan.",
 	"Advanced Parameters": "Avancerade parametrar",
 	"Advanced Parameters": "Avancerade parametrar",
 	"Advanced Params": "Avancerade parametrar",
 	"Advanced Params": "Avancerade parametrar",
 	"all": "alla",
 	"all": "alla",
@@ -41,7 +41,7 @@
 	"All Users": "Alla användare",
 	"All Users": "Alla användare",
 	"Allow": "Tillåt",
 	"Allow": "Tillåt",
 	"Allow Chat Deletion": "Tillåt chattborttagning",
 	"Allow Chat Deletion": "Tillåt chattborttagning",
-	"Allow non-local voices": "",
+	"Allow non-local voices": "Tillåt icke-lokala röster",
 	"alphanumeric characters and hyphens": "alfanumeriska tecken och bindestreck",
 	"alphanumeric characters and hyphens": "alfanumeriska tecken och bindestreck",
 	"Already have an account?": "Har du redan ett konto?",
 	"Already have an account?": "Har du redan ett konto?",
 	"an assistant": "en assistent",
 	"an assistant": "en assistent",
@@ -51,7 +51,7 @@
 	"API Key": "API-nyckel",
 	"API Key": "API-nyckel",
 	"API Key created.": "API-nyckel skapad.",
 	"API Key created.": "API-nyckel skapad.",
 	"API keys": "API-nycklar",
 	"API keys": "API-nycklar",
-	"April": "April",
+	"April": "april",
 	"Archive": "Arkiv",
 	"Archive": "Arkiv",
 	"Archive All Chats": "Arkivera alla chattar",
 	"Archive All Chats": "Arkivera alla chattar",
 	"Archived Chats": "Arkiverade chattar",
 	"Archived Chats": "Arkiverade chattar",
@@ -60,7 +60,7 @@
 	"Attach file": "Bifoga fil",
 	"Attach file": "Bifoga fil",
 	"Attention to detail": "Detaljerad uppmärksamhet",
 	"Attention to detail": "Detaljerad uppmärksamhet",
 	"Audio": "Ljud",
 	"Audio": "Ljud",
-	"August": "Augusti",
+	"August": "augusti",
 	"Auto-playback response": "Automatisk uppspelning",
 	"Auto-playback response": "Automatisk uppspelning",
 	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 bas-URL",
 	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 bas-URL",
 	"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 bas-URL krävs.",
 	"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 bas-URL krävs.",
@@ -68,16 +68,17 @@
 	"Back": "Tillbaka",
 	"Back": "Tillbaka",
 	"Bad Response": "Felaktig respons",
 	"Bad Response": "Felaktig respons",
 	"Banners": "Banners",
 	"Banners": "Banners",
-	"Base Model (From)": "Basmodell (från)",
-	"before": "før",
+	"Base Model (From)": "Basmodell (Från)",
+	"Batch Size (num_batch)": "Batchstorlek (num_batch)",
+	"before": "för",
 	"Being lazy": "Lägg till",
 	"Being lazy": "Lägg till",
-	"Brave Search API Key": "API-nyckel för modig sökning",
+	"Brave Search API Key": "API-nyckel för Brave Search",
 	"Bypass SSL verification for Websites": "Kringgå SSL-verifiering för webbplatser",
 	"Bypass SSL verification for Websites": "Kringgå SSL-verifiering för webbplatser",
-	"Call": "",
-	"Call feature is not supported when using Web STT engine": "",
-	"Camera": "",
+	"Call": "Samtal",
+	"Call feature is not supported when using Web STT engine": "Samtalsfunktionen är inte kompatibel med Web Tal-till-text motor",
+	"Camera": "Kamera",
 	"Cancel": "Avbryt",
 	"Cancel": "Avbryt",
-	"Capabilities": "Kapacitet",
+	"Capabilities": "Kapaciteter",
 	"Change Password": "Ändra lösenord",
 	"Change Password": "Ändra lösenord",
 	"Chat": "Chatt",
 	"Chat": "Chatt",
 	"Chat Bubble UI": "Chatbubblar UI",
 	"Chat Bubble UI": "Chatbubblar UI",
@@ -93,12 +94,12 @@
 	"Chunk Params": "Chunk-parametrar",
 	"Chunk Params": "Chunk-parametrar",
 	"Chunk Size": "Chunk-storlek",
 	"Chunk Size": "Chunk-storlek",
 	"Citation": "Citat",
 	"Citation": "Citat",
-	"Clear memory": "",
+	"Clear memory": "Rensa minnet",
 	"Click here for help.": "Klicka här för hjälp.",
 	"Click here for help.": "Klicka här för hjälp.",
 	"Click here to": "Klicka här för att",
 	"Click here to": "Klicka här för att",
 	"Click here to select": "Klicka här för att välja",
 	"Click here to select": "Klicka här för att välja",
 	"Click here to select a csv file.": "Klicka här för att välja en csv-fil.",
 	"Click here to select a csv file.": "Klicka här för att välja en csv-fil.",
-	"Click here to select a py file.": "",
+	"Click here to select a py file.": "Klicka här för att välja en python-fil.",
 	"Click here to select documents.": "Klicka här för att välja dokument.",
 	"Click here to select documents.": "Klicka här för att välja dokument.",
 	"click here.": "klicka här.",
 	"click here.": "klicka här.",
 	"Click on the user role button to change a user's role.": "Klicka på knappen för användarroll för att ändra en användares roll.",
 	"Click on the user role button to change a user's role.": "Klicka på knappen för användarroll för att ändra en användares roll.",
@@ -109,10 +110,10 @@
 	"ComfyUI Base URL": "ComfyUI Base URL",
 	"ComfyUI Base URL": "ComfyUI Base URL",
 	"ComfyUI Base URL is required.": "ComfyUI Base URL krävs.",
 	"ComfyUI Base URL is required.": "ComfyUI Base URL krävs.",
 	"Command": "Kommando",
 	"Command": "Kommando",
-	"Concurrent Requests": "Samtidiga begäranden",
+	"Concurrent Requests": "Parallella anrop",
 	"Confirm Password": "Bekräfta lösenord",
 	"Confirm Password": "Bekräfta lösenord",
 	"Connections": "Anslutningar",
 	"Connections": "Anslutningar",
-	"Contact Admin for WebUI Access": "",
+	"Contact Admin for WebUI Access": "Kontakta administratören för att få åtkomst till WebUI",
 	"Content": "Innehåll",
 	"Content": "Innehåll",
 	"Context Length": "Kontextlängd",
 	"Context Length": "Kontextlängd",
 	"Continue Response": "Fortsätt svar",
 	"Continue Response": "Fortsätt svar",
@@ -133,15 +134,15 @@
 	"Custom": "Anpassad",
 	"Custom": "Anpassad",
 	"Customize models for a specific purpose": "Anpassa modeller för ett specifikt syfte",
 	"Customize models for a specific purpose": "Anpassa modeller för ett specifikt syfte",
 	"Dark": "Mörk",
 	"Dark": "Mörk",
-	"Dashboard": "",
+	"Dashboard": "Instrumentpanel",
 	"Database": "Databas",
 	"Database": "Databas",
-	"December": "December",
+	"December": "december",
 	"Default": "Standard",
 	"Default": "Standard",
 	"Default (Automatic1111)": "Standard (Automatic1111)",
 	"Default (Automatic1111)": "Standard (Automatic1111)",
 	"Default (SentenceTransformers)": "Standard (SentenceTransformers)",
 	"Default (SentenceTransformers)": "Standard (SentenceTransformers)",
 	"Default Model": "Standardmodell",
 	"Default Model": "Standardmodell",
 	"Default model updated": "Standardmodell uppdaterad",
 	"Default model updated": "Standardmodell uppdaterad",
-	"Default Prompt Suggestions": "Standardpromptförslag",
+	"Default Prompt Suggestions": "Standardinstruktionsförslag",
 	"Default User Role": "Standardanvändarroll",
 	"Default User Role": "Standardanvändarroll",
 	"delete": "radera",
 	"delete": "radera",
 	"Delete": "Radera",
 	"Delete": "Radera",
@@ -156,42 +157,43 @@
 	"Description": "Beskrivning",
 	"Description": "Beskrivning",
 	"Didn't fully follow instructions": "Följde inte instruktionerna",
 	"Didn't fully follow instructions": "Följde inte instruktionerna",
 	"Discover a model": "Upptäck en modell",
 	"Discover a model": "Upptäck en modell",
-	"Discover a prompt": "Upptäck en prompt",
-	"Discover, download, and explore custom prompts": "Upptäck, ladda ner och utforska anpassade prompts",
+	"Discover a prompt": "Upptäck en instruktion",
+	"Discover, download, and explore custom prompts": "Upptäck, ladda ner och utforska anpassade instruktioner",
 	"Discover, download, and explore model presets": "Upptäck, ladda ner och utforska modellförinställningar",
 	"Discover, download, and explore model presets": "Upptäck, ladda ner och utforska modellförinställningar",
-	"Dismissible": "",
+	"Dismissible": "Kan stängas",
+	"Display Emoji in Call": "Visa Emoji under samtal",
 	"Display the username instead of You in the Chat": "Visa användarnamnet istället för du i chatten",
 	"Display the username instead of You in the Chat": "Visa användarnamnet istället för du i chatten",
 	"Document": "Dokument",
 	"Document": "Dokument",
 	"Document Settings": "Dokumentinställningar",
 	"Document Settings": "Dokumentinställningar",
-	"Documentation": "",
+	"Documentation": "Dokumentation",
 	"Documents": "Dokument",
 	"Documents": "Dokument",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "gör inga externa anslutningar, och dina data förblir säkra på din lokalt värdade server.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "gör inga externa anslutningar, och dina data förblir säkra på din lokalt värdade server.",
 	"Don't Allow": "Tillåt inte",
 	"Don't Allow": "Tillåt inte",
-	"Don't have an account?": "Har du inte ett konto?",
-	"Don't like the style": "Du tycker inte om utseendet",
+	"Don't have an account?": "Har du inget konto?",
+	"Don't like the style": "Tycker inte om utseendet",
 	"Download": "Ladda ner",
 	"Download": "Ladda ner",
 	"Download canceled": "Nedladdning avbruten",
 	"Download canceled": "Nedladdning avbruten",
 	"Download Database": "Ladda ner databas",
 	"Download Database": "Ladda ner databas",
-	"Drop any files here to add to the conversation": "Släpp filer här för att lägga till i konversationen",
+	"Drop any files here to add to the conversation": "Släpp filer här för att lägga till i samtalet",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "t.ex. '30s', '10m'. Giltiga tidsenheter är 's', 'm', 'h'.",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "t.ex. '30s', '10m'. Giltiga tidsenheter är 's', 'm', 'h'.",
 	"Edit": "Redigera",
 	"Edit": "Redigera",
 	"Edit Doc": "Redigera dokument",
 	"Edit Doc": "Redigera dokument",
 	"Edit User": "Redigera användare",
 	"Edit User": "Redigera användare",
 	"Email": "E-post",
 	"Email": "E-post",
-	"Embedding Batch Size": "",
-	"Embedding Model": "Embeddingsmodell",
-	"Embedding Model Engine": "Embeddingsmodellmotor",
-	"Embedding model set to \"{{embedding_model}}\"": "Embeddingsmodell inställd på \"{{embedding_model}}\"",
+	"Embedding Batch Size": "Batchstorlek för inbäddning",
+	"Embedding Model": "Inbäddningsmodell",
+	"Embedding Model Engine": "Motor för inbäddningsmodell",
+	"Embedding model set to \"{{embedding_model}}\"": "Inbäddningsmodell inställd på \"{{embedding_model}}\"",
 	"Enable Chat History": "Aktivera chatthistorik",
 	"Enable Chat History": "Aktivera chatthistorik",
 	"Enable Community Sharing": "Aktivera community-delning",
 	"Enable Community Sharing": "Aktivera community-delning",
 	"Enable New Sign Ups": "Aktivera nya registreringar",
 	"Enable New Sign Ups": "Aktivera nya registreringar",
 	"Enable Web Search": "Aktivera webbsökning",
 	"Enable Web Search": "Aktivera webbsökning",
-	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Se till att din CSV-fil innehåller fyra kolumner i denna ordning: Namn, E-post, Lösenord, Roll.",
+	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Se till att din CSV-fil innehåller fyra kolumner i denna ordning: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Skriv {{role}} meddelande här",
 	"Enter {{role}} message here": "Skriv {{role}} meddelande här",
 	"Enter a detail about yourself for your LLMs to recall": "Skriv en detalj om dig själv för att dina LLMs ska komma ihåg",
 	"Enter a detail about yourself for your LLMs to recall": "Skriv en detalj om dig själv för att dina LLMs ska komma ihåg",
-	"Enter Brave Search API Key": "Ange API-nyckel för modig sökning",
-	"Enter Chunk Overlap": "Ange Chunk-överlappning",
-	"Enter Chunk Size": "Ange Chunk-storlek",
+	"Enter Brave Search API Key": "Ange API-nyckel för Brave Search",
+	"Enter Chunk Overlap": "Ange chunköverlappning",
+	"Enter Chunk Size": "Ange chunkstorlek",
 	"Enter Github Raw URL": "Ange Github Raw URL",
 	"Enter Github Raw URL": "Ange Github Raw URL",
 	"Enter Google PSE API Key": "Ange Google PSE API-nyckel",
 	"Enter Google PSE API Key": "Ange Google PSE API-nyckel",
 	"Enter Google PSE Engine Id": "Ange Google PSE Engine Id",
 	"Enter Google PSE Engine Id": "Ange Google PSE Engine Id",
@@ -199,12 +201,13 @@
 	"Enter language codes": "Skriv språkkoder",
 	"Enter language codes": "Skriv språkkoder",
 	"Enter model tag (e.g. {{modelTag}})": "Ange modelltagg (t.ex. {{modelTag}})",
 	"Enter model tag (e.g. {{modelTag}})": "Ange modelltagg (t.ex. {{modelTag}})",
 	"Enter Number of Steps (e.g. 50)": "Ange antal steg (t.ex. 50)",
 	"Enter Number of Steps (e.g. 50)": "Ange antal steg (t.ex. 50)",
-	"Enter Score": "Ange poäng",
+	"Enter Score": "Ange betyg",
 	"Enter Searxng Query URL": "Ange Searxng Query URL",
 	"Enter Searxng Query URL": "Ange Searxng Query URL",
 	"Enter Serper API Key": "Ange Serper API-nyckel",
 	"Enter Serper API Key": "Ange Serper API-nyckel",
-	"Enter Serply API Key": "",
+	"Enter Serply API Key": "Ange Serply API-nyckel",
 	"Enter Serpstack API Key": "Ange Serpstack API-nyckel",
 	"Enter Serpstack API Key": "Ange Serpstack API-nyckel",
 	"Enter stop sequence": "Ange stoppsekvens",
 	"Enter stop sequence": "Ange stoppsekvens",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Ange Top K",
 	"Enter Top K": "Ange Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ange URL (t.ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ange URL (t.ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Ange URL (t.ex. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Ange URL (t.ex. http://localhost:11434)",
@@ -216,38 +219,38 @@
 	"Experimental": "Experimentell",
 	"Experimental": "Experimentell",
 	"Export": "Export",
 	"Export": "Export",
 	"Export All Chats (All Users)": "Exportera alla chattar (alla användare)",
 	"Export All Chats (All Users)": "Exportera alla chattar (alla användare)",
-	"Export chat (.json)": "",
+	"Export chat (.json)": "Exportera chatt (.json)",
 	"Export Chats": "Exportera chattar",
 	"Export Chats": "Exportera chattar",
 	"Export Documents Mapping": "Exportera dokumentmappning",
 	"Export Documents Mapping": "Exportera dokumentmappning",
 	"Export Models": "Exportera modeller",
 	"Export Models": "Exportera modeller",
-	"Export Prompts": "Exportera prompts",
-	"Export Tools": "",
-	"External Models": "",
+	"Export Prompts": "Exportera instruktioner",
+	"Export Tools": "Exportera verktyg",
+	"External Models": "Externa modeller",
 	"Failed to create API Key.": "Misslyckades med att skapa API-nyckel.",
 	"Failed to create API Key.": "Misslyckades med att skapa API-nyckel.",
 	"Failed to read clipboard contents": "Misslyckades med att läsa urklippsinnehåll",
 	"Failed to read clipboard contents": "Misslyckades med att läsa urklippsinnehåll",
-	"Failed to update settings": "",
-	"February": "Februar",
-	"Feel free to add specific details": "Förfoga att lägga till specifika detaljer",
+	"Failed to update settings": "Misslyckades med att uppdatera inställningarna",
+	"February": "februari",
+	"Feel free to add specific details": "Tveka inte att lägga till specifika detaljer",
 	"File Mode": "Fil-läge",
 	"File Mode": "Fil-läge",
 	"File not found.": "Fil hittades inte.",
 	"File not found.": "Fil hittades inte.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrycksmanipulering upptäckt: Kan inte använda initialer som avatar. Återställning till standardprofilbild.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrycksmanipulering upptäckt: Kan inte använda initialer som avatar. Återställning till standardprofilbild.",
-	"Fluidly stream large external response chunks": "Flytande ström stora externa svarsblock",
-	"Focus chat input": "Fokusera chattindata",
+	"Fluidly stream large external response chunks": "Strömma flytande stora externa svarschunks",
+	"Focus chat input": "Fokusera på chattfältet",
 	"Followed instructions perfectly": "Följde instruktionerna perfekt",
 	"Followed instructions perfectly": "Följde instruktionerna perfekt",
 	"Format your variables using square brackets like this:": "Formatera dina variabler med hakparenteser så här:",
 	"Format your variables using square brackets like this:": "Formatera dina variabler med hakparenteser så här:",
 	"Frequency Penalty": "Straff för frekvens",
 	"Frequency Penalty": "Straff för frekvens",
 	"General": "Allmän",
 	"General": "Allmän",
 	"General Settings": "Allmänna inställningar",
 	"General Settings": "Allmänna inställningar",
-	"Generate Image": "",
-	"Generating search query": "Generera sökfråga",
-	"Generation Info": "Generasjon Info",
+	"Generate Image": "Generera bild",
+	"Generating search query": "Genererar sökfråga",
+	"Generation Info": "Info om generation",
 	"Good Response": "Bra svar",
 	"Good Response": "Bra svar",
 	"Google PSE API Key": "Google PSE API-nyckel",
 	"Google PSE API Key": "Google PSE API-nyckel",
 	"Google PSE Engine Id": "Google PSE Engine Id",
 	"Google PSE Engine Id": "Google PSE Engine Id",
 	"h:mm a": "h:mm a",
 	"h:mm a": "h:mm a",
-	"has no conversations.": "har ingen samtaler.",
+	"has no conversations.": "har inga samtal.",
 	"Hello, {{name}}": "Hej, {{name}}",
 	"Hello, {{name}}": "Hej, {{name}}",
-	"Help": "Hjelp",
+	"Help": "Hjälp",
 	"Hide": "Dölj",
 	"Hide": "Dölj",
 	"How can I help you today?": "Hur kan jag hjälpa dig idag?",
 	"How can I help you today?": "Hur kan jag hjälpa dig idag?",
 	"Hybrid Search": "Hybrid sökning",
 	"Hybrid Search": "Hybrid sökning",
@@ -258,52 +261,52 @@
 	"Import Chats": "Importera chattar",
 	"Import Chats": "Importera chattar",
 	"Import Documents Mapping": "Importera dokumentmappning",
 	"Import Documents Mapping": "Importera dokumentmappning",
 	"Import Models": "Importera modeller",
 	"Import Models": "Importera modeller",
-	"Import Prompts": "Importera prompts",
-	"Import Tools": "",
-	"Include `--api` flag when running stable-diffusion-webui": "Inkludera `--api`-flagga när du kör stabil-diffusion-webui",
+	"Import Prompts": "Importera instruktioner",
+	"Import Tools": "Importera verktyg",
+	"Include `--api` flag when running stable-diffusion-webui": "Inkludera flaggan `--api` när du kör stable-diffusion-webui",
 	"Info": "Information",
 	"Info": "Information",
 	"Input commands": "Indatakommandon",
 	"Input commands": "Indatakommandon",
 	"Install from Github URL": "Installera från Github-URL",
 	"Install from Github URL": "Installera från Github-URL",
-	"Instant Auto-Send After Voice Transcription": "",
+	"Instant Auto-Send After Voice Transcription": "Skicka automatiskt efter rösttranskribering",
 	"Interface": "Gränssnitt",
 	"Interface": "Gränssnitt",
 	"Invalid Tag": "Ogiltig tagg",
 	"Invalid Tag": "Ogiltig tagg",
-	"January": "januar",
+	"January": "januari",
 	"join our Discord for help.": "gå med i vår Discord för hjälp.",
 	"join our Discord for help.": "gå med i vår Discord för hjälp.",
 	"JSON": "JSON",
 	"JSON": "JSON",
 	"JSON Preview": "Förhandsversion av JSON",
 	"JSON Preview": "Förhandsversion av JSON",
 	"July": "juli",
 	"July": "juli",
 	"June": "juni",
 	"June": "juni",
-	"JWT Expiration": "JWT-utgång",
+	"JWT Expiration": "JWT-utgångsdatum",
 	"JWT Token": "JWT-token",
 	"JWT Token": "JWT-token",
-	"Keep Alive": "Håll vid liv",
+	"Keep Alive": "Keep Alive",
 	"Keyboard shortcuts": "Tangentbordsgenvägar",
 	"Keyboard shortcuts": "Tangentbordsgenvägar",
-	"Knowledge": "",
+	"Knowledge": "Kunskap",
 	"Language": "Språk",
 	"Language": "Språk",
 	"Last Active": "Senast aktiv",
 	"Last Active": "Senast aktiv",
 	"Light": "Ljus",
 	"Light": "Ljus",
-	"Listening...": "",
-	"LLMs can make mistakes. Verify important information.": "LLM:er kan göra misstag. Verifiera viktig information.",
-	"Local Models": "",
+	"Listening...": "Lyssnar...",
+	"LLMs can make mistakes. Verify important information.": "LLM:er kan göra misstag. Granska viktig information.",
+	"Local Models": "Lokala modeller",
 	"LTR": "LTR",
 	"LTR": "LTR",
 	"Made by OpenWebUI Community": "Skapad av OpenWebUI Community",
 	"Made by OpenWebUI Community": "Skapad av OpenWebUI Community",
 	"Make sure to enclose them with": "Se till att bifoga dem med",
 	"Make sure to enclose them with": "Se till att bifoga dem med",
-	"Manage": "",
+	"Manage": "Hantera",
 	"Manage Models": "Hantera modeller",
 	"Manage Models": "Hantera modeller",
 	"Manage Ollama Models": "Hantera Ollama-modeller",
 	"Manage Ollama Models": "Hantera Ollama-modeller",
-	"Manage Pipelines": "Hantera pipelines",
+	"Manage Pipelines": "Hantera rörledningar",
 	"March": "mars",
 	"March": "mars",
-	"Max Tokens (num_predict)": "Maximalt antal polletter (num_predict)",
+	"Max Tokens (num_predict)": "Maximalt antal tokens (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Högst 3 modeller kan laddas ner samtidigt. Vänligen försök igen senare.",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Högst 3 modeller kan laddas ner samtidigt. Vänligen försök igen senare.",
-	"May": "mai",
-	"Memories accessible by LLMs will be shown here.": "Minnen som kan komma ihåg av LLM:er kommer att visas här.",
+	"May": "maj",
+	"Memories accessible by LLMs will be shown here.": "Minnen som LLM:er kan komma åt visas här.",
 	"Memory": "Minnen",
 	"Memory": "Minnen",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meddelanden du skickar efter att ha skapat din länk kommer inte att delas. Användare med URL:en kommer att kunna se delad chatt.",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meddelanden du skickar efter att ha skapat din länk kommer inte att delas. Användare med URL:en kommer att kunna se delad chatt.",
-	"Minimum Score": "Minimum poäng",
+	"Minimum Score": "Tröskel",
 	"Mirostat": "Mirostat",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Tau": "Mirostat Tau",
 	"Mirostat Tau": "Mirostat Tau",
-	"MMMM DD, YYYY": "MMMM DD, ÅÅÅÅ",
-	"MMMM DD, YYYY HH:mm": "MMMM DD, ÅÅÅÅ HH:mm",
+	"MMMM DD, YYYY": "MMMM DD, YYYY",
+	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
 	"Model '{{modelName}}' has been successfully downloaded.": "Modellen '{{modelName}}' har laddats ner framgångsrikt.",
 	"Model '{{modelName}}' has been successfully downloaded.": "Modellen '{{modelName}}' har laddats ner framgångsrikt.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Modellen '{{modelTag}}' är redan i kö för nedladdning.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Modellen '{{modelTag}}' är redan i kö för nedladdning.",
 	"Model {{modelId}} not found": "Modell {{modelId}} hittades inte",
 	"Model {{modelId}} not found": "Modell {{modelId}} hittades inte",
@@ -314,7 +317,7 @@
 	"Model not selected": "Modell inte vald",
 	"Model not selected": "Modell inte vald",
 	"Model Params": "Modell Params",
 	"Model Params": "Modell Params",
 	"Model Whitelisting": "Modellens vitlista",
 	"Model Whitelisting": "Modellens vitlista",
-	"Model(s) Whitelisted": "Modell(er) vitlistade",
+	"Model(s) Whitelisted": "Vitlistade modeller",
 	"Modelfile Content": "Modelfilens innehåll",
 	"Modelfile Content": "Modelfilens innehåll",
 	"Models": "Modeller",
 	"Models": "Modeller",
 	"More": "Mer",
 	"More": "Mer",
@@ -323,24 +326,24 @@
 	"Name your model": "Namnge din modell",
 	"Name your model": "Namnge din modell",
 	"New Chat": "Ny chatt",
 	"New Chat": "Ny chatt",
 	"New Password": "Nytt lösenord",
 	"New Password": "Nytt lösenord",
-	"No documents found": "",
+	"No documents found": "Inga dokument hittades",
 	"No results found": "Inga resultat hittades",
 	"No results found": "Inga resultat hittades",
 	"No search query generated": "Ingen sökfråga genererad",
 	"No search query generated": "Ingen sökfråga genererad",
-	"No source available": "Ingen tilgjengelig kilde",
+	"No source available": "Ingen tillgänglig källa",
 	"None": "Ingen",
 	"None": "Ingen",
 	"Not factually correct": "Inte faktiskt korrekt",
 	"Not factually correct": "Inte faktiskt korrekt",
-	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Merk: Hvis du angir en minimumspoengsum, returnerer søket bare dokumenter med en poengsum som er større enn eller lik minimumspoengsummen.",
+	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Obs: Om du anger en tröskel kommer sökningen endast att returnera dokument med ett betyg som är större än eller lika med tröskeln.",
 	"Notifications": "Notifikationer",
 	"Notifications": "Notifikationer",
 	"November": "november",
 	"November": "november",
 	"num_thread (Ollama)": "num_thread (Ollama)",
 	"num_thread (Ollama)": "num_thread (Ollama)",
 	"October": "oktober",
 	"October": "oktober",
 	"Off": "Av",
 	"Off": "Av",
 	"Okay, Let's Go!": "Okej, nu kör vi!",
 	"Okay, Let's Go!": "Okej, nu kör vi!",
-	"OLED Dark": "OLED mörkt",
+	"OLED Dark": "Mörk (OLED)",
 	"Ollama": "Ollama",
 	"Ollama": "Ollama",
 	"Ollama API": "Ollama API",
 	"Ollama API": "Ollama API",
 	"Ollama API disabled": "Ollama API inaktiverat",
 	"Ollama API disabled": "Ollama API inaktiverat",
-	"Ollama API is disabled": "",
+	"Ollama API is disabled": "Ollama API är inaktiverat",
 	"Ollama Version": "Ollama-version",
 	"Ollama Version": "Ollama-version",
 	"On": "På",
 	"On": "På",
 	"Only": "Endast",
 	"Only": "Endast",
@@ -363,50 +366,50 @@
 	"PDF document (.pdf)": "PDF-dokument (.pdf)",
 	"PDF document (.pdf)": "PDF-dokument (.pdf)",
 	"PDF Extract Images (OCR)": "PDF Extrahera bilder (OCR)",
 	"PDF Extract Images (OCR)": "PDF Extrahera bilder (OCR)",
 	"pending": "väntande",
 	"pending": "väntande",
-	"Permission denied when accessing media devices": "",
-	"Permission denied when accessing microphone": "",
+	"Permission denied when accessing media devices": "Nekad behörighet vid åtkomst till mediaenheter",
+	"Permission denied when accessing microphone": "Nekad behörighet vid åtkomst till mikrofon",
 	"Permission denied when accessing microphone: {{error}}": "Tillstånd nekades vid åtkomst till mikrofon: {{error}}",
 	"Permission denied when accessing microphone: {{error}}": "Tillstånd nekades vid åtkomst till mikrofon: {{error}}",
 	"Personalization": "Personalisering",
 	"Personalization": "Personalisering",
 	"Pipelines": "Rörledningar",
 	"Pipelines": "Rörledningar",
-	"Pipelines Valves": "Rörledningar Ventiler",
-	"Plain text (.txt)": "Rå text (.txt)",
+	"Pipelines Valves": "Ventiler för rörledningar",
+	"Plain text (.txt)": "Text (.txt)",
 	"Playground": "Lekplats",
 	"Playground": "Lekplats",
-	"Positive attitude": "Positivt humör",
+	"Positive attitude": "Positivt inställning",
 	"Previous 30 days": "Föregående 30 dagar",
 	"Previous 30 days": "Föregående 30 dagar",
 	"Previous 7 days": "Föregående 7 dagar",
 	"Previous 7 days": "Föregående 7 dagar",
 	"Profile Image": "Profilbild",
 	"Profile Image": "Profilbild",
-	"Prompt": "Prompt",
-	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (t.ex. Berätta mig en rolig faktor om Romerska Imperiet)",
-	"Prompt Content": "Promptinnehåll",
-	"Prompt suggestions": "Förslag",
-	"Prompts": "Prompts",
-	"Pull \"{{searchValue}}\" from Ollama.com": "Dra \"{{searchValue}}\" från Ollama.com",
-	"Pull a model from Ollama.com": "Dra en modell från Ollama.com",
-	"Query Params": "Frågeparametrar",
+	"Prompt": "Instruktion",
+	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Instruktion (t.ex. Berätta en kuriosa om Romerska Imperiet)",
+	"Prompt Content": "Instruktionens innehåll",
+	"Prompt suggestions": "Instruktionsförslag",
+	"Prompts": "Instruktioner",
+	"Pull \"{{searchValue}}\" from Ollama.com": "Ladda ner \"{{searchValue}}\" från Ollama.com",
+	"Pull a model from Ollama.com": "Ladda ner en modell från Ollama.com",
+	"Query Params": "Inställningar för sökfråga",
 	"RAG Template": "RAG-mall",
 	"RAG Template": "RAG-mall",
 	"Read Aloud": "Läs igenom",
 	"Read Aloud": "Läs igenom",
 	"Record voice": "Spela in röst",
 	"Record voice": "Spela in röst",
 	"Redirecting you to OpenWebUI Community": "Omdirigerar dig till OpenWebUI Community",
 	"Redirecting you to OpenWebUI Community": "Omdirigerar dig till OpenWebUI Community",
-	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
-	"Refused when it shouldn't have": "Avvisades när det inte borde ha",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referera till dig själv som \"Användare\" (t.ex. \"Användaren lär sig spanska\")",
+	"Refused when it shouldn't have": "Avvisades när det inte borde ha gjort det",
 	"Regenerate": "Regenerera",
 	"Regenerate": "Regenerera",
 	"Release Notes": "Versionsinformation",
 	"Release Notes": "Versionsinformation",
 	"Remove": "Ta bort",
 	"Remove": "Ta bort",
 	"Remove Model": "Ta bort modell",
 	"Remove Model": "Ta bort modell",
 	"Rename": "Byt namn",
 	"Rename": "Byt namn",
 	"Repeat Last N": "Upprepa senaste N",
 	"Repeat Last N": "Upprepa senaste N",
-	"Request Mode": "Begär läge",
+	"Request Mode": "Frågeläge",
 	"Reranking Model": "Reranking modell",
 	"Reranking Model": "Reranking modell",
 	"Reranking model disabled": "Reranking modell inaktiverad",
 	"Reranking model disabled": "Reranking modell inaktiverad",
 	"Reranking model set to \"{{reranking_model}}\"": "Reranking modell inställd på \"{{reranking_model}}\"",
 	"Reranking model set to \"{{reranking_model}}\"": "Reranking modell inställd på \"{{reranking_model}}\"",
-	"Reset Upload Directory": "",
+	"Reset Upload Directory": "Återställ uppladdningskatalog",
 	"Reset Vector Storage": "Återställ vektorlager",
 	"Reset Vector Storage": "Återställ vektorlager",
 	"Response AutoCopy to Clipboard": "Svara AutoCopy till urklipp",
 	"Response AutoCopy to Clipboard": "Svara AutoCopy till urklipp",
 	"Role": "Roll",
 	"Role": "Roll",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"RTL": "RTL",
 	"RTL": "RTL",
-	"Running": "",
+	"Running": "Kör",
 	"Save": "Spara",
 	"Save": "Spara",
 	"Save & Create": "Spara och skapa",
 	"Save & Create": "Spara och skapa",
 	"Save & Update": "Spara och uppdatera",
 	"Save & Update": "Spara och uppdatera",
@@ -419,35 +422,35 @@
 	"Search Chats": "Sök i chattar",
 	"Search Chats": "Sök i chattar",
 	"Search Documents": "Sök dokument",
 	"Search Documents": "Sök dokument",
 	"Search Models": "Sök modeller",
 	"Search Models": "Sök modeller",
-	"Search Prompts": "Sök promptar",
-	"Search Query Generation Prompt": "",
-	"Search Query Generation Prompt Length Threshold": "",
+	"Search Prompts": "Sök instruktioner",
+	"Search Query Generation Prompt": "Instruktion för generering av sökfrågor",
+	"Search Query Generation Prompt Length Threshold": "Tröskelvärde för generering av sökfrågor",
 	"Search Result Count": "Antal sökresultat",
 	"Search Result Count": "Antal sökresultat",
-	"Search Tools": "",
+	"Search Tools": "Sökverktyg",
 	"Searched {{count}} sites_one": "Sökte på {{count}} sites_one",
 	"Searched {{count}} sites_one": "Sökte på {{count}} sites_one",
 	"Searched {{count}} sites_other": "Sökte på {{count}} sites_other",
 	"Searched {{count}} sites_other": "Sökte på {{count}} sites_other",
-	"Searching \"{{searchQuery}}\"": "",
+	"Searching \"{{searchQuery}}\"": "Söker \"{{searchQuery}}\"",
 	"Searxng Query URL": "Searxng Query URL",
 	"Searxng Query URL": "Searxng Query URL",
 	"See readme.md for instructions": "Se readme.md för instruktioner",
 	"See readme.md for instructions": "Se readme.md för instruktioner",
 	"See what's new": "Se vad som är nytt",
 	"See what's new": "Se vad som är nytt",
 	"Seed": "Seed",
 	"Seed": "Seed",
 	"Select a base model": "Välj en basmodell",
 	"Select a base model": "Välj en basmodell",
-	"Select a engine": "",
+	"Select a engine": "Välj en motor",
 	"Select a mode": "Välj ett läge",
 	"Select a mode": "Välj ett läge",
 	"Select a model": "Välj en modell",
 	"Select a model": "Välj en modell",
-	"Select a pipeline": "Välj en pipeline",
-	"Select a pipeline url": "Välj en pipeline-URL",
+	"Select a pipeline": "Välj en rörledning",
+	"Select a pipeline url": "Välj en URL för rörledningen",
 	"Select an Ollama instance": "Välj en Ollama-instans",
 	"Select an Ollama instance": "Välj en Ollama-instans",
-	"Select Documents": "",
+	"Select Documents": "Välj dokument",
 	"Select model": "Välj en modell",
 	"Select model": "Välj en modell",
-	"Select only one model to call": "",
+	"Select only one model to call": "Välj endast en modell att ringa",
 	"Selected model(s) do not support image inputs": "Valda modeller stöder inte bildinmatningar",
 	"Selected model(s) do not support image inputs": "Valda modeller stöder inte bildinmatningar",
 	"Send": "Skicka",
 	"Send": "Skicka",
 	"Send a Message": "Skicka ett meddelande",
 	"Send a Message": "Skicka ett meddelande",
 	"Send message": "Skicka meddelande",
 	"Send message": "Skicka meddelande",
 	"September": "september",
 	"September": "september",
 	"Serper API Key": "Serper API-nyckel",
 	"Serper API Key": "Serper API-nyckel",
-	"Serply API Key": "",
+	"Serply API Key": "Serply API-nyckel",
 	"Serpstack API Key": "Serpstack API-nyckel",
 	"Serpstack API Key": "Serpstack API-nyckel",
 	"Server connection verified": "Serveranslutning verifierad",
 	"Server connection verified": "Serveranslutning verifierad",
 	"Set as default": "Ange som standard",
 	"Set as default": "Ange som standard",
@@ -460,15 +463,15 @@
 	"Set Voice": "Ange röst",
 	"Set Voice": "Ange röst",
 	"Settings": "Inställningar",
 	"Settings": "Inställningar",
 	"Settings saved successfully!": "Inställningar sparades framgångsrikt!",
 	"Settings saved successfully!": "Inställningar sparades framgångsrikt!",
-	"Settings updated successfully": "",
+	"Settings updated successfully": "Inställningar uppdaterades framgångsrikt",
 	"Share": "Dela",
 	"Share": "Dela",
 	"Share Chat": "Dela chatt",
 	"Share Chat": "Dela chatt",
 	"Share to OpenWebUI Community": "Dela till OpenWebUI Community",
 	"Share to OpenWebUI Community": "Dela till OpenWebUI Community",
 	"short-summary": "kort sammanfattning",
 	"short-summary": "kort sammanfattning",
 	"Show": "Visa",
 	"Show": "Visa",
-	"Show Admin Details in Account Pending Overlay": "",
+	"Show Admin Details in Account Pending Overlay": "Visa administratörsinformation till väntande konton",
 	"Show shortcuts": "Visa genvägar",
 	"Show shortcuts": "Visa genvägar",
-	"Showcased creativity": "Visuell kreativitet",
+	"Showcased creativity": "Visade kreativitet",
 	"sidebar": "sidofält",
 	"sidebar": "sidofält",
 	"Sign in": "Logga in",
 	"Sign in": "Logga in",
 	"Sign Out": "Logga ut",
 	"Sign Out": "Logga ut",
@@ -478,16 +481,17 @@
 	"Speech recognition error: {{error}}": "Fel vid taligenkänning: {{error}}",
 	"Speech recognition error: {{error}}": "Fel vid taligenkänning: {{error}}",
 	"Speech-to-Text Engine": "Tal-till-text-motor",
 	"Speech-to-Text Engine": "Tal-till-text-motor",
 	"Stop Sequence": "Stoppsekvens",
 	"Stop Sequence": "Stoppsekvens",
-	"STT Model": "",
-	"STT Settings": "STT-inställningar",
+	"STT Model": "Tal-till-text-modell",
+	"STT Settings": "Tal-till-text-inställningar",
 	"Submit": "Skicka in",
 	"Submit": "Skicka in",
 	"Subtitle (e.g. about the Roman Empire)": "Undertext (t.ex. om Romerska Imperiet)",
 	"Subtitle (e.g. about the Roman Empire)": "Undertext (t.ex. om Romerska Imperiet)",
 	"Success": "Framgång",
 	"Success": "Framgång",
 	"Successfully updated.": "Uppdaterades framgångsrikt.",
 	"Successfully updated.": "Uppdaterades framgångsrikt.",
 	"Suggested": "Föreslagen",
 	"Suggested": "Föreslagen",
 	"System": "System",
 	"System": "System",
-	"System Prompt": "Systemprompt",
+	"System Prompt": "Systeminstruktion",
 	"Tags": "Taggar",
 	"Tags": "Taggar",
+	"Tavily API Key": "",
 	"Tell us more:": "Berätta mer:",
 	"Tell us more:": "Berätta mer:",
 	"Temperature": "Temperatur",
 	"Temperature": "Temperatur",
 	"Template": "Mall",
 	"Template": "Mall",
@@ -495,48 +499,49 @@
 	"Text-to-Speech Engine": "Text-till-tal-motor",
 	"Text-to-Speech Engine": "Text-till-tal-motor",
 	"Tfs Z": "Tfs Z",
 	"Tfs Z": "Tfs Z",
 	"Thanks for your feedback!": "Tack för din feedback!",
 	"Thanks for your feedback!": "Tack för din feedback!",
-	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Poäng ska vara ett värde mellan 0,0 (0%) och 1,0 (100%).",
+	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Betyget ska vara ett värde mellan 0.0 (0%) och 1.0 (100%).",
 	"Theme": "Tema",
 	"Theme": "Tema",
 	"Thinking...": "",
 	"Thinking...": "",
-	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Detta säkerställer att dina värdefulla konversationer sparas säkert till din backend-databas. Tack!",
-	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
+	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Detta säkerställer att dina värdefulla samtal sparas säkert till din backend-databas. Tack!",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Detta är en experimentell funktion som kanske inte fungerar som förväntat och som kan komma att ändras när som helst.",
 	"This setting does not sync across browsers or devices.": "Denna inställning synkroniseras inte mellan webbläsare eller enheter.",
 	"This setting does not sync across browsers or devices.": "Denna inställning synkroniseras inte mellan webbläsare eller enheter.",
 	"Thorough explanation": "Djupare förklaring",
 	"Thorough explanation": "Djupare förklaring",
-	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Uppdatera flera variabelplatser efter varandra genom att trycka på tabb-tangenten i chattinmatningen efter varje ersättning.",
+	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Uppdatera fler variabler genom att trycka på tabb-tangenten i chattinmatningen efter varje ersättning.",
 	"Title": "Titel",
 	"Title": "Titel",
-	"Title (e.g. Tell me a fun fact)": "Tittel (f.eks. Fortell meg en fun fact)",
+	"Title (e.g. Tell me a fun fact)": "Titel (t.ex. Berätta en kuriosa)",
 	"Title Auto-Generation": "Automatisk generering av titel",
 	"Title Auto-Generation": "Automatisk generering av titel",
-	"Title cannot be an empty string.": "Tittel kan ikke være en tom streng.",
-	"Title Generation Prompt": "Titelgenereringsprompt",
+	"Title cannot be an empty string.": "Titeln får inte vara en tom sträng.",
+	"Title Generation Prompt": "Instruktion för titelgenerering",
 	"to": "till",
 	"to": "till",
 	"To access the available model names for downloading,": "För att komma åt de tillgängliga modellnamnen för nedladdning,",
 	"To access the available model names for downloading,": "För att komma åt de tillgängliga modellnamnen för nedladdning,",
-	"To access the GGUF models available for downloading,": "För att komma åt de GGUF-modeller som finns tillgängliga för nedladdning,",
-	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
-	"To add documents here, upload them to the \"Documents\" workspace first.": "",
+	"To access the GGUF models available for downloading,": "För att komma åt de GGUF-modellerna som finns tillgängliga för nedladdning,",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "För att få tillgång till WebUI, kontakta administratören. Administratörer kan hantera behörigheter från administrationspanelen.",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "Om du vill lägga till dokument här ska du först ladda upp dem till arbetsytan \"Dokument\".",
 	"to chat input.": "till chattinmatning.",
 	"to chat input.": "till chattinmatning.",
-	"To select toolkits here, add them to the \"Tools\" workspace first.": "",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "Om du vill välja verktygslådor här måste du först lägga till dem i arbetsytan \"Verktyg\".",
 	"Today": "Idag",
 	"Today": "Idag",
 	"Toggle settings": "Växla inställningar",
 	"Toggle settings": "Växla inställningar",
 	"Toggle sidebar": "Växla sidofält",
 	"Toggle sidebar": "Växla sidofält",
-	"Tools": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "Tokens att behålla vid kontextuppdatering (num_keep)",
+	"Tools": "Verktyg",
 	"Top K": "Topp K",
 	"Top K": "Topp K",
 	"Top P": "Topp P",
 	"Top P": "Topp P",
 	"Trouble accessing Ollama?": "Problem med att komma åt Ollama?",
 	"Trouble accessing Ollama?": "Problem med att komma åt Ollama?",
-	"TTS Model": "",
-	"TTS Settings": "TTS-inställningar",
-	"TTS Voice": "",
+	"TTS Model": "Text-till-tal-modell",
+	"TTS Settings": "Text-till-tal-inställningar",
+	"TTS Voice": "Text-till-tal-röst",
 	"Type": "Typ",
 	"Type": "Typ",
 	"Type Hugging Face Resolve (Download) URL": "Skriv Hugging Face Resolve (nedladdning) URL",
 	"Type Hugging Face Resolve (Download) URL": "Skriv Hugging Face Resolve (nedladdning) URL",
-	"Uh-oh! There was an issue connecting to {{provider}}.": "Oj då! Det uppstod ett problem med att ansluta till {{provider}}.",
+	"Uh-oh! There was an issue connecting to {{provider}}.": "Oj då! Det uppstod ett problem med anslutningen till {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Okänd filtyp '{{file_type}}', men accepterar och behandlar som vanlig text",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Okänd filtyp '{{file_type}}', men accepterar och behandlar som vanlig text",
 	"Update and Copy Link": "Uppdatera och kopiera länk",
 	"Update and Copy Link": "Uppdatera och kopiera länk",
 	"Update password": "Uppdatera lösenord",
 	"Update password": "Uppdatera lösenord",
 	"Upload a GGUF model": "Ladda upp en GGUF-modell",
 	"Upload a GGUF model": "Ladda upp en GGUF-modell",
 	"Upload Files": "Ladda upp filer",
 	"Upload Files": "Ladda upp filer",
-	"Upload Pipeline": "",
-	"Upload Progress": "Uppladdningsförlopp",
+	"Upload Pipeline": "Ladda upp rörledning",
+	"Upload Progress": "Uppladdningsframsteg",
 	"URL Mode": "URL-läge",
 	"URL Mode": "URL-läge",
-	"Use '#' in the prompt input to load and select your documents.": "Använd '#' i promptinmatningen för att ladda och välja dina dokument.",
+	"Use '#' in the prompt input to load and select your documents.": "Använd '#' i instruktionsinmatningen för att ladda och välja dina dokument.",
 	"Use Gravatar": "Använd Gravatar",
 	"Use Gravatar": "Använd Gravatar",
 	"Use Initials": "Använd initialer",
 	"Use Initials": "Använd initialer",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
@@ -552,31 +557,31 @@
 	"Warning": "Varning",
 	"Warning": "Varning",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Varning: Om du uppdaterar eller ändrar din embedding modell måste du importera alla dokument igen.",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Varning: Om du uppdaterar eller ändrar din embedding modell måste du importera alla dokument igen.",
 	"Web": "Webb",
 	"Web": "Webb",
-	"Web API": "",
+	"Web API": "Webb-API",
 	"Web Loader Settings": "Web Loader-inställningar",
 	"Web Loader Settings": "Web Loader-inställningar",
 	"Web Params": "Web-parametrar",
 	"Web Params": "Web-parametrar",
 	"Web Search": "Webbsökning",
 	"Web Search": "Webbsökning",
-	"Web Search Engine": "Sökmotor på webben",
+	"Web Search Engine": "Webbsökmotor",
 	"Webhook URL": "Webhook-URL",
 	"Webhook URL": "Webhook-URL",
 	"WebUI Add-ons": "WebUI-tillägg",
 	"WebUI Add-ons": "WebUI-tillägg",
 	"WebUI Settings": "WebUI-inställningar",
 	"WebUI Settings": "WebUI-inställningar",
 	"WebUI will make requests to": "WebUI kommer att skicka förfrågningar till",
 	"WebUI will make requests to": "WebUI kommer att skicka förfrågningar till",
 	"What’s New in": "Vad är nytt i",
 	"What’s New in": "Vad är nytt i",
 	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "När historiken är avstängd visas inte nya chattar i denna webbläsare i din historik på någon av dina enheter.",
 	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "När historiken är avstängd visas inte nya chattar i denna webbläsare i din historik på någon av dina enheter.",
-	"Whisper (Local)": "",
-	"Widescreen Mode": "",
-	"Workspace": "arbetsyta",
-	"Write a prompt suggestion (e.g. Who are you?)": "Skriv ett förslag (t.ex. Vem är du?)",
+	"Whisper (Local)": "Whisper (lokal)",
+	"Widescreen Mode": "Bredbildsläge",
+	"Workspace": "Arbetsyta",
+	"Write a prompt suggestion (e.g. Who are you?)": "Skriv ett instruktionsförslag (t.ex. Vem är du?)",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Skriv en sammanfattning på 50 ord som sammanfattar [ämne eller nyckelord].",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Skriv en sammanfattning på 50 ord som sammanfattar [ämne eller nyckelord].",
-	"Yesterday": "Igenom",
-	"You": "du",
-	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
+	"Yesterday": "Igår",
+	"You": "Dig",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Du kan anpassa dina interaktioner med stora språkmodeller genom att lägga till minnen via knappen 'Hantera' nedan, så att de blir mer användbara och skräddarsydda för dig.",
 	"You cannot clone a base model": "Du kan inte klona en basmodell",
 	"You cannot clone a base model": "Du kan inte klona en basmodell",
-	"You have no archived conversations.": "Du har inga arkiverade konversationer.",
+	"You have no archived conversations.": "Du har inga arkiverade samtal.",
 	"You have shared this chat": "Du har delat denna chatt",
 	"You have shared this chat": "Du har delat denna chatt",
 	"You're a helpful assistant.": "Du är en hjälpsam assistent.",
 	"You're a helpful assistant.": "Du är en hjälpsam assistent.",
 	"You're now logged in.": "Du är nu inloggad.",
 	"You're now logged in.": "Du är nu inloggad.",
-	"Your account status is currently pending activation.": "",
+	"Your account status is currently pending activation.": "Ditt konto väntar på att bli aktiverat",
 	"Youtube": "Youtube",
 	"Youtube": "Youtube",
 	"Youtube Loader Settings": "Youtube Loader-inställningar"
 	"Youtube Loader Settings": "Youtube Loader-inställningar"
 }
 }

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

@@ -69,6 +69,7 @@
 	"Bad Response": "",
 	"Bad Response": "",
 	"Banners": "",
 	"Banners": "",
 	"Base Model (From)": "",
 	"Base Model (From)": "",
+	"Batch Size (num_batch)": "",
 	"before": "",
 	"before": "",
 	"Being lazy": "",
 	"Being lazy": "",
 	"Brave Search API Key": "",
 	"Brave Search API Key": "",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore custom prompts": "",
 	"Discover, download, and explore model presets": "",
 	"Discover, download, and explore model presets": "",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "",
 	"Display the username instead of You in the Chat": "",
 	"Document": "",
 	"Document": "",
 	"Document Settings": "",
 	"Document Settings": "",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter stop sequence": "",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -488,6 +491,7 @@
 	"System": "",
 	"System": "",
 	"System Prompt": "",
 	"System Prompt": "",
 	"Tags": "",
 	"Tags": "",
+	"Tavily API Key": "",
 	"Tell us more:": "",
 	"Tell us more:": "",
 	"Temperature": "",
 	"Temperature": "",
 	"Template": "",
 	"Template": "",
@@ -518,6 +522,7 @@
 	"Today": "",
 	"Today": "",
 	"Toggle settings": "",
 	"Toggle settings": "",
 	"Toggle sidebar": "",
 	"Toggle sidebar": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "",
 	"Top K": "",
 	"Top P": "",
 	"Top P": "",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Kötü Yanıt",
 	"Bad Response": "Kötü Yanıt",
 	"Banners": "Afişler",
 	"Banners": "Afişler",
 	"Base Model (From)": "Temel Model ('den)",
 	"Base Model (From)": "Temel Model ('den)",
+	"Batch Size (num_batch)": "",
 	"before": "önce",
 	"before": "önce",
 	"Being lazy": "Tembelleşiyor",
 	"Being lazy": "Tembelleşiyor",
 	"Brave Search API Key": "Brave Search API Anahtarı",
 	"Brave Search API Key": "Brave Search API Anahtarı",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Özel promptları keşfedin, indirin ve inceleyin",
 	"Discover, download, and explore custom prompts": "Özel promptları keşfedin, indirin ve inceleyin",
 	"Discover, download, and explore model presets": "Model ön ayarlarını keşfedin, indirin ve inceleyin",
 	"Discover, download, and explore model presets": "Model ön ayarlarını keşfedin, indirin ve inceleyin",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Sohbet'te Siz yerine kullanıcı adını göster",
 	"Display the username instead of You in the Chat": "Sohbet'te Siz yerine kullanıcı adını göster",
 	"Document": "Belge",
 	"Document": "Belge",
 	"Document Settings": "Belge Ayarları",
 	"Document Settings": "Belge Ayarları",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Serpstack API Anahtarını Girin",
 	"Enter Serpstack API Key": "Serpstack API Anahtarını Girin",
 	"Enter stop sequence": "Durdurma dizisini girin",
 	"Enter stop sequence": "Durdurma dizisini girin",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Top K'yı girin",
 	"Enter Top K": "Top K'yı girin",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL'yi Girin (örn. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL'yi Girin (örn. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL'yi Girin (e.g. http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "URL'yi Girin (e.g. http://localhost:11434)",
@@ -488,6 +491,7 @@
 	"System": "Sistem",
 	"System": "Sistem",
 	"System Prompt": "Sistem Promptu",
 	"System Prompt": "Sistem Promptu",
 	"Tags": "Etiketler",
 	"Tags": "Etiketler",
+	"Tavily API Key": "",
 	"Tell us more:": "Bize daha fazlasını anlat:",
 	"Tell us more:": "Bize daha fazlasını anlat:",
 	"Temperature": "Temperature",
 	"Temperature": "Temperature",
 	"Template": "Şablon",
 	"Template": "Şablon",
@@ -518,6 +522,7 @@
 	"Today": "Bugün",
 	"Today": "Bugün",
 	"Toggle settings": "Ayarları Aç/Kapat",
 	"Toggle settings": "Ayarları Aç/Kapat",
 	"Toggle sidebar": "Kenar Çubuğunu Aç/Kapat",
 	"Toggle sidebar": "Kenar Çubuğunu Aç/Kapat",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Неправильна відповідь",
 	"Bad Response": "Неправильна відповідь",
 	"Banners": "Прапори",
 	"Banners": "Прапори",
 	"Base Model (From)": "Базова модель (від)",
 	"Base Model (From)": "Базова модель (від)",
+	"Batch Size (num_batch)": "",
 	"before": "до того, як",
 	"before": "до того, як",
 	"Being lazy": "Не поспішати",
 	"Being lazy": "Не поспішати",
 	"Brave Search API Key": "Ключ API пошуку Brave",
 	"Brave Search API Key": "Ключ API пошуку Brave",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Знайдіть, завантажте та досліджуйте налаштовані промти",
 	"Discover, download, and explore custom prompts": "Знайдіть, завантажте та досліджуйте налаштовані промти",
 	"Discover, download, and explore model presets": "Знайдіть, завантажте та досліджуйте налаштовані налаштування моделі",
 	"Discover, download, and explore model presets": "Знайдіть, завантажте та досліджуйте налаштовані налаштування моделі",
 	"Dismissible": "Неприйнятно",
 	"Dismissible": "Неприйнятно",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Показувати ім'я користувача замість 'Ви' в чаті",
 	"Display the username instead of You in the Chat": "Показувати ім'я користувача замість 'Ви' в чаті",
 	"Document": "Документ",
 	"Document": "Документ",
 	"Document Settings": "Налаштування документа",
 	"Document Settings": "Налаштування документа",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "Введіть ключ API Serpstack",
 	"Enter Serpstack API Key": "Введіть ключ API Serpstack",
 	"Enter stop sequence": "Введіть символ зупинки",
 	"Enter stop sequence": "Введіть символ зупинки",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Введіть Top K",
 	"Enter Top K": "Введіть Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введіть URL-адресу (напр., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введіть URL-адресу (напр., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Введіть URL-адресу (напр., http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Введіть URL-адресу (напр., http://localhost:11434)",
@@ -490,6 +493,7 @@
 	"System": "Система",
 	"System": "Система",
 	"System Prompt": "Системний промт",
 	"System Prompt": "Системний промт",
 	"Tags": "Теги",
 	"Tags": "Теги",
+	"Tavily API Key": "",
 	"Tell us more:": "Розкажи нам більше:",
 	"Tell us more:": "Розкажи нам більше:",
 	"Temperature": "Температура",
 	"Temperature": "Температура",
 	"Template": "Шаблон",
 	"Template": "Шаблон",
@@ -520,6 +524,7 @@
 	"Today": "Сьогодні",
 	"Today": "Сьогодні",
 	"Toggle settings": "Переключити налаштування",
 	"Toggle settings": "Переключити налаштування",
 	"Toggle sidebar": "Переключити бокову панель",
 	"Toggle sidebar": "Переключити бокову панель",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "Trả lời KHÔNG tốt",
 	"Bad Response": "Trả lời KHÔNG tốt",
 	"Banners": "Biểu ngữ",
 	"Banners": "Biểu ngữ",
 	"Base Model (From)": "Mô hình cơ sở (từ)",
 	"Base Model (From)": "Mô hình cơ sở (từ)",
+	"Batch Size (num_batch)": "",
 	"before": "trước",
 	"before": "trước",
 	"Being lazy": "Lười biếng",
 	"Being lazy": "Lười biếng",
 	"Brave Search API Key": "Khóa API tìm kiếm dũng cảm",
 	"Brave Search API Key": "Khóa API tìm kiếm dũng cảm",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "Tìm kiếm, tải về và khám phá thêm các prompt tùy chỉnh",
 	"Discover, download, and explore custom prompts": "Tìm kiếm, tải về và khám phá thêm các prompt tùy chỉnh",
 	"Discover, download, and explore model presets": "Tìm kiếm, tải về và khám phá thêm các thiết lập mô hình sẵn",
 	"Discover, download, and explore model presets": "Tìm kiếm, tải về và khám phá thêm các thiết lập mô hình sẵn",
 	"Dismissible": "Có thể loại bỏ",
 	"Dismissible": "Có thể loại bỏ",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "Hiển thị tên người sử dụng thay vì 'Bạn' trong nội dung chat",
 	"Display the username instead of You in the Chat": "Hiển thị tên người sử dụng thay vì 'Bạn' trong nội dung chat",
 	"Document": "Tài liệu",
 	"Document": "Tài liệu",
 	"Document Settings": "Cấu hình kho tài liệu",
 	"Document Settings": "Cấu hình kho tài liệu",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "Nhập Serply API Key",
 	"Enter Serply API Key": "Nhập Serply API Key",
 	"Enter Serpstack API Key": "Nhập Serpstack API Key",
 	"Enter Serpstack API Key": "Nhập Serpstack API Key",
 	"Enter stop sequence": "Nhập stop sequence",
 	"Enter stop sequence": "Nhập stop sequence",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "Nhập Top K",
 	"Enter Top K": "Nhập Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Nhập URL (vd: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Nhập URL (vd: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Nhập URL (vd: http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "Nhập URL (vd: http://localhost:11434)",
@@ -487,6 +490,7 @@
 	"System": "Hệ thống",
 	"System": "Hệ thống",
 	"System Prompt": "Prompt Hệ thống (System Prompt)",
 	"System Prompt": "Prompt Hệ thống (System Prompt)",
 	"Tags": "Thẻ",
 	"Tags": "Thẻ",
+	"Tavily API Key": "",
 	"Tell us more:": "Hãy cho chúng tôi hiểu thêm về chất lượng của câu trả lời:",
 	"Tell us more:": "Hãy cho chúng tôi hiểu thêm về chất lượng của câu trả lời:",
 	"Temperature": "Mức độ sáng tạo",
 	"Temperature": "Mức độ sáng tạo",
 	"Template": "Mẫu",
 	"Template": "Mẫu",
@@ -517,6 +521,7 @@
 	"Today": "Hôm nay",
 	"Today": "Hôm nay",
 	"Toggle settings": "Bật/tắt cài đặt",
 	"Toggle settings": "Bật/tắt cài đặt",
 	"Toggle sidebar": "Bật/tắt thanh bên",
 	"Toggle sidebar": "Bật/tắt thanh bên",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

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

@@ -33,7 +33,7 @@
 	"Admin": "管理员联系方式",
 	"Admin": "管理员联系方式",
 	"Admin Panel": "管理员面板",
 	"Admin Panel": "管理员面板",
 	"Admin Settings": "管理员设置",
 	"Admin Settings": "管理员设置",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理员拥有所有工具的访问权限;用户则需在工作空间中为每个模型单独分配工具。",
 	"Advanced Parameters": "高级参数",
 	"Advanced Parameters": "高级参数",
 	"Advanced Params": "高级参数",
 	"Advanced Params": "高级参数",
 	"all": "所有",
 	"all": "所有",
@@ -69,6 +69,7 @@
 	"Bad Response": "点踩回复",
 	"Bad Response": "点踩回复",
 	"Banners": "公告横幅",
 	"Banners": "公告横幅",
 	"Base Model (From)": "基础模型 (来自)",
 	"Base Model (From)": "基础模型 (来自)",
+	"Batch Size (num_batch)": "批大小 (num_batch)",
 	"before": "对话",
 	"before": "对话",
 	"Being lazy": "懒惰",
 	"Being lazy": "懒惰",
 	"Brave Search API Key": "Brave Search API 密钥",
 	"Brave Search API Key": "Brave Search API 密钥",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "发现、下载并探索更多自定义提示词",
 	"Discover, download, and explore custom prompts": "发现、下载并探索更多自定义提示词",
 	"Discover, download, and explore model presets": "发现、下载并探索更多模型预设",
 	"Discover, download, and explore model presets": "发现、下载并探索更多模型预设",
 	"Dismissible": "是否可关闭",
 	"Dismissible": "是否可关闭",
+	"Display Emoji in Call": "在通话中显示 Emoji 表情符号",
 	"Display the username instead of You in the Chat": "在对话中显示用户名而不是“你”",
 	"Display the username instead of You in the Chat": "在对话中显示用户名而不是“你”",
 	"Document": "文档",
 	"Document": "文档",
 	"Document Settings": "文档设置",
 	"Document Settings": "文档设置",
@@ -202,9 +204,10 @@
 	"Enter Score": "输入评分",
 	"Enter Score": "输入评分",
 	"Enter Searxng Query URL": "输入 Searxng 查询地址",
 	"Enter Searxng Query URL": "输入 Searxng 查询地址",
 	"Enter Serper API Key": "输入 Serper API 密钥",
 	"Enter Serper API Key": "输入 Serper API 密钥",
-	"Enter Serply API Key": "",
+	"Enter Serply API Key": "输入 Serply API 密钥",
 	"Enter Serpstack API Key": "输入 Serpstack API 密钥",
 	"Enter Serpstack API Key": "输入 Serpstack API 密钥",
 	"Enter stop sequence": "输入停止序列 (Stop Sequence)",
 	"Enter stop sequence": "输入停止序列 (Stop Sequence)",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "输入 Top K",
 	"Enter Top K": "输入 Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)",
@@ -424,7 +427,7 @@
 	"Search Query Generation Prompt Length Threshold": "搜索查询生成提示长度阈值",
 	"Search Query Generation Prompt Length Threshold": "搜索查询生成提示长度阈值",
 	"Search Result Count": "搜索结果数量",
 	"Search Result Count": "搜索结果数量",
 	"Search Tools": "搜索工具",
 	"Search Tools": "搜索工具",
-	"Searched {{count}} sites_other": "检索到 {{count}} 个网站",
+	"Searched {{count}} sites_other": "搜索到 {{count}} 个结果",
 	"Searching \"{{searchQuery}}\"": "搜索 \"{{searchQuery}}\" 中",
 	"Searching \"{{searchQuery}}\"": "搜索 \"{{searchQuery}}\" 中",
 	"Searxng Query URL": "Searxng 查询 URL",
 	"Searxng Query URL": "Searxng 查询 URL",
 	"See readme.md for instructions": "查看 readme.md 以获取说明",
 	"See readme.md for instructions": "查看 readme.md 以获取说明",
@@ -487,6 +490,7 @@
 	"System": "系统",
 	"System": "系统",
 	"System Prompt": "系统提示词",
 	"System Prompt": "系统提示词",
 	"Tags": "标签",
 	"Tags": "标签",
+	"Tavily API Key": "",
 	"Tell us more:": "请告诉我们更多细节",
 	"Tell us more:": "请告诉我们更多细节",
 	"Temperature": "温度 (Temperature)",
 	"Temperature": "温度 (Temperature)",
 	"Template": "模板",
 	"Template": "模板",
@@ -513,10 +517,11 @@
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "请联系管理员以访问。管理员可以在后台管理面板中管理用户状态。",
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "请联系管理员以访问。管理员可以在后台管理面板中管理用户状态。",
 	"To add documents here, upload them to the \"Documents\" workspace first.": "要在此处添加文档,请先将它们上传到工作空间中的“文档”内。",
 	"To add documents here, upload them to the \"Documents\" workspace first.": "要在此处添加文档,请先将它们上传到工作空间中的“文档”内。",
 	"to chat input.": "到对话输入。",
 	"to chat input.": "到对话输入。",
-	"To select toolkits here, add them to the \"Tools\" workspace first.": "",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "要在这里选择工具包,请先将它们添加到工作空间中的“工具”。",
 	"Today": "今天",
 	"Today": "今天",
 	"Toggle settings": "切换设置",
 	"Toggle settings": "切换设置",
 	"Toggle sidebar": "切换侧边栏",
 	"Toggle sidebar": "切换侧边栏",
+	"Tokens To Keep On Context Refresh (num_keep)": "在语境刷新时需保留的 Tokens",
 	"Tools": "工具",
 	"Tools": "工具",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",
@@ -555,7 +560,7 @@
 	"Web Loader Settings": "网页爬取设置",
 	"Web Loader Settings": "网页爬取设置",
 	"Web Params": "网络爬取设置",
 	"Web Params": "网络爬取设置",
 	"Web Search": "网络搜索",
 	"Web Search": "网络搜索",
-	"Web Search Engine": "Web 搜索引擎",
+	"Web Search Engine": "网络搜索引擎",
 	"Webhook URL": "Webhook URL",
 	"Webhook URL": "Webhook URL",
 	"WebUI Add-ons": "WebUI 附加组件",
 	"WebUI Add-ons": "WebUI 附加组件",
 	"WebUI Settings": "WebUI 设置",
 	"WebUI Settings": "WebUI 设置",

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

@@ -69,6 +69,7 @@
 	"Bad Response": "錯誤回應",
 	"Bad Response": "錯誤回應",
 	"Banners": "橫幅",
 	"Banners": "橫幅",
 	"Base Model (From)": "基本模型(來自)",
 	"Base Model (From)": "基本模型(來自)",
+	"Batch Size (num_batch)": "",
 	"before": "前",
 	"before": "前",
 	"Being lazy": "懶人模式",
 	"Being lazy": "懶人模式",
 	"Brave Search API Key": "搜尋 API Key",
 	"Brave Search API Key": "搜尋 API Key",
@@ -160,6 +161,7 @@
 	"Discover, download, and explore custom prompts": "發現、下載並探索他人設置的提示詞",
 	"Discover, download, and explore custom prompts": "發現、下載並探索他人設置的提示詞",
 	"Discover, download, and explore model presets": "發現、下載並探索他人設置的模型",
 	"Discover, download, and explore model presets": "發現、下載並探索他人設置的模型",
 	"Dismissible": "",
 	"Dismissible": "",
+	"Display Emoji in Call": "",
 	"Display the username instead of You in the Chat": "在聊天中顯示使用者名稱而不是「你」",
 	"Display the username instead of You in the Chat": "在聊天中顯示使用者名稱而不是「你」",
 	"Document": "文件",
 	"Document": "文件",
 	"Document Settings": "文件設定",
 	"Document Settings": "文件設定",
@@ -205,6 +207,7 @@
 	"Enter Serply API Key": "",
 	"Enter Serply API Key": "",
 	"Enter Serpstack API Key": "輸入 Serpstack API Key",
 	"Enter Serpstack API Key": "輸入 Serpstack API Key",
 	"Enter stop sequence": "輸入停止序列",
 	"Enter stop sequence": "輸入停止序列",
+	"Enter Tavily API Key": "",
 	"Enter Top K": "輸入 Top K",
 	"Enter Top K": "輸入 Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "輸入 URL(例如 http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "輸入 URL(例如 http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "輸入 URL(例如 http://localhost:11434)",
 	"Enter URL (e.g. http://localhost:11434)": "輸入 URL(例如 http://localhost:11434)",
@@ -487,6 +490,7 @@
 	"System": "系統",
 	"System": "系統",
 	"System Prompt": "系統提示詞",
 	"System Prompt": "系統提示詞",
 	"Tags": "標籤",
 	"Tags": "標籤",
+	"Tavily API Key": "",
 	"Tell us more:": "告訴我們更多:",
 	"Tell us more:": "告訴我們更多:",
 	"Temperature": "溫度",
 	"Temperature": "溫度",
 	"Template": "模板",
 	"Template": "模板",
@@ -517,6 +521,7 @@
 	"Today": "今天",
 	"Today": "今天",
 	"Toggle settings": "切換設定",
 	"Toggle settings": "切換設定",
 	"Toggle sidebar": "切換側邊欄",
 	"Toggle sidebar": "切換側邊欄",
+	"Tokens To Keep On Context Refresh (num_keep)": "",
 	"Tools": "",
 	"Tools": "",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",

+ 2 - 0
src/lib/stores/index.ts

@@ -92,6 +92,8 @@ type Settings = {
 	top_k?: string;
 	top_k?: string;
 	top_p?: string;
 	top_p?: string;
 	num_ctx?: string;
 	num_ctx?: string;
+	num_batch?: string;
+	num_keep?: string;
 	options?: ModelOptions;
 	options?: ModelOptions;
 };
 };
 
 

+ 19 - 1
src/lib/utils/index.ts

@@ -436,13 +436,31 @@ export const removeEmojis = (str) => {
 
 
 export const extractSentences = (text) => {
 export const extractSentences = (text) => {
 	// Split the paragraph into sentences based on common punctuation marks
 	// Split the paragraph into sentences based on common punctuation marks
-	const sentences = text.split(/(?<=[.!?])/);
+	const sentences = text.split(/(?<=[.!?])\s+/);
 
 
 	return sentences
 	return sentences
 		.map((sentence) => removeEmojis(sentence.trim()))
 		.map((sentence) => removeEmojis(sentence.trim()))
 		.filter((sentence) => sentence !== '');
 		.filter((sentence) => sentence !== '');
 };
 };
 
 
+export const extractSentencesForAudio = (text) => {
+	return extractSentences(text).reduce((mergedTexts, currentText) => {
+		const lastIndex = mergedTexts.length - 1;
+		if (lastIndex >= 0) {
+			const previousText = mergedTexts[lastIndex];
+			const wordCount = previousText.split(/\s+/).length;
+			if (wordCount < 2) {
+				mergedTexts[lastIndex] = previousText + ' ' + currentText;
+			} else {
+				mergedTexts.push(currentText);
+			}
+		} else {
+			mergedTexts.push(currentText);
+		}
+		return mergedTexts;
+	}, []);
+};
+
 export const blobToFile = (blob, fileName) => {
 export const blobToFile = (blob, fileName) => {
 	// Create a new File object from the Blob
 	// Create a new File object from the Blob
 	const file = new File([blob], fileName, { type: blob.type });
 	const file = new File([blob], fileName, { type: blob.type });

+ 11 - 1
src/routes/(app)/admin/+page.svelte

@@ -18,6 +18,7 @@
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import UserChatsModal from '$lib/components/admin/UserChatsModal.svelte';
 	import UserChatsModal from '$lib/components/admin/UserChatsModal.svelte';
 	import AddUserModal from '$lib/components/admin/AddUserModal.svelte';
 	import AddUserModal from '$lib/components/admin/AddUserModal.svelte';
+	import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -30,6 +31,7 @@
 
 
 	let page = 1;
 	let page = 1;
 
 
+	let showDeleteConfirmDialog = false;
 	let showAddUserModal = false;
 	let showAddUserModal = false;
 
 
 	let showUserChatsModal = false;
 	let showUserChatsModal = false;
@@ -77,6 +79,13 @@
 	});
 	});
 </script>
 </script>
 
 
+<ConfirmDialog
+	bind:show={showDeleteConfirmDialog}
+	on:confirm={() => {
+		deleteUserHandler(selectedUser.id);
+	}}
+/>
+
 {#key selectedUser}
 {#key selectedUser}
 	<EditUserModal
 	<EditUserModal
 		bind:show={showEditUserModal}
 		bind:show={showEditUserModal}
@@ -256,7 +265,8 @@
 										<button
 										<button
 											class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 											class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 											on:click={async () => {
 											on:click={async () => {
-												deleteUserHandler(user.id);
+												showDeleteConfirmDialog = true;
+												selectedUser = user;
 											}}
 											}}
 										>
 										>
 											<svg
 											<svg