mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
Merge remote-tracking branch 'origin/dev' into feat/model-config
This commit is contained in:
@@ -644,7 +644,7 @@
|
||||
}}
|
||||
/>
|
||||
<form
|
||||
dir={$settings?.chatDirection}
|
||||
dir={$settings?.chatDirection ?? 'LTR'}
|
||||
class=" flex flex-col relative w-full rounded-3xl px-1.5 bg-gray-50 dark:bg-gray-850 dark:text-gray-100"
|
||||
on:submit|preventDefault={() => {
|
||||
submitPrompt(prompt, user);
|
||||
|
||||
@@ -361,13 +361,14 @@
|
||||
history: history
|
||||
});
|
||||
|
||||
const element = document.getElementById('messages-container');
|
||||
autoScroll =
|
||||
element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
|
||||
|
||||
setTimeout(() => {
|
||||
scrollToBottom();
|
||||
}, 100);
|
||||
if (autoScroll) {
|
||||
const element = document.getElementById('messages-container');
|
||||
autoScroll =
|
||||
element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
|
||||
setTimeout(() => {
|
||||
scrollToBottom();
|
||||
}, 100);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
|
||||
@@ -30,70 +30,17 @@
|
||||
};
|
||||
|
||||
const checkPythonCode = (str) => {
|
||||
// Check if the string contains typical Python keywords, syntax, or functions
|
||||
const pythonKeywords = [
|
||||
'def',
|
||||
'class',
|
||||
'import',
|
||||
'from',
|
||||
'if',
|
||||
'else',
|
||||
'elif',
|
||||
'for',
|
||||
'while',
|
||||
'try',
|
||||
'except',
|
||||
'finally',
|
||||
'return',
|
||||
'yield',
|
||||
'lambda',
|
||||
'assert',
|
||||
'pass',
|
||||
'break',
|
||||
'continue',
|
||||
'global',
|
||||
'nonlocal',
|
||||
'del',
|
||||
'True',
|
||||
'False',
|
||||
'None',
|
||||
'and',
|
||||
'or',
|
||||
'not',
|
||||
'in',
|
||||
'is',
|
||||
'as',
|
||||
'with'
|
||||
];
|
||||
|
||||
for (let keyword of pythonKeywords) {
|
||||
if (str.includes(keyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the string contains typical Python syntax characters
|
||||
const pythonSyntax = [
|
||||
'def ',
|
||||
'class ',
|
||||
'import ',
|
||||
'from ',
|
||||
'if ',
|
||||
'else:',
|
||||
'elif ',
|
||||
'for ',
|
||||
'while ',
|
||||
'try:',
|
||||
'except:',
|
||||
'finally:',
|
||||
'return ',
|
||||
'yield ',
|
||||
'lambda ',
|
||||
'assert ',
|
||||
'pass',
|
||||
'break',
|
||||
'continue',
|
||||
'global ',
|
||||
'nonlocal ',
|
||||
'del ',
|
||||
'True',
|
||||
@@ -104,29 +51,7 @@
|
||||
' not ',
|
||||
' in ',
|
||||
' is ',
|
||||
' as ',
|
||||
' with ',
|
||||
':',
|
||||
'=',
|
||||
'==',
|
||||
'!=',
|
||||
'>',
|
||||
'<',
|
||||
'>=',
|
||||
'<=',
|
||||
'+',
|
||||
'-',
|
||||
'*',
|
||||
'/',
|
||||
'%',
|
||||
'**',
|
||||
'//',
|
||||
'(',
|
||||
')',
|
||||
'[',
|
||||
']',
|
||||
'{',
|
||||
'}'
|
||||
' with '
|
||||
];
|
||||
|
||||
for (let syntax of pythonSyntax) {
|
||||
@@ -186,7 +111,8 @@
|
||||
code.includes('matplotlib') ? 'matplotlib' : null,
|
||||
code.includes('sklearn') ? 'scikit-learn' : null,
|
||||
code.includes('scipy') ? 'scipy' : null,
|
||||
code.includes('re') ? 'regex' : null
|
||||
code.includes('re') ? 'regex' : null,
|
||||
code.includes('seaborn') ? 'seaborn' : null
|
||||
].filter(Boolean);
|
||||
|
||||
console.log(packages);
|
||||
@@ -235,7 +161,8 @@ __builtins__.input = input`);
|
||||
code.includes('pandas') ? 'pandas' : null,
|
||||
code.includes('sklearn') ? 'scikit-learn' : null,
|
||||
code.includes('scipy') ? 'scipy' : null,
|
||||
code.includes('re') ? 'regex' : null
|
||||
code.includes('re') ? 'regex' : null,
|
||||
code.includes('seaborn') ? 'seaborn' : null
|
||||
].filter(Boolean);
|
||||
|
||||
console.log(packages);
|
||||
|
||||
@@ -68,11 +68,11 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
||||
<div
|
||||
class=" snap-center min-w-80 w-full max-w-full m-1 outline outline-1 {history.messages[
|
||||
class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
|
||||
currentMessageId
|
||||
].model === model
|
||||
? 'outline-gray-200 dark:outline-gray-700 outline-2'
|
||||
: 'outline-gray-100 dark:outline-gray-850 '} transition p-6 rounded-3xl"
|
||||
? 'border-gray-100 dark:border-gray-700 border-[1.5px]'
|
||||
: 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl"
|
||||
on:click={() => {
|
||||
currentMessageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
export let src = '/user.png';
|
||||
</script>
|
||||
|
||||
<div class={$settings?.chatDirection === 'LTR' ? 'mr-3' : 'ml-3'}>
|
||||
<div class={($settings?.chatDirection ?? 'LTR') === 'LTR' ? 'mr-3' : 'ml-3'}>
|
||||
<img
|
||||
crossorigin="anonymous"
|
||||
src={src.startsWith(WEBUI_BASE_URL) ||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
[key: string]: any;
|
||||
} = [];
|
||||
|
||||
export let className = ' w-[30rem]';
|
||||
export let className = 'w-[30rem]';
|
||||
|
||||
let show = false;
|
||||
|
||||
@@ -213,7 +213,9 @@
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content
|
||||
class=" z-40 {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-700/50 outline-none "
|
||||
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-700/50 outline-none "
|
||||
transition={flyAndScale}
|
||||
side={$mobile ? 'bottom' : 'bottom-start'}
|
||||
sideOffset={4}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
let showManageModal = false;
|
||||
|
||||
// Addons
|
||||
let enableMemory = true;
|
||||
let enableMemory = false;
|
||||
|
||||
onMount(async () => {
|
||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
||||
enableMemory = settings?.memory ?? true;
|
||||
enableMemory = settings?.memory ?? false;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
|
||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
||||
<div>
|
||||
LLMs will become more helpful as you chat, picking up on details and preferences to tailor
|
||||
its responses to you.
|
||||
You can personalize your interactions with LLMs by adding memories through the 'Manage'
|
||||
button below, making them more helpful and tailored to you.
|
||||
</div>
|
||||
|
||||
<!-- <div class="mt-3">
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import { createEventDispatcher, getContext } from 'svelte';
|
||||
|
||||
import Modal from '$lib/components/common/Modal.svelte';
|
||||
import { addNewMemory } from '$lib/apis/memories';
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let show;
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
let loading = false;
|
||||
let memory = '';
|
||||
let content = '';
|
||||
|
||||
const submitHandler = () => {
|
||||
console.log('submitHandler');
|
||||
const submitHandler = async () => {
|
||||
loading = true;
|
||||
|
||||
const res = await addNewMemory(localStorage.token, content).catch((error) => {
|
||||
toast.error(error);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
console.log(res);
|
||||
toast.success('Memory added successfully');
|
||||
content = '';
|
||||
show = false;
|
||||
dispatch('save');
|
||||
}
|
||||
|
||||
loading = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -48,7 +68,7 @@
|
||||
>
|
||||
<div class="">
|
||||
<textarea
|
||||
bind:value={memory}
|
||||
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')}
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
import Modal from '$lib/components/common/Modal.svelte';
|
||||
import AddMemoryModal from './AddMemoryModal.svelte';
|
||||
import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -18,7 +21,7 @@
|
||||
|
||||
$: if (show) {
|
||||
(async () => {
|
||||
// chats = await getArchivedChatList(localStorage.token);
|
||||
memories = await getMemories(localStorage.token);
|
||||
})();
|
||||
}
|
||||
</script>
|
||||
@@ -65,20 +68,54 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each memories as memory}
|
||||
<tr class="border-b dark:border-gray-800">
|
||||
<td class="px-3 py-2"> {memory.name} </td>
|
||||
<td class="px-3 py-2 hidden md:flex">
|
||||
{dayjs(memory.created_at).format($i18n.t('MMMM DD, YYYY'))}
|
||||
<tr class="border-b dark:border-gray-800 items-center">
|
||||
<td class="px-3 py-1">
|
||||
<div class="line-clamp-1">
|
||||
{memory.content}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-3 py-2 text-right">
|
||||
<button
|
||||
class="text-xs text-gray-500 dark:text-gray-400"
|
||||
on:click={() => {
|
||||
// showMemory(memory);
|
||||
}}
|
||||
>
|
||||
{$i18n.t('View')}
|
||||
</button>
|
||||
<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'))}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-3 py-1">
|
||||
<div class="flex justify-end w-full">
|
||||
<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"
|
||||
on:click={async () => {
|
||||
const res = await deleteMemoryById(
|
||||
localStorage.token,
|
||||
memory.id
|
||||
).catch((error) => {
|
||||
toast.error(error);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
toast.success('Memory deleted successfully');
|
||||
memories = await getMemories(localStorage.token);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<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"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
@@ -89,9 +126,7 @@
|
||||
{:else}
|
||||
<div class="text-center flex h-full text-sm w-full">
|
||||
<div class=" my-auto pb-10 px-4 w-full text-gray-500">
|
||||
{$i18n.t(
|
||||
'As you chat with LLMs, the details and preferences it remembers will be shown here.'
|
||||
)}
|
||||
{$i18n.t('Memories accessible by LLMs will be shown here.')}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -103,13 +138,28 @@
|
||||
showAddMemoryModal = true;
|
||||
}}>Add memory</button
|
||||
>
|
||||
<!-- <button
|
||||
<button
|
||||
class=" px-3.5 py-1.5 font-medium text-red-500 hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-red-300 dark:outline-red-800 rounded-3xl"
|
||||
>Clear memory</button
|
||||
> -->
|
||||
on:click={async () => {
|
||||
const res = await deleteMemoriesByUserId(localStorage.token).catch((error) => {
|
||||
toast.error(error);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
toast.success('Memory cleared successfully');
|
||||
memories = [];
|
||||
}
|
||||
}}>Clear memory</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<AddMemoryModal bind:show={showAddMemoryModal} />
|
||||
<AddMemoryModal
|
||||
bind:show={showAddMemoryModal}
|
||||
on:save={async () => {
|
||||
memories = await getMemories(localStorage.token);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -254,6 +254,8 @@
|
||||
embeddingModel = '';
|
||||
} else if (e.target.value === 'openai') {
|
||||
embeddingModel = 'text-embedding-3-small';
|
||||
} else if (e.target.value === '') {
|
||||
embeddingModel = 'sentence-transformers/all-MiniLM-L6-v2';
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -329,7 +329,6 @@
|
||||
info: model
|
||||
}))}
|
||||
bind:value={selectedModelId}
|
||||
className="w-[42rem]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user