Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
f9e3c47d
Commit
f9e3c47d
authored
Jul 09, 2024
by
Michael Poluektov
Browse files
rebase
parents
49b4211c
24ef5af2
Changes
149
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
345 additions
and
138 deletions
+345
-138
src/lib/components/admin/Settings/Pipelines.svelte
src/lib/components/admin/Settings/Pipelines.svelte
+5
-5
src/lib/components/admin/Settings/Users.svelte
src/lib/components/admin/Settings/Users.svelte
+2
-2
src/lib/components/admin/Settings/WebSearch.svelte
src/lib/components/admin/Settings/WebSearch.svelte
+5
-5
src/lib/components/chat/Chat.svelte
src/lib/components/chat/Chat.svelte
+102
-60
src/lib/components/chat/ChatControls.svelte
src/lib/components/chat/ChatControls.svelte
+63
-0
src/lib/components/chat/Controls/Controls.svelte
src/lib/components/chat/Controls/Controls.svelte
+49
-0
src/lib/components/chat/MessageInput.svelte
src/lib/components/chat/MessageInput.svelte
+1
-1
src/lib/components/chat/MessageInput/CallOverlay.svelte
src/lib/components/chat/MessageInput/CallOverlay.svelte
+6
-4
src/lib/components/chat/Messages/CodeBlock.svelte
src/lib/components/chat/Messages/CodeBlock.svelte
+2
-1
src/lib/components/chat/Messages/Name.svelte
src/lib/components/chat/Messages/Name.svelte
+1
-1
src/lib/components/chat/Messages/Placeholder.svelte
src/lib/components/chat/Messages/Placeholder.svelte
+3
-3
src/lib/components/chat/Messages/ResponseMessage.svelte
src/lib/components/chat/Messages/ResponseMessage.svelte
+4
-1
src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte
...nts/chat/Messages/ResponseMessage/WebSearchResults.svelte
+15
-22
src/lib/components/chat/ModelSelector.svelte
src/lib/components/chat/ModelSelector.svelte
+2
-2
src/lib/components/chat/ModelSelector/Selector.svelte
src/lib/components/chat/ModelSelector/Selector.svelte
+4
-4
src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
...b/components/chat/Settings/Advanced/AdvancedParams.svelte
+19
-19
src/lib/components/chat/Settings/General.svelte
src/lib/components/chat/Settings/General.svelte
+4
-0
src/lib/components/chat/SettingsModal.svelte
src/lib/components/chat/SettingsModal.svelte
+35
-4
src/lib/components/common/Banner.svelte
src/lib/components/common/Banner.svelte
+5
-4
src/lib/components/common/Collapsible.svelte
src/lib/components/common/Collapsible.svelte
+18
-0
No files found.
src/lib/components/admin/Settings/Pipelines.svelte
View file @
f9e3c47d
...
...
@@ -214,7 +214,7 @@
<div class="flex gap-2">
<div class="flex-1">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={selectedPipelinesUrlIdx}
placeholder={$i18n.t('Select a pipeline url')}
on:change={async () => {
...
...
@@ -328,7 +328,7 @@
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Enter Github Raw URL')}
bind:value={pipelineDownloadUrl}
/>
...
...
@@ -412,7 +412,7 @@
<div class="flex gap-2">
<div class="flex-1">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={selectedPipelineIdx}
placeholder={$i18n.t('Select a pipeline')}
on:change={async () => {
...
...
@@ -482,7 +482,7 @@
<div class=" flex-1">
{#if valves_spec.properties[property]?.enum ?? null}
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={valves[property]}
>
{#each valves_spec.properties[property].enum as option}
...
...
@@ -503,7 +503,7 @@
</div>
{:else}
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={valves_spec.properties[property].title}
bind:value={valves[property]}
...
...
src/lib/components/admin/Settings/Users.svelte
View file @
f9e3c47d
...
...
@@ -112,7 +112,7 @@
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={defaultModelId}
placeholder="Select a model"
>
...
...
@@ -140,7 +140,7 @@
<div class="flex w-full">
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={modelId}
placeholder="Select a model"
>
...
...
src/lib/components/admin/Settings/WebSearch.svelte
View file @
f9e3c47d
...
...
@@ -101,7 +101,7 @@
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Searxng Query URL')}
bind:value={webConfig.search.searxng_query_url}
...
...
@@ -129,7 +129,7 @@
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter Google PSE Engine Id')}
bind:value={webConfig.search.google_pse_engine_id}
...
...
@@ -205,7 +205,7 @@
</div>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Search Result Count')}
bind:value={webConfig.search.result_count}
required
...
...
@@ -218,7 +218,7 @@
</div>
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Concurrent Requests')}
bind:value={webConfig.search.concurrent_requests}
required
...
...
@@ -267,7 +267,7 @@
<div class=" w-20 text-xs font-medium self-center">{$i18n.t('Language')}</div>
<div class=" flex-1 self-center">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
class="w-full rounded-lg py-2 px-4 text-sm
bg-gray-50
dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={$i18n.t('Enter language codes')}
bind:value={youtubeLanguage}
...
...
src/lib/components/chat/Chat.svelte
View file @
f9e3c47d
...
...
@@ -60,19 +60,26 @@
import Navbar from '$lib/components/layout/Navbar.svelte';
import CallOverlay from './MessageInput/CallOverlay.svelte';
import { error } from '@sveltejs/kit';
import ChatControls from './ChatControls.svelte';
import EventConfirmDialog from '../common/ConfirmDialog.svelte';
const i18n: Writable<i18nType> = getContext('i18n');
export let chatIdProp = '';
let loaded = false;
const eventTarget = new EventTarget();
let showControls = false;
let stopResponseFlag = false;
let autoScroll = true;
let processing = '';
let messagesContainerElement: HTMLDivElement;
let showEventConfirmation = false;
let eventConfirmationTitle = '';
let eventConfirmationMessage = '';
let eventCallback = null;
let showModelSelector = true;
let selectedModels = [''];
...
...
@@ -96,6 +103,8 @@
currentId: null
};
let params = {};
$: if (history.currentId !== null) {
let _messages = [];
...
...
@@ -126,21 +135,35 @@
})();
}
const chatEventHandler = async (
data
) => {
if (
data
.chat_id === $chatId) {
const chatEventHandler = async (
event, cb
) => {
if (
event
.chat_id === $chatId) {
await tick();
console.log(
data
);
let message = history.messages[
data
.message_id];
console.log(
event
);
let message = history.messages[
event
.message_id];
const status = {
done: data?.data?.done ?? null,
description: data?.data?.status ?? null
};
const type = event?.data?.type ?? null;
const data = event?.data?.data ?? null;
if (type === 'status') {
if (message?.statusHistory) {
message.statusHistory.push(data);
} else {
message.statusHistory = [data];
}
} else if (type === 'citation') {
if (message?.citations) {
message.citations.push(data);
} else {
message.citations = [data];
}
} else if (type === 'confirmation') {
eventCallback = cb;
showEventConfirmation = true;
if (message.statusHistory) {
message.statusHistory.push(status)
;
eventConfirmationTitle = data.title;
eventConfirmationMessage = data.message
;
} else {
message.statusHistory = [status]
;
console.log('Unknown message type', data)
;
}
messages = messages;
...
...
@@ -221,6 +244,7 @@
messages: {},
currentId: null
};
params = {};
if ($page.url.searchParams.get('models')) {
selectedModels = $page.url.searchParams.get('models')?.split(',');
...
...
@@ -290,11 +314,7 @@
await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
}
await settings.set({
...$settings,
system: chatContent.system ?? $settings.system,
params: chatContent.options ?? $settings.params
});
params = chatContent?.params ?? {};
autoScroll = true;
await tick();
...
...
@@ -507,9 +527,7 @@
title: $i18n.t('New Chat'),
models: selectedModels,
system: $settings.system ?? undefined,
options: {
...($settings.params ?? {})
},
params: params,
messages: messages,
history: history,
tags: [],
...
...
@@ -607,11 +625,11 @@
scrollToBottom();
const messagesBody = [
$settings.system || (responseMessage?.userContext ?? null)
params?.system ||
$settings.system || (responseMessage?.userContext ?? null)
? {
role: 'system',
content: `${promptTemplate(
$settings?.system ?? '',
params?.system ??
$settings?.system ?? '',
$user.name,
$settings?.userLocation
? await getAndUpdateUserLocation(localStorage.token)
...
...
@@ -696,15 +714,16 @@
model: model.id,
messages: messagesBody,
options: {
...($settings.params ?? {}),
...(
params ??
$settings.params ?? {}),
stop:
$settings?.params?.stop ?? undefined
? $settings.params.stop.map((str) =>
params?.stop ??
$settings?.params?.stop ?? undefined
?
(params?.stop ??
$settings.params.stop
)
.map((str) =>
decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"'))
)
: undefined,
num_predict: $settings?.params?.max_tokens ?? undefined,
repeat_penalty: $settings?.params?.frequency_penalty ?? undefined
num_predict: params?.max_tokens ?? $settings?.params?.max_tokens ?? undefined,
repeat_penalty:
params?.frequency_penalty ?? $settings?.params?.frequency_penalty ?? undefined
},
format: $settings.requestFormat ?? undefined,
keep_alive: $settings.keepAlive ?? undefined,
...
...
@@ -840,7 +859,8 @@
chat = await updateChatById(localStorage.token, _chatId, {
messages: messages,
history: history,
models: selectedModels
models: selectedModels,
params: params
});
await chats.set(await getChatList(localStorage.token));
}
...
...
@@ -950,11 +970,11 @@
}
: undefined,
messages: [
$settings.system || (responseMessage?.userContext ?? null)
params?.system ||
$settings.system || (responseMessage?.userContext ?? null)
? {
role: 'system',
content: `${promptTemplate(
$settings?.system ?? '',
params?.system ??
$settings?.system ?? '',
$user.name,
$settings?.userLocation
? await getAndUpdateUserLocation(localStorage.token)
...
...
@@ -999,17 +1019,18 @@
: message?.raContent ?? message.content
})
})),
seed: $settings?.params?.seed ?? undefined,
seed:
params?.seed ??
$settings?.params?.seed ?? undefined,
stop:
$settings?.params?.stop ?? undefined
? $settings.params.stop.map((str) =>
params?.stop ??
$settings?.params?.stop ?? undefined
?
(params?.stop ??
$settings.params.stop
)
.map((str) =>
decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"'))
)
: undefined,
temperature: $settings?.params?.temperature ?? undefined,
top_p: $settings?.params?.top_p ?? undefined,
frequency_penalty: $settings?.params?.frequency_penalty ?? undefined,
max_tokens: $settings?.params?.max_tokens ?? undefined,
temperature: params?.temperature ?? $settings?.params?.temperature ?? undefined,
top_p: params?.top_p ?? $settings?.params?.top_p ?? undefined,
frequency_penalty:
params?.frequency_penalty ?? $settings?.params?.frequency_penalty ?? undefined,
max_tokens: params?.max_tokens ?? $settings?.params?.max_tokens ?? undefined,
tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
files: files.length > 0 ? files : undefined,
session_id: $socket?.id,
...
...
@@ -1115,7 +1136,8 @@
chat = await updateChatById(localStorage.token, _chatId, {
models: selectedModels,
messages: messages,
history: history
history: history,
params: params
});
await chats.set(await getChatList(localStorage.token));
}
...
...
@@ -1382,6 +1404,18 @@
<audio id="audioElement" src="" style="display: none;" />
<EventConfirmDialog
bind:show={showEventConfirmation}
title={eventConfirmationTitle}
message={eventConfirmationMessage}
on:confirm={(e) => {
eventCallback(true);
}}
on:cancel={() => {
eventCallback(false);
}}
/>
{#if $showCallOverlay}
<CallOverlay
{submitPrompt}
...
...
@@ -1416,6 +1450,7 @@
{title}
bind:selectedModels
bind:showModelSelector
bind:showControls
shareEnabled={messages.length > 0}
{chat}
{initNewChat}
...
...
@@ -1425,7 +1460,7 @@
<div
class="absolute top-[4.25rem] w-full {$showSidebar
? 'md:max-w-[calc(100%-260px)]'
: ''} z-20"
: ''}
{showControls ? 'lg:pr-[24rem]' : ''}
z-20"
>
<div class=" flex flex-col gap-1 w-full">
{#each $banners.filter( (b) => (b.dismissible ? !JSON.parse(localStorage.getItem('dismissedBannerIds') ?? '[]').includes(b.id) : true) ) as banner}
...
...
@@ -1452,7 +1487,9 @@
<div class="flex flex-col flex-auto z-10">
<div
class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0 max-w-full z-10"
class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0 max-w-full z-10 scrollbar-hidden {showControls
? 'lg:pr-[24rem]'
: ''}"
id="messages-container"
bind:this={messagesContainerElement}
on:scroll={(e) => {
...
...
@@ -1477,26 +1514,31 @@
/>
</div>
</div>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
bind:selectedToolIds
bind:webSearchEnabled
bind:atSelectedModel
availableToolIds={selectedModelIds.reduce((a, e, i, arr) => {
const model = $models.find((m) => m.id === e);
if (model?.info?.meta?.toolIds ?? false) {
return [...new Set([...a, ...model.info.meta.toolIds])];
}
return a;
}, [])}
transparentBackground={$settings?.backgroundImageUrl ?? false}
{selectedModels}
{messages}
{submitPrompt}
{stopResponse}
/>
<div class={showControls ? 'lg:pr-[24rem]' : ''}>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
bind:selectedToolIds
bind:webSearchEnabled
bind:atSelectedModel
availableToolIds={selectedModelIds.reduce((a, e, i, arr) => {
const model = $models.find((m) => m.id === e);
if (model?.info?.meta?.toolIds ?? false) {
return [...new Set([...a, ...model.info.meta.toolIds])];
}
return a;
}, [])}
transparentBackground={$settings?.backgroundImageUrl ?? false}
{selectedModels}
{messages}
{submitPrompt}
{stopResponse}
/>
</div>
</div>
<ChatControls bind:show={showControls} bind:params />
</div>
{/if}
src/lib/components/chat/ChatControls.svelte
0 → 100644
View file @
f9e3c47d
<script lang="ts">
import { slide } from 'svelte/transition';
import Modal from '../common/Modal.svelte';
import Controls from './Controls/Controls.svelte';
import { onMount } from 'svelte';
export let show = false;
export let chatId = null;
export let params = {};
let largeScreen = false;
onMount(() => {
// listen to resize 1024px
const mediaQuery = window.matchMedia('(min-width: 1024px)');
const handleMediaQuery = (e) => {
if (e.matches) {
largeScreen = true;
} else {
largeScreen = false;
}
};
mediaQuery.addEventListener('change', handleMediaQuery);
handleMediaQuery(mediaQuery);
return () => {
mediaQuery.removeEventListener('change', handleMediaQuery);
};
});
</script>
{#if largeScreen}
{#if show}
<div class=" absolute bottom-0 right-0 z-20 h-full pointer-events-none">
<div class="pr-4 pt-14 pb-8 w-[24rem] h-full" in:slide={{ duration: 200, axis: 'x' }}>
<div
class="w-full h-full px-5 py-4 bg-white dark:shadow-lg dark:bg-gray-850 border border-gray-50 dark:border-gray-800 rounded-xl z-50 pointer-events-auto overflow-y-auto scrollbar-hidden"
>
<Controls
on:close={() => {
show = false;
}}
bind:params
/>
</div>
</div>
</div>
{/if}
{:else}
<Modal bind:show>
<div class=" px-6 py-4 h-full">
<Controls
on:close={() => {
show = false;
}}
bind:params
/>
</div>
</Modal>
{/if}
src/lib/components/chat/Controls/Controls.svelte
0 → 100644
View file @
f9e3c47d
<script>
import { createEventDispatcher, getContext } from 'svelte';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
import XMark from '$lib/components/icons/XMark.svelte';
import AdvancedParams from '../Settings/Advanced/AdvancedParams.svelte';
export let params = {};
</script>
<div class=" dark:text-white">
<div class=" flex justify-between dark:text-gray-100 mb-2">
<div class=" text-lg font-medium self-center font-primary">{$i18n.t('Chat Controls')}</div>
<button
class="self-center"
on:click={() => {
dispatch('close');
}}
>
<XMark className="size-4" />
</button>
</div>
<div class=" dark:text-gray-200 text-sm font-primary">
<div>
<div class="mb-1.5 font-medium">System Prompt</div>
<div>
<textarea
bind:value={params.system}
class="w-full rounded-lg px-4 py-3 text-sm dark:text-gray-300 dark:bg-gray-850 border border-gray-100 dark:border-gray-800 outline-none resize-none"
rows="3"
placeholder="Enter system prompt"
/>
</div>
</div>
<hr class="my-2 border-gray-100 dark:border-gray-800" />
<div>
<div class="mb-1.5 font-medium">Advanced Params</div>
<div>
<AdvancedParams bind:params />
</div>
</div>
</div>
</div>
src/lib/components/chat/MessageInput.svelte
View file @
f9e3c47d
...
...
@@ -316,7 +316,7 @@
</div>
{/if}
<div class="w-full">
<div class="w-full
font-primary
">
<div class=" -mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center">
<div class="flex flex-col max-w-6xl px-2.5 md:px-6 w-full">
<div class="relative">
...
...
src/lib/components/chat/MessageInput/CallOverlay.svelte
View file @
f9e3c47d
...
...
@@ -662,10 +662,11 @@
: rmsLevel * 100 > 1
? 'size-14'
: 'size-12'} transition-all rounded-full {(model?.info?.meta
?.profile_image_url ?? '/favicon.png') !== '/favicon.png'
?.profile_image_url ?? '/
static/
favicon.png') !== '/
static/
favicon.png'
? ' bg-cover bg-center bg-no-repeat'
: 'bg-black dark:bg-white'} bg-black dark:bg-white"
style
={(
model
?.
info
?.
meta
?.
profile_image_url
??
'/favicon.png'
)
!== '/favicon.png'
style
={(
model
?.
info
?.
meta
?.
profile_image_url
??
'/static/favicon.png'
)
!==
'/static/favicon.png'
?
`
background
-
image
:
url
(
'${model?.info?.meta?.profile_image_url}'
);`
:
''
}
/>
...
...
@@ -743,10 +744,11 @@
: rmsLevel * 100 > 1
? 'size-[11.5rem]'
: 'size-44'} transition-all rounded-full {(model?.info?.meta
?.profile_image_url ?? '/favicon.png') !== '/favicon.png'
?.profile_image_url ?? '/
static/
favicon.png') !== '/
static/
favicon.png'
? ' bg-cover bg-center bg-no-repeat'
: 'bg-black dark:bg-white'} "
style
={(
model
?.
info
?.
meta
?.
profile_image_url
??
'/favicon.png'
)
!== '/favicon.png'
style
={(
model
?.
info
?.
meta
?.
profile_image_url
??
'/static/favicon.png'
)
!==
'/static/favicon.png'
?
`
background
-
image
:
url
(
'${model?.info?.meta?.profile_image_url}'
);`
:
''
}
/>
...
...
src/lib/components/chat/Messages/CodeBlock.svelte
View file @
f9e3c47d
...
...
@@ -250,7 +250,8 @@ __builtins__.input = input`);
stderr ||
result) &&
'border-bottom-left-radius: 0px; border-bottom-right-radius: 0px;'}"><code
class="language-{lang} rounded-t-none whitespace-pre">{@html highlightedCode || code}</code
class="language-{lang} rounded-t-none whitespace-pre"
>{#if highlightedCode}{@html highlightedCode}{:else}{code}{/if}</code
></pre>
<div
...
...
src/lib/components/chat/Messages/Name.svelte
View file @
f9e3c47d
<div class=" self-center font-bold mb-0.5 line-clamp-1 contents">
<div class=" self-center font-
semi
bold mb-0.5 line-clamp-1 contents">
<slot />
</div>
src/lib/components/chat/Messages/Placeholder.svelte
View file @
f9e3c47d
...
...
@@ -65,7 +65,7 @@
</div>
<div
class=" mt-2 mb-4 text-3xl text-gray-800 dark:text-gray-100 font-semibold text-left flex items-center gap-4"
class=" mt-2 mb-4 text-3xl text-gray-800 dark:text-gray-100 font-semibold text-left flex items-center gap-4
font-primary
"
>
<div>
<div class=" capitalize line-clamp-1" in:fade={{ duration: 200 }}>
...
...
@@ -102,7 +102,7 @@
</div>
{/if}
{:else}
<div class=" font-medium text-gray-400 dark:text-gray-500 line-clamp-1">
<div class=" font-medium text-gray-400 dark:text-gray-500 line-clamp-1
font-p
">
{$i18n.t('How can I help you today?')}
</div>
{/if}
...
...
@@ -110,7 +110,7 @@
</div>
</div>
<div class=" w-full" in:fade={{ duration: 200, delay: 300 }}>
<div class=" w-full
font-primary
" in:fade={{ duration: 200, delay: 300 }}>
<Suggestions
suggestionPrompts={models[selectedModelIdx]?.info?.meta?.suggestion_prompts ??
$config.default_prompt_suggestions}
...
...
src/lib/components/chat/Messages/ResponseMessage.svelte
View file @
f9e3c47d
...
...
@@ -152,7 +152,10 @@
}
tooltipInstance = tippy(`#info-${message.id}`, {
content: `<span class="text-xs" id="tooltip-${message.id}">${tooltipContent}</span>`,
allowHTML: true
allowHTML: true,
theme: 'dark',
arrow: false,
offset: [0, 4]
});
}
};
...
...
src/lib/components/chat/Messages/ResponseMessage/WebSearchResults.svelte
View file @
f9e3c47d
...
...
@@ -2,32 +2,25 @@
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte';
import { Collapsible } from 'bits-ui';
import { slide } from 'svelte/transition';
import Collapsible from '$lib/components/common/Collapsible.svelte';
export let status = { urls: [], query: '' };
let state = false;
</script>
<Collapsible.Root class="w-full space-y-1" bind:open={state}>
<Collapsible.Trigger>
<div
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
>
<slot />
{#if state}
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
{:else}
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
{/if}
</div>
</Collapsible.Trigger>
<Collapsible.Content
class=" text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl"
transition={slide}
<Collapsible bind:open={state} className="w-full space-y-1">
<div
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
>
<slot />
{#if state}
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
{:else}
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
{/if}
</div>
<div class="text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl" slot="content">
{#if status?.query}
<a
href="https://www.google.com/search?q={status.query}"
...
...
@@ -93,5 +86,5 @@
</div>
</a>
{/each}
</
Collapsible.Content
>
</Collapsible
.Root
>
</
div
>
</Collapsible>
src/lib/components/chat/ModelSelector.svelte
View file @
f9e3c47d
...
...
@@ -34,7 +34,7 @@
}
</script>
<div class="flex flex-col w-full
items-center md:
items-start">
<div class="flex flex-col w-full items-start">
{#each selectedModels as selectedModel, selectedModelIdx}
<div class="flex w-full max-w-fit">
<div class="overflow-hidden w-full">
...
...
@@ -103,7 +103,7 @@
</div>
{#if showSetDefault && !$mobile}
<div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500">
<div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500
font-primary
">
<button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button>
</div>
{/if}
src/lib/components/chat/ModelSelector/Selector.svelte
View file @
f9e3c47d
...
...
@@ -206,7 +206,7 @@
}}
closeFocus={false}
>
<DropdownMenu.Trigger class="relative w-full" aria-label={placeholder}>
<DropdownMenu.Trigger class="relative w-full
font-primary
" aria-label={placeholder}>
<div
class="flex w-full text-left px-0.5 outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none"
>
...
...
@@ -222,7 +222,7 @@
<DropdownMenu.Content
class=" z-40 {$mobile
? `w-full`
: `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-
85
0/
5
0 outline-none
"
: `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-
70
0/
4
0 outline-none"
transition={flyAndScale}
side={$mobile ? 'bottom' : 'bottom-start'}
sideOffset={4}
...
...
@@ -260,7 +260,7 @@
<div class="flex gap-0.5 self-start h-full mb-0.5 -translate-x-1">
{#each item.model?.info?.meta.tags as tag}
<div
class=" text-xs font-b
lack
px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
class=" text-xs font-b
old
px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
>
{tag.name}
</div>
...
...
@@ -299,7 +299,7 @@
<div class="flex gap-0.5 self-center items-center h-full translate-y-[0.5px]">
{#each item.model?.info?.meta.tags as tag}
<div
class=" text-xs font-b
lack
px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
class=" text-xs font-b
old
px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
>
{tag.name}
</div>
...
...
src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
View file @
f9e3c47d
...
...
@@ -44,7 +44,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Seed')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.seed = (params?.seed ?? null) === null ? 0 : null;
...
...
@@ -79,7 +79,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Stop Sequence')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.stop = (params?.stop ?? null) === null ? '' : null;
...
...
@@ -113,7 +113,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Temperature')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.temperature = (params?.temperature ?? null) === null ? 0.8 : null;
...
...
@@ -159,7 +159,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.mirostat = (params?.mirostat ?? null) === null ? 0 : null;
...
...
@@ -205,7 +205,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Eta')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.mirostat_eta = (params?.mirostat_eta ?? null) === null ? 0.1 : null;
...
...
@@ -251,7 +251,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Tau')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.mirostat_tau = (params?.mirostat_tau ?? null) === null ? 5.0 : null;
...
...
@@ -297,7 +297,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.top_k = (params?.top_k ?? null) === null ? 40 : null;
...
...
@@ -343,7 +343,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Top P')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.top_p = (params?.top_p ?? null) === null ? 0.9 : null;
...
...
@@ -389,7 +389,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Frequency Penalty')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.frequency_penalty = (params?.frequency_penalty ?? null) === null ? 1.1 : null;
...
...
@@ -435,7 +435,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Repeat Last N')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.repeat_last_n = (params?.repeat_last_n ?? null) === null ? 64 : null;
...
...
@@ -481,7 +481,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Tfs Z')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.tfs_z = (params?.tfs_z ?? null) === null ? 1 : null;
...
...
@@ -527,7 +527,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Context Length')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.num_ctx = (params?.num_ctx ?? null) === null ? 2048 : null;
...
...
@@ -572,7 +572,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Batch Size (num_batch)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.num_batch = (params?.num_batch ?? null) === null ? 512 : null;
...
...
@@ -619,7 +619,7 @@
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.num_keep = (params?.num_keep ?? null) === null ? 24 : null;
...
...
@@ -664,7 +664,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.max_tokens = (params?.max_tokens ?? null) === null ? 128 : null;
...
...
@@ -711,7 +711,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('use_mmap (Ollama)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.use_mmap = (params?.use_mmap ?? null) === null ? true : null;
...
...
@@ -731,7 +731,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('use_mlock (Ollama)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.use_mlock = (params?.use_mlock ?? null) === null ? true : null;
...
...
@@ -751,7 +751,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('num_thread (Ollama)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.num_thread = (params?.num_thread ?? null) === null ? 2 : null;
...
...
@@ -797,7 +797,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Template')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
class="p-1 px-3 text-xs flex rounded transition
flex-shrink-0 outline-none
"
type="button"
on:click={() => {
params.template = (params?.template ?? null) === null ? '' : null;
...
...
src/lib/components/chat/Settings/General.svelte
View file @
f9e3c47d
...
...
@@ -95,6 +95,8 @@
}
if (themeToApply === 'dark' && !_theme.includes('oled')) {
document.documentElement.style.setProperty('--color-gray-800', '#333');
document.documentElement.style.setProperty('--color-gray-850', '#262626');
document.documentElement.style.setProperty('--color-gray-900', '#171717');
document.documentElement.style.setProperty('--color-gray-950', '#0d0d0d');
}
...
...
@@ -118,6 +120,8 @@
theme.set(_theme);
localStorage.setItem('theme', _theme);
if (_theme.includes('oled')) {
document.documentElement.style.setProperty('--color-gray-800', '#101010');
document.documentElement.style.setProperty('--color-gray-850', '#050505');
document.documentElement.style.setProperty('--color-gray-900', '#000000');
document.documentElement.style.setProperty('--color-gray-950', '#000000');
document.documentElement.classList.add('dark');
...
...
src/lib/components/chat/SettingsModal.svelte
View file @
f9e3c47d
<script lang="ts">
import { getContext } from 'svelte';
import { getContext
, tick
} from 'svelte';
import { toast } from 'svelte-sonner';
import { models, settings, user } from '$lib/stores';
import { updateUserSettings } from '$lib/apis/users';
import { getModels as _getModels } from '$lib/apis';
import { goto } from '$app/navigation';
import Modal from '../common/Modal.svelte';
import Account from './Settings/Account.svelte';
...
...
@@ -14,8 +15,6 @@
import Chats from './Settings/Chats.svelte';
import User from '../icons/User.svelte';
import Personalization from './Settings/Personalization.svelte';
import { updateUserSettings } from '$lib/apis/users';
import { goto } from '$app/navigation';
import Valves from './Settings/Valves.svelte';
const i18n = getContext('i18n');
...
...
@@ -34,6 +33,37 @@
};
let selectedTab = 'general';
// Function to handle sideways scrolling
const scrollHandler = (event) => {
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
event.preventDefault(); // Prevent default vertical scrolling
settingsTabsContainer.scrollLeft += event.deltaY; // Scroll sideways
}
};
const addScrollListener = async () => {
await tick();
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
settingsTabsContainer.addEventListener('wheel', scrollHandler);
}
};
const removeScrollListener = async () => {
await tick();
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
settingsTabsContainer.removeEventListener('wheel', scrollHandler);
}
};
$: if (show) {
addScrollListener();
} else {
removeScrollListener();
}
</script>
<Modal bind:show>
...
...
@@ -61,6 +91,7 @@
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
<div
id="settings-tabs-container"
class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
>
<button
...
...
src/lib/components/common/Banner.svelte
View file @
f9e3c47d
...
...
@@ -45,7 +45,7 @@
<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
<div class="flex justify-between self-start">
<div
class=" text-xs font-b
lack
{classNames[banner.type] ??
class=" text-xs font-b
old
{classNames[banner.type] ??
classNames['info']} w-fit px-2 rounded uppercase line-clamp-1 mr-0.5"
>
{banner.type}
...
...
@@ -54,7 +54,7 @@
{#if banner.url}
<div class="flex md:hidden group w-fit md:items-center">
<a
class="text-gray-700 dark:text-white text-xs font-bold underline"
class="text-gray-700 dark:text-white text-xs font-
semi
bold underline"
href="/assets/files/whitepaper.pdf"
target="_blank">Learn More</a
>
...
...
@@ -88,7 +88,7 @@
{#if banner.url}
<div class="hidden md:flex group w-fit md:items-center">
<a
class="text-gray-700 dark:text-white text-xs font-bold underline"
class="text-gray-700 dark:text-white text-xs font-
semi
bold underline"
href="/"
target="_blank">Learn More</a
>
...
...
@@ -116,7 +116,8 @@
on:click={() => {
dismiss(banner.id);
}}
class=" -mt-[3px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white h-1">×</button
class=" -mt-1 -mb-2 -translate-y-[1px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white"
>×</button
>
{/if}
</div>
...
...
src/lib/components/common/Collapsible.svelte
0 → 100644
View file @
f9e3c47d
<script lang="ts">
import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
export let open = false;
export let className = '';
</script>
<div class={className}>
<button on:click={() => (open = !open)}>
<slot />
</button>
{#if open}
<div transition:slide={{ duration: 300, easing: quintOut, axis: 'y' }}>
<slot name="content" />
</div>
{/if}
</div>
Prev
1
2
3
4
5
6
7
8
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment