Commit 4ff17acc authored by Jun Siang Cheah's avatar Jun Siang Cheah
Browse files

Merge remote-tracking branch 'upstream/dev' into feat/oauth

parents f49d814d 9928114c
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { settings, user, config, models } from '$lib/stores'; import { settings, user, config, models, tools } from '$lib/stores';
import { onMount, tick, getContext } from 'svelte'; import { onMount, tick, getContext } from 'svelte';
import { addNewModel, getModelById, getModelInfos } from '$lib/apis/models'; import { addNewModel, getModelById, getModelInfos } from '$lib/apis/models';
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte'; import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import Checkbox from '$lib/components/common/Checkbox.svelte'; import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tags from '$lib/components/common/Tags.svelte'; import Tags from '$lib/components/common/Tags.svelte';
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
import { stringify } from 'postcss';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -30,11 +33,6 @@ ...@@ -30,11 +33,6 @@
let id = ''; let id = '';
let name = ''; let name = '';
let params = {};
let capabilities = {
vision: true
};
let info = { let info = {
id: '', id: '',
base_model_id: null, base_model_id: null,
...@@ -53,14 +51,21 @@ ...@@ -53,14 +51,21 @@
} }
}; };
let params = {};
let capabilities = {
vision: true
};
let toolIds = [];
let knowledge = [];
$: if (name) { $: if (name) {
id = name.replace(/\s+/g, '-').toLowerCase(); id = name.replace(/\s+/g, '-').toLowerCase();
} }
let baseModel = null; const addUsage = (base_model_id) => {
$: { const baseModel = $models.find((m) => m.id === base_model_id);
baseModel = $models.find((m) => m.id === info.base_model_id);
console.log(baseModel);
if (baseModel) { if (baseModel) {
if (baseModel.owned_by === 'openai') { if (baseModel.owned_by === 'openai') {
capabilities.usage = baseModel.info?.meta?.capabilities?.usage ?? false; capabilities.usage = baseModel.info?.meta?.capabilities?.usage ?? false;
...@@ -69,7 +74,7 @@ ...@@ -69,7 +74,7 @@
} }
capabilities = capabilities; capabilities = capabilities;
} }
} };
const submitHandler = async () => { const submitHandler = async () => {
loading = true; loading = true;
...@@ -77,8 +82,24 @@ ...@@ -77,8 +82,24 @@
info.id = id; info.id = id;
info.name = name; info.name = name;
info.meta.capabilities = capabilities; info.meta.capabilities = capabilities;
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
if (knowledge.length > 0) {
info.meta.knowledge = knowledge;
} else {
if (info.meta.knowledge) {
delete info.meta.knowledge;
}
}
if (toolIds.length > 0) {
info.meta.toolIds = toolIds;
} else {
if (info.meta.toolIds) {
delete info.meta.toolIds;
}
}
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
Object.keys(info.params).forEach((key) => { Object.keys(info.params).forEach((key) => {
if (info.params[key] === '' || info.params[key] === null) { if (info.params[key] === '' || info.params[key] === null) {
delete info.params[key]; delete info.params[key];
...@@ -124,15 +145,34 @@ ...@@ -124,15 +145,34 @@
id = model.id; id = model.id;
if (model.info.base_model_id) {
const base_model = $models
.filter((m) => !m?.preset)
.find((m) =>
[model.info.base_model_id, `${model.info.base_model_id}:latest`].includes(m.id)
);
console.log('base_model', base_model);
if (!base_model) {
model.info.base_model_id = null;
} else if ($models.find((m) => m.id === `${model.info.base_model_id}:latest`)) {
model.info.base_model_id = `${model.info.base_model_id}:latest`;
}
}
params = { ...params, ...model?.info?.params }; params = { ...params, ...model?.info?.params };
params.stop = params?.stop ? (params?.stop ?? []).join(',') : null; params.stop = params?.stop ? (params?.stop ?? []).join(',') : null;
capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) }; capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) };
toolIds = model?.info?.meta?.toolIds ?? [];
info = { info = {
...info, ...info,
...model.info ...model.info
}; };
console.log(info);
}; };
onMount(async () => { onMount(async () => {
...@@ -233,7 +273,7 @@ ...@@ -233,7 +273,7 @@
<button <button
class="flex space-x-1" class="flex space-x-1"
on:click={() => { on:click={() => {
history.back(); goto('/workspace/models');
}} }}
> >
<div class=" self-center"> <div class=" self-center">
...@@ -252,7 +292,7 @@ ...@@ -252,7 +292,7 @@
</div> </div>
<div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div> <div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div>
</button> </button>
<!-- <hr class="my-3 dark:border-gray-700" /> --> <!-- <hr class="my-3 dark:border-gray-850" /> -->
<form <form
class="flex flex-col max-w-2xl mx-auto mt-4 mb-10" class="flex flex-col max-w-2xl mx-auto mt-4 mb-10"
...@@ -331,6 +371,9 @@ ...@@ -331,6 +371,9 @@
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg" class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
placeholder="Select a base model (e.g. llama3, gpt-4o)" placeholder="Select a base model (e.g. llama3, gpt-4o)"
bind:value={info.base_model_id} bind:value={info.base_model_id}
on:change={(e) => {
addUsage(e.target.value);
}}
required required
> >
<option value={null} class=" text-gray-900">{$i18n.t('Select a base model')}</option> <option value={null} class=" text-gray-900">{$i18n.t('Select a base model')}</option>
...@@ -416,6 +459,7 @@ ...@@ -416,6 +459,7 @@
{#if showAdvanced} {#if showAdvanced}
<div class="my-2"> <div class="my-2">
<AdvancedParams <AdvancedParams
admin={true}
bind:params bind:params
on:change={(e) => { on:change={(e) => {
info.params = { ...info.params, ...params }; info.params = { ...info.params, ...params };
...@@ -518,6 +562,14 @@ ...@@ -518,6 +562,14 @@
{/if} {/if}
</div> </div>
<div class="my-2">
<Knowledge bind:knowledge />
</div>
<div class="my-2">
<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
</div>
<div class="my-1"> <div class="my-1">
<div class="flex w-full justify-between mb-1"> <div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import { onMount, getContext } from 'svelte'; import { onMount, getContext } from 'svelte';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { settings, user, config, models } from '$lib/stores'; import { settings, user, config, models, tools } from '$lib/stores';
import { splitStream } from '$lib/utils'; import { splitStream } from '$lib/utils';
import { getModelInfos, updateModelById } from '$lib/apis/models'; import { getModelInfos, updateModelById } from '$lib/apis/models';
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
import { getModels } from '$lib/apis'; import { getModels } from '$lib/apis';
import Checkbox from '$lib/components/common/Checkbox.svelte'; import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tags from '$lib/components/common/Tags.svelte'; import Tags from '$lib/components/common/Tags.svelte';
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -54,19 +56,37 @@ ...@@ -54,19 +56,37 @@
}; };
let params = {}; let params = {};
let capabilities = { let capabilities = {
vision: true vision: true
}; };
let knowledge = [];
let toolIds = [];
const updateHandler = async () => { const updateHandler = async () => {
loading = true; loading = true;
info.id = id; info.id = id;
info.name = name; info.name = name;
info.meta.capabilities = capabilities; info.meta.capabilities = capabilities;
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
if (knowledge.length > 0) {
info.meta.knowledge = knowledge;
} else {
if (info.meta.knowledge) {
delete info.meta.knowledge;
}
}
if (toolIds.length > 0) {
info.meta.toolIds = toolIds;
} else {
if (info.meta.toolIds) {
delete info.meta.toolIds;
}
}
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
Object.keys(info.params).forEach((key) => { Object.keys(info.params).forEach((key) => {
if (info.params[key] === '' || info.params[key] === null) { if (info.params[key] === '' || info.params[key] === null) {
delete info.params[key]; delete info.params[key];
...@@ -119,6 +139,14 @@ ...@@ -119,6 +139,14 @@
) )
: null; : null;
if (model?.info?.meta?.knowledge) {
knowledge = [...model?.info?.meta?.knowledge];
}
if (model?.info?.meta?.toolIds) {
toolIds = [...model?.info?.meta?.toolIds];
}
if (model?.owned_by === 'openai') { if (model?.owned_by === 'openai') {
capabilities.usage = false; capabilities.usage = false;
} }
...@@ -126,6 +154,7 @@ ...@@ -126,6 +154,7 @@
if (model?.info?.meta?.capabilities) { if (model?.info?.meta?.capabilities) {
capabilities = { ...capabilities, ...model?.info?.meta?.capabilities }; capabilities = { ...capabilities, ...model?.info?.meta?.capabilities };
} }
console.log(model); console.log(model);
} else { } else {
goto('/workspace/models'); goto('/workspace/models');
...@@ -205,7 +234,7 @@ ...@@ -205,7 +234,7 @@
<button <button
class="flex space-x-1" class="flex space-x-1"
on:click={() => { on:click={() => {
history.back(); goto('/workspace/models');
}} }}
> >
<div class=" self-center"> <div class=" self-center">
...@@ -393,6 +422,7 @@ ...@@ -393,6 +422,7 @@
{#if showAdvanced} {#if showAdvanced}
<div class="my-2"> <div class="my-2">
<AdvancedParams <AdvancedParams
admin={true}
bind:params bind:params
on:change={(e) => { on:change={(e) => {
info.params = { ...info.params, ...params }; info.params = { ...info.params, ...params };
...@@ -405,7 +435,7 @@ ...@@ -405,7 +435,7 @@
<hr class=" dark:border-gray-850 my-1" /> <hr class=" dark:border-gray-850 my-1" />
<div class="my-1"> <div class="my-2">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
...@@ -495,7 +525,15 @@ ...@@ -495,7 +525,15 @@
{/if} {/if}
</div> </div>
<div class="my-1"> <div class="my-2">
<Knowledge bind:knowledge />
</div>
<div class="my-2">
<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
</div>
<div class="my-2">
<div class="flex w-full justify-between mb-1"> <div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
</div> </div>
......
<script>
import Tools from '$lib/components/workspace/Tools.svelte';
</script>
<Tools />
<script>
import { goto } from '$app/navigation';
import { createNewTool, getTools } from '$lib/apis/tools';
import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
import { tools } from '$lib/stores';
import { onMount } from 'svelte';
import { toast } from 'svelte-sonner';
let mounted = false;
let clone = false;
let tool = null;
const saveHandler = async (data) => {
console.log(data);
const res = await createNewTool(localStorage.token, {
id: data.id,
name: data.name,
meta: data.meta,
content: data.content
}).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success('Tool created successfully');
tools.set(await getTools(localStorage.token));
await goto('/workspace/tools');
}
};
onMount(() => {
if (sessionStorage.tool) {
tool = JSON.parse(sessionStorage.tool);
sessionStorage.removeItem('tool');
console.log(tool);
clone = true;
}
mounted = true;
});
</script>
{#if mounted}
<ToolkitEditor
id={tool?.id ?? ''}
name={tool?.name ?? ''}
meta={tool?.meta ?? { description: '' }}
content={tool?.content ?? ''}
{clone}
on:save={(e) => {
saveHandler(e.detail);
}}
/>
{/if}
<script>
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { getToolById, getTools, updateToolById } from '$lib/apis/tools';
import Spinner from '$lib/components/common/Spinner.svelte';
import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
import { tools } from '$lib/stores';
import { onMount } from 'svelte';
import { toast } from 'svelte-sonner';
let tool = null;
const saveHandler = async (data) => {
console.log(data);
const res = await updateToolById(localStorage.token, tool.id, {
id: data.id,
name: data.name,
meta: data.meta,
content: data.content
}).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success('Tool updated successfully');
tools.set(await getTools(localStorage.token));
// await goto('/workspace/tools');
}
};
onMount(async () => {
console.log('mounted');
const id = $page.url.searchParams.get('id');
if (id) {
tool = await getToolById(localStorage.token, id).catch((error) => {
toast.error(error);
goto('/workspace/tools');
return null;
});
console.log(tool);
}
});
</script>
{#if tool}
<ToolkitEditor
edit={true}
id={tool.id}
name={tool.name}
meta={tool.meta}
content={tool.content}
on:save={(e) => {
saveHandler(e.detail);
}}
/>
{:else}
<div class="flex items-center justify-center h-full">
<div class=" pb-16">
<Spinner />
</div>
</div>
{/if}
<script> <script>
import { io } from 'socket.io-client'; import { io } from 'socket.io-client';
import { spring } from 'svelte/motion';
let loadingProgress = spring(0, {
stiffness: 0.05
});
import { onMount, tick, setContext } from 'svelte'; import { onMount, tick, setContext } from 'svelte';
import { import {
...@@ -121,8 +126,35 @@ ...@@ -121,8 +126,35 @@
await tick(); await tick();
document.getElementById('splash-screen')?.remove(); if (
loaded = true; document.documentElement.classList.contains('her') &&
document.getElementById('progress-bar')
) {
loadingProgress.subscribe((value) => {
const progressBar = document.getElementById('progress-bar');
if (progressBar) {
progressBar.style.width = `${value}%`;
}
});
await loadingProgress.set(100);
document.getElementById('splash-screen')?.remove();
const audio = new Audio(`/audio/greeting.mp3`);
const playAudio = () => {
audio.play();
document.removeEventListener('click', playAudio);
};
document.addEventListener('click', playAudio);
loaded = true;
} else {
document.getElementById('splash-screen')?.remove();
loaded = true;
}
return () => { return () => {
window.removeEventListener('resize', onResize); window.removeEventListener('resize', onResize);
......
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
{#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false} {#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
<div class=" my-auto pb-10 w-full"> <div class=" my-auto pb-10 w-full">
<div <div
class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-bold dark:text-gray-200" class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-medium dark:text-gray-200"
> >
<div> <div>
{$i18n.t('Signing in')} {$i18n.t('Signing in')}
...@@ -157,7 +157,7 @@ ...@@ -157,7 +157,7 @@
}} }}
> >
<div class="mb-1"> <div class="mb-1">
<div class=" text-2xl font-bold"> <div class=" text-2xl font-medium">
{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Sign up')} {mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Sign up')}
{$i18n.t('to')} {$i18n.t('to')}
{$WEBUI_NAME} {$WEBUI_NAME}
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
<div class="flex flex-col mt-4"> <div class="flex flex-col mt-4">
{#if mode === 'signup'} {#if mode === 'signup'}
<div> <div>
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Name')}</div> <div class=" text-sm font-medium text-left mb-1">{$i18n.t('Name')}</div>
<input <input
bind:value={name} bind:value={name}
type="text" type="text"
...@@ -191,7 +191,7 @@ ...@@ -191,7 +191,7 @@
{/if} {/if}
<div class="mb-2"> <div class="mb-2">
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Email')}</div> <div class=" text-sm font-medium text-left mb-1">{$i18n.t('Email')}</div>
<input <input
bind:value={email} bind:value={email}
type="email" type="email"
...@@ -203,7 +203,7 @@ ...@@ -203,7 +203,7 @@
</div> </div>
<div> <div>
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Password')}</div> <div class=" text-sm font-medium text-left mb-1">{$i18n.t('Password')}</div>
<input <input
bind:value={password} bind:value={password}
...@@ -218,7 +218,7 @@ ...@@ -218,7 +218,7 @@
<div class="mt-5"> <div class="mt-5">
<button <button
class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-semibold text-sm py-3 transition" class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-medium text-sm py-3 transition"
type="submit" type="submit"
> >
{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')} {mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment