From 8e9e429a912725ffdfc0aaa85af37f420e87a3c4 Mon Sep 17 00:00:00 2001 From: arkohut <39525455+arkohut@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:19:16 +0800 Subject: [PATCH 01/20] fix: tolerant readonly filesystem for copy favicon to static dir --- backend/config.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/config.py b/backend/config.py index fcced4f613..9ee1460407 100644 --- a/backend/config.py +++ b/backend/config.py @@ -310,6 +310,12 @@ if frontend_favicon.exists(): shutil.copyfile(frontend_favicon, STATIC_DIR / "favicon.png") except PermissionError: logging.error(f"No write permission to {STATIC_DIR / 'favicon.png'}") + except OSError as e: + if e.errno == 30: # Read-only file system + logging.error(f"Read-only file system: {STATIC_DIR / 'favicon.png'}") + else: + logging.error(f"OS error occurred: {e}") + else: logging.warning(f"Frontend favicon not found at {frontend_favicon}") From efb4a710c80635cc0066fc060e5021de79732d1f Mon Sep 17 00:00:00 2001 From: teampen <136991215+teampen@users.noreply.github.com> Date: Sun, 9 Jun 2024 20:44:34 -0400 Subject: [PATCH 02/20] adding Serply as an alternative web search --- README.md | 2 +- backend/apps/rag/main.py | 19 +- backend/apps/rag/search/serply.py | 68 ++++++ backend/apps/rag/search/testdata/serply.json | 206 ++++++++++++++++++ .../documents/Settings/WebParams.svelte | 20 +- 5 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 backend/apps/rag/search/serply.py create mode 100644 backend/apps/rag/search/testdata/serply.json diff --git a/README.md b/README.md index a8d79bd5cd..af10c67bc5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,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. -- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, and `serper`, 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`, and [`Serply`](https://serply.io) 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. diff --git a/backend/apps/rag/main.py b/backend/apps/rag/main.py index d405ef0b4e..be55f0f95c 100644 --- a/backend/apps/rag/main.py +++ b/backend/apps/rag/main.py @@ -67,7 +67,7 @@ from apps.rag.search.main import SearchResult from apps.rag.search.searxng import search_searxng from apps.rag.search.serper import search_serper from apps.rag.search.serpstack import search_serpstack - +from apps.rag.search.serply import search_serply from utils.misc import ( calculate_sha256, @@ -113,6 +113,7 @@ from config import ( SERPSTACK_API_KEY, SERPSTACK_HTTPS, SERPER_API_KEY, + SERPLY_API_KEY, RAG_WEB_SEARCH_RESULT_COUNT, RAG_WEB_SEARCH_CONCURRENT_REQUESTS, RAG_EMBEDDING_OPENAI_BATCH_SIZE, @@ -165,6 +166,7 @@ app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS app.state.config.SERPER_API_KEY = SERPER_API_KEY +app.state.config.SERPLY_API_KEY = SERPLY_API_KEY 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 @@ -392,6 +394,7 @@ async def get_rag_config(user=Depends(get_admin_user)): "serpstack_api_key": app.state.config.SERPSTACK_API_KEY, "serpstack_https": app.state.config.SERPSTACK_HTTPS, "serper_api_key": app.state.config.SERPER_API_KEY, + "serply_api_key": app.state.config.SERPLY_API_KEY, "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT, "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS, }, @@ -419,6 +422,7 @@ class WebSearchConfig(BaseModel): serpstack_api_key: Optional[str] = None serpstack_https: Optional[bool] = None serper_api_key: Optional[str] = None + serply_api_key: Optional[str] = None result_count: Optional[int] = None concurrent_requests: Optional[int] = None @@ -469,6 +473,7 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_ app.state.config.SERPSTACK_API_KEY = form_data.web.search.serpstack_api_key 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.SERPLY_API_KEY = form_data.web.search.serply_api_key app.state.config.RAG_WEB_SEARCH_RESULT_COUNT = form_data.web.search.result_count app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS = ( form_data.web.search.concurrent_requests @@ -497,6 +502,7 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_ "serpstack_api_key": app.state.config.SERPSTACK_API_KEY, "serpstack_https": app.state.config.SERPSTACK_HTTPS, "serper_api_key": app.state.config.SERPER_API_KEY, + "serply_api_key": app.state.config.SERPLY_API_KEY, "result_count": app.state.config.RAG_WEB_SEARCH_RESULT_COUNT, "concurrent_requests": app.state.config.RAG_WEB_SEARCH_CONCURRENT_REQUESTS, }, @@ -744,6 +750,7 @@ def search_web(engine: str, query: str) -> list[SearchResult]: - BRAVE_SEARCH_API_KEY - SERPSTACK_API_KEY - SERPER_API_KEY + - SERPLY_API_KEY Args: query (str): The query to search for @@ -802,6 +809,15 @@ def search_web(engine: str, query: str) -> list[SearchResult]: ) else: raise Exception("No SERPER_API_KEY found in environment variables") + elif engine == "serply": + if app.state.config.SERPLY_API_KEY: + return search_serply( + app.state.config.SERPLY_API_KEY, + query, + app.state.config.RAG_WEB_SEARCH_RESULT_COUNT, + ) + else: + raise Exception("No SERPLY_API_KEY found in environment variables") else: raise Exception("No search engine API key found in environment variables") @@ -809,6 +825,7 @@ def search_web(engine: str, query: str) -> list[SearchResult]: @app.post("/web/search") def store_web_search(form_data: SearchForm, user=Depends(get_current_user)): try: + logging.info(f"trying to web search with {app.state.config.RAG_WEB_SEARCH_ENGINE, form_data.query}") web_results = search_web( app.state.config.RAG_WEB_SEARCH_ENGINE, form_data.query ) diff --git a/backend/apps/rag/search/serply.py b/backend/apps/rag/search/serply.py new file mode 100644 index 0000000000..12d5e51d26 --- /dev/null +++ b/backend/apps/rag/search/serply.py @@ -0,0 +1,68 @@ +import json +import logging + +import requests +from urllib.parse import urlencode + +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_serply( + api_key: str, + query: str, + count: int, + hl: str = "us", + limit: int = 10, + device_type: str = "desktop", + proxy_location: str = "US" + ) -> list[SearchResult]: + """Search using serper.dev's API and return the results as a list of SearchResult objects. + + Args: + api_key (str): A serply.io API key + query (str): The query to search for + hl (str): Host Language code to display results in (reference https://developers.google.com/custom-search/docs/xml_results?hl=en#wsInterfaceLanguages) + limit (int): The maximum number of results to return [10-100, defaults to 10] + """ + log.info("Searching with Serply") + + url = "https://api.serply.io/v1/search/" + + query_payload = { + "q": query, + "language": "en", + "num": limit, + "gl": proxy_location.upper(), + "hl": hl.lower() + } + + url = f"{url}{urlencode(query_payload)}" + headers = { + "X-API-KEY": api_key, + "X-User-Agent": device_type, + "User-Agent": "open-webui", + "X-Proxy-Location": proxy_location + } + + response = requests.request("GET", url, headers=headers) + response.raise_for_status() + + json_response = response.json() + log.info(f"results from serply search: {json_response}") + + results = sorted( + json_response.get("results", []), key=lambda x: x.get("realPosition", 0) + ) + + return [ + SearchResult( + link=result["link"], + title=result.get("title"), + snippet=result.get("description"), + ) + for result in results[:count] + ] diff --git a/backend/apps/rag/search/testdata/serply.json b/backend/apps/rag/search/testdata/serply.json new file mode 100644 index 0000000000..7d575de40c --- /dev/null +++ b/backend/apps/rag/search/testdata/serply.json @@ -0,0 +1,206 @@ +{ + "ads": [], + "ads_count": 0, + "answers": [], + "results": [ + { + "title": "Apple", + "link": "https://www.apple.com/", + "description": "Discover the innovative world of Apple and shop everything iPhone, iPad, Apple Watch, Mac, and Apple TV, plus explore accessories, entertainment, ...", + "additional_links": [ + { + "text": "AppleApplehttps://www.apple.com", + "href": "https://www.apple.com/" + } + ], + "cite": {}, + "subdomains": [ + { + "title": "Support", + "link": "https://support.apple.com/", + "description": "SupportContact - iPhone Support - Billing and Subscriptions - Apple Repair" + }, + { + "title": "Store", + "link": "https://www.apple.com/store", + "description": "StoreShop iPhone - Shop iPad - App Store - Shop Mac - ..." + }, + { + "title": "Mac", + "link": "https://www.apple.com/mac/", + "description": "MacMacBook Air - MacBook Pro - iMac - Compare Mac models - Mac mini" + }, + { + "title": "iPad", + "link": "https://www.apple.com/ipad/", + "description": "iPadShop iPad - iPad Pro - iPad Air - Compare iPad models - ..." + }, + { + "title": "Watch", + "link": "https://www.apple.com/watch/", + "description": "WatchShop Apple Watch - Series 9 - SE - Ultra 2 - Nike - Hermès - ..." + } + ], + "realPosition": 1 + }, + { + "title": "Apple", + "link": "https://www.apple.com/", + "description": "Discover the innovative world of Apple and shop everything iPhone, iPad, Apple Watch, Mac, and Apple TV, plus explore accessories, entertainment, ...", + "additional_links": [ + { + "text": "AppleApplehttps://www.apple.com", + "href": "https://www.apple.com/" + } + ], + "cite": {}, + "realPosition": 2 + }, + { + "title": "Apple Inc.", + "link": "https://en.wikipedia.org/wiki/Apple_Inc.", + "description": "Apple Inc. (formerly Apple Computer, Inc.) is an American multinational corporation and technology company headquartered in Cupertino, California, ...", + "additional_links": [ + { + "text": "Apple Inc.Wikipediahttps://en.wikipedia.org › wiki › Apple_Inc", + "href": "https://en.wikipedia.org/wiki/Apple_Inc." + }, + { + "text": "", + "href": "https://en.wikipedia.org/wiki/Apple_Inc." + }, + { + "text": "History", + "href": "https://en.wikipedia.org/wiki/History_of_Apple_Inc." + }, + { + "text": "List of Apple products", + "href": "https://en.wikipedia.org/wiki/List_of_Apple_products" + }, + { + "text": "Litigation involving Apple Inc.", + "href": "https://en.wikipedia.org/wiki/Litigation_involving_Apple_Inc." + }, + { + "text": "Apple Park", + "href": "https://en.wikipedia.org/wiki/Apple_Park" + } + ], + "cite": { + "domain": "https://en.wikipedia.org › wiki › Apple_Inc", + "span": " › wiki › Apple_Inc" + }, + "realPosition": 3 + }, + { + "title": "Apple Inc. (AAPL) Company Profile & Facts", + "link": "https://finance.yahoo.com/quote/AAPL/profile/", + "description": "Apple Inc. designs, manufactures, and markets smartphones, personal computers, tablets, wearables, and accessories worldwide. The company offers iPhone, a line ...", + "additional_links": [ + { + "text": "Apple Inc. (AAPL) Company Profile & FactsYahoo Financehttps://finance.yahoo.com › quote › AAPL › profile", + "href": "https://finance.yahoo.com/quote/AAPL/profile/" + } + ], + "cite": { + "domain": "https://finance.yahoo.com › quote › AAPL › profile", + "span": " › quote › AAPL › profile" + }, + "realPosition": 4 + }, + { + "title": "Apple Inc - Company Profile and News", + "link": "https://www.bloomberg.com/profile/company/AAPL:US", + "description": "Apple Inc. Apple Inc. designs, manufactures, and markets smartphones, personal computers, tablets, wearables and accessories, and sells a variety of related ...", + "additional_links": [ + { + "text": "Apple Inc - Company Profile and NewsBloomberghttps://www.bloomberg.com › company › AAPL:US", + "href": "https://www.bloomberg.com/profile/company/AAPL:US" + }, + { + "text": "", + "href": "https://www.bloomberg.com/profile/company/AAPL:US" + } + ], + "cite": { + "domain": "https://www.bloomberg.com › company › AAPL:US", + "span": " › company › AAPL:US" + }, + "realPosition": 5 + }, + { + "title": "Apple Inc. | History, Products, Headquarters, & Facts", + "link": "https://www.britannica.com/money/Apple-Inc", + "description": "May 22, 2024 — Apple Inc. is an American multinational technology company that revolutionized the technology sector through its innovation of computer ...", + "additional_links": [ + { + "text": "Apple Inc. | History, Products, Headquarters, & FactsBritannicahttps://www.britannica.com › money › Apple-Inc", + "href": "https://www.britannica.com/money/Apple-Inc" + }, + { + "text": "", + "href": "https://www.britannica.com/money/Apple-Inc" + } + ], + "cite": { + "domain": "https://www.britannica.com › money › Apple-Inc", + "span": " › money › Apple-Inc" + }, + "realPosition": 6 + } + ], + "shopping_ads": [], + "places": [ + { + "title": "Apple Inc." + }, + { + "title": "Apple Inc" + }, + { + "title": "Apple Inc" + } + ], + "related_searches": { + "images": [], + "text": [ + { + "title": "apple inc full form", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Inc+full+form&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhPEAE" + }, + { + "title": "apple company history", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+company+history&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhOEAE" + }, + { + "title": "apple store", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Store&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhQEAE" + }, + { + "title": "apple id", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+id&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhSEAE" + }, + { + "title": "apple inc industry", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+Inc+industry&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhREAE" + }, + { + "title": "apple login", + "link": "https://www.google.com/search?sca_esv=6b6df170a5c9891b&sca_upv=1&q=Apple+login&sa=X&ved=2ahUKEwjLxuSJwM-GAxUHODQIHYuJBhgQ1QJ6BAhTEAE" + } + ] + }, + "image_results": [], + "carousel": [], + "total": 2450000000, + "knowledge_graph": "", + "related_questions": [ + "What does the Apple Inc do?", + "Why did Apple change to Apple Inc?", + "Who owns Apple Inc.?", + "What is Apple Inc best known for?" + ], + "carousel_count": 0, + "ts": 2.491065263748169, + "device_type": null +} \ No newline at end of file diff --git a/src/lib/components/documents/Settings/WebParams.svelte b/src/lib/components/documents/Settings/WebParams.svelte index 89d4442b06..7b3a2e434f 100644 --- a/src/lib/components/documents/Settings/WebParams.svelte +++ b/src/lib/components/documents/Settings/WebParams.svelte @@ -11,7 +11,7 @@ export let saveHandler: Function; let webConfig = null; - let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper']; + let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper', 'serply']; let youtubeLanguage = 'en'; let youtubeTranslation = null; @@ -188,6 +188,24 @@ + {:else if webConfig.search.engine === 'serply'} +
+
+ {$i18n.t('Serply API Key')} +
+ +
+
+ +
+
+
{/if} {/if} From 4dcec4855eb66ef3a4c4adc7b2fa31da21fd3c3c Mon Sep 17 00:00:00 2001 From: teampen <136991215+teampen@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:39:46 -0400 Subject: [PATCH 03/20] adding Serply as an alternative web search --- backend/config.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/config.py b/backend/config.py index dd3bc9e4b3..098de3b5a0 100644 --- a/backend/config.py +++ b/backend/config.py @@ -852,6 +852,12 @@ SERPER_API_KEY = PersistentConfig( os.getenv("SERPER_API_KEY", ""), ) +SERPLY_API_KEY = PersistentConfig( + "SERPLY_API_KEY", + "rag.web.search.serply_api_key", + os.getenv("SERPLY_API_KEY", ""), +) + RAG_WEB_SEARCH_RESULT_COUNT = PersistentConfig( "RAG_WEB_SEARCH_RESULT_COUNT", From 79bf8d6dd31dc17f37aea0bfb339b7150484050c Mon Sep 17 00:00:00 2001 From: teampen <136991215+teampen@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:43:13 -0400 Subject: [PATCH 04/20] undo changes to deprecated web search params --- .../documents/Settings/WebParams.svelte | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/lib/components/documents/Settings/WebParams.svelte b/src/lib/components/documents/Settings/WebParams.svelte index 7130c9c3b3..b5a4d1679d 100644 --- a/src/lib/components/documents/Settings/WebParams.svelte +++ b/src/lib/components/documents/Settings/WebParams.svelte @@ -188,24 +188,6 @@ - {:else if webConfig.search.engine === 'serply'} -
-
- {$i18n.t('Serply API Key')} -
- -
-
- -
-
-
{/if} {/if} From 14eb667fc8b332d1d8027aee510a4d2a40edb93a Mon Sep 17 00:00:00 2001 From: teampen <136991215+teampen@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:52:08 -0400 Subject: [PATCH 05/20] add changes to web search in admin settings --- .../admin/Settings/WebSearch.svelte | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib/components/admin/Settings/WebSearch.svelte b/src/lib/components/admin/Settings/WebSearch.svelte index 7013759fa2..eeafdce15a 100644 --- a/src/lib/components/admin/Settings/WebSearch.svelte +++ b/src/lib/components/admin/Settings/WebSearch.svelte @@ -11,7 +11,7 @@ export let saveHandler: Function; let webConfig = null; - let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper']; + let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper', 'serply']; let youtubeLanguage = 'en'; let youtubeTranslation = null; @@ -188,6 +188,24 @@ + {:else if webConfig.search.engine === 'serply'} +
+
+ {$i18n.t('Serply API Key')} +
+ +
+
+ +
+
+
{/if} {/if} From 2972774d872066fe179c0e255e9a9dc1a8603621 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 00:07:47 -0700 Subject: [PATCH 06/20] refac --- src/lib/components/chat/Chat.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index b09faf1103..49ba8961da 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -327,6 +327,9 @@ chatTextAreaElement.style.height = ''; } + const _files = JSON.parse(JSON.stringify(files)); + files = []; + prompt = ''; // Create user message @@ -338,7 +341,7 @@ role: 'user', user: _user ?? undefined, content: userPrompt, - files: files.length > 0 ? files : undefined, + files: _files.length > 0 ? _files : undefined, timestamp: Math.floor(Date.now() / 1000), // Unix epoch models: selectedModels.filter((m, mIdx) => selectedModels.indexOf(m) === mIdx) }; @@ -378,9 +381,6 @@ } await tick(); } - - files = []; - // Send prompt _responses = await sendPrompt(userPrompt, userMessageId); } From bf5a62298c4c87ff222b759e45d2dd195764fa6c Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 00:15:46 -0700 Subject: [PATCH 07/20] refac --- .../chat/MessageInput/CallOverlay.svelte | 2 +- .../chat/Messages/ResponseMessage.svelte | 149 +++++++++--------- 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/lib/components/chat/MessageInput/CallOverlay.svelte b/src/lib/components/chat/MessageInput/CallOverlay.svelte index 4fb7445736..295750c9ee 100644 --- a/src/lib/components/chat/MessageInput/CallOverlay.svelte +++ b/src/lib/components/chat/MessageInput/CallOverlay.svelte @@ -205,7 +205,7 @@ if (_responses.at(0)) { const content = _responses[0]; - if (content) { + if ((content ?? '').trim() !== '') { assistantSpeakingHandler(content); } } diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index 8c9ac7b4c5..7933c02157 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -211,93 +211,98 @@ speaking = null; speakingIdx = null; } else { - speaking = true; + if ((message?.content ?? '').trim() !== '') { + speaking = true; - if ($config.audio.tts.engine === 'openai') { - loadingSpeech = true; + if ($config.audio.tts.engine === 'openai') { + loadingSpeech = true; - const sentences = extractSentences(message.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; + const sentences = extractSentences(message.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; + } else { + mergedTexts.push(currentText); + } } else { mergedTexts.push(currentText); } - } else { - mergedTexts.push(currentText); + return mergedTexts; + }, []); + + console.log(sentences); + + sentencesAudio = sentences.reduce((a, e, i, arr) => { + a[i] = null; + return a; + }, {}); + + 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); + + speaking = null; + loadingSpeech = false; + + return null; + }); + + if (res) { + const blob = await res.blob(); + const blobUrl = URL.createObjectURL(blob); + const audio = new Audio(blobUrl); + sentencesAudio[idx] = audio; + loadingSpeech = false; + lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx)); + } } - return mergedTexts; - }, []); + } else { + let voices = []; + const getVoicesLoop = setInterval(async () => { + voices = await speechSynthesis.getVoices(); + if (voices.length > 0) { + clearInterval(getVoicesLoop); - console.log(sentences); + const voice = + voices + ?.filter( + (v) => + v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice) + ) + ?.at(0) ?? undefined; - sentencesAudio = sentences.reduce((a, e, i, arr) => { - a[i] = null; - return a; - }, {}); + console.log(voice); - let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately + const speak = new SpeechSynthesisUtterance(message.content); - 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); + console.log(speak); - speaking = null; - loadingSpeech = false; + speak.onend = () => { + speaking = null; + if ($settings.conversationMode) { + document.getElementById('voice-input-button')?.click(); + } + }; - return null; - }); + if (voice) { + speak.voice = voice; + } - if (res) { - const blob = await res.blob(); - const blobUrl = URL.createObjectURL(blob); - const audio = new Audio(blobUrl); - sentencesAudio[idx] = audio; - loadingSpeech = false; - lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx)); - } + speechSynthesis.speak(speak); + } + }, 100); } } else { - 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; - - console.log(voice); - - const speak = new SpeechSynthesisUtterance(message.content); - - console.log(speak); - - speak.onend = () => { - speaking = null; - if ($settings.conversationMode) { - document.getElementById('voice-input-button')?.click(); - } - }; - - if (voice) { - speak.voice = voice; - } - - speechSynthesis.speak(speak); - } - }, 100); + toast.error('No content to speak'); } } }; From 7349e1d8c8f5125d7f567e520b5e923c380f41f9 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 00:56:13 -0700 Subject: [PATCH 08/20] refac --- src/lib/components/chat/Chat.svelte | 129 +++++++++++++++------------- 1 file changed, 71 insertions(+), 58 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 49ba8961da..861b985a5d 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -358,29 +358,6 @@ // Wait until history/message have been updated await tick(); - // Create new chat if only one message in messages - if (messages.length == 1) { - if ($settings.saveChatHistory ?? true) { - chat = await createNewChat(localStorage.token, { - id: $chatId, - title: $i18n.t('New Chat'), - models: selectedModels, - system: $settings.system ?? undefined, - options: { - ...($settings.params ?? {}) - }, - messages: messages, - history: history, - tags: [], - timestamp: Date.now() - }); - await chats.set(await getChatList(localStorage.token)); - await chatId.set(chat.id); - } else { - await chatId.set('local'); - } - await tick(); - } // Send prompt _responses = await sendPrompt(userPrompt, userMessageId); } @@ -390,15 +367,78 @@ const sendPrompt = async (prompt, parentId, modelId = null) => { let _responses = []; + + // If modelId is provided, use it, else use selected model + let selectedModelIds = modelId + ? [modelId] + : atSelectedModel !== undefined + ? [atSelectedModel.id] + : selectedModels; + + // Create response messages for each selected model + const responseMessageIds = {}; + for (const modelId of selectedModelIds) { + const model = $models.filter((m) => m.id === modelId).at(0); + + if (model) { + let responseMessageId = uuidv4(); + let responseMessage = { + parentId: parentId, + id: responseMessageId, + childrenIds: [], + role: 'assistant', + content: '', + model: model.id, + modelName: model.name ?? model.id, + userContext: null, + timestamp: Math.floor(Date.now() / 1000) // Unix epoch + }; + + // Add message to history and Set currentId to messageId + history.messages[responseMessageId] = responseMessage; + history.currentId = responseMessageId; + + // Append messageId to childrenIds of parent message + if (parentId !== null) { + history.messages[parentId].childrenIds = [ + ...history.messages[parentId].childrenIds, + responseMessageId + ]; + } + + responseMessageIds[modelId] = responseMessageId; + } + } + await tick(); + + // Create new chat if only one message in messages + if (messages.length == 2) { + if ($settings.saveChatHistory ?? true) { + chat = await createNewChat(localStorage.token, { + id: $chatId, + title: $i18n.t('New Chat'), + models: selectedModels, + system: $settings.system ?? undefined, + options: { + ...($settings.params ?? {}) + }, + messages: messages, + history: history, + tags: [], + timestamp: Date.now() + }); + await chats.set(await getChatList(localStorage.token)); + await chatId.set(chat.id); + } else { + await chatId.set('local'); + } + await tick(); + } + const _chatId = JSON.parse(JSON.stringify($chatId)); await Promise.all( - (modelId - ? [modelId] - : atSelectedModel !== undefined - ? [atSelectedModel.id] - : selectedModels - ).map(async (modelId) => { + selectedModelIds.map(async (modelId) => { console.log('modelId', modelId); const model = $models.filter((m) => m.id === modelId).at(0); @@ -416,33 +456,8 @@ ); } - // Create response message - let responseMessageId = uuidv4(); - let responseMessage = { - parentId: parentId, - id: responseMessageId, - childrenIds: [], - role: 'assistant', - content: '', - model: model.id, - modelName: model.name ?? model.id, - userContext: null, - timestamp: Math.floor(Date.now() / 1000) // Unix epoch - }; - - // Add message to history and Set currentId to messageId - history.messages[responseMessageId] = responseMessage; - history.currentId = responseMessageId; - - // Append messageId to childrenIds of parent message - if (parentId !== null) { - history.messages[parentId].childrenIds = [ - ...history.messages[parentId].childrenIds, - responseMessageId - ]; - } - - await tick(); + let responseMessageId = responseMessageIds[modelId]; + let responseMessage = history.messages[responseMessageId]; let userContext = null; if ($settings?.memory ?? false) { @@ -451,7 +466,6 @@ toast.error(error); return null; }); - if (res) { if (res.documents[0].length > 0) { userContext = res.documents.reduce((acc, doc, index) => { @@ -477,7 +491,6 @@ } let _response = null; - if (model?.owned_by === 'openai') { _response = await sendPromptOpenAI(model, prompt, responseMessageId, _chatId); } else if (model) { From 140d7ff72149d97b1ef7e130c48f223020bd472b Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 01:07:24 -0700 Subject: [PATCH 09/20] refac --- .../chat/Settings/Advanced/AdvancedParams.svelte | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index 05a6aed140..7d5d773529 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -143,7 +143,6 @@ class=" bg-transparent text-center w-14" min="0" max="1" - step="0.05" /> @@ -235,7 +234,6 @@ class=" bg-transparent text-center w-14" min="0" max="1" - step="0.05" /> @@ -281,7 +279,6 @@ class=" bg-transparent text-center w-14" min="0" max="10" - step="0.5" /> @@ -327,7 +324,6 @@ class=" bg-transparent text-center w-14" min="0" max="100" - step="0.5" /> @@ -373,7 +369,6 @@ class=" bg-transparent text-center w-14" min="0" max="1" - step="0.05" /> @@ -419,7 +414,6 @@ class=" bg-transparent text-center w-14" min="0" max="2" - step="0.05" /> @@ -511,7 +505,6 @@ class=" bg-transparent text-center w-14" min="0" max="2" - step="0.05" /> From 3566002b0bc87cb7025be00a03e18818f62b8ace Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 10 Jun 2024 03:49:23 -0500 Subject: [PATCH 10/20] doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ef4a477de..5bce3ad06e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,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. -- 🔍 **Web Search for RAG**: Perform web searches using providers like `SearXNG`, `Google PSE`, `Brave Search`, `serpstack`, `serper`, and [`Serply`](https://serply.io) 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`, and `Serply` 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. From 48c9fb0ddf41a025375aaf90cccabb0d8331e515 Mon Sep 17 00:00:00 2001 From: Karl Lee <61072264+KarlLee830@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:02:52 +0800 Subject: [PATCH 11/20] Update Chinese translation --- .../components/workspace/Models/Knowledge.svelte | 4 ++-- src/lib/i18n/locales/zh-CN/translation.json | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/lib/components/workspace/Models/Knowledge.svelte b/src/lib/components/workspace/Models/Knowledge.svelte index f853925cc5..1a945a2760 100644 --- a/src/lib/components/workspace/Models/Knowledge.svelte +++ b/src/lib/components/workspace/Models/Knowledge.svelte @@ -13,7 +13,7 @@
- To add documents here, upload them to the "Documents" workspace first. + {$i18n.t('To add documents here, upload them to the "Documents" workspace first.')}
@@ -97,7 +97,7 @@ {$i18n.t('Select Documents')}
diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 3f13202be6..4b059ec7ef 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -74,7 +74,7 @@ "Bypass SSL verification for Websites": "绕过网站的 SSL 验证", "Call": "呼叫", "Call feature is not supported when using Web STT engine": "使用 Web 语音转文字引擎时不支持呼叫功能。", - "Camera": "", + "Camera": "摄像头", "Cancel": "取消", "Capabilities": "能力", "Change Password": "更改密码", @@ -246,6 +246,7 @@ "Hello, {{name}}": "你好,{{name}}", "Help": "帮助", "Hide": "隐藏", + "Hide Model": "隐藏模型", "How can I help you today?": "今天我能帮你做些什么?", "Hybrid Search": "混合搜索", "Image Generation (Experimental)": "图像生成(实验性)", @@ -273,7 +274,7 @@ "JWT Token": "JWT 令牌", "Keep Alive": "保持活动", "Keyboard shortcuts": "键盘快捷键", - "Knowledge": "", + "Knowledge": "知识库", "Language": "语言", "Last Active": "最后在线时间", "Light": "浅色", @@ -319,7 +320,7 @@ "Name your model": "为您的模型命名", "New Chat": "新对话", "New Password": "新密码", - "No documents found": "", + "No documents found": "未找到文档", "No results found": "未找到结果", "No search query generated": "未生成搜索查询", "No source available": "没有可用来源", @@ -416,8 +417,8 @@ "Search Documents": "搜索文档", "Search Models": "搜索模型", "Search Prompts": "搜索提示词", - "Search Query Generation Prompt": "", - "Search Query Generation Prompt Length Threshold": "", + "Search Query Generation Prompt": "搜索查询生成提示", + "Search Query Generation Prompt Length Threshold": "搜索查询生成提示长度阈值", "Search Result Count": "搜索结果数量", "Searched {{count}} sites_other": "检索到 {{count}} 个网站", "Searching the web for '{{searchQuery}}'": "在网络中搜索 '{{searchQuery}}' ", @@ -458,6 +459,7 @@ "Share to OpenWebUI Community": "分享到 OpenWebUI 社区", "short-summary": "简短总结", "Show": "显示", + "Show Model": "显示模型", "Show Admin Details in Account Pending Overlay": "在用户待激活界面中显示管理员邮箱等详细信息", "Show shortcuts": "显示快捷方式", "Showcased creativity": "很有创意", @@ -567,5 +569,7 @@ "You're now logged in.": "已登录。", "Your account status is currently pending activation.": "您的账号当前状态为待激活。", "Youtube": "YouTube", - "Youtube Loader Settings": "YouTube 爬取设置" + "Youtube Loader Settings": "YouTube 爬取设置", + "To add documents here, upload them to the \"Documents\" workspace first.": "要在此处添加文档,请先将它们上传到工作空间中的“文档”内。", + "Select Documents": "选择文档" } From d20f6cb45baf3416287e92229ac2e19dd7cb85da Mon Sep 17 00:00:00 2001 From: arkohut <39525455+arkohut@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:27:35 +0800 Subject: [PATCH 12/20] fix: use Exception to handle all errors --- backend/config.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/backend/config.py b/backend/config.py index 9ee1460407..0859d2b70c 100644 --- a/backend/config.py +++ b/backend/config.py @@ -308,13 +308,8 @@ frontend_favicon = FRONTEND_BUILD_DIR / "favicon.png" if frontend_favicon.exists(): try: shutil.copyfile(frontend_favicon, STATIC_DIR / "favicon.png") - except PermissionError: - logging.error(f"No write permission to {STATIC_DIR / 'favicon.png'}") - except OSError as e: - if e.errno == 30: # Read-only file system - logging.error(f"Read-only file system: {STATIC_DIR / 'favicon.png'}") - else: - logging.error(f"OS error occurred: {e}") + except Exception as e: + logging.error(f"An error occurred: {e}") else: logging.warning(f"Frontend favicon not found at {frontend_favicon}") From 2b87ab32ffe6f0ceee70a45eb6f8d3cf6b82d978 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Mon, 10 Jun 2024 15:27:06 +0100 Subject: [PATCH 13/20] Updated pt-PT translation --- src/lib/i18n/locales/pt-PT/translation.json | 422 ++++++++++---------- 1 file changed, 211 insertions(+), 211 deletions(-) diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index 0791452604..0a21b221fe 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -5,16 +5,16 @@ "(latest)": "(mais recente)", "{{ models }}": "{{ modelos }}", "{{ owner }}: You cannot delete a base model": "{{ owner }}: Não é possível excluir um modelo base", - "{{modelName}} is thinking...": "{{modelName}} está pensando...", + "{{modelName}} is thinking...": "{{modelName}} está a pensar...", "{{user}}'s Chats": "{{user}}'s Chats", "{{webUIName}} Backend Required": "{{webUIName}} Backend Necessário", "A task model is used when performing tasks such as generating titles for chats and web search queries": "Um modelo de tarefa é usado ao executar tarefas como gerar títulos para bate-papos e consultas de pesquisa na Web", - "a user": "um usuário", - "About": "Sobre", + "a user": "um utilizador", + "About": "Acerca de", "Account": "Conta", - "Account Activation Pending": "", + "Account Activation Pending": "Ativação da Conta Pendente", "Accurate information": "Informações precisas", - "Active Users": "", + "Active Users": "Utilizadores Ativos", "Add": "Adicionar", "Add a model id": "Adicionar um ID de modelo", "Add a short description about what this model does": "Adicione uma breve descrição sobre o que este modelo faz", @@ -22,30 +22,30 @@ "Add a tag": "Adicionar uma tag", "Add custom prompt": "Adicionar um prompt curto", "Add Docs": "Adicionar Documentos", - "Add Files": "Adicionar Arquivos", + "Add Files": "Adicionar Ficheiros", "Add Memory": "Adicionar memória", "Add message": "Adicionar mensagem", "Add Model": "Adicionar modelo", "Add Tags": "adicionar tags", - "Add User": "Adicionar Usuário", - "Adjusting these settings will apply changes universally to all users.": "Ajustar essas configurações aplicará alterações universalmente a todos os usuários.", + "Add User": "Adicionar Utilizador", + "Adjusting these settings will apply changes universally to all users.": "Ajustar essas configurações aplicará alterações universalmente a todos os utilizadores.", "admin": "administrador", - "Admin": "", + "Admin": "Admin", "Admin Panel": "Painel do Administrador", "Admin Settings": "Configurações do Administrador", "Advanced Parameters": "Parâmetros Avançados", "Advanced Params": "Params Avançados", "all": "todos", "All Documents": "Todos os Documentos", - "All Users": "Todos os Usuários", + "All Users": "Todos os utilizadores", "Allow": "Permitir", - "Allow Chat Deletion": "Permitir Exclusão de Bate-papo", - "Allow non-local voices": "", + "Allow Chat Deletion": "Permitir Exclusão de Conversa", + "Allow non-local voices": "Permitir vozes não locais", "alphanumeric characters and hyphens": "caracteres alfanuméricos e hífens", "Already have an account?": "Já tem uma conta?", "an assistant": "um assistente", "and": "e", - "and create a new shared link.": "e criar um novo link compartilhado.", + "and create a new shared link.": "e criar um novo link partilhado.", "API Base URL": "URL Base da API", "API Key": "Chave da API", "API Key created.": "Chave da API criada.", @@ -53,69 +53,69 @@ "April": "Abril", "Archive": "Arquivo", "Archive All Chats": "Arquivar todos os chats", - "Archived Chats": "Bate-papos arquivados", - "are allowed - Activate this command by typing": "são permitidos - Ative este comando digitando", - "Are you sure?": "Tem certeza?", - "Attach file": "Anexar arquivo", + "Archived Chats": "Conversas arquivadas", + "are allowed - Activate this command by typing": "são permitidos - Ative este comando escrevendo", + "Are you sure?": "Tem a certeza?", + "Attach file": "Anexar ficheiro", "Attention to detail": "Detalhado", "Audio": "Áudio", "August": "Agosto", "Auto-playback response": "Reprodução automática da resposta", "AUTOMATIC1111 Base URL": "URL Base do AUTOMATIC1111", - "AUTOMATIC1111 Base URL is required.": "A URL Base do AUTOMATIC1111 é obrigatória.", + "AUTOMATIC1111 Base URL is required.": "O URL Base do AUTOMATIC1111 é obrigatório.", "available!": "disponível!", "Back": "Voltar", - "Bad Response": "Resposta ruim", + "Bad Response": "Resposta má", "Banners": "Estandartes", "Base Model (From)": "Modelo Base (De)", "before": "antes", "Being lazy": "Ser preguiçoso", - "Brave Search API Key": "Chave da API de Pesquisa Admirável", + "Brave Search API Key": "Chave da API de Pesquisa Brave", "Bypass SSL verification for Websites": "Ignorar verificação SSL para sites", - "Call": "", - "Call feature is not supported when using Web STT engine": "", - "Camera": "", + "Call": "Chamar", + "Call feature is not supported when using Web STT engine": "A funcionalide de Chamar não é suportada quando usa um motor Web STT", + "Camera": "Camera", "Cancel": "Cancelar", "Capabilities": "Capacidades", "Change Password": "Alterar Senha", - "Chat": "Bate-papo", - "Chat Bubble UI": "UI de Bala de Bate-papo", - "Chat direction": "Direção do Bate-papo", - "Chat History": "Histórico de Bate-papo", - "Chat History is off for this browser.": "O histórico de bate-papo está desativado para este navegador.", - "Chats": "Bate-papos", + "Chat": "Conversa", + "Chat Bubble UI": "Bolha UI da Conversa", + "Chat direction": "Direção da Conversa", + "Chat History": "Histórico da Conversa", + "Chat History is off for this browser.": "O histórico da conversa está desativado para este navegador.", + "Chats": "Conversas", "Check Again": "Verifique novamente", "Check for updates": "Verificar atualizações", "Checking for updates...": "Verificando atualizações...", - "Choose a model before saving...": "Escolha um modelo antes de salvar...", + "Choose a model before saving...": "Escolha um modelo antes de guardar...", "Chunk Overlap": "Sobreposição de Fragmento", "Chunk Params": "Parâmetros de Fragmento", "Chunk Size": "Tamanho do Fragmento", "Citation": "Citação", - "Clear memory": "", + "Clear memory": "Limpar memória", "Click here for help.": "Clique aqui para obter ajuda.", "Click here to": "Clique aqui para", "Click here to select": "Clique aqui para selecionar", - "Click here to select a csv file.": "Clique aqui para selecionar um arquivo csv.", - "Click here to select a py file.": "", + "Click here to select a csv file.": "Clique aqui para selecionar um ficheiro csv.", + "Click here to select a py file.": "Clique aqui para selecionar um ficheiro py", "Click here to select documents.": "Clique aqui para selecionar documentos.", "click here.": "clique aqui.", - "Click on the user role button to change a user's role.": "Clique no botão de função do usuário para alterar a função de um usuário.", - "Clone": "Clone", + "Click on the user role button to change a user's role.": "Clique no botão de função do utilizador para alterar a função de um utilizador.", + "Clone": "Clonar", "Close": "Fechar", "Collection": "Coleção", "ComfyUI": "ComfyUI", "ComfyUI Base URL": "URL Base do ComfyUI", - "ComfyUI Base URL is required.": "A URL Base do ComfyUI é obrigatória.", + "ComfyUI Base URL is required.": "O URL Base do ComfyUI é obrigatório.", "Command": "Comando", "Concurrent Requests": "Solicitações simultâneas", "Confirm Password": "Confirmar Senha", "Connections": "Conexões", - "Contact Admin for WebUI Access": "", + "Contact Admin for WebUI Access": "Contatar Admin para acesso ao WebUI", "Content": "Conteúdo", "Context Length": "Comprimento do Contexto", "Continue Response": "Continuar resposta", - "Copied shared chat URL to clipboard!": "URL de bate-papo compartilhado copiada com sucesso!", + "Copied shared chat URL to clipboard!": "URL de Conversa partilhado copiada com sucesso!", "Copy": "Copiar", "Copy last code block": "Copiar último bloco de código", "Copy last response": "Copiar última resposta", @@ -132,8 +132,8 @@ "Custom": "Personalizado", "Customize models for a specific purpose": "Personalizar modelos para uma finalidade específica", "Dark": "Escuro", - "Dashboard": "", - "Database": "Banco de dados", + "Dashboard": "Painel", + "Database": "Base de dados", "December": "Dezembro", "Default": "Padrão", "Default (Automatic1111)": "Padrão (Automatic1111)", @@ -141,118 +141,118 @@ "Default Model": "Modelo padrão", "Default model updated": "Modelo padrão atualizado", "Default Prompt Suggestions": "Sugestões de Prompt Padrão", - "Default User Role": "Função de Usuário Padrão", - "delete": "excluir", - "Delete": "Excluir", - "Delete a model": "Excluir um modelo", - "Delete All Chats": "Excluir todos os chats", - "Delete chat": "Excluir bate-papo", - "Delete Chat": "Excluir Bate-papo", - "delete this link": "excluir este link", - "Delete User": "Excluir Usuário", - "Deleted {{deleteModelTag}}": "{{deleteModelTag}} excluído", - "Deleted {{name}}": "Suprimido {{name}}", + "Default User Role": "Função de Utilizador Padrão", + "delete": "apagar", + "Delete": "Apagar", + "Delete a model": "Apagar um modelo", + "Delete All Chats": "Apagar todas as conversas", + "Delete chat": "Apagar conversa", + "Delete Chat": "Apagar Conversa", + "delete this link": "apagar este link", + "Delete User": "Apagar Utilizador", + "Deleted {{deleteModelTag}}": "{{deleteModelTag}} apagado", + "Deleted {{name}}": "Apagado {{name}}", "Description": "Descrição", "Didn't fully follow instructions": "Não seguiu instruções com precisão", "Discover a model": "Descubra um modelo", "Discover a prompt": "Descobrir um prompt", - "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", - "Dismissible": "", - "Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Bate-papo", + "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", + "Dismissible": "Dispensável", + "Display the username instead of You in the Chat": "Exibir o nome de utilizador em vez de Você na Conversa", "Document": "Documento", "Document Settings": "Configurações de Documento", - "Documentation": "", + "Documentation": "Documentação", "Documents": "Documentos", - "does not make any external connections, and your data stays securely on your locally hosted server.": "não faz conexões externas e seus dados permanecem seguros em seu servidor hospedado localmente.", + "does not make any external connections, and your data stays securely on your locally hosted server.": "não faz conexões externas e os seus dados permanecem seguros no seu servidor alojado localmente.", "Don't Allow": "Não Permitir", "Don't have an account?": "Não tem uma conta?", "Don't like the style": "Não gosta do estilo", - "Download": "Baixar", + "Download": "Descarregar", "Download canceled": "Download cancelado", - "Download Database": "Baixar Banco de Dados", - "Drop any files here to add to the conversation": "Solte os arquivos aqui para adicionar à conversa", + "Download Database": "Descarregar Base de Dados", + "Drop any files here to add to the conversation": "Largue os ficheiros aqui para adicionar à conversa", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "por exemplo, '30s', '10m'. Unidades de tempo válidas são 's', 'm', 'h'.", "Edit": "Editar", "Edit Doc": "Editar Documento", - "Edit User": "Editar Usuário", + "Edit User": "Editar Utilizador", "Email": "E-mail", - "Embedding Batch Size": "", + "Embedding Batch Size": "Tamanho do Lote do Embedding", "Embedding Model": "Modelo de Embedding", "Embedding Model Engine": "Motor de Modelo de Embedding", "Embedding model set to \"{{embedding_model}}\"": "Modelo de Embedding definido como \"{{embedding_model}}\"", - "Enable Chat History": "Ativar Histórico de Bate-papo", - "Enable Community Sharing": "Habilite o compartilhamento da comunidade", + "Enable Chat History": "Ativar Histórico de Conversas", + "Enable Community Sharing": "Active a Partilha da Comunidade", "Enable New Sign Ups": "Ativar Novas Inscrições", "Enable Web Search": "Ativar pesquisa na Web", - "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Garanta que seu arquivo CSV inclua 4 colunas nesta ordem: Nome, E-mail, Senha, Função.", - "Enter {{role}} message here": "Digite a mensagem de {{role}} aqui", - "Enter a detail about yourself for your LLMs to recall": "Digite um detalhe sobre você para que seus LLMs possam lembrá-lo", - "Enter Brave Search API Key": "Insira a chave da API do Brave Search", - "Enter Chunk Overlap": "Digite a Sobreposição de Fragmento", - "Enter Chunk Size": "Digite o Tamanho do Fragmento", - "Enter Github Raw URL": "Insira o URL bruto do Github", - "Enter Google PSE API Key": "Insira a chave da API PSE do Google", - "Enter Google PSE Engine Id": "Insira o ID do mecanismo PSE do Google", - "Enter Image Size (e.g. 512x512)": "Digite o Tamanho da Imagem (por exemplo, 512x512)", - "Enter language codes": "Digite os códigos de idioma", - "Enter model tag (e.g. {{modelTag}})": "Digite a tag do modelo (por exemplo, {{modelTag}})", - "Enter Number of Steps (e.g. 50)": "Digite o Número de Etapas (por exemplo, 50)", - "Enter Score": "Digite a Pontuação", - "Enter Searxng Query URL": "Insira o URL da Consulta Searxng", - "Enter Serper API Key": "Insira a chave da API Serper", - "Enter Serpstack API Key": "Insira a chave da API Serpstack", - "Enter stop sequence": "Digite a sequência de parada", - "Enter Top K": "Digite o Top K", - "Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)", - "Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)", - "Enter Your Email": "Digite seu E-mail", - "Enter Your Full Name": "Digite seu Nome Completo", - "Enter Your Password": "Digite sua Senha", - "Enter Your Role": "Digite sua Função", + "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Confirme que o seu ficheiro CSV inclui 4 colunas nesta ordem: Nome, E-mail, Senha, Função.", + "Enter {{role}} message here": "Escreva a mensagem de {{role}} aqui", + "Enter a detail about yourself for your LLMs to recall": "Escreva um detalhe sobre você para que os seus LLMs possam lembrar-se", + "Enter Brave Search API Key": "Escreva a chave da API do Brave Search", + "Enter Chunk Overlap": "Escreva a Sobreposição de Fragmento", + "Enter Chunk Size": "Escreva o Tamanho do Fragmento", + "Enter Github Raw URL": "Escreva o URL cru do Github", + "Enter Google PSE API Key": "Escreva a chave da API PSE do Google", + "Enter Google PSE Engine Id": "Escreva o ID do mecanismo PSE do Google", + "Enter Image Size (e.g. 512x512)": "Escreva o Tamanho da Imagem (por exemplo, 512x512)", + "Enter language codes": "Escreva os códigos de idioma", + "Enter model tag (e.g. {{modelTag}})": "Escreva a tag do modelo (por exemplo, {{modelTag}})", + "Enter Number of Steps (e.g. 50)": "Escreva o Número de Etapas (por exemplo, 50)", + "Enter Score": "Escreva a Pontuação", + "Enter Searxng Query URL": "Escreva o URL da Pesquisa Searxng", + "Enter Serper API Key": "Escreva a chave da API Serper", + "Enter Serpstack API Key": "Escreva a chave da API Serpstack", + "Enter stop sequence": "Escreva a sequência de paragem", + "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://localhost:11434)": "Escreva o URL (por exemplo, http://localhost:11434)", + "Enter Your Email": "Escreva o seu E-mail", + "Enter Your Full Name": "Escreva o seu Nome Completo", + "Enter Your Password": "Escreva a sua Senha", + "Enter Your Role": "Escreva a sua Função", "Error": "Erro", "Experimental": "Experimental", - "Export": "Exportação", - "Export All Chats (All Users)": "Exportar Todos os Bate-papos (Todos os Usuários)", - "Export chat (.json)": "", - "Export Chats": "Exportar Bate-papos", + "Export": "Exportar", + "Export All Chats (All Users)": "Exportar Todas as Conversas (Todos os Utilizadores)", + "Export chat (.json)": "Exportar Conversa (.json)", + "Export Chats": "Exportar Conversas", "Export Documents Mapping": "Exportar Mapeamento de Documentos", "Export Models": "Modelos de Exportação", "Export Prompts": "Exportar Prompts", - "External Models": "", + "External Models": "Modelos Externos", "Failed to create API Key.": "Falha ao criar a Chave da API.", "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência", - "Failed to update settings": "", + "Failed to update settings": "Falha ao atualizar as definições", "February": "Fevereiro", "Feel free to add specific details": "Sinta-se à vontade para adicionar detalhes específicos", - "File Mode": "Modo de Arquivo", - "File not found.": "Arquivo não encontrado.", - "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Impostação de impressão digital detectada: Não é possível usar iniciais como avatar. Padronizando para imagem de perfil padrão.", + "File Mode": "Modo de Ficheiro", + "File not found.": "Ficheiro não encontrado.", + "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Detectada falsificação da impressão digital: Não é possível usar iniciais como avatar. A usar a imagem de perfil padrão.", "Fluidly stream large external response chunks": "Transmita com fluidez grandes blocos de resposta externa", - "Focus chat input": "Focar entrada de bate-papo", + "Focus chat input": "Focar na conversa", "Followed instructions perfectly": "Seguiu instruções perfeitamente", - "Format your variables using square brackets like this:": "Formate suas variáveis usando colchetes como este:", + "Format your variables using square brackets like this:": "Formate as suas variáveis usando parenteses rectos como este:", "Frequency Penalty": "Penalidade de Frequência", "General": "Geral", "General Settings": "Configurações Gerais", - "Generate Image": "", - "Generating search query": "Gerar consulta de pesquisa", + "Generate Image": "Gerar imagem", + "Generating search query": "A gerar a consulta da pesquisa", "Generation Info": "Informações de Geração", "Good Response": "Boa Resposta", "Google PSE API Key": "Chave da API PSE do Google", "Google PSE Engine Id": "ID do mecanismo PSE do Google", "h:mm a": "h:mm a", - "has no conversations.": "não possui bate-papos.", + "has no conversations.": "não possui conversas.", "Hello, {{name}}": "Olá, {{name}}", - "Help": "Help", + "Help": "Ajuda", "Hide": "Ocultar", "How can I help you today?": "Como posso ajudá-lo hoje?", "Hybrid Search": "Pesquisa Híbrida", "Image Generation (Experimental)": "Geração de Imagens (Experimental)", "Image Generation Engine": "Mecanismo de Geração de Imagens", - "Image Settings": "Configurações de Imagem", + "Image Settings": "Configurações da Imagem", "Images": "Imagens", - "Import Chats": "Importar Bate-papos", + "Import Chats": "Importar Conversas", "Import Documents Mapping": "Importar Mapeamento de Documentos", "Import Models": "Importar Modelos", "Import Prompts": "Importar Prompts", @@ -260,7 +260,7 @@ "Info": "Informação", "Input commands": "Comandos de entrada", "Install from Github URL": "Instalar a partir do URL do Github", - "Instant Auto-Send After Voice Transcription": "", + "Instant Auto-Send After Voice Transcription": "Enviar automaticamente depois da transcrição da voz", "Interface": "Interface", "Invalid Tag": "Etiqueta Inválida", "January": "Janeiro", @@ -273,55 +273,55 @@ "JWT Token": "Token JWT", "Keep Alive": "Manter Vivo", "Keyboard shortcuts": "Atalhos de teclado", - "Knowledge": "", + "Knowledge": "Conhecimento", "Language": "Idioma", "Last Active": "Último Ativo", "Light": "Claro", - "Listening...": "", + "Listening...": "A escutar...", "LLMs can make mistakes. Verify important information.": "LLMs podem cometer erros. Verifique informações importantes.", - "Local Models": "", + "Local Models": "Modelos Locais", "LTR": "LTR", "Made by OpenWebUI Community": "Feito pela Comunidade OpenWebUI", "Make sure to enclose them with": "Certifique-se de colocá-los entre", - "Manage": "", - "Manage Models": "Gerenciar Modelos", - "Manage Ollama Models": "Gerenciar Modelos Ollama", - "Manage Pipelines": "Gerenciar pipelines", + "Manage": "Gerir", + "Manage Models": "Gerir Modelos", + "Manage Ollama Models": "Gerir Modelos Ollama", + "Manage Pipelines": "Gerir pipelines", "March": "Março", - "Max Tokens (num_predict)": "Max Tokens (num_predict)", - "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Máximo de 3 modelos podem ser baixados simultaneamente. Tente novamente mais tarde.", + "Max Tokens (num_predict)": "Máx Tokens (num_predict)", + "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "O máximo de 3 modelos podem ser descarregados simultaneamente. Tente novamente mais tarde.", "May": "Maio", "Memories accessible by LLMs will be shown here.": "Memórias acessíveis por LLMs serão mostradas aqui.", "Memory": "Memória", - "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens que você enviar após criar seu link não serão compartilhadas. Os usuários com o URL poderão visualizar o bate-papo compartilhado.", + "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens que você enviar após criar o seu link não serão partilhadas. Os utilizadores com o URL poderão visualizar a conversa partilhada.", "Minimum Score": "Mínimo de Pontuação", "Mirostat": "Mirostat", "Mirostat Eta": "Mirostat Eta", "Mirostat Tau": "Mirostat Tau", "MMMM DD, YYYY": "DD/MM/YYYY", "MMMM DD, YYYY HH:mm": "DD/MM/YYYY HH:mm", - "Model '{{modelName}}' has been successfully downloaded.": "O modelo '{{modelName}}' foi baixado com sucesso.", - "Model '{{modelTag}}' is already in queue for downloading.": "O modelo '{{modelTag}}' já está na fila para download.", - "Model {{modelId}} not found": "Modelo {{modelId}} não encontrado", + "Model '{{modelName}}' has been successfully downloaded.": "O modelo '{{modelName}}' foi descarregado com sucesso.", + "Model '{{modelTag}}' is already in queue for downloading.": "O modelo '{{modelTag}}' já está na fila para descarregar.", + "Model {{modelId}} not found": "Modelo {{modelId}} não foi encontrado", "Model {{modelName}} is not vision capable": "O modelo {{modelName}} não é capaz de visão", "Model {{name}} is now {{status}}": "Modelo {{name}} agora é {{status}}", - "Model filesystem path detected. Model shortname is required for update, cannot continue.": "Caminho do sistema de arquivos do modelo detectado. É necessário o nome curto do modelo para atualização, não é possível continuar.", + "Model filesystem path detected. Model shortname is required for update, cannot continue.": "Dtectado caminho do sistema de ficheiros do modelo. É necessário o nome curto do modelo para atualização, não é possível continuar.", "Model ID": "ID do modelo", "Model not selected": "Modelo não selecionado", "Model Params": "Params Modelo", - "Model Whitelisting": "Lista de Permissões de Modelo", + "Model Whitelisting": "Lista de Permissões do Modelo", "Model(s) Whitelisted": "Modelo(s) na Lista de Permissões", - "Modelfile Content": "Conteúdo do Arquivo de Modelo", + "Modelfile Content": "Conteúdo do Ficheiro do Modelo", "Models": "Modelos", "More": "Mais", "Name": "Nome", - "Name Tag": "Tag de Nome", + "Name Tag": "Etiqueta de Nome", "Name your model": "Atribua um nome ao seu modelo", - "New Chat": "Novo Bate-papo", + "New Chat": "Nova Conversa", "New Password": "Nova Senha", - "No documents found": "", - "No results found": "Nenhum resultado encontrado", - "No search query generated": "Nenhuma consulta de pesquisa gerada", + "No documents found": "Não foram encontrados documentos", + "No results found": "Não foram encontrados resultados", + "No search query generated": "Não foi gerada nenhuma consulta de pesquisa", "No source available": "Nenhuma fonte disponível", "None": "Nenhum", "Not factually correct": "Não é correto em termos factuais", @@ -336,18 +336,18 @@ "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API disabled": "API do Ollama desativada", - "Ollama API is disabled": "", + "Ollama API is disabled": "A API do Ollama está desactivada", "Ollama Version": "Versão do Ollama", "On": "Ligado", - "Only": "Somente", - "Only alphanumeric characters and hyphens are allowed in the command string.": "Somente caracteres alfanuméricos e hífens são permitidos na string de comando.", - "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Opa! Aguente firme! Seus arquivos ainda estão no forno de processamento. Estamos cozinhando-os com perfeição. Por favor, seja paciente e avisaremos quando estiverem prontos.", - "Oops! Looks like the URL is invalid. Please double-check and try again.": "Opa! Parece que a URL é inválida. Verifique novamente e tente outra vez.", - "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Opa! Você está usando um método não suportado (somente frontend). Por favor, sirva o WebUI a partir do backend.", + "Only": "Apenas", + "Only alphanumeric characters and hyphens are allowed in the command string.": "Apenas caracteres alfanuméricos e hífens são permitidos na string de comando.", + "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Epá! Segura-te! Os teus ficheiros ainda estão no forno de processamento. Estamos a cozinhá-los com perfeição. Por favor, seja paciente e avisaremos quando estiverem prontos.", + "Oops! Looks like the URL is invalid. Please double-check and try again.": "Epá! Parece que o URL é inválido. Verifique novamente e tente outra vez.", + "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Epá! Você está a usar um método não suportado (somente frontend). Por favor, sirva o WebUI a partir do backend.", "Open": "Abrir", - "Open AI": "OpenAI", - "Open AI (Dall-E)": "OpenAI (Dall-E)", - "Open new chat": "Abrir novo bate-papo", + "Open AI": "Open AI", + "Open AI (Dall-E)": "Open AI (Dall-E)", + "Open new chat": "Abrir nova conversa", "OpenAI": "OpenAI", "OpenAI API": "API OpenAI", "OpenAI API Config": "Configuração da API OpenAI", @@ -359,31 +359,31 @@ "PDF document (.pdf)": "Documento PDF (.pdf)", "PDF Extract Images (OCR)": "Extrair Imagens de PDF (OCR)", "pending": "pendente", - "Permission denied when accessing media devices": "", - "Permission denied when accessing microphone": "", - "Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}", + "Permission denied when accessing media devices": "A permissão foi negada ao aceder aos dispositivos de media", + "Permission denied when accessing microphone": "A permissão foi negada ao aceder ao microfone", + "Permission denied when accessing microphone: {{error}}": "A permissão foi negada ao aceder o microfone: {{error}}", "Personalization": "Personalização", "Pipelines": "Condutas", "Pipelines Valves": "Válvulas de Condutas", "Plain text (.txt)": "Texto sem formatação (.txt)", - "Playground": "Parque infantil", + "Playground": "Recreio", "Positive attitude": "Atitude Positiva", "Previous 30 days": "Últimos 30 dias", "Previous 7 days": "Últimos 7 dias", "Profile Image": "Imagem de Perfil", "Prompt": "Prompt", - "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (ex.: Dê-me um fatídico sobre o Império Romano)", + "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (ex.: Dê-me um facto divertido sobre o Império Romano)", "Prompt Content": "Conteúdo do Prompt", "Prompt suggestions": "Sugestões de Prompt", "Prompts": "Prompts", - "Pull \"{{searchValue}}\" from Ollama.com": "Extrair \"{{searchValue}}\" do Ollama.com", - "Pull a model from Ollama.com": "Extrair um modelo do Ollama.com", + "Pull \"{{searchValue}}\" from Ollama.com": "Puxar \"{{searchValue}}\" do Ollama.com", + "Pull a model from Ollama.com": "Puxar um modelo do Ollama.com", "Query Params": "Parâmetros de Consulta", "RAG Template": "Modelo RAG", "Read Aloud": "Ler em Voz Alta", "Record voice": "Gravar voz", - "Redirecting you to OpenWebUI Community": "Redirecionando você para a Comunidade OpenWebUI", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", + "Redirecting you to OpenWebUI Community": "Redirecionando-o para a Comunidade OpenWebUI", + "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refera-se a si próprio como \"User\" (por exemplo, \"User está a aprender Espanhol\")", "Refused when it shouldn't have": "Recusado quando não deveria", "Regenerate": "Regenerar", "Release Notes": "Notas de Lançamento", @@ -391,51 +391,51 @@ "Remove Model": "Remover Modelo", "Rename": "Renomear", "Repeat Last N": "Repetir Últimos N", - "Request Mode": "Modo de Solicitação", + "Request Mode": "Modo de Pedido", "Reranking Model": "Modelo de Reranking", "Reranking model disabled": "Modelo de Reranking desativado", "Reranking model set to \"{{reranking_model}}\"": "Modelo de Reranking definido como \"{{reranking_model}}\"", - "Reset Upload Directory": "", + "Reset Upload Directory": "Limpar Pasta de Carregamento", "Reset Vector Storage": "Redefinir Armazenamento de Vetor", "Response AutoCopy to Clipboard": "Cópia Automática da Resposta para a Área de Transferência", "Role": "Função", "Rosé Pine": "Rosé Pine", "Rosé Pine Dawn": "Rosé Pine Dawn", "RTL": "RTL", - "Running": "", - "Save": "Salvar", - "Save & Create": "Salvar e Criar", - "Save & Update": "Salvar e Atualizar", - "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvar logs de bate-papo diretamente no armazenamento do seu navegador não é mais suportado. Reserve um momento para baixar e excluir seus logs de bate-papo clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar seus logs de bate-papo para o backend através de", + "Running": "A correr", + "Save": "Guardar", + "Save & Create": "Guardar e Criar", + "Save & Update": "Guardar e Atualizar", + "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Guardar o registo das conversas diretamente no armazenamento do seu navegador já não é suportado. Reserve um momento para descarregar e eliminar os seus registos de conversas clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar os seus registos de conversas para o backend através de", "Scan": "Digitalizar", "Scan complete!": "Digitalização concluída!", "Scan for documents from {{path}}": "Digitalizar documentos de {{path}}", "Search": "Pesquisar", "Search a model": "Pesquisar um modelo", - "Search Chats": "Pesquisar Chats", + "Search Chats": "Pesquisar Conversas", "Search Documents": "Pesquisar Documentos", "Search Models": "Modelos de pesquisa", "Search Prompts": "Pesquisar Prompts", - "Search Query Generation Prompt": "", - "Search Query Generation Prompt Length Threshold": "", + "Search Query Generation Prompt": "Prompt de geração de consulta de pesquisa", + "Search Query Generation Prompt Length Threshold": "Limite de comprimento do prompt de geração de consulta de pesquisa", "Search Result Count": "Contagem de resultados da pesquisa", "Searched {{count}} sites_one": "Pesquisado {{count}} sites_one", "Searched {{count}} sites_many": "Pesquisado {{count}} sites_many", "Searched {{count}} sites_other": "Pesquisado {{count}} sites_other", - "Searching the web for '{{searchQuery}}'": "Pesquisando na Web por '{{searchQuery}}'", + "Searching the web for '{{searchQuery}}'": "A pesquisar na Web por '{{searchQuery}}'", "Searxng Query URL": "URL de consulta Searxng", "See readme.md for instructions": "Consulte readme.md para obter instruções", "See what's new": "Veja o que há de novo", "Seed": "Semente", "Select a base model": "Selecione um modelo base", - "Select a engine": "", + "Select a engine": "Selecione um motor", "Select a mode": "Selecione um modo", "Select a model": "Selecione um modelo", "Select a pipeline": "Selecione um pipeline", "Select a pipeline url": "Selecione um URL de pipeline", "Select an Ollama instance": "Selecione uma instância Ollama", - "Select model": "Selecione um modelo", - "Select only one model to call": "", + "Select model": "Selecione o modelo", + "Select only one model to call": "Selecione apenas um modelo para a chamada", "Selected model(s) do not support image inputs": "O(s) modelo(s) selecionado(s) não suporta(m) entradas de imagem", "Send": "Enviar", "Send a Message": "Enviar uma Mensagem", @@ -453,26 +453,26 @@ "Set Task Model": "Definir modelo de tarefa", "Set Voice": "Definir Voz", "Settings": "Configurações", - "Settings saved successfully!": "Configurações salvas com sucesso!", - "Settings updated successfully": "", - "Share": "Compartilhar", - "Share Chat": "Compartilhar Bate-papo", - "Share to OpenWebUI Community": "Compartilhar com a Comunidade OpenWebUI", + "Settings saved successfully!": "Configurações guardadas com sucesso!", + "Settings updated successfully": "Configurações atualizadas com sucesso", + "Share": "Partilhar", + "Share Chat": "Partilhar Conversa", + "Share to OpenWebUI Community": "Partilhar com a Comunidade OpenWebUI", "short-summary": "resumo-curto", "Show": "Mostrar", - "Show Admin Details in Account Pending Overlay": "", - "Show shortcuts": "Mostrar", + "Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na sobreposição de Conta Pendente", + "Show shortcuts": "Mostrar atalhos", "Showcased creativity": "Criatividade Exibida", "sidebar": "barra lateral", "Sign in": "Entrar", "Sign Out": "Sair", "Sign up": "Inscrever-se", - "Signing in": "Entrando", + "Signing in": "A entrar", "Source": "Fonte", "Speech recognition error: {{error}}": "Erro de reconhecimento de fala: {{error}}", - "Speech-to-Text Engine": "Mecanismo de Fala para Texto", - "Stop Sequence": "Sequência de Parada", - "STT Model": "", + "Speech-to-Text Engine": "Motor de Fala para Texto", + "Stop Sequence": "Sequência de Paragem", + "STT Model": "Modelo STT", "STT Settings": "Configurações STT", "Submit": "Enviar", "Subtitle (e.g. about the Roman Empire)": "Subtítulo (ex.: sobre o Império Romano)", @@ -481,69 +481,69 @@ "Suggested": "Sugerido", "System": "Sistema", "System Prompt": "Prompt do Sistema", - "Tags": "Tags", - "Tell us more:": "Dê-nos mais:", + "Tags": "Etiquetas", + "Tell us more:": "Diga-nos mais:", "Temperature": "Temperatura", "Template": "Modelo", - "Text Completion": "Complemento de Texto", - "Text-to-Speech Engine": "Mecanismo de Texto para Fala", + "Text Completion": "Conclusão de Texto", + "Text-to-Speech Engine": "Motor de Texto para Fala", "Tfs Z": "Tfs Z", - "Thanks for your feedback!": "Obrigado pelo feedback!", - "The score should be a value between 0.0 (0%) and 1.0 (100%).": "O score deve ser um valor entre 0.0 (0%) e 1.0 (100%).", + "Thanks for your feedback!": "Obrigado pelo seu feedback!", + "The score should be a value between 0.0 (0%) and 1.0 (100%).": "A pontuação deve ser um valor entre 0.0 (0%) e 1.0 (100%).", "Theme": "Tema", - "Thinking...": "", - "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Isso garante que suas conversas valiosas sejam salvas com segurança em seu banco de dados de backend. Obrigado!", - "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "Thinking...": "A pensar...", + "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Isto garante que suas conversas valiosas sejam guardadas com segurança na sua base de dados de backend. Obrigado!", + "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Isto é um recurso experimental, pode não funcionar conforme o esperado e está sujeito a alterações a qualquer momento.", "This setting does not sync across browsers or devices.": "Esta configuração não sincroniza entre navegadores ou dispositivos.", - "Thorough explanation": "Explicação Completa", - "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada de bate-papo após cada substituição.", + "Thorough explanation": "Explicação Minuciosa", + "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada da conversa após cada substituição.", "Title": "Título", - "Title (e.g. Tell me a fun fact)": "Título (ex.: Dê-me um fatídico fatídico)", + "Title (e.g. Tell me a fun fact)": "Título (ex.: Diz-me um facto divertido)", "Title Auto-Generation": "Geração Automática de Título", "Title cannot be an empty string.": "Título não pode ser uma string vazia.", "Title Generation Prompt": "Prompt de Geração de Título", "to": "para", - "To access the available model names for downloading,": "Para acessar os nomes de modelo disponíveis para download,", - "To access the GGUF models available for downloading,": "Para acessar os modelos GGUF disponíveis para download,", - "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "", - "to chat input.": "para a entrada de bate-papo.", + "To access the available model names for downloading,": "Para aceder aos nomes de modelo disponíveis para descarregar,", + "To access the GGUF models available for downloading,": "Para aceder aos modelos GGUF disponíveis para descarregar,", + "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Para aceder ao WebUI, entre em contato com o administrador. Os administradores podem gerir o status dos utilizadores no Painel de Administração.", + "to chat input.": "para a entrada da conversa.", "Today": "Hoje", "Toggle settings": "Alternar configurações", "Toggle sidebar": "Alternar barra lateral", "Top K": "Top K", "Top P": "Top P", - "Trouble accessing Ollama?": "Problemas para acessar o Ollama?", - "TTS Model": "", + "Trouble accessing Ollama?": "Problemas a aceder ao Ollama?", + "TTS Model": "Modelo TTS", "TTS Settings": "Configurações TTS", - "TTS Voice": "", + "TTS Voice": "Voz TTS", "Type": "Tipo", - "Type Hugging Face Resolve (Download) URL": "Digite a URL do Hugging Face Resolve (Download)", - "Uh-oh! There was an issue connecting to {{provider}}.": "Opa! Houve um problema ao conectar-se a {{provider}}.", - "Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de arquivo desconhecido '{{file_type}}', mas aceitando e tratando como texto simples", + "Type Hugging Face Resolve (Download) URL": "Escreva o URL do Hugging Face Resolve (Descarregar)", + "Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Houve um problema ao conectar a {{provider}}.", + "Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de ficheiro desconhecido '{{file_type}}', mas aceitando e tratando como texto simples", "Update and Copy Link": "Atualizar e Copiar Link", "Update password": "Atualizar senha", "Upload a GGUF model": "Carregar um modelo GGUF", "Upload Files": "Carregar ficheiros", - "Upload Pipeline": "", + "Upload Pipeline": "Carregar Pipeline", "Upload Progress": "Progresso do Carregamento", "URL Mode": "Modo de URL", - "Use '#' in the prompt input to load and select your documents.": "Use '#' na entrada do prompt para carregar e selecionar seus documentos.", + "Use '#' in the prompt input to load and select your documents.": "Use '#' na entrada do prompt para carregar e selecionar os seus documentos.", "Use Gravatar": "Usar Gravatar", "Use Initials": "Usar Iniciais", "use_mlock (Ollama)": "use_mlock (Ollama)", "use_mmap (Ollama)": "use_mmap (Ollama)", - "user": "usuário", - "User Permissions": "Permissões do Usuário", - "Users": "Usuários", + "user": "utilizador", + "User Permissions": "Permissões do Utilizador", + "Users": "Utilizadores", "Utilize": "Utilizar", "Valid time units:": "Unidades de tempo válidas:", "variable": "variável", "variable to have them replaced with clipboard content.": "variável para que sejam substituídos pelo conteúdo da área de transferência.", "Version": "Versão", - "Warning": "Advertência", - "Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar seu modelo de vetorização, você precisará reimportar todos os documentos.", + "Warning": "Aviso", + "Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar o seu modelo de vetorização, você tem de reimportar todos os documentos.", "Web": "Web", - "Web API": "", + "Web API": "Web API", "Web Loader Settings": "Configurações do Carregador da Web", "Web Params": "Parâmetros da Web", "Web Search": "Pesquisa na Web", @@ -551,23 +551,23 @@ "Webhook URL": "URL do Webhook", "WebUI Add-ons": "Complementos WebUI", "WebUI Settings": "Configurações WebUI", - "WebUI will make requests to": "WebUI fará solicitações para", + "WebUI will make requests to": "WebUI fará pedidos a", "What’s New in": "O que há de novo em", - "When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando o histórico está desativado, novos bate-papos neste navegador não aparecerão em seu histórico em nenhum dos seus dispositivos.", - "Whisper (Local)": "", - "Widescreen Mode": "", + "When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando o histórico está desativado, novas conversas neste navegador não aparecerão em seu histórico em nenhum dos seus dispositivos.", + "Whisper (Local)": "Whisper (Local)", + "Widescreen Mode": "Modo Widescreen", "Workspace": "Espaço de Trabalho", - "Write a prompt suggestion (e.g. Who are you?)": "Escreva uma sugestão de prompt (por exemplo, Quem é você?)", + "Write a prompt suggestion (e.g. Who are you?)": "Escreva uma sugestão de prompt (por exemplo, Quem és tu?)", "Write a summary in 50 words that summarizes [topic or keyword].": "Escreva um resumo em 50 palavras que resuma [tópico ou palavra-chave].", "Yesterday": "Ontem", "You": "Você", - "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "", + "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Você pode personalizar as suas interações com LLMs adicionando memórias através do botão ‘Gerir’ abaixo, tornando-as mais úteis e personalizadas para você.", "You cannot clone a base model": "Não é possível clonar um modelo base", - "You have no archived conversations.": "Você não tem bate-papos arquivados.", - "You have shared this chat": "Você compartilhou este bate-papo", + "You have no archived conversations.": "Você não tem conversas arquivadas.", + "You have shared this chat": "Você partilhou esta conversa", "You're a helpful assistant.": "Você é um assistente útil.", - "You're now logged in.": "Você está conectado agora.", - "Your account status is currently pending activation.": "", + "You're now logged in.": "Você agora está conectado.", + "Your account status is currently pending activation.": "O status da sua conta está atualmente com a ativação pendente.", "Youtube": "Youtube", "Youtube Loader Settings": "Configurações do Carregador do Youtube" } From 34f04c53fc8468dca4c1ab03cf421cc63e0f34cd Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 11:04:00 -0700 Subject: [PATCH 14/20] fix: audio --- src/lib/components/chat/MessageInput.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 372c26d104..b3ceb3e91d 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -29,6 +29,7 @@ import InputMenu from './MessageInput/InputMenu.svelte'; import Headphone from '../icons/Headphone.svelte'; import VoiceRecording from './MessageInput/VoiceRecording.svelte'; + import { transcribeAudio } from '$lib/apis/audio'; const i18n = getContext('i18n'); From a75b68c19c6d629d08bcbbe617a22a821fa5718f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 11:40:58 -0700 Subject: [PATCH 15/20] refac: message status history --- src/lib/components/chat/Chat.svelte | 41 +++++++++++-------- .../chat/Messages/ResponseMessage.svelte | 15 ++++--- .../ResponseMessage/WebSearchResults.svelte | 41 +++++++++++++++++-- .../components/icons/MagnifyingGlass.svelte | 19 +++++++++ 4 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 src/lib/components/icons/MagnifyingGlass.svelte diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 861b985a5d..47e1075df3 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -515,11 +515,13 @@ const getWebSearchResults = async (model: string, parentId: string, responseId: string) => { const responseMessage = history.messages[responseId]; - responseMessage.status = { - done: false, - action: 'web_search', - description: $i18n.t('Generating search query') - }; + responseMessage.statusHistory = [ + { + done: false, + action: 'web_search', + description: $i18n.t('Generating search query') + } + ]; messages = messages; const prompt = history.messages[parentId].content; @@ -532,19 +534,21 @@ if (!searchQuery) { toast.warning($i18n.t('No search query generated')); - responseMessage.status = { - ...responseMessage.status, + responseMessage.statusHistory.push({ done: true, error: true, + action: 'web_search', description: 'No search query generated' - }; + }); + messages = messages; } - responseMessage.status = { - ...responseMessage.status, - description: $i18n.t("Searching the web for '{{searchQuery}}'", { searchQuery }) - }; + 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) => { @@ -555,12 +559,13 @@ }); if (results) { - responseMessage.status = { - ...responseMessage.status, + 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 = []; @@ -575,12 +580,12 @@ messages = messages; } else { - responseMessage.status = { - ...responseMessage.status, + responseMessage.statusHistory.push({ done: true, error: true, + action: 'web_search', description: 'No search results found' - }; + }); messages = messages; } }; diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index 7933c02157..281f7671f0 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -420,26 +420,29 @@ class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-headings:-mb-4 prose-p:m-0 prose-p:-mb-6 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-8 prose-ol:p-0 prose-li:-mb-4 whitespace-pre-line" >
- {#if message?.status} + {#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0} + {@const status = ( + message?.statusHistory ?? [...(message?.status ? [message?.status] : [])] + ).at(-1)}
- {#if message?.status?.done === false} + {#if status.done === false}
{/if} - {#if message?.status?.action === 'web_search' && message?.status?.urls} - + {#if status?.action === 'web_search' && status?.urls} +
- {message.status.description} + {status?.description}
{:else}
- {message.status.description} + {status?.description}
{/if} diff --git a/src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte b/src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte index dc233c6d4f..5281080362 100644 --- a/src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte @@ -1,10 +1,11 @@ @@ -27,11 +28,45 @@ class=" text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl" transition={slide} > - {#each urls as url, urlIdx} + {#if status?.query} + +
+ + +
+ {status.query} +
+
+ +
+ + + + +
+
+ {/if} + + {#each status.urls as url, urlIdx} diff --git a/src/lib/components/icons/MagnifyingGlass.svelte b/src/lib/components/icons/MagnifyingGlass.svelte new file mode 100644 index 0000000000..a61186b5d0 --- /dev/null +++ b/src/lib/components/icons/MagnifyingGlass.svelte @@ -0,0 +1,19 @@ + + + + + From 547b990041835578208805340d0b16c9e6f387bc Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 10 Jun 2024 13:29:09 -0700 Subject: [PATCH 16/20] refac: params --- .../Settings/Advanced/AdvancedParams.svelte | 320 +++++++++--------- .../components/chat/Settings/General.svelte | 61 ++-- .../workspace/models/create/+page.svelte | 1 + .../(app)/workspace/models/edit/+page.svelte | 1 + 4 files changed, 193 insertions(+), 190 deletions(-) diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index 7d5d773529..92535fa346 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -5,21 +5,23 @@ const i18n = getContext('i18n'); + export let admin = false; + export let params = { // Advanced - seed: 0, + seed: null, stop: null, - temperature: '', - frequency_penalty: '', - repeat_last_n: '', - mirostat: '', - mirostat_eta: '', - mirostat_tau: '', - top_k: '', - top_p: '', - tfs_z: '', - num_ctx: '', - max_tokens: '', + temperature: null, + frequency_penalty: null, + repeat_last_n: null, + mirostat: null, + mirostat_eta: null, + mirostat_tau: null, + top_k: null, + top_p: null, + tfs_z: null, + num_ctx: null, + max_tokens: null, use_mmap: null, use_mlock: null, num_thread: null, @@ -112,10 +114,10 @@ class="p-1 px-3 text-xs flex rounded transition" type="button" on:click={() => { - params.temperature = (params?.temperature ?? '') === '' ? 0.8 : ''; + params.temperature = (params?.temperature ?? null) === null ? 0.8 : null; }} > - {#if (params?.temperature ?? '') === ''} + {#if (params?.temperature ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -123,7 +125,7 @@
- {#if (params?.temperature ?? '') !== ''} + {#if (params?.temperature ?? null) !== null}
{ - params.mirostat = (params?.mirostat ?? '') === '' ? 0 : ''; + params.mirostat = (params?.mirostat ?? null) === null ? 0 : null; }} > - {#if (params?.mirostat ?? '') === ''} + {#if (params?.mirostat ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -168,7 +170,7 @@
- {#if (params?.mirostat ?? '') !== ''} + {#if (params?.mirostat ?? null) !== null}
{ - params.mirostat_eta = (params?.mirostat_eta ?? '') === '' ? 0.1 : ''; + params.mirostat_eta = (params?.mirostat_eta ?? null) === null ? 0.1 : null; }} > - {#if (params?.mirostat_eta ?? '') === ''} + {#if (params?.mirostat_eta ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -214,7 +216,7 @@
- {#if (params?.mirostat_eta ?? '') !== ''} + {#if (params?.mirostat_eta ?? null) !== null}
{ - params.mirostat_tau = (params?.mirostat_tau ?? '') === '' ? 5.0 : ''; + params.mirostat_tau = (params?.mirostat_tau ?? null) === null ? 5.0 : null; }} > - {#if (params?.mirostat_tau ?? '') === ''} + {#if (params?.mirostat_tau ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -259,7 +261,7 @@
- {#if (params?.mirostat_tau ?? '') !== ''} + {#if (params?.mirostat_tau ?? null) !== null}
{ - params.top_k = (params?.top_k ?? '') === '' ? 40 : ''; + params.top_k = (params?.top_k ?? null) === null ? 40 : null; }} > - {#if (params?.top_k ?? '') === ''} + {#if (params?.top_k ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -304,7 +306,7 @@
- {#if (params?.top_k ?? '') !== ''} + {#if (params?.top_k ?? null) !== null}
{ - params.top_p = (params?.top_p ?? '') === '' ? 0.9 : ''; + params.top_p = (params?.top_p ?? null) === null ? 0.9 : null; }} > - {#if (params?.top_p ?? '') === ''} + {#if (params?.top_p ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -349,7 +351,7 @@
- {#if (params?.top_p ?? '') !== ''} + {#if (params?.top_p ?? null) !== null}
{ - params.frequency_penalty = (params?.frequency_penalty ?? '') === '' ? 1.1 : ''; + params.frequency_penalty = (params?.frequency_penalty ?? null) === null ? 1.1 : null; }} > - {#if (params?.frequency_penalty ?? '') === ''} + {#if (params?.frequency_penalty ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -394,7 +396,7 @@
- {#if (params?.frequency_penalty ?? '') !== ''} + {#if (params?.frequency_penalty ?? null) !== null}
{ - params.repeat_last_n = (params?.repeat_last_n ?? '') === '' ? 64 : ''; + params.repeat_last_n = (params?.repeat_last_n ?? null) === null ? 64 : null; }} > - {#if (params?.repeat_last_n ?? '') === ''} + {#if (params?.repeat_last_n ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -439,7 +441,7 @@
- {#if (params?.repeat_last_n ?? '') !== ''} + {#if (params?.repeat_last_n ?? null) !== null}
{ - params.tfs_z = (params?.tfs_z ?? '') === '' ? 1 : ''; + params.tfs_z = (params?.tfs_z ?? null) === null ? 1 : null; }} > - {#if (params?.tfs_z ?? '') === ''} + {#if (params?.tfs_z ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -485,7 +487,7 @@
- {#if (params?.tfs_z ?? '') !== ''} + {#if (params?.tfs_z ?? null) !== null}
{ - params.num_ctx = (params?.num_ctx ?? '') === '' ? 2048 : ''; + params.num_ctx = (params?.num_ctx ?? null) === null ? 2048 : null; }} > - {#if (params?.num_ctx ?? '') === ''} + {#if (params?.num_ctx ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -530,7 +532,7 @@
- {#if (params?.num_ctx ?? '') !== ''} + {#if (params?.num_ctx ?? null) !== null}
{ - params.max_tokens = (params?.max_tokens ?? '') === '' ? 128 : ''; + params.max_tokens = (params?.max_tokens ?? null) === null ? 128 : null; }} > - {#if (params?.max_tokens ?? '') === ''} + {#if (params?.max_tokens ?? null) === null} {$i18n.t('Default')} {:else} {$i18n.t('Custom')} @@ -575,7 +577,7 @@
- {#if (params?.max_tokens ?? '') !== ''} + {#if (params?.max_tokens ?? null) !== null}
-
-
-
{$i18n.t('use_mmap (Ollama)')}
+ {#if admin} +
+
+
{$i18n.t('use_mmap (Ollama)')}
- -
-
- -
-
-
{$i18n.t('use_mlock (Ollama)')}
- - -
-
- -
-
-
{$i18n.t('num_thread (Ollama)')}
- - -
- - {#if (params?.num_thread ?? null) !== null} -
-
- -
-
- -
+
- {/if} -
- -
-
-
{$i18n.t('Template')}
- -
- {#if (params?.template ?? null) !== null} -
-
-