Spaces:
Running
Running
use derived instead of states
Browse files
src/lib/components/chat/User.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
-
import { Send,
|
| 3 |
import {
|
| 4 |
Handle,
|
| 5 |
useEdges,
|
|
@@ -28,7 +28,7 @@
|
|
| 28 |
const { update: updateEdges } = useEdges();
|
| 29 |
const { fitView, updateNodeData } = useSvelteFlow();
|
| 30 |
|
| 31 |
-
let selectedModels = $
|
| 32 |
(nodeData.current?.data.selectedModels as ChatModel[]) ?? []
|
| 33 |
);
|
| 34 |
let prompt = $state.raw<string>((nodeData.current?.data.prompt as string) ?? '');
|
|
@@ -36,25 +36,38 @@
|
|
| 36 |
let messages = $state.raw<ChatMessage[]>(
|
| 37 |
(nodeData.current?.data?.messages as ChatMessage[]) ?? []
|
| 38 |
);
|
| 39 |
-
let openSettingsModel = $state.raw<ChatModel | null>(null);
|
| 40 |
|
| 41 |
function addModel(model: ChatModel) {
|
| 42 |
if (!selectedModels.some((m) => m.id === model.id)) {
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
if (lastMessage) {
|
| 45 |
handleTriggerAction([model]);
|
| 46 |
}
|
| 47 |
}
|
| 48 |
}
|
| 49 |
function removeModel(model: ChatModel) {
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
}
|
| 52 |
|
| 53 |
function handleTriggerAction(models: ChatModel[] = selectedModels) {
|
| 54 |
const newNodes: Node[] = [];
|
| 55 |
const newEdges: Edge[] = [];
|
| 56 |
messages = [...messages, { role: 'user', content: prompt }];
|
| 57 |
-
updateNodeData(id, { messages }, { replace: true });
|
| 58 |
|
| 59 |
models.forEach((m) => {
|
| 60 |
const newNodeId = `assistant-${crypto.randomUUID()}`;
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
+
import { Send, X } from '@lucide/svelte';
|
| 3 |
import {
|
| 4 |
Handle,
|
| 5 |
useEdges,
|
|
|
|
| 28 |
const { update: updateEdges } = useEdges();
|
| 29 |
const { fitView, updateNodeData } = useSvelteFlow();
|
| 30 |
|
| 31 |
+
let selectedModels = $derived<ChatModel[]>(
|
| 32 |
(nodeData.current?.data.selectedModels as ChatModel[]) ?? []
|
| 33 |
);
|
| 34 |
let prompt = $state.raw<string>((nodeData.current?.data.prompt as string) ?? '');
|
|
|
|
| 36 |
let messages = $state.raw<ChatMessage[]>(
|
| 37 |
(nodeData.current?.data?.messages as ChatMessage[]) ?? []
|
| 38 |
);
|
|
|
|
| 39 |
|
| 40 |
function addModel(model: ChatModel) {
|
| 41 |
if (!selectedModels.some((m) => m.id === model.id)) {
|
| 42 |
+
updateNodeData(
|
| 43 |
+
id,
|
| 44 |
+
{
|
| 45 |
+
...nodeData.current,
|
| 46 |
+
selectedModels: [...selectedModels, model]
|
| 47 |
+
},
|
| 48 |
+
{ replace: true }
|
| 49 |
+
);
|
| 50 |
if (lastMessage) {
|
| 51 |
handleTriggerAction([model]);
|
| 52 |
}
|
| 53 |
}
|
| 54 |
}
|
| 55 |
function removeModel(model: ChatModel) {
|
| 56 |
+
updateNodeData(
|
| 57 |
+
id,
|
| 58 |
+
{
|
| 59 |
+
...nodeData.current,
|
| 60 |
+
selectedModels: selectedModels.filter((m) => m.id !== model.id)
|
| 61 |
+
},
|
| 62 |
+
{ replace: true }
|
| 63 |
+
);
|
| 64 |
}
|
| 65 |
|
| 66 |
function handleTriggerAction(models: ChatModel[] = selectedModels) {
|
| 67 |
const newNodes: Node[] = [];
|
| 68 |
const newEdges: Edge[] = [];
|
| 69 |
messages = [...messages, { role: 'user', content: prompt }];
|
| 70 |
+
updateNodeData(id, { ...nodeData.current?.data, messages }, { replace: true });
|
| 71 |
|
| 72 |
models.forEach((m) => {
|
| 73 |
const newNodeId = `assistant-${crypto.randomUUID()}`;
|
src/lib/components/model/SettingsModel.svelte
CHANGED
|
@@ -12,14 +12,18 @@
|
|
| 12 |
model,
|
| 13 |
children,
|
| 14 |
onSave
|
| 15 |
-
}: {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
// svelte-ignore state_referenced_locally
|
| 18 |
-
let temperature = $state<number>(model.temperature ??
|
| 19 |
// svelte-ignore state_referenced_locally
|
| 20 |
let max_tokens = $state<number | undefined>(model.max_tokens ?? undefined);
|
| 21 |
// svelte-ignore state_referenced_locally
|
| 22 |
-
let top_p = $state<number>(model.top_p ??
|
| 23 |
let open = $state<boolean>(false);
|
| 24 |
</script>
|
| 25 |
|
|
@@ -28,38 +32,58 @@
|
|
| 28 |
<Popover.Content class="w-80 rounded-2xl p-0">
|
| 29 |
<div class="grid gap-4">
|
| 30 |
<header class="border-b border-border px-5 pt-4 pb-4">
|
| 31 |
-
<h4 class="text-
|
| 32 |
</header>
|
| 33 |
<main class="grid gap-5 px-5 py-0">
|
| 34 |
<div class="space-y-1">
|
| 35 |
<div class="flex items-center justify-between">
|
| 36 |
<h4 class="text-sm leading-none font-medium">Temperature</h4>
|
| 37 |
-
<
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
min={0}
|
| 40 |
max={2}
|
| 41 |
-
step={0.
|
| 42 |
-
|
| 43 |
-
class="h-7! w-24!"
|
| 44 |
/>
|
| 45 |
-
|
| 46 |
-
<Slider type="single" bind:value={temperature} min={0} max={2} step={0.01} class="mt-2" />
|
| 47 |
</div>
|
| 48 |
|
| 49 |
<div class="space-y-1">
|
| 50 |
<div class="flex items-center justify-between">
|
| 51 |
<h4 class="text-sm leading-none font-medium">Max Tokens</h4>
|
| 52 |
<div class="flex items-center gap-1">
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
| 63 |
<Button variant="outline" size="icon-xs" onclick={() => (max_tokens = undefined)}>
|
| 64 |
<X class="size-3.5" />
|
| 65 |
</Button>
|
|
@@ -75,30 +99,39 @@
|
|
| 75 |
step={256}
|
| 76 |
class="mt-2"
|
| 77 |
/>
|
| 78 |
-
{:else}
|
| 79 |
-
<div class="mt-2 h-1.5 w-full rounded-full bg-muted"></div>
|
| 80 |
{/if}
|
| 81 |
</div>
|
| 82 |
|
| 83 |
<div class="space-y-1">
|
| 84 |
<div class="flex items-center justify-between">
|
| 85 |
<h4 class="text-sm leading-none font-medium">Top-P</h4>
|
| 86 |
-
<
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
</div>
|
| 95 |
-
|
|
|
|
|
|
|
| 96 |
</div>
|
| 97 |
</main>
|
| 98 |
<footer class="flex justify-end border-t border-border px-5 pt-3 pb-3">
|
| 99 |
<Button
|
| 100 |
variant="default"
|
| 101 |
-
size="
|
| 102 |
onclick={() => {
|
| 103 |
onSave({ ...model, temperature, max_tokens, top_p });
|
| 104 |
open = false;
|
|
|
|
| 12 |
model,
|
| 13 |
children,
|
| 14 |
onSave
|
| 15 |
+
}: {
|
| 16 |
+
model: ChatModel;
|
| 17 |
+
children: Snippet;
|
| 18 |
+
onSave: (model: ChatModel) => void;
|
| 19 |
+
} = $props();
|
| 20 |
|
| 21 |
// svelte-ignore state_referenced_locally
|
| 22 |
+
let temperature = $state<number | undefined>(model.temperature ?? undefined);
|
| 23 |
// svelte-ignore state_referenced_locally
|
| 24 |
let max_tokens = $state<number | undefined>(model.max_tokens ?? undefined);
|
| 25 |
// svelte-ignore state_referenced_locally
|
| 26 |
+
let top_p = $state<number | undefined>(model.top_p ?? undefined);
|
| 27 |
let open = $state<boolean>(false);
|
| 28 |
</script>
|
| 29 |
|
|
|
|
| 32 |
<Popover.Content class="w-80 rounded-2xl p-0">
|
| 33 |
<div class="grid gap-4">
|
| 34 |
<header class="border-b border-border px-5 pt-4 pb-4">
|
| 35 |
+
<h4 class="text-sm leading-none font-medium text-primary/90">Generation Settings</h4>
|
| 36 |
</header>
|
| 37 |
<main class="grid gap-5 px-5 py-0">
|
| 38 |
<div class="space-y-1">
|
| 39 |
<div class="flex items-center justify-between">
|
| 40 |
<h4 class="text-sm leading-none font-medium">Temperature</h4>
|
| 41 |
+
<div class="flex items-center gap-1">
|
| 42 |
+
{#if temperature === undefined}
|
| 43 |
+
<Button variant="blue" size="2xs" onclick={() => (temperature = 0.5)}>Set</Button>
|
| 44 |
+
{:else}
|
| 45 |
+
<Input
|
| 46 |
+
type="number"
|
| 47 |
+
min={0}
|
| 48 |
+
max={2}
|
| 49 |
+
step={0.1}
|
| 50 |
+
bind:value={temperature}
|
| 51 |
+
class="h-7! w-24!"
|
| 52 |
+
/>
|
| 53 |
+
<Button variant="outline" size="icon-xs" onclick={() => (temperature = undefined)}>
|
| 54 |
+
<X class="size-3.5" />
|
| 55 |
+
</Button>
|
| 56 |
+
{/if}
|
| 57 |
+
</div>
|
| 58 |
+
</div>
|
| 59 |
+
{#if temperature !== undefined}
|
| 60 |
+
<Slider
|
| 61 |
+
type="single"
|
| 62 |
+
bind:value={temperature}
|
| 63 |
min={0}
|
| 64 |
max={2}
|
| 65 |
+
step={0.01}
|
| 66 |
+
class="mt-2"
|
|
|
|
| 67 |
/>
|
| 68 |
+
{/if}
|
|
|
|
| 69 |
</div>
|
| 70 |
|
| 71 |
<div class="space-y-1">
|
| 72 |
<div class="flex items-center justify-between">
|
| 73 |
<h4 class="text-sm leading-none font-medium">Max Tokens</h4>
|
| 74 |
<div class="flex items-center gap-1">
|
| 75 |
+
{#if max_tokens === undefined}
|
| 76 |
+
<Button variant="blue" size="2xs" onclick={() => (max_tokens = 32000)}>Set</Button>
|
| 77 |
+
{:else}
|
| 78 |
+
<Input
|
| 79 |
+
type="number"
|
| 80 |
+
min={0}
|
| 81 |
+
max={204800}
|
| 82 |
+
step={256}
|
| 83 |
+
placeholder="—"
|
| 84 |
+
class="h-7! w-24!"
|
| 85 |
+
bind:value={max_tokens}
|
| 86 |
+
/>
|
| 87 |
<Button variant="outline" size="icon-xs" onclick={() => (max_tokens = undefined)}>
|
| 88 |
<X class="size-3.5" />
|
| 89 |
</Button>
|
|
|
|
| 99 |
step={256}
|
| 100 |
class="mt-2"
|
| 101 |
/>
|
|
|
|
|
|
|
| 102 |
{/if}
|
| 103 |
</div>
|
| 104 |
|
| 105 |
<div class="space-y-1">
|
| 106 |
<div class="flex items-center justify-between">
|
| 107 |
<h4 class="text-sm leading-none font-medium">Top-P</h4>
|
| 108 |
+
<div class="flex items-center gap-1">
|
| 109 |
+
{#if top_p === undefined}
|
| 110 |
+
<Button variant="blue" size="2xs" onclick={() => (top_p = 0.7)}>Set</Button>
|
| 111 |
+
{:else}
|
| 112 |
+
<Input
|
| 113 |
+
type="number"
|
| 114 |
+
min={0}
|
| 115 |
+
max={1}
|
| 116 |
+
step={0.01}
|
| 117 |
+
bind:value={top_p}
|
| 118 |
+
class="h-7! w-24!"
|
| 119 |
+
/>
|
| 120 |
+
<Button variant="outline" size="icon-xs" onclick={() => (top_p = undefined)}>
|
| 121 |
+
<X class="size-3.5" />
|
| 122 |
+
</Button>
|
| 123 |
+
{/if}
|
| 124 |
+
</div>
|
| 125 |
</div>
|
| 126 |
+
{#if top_p !== undefined}
|
| 127 |
+
<Slider type="single" bind:value={top_p} min={0} max={1} step={0.01} class="mt-2" />
|
| 128 |
+
{/if}
|
| 129 |
</div>
|
| 130 |
</main>
|
| 131 |
<footer class="flex justify-end border-t border-border px-5 pt-3 pb-3">
|
| 132 |
<Button
|
| 133 |
variant="default"
|
| 134 |
+
size="xs"
|
| 135 |
onclick={() => {
|
| 136 |
onSave({ ...model, temperature, max_tokens, top_p });
|
| 137 |
open = false;
|
src/lib/components/ui/button/button.svelte
CHANGED
|
@@ -14,12 +14,14 @@
|
|
| 14 |
'bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs text-gray-600 dark:text-gray-400',
|
| 15 |
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs',
|
| 16 |
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
| 17 |
-
link: 'text-primary underline-offset-4 hover:underline'
|
|
|
|
| 18 |
},
|
| 19 |
size: {
|
| 20 |
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
| 21 |
sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
|
| 22 |
-
xs: 'h-7 gap-1 rounded-md px-2.5 has-[>svg]:px-2',
|
|
|
|
| 23 |
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
| 24 |
icon: 'size-9',
|
| 25 |
'icon-sm': 'size-8',
|
|
|
|
| 14 |
'bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs text-gray-600 dark:text-gray-400',
|
| 15 |
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs',
|
| 16 |
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
| 17 |
+
link: 'text-primary underline-offset-4 hover:underline',
|
| 18 |
+
blue: 'bg-blue-500/10 text-blue-500 border border-blue-500/20 hover:bg-blue-500/20 shadow-xs'
|
| 19 |
},
|
| 20 |
size: {
|
| 21 |
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
| 22 |
sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
|
| 23 |
+
xs: 'h-7 gap-1 rounded-md px-2.5 has-[>svg]:px-2 text-xs!',
|
| 24 |
+
'2xs': 'h-6 gap-1 rounded-md px-2.5 has-[>svg]:px-2 text-xs!',
|
| 25 |
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
| 26 |
icon: 'size-9',
|
| 27 |
'icon-sm': 'size-8',
|