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
a02ba52d
Unverified
Commit
a02ba52d
authored
Jun 15, 2024
by
Que Nguyen
Committed by
GitHub
Jun 15, 2024
Browse files
Merge branch 'dev' into searxng
parents
7b5f434a
1275371e
Changes
72
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
724 additions
and
296 deletions
+724
-296
src/lib/components/chat/ModelSelector/Selector.svelte
src/lib/components/chat/ModelSelector/Selector.svelte
+7
-3
src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
...b/components/chat/Settings/Advanced/AdvancedParams.svelte
+94
-0
src/lib/components/chat/Settings/General.svelte
src/lib/components/chat/Settings/General.svelte
+4
-0
src/lib/components/chat/Settings/Interface.svelte
src/lib/components/chat/Settings/Interface.svelte
+32
-0
src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte
...nents/chat/Settings/Personalization/AddMemoryModal.svelte
+4
-3
src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte
...ents/chat/Settings/Personalization/EditMemoryModal.svelte
+136
-0
src/lib/components/chat/Settings/Personalization/ManageModal.svelte
...mponents/chat/Settings/Personalization/ManageModal.svelte
+46
-3
src/lib/components/common/ConfirmDialog.svelte
src/lib/components/common/ConfirmDialog.svelte
+5
-2
src/lib/components/common/Tooltip.svelte
src/lib/components/common/Tooltip.svelte
+2
-0
src/lib/components/layout/Sidebar.svelte
src/lib/components/layout/Sidebar.svelte
+58
-284
src/lib/components/layout/Sidebar/ChatItem.svelte
src/lib/components/layout/Sidebar/ChatItem.svelte
+281
-0
src/lib/components/workspace/Models.svelte
src/lib/components/workspace/Models.svelte
+13
-1
src/lib/i18n/locales/ar-BH/translation.json
src/lib/i18n/locales/ar-BH/translation.json
+5
-0
src/lib/i18n/locales/bg-BG/translation.json
src/lib/i18n/locales/bg-BG/translation.json
+5
-0
src/lib/i18n/locales/bn-BD/translation.json
src/lib/i18n/locales/bn-BD/translation.json
+5
-0
src/lib/i18n/locales/ca-ES/translation.json
src/lib/i18n/locales/ca-ES/translation.json
+5
-0
src/lib/i18n/locales/ceb-PH/translation.json
src/lib/i18n/locales/ceb-PH/translation.json
+5
-0
src/lib/i18n/locales/de-DE/translation.json
src/lib/i18n/locales/de-DE/translation.json
+5
-0
src/lib/i18n/locales/dg-DG/translation.json
src/lib/i18n/locales/dg-DG/translation.json
+5
-0
src/lib/i18n/locales/en-GB/translation.json
src/lib/i18n/locales/en-GB/translation.json
+7
-0
No files found.
src/lib/components/chat/ModelSelector/Selector.svelte
View file @
a02ba52d
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { marked } from 'marked';
import { flyAndScale } from '$lib/utils/transitions';
import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
...
...
@@ -333,9 +334,12 @@
{#if item.model?.info?.meta?.description}
<Tooltip
content={`${sanitizeResponseContent(
item.model?.info?.meta?.description
).replaceAll('\n', '<br>')}`}
content={`${marked.parse(
sanitizeResponseContent(item.model?.info?.meta?.description).replaceAll(
'\n',
'<br>'
)
)}`}
>
<div class="">
<svg
...
...
src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte
View file @
a02ba52d
...
...
@@ -21,6 +21,8 @@
top_p: null,
tfs_z: null,
num_ctx: null,
num_batch: null,
num_keep: null,
max_tokens: null,
use_mmap: null,
use_mlock: null,
...
...
@@ -565,6 +567,98 @@
{/if}
</div>
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Batch Size (num_batch)')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
params.num_batch = (params?.num_batch ?? null) === null ? 512 : null;
}}
>
{#if (params?.num_batch ?? null) === null}
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
{#if (params?.num_batch ?? null) !== null}
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
id="steps-range"
type="range"
min="256"
max="8192"
step="256"
bind:value={params.num_batch}
class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</div>
<div class="">
<input
bind:value={params.num_batch}
type="number"
class=" bg-transparent text-center w-14"
min="256"
step="256"
/>
</div>
</div>
{/if}
</div>
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">
{$i18n.t('Tokens To Keep On Context Refresh (num_keep)')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
params.num_keep = (params?.num_keep ?? null) === null ? 24 : null;
}}
>
{#if (params?.num_keep ?? null) === null}
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
{#if (params?.num_keep ?? null) !== null}
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
id="steps-range"
type="range"
min="-1"
max="10240000"
step="1"
bind:value={params.num_keep}
class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</div>
<div class="">
<input
bind:value={params.num_keep}
type="number"
class=" bg-transparent text-center w-14"
min="-1"
step="1"
/>
</div>
</div>
{/if}
</div>
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div>
...
...
src/lib/components/chat/Settings/General.svelte
View file @
a02ba52d
...
...
@@ -55,6 +55,8 @@
stop: null,
tfs_z: null,
num_ctx: null,
num_batch: null,
num_keep: null,
max_tokens: null
};
...
...
@@ -308,6 +310,8 @@
top_p: params.top_p !== null ? params.top_p : undefined,
tfs_z: params.tfs_z !== null ? params.tfs_z : undefined,
num_ctx: params.num_ctx !== null ? params.num_ctx : undefined,
num_batch: params.num_batch !== null ? params.num_batch : undefined,
num_keep: params.num_keep !== null ? params.num_keep : undefined,
max_tokens: params.max_tokens !== null ? params.max_tokens : undefined,
use_mmap: params.use_mmap !== null ? params.use_mmap : undefined,
use_mlock: params.use_mlock !== null ? params.use_mlock : undefined,
...
...
src/lib/components/chat/Settings/Interface.svelte
View file @
a02ba52d
...
...
@@ -20,9 +20,12 @@
// Interface
let defaultModelId = '';
let showUsername = false;
let chatBubble = true;
let chatDirection: 'LTR' | 'RTL' = 'LTR';
let showEmojiInCall = false;
const toggleSplitLargeChunks = async () => {
splitLargeChunks = !splitLargeChunks;
saveSettings({ splitLargeChunks: splitLargeChunks });
...
...
@@ -43,6 +46,11 @@
saveSettings({ showUsername: showUsername });
};
const toggleEmojiInCall = async () => {
showEmojiInCall = !showEmojiInCall;
saveSettings({ showEmojiInCall: showEmojiInCall });
};
const toggleTitleAutoGenerate = async () => {
titleAutoGenerate = !titleAutoGenerate;
saveSettings({
...
...
@@ -88,8 +96,12 @@
onMount(async () => {
titleAutoGenerate = $settings?.title?.auto ?? true;
responseAutoCopy = $settings.responseAutoCopy ?? false;
showUsername = $settings.showUsername ?? false;
showEmojiInCall = $settings.showEmojiInCall ?? false;
chatBubble = $settings.chatBubble ?? true;
widescreenMode = $settings.widescreenMode ?? false;
splitLargeChunks = $settings.splitLargeChunks ?? false;
...
...
@@ -192,6 +204,26 @@
</div>
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Display Emoji in Call')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
toggleEmojiInCall();
}}
type="button"
>
{#if showEmojiInCall === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
{#if !$settings.chatBubble}
<div>
<div class=" py-0.5 flex w-full justify-between">
...
...
src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte
View file @
a02ba52d
...
...
@@ -2,13 +2,12 @@
import { createEventDispatcher, getContext } from 'svelte';
import Modal from '$lib/components/common/Modal.svelte';
import { addNewMemory } from '$lib/apis/memories';
import { addNewMemory
, updateMemoryById
} from '$lib/apis/memories';
import { toast } from 'svelte-sonner';
const dispatch = createEventDispatcher();
export let show;
const i18n = getContext('i18n');
let loading = false;
...
...
@@ -38,7 +37,9 @@
<Modal bind:show size="sm">
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
<div class=" text-lg font-medium self-center">{$i18n.t('Add Memory')}</div>
<div class=" text-lg font-medium self-center">
{$i18n.t('Add Memory')}
</div>
<button
class="self-center"
on:click={() => {
...
...
src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte
0 → 100644
View file @
a02ba52d
<script>
import { createEventDispatcher, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import { updateMemoryById } from '$lib/apis/memories';
import Modal from '$lib/components/common/Modal.svelte';
const dispatch = createEventDispatcher();
export let show;
export let memory = {};
const i18n = getContext('i18n');
let loading = false;
let content = '';
$: if (show) {
setContent();
}
const setContent = () => {
content = memory.content;
};
const submitHandler = async () => {
loading = true;
const res = await updateMemoryById(localStorage.token, memory.id, content).catch((error) => {
toast.error(error);
return null;
});
if (res) {
console.log(res);
toast.success('Memory updated successfully');
dispatch('save');
show = false;
}
loading = false;
};
</script>
<Modal bind:show size="sm">
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
<div class=" text-lg font-medium self-center">
{$i18n.t('Edit Memory')}
</div>
<button
class="self-center"
on:click={() => {
show = false;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-5 h-5"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
<div class="flex flex-col md:flex-row w-full px-5 pb-4 md:space-x-4 dark:text-gray-200">
<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
<form
class="flex flex-col w-full"
on:submit|preventDefault={() => {
submitHandler();
}}
>
<div class="">
<textarea
bind:value={content}
class=" bg-transparent w-full text-sm resize-none rounded-xl p-3 outline outline-1 outline-gray-100 dark:outline-gray-800"
rows="3"
placeholder={$i18n.t('Enter a detail about yourself for your LLMs to recall')}
/>
<div class="text-xs text-gray-500">
ⓘ {$i18n.t('Refer to yourself as "User" (e.g., "User is learning Spanish")')}
</div>
</div>
<div class="flex justify-end pt-1 text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-3xl flex flex-row space-x-1 items-center {loading
? ' cursor-not-allowed'
: ''}"
type="submit"
disabled={loading}
>
{$i18n.t('Update')}
{#if loading}
<div class="ml-2 self-center">
<svg
class=" w-4 h-4"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_ajPY {
transform-origin: center;
animation: spinner_AtaB 0.75s infinite linear;
}
@keyframes spinner_AtaB {
100% {
transform: rotate(360deg);
}
}
</style><path
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
opacity=".25"
/><path
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
class="spinner_ajPY"
/></svg
>
</div>
{/if}
</button>
</div>
</form>
</div>
</div>
</div>
</Modal>
src/lib/components/chat/Settings/Personalization/ManageModal.svelte
View file @
a02ba52d
...
...
@@ -10,18 +10,24 @@
import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { error } from '@sveltejs/kit';
import EditMemoryModal from './EditMemoryModal.svelte';
const i18n = getContext('i18n');
export let show = false;
let memories = [];
let loading = true;
let showAddMemoryModal = false;
let showEditMemoryModal = false;
$: if (show) {
let selectedMemory = null;
$: if (show && memories.length === 0 && loading) {
(async () => {
memories = await getMemories(localStorage.token);
loading = false;
})();
}
</script>
...
...
@@ -62,7 +68,9 @@
>
<tr>
<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created At')} </th>
<th scope="col" class="px-3 py-2 hidden md:flex">
{$i18n.t('Last Modified')}
</th>
<th scope="col" class="px-3 py-2 text-right" />
</tr>
</thead>
...
...
@@ -76,11 +84,38 @@
</td>
<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
<div class="my-auto whitespace-nowrap">
{dayjs(memory.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
{dayjs(memory.updated_at * 1000).format(
$i18n.t('MMMM DD, YYYY hh:mm:ss A')
)}
</div>
</td>
<td class="px-3 py-1">
<div class="flex justify-end w-full">
<Tooltip content="Edit">
<button
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
on:click={() => {
selectedMemory = memory;
showEditMemoryModal = true;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4 s-FoVA_WMOgxUD"
><path
stroke-linecap="round"
stroke-linejoin="round"
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
class="s-FoVA_WMOgxUD"
/></svg
>
</button>
</Tooltip>
<Tooltip content="Delete">
<button
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
...
...
@@ -163,3 +198,11 @@
memories = await getMemories(localStorage.token);
}}
/>
<EditMemoryModal
bind:show={showEditMemoryModal}
memory={selectedMemory}
on:save={async () => {
memories = await getMemories(localStorage.token);
}}
/>
src/lib/components/common/ConfirmDialog.svelte
View file @
a02ba52d
...
...
@@ -9,6 +9,9 @@
export let title = 'Confirm your action';
export let message = 'This action cannot be undone. Do you wish to continue?';
export let cancelLabel = 'Cancel';
export let confirmLabel = 'Confirm';
export let show = false;
let modalElement = null;
let mounted = false;
...
...
@@ -70,7 +73,7 @@
}}
type="button"
>
C
ancel
{c
ancel
Label}
</button>
<button
class="bg-gray-900 hover:bg-gray-850 text-gray-100 dark:bg-gray-100 dark:hover:bg-white dark:text-gray-800 font-medium w-full py-2.5 rounded-lg transition"
...
...
@@ -80,7 +83,7 @@
}}
type="button"
>
C
onfirm
{c
onfirm
Label}
</button>
</div>
</div>
...
...
src/lib/components/common/Tooltip.svelte
View file @
a02ba52d
<script lang="ts">
import { onDestroy } from 'svelte';
import { marked } from 'marked';
import tippy from 'tippy.js';
export let placement = 'top';
...
...
src/lib/components/layout/Sidebar.svelte
View file @
a02ba52d
<script lang="ts">
import { toast } from 'svelte-sonner';
import { goto } from '$app/navigation';
import {
user,
...
...
@@ -11,10 +12,11 @@
mobile,
showArchivedChats
} from '$lib/stores';
import { onMount, getContext } from 'svelte';
import { onMount, getContext
, tick
} from 'svelte';
const i18n = getContext('i18n');
import { updateUserSettings } from '$lib/apis/users';
import {
deleteChatById,
getChatList,
...
...
@@ -25,37 +27,25 @@
archiveChatById,
cloneChatById
} from '$lib/apis/chats';
import { toast } from 'svelte-sonner';
import { fade, slide } from 'svelte/transition';
import { WEBUI_BASE_URL } from '$lib/constants';
import Tooltip from '../common/Tooltip.svelte';
import ChatMenu from './Sidebar/ChatMenu.svelte';
import ShareChatModal from '../chat/ShareChatModal.svelte';
import ArchiveBox from '../icons/ArchiveBox.svelte';
import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
import UserMenu from './Sidebar/UserMenu.svelte';
import { updateUserSettings } from '$lib/apis/users';
import ChatItem from './Sidebar/ChatItem.svelte';
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
const BREAKPOINT = 768;
let show = false;
let navElement;
let title: string = 'UI';
let search = '';
let sh
areChatId = null
;
let sh
iftKey = false
;
let selectedChatId = null;
let deleteChat = null;
let chatDeleteId = null;
let chatTitleEditId = null;
let chatTitle = '';
let showShareChatModal = false;
let showDeleteConfirm = false;
let showDropdown = false;
let isEditing = false;
let filteredChatList = [];
$: filteredChatList = $chats.filter((chat) => {
...
...
@@ -78,13 +68,6 @@
}
});
mobile;
const onResize = () => {
if ($showSidebar && window.innerWidth < BREAKPOINT) {
showSidebar.set(false);
}
};
onMount(async () => {
mobile.subscribe((e) => {
if ($showSidebar && e) {
...
...
@@ -125,10 +108,28 @@
checkDirection();
};
const onKeyDown = (e) => {
if (e.key === 'Shift') {
shiftKey = true;
}
};
const onKeyUp = (e) => {
if (e.key === 'Shift') {
shiftKey = false;
}
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
window.addEventListener('touchstart', onTouchStart);
window.addEventListener('touchend', onTouchEnd);
return () => {
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('touchstart', onTouchStart);
window.removeEventListener('touchend', onTouchEnd);
};
...
...
@@ -149,69 +150,29 @@
await chats.set(enrichedChats);
};
const loadChat = async (id) => {
goto(`/c/${id}`);
};
const editChatTitle = async (id, _title) => {
if (_title === '') {
toast.error($i18n.t('Title cannot be an empty string.'));
} else {
title = _title;
await updateChatById(localStorage.token, id, {
title: _title
});
await chats.set(await getChatList(localStorage.token));
}
const saveSettings = async (updated) => {
await settings.set({ ...$settings, ...updated });
await updateUserSettings(localStorage.token, { ui: $settings });
location.href = '/';
};
const deleteChat = async (id) => {
const deleteChat
Handler
= async (id) => {
const res = await deleteChatById(localStorage.token, id).catch((error) => {
toast.error(error);
chatDeleteId = null;
return null;
});
if (res) {
if ($chatId === id) {
await chatId.set('');
await tick();
goto('/');
}
await chats.set(await getChatList(localStorage.token));
}
};
const cloneChatHandler = async (id) => {
const res = await cloneChatById(localStorage.token, id).catch((error) => {
toast.error(error);
return null;
});
if (res) {
goto(`/c/${res.id}`);
await chats.set(await getChatList(localStorage.token));
}
};
const saveSettings = async (updated) => {
await settings.set({ ...$settings, ...updated });
await updateUserSettings(localStorage.token, { ui: $settings });
location.href = '/';
};
const archiveChatHandler = async (id) => {
await archiveChatById(localStorage.token, id);
await chats.set(await getChatList(localStorage.token));
};
const focusEdit = async (node: HTMLInputElement) => {
node.focus();
};
</script>
<ShareChatModal bind:show={showShareChatModal} chatId={shareChatId} />
<ArchivedChatsModal
bind:show={$showArchivedChats}
on:change={async () => {
...
...
@@ -219,6 +180,18 @@
}}
/>
<DeleteConfirmDialog
bind:show={showDeleteConfirm}
title="Delete chat?"
on:confirm={() => {
deleteChatHandler(deleteChat.id);
}}
>
<div class=" text-sm text-gray-500">
This will delete <span class=" font-semibold">{deleteChat.title}</span>.
</div>
</DeleteConfirmDialog>
<!-- svelte-ignore a11y-no-static-element-interactions -->
{#if $showSidebar}
...
...
@@ -252,12 +225,10 @@
draggable="false"
on:click={async () => {
selectedChatId = null;
await goto('/');
const newChatButton = document.getElementById('new-chat-button');
setTimeout(() => {
newChatButton?.click();
if ($mobile) {
showSidebar.set(false);
}
...
...
@@ -486,215 +457,18 @@
</div>
{/if}
<div class=" w-full pr-2 relative group">
{#if chatTitleEditId === chat.id}
<div
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
chat.id === chatTitleEditId ||
chat.id === chatDeleteId
? 'bg-gray-200 dark:bg-gray-900'
: chat.id === selectedChatId
? 'bg-gray-100 dark:bg-gray-950'
: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
>
<input
use:focusEdit
bind:value={chatTitle}
class=" bg-transparent w-full outline-none mr-10"
/>
</div>
{:else}
<a
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
chat.id === chatTitleEditId ||
chat.id === chatDeleteId
? 'bg-gray-200 dark:bg-gray-900'
: chat.id === selectedChatId
? 'bg-gray-100 dark:bg-gray-950'
: ' group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
href="/c/{chat.id}"
on:click={() => {
selectedChatId = chat.id;
if ($mobile) {
showSidebar.set(false);
}
}}
on:dblclick={() => {
chatTitle = chat.title;
chatTitleEditId = chat.id;
}}
draggable="false"
>
<div class=" flex self-center flex-1 w-full">
<div class=" text-left self-center overflow-hidden w-full h-[20px]">
{chat.title}
</div>
</div>
</a>
{/if}
<div
class="
{chat.id === $chatId || chat.id === chatTitleEditId || chat.id === chatDeleteId
? 'from-gray-200 dark:from-gray-900'
: chat.id === selectedChatId
? 'from-gray-100 dark:from-gray-950'
: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
to-transparent"
>
{#if chatTitleEditId === chat.id}
<div class="flex self-center space-x-1.5 z-10">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
editChatTitle(chat.id, chatTitle);
chatTitleEditId = null;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
chatTitleEditId = null;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else if chatDeleteId === chat.id}
<div class="flex self-center space-x-1.5 z-10">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
deleteChat(chat.id);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
chatDeleteId = null;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else}
<div class="flex self-center space-x-1 z-10">
<ChatMenu
chatId={chat.id}
cloneChatHandler={() => {
cloneChatHandler(chat.id);
}}
shareHandler={() => {
shareChatId = selectedChatId;
showShareChatModal = true;
}}
archiveChatHandler={() => {
archiveChatHandler(chat.id);
}}
renameHandler={() => {
chatTitle = chat.title;
chatTitleEditId = chat.id;
}}
deleteHandler={() => {
chatDeleteId = chat.id;
}}
onClose={() => {
selectedChatId = null;
}}
>
<button
aria-label="Chat Menu"
class=" self-center dark:hover:text-white transition"
on:click={() => {
selectedChatId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
</ChatMenu>
{#if chat.id === $chatId}
<button
id="delete-chat-button"
class="hidden"
on:click={() => {
chatDeleteId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
{/if}
</div>
{/if}
</div>
</div>
<ChatItem
{chat}
{shiftKey}
selected={selectedChatId === chat.id}
on:select={() => {
selectedChatId = chat.id;
}}
on:delete={() => {
deleteChat = chat;
showDeleteConfirm = true;
}}
/>
{/each}
</div>
</div>
...
...
src/lib/components/layout/Sidebar/ChatItem.svelte
0 → 100644
View file @
a02ba52d
<script lang="ts">
import { toast } from 'svelte-sonner';
import { goto, invalidate, invalidateAll } from '$app/navigation';
import { onMount, getContext, createEventDispatcher, tick } from 'svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
import {
archiveChatById,
cloneChatById,
deleteChatById,
getChatList,
updateChatById
} from '$lib/apis/chats';
import { chatId, chats, mobile, showSidebar } from '$lib/stores';
import ChatMenu from './ChatMenu.svelte';
import ShareChatModal from '$lib/components/chat/ShareChatModal.svelte';
import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
export let chat;
export let selected = false;
export let shiftKey = false;
let mouseOver = false;
let showShareChatModal = false;
let confirmEdit = false;
let chatTitle = chat.title;
const editChatTitle = async (id, _title) => {
if (_title === '') {
toast.error($i18n.t('Title cannot be an empty string.'));
} else {
await updateChatById(localStorage.token, id, {
title: _title
});
await chats.set(await getChatList(localStorage.token));
}
};
const cloneChatHandler = async (id) => {
const res = await cloneChatById(localStorage.token, id).catch((error) => {
toast.error(error);
return null;
});
if (res) {
goto(`/c/${res.id}`);
await chats.set(await getChatList(localStorage.token));
}
};
const archiveChatHandler = async (id) => {
await archiveChatById(localStorage.token, id);
await chats.set(await getChatList(localStorage.token));
};
const focusEdit = async (node: HTMLInputElement) => {
node.focus();
};
</script>
<ShareChatModal bind:show={showShareChatModal} chatId={chat.id} />
<div class=" w-full pr-2 relative group">
{#if confirmEdit}
<div
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId || confirmEdit
? 'bg-gray-200 dark:bg-gray-900'
: selected
? 'bg-gray-100 dark:bg-gray-950'
: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
>
<input
use:focusEdit
bind:value={chatTitle}
class=" bg-transparent w-full outline-none mr-10"
/>
</div>
{:else}
<a
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId || confirmEdit
? 'bg-gray-200 dark:bg-gray-900'
: selected
? 'bg-gray-100 dark:bg-gray-950'
: ' group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
href="/c/{chat.id}"
on:click={() => {
dispatch('select');
if ($mobile) {
showSidebar.set(false);
}
}}
on:dblclick={() => {
chatTitle = chat.title;
confirmEdit = true;
}}
on:mouseenter={(e) => {
mouseOver = true;
}}
on:mouseleave={(e) => {
mouseOver = false;
}}
on:focus={(e) => {}}
draggable="false"
>
<div class=" flex self-center flex-1 w-full">
<div class=" text-left self-center overflow-hidden w-full h-[20px]">
{chat.title}
</div>
</div>
</a>
{/if}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="
{chat.id === $chatId || confirmEdit
? 'from-gray-200 dark:from-gray-900'
: selected
? 'from-gray-100 dark:from-gray-950'
: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
to-transparent"
on:mouseenter={(e) => {
mouseOver = true;
}}
on:mouseleave={(e) => {
mouseOver = false;
}}
>
{#if confirmEdit}
<div class="flex self-center space-x-1.5 z-10">
<Tooltip content="Confirm">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
editChatTitle(chat.id, chatTitle);
confirmEdit = false;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
</Tooltip>
<Tooltip content="Cancel">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
confirmEdit = false;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</Tooltip>
</div>
{:else if shiftKey && mouseOver}
<div class=" flex items-center self-center space-x-1.5">
<Tooltip content="Archive" className="flex items-center">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
archiveChatHandler(chat.id);
}}
type="button"
>
<ArchiveBox className="size-4 translate-y-[0.5px]" strokeWidth="2" />
</button>
</Tooltip>
<Tooltip content="Delete">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
deleteChat(chat.id);
}}
type="button"
>
<GarbageBin strokeWidth="2" />
</button>
</Tooltip>
</div>
{:else}
<div class="flex self-center space-x-1 z-10">
<ChatMenu
chatId={chat.id}
cloneChatHandler={() => {
cloneChatHandler(chat.id);
}}
shareHandler={() => {
showShareChatModal = true;
}}
archiveChatHandler={() => {
archiveChatHandler(chat.id);
}}
renameHandler={() => {
chatTitle = chat.title;
confirmEdit = true;
}}
deleteHandler={() => {
dispatch('delete');
}}
onClose={() => {
selected = false;
}}
>
<button
aria-label="Chat Menu"
class=" self-center dark:hover:text-white transition"
on:click={() => {
dispatch('select');
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
</ChatMenu>
{#if chat.id === $chatId}
<!-- Shortcut support using "delete-chat-button" id -->
<button
id="delete-chat-button"
class="hidden"
on:click={() => {
dispatch('delete');
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
{/if}
</div>
{/if}
</div>
</div>
src/lib/components/workspace/Models.svelte
View file @
a02ba52d
...
...
@@ -17,15 +17,19 @@
import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
import ModelMenu from './Models/ModelMenu.svelte';
import ModelDeleteConfirmDialog from '../common/ConfirmDialog.svelte';
const i18n = getContext('i18n');
let showModelDeleteConfirm = false;
let localModelfiles = [];
let importFiles;
let modelsImportInputElement: HTMLInputElement;
let _models = [];
let selectedModel = null;
let sortable = null;
let searchValue = '';
...
...
@@ -199,6 +203,13 @@
</title>
</svelte:head>
<ModelDeleteConfirmDialog
bind:show={showModelDeleteConfirm}
on:confirm={() => {
deleteModelHandler(selectedModel);
}}
/>
<div class=" text-lg font-semibold mb-3">{$i18n.t('Models')}</div>
<div class=" flex w-full space-x-2">
...
...
@@ -339,7 +350,8 @@
hideModelHandler(model);
}}
deleteHandler={() => {
deleteModelHandler(model);
selectedModel = model;
showModelDeleteConfirm = true;
}}
onClose={() => {}}
>
...
...
src/lib/i18n/locales/ar-BH/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
"استجابة خطاء"
,
"Banners"
:
"لافتات"
,
"Base Model (From)"
:
"النموذج الأساسي (من)"
,
"Batch Size (num_batch)"
:
""
,
"before"
:
"قبل"
,
"Being lazy"
:
"كون كسول"
,
"Brave Search API Key"
:
"مفتاح واجهة برمجة تطبيقات البحث الشجاع"
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"اكتشاف وتنزيل واستكشاف المطالبات المخصصة"
,
"Discover, download, and explore model presets"
:
"اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"اعرض اسم المستخدم بدلاً منك في الدردشة"
,
"Document"
:
"المستند"
,
"Document Settings"
:
"أعدادات المستند"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
"أدخل مفتاح واجهة برمجة تطبيقات Serpstack"
,
"Enter stop sequence"
:
"أدخل تسلسل التوقف"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"أدخل Top K"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"الرابط (e.g. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
"URL (e.g. http://localhost:11434)"
,
...
...
@@ -492,6 +495,7 @@
"System"
:
"النظام"
,
"System Prompt"
:
"محادثة النظام"
,
"Tags"
:
"الوسوم"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
"أخبرنا المزيد:"
,
"Temperature"
:
"درجة حرارة"
,
"Template"
:
"نموذج"
,
...
...
@@ -522,6 +526,7 @@
"Today"
:
"اليوم"
,
"Toggle settings"
:
"فتح وأغلاق الاعدادات"
,
"Toggle sidebar"
:
"فتح وأغلاق الشريط الجانبي"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Top P"
,
...
...
src/lib/i18n/locales/bg-BG/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
"Невалиден отговор от API"
,
"Banners"
:
"Банери"
,
"Base Model (From)"
:
"Базов модел (от)"
,
"Batch Size (num_batch)"
:
""
,
"before"
:
"преди"
,
"Being lazy"
:
"Да бъдеш мързелив"
,
"Brave Search API Key"
:
"Смел ключ за API за търсене"
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"Откриване, сваляне и преглед на персонализирани промптове"
,
"Discover, download, and explore model presets"
:
"Откриване, сваляне и преглед на пресетове на модели"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"Показване на потребителското име вместо Вие в чата"
,
"Document"
:
"Документ"
,
"Document Settings"
:
"Документ Настройки"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
"Въведете Serpstack API ключ"
,
"Enter stop sequence"
:
"Въведете стоп последователност"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Въведете Top K"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"Въведете URL (напр. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
"Въведете URL (напр. http://localhost:11434)"
,
...
...
@@ -488,6 +491,7 @@
"System"
:
"Система"
,
"System Prompt"
:
"Системен Промпт"
,
"Tags"
:
"Тагове"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
"Повече информация:"
,
"Temperature"
:
"Температура"
,
"Template"
:
"Шаблон"
,
...
...
@@ -518,6 +522,7 @@
"Today"
:
"днес"
,
"Toggle settings"
:
"Toggle settings"
,
"Toggle sidebar"
:
"Toggle sidebar"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Top P"
,
...
...
src/lib/i18n/locales/bn-BD/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
"খারাপ প্রতিক্রিয়া"
,
"Banners"
:
"ব্যানার"
,
"Base Model (From)"
:
"বেস মডেল (থেকে)"
,
"Batch Size (num_batch)"
:
""
,
"before"
:
"পূর্ববর্তী"
,
"Being lazy"
:
"অলস হওয়া"
,
"Brave Search API Key"
:
"সাহসী অনুসন্ধান API কী"
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"কাস্টম প্রম্পটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন"
,
"Discover, download, and explore model presets"
:
"মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান"
,
"Document"
:
"ডকুমেন্ট"
,
"Document Settings"
:
"ডকুমেন্ট সেটিংসমূহ"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
"Serpstack API কী লিখুন"
,
"Enter stop sequence"
:
"স্টপ সিকোয়েন্স লিখুন"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Top K লিখুন"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"ইউআরএল দিন (যেমন http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
"ইউআরএল দিন (যেমন http://localhost:11434)"
,
...
...
@@ -488,6 +491,7 @@
"System"
:
"সিস্টেম"
,
"System Prompt"
:
"সিস্টেম প্রম্পট"
,
"Tags"
:
"ট্যাগসমূহ"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
"আরও বলুন:"
,
"Temperature"
:
"তাপমাত্রা"
,
"Template"
:
"টেম্পলেট"
,
...
...
@@ -518,6 +522,7 @@
"Today"
:
"আজ"
,
"Toggle settings"
:
"সেটিংস টোগল"
,
"Toggle sidebar"
:
"সাইডবার টোগল"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Top P"
,
...
...
src/lib/i18n/locales/ca-ES/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
"Resposta Erroni"
,
"Banners"
:
"Banners"
,
"Base Model (From)"
:
"Model base (des de)"
,
"Batch Size (num_batch)"
:
""
,
"before"
:
"abans"
,
"Being lazy"
:
"Ser l'estupidez"
,
"Brave Search API Key"
:
"Clau API Brave Search"
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"Descobreix, descarrega i explora prompts personalitzats"
,
"Discover, download, and explore model presets"
:
"Descobreix, descarrega i explora presets de models"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"Mostra el nom d'usuari en lloc de 'Tu' al Xat"
,
"Document"
:
"Document"
,
"Document Settings"
:
"Configuració de Documents"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
"Introduïu la clau de l'API Serpstack"
,
"Enter stop sequence"
:
"Introdueix la seqüència de parada"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Introdueix Top K"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"Introdueix l'URL (p. ex. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
"Introdueix l'URL (p. ex. http://localhost:11434)"
,
...
...
@@ -489,6 +492,7 @@
"System"
:
"Sistema"
,
"System Prompt"
:
"Prompt del Sistema"
,
"Tags"
:
"Etiquetes"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
"Dóna'ns més informació:"
,
"Temperature"
:
"Temperatura"
,
"Template"
:
"Plantilla"
,
...
...
@@ -519,6 +523,7 @@
"Today"
:
"Avui"
,
"Toggle settings"
:
"Commuta configuracions"
,
"Toggle sidebar"
:
"Commuta barra lateral"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Top P"
,
...
...
src/lib/i18n/locales/ceb-PH/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
""
,
"Banners"
:
""
,
"Base Model (From)"
:
""
,
"Batch Size (num_batch)"
:
""
,
"before"
:
""
,
"Being lazy"
:
""
,
"Brave Search API Key"
:
""
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"Pagdiskubre, pag-download ug pagsuhid sa mga naandan nga pag-aghat"
,
"Discover, download, and explore model presets"
:
"Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan"
,
"Document"
:
"Dokumento"
,
"Document Settings"
:
"Mga Setting sa Dokumento"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
""
,
"Enter stop sequence"
:
"Pagsulod sa katapusan nga han-ay"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Pagsulod sa Top K"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"Pagsulod sa URL (e.g. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
""
,
...
...
@@ -488,6 +491,7 @@
"System"
:
"Sistema"
,
"System Prompt"
:
"Madasig nga Sistema"
,
"Tags"
:
"Mga tag"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
""
,
"Temperature"
:
"Temperatura"
,
"Template"
:
"Modelo"
,
...
...
@@ -518,6 +522,7 @@
"Today"
:
""
,
"Toggle settings"
:
"I-toggle ang mga setting"
,
"Toggle sidebar"
:
"I-toggle ang sidebar"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Ibabaw nga P"
,
...
...
src/lib/i18n/locales/de-DE/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
"Schlechte Antwort"
,
"Banners"
:
"Banner"
,
"Base Model (From)"
:
"Basismodell (von)"
,
"Batch Size (num_batch)"
:
""
,
"before"
:
"bereits geteilt"
,
"Being lazy"
:
"Faul sein"
,
"Brave Search API Key"
:
"API-Schlüssel für die Brave-Suche"
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"Benutzerdefinierte Prompts entdecken, herunterladen und erkunden"
,
"Discover, download, and explore model presets"
:
"Modellvorgaben entdecken, herunterladen und erkunden"
,
"Dismissible"
:
"ausblendbar"
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"Den Benutzernamen anstelle von 'du' im Chat anzeigen"
,
"Document"
:
"Dokument"
,
"Document Settings"
:
"Dokumenteinstellungen"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
"Geben Sie den Serpstack-API-Schlüssel ein"
,
"Enter stop sequence"
:
"Stop-Sequenz eingeben"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Gib Top K ein"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"Gib die URL ein (z.B. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
"Gib die URL ein (z.B. http://localhost:11434)"
,
...
...
@@ -488,6 +491,7 @@
"System"
:
"System"
,
"System Prompt"
:
"System-Prompt"
,
"Tags"
:
"Tags"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
"Erzähl uns mehr"
,
"Temperature"
:
"Temperatur"
,
"Template"
:
"Vorlage"
,
...
...
@@ -518,6 +522,7 @@
"Today"
:
"Heute"
,
"Toggle settings"
:
"Einstellungen umschalten"
,
"Toggle sidebar"
:
"Seitenleiste umschalten"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K"
,
"Top P"
:
"Top P"
,
...
...
src/lib/i18n/locales/dg-DG/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
""
,
"Banners"
:
""
,
"Base Model (From)"
:
""
,
"Batch Size (num_batch)"
:
""
,
"before"
:
""
,
"Being lazy"
:
""
,
"Brave Search API Key"
:
""
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
"Discover, download, and explore custom prompts"
,
"Discover, download, and explore model presets"
:
"Discover, download, and explore model presets"
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
"Display username instead of You in Chat"
,
"Document"
:
"Document"
,
"Document Settings"
:
"Document Settings"
,
...
...
@@ -205,6 +207,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
""
,
"Enter stop sequence"
:
"Enter stop bark"
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
"Enter Top Wow"
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
"Enter URL (e.g. http://127.0.0.1:7860/)"
,
"Enter URL (e.g. http://localhost:11434)"
:
""
,
...
...
@@ -488,6 +491,7 @@
"System"
:
"System very system"
,
"System Prompt"
:
"System Prompt much prompt"
,
"Tags"
:
"Tags very tags"
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
""
,
"Temperature"
:
"Temperature very temp"
,
"Template"
:
"Template much template"
,
...
...
@@ -518,6 +522,7 @@
"Today"
:
""
,
"Toggle settings"
:
"Toggle settings much toggle"
,
"Toggle sidebar"
:
"Toggle sidebar much toggle"
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
"Top K very top"
,
"Top P"
:
"Top P very top"
,
...
...
src/lib/i18n/locales/en-GB/translation.json
View file @
a02ba52d
...
...
@@ -69,6 +69,7 @@
"Bad Response"
:
""
,
"Banners"
:
""
,
"Base Model (From)"
:
""
,
"Batch Size (num_batch)"
:
""
,
"before"
:
""
,
"Being lazy"
:
""
,
"Brave Search API Key"
:
""
,
...
...
@@ -160,6 +161,7 @@
"Discover, download, and explore custom prompts"
:
""
,
"Discover, download, and explore model presets"
:
""
,
"Dismissible"
:
""
,
"Display Emoji in Call"
:
""
,
"Display the username instead of You in the Chat"
:
""
,
"Document"
:
""
,
"Document Settings"
:
""
,
...
...
@@ -176,6 +178,7 @@
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'."
:
""
,
"Edit"
:
""
,
"Edit Doc"
:
""
,
"Edit Memory"
:
""
,
"Edit User"
:
""
,
"Email"
:
""
,
"Embedding Batch Size"
:
""
,
...
...
@@ -205,6 +208,7 @@
"Enter Serply API Key"
:
""
,
"Enter Serpstack API Key"
:
""
,
"Enter stop sequence"
:
""
,
"Enter Tavily API Key"
:
""
,
"Enter Top K"
:
""
,
"Enter URL (e.g. http://127.0.0.1:7860/)"
:
""
,
"Enter URL (e.g. http://localhost:11434)"
:
""
,
...
...
@@ -280,6 +284,7 @@
"Knowledge"
:
""
,
"Language"
:
""
,
"Last Active"
:
""
,
"Last Modified"
:
""
,
"Light"
:
""
,
"Listening..."
:
""
,
"LLMs can make mistakes. Verify important information."
:
""
,
...
...
@@ -488,6 +493,7 @@
"System"
:
""
,
"System Prompt"
:
""
,
"Tags"
:
""
,
"Tavily API Key"
:
""
,
"Tell us more:"
:
""
,
"Temperature"
:
""
,
"Template"
:
""
,
...
...
@@ -518,6 +524,7 @@
"Today"
:
""
,
"Toggle settings"
:
""
,
"Toggle sidebar"
:
""
,
"Tokens To Keep On Context Refresh (num_keep)"
:
""
,
"Tools"
:
""
,
"Top K"
:
""
,
"Top P"
:
""
,
...
...
Prev
1
2
3
4
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