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
08cc20cb
Commit
08cc20cb
authored
Jun 20, 2024
by
Timothy J. Baek
Browse files
feat: filter selector model
parent
bf5775e0
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
117 additions
and
32 deletions
+117
-32
src/lib/components/workspace/Functions.svelte
src/lib/components/workspace/Functions.svelte
+4
-23
src/lib/components/workspace/Functions/FunctionEditor.svelte
src/lib/components/workspace/Functions/FunctionEditor.svelte
+20
-7
src/lib/components/workspace/Models/FiltersSelector.svelte
src/lib/components/workspace/Models/FiltersSelector.svelte
+59
-0
src/lib/stores/index.ts
src/lib/stores/index.ts
+2
-0
src/routes/(app)/workspace/+layout.svelte
src/routes/(app)/workspace/+layout.svelte
+6
-1
src/routes/(app)/workspace/functions/create/+page.svelte
src/routes/(app)/workspace/functions/create/+page.svelte
+2
-0
src/routes/(app)/workspace/functions/edit/+page.svelte
src/routes/(app)/workspace/functions/edit/+page.svelte
+2
-0
src/routes/(app)/workspace/models/edit/+page.svelte
src/routes/(app)/workspace/models/edit/+page.svelte
+22
-1
No files found.
src/lib/components/workspace/Functions.svelte
View file @
08cc20cb
...
...
@@ -3,7 +3,7 @@
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
import { WEBUI_NAME } from '$lib/stores';
import { WEBUI_NAME
, functions
} from '$lib/stores';
import { onMount, getContext } from 'svelte';
import { createNewPrompt, deletePromptByCommand, getPrompts } from '$lib/apis/prompts';
...
...
@@ -27,17 +27,6 @@
let showConfirm = false;
let query = '';
let functions = [];
onMount(async () => {
functions = await getFunctions(localStorage.token).catch((error) => {
toast.error(error);
return [];
});
console.log(functions);
});
</script>
<svelte:head>
...
...
@@ -94,7 +83,7 @@
<hr class=" dark:border-gray-850 my-2.5" />
<div class="my-3 mb-5">
{#each functions.filter((f) => query === '' || f.name
{#each
$
functions.filter((f) => query === '' || f.name
.toLowerCase()
.includes(query.toLowerCase()) || f.id.toLowerCase().includes(query.toLowerCase())) as func}
<button
...
...
@@ -237,11 +226,7 @@
if (res) {
toast.success('Function deleted successfully');
functions = await getFunctions(localStorage.token).catch((error) => {
toast.error(error);
return [];
});
functions.set(await getFunctions(localStorage.token));
}
}}
>
...
...
@@ -363,11 +348,7 @@
}
toast.success('Functions imported successfully');
functions = await getFunctions(localStorage.token).catch((error) => {
toast.error(error);
return [];
});
functions.set(await getFunctions(localStorage.token));
};
reader.readAsText(importFiles[0]);
...
...
src/lib/components/workspace/Functions/FunctionEditor.svelte
View file @
08cc20cb
...
...
@@ -27,17 +27,29 @@
}
let codeEditor;
let boilerplate = `from
typing import Optiona
l
let boilerplate = `from
pydantic import BaseMode
l
from typing import Optional
class Filter:
class Valves(BaseModel):
max_turns: int
pass
def __init__(self):
self.max_turns = 10
# Indicates custom file handling logic. This flag helps disengage default routines in favor of custom
# implementations, informing the WebUI to defer file-related operations to designated methods within this class.
self.file_handler = True
# Initialize 'valves' with specific configurations. Using 'Valves' instance helps encapsulate settings,
# which ensures settings are managed cohesively and not confused with operational flags like 'file_handler'.
self.valves = self.Valves(**{"max_turns": 10})
pass
def inlet(self, body: dict, user: Optional[dict] = None) -> dict:
# This method is invoked before the request is sent to the chat completion API.
# It can be used to modify the request body or perform validation checks.
# Modify the request body or validate it before processing by the chat completion API.
# This function is the pre-processor for the API where various checks on the input can be performed.
# It can also modify the request before sending it to the API.
print("inlet")
print(body)
print(user)
...
...
@@ -52,8 +64,9 @@ class Filter:
return body
def outlet(self, body: dict, user: Optional[dict] = None) -> dict:
# This method is invoked after the chat completion API has processed
# the request and generated a response. It can be used to overwrite the response messages.
# Modify or analyze the response body after processing by the API.
# This function is the post-processor for the API, which can be used to modify the response
# or perform additional checks and analytics.
print(f"outlet")
print(body)
print(user)
...
...
src/lib/components/workspace/Models/FiltersSelector.svelte
0 → 100644
View file @
08cc20cb
<script lang="ts">
import { getContext, onMount } from 'svelte';
import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
export let filters = [];
export let selectedFilterIds = [];
let _filters = {};
onMount(() => {
_filters = filters.reduce((acc, filter) => {
acc[filter.id] = {
...filter,
selected: selectedFilterIds.includes(filter.id)
};
return acc;
}, {});
});
</script>
<div>
<div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Filters')}</div>
</div>
<div class=" text-xs dark:text-gray-500">
{$i18n.t('To select filters here, add them to the "Functions" workspace first.')}
</div>
<div class="flex flex-col">
{#if filters.length > 0}
<div class=" flex items-center mt-2 flex-wrap">
{#each Object.keys(_filters) as filter, filterIdx}
<div class=" flex items-center gap-2 mr-3">
<div class="self-center flex items-center">
<Checkbox
state={_filters[filter].selected ? 'checked' : 'unchecked'}
on:change={(e) => {
_filters[filter].selected = e.detail === 'checked';
selectedFilterIds = Object.keys(_filters).filter((t) => _filters[t].selected);
}}
/>
</div>
<div class=" py-0.5 text-sm w-full capitalize font-medium">
<Tooltip content={_filters[filter].meta.description}>
{_filters[filter].name}
</Tooltip>
</div>
</div>
{/each}
</div>
{/if}
</div>
</div>
src/lib/stores/index.ts
View file @
08cc20cb
...
...
@@ -27,7 +27,9 @@ export const tags = writable([]);
export
const
models
:
Writable
<
Model
[]
>
=
writable
([]);
export
const
prompts
:
Writable
<
Prompt
[]
>
=
writable
([]);
export
const
documents
:
Writable
<
Document
[]
>
=
writable
([]);
export
const
tools
=
writable
([]);
export
const
functions
=
writable
([]);
export
const
banners
:
Writable
<
Banner
[]
>
=
writable
([]);
...
...
src/routes/(app)/workspace/+layout.svelte
View file @
08cc20cb
<script lang="ts">
import { onMount, getContext } from 'svelte';
import { WEBUI_NAME, showSidebar } from '$lib/stores';
import { WEBUI_NAME, showSidebar
, functions
} from '$lib/stores';
import MenuLines from '$lib/components/icons/MenuLines.svelte';
import { page } from '$app/stores';
import { getFunctions } from '$lib/apis/functions';
const i18n = getContext('i18n');
onMount(async () => {
functions.set(await getFunctions(localStorage.token));
});
</script>
<svelte:head>
...
...
src/routes/(app)/workspace/functions/create/+page.svelte
View file @
08cc20cb
...
...
@@ -3,6 +3,7 @@
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { functions } from '$lib/stores';
import { createNewFunction, getFunctions } from '$lib/apis/functions';
import FunctionEditor from '$lib/components/workspace/Functions/FunctionEditor.svelte';
...
...
@@ -24,6 +25,7 @@
if (res) {
toast.success('Function created successfully');
functions.set(await getFunctions(localStorage.token));
await goto('/workspace/functions');
}
};
...
...
src/routes/(app)/workspace/functions/edit/+page.svelte
View file @
08cc20cb
...
...
@@ -4,6 +4,7 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { functions } from '$lib/stores';
import { updateFunctionById, getFunctions, getFunctionById } from '$lib/apis/functions';
import FunctionEditor from '$lib/components/workspace/Functions/FunctionEditor.svelte';
...
...
@@ -25,6 +26,7 @@
if (res) {
toast.success('Function updated successfully');
functions.set(await getFunctions(localStorage.token));
}
};
...
...
src/routes/(app)/workspace/models/edit/+page.svelte
View file @
08cc20cb
...
...
@@ -5,7 +5,7 @@
import
{
onMount
,
getContext
}
from
'svelte'
;
import
{
page
}
from
'$app/stores'
;
import
{
settings
,
user
,
config
,
models
,
tools
}
from
'$lib/stores'
;
import
{
settings
,
user
,
config
,
models
,
tools
,
functions
}
from
'$lib/stores'
;
import
{
splitStream
}
from
'$lib/utils'
;
import
{
getModelInfos
,
updateModelById
}
from
'$lib/apis/models'
;
...
...
@@ -16,6 +16,7 @@
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
FiltersSelector
from
'$lib/components/workspace/Models/FiltersSelector.svelte'
;
const
i18n
=
getContext
(
'i18n'
);
...
...
@@ -62,6 +63,7 @@
let
knowledge
=
[];
let
toolIds
=
[];
let
filterIds
=
[];
const
updateHandler
=
async
()
=>
{
loading
=
true
;
...
...
@@ -86,6 +88,14 @@
}
}
if
(
filterIds
.
length
>
0
)
{
info
.
meta
.
filterIds
=
filterIds
;
}
else
{
if
(
info
.
meta
.
filterIds
)
{
delete
info
.
meta
.
filterIds
;
}
}
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
)
{
...
...
@@ -147,6 +157,10 @@
toolIds
=
[...
model
?.
info
?.
meta
?.
toolIds
];
}
if
(
model
?.
info
?.
meta
?.
filterIds
)
{
filterIds
=
[...
model
?.
info
?.
meta
?.
filterIds
];
}
if
(
model
?.
owned_by
===
'openai'
)
{
capabilities
.
usage
=
false
;
}
...
...
@@ -534,6 +548,13 @@
<
ToolsSelector
bind
:
selectedToolIds
={
toolIds
}
tools
={$
tools
}
/>
</
div
>
<
div
class
=
"my-2"
>
<
FiltersSelector
bind
:
selectedFilterIds
={
filterIds
}
filters
={$
functions
.
filter
((
func
)
=>
func
.
type
===
'filter'
)}
/>
</
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
>
...
...
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