diff --git a/backend/apps/ollama/main.py b/backend/apps/ollama/main.py index 03a8e198e..810a05999 100644 --- a/backend/apps/ollama/main.py +++ b/backend/apps/ollama/main.py @@ -147,13 +147,17 @@ async def cleanup_response( await session.close() -async def post_streaming_url(url: str, payload: str, stream: bool = True): +async def post_streaming_url(url: str, payload: Union[str, bytes], stream: bool = True): r = None try: session = aiohttp.ClientSession( trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT) ) - r = await session.post(url, data=payload) + r = await session.post( + url, + data=payload, + headers={"Content-Type": "application/json"}, + ) r.raise_for_status() if stream: @@ -422,6 +426,7 @@ async def copy_model( r = requests.request( method="POST", url=f"{url}/api/copy", + headers={"Content-Type": "application/json"}, data=form_data.model_dump_json(exclude_none=True).encode(), ) @@ -470,6 +475,7 @@ async def delete_model( r = requests.request( method="DELETE", url=f"{url}/api/delete", + headers={"Content-Type": "application/json"}, data=form_data.model_dump_json(exclude_none=True).encode(), ) try: @@ -510,6 +516,7 @@ async def show_model_info(form_data: ModelNameForm, user=Depends(get_verified_us r = requests.request( method="POST", url=f"{url}/api/show", + headers={"Content-Type": "application/json"}, data=form_data.model_dump_json(exclude_none=True).encode(), ) try: @@ -567,6 +574,7 @@ async def generate_embeddings( r = requests.request( method="POST", url=f"{url}/api/embeddings", + headers={"Content-Type": "application/json"}, data=form_data.model_dump_json(exclude_none=True).encode(), ) try: @@ -616,6 +624,7 @@ def generate_ollama_embeddings( r = requests.request( method="POST", url=f"{url}/api/embeddings", + headers={"Content-Type": "application/json"}, data=form_data.model_dump_json(exclude_none=True).encode(), ) try: diff --git a/backend/main.py b/backend/main.py index 873116dd7..8ddaffcac 100644 --- a/backend/main.py +++ b/backend/main.py @@ -980,9 +980,9 @@ async def get_all_models(): function_module, _, _ = load_function_module_by_id(action_id) webui_app.state.FUNCTIONS[action_id] = function_module - icon_url = None - if action.meta.manifest is not None: - icon_url = action.meta.manifest.get("icon_url", None) + __webui__ = False + if hasattr(function_module, "__webui__"): + __webui__ = function_module.__webui__ if hasattr(function_module, "actions"): actions = function_module.actions @@ -994,7 +994,10 @@ async def get_all_models(): "name", f"{action.name} ({_action['id']})" ), "description": action.meta.description, - "icon_url": _action.get("icon_url", icon_url), + "icon_url": _action.get( + "icon_url", action.meta.manifest.get("icon_url", None) + ), + **({"__webui__": __webui__} if __webui__ else {}), } for _action in actions ] @@ -1005,7 +1008,8 @@ async def get_all_models(): "id": action_id, "name": action.name, "description": action.meta.description, - "icon_url": icon_url, + "icon_url": action.meta.manifest.get("icon_url", None), + **({"__webui__": __webui__} if __webui__ else {}), } ) @@ -2176,7 +2180,20 @@ async def get_manifest_json(): "display": "standalone", "background_color": "#343541", "orientation": "portrait-primary", - "icons": [{"src": "/static/logo.png", "type": "image/png", "sizes": "500x500"}], + "icons": [ + { + "src": "/static/logo.png", + "type": "image/png", + "sizes": "500x500", + "purpose": "any", + }, + { + "src": "/static/logo.png", + "type": "image/png", + "sizes": "500x500", + "purpose": "maskable", + }, + ], } diff --git a/package-lock.json b/package-lock.json index 52c5f8933..aa813a4db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "codemirror": "^6.0.1", "crc-32": "^1.2.2", "dayjs": "^1.11.10", + "dompurify": "^3.1.6", "eventsource-parser": "^1.1.2", "file-saver": "^2.0.5", "fuse.js": "^7.0.0", @@ -3918,9 +3919,9 @@ } }, "node_modules/dompurify": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz", - "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==" + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==" }, "node_modules/domutils": { "version": "3.1.0", diff --git a/package.json b/package.json index 2d32422d1..fef2cbaef 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "codemirror": "^6.0.1", "crc-32": "^1.2.2", "dayjs": "^1.11.10", + "dompurify": "^3.1.6", "eventsource-parser": "^1.1.2", "file-saver": "^2.0.5", "fuse.js": "^7.0.0", diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 64b51be96..9d28df0c1 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -26,7 +26,8 @@ socket, showCallOverlay, tools, - currentChatPage + currentChatPage, + temporaryChatEnabled } from '$lib/stores'; import { convertMessagesToHistory, @@ -238,7 +239,7 @@ } }); } else { - if (!($settings.saveChatHistory ?? true)) { + if ($temporaryChatEnabled) { await goto('/'); } } @@ -414,7 +415,7 @@ } if ($chatId == chatId) { - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, chatId, { models: selectedModels, messages: messages, @@ -429,7 +430,7 @@ } }; - const chatActionHandler = async (chatId, actionId, modelId, responseMessageId) => { + const chatActionHandler = async (chatId, actionId, modelId, responseMessageId, event = null) => { const res = await chatAction(localStorage.token, actionId, { model: modelId, messages: messages.map((m) => ({ @@ -439,6 +440,7 @@ info: m.info ? m.info : undefined, timestamp: m.timestamp })), + ...(event ? { event: event } : {}), chat_id: chatId, session_id: $socket?.id, id: responseMessageId @@ -462,7 +464,7 @@ } if ($chatId == chatId) { - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, chatId, { models: selectedModels, messages: messages, @@ -620,7 +622,7 @@ // Create new chat if only one message in messages if (newChat && messages.length == 2) { - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await createNewChat(localStorage.token, { id: $chatId, title: $i18n.t('New Chat'), @@ -954,7 +956,7 @@ } if ($chatId == _chatId) { - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, _chatId, { messages: messages, history: history, @@ -1227,7 +1229,7 @@ } if ($chatId == _chatId) { - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, _chatId, { models: selectedModels, messages: messages, @@ -1400,7 +1402,7 @@ title = _title; } - if ($settings.saveChatHistory ?? true) { + if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, _chatId, { title: _title }); currentChatPage.set(1); diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index fb6754e86..9cc7f9526 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -342,7 +342,13 @@ {continueGeneration} {regenerateResponse} on:action={async (e) => { - await chatActionHandler(chatId, e.detail, message.model, message.id); + console.log('action', e); + if (typeof e.detail === 'string') { + await chatActionHandler(chatId, e.detail, message.model, message.id); + } else { + const { id, event } = e.detail; + await chatActionHandler(chatId, id, message.model, message.id, event); + } }} on:save={async (e) => { console.log('save', e); diff --git a/src/lib/components/chat/Messages/CodeBlock.svelte b/src/lib/components/chat/Messages/CodeBlock.svelte index bb10af409..f368c8459 100644 --- a/src/lib/components/chat/Messages/CodeBlock.svelte +++ b/src/lib/components/chat/Messages/CodeBlock.svelte @@ -261,7 +261,7 @@ __builtins__.input = input`);
-
{@html lang}
+
{lang}
{#if lang.toLowerCase() === 'python' || lang.toLowerCase() === 'py' || (lang === '' && checkPythonCode(code))} diff --git a/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte b/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte index 4567cf507..8ca6fa37d 100644 --- a/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte +++ b/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte @@ -1,4 +1,5 @@
-
-
-
{$i18n.t('Chat History')}
- - -
- -
- {$i18n.t('This setting does not sync across browsers or devices.')} -
-
- -
-
- import { getDocs } from '$lib/apis/documents'; - import { - getRAGConfig, - updateRAGConfig, - getQuerySettings, - scanDocs, - updateQuerySettings, - resetVectorDB, - getEmbeddingConfig, - updateEmbeddingConfig, - getRerankingConfig, - updateRerankingConfig - } from '$lib/apis/rag'; - - import { documents, models } from '$lib/stores'; - import { onMount, getContext } from 'svelte'; - import { toast } from 'svelte-sonner'; - - import Tooltip from '$lib/components/common/Tooltip.svelte'; - - const i18n = getContext('i18n'); - - export let saveHandler: Function; - - let scanDirLoading = false; - let updateEmbeddingModelLoading = false; - let updateRerankingModelLoading = false; - - let showResetConfirm = false; - - let chunkSize = 0; - let chunkOverlap = 0; - let pdfExtractImages = true; - - const submitHandler = async () => { - const res = await updateRAGConfig(localStorage.token, { - pdf_extract_images: pdfExtractImages, - chunk: { - chunk_overlap: chunkOverlap, - chunk_size: chunkSize - } - }); - }; - - onMount(async () => { - const res = await getRAGConfig(localStorage.token); - - if (res) { - pdfExtractImages = res.pdf_extract_images; - - chunkSize = res.chunk.chunk_size; - chunkOverlap = res.chunk.chunk_overlap; - } - }); - - -
{ - submitHandler(); - saveHandler(); - }} -> -
-
-
{$i18n.t('Chunk Params')}
- -
-
-
{$i18n.t('Chunk Size')}
- -
- -
-
- -
-
- {$i18n.t('Chunk Overlap')} -
- -
- -
-
-
- -
-
-
{$i18n.t('PDF Extract Images (OCR)')}
- - -
-
-
-
-
- -
-
diff --git a/src/lib/components/documents/Settings/QueryParams.svelte b/src/lib/components/documents/Settings/QueryParams.svelte deleted file mode 100644 index 140afed6c..000000000 --- a/src/lib/components/documents/Settings/QueryParams.svelte +++ /dev/null @@ -1,119 +0,0 @@ - - -
{ - submitHandler(); - saveHandler(); - }} -> -
-
-
{$i18n.t('Query Params')}
- -
-
-
{$i18n.t('Top K')}
- -
- -
-
- - {#if querySettings.hybrid === true} -
-
- {$i18n.t('Minimum Score')} -
- -
- -
-
- {/if} -
- - {#if querySettings.hybrid === true} -
- {$i18n.t( - 'Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.' - )} -
- -
- {/if} - -
-
{$i18n.t('RAG Template')}
-