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
4ff17acc
Commit
4ff17acc
authored
Jun 16, 2024
by
Jun Siang Cheah
Browse files
Merge remote-tracking branch 'upstream/dev' into feat/oauth
parents
f49d814d
9928114c
Changes
168
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
278 additions
and
28 deletions
+278
-28
src/routes/(app)/workspace/models/create/+page.svelte
src/routes/(app)/workspace/models/create/+page.svelte
+66
-14
src/routes/(app)/workspace/models/edit/+page.svelte
src/routes/(app)/workspace/models/edit/+page.svelte
+44
-6
src/routes/(app)/workspace/tools/+page.svelte
src/routes/(app)/workspace/tools/+page.svelte
+5
-0
src/routes/(app)/workspace/tools/create/+page.svelte
src/routes/(app)/workspace/tools/create/+page.svelte
+57
-0
src/routes/(app)/workspace/tools/edit/+page.svelte
src/routes/(app)/workspace/tools/edit/+page.svelte
+66
-0
src/routes/+layout.svelte
src/routes/+layout.svelte
+34
-2
src/routes/auth/+page.svelte
src/routes/auth/+page.svelte
+6
-6
static/audio/greeting.mp3
static/audio/greeting.mp3
+0
-0
No files found.
src/routes/(app)/workspace/models/create/+page.svelte
View file @
4ff17acc
...
...
@@ -2,7 +2,7 @@
import { v4 as uuidv4 } from 'uuid';
import { toast } from 'svelte-sonner';
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 { addNewModel, getModelById, getModelInfos } from '$lib/apis/models';
...
...
@@ -11,6 +11,9 @@
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import Checkbox from '$lib/components/common/Checkbox.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');
...
...
@@ -30,11 +33,6 @@
let id = '';
let name = '';
let params = {};
let capabilities = {
vision: true
};
let info = {
id: '',
base_model_id: null,
...
...
@@ -53,14 +51,21 @@
}
};
let params = {};
let capabilities = {
vision: true
};
let toolIds = [];
let knowledge = [];
$: if (name) {
id = name.replace(/\s+/g, '-').toLowerCase();
}
let baseModel = null;
$: {
baseModel = $models.find((m) => m.id === info.base_model_id);
console.log(baseModel);
const addUsage = (base_model_id) => {
const baseModel = $models.find((m) => m.id === base_model_id);
if (baseModel) {
if (baseModel.owned_by === 'openai') {
capabilities.usage = baseModel.info?.meta?.capabilities?.usage ?? false;
...
...
@@ -69,7 +74,7 @@
}
capabilities = capabilities;
}
}
}
;
const submitHandler = async () => {
loading = true;
...
...
@@ -77,8 +82,24 @@
info.id = id;
info.name = name;
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) => {
if (info.params[key] === '' || info.params[key] === null) {
delete info.params[key];
...
...
@@ -124,15 +145,34 @@
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.stop = params?.stop ? (params?.stop ?? []).join(',') : null;
capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) };
toolIds = model?.info?.meta?.toolIds ?? [];
info = {
...info,
...model.info
};
console.log(info);
};
onMount(async () => {
...
...
@@ -233,7 +273,7 @@
<button
class="flex space-x-1"
on:click={() => {
history.back(
);
goto('/workspace/models'
);
}}
>
<div class=" self-center">
...
...
@@ -252,7 +292,7 @@
</div>
<div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div>
</button>
<!-- <hr class="my-3 dark:border-gray-
70
0" /> -->
<!-- <hr class="my-3 dark:border-gray-
85
0" /> -->
<form
class="flex flex-col max-w-2xl mx-auto mt-4 mb-10"
...
...
@@ -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"
placeholder="Select a base model (e.g. llama3, gpt-4o)"
bind:value={info.base_model_id}
on:change={(e) => {
addUsage(e.target.value);
}}
required
>
<option value={null} class=" text-gray-900">{$i18n.t('Select a base model')}</option>
...
...
@@ -416,6 +459,7 @@
{#if showAdvanced}
<div class="my-2">
<AdvancedParams
admin={true}
bind:params
on:change={(e) => {
info.params = { ...info.params, ...params };
...
...
@@ -518,6 +562,14 @@
{/if}
</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="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
...
...
src/routes/(app)/workspace/models/edit/+page.svelte
View file @
4ff17acc
...
...
@@ -5,7 +5,7 @@
import
{
onMount
,
getContext
}
from
'svelte'
;
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
{
getModelInfos
,
updateModelById
}
from
'$lib/apis/models'
;
...
...
@@ -14,6 +14,8 @@
import
{
getModels
}
from
'$lib/apis'
;
import
Checkbox
from
'$lib/components/common/Checkbox.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'
);
...
...
@@ -54,19 +56,37 @@
};
let
params
=
{};
let
capabilities
=
{
vision
:
true
};
let
knowledge
=
[];
let
toolIds
=
[];
const
updateHandler
=
async
()
=>
{
loading
=
true
;
info
.
id
=
id
;
info
.
name
=
name
;
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
)
=>
{
if
(
info
.
params
[
key
]
===
''
||
info
.
params
[
key
]
===
null
)
{
delete
info
.
params
[
key
];
...
...
@@ -119,6 +139,14 @@
)
:
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'
)
{
capabilities
.
usage
=
false
;
}
...
...
@@ -126,6 +154,7 @@
if
(
model
?.
info
?.
meta
?.
capabilities
)
{
capabilities
=
{
...
capabilities
,
...
model
?.
info
?.
meta
?.
capabilities
};
}
console
.
log
(
model
);
}
else
{
goto
(
'/workspace/models'
);
...
...
@@ -205,7 +234,7 @@
<
button
class
=
"flex space-x-1"
on
:
click
={()
=>
{
history
.
back
(
);
goto
(
'/workspace/models'
);
}}
>
<
div
class
=
" self-center"
>
...
...
@@ -393,6 +422,7 @@
{#
if
showAdvanced
}
<
div
class
=
"my-2"
>
<
AdvancedParams
admin
={
true
}
bind
:
params
on
:
change
={(
e
)
=>
{
info
.
params
=
{
...
info
.
params
,
...
params
};
...
...
@@ -405,7 +435,7 @@
<
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
=
" self-center text-sm font-semibold"
>{$
i18n
.
t
(
'Prompt suggestions'
)}</
div
>
...
...
@@ -495,7 +525,15 @@
{/
if
}
</
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
=
" self-center text-sm font-semibold"
>{$
i18n
.
t
(
'Capabilities'
)}</
div
>
</
div
>
...
...
src/routes/(app)/workspace/tools/+page.svelte
0 → 100644
View file @
4ff17acc
<script>
import Tools from '$lib/components/workspace/Tools.svelte';
</script>
<Tools />
src/routes/(app)/workspace/tools/create/+page.svelte
0 → 100644
View file @
4ff17acc
<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}
src/routes/(app)/workspace/tools/edit/+page.svelte
0 → 100644
View file @
4ff17acc
<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}
src/routes/+layout.svelte
View file @
4ff17acc
<script>
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 {
...
...
@@ -121,8 +126,35 @@
await tick();
document.getElementById('splash-screen')?.remove();
loaded = true;
if (
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 () => {
window.removeEventListener('resize', onResize);
...
...
src/routes/auth/+page.svelte
View file @
4ff17acc
...
...
@@ -135,7 +135,7 @@
{#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
<div class=" my-auto pb-10 w-full">
<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>
{$i18n.t('Signing in')}
...
...
@@ -157,7 +157,7 @@
}}
>
<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')}
{$i18n.t('to')}
{$WEBUI_NAME}
...
...
@@ -176,7 +176,7 @@
<div class="flex flex-col mt-4">
{#if mode === 'signup'}
<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
bind:value={name}
type="text"
...
...
@@ -191,7 +191,7 @@
{/if}
<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
bind:value={email}
type="email"
...
...
@@ -203,7 +203,7 @@
</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
bind:value={password}
...
...
@@ -218,7 +218,7 @@
<div class="mt-5">
<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"
>
{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
...
...
static/audio/greeting.mp3
0 → 100644
View file @
4ff17acc
File added
Prev
1
…
5
6
7
8
9
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