Spaces:
Running
Running
show model that supports image input
Browse files
src/lib/components/model/ListModels.svelte
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
-
import { X } from '@lucide/svelte';
|
| 3 |
|
| 4 |
import { Button } from '$lib/components/ui/button';
|
| 5 |
import SettingsModel from './SettingsModel.svelte';
|
|
|
|
|
|
|
| 6 |
|
| 7 |
let {
|
| 8 |
selectedModels,
|
|
@@ -15,7 +17,8 @@
|
|
| 15 |
} = $props();
|
| 16 |
</script>
|
| 17 |
|
| 18 |
-
{#each selectedModels as model}
|
|
|
|
| 19 |
{#if !showSelector}
|
| 20 |
<div
|
| 21 |
class="group relative inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md border bg-background px-3 text-sm font-normal! text-gray-600 has-[>svg]:px-2.5 dark:border-input dark:bg-input/30 dark:text-gray-400"
|
|
@@ -36,6 +39,20 @@
|
|
| 36 |
class="size-3.5 rounded"
|
| 37 |
/>
|
| 38 |
{model.split('/').pop() ?? model}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
<Button
|
| 40 |
variant="default"
|
| 41 |
size="icon-3xs"
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
+
import { Image, X } from '@lucide/svelte';
|
| 3 |
|
| 4 |
import { Button } from '$lib/components/ui/button';
|
| 5 |
import SettingsModel from './SettingsModel.svelte';
|
| 6 |
+
import { modelsState } from '$lib/state/models.svelte';
|
| 7 |
+
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
|
| 8 |
|
| 9 |
let {
|
| 10 |
selectedModels,
|
|
|
|
| 17 |
} = $props();
|
| 18 |
</script>
|
| 19 |
|
| 20 |
+
{#each selectedModels as model (model)}
|
| 21 |
+
{@const modelData = modelsState.models.find((m) => m.id === model)}
|
| 22 |
{#if !showSelector}
|
| 23 |
<div
|
| 24 |
class="group relative inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md border bg-background px-3 text-sm font-normal! text-gray-600 has-[>svg]:px-2.5 dark:border-input dark:bg-input/30 dark:text-gray-400"
|
|
|
|
| 39 |
class="size-3.5 rounded"
|
| 40 |
/>
|
| 41 |
{model.split('/').pop() ?? model}
|
| 42 |
+
{#if modelData?.architecture?.input_modalities?.includes('image')}
|
| 43 |
+
<Tooltip.Root delayDuration={0}>
|
| 44 |
+
<Tooltip.Trigger>
|
| 45 |
+
<span
|
| 46 |
+
class="flex size-4 items-center justify-center rounded bg-gray-500/10 text-xs text-gray-500"
|
| 47 |
+
>
|
| 48 |
+
<Image class="size-2.5" />
|
| 49 |
+
</span>
|
| 50 |
+
</Tooltip.Trigger>
|
| 51 |
+
<Tooltip.Content>
|
| 52 |
+
<p>This model supports image input.</p>
|
| 53 |
+
</Tooltip.Content>
|
| 54 |
+
</Tooltip.Root>
|
| 55 |
+
{/if}
|
| 56 |
<Button
|
| 57 |
variant="default"
|
| 58 |
size="icon-3xs"
|
src/lib/components/model/SettingsModel.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
import type { Snippet } from 'svelte';
|
| 3 |
-
import { Check, ExternalLink, Frown, MessageCircle,
|
| 4 |
|
| 5 |
import type { ChatModel } from '$lib/helpers/types';
|
| 6 |
import { formatPricingPerToken, getProviderName } from '$lib/index.js';
|
|
@@ -65,7 +65,8 @@
|
|
| 65 |
if (loading) return;
|
| 66 |
loading = true;
|
| 67 |
await new Promise((resolve) => setTimeout(resolve, 600));
|
| 68 |
-
|
|
|
|
| 69 |
loading = false;
|
| 70 |
open = false;
|
| 71 |
}
|
|
@@ -123,7 +124,7 @@
|
|
| 123 |
>
|
| 124 |
</div>
|
| 125 |
{/if}
|
| 126 |
-
{#each modelsFiltered as mdl
|
| 127 |
<button
|
| 128 |
class="{mdl.id === model?.id
|
| 129 |
? 'from-blue-500/20! to-blue-500/5! dark:from-blue-500/50! dark:to-blue-500/20!'
|
|
@@ -143,22 +144,40 @@
|
|
| 143 |
</span>
|
| 144 |
</span>
|
| 145 |
</span>
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
<Tooltip.
|
| 149 |
-
<
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
<
|
| 157 |
-
<
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
</button>
|
| 163 |
{/each}
|
| 164 |
</div>
|
|
@@ -224,7 +243,7 @@
|
|
| 224 |
<Select.Content>
|
| 225 |
<Select.Group>
|
| 226 |
<Select.GroupHeading>Selection mode</Select.GroupHeading>
|
| 227 |
-
{#each PROVIDER_SELECTION_MODES as mode}
|
| 228 |
<Select.Item value={mode.value}>
|
| 229 |
<div class="flex size-5 items-center justify-center rounded {mode.class}">
|
| 230 |
<mode.icon class="size-3 {mode.iconClass}" />
|
|
@@ -243,7 +262,7 @@
|
|
| 243 |
<Select.Separator />
|
| 244 |
<Select.Group>
|
| 245 |
<Select.GroupHeading>Specific provider</Select.GroupHeading>
|
| 246 |
-
{#each model.providers as provider}
|
| 247 |
{@const providerName = getProviderName(provider.provider)}
|
| 248 |
<Select.Item value={provider.provider}>
|
| 249 |
<div class="flex items-center gap-2 capitalize">
|
|
@@ -390,9 +409,13 @@
|
|
| 390 |
</div>
|
| 391 |
</div>
|
| 392 |
<div class="flex items-center justify-end gap-3">
|
| 393 |
-
<Button
|
|
|
|
|
|
|
|
|
|
|
|
|
| 394 |
<MessageCircle class="size-4" />
|
| 395 |
-
{#if selectedModels.includes(model
|
| 396 |
Remove from chat
|
| 397 |
{:else}
|
| 398 |
Use this model
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
import type { Snippet } from 'svelte';
|
| 3 |
+
import { Check, ExternalLink, Frown, MessageCircle, Save, X, Image } from '@lucide/svelte';
|
| 4 |
|
| 5 |
import type { ChatModel } from '$lib/helpers/types';
|
| 6 |
import { formatPricingPerToken, getProviderName } from '$lib/index.js';
|
|
|
|
| 65 |
if (loading) return;
|
| 66 |
loading = true;
|
| 67 |
await new Promise((resolve) => setTimeout(resolve, 600));
|
| 68 |
+
if (!model) return;
|
| 69 |
+
saveModelSettings(model.id, { temperature, top_p, max_tokens, provider });
|
| 70 |
loading = false;
|
| 71 |
open = false;
|
| 72 |
}
|
|
|
|
| 124 |
>
|
| 125 |
</div>
|
| 126 |
{/if}
|
| 127 |
+
{#each modelsFiltered as mdl (mdl.id)}
|
| 128 |
<button
|
| 129 |
class="{mdl.id === model?.id
|
| 130 |
? 'from-blue-500/20! to-blue-500/5! dark:from-blue-500/50! dark:to-blue-500/20!'
|
|
|
|
| 144 |
</span>
|
| 145 |
</span>
|
| 146 |
</span>
|
| 147 |
+
<div class="flex items-center gap-1">
|
| 148 |
+
{#if mdl.architecture?.input_modalities?.includes('image')}
|
| 149 |
+
<Tooltip.Root delayDuration={0}>
|
| 150 |
+
<Tooltip.Trigger>
|
| 151 |
+
<span
|
| 152 |
+
class="flex size-[18px] items-center justify-center rounded bg-gray-500/10 text-gray-500"
|
| 153 |
+
>
|
| 154 |
+
<Image class="size-2.5" />
|
| 155 |
+
</span>
|
| 156 |
+
</Tooltip.Trigger>
|
| 157 |
+
<Tooltip.Content>
|
| 158 |
+
<p class="flex items-center gap-1">
|
| 159 |
+
<Check class="size-3.5" /> This model supports image input
|
| 160 |
+
</p>
|
| 161 |
+
</Tooltip.Content>
|
| 162 |
+
</Tooltip.Root>
|
| 163 |
+
{/if}
|
| 164 |
+
{#if selectedModels.includes(mdl.id)}
|
| 165 |
+
<Tooltip.Root delayDuration={0}>
|
| 166 |
+
<Tooltip.Trigger>
|
| 167 |
+
<span
|
| 168 |
+
class="flex size-[18px] items-center justify-center rounded bg-indigo-500/10 text-indigo-500"
|
| 169 |
+
>
|
| 170 |
+
<MessageCircle class="size-2.5 fill-indigo-500" />
|
| 171 |
+
</span>
|
| 172 |
+
</Tooltip.Trigger>
|
| 173 |
+
<Tooltip.Content>
|
| 174 |
+
<p class="flex items-center gap-1">
|
| 175 |
+
<Check class="size-3.5" /> This model will be used in the flow
|
| 176 |
+
</p>
|
| 177 |
+
</Tooltip.Content>
|
| 178 |
+
</Tooltip.Root>
|
| 179 |
+
{/if}
|
| 180 |
+
</div>
|
| 181 |
</button>
|
| 182 |
{/each}
|
| 183 |
</div>
|
|
|
|
| 243 |
<Select.Content>
|
| 244 |
<Select.Group>
|
| 245 |
<Select.GroupHeading>Selection mode</Select.GroupHeading>
|
| 246 |
+
{#each PROVIDER_SELECTION_MODES as mode (mode.value)}
|
| 247 |
<Select.Item value={mode.value}>
|
| 248 |
<div class="flex size-5 items-center justify-center rounded {mode.class}">
|
| 249 |
<mode.icon class="size-3 {mode.iconClass}" />
|
|
|
|
| 262 |
<Select.Separator />
|
| 263 |
<Select.Group>
|
| 264 |
<Select.GroupHeading>Specific provider</Select.GroupHeading>
|
| 265 |
+
{#each model.providers as provider (provider.provider)}
|
| 266 |
{@const providerName = getProviderName(provider.provider)}
|
| 267 |
<Select.Item value={provider.provider}>
|
| 268 |
<div class="flex items-center gap-2 capitalize">
|
|
|
|
| 409 |
</div>
|
| 410 |
</div>
|
| 411 |
<div class="flex items-center justify-end gap-3">
|
| 412 |
+
<Button
|
| 413 |
+
variant="outline"
|
| 414 |
+
class="flex-1"
|
| 415 |
+
onclick={() => model && onToggleModel?.(model.id)}
|
| 416 |
+
>
|
| 417 |
<MessageCircle class="size-4" />
|
| 418 |
+
{#if model && selectedModels.includes(model.id)}
|
| 419 |
Remove from chat
|
| 420 |
{:else}
|
| 421 |
Use this model
|
src/lib/helpers/types.ts
CHANGED
|
@@ -1,17 +1,4 @@
|
|
| 1 |
export interface ChatModel {
|
| 2 |
-
// id: string;
|
| 3 |
-
// modelId: string;
|
| 4 |
-
// modelName: string;
|
| 5 |
-
// author: string;
|
| 6 |
-
// avatarUrl: string;
|
| 7 |
-
// pipeline_tag?: 'text-generation' | 'image-text-to-text';
|
| 8 |
-
// likes?: number;
|
| 9 |
-
// downloads?: number;
|
| 10 |
-
// temperature?: number;
|
| 11 |
-
// max_tokens?: number;
|
| 12 |
-
// top_p?: number;
|
| 13 |
-
// provider: string;
|
| 14 |
-
// isError?: boolean;
|
| 15 |
id: string;
|
| 16 |
owned_by: string;
|
| 17 |
providers: ChatModelProvider[];
|
|
@@ -20,6 +7,9 @@ export interface ChatModel {
|
|
| 20 |
temperature?: number;
|
| 21 |
max_tokens?: number;
|
| 22 |
top_p?: number;
|
|
|
|
|
|
|
|
|
|
| 23 |
}
|
| 24 |
|
| 25 |
export interface ChatModelProvider {
|
|
|
|
| 1 |
export interface ChatModel {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
id: string;
|
| 3 |
owned_by: string;
|
| 4 |
providers: ChatModelProvider[];
|
|
|
|
| 7 |
temperature?: number;
|
| 8 |
max_tokens?: number;
|
| 9 |
top_p?: number;
|
| 10 |
+
architecture?: {
|
| 11 |
+
input_modalities?: string[];
|
| 12 |
+
};
|
| 13 |
}
|
| 14 |
|
| 15 |
export interface ChatModelProvider {
|