Spaces:
Runtime error
Runtime error
Thomas G. Lopes
commited on
Commit
·
d7d2be5
1
Parent(s):
bee7674
images upload
Browse files
src/routes/canvas/+page.svelte
CHANGED
|
@@ -8,6 +8,7 @@
|
|
| 8 |
import ChatNode from "./chat-node.svelte";
|
| 9 |
import { edges, nodes } from "./state.js";
|
| 10 |
import { models } from "$lib/state/models.svelte";
|
|
|
|
| 11 |
|
| 12 |
const nodeTypes = { chat: ChatNode } as const;
|
| 13 |
|
|
@@ -80,3 +81,5 @@
|
|
| 80 |
</SvelteFlow>
|
| 81 |
{/if}
|
| 82 |
</div>
|
|
|
|
|
|
|
|
|
| 8 |
import ChatNode from "./chat-node.svelte";
|
| 9 |
import { edges, nodes } from "./state.js";
|
| 10 |
import { models } from "$lib/state/models.svelte";
|
| 11 |
+
import ImgPreview from "$lib/components/inference-playground/img-preview.svelte";
|
| 12 |
|
| 13 |
const nodeTypes = { chat: ChatNode } as const;
|
| 14 |
|
|
|
|
| 81 |
</SvelteFlow>
|
| 82 |
{/if}
|
| 83 |
</div>
|
| 84 |
+
|
| 85 |
+
<ImgPreview />
|
src/routes/canvas/chat-node.svelte
CHANGED
|
@@ -1,28 +1,32 @@
|
|
| 1 |
<script lang="ts">
|
|
|
|
| 2 |
import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte";
|
|
|
|
| 3 |
import { models } from "$lib/state/models.svelte";
|
| 4 |
import { token } from "$lib/state/token.svelte";
|
| 5 |
import type { Model } from "$lib/types.js";
|
|
|
|
| 6 |
import { InferenceClient } from "@huggingface/inference";
|
|
|
|
| 7 |
import { Handle, Position, useSvelteFlow, type Edge, type Node, type NodeProps } from "@xyflow/svelte";
|
|
|
|
|
|
|
|
|
|
| 8 |
import { onMount } from "svelte";
|
| 9 |
-
import {
|
| 10 |
-
import
|
| 11 |
-
import
|
| 12 |
-
import
|
| 13 |
-
import IconStop from "~icons/lucide/square";
|
| 14 |
import IconCopy from "~icons/lucide/copy";
|
|
|
|
| 15 |
import IconAttachment from "~icons/lucide/paperclip";
|
| 16 |
-
import
|
| 17 |
import IconSend from "~icons/lucide/send";
|
| 18 |
-
import
|
|
|
|
| 19 |
import ModelPicker from "./model-picker.svelte";
|
| 20 |
import ProviderPicker from "./provider-picker.svelte";
|
| 21 |
-
import {
|
| 22 |
-
import { marked } from "marked";
|
| 23 |
-
import { images } from "$lib/state/images.svelte.js";
|
| 24 |
-
import { AsyncQueue } from "$lib/utils/queue.js";
|
| 25 |
-
import { FileUpload } from "melt/builders";
|
| 26 |
|
| 27 |
type Props = Omit<NodeProps, "data"> & {
|
| 28 |
data: { query: string; response: string; modelId?: Model["id"]; provider?: string; imageIds?: string[] };
|
|
@@ -315,7 +319,17 @@
|
|
| 315 |
<!-- Message container with top bar, textarea, and bottom bar -->
|
| 316 |
<div
|
| 317 |
class="rounded-lg border border-gray-200 bg-gray-50 focus-within:border-gray-900 focus-within:ring-2 focus-within:ring-gray-900/10"
|
|
|
|
| 318 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
<!-- Top bar with buttons and character count -->
|
| 320 |
<div class="flex items-center justify-between border-b border-gray-200 px-4 py-2">
|
| 321 |
<div class="flex items-center gap-2">
|
|
@@ -323,8 +337,10 @@
|
|
| 323 |
type="button"
|
| 324 |
class="flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-200 hover:text-gray-900"
|
| 325 |
title="Attach file"
|
|
|
|
| 326 |
>
|
| 327 |
<IconAttachment class="h-4 w-4" />
|
|
|
|
| 328 |
</button>
|
| 329 |
<button
|
| 330 |
type="button"
|
|
@@ -355,6 +371,39 @@
|
|
| 355 |
</div>
|
| 356 |
</div>
|
| 357 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
<!-- Bottom bar with hint and send button (outside textarea) -->
|
| 359 |
<div class="mt-2 flex items-center justify-between">
|
| 360 |
<div class="text-xs text-gray-500">Shift + Enter for newline</div>
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
+
import { previewImage } from "$lib/components/inference-playground/img-preview.svelte";
|
| 3 |
import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte";
|
| 4 |
+
import { images } from "$lib/state/images.svelte.js";
|
| 5 |
import { models } from "$lib/state/models.svelte";
|
| 6 |
import { token } from "$lib/state/token.svelte";
|
| 7 |
import type { Model } from "$lib/types.js";
|
| 8 |
+
import { AsyncQueue } from "$lib/utils/queue.js";
|
| 9 |
import { InferenceClient } from "@huggingface/inference";
|
| 10 |
+
import type { ChatCompletionInputMessage } from "@huggingface/tasks";
|
| 11 |
import { Handle, Position, useSvelteFlow, type Edge, type Node, type NodeProps } from "@xyflow/svelte";
|
| 12 |
+
import { marked } from "marked";
|
| 13 |
+
import { FileUpload } from "melt/builders";
|
| 14 |
+
import { ElementSize } from "runed";
|
| 15 |
import { onMount } from "svelte";
|
| 16 |
+
import { fade } from "svelte/transition";
|
| 17 |
+
import IconImage from "~icons/carbon/image-reference";
|
| 18 |
+
import IconMaximize from "~icons/carbon/maximize";
|
| 19 |
+
import IconCode from "~icons/lucide/code";
|
|
|
|
| 20 |
import IconCopy from "~icons/lucide/copy";
|
| 21 |
+
import IconLoading from "~icons/lucide/loader-2";
|
| 22 |
import IconAttachment from "~icons/lucide/paperclip";
|
| 23 |
+
import IconAdd from "~icons/lucide/plus";
|
| 24 |
import IconSend from "~icons/lucide/send";
|
| 25 |
+
import IconStop from "~icons/lucide/square";
|
| 26 |
+
import IconX from "~icons/lucide/x";
|
| 27 |
import ModelPicker from "./model-picker.svelte";
|
| 28 |
import ProviderPicker from "./provider-picker.svelte";
|
| 29 |
+
import { edges, nodes } from "./state.js";
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
type Props = Omit<NodeProps, "data"> & {
|
| 32 |
data: { query: string; response: string; modelId?: Model["id"]; provider?: string; imageIds?: string[] };
|
|
|
|
| 319 |
<!-- Message container with top bar, textarea, and bottom bar -->
|
| 320 |
<div
|
| 321 |
class="rounded-lg border border-gray-200 bg-gray-50 focus-within:border-gray-900 focus-within:ring-2 focus-within:ring-gray-900/10"
|
| 322 |
+
{...fileUpload.dropzone}
|
| 323 |
>
|
| 324 |
+
{#if fileUpload.isDragging}
|
| 325 |
+
<div
|
| 326 |
+
class="absolute inset-2 z-10 flex flex-col items-center justify-center rounded-xl bg-gray-800/50 backdrop-blur-md"
|
| 327 |
+
transition:fade={{ duration: 100 }}
|
| 328 |
+
>
|
| 329 |
+
<IconImage />
|
| 330 |
+
<p>Drop the image here to upload</p>
|
| 331 |
+
</div>
|
| 332 |
+
{/if}
|
| 333 |
<!-- Top bar with buttons and character count -->
|
| 334 |
<div class="flex items-center justify-between border-b border-gray-200 px-4 py-2">
|
| 335 |
<div class="flex items-center gap-2">
|
|
|
|
| 337 |
type="button"
|
| 338 |
class="flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-200 hover:text-gray-900"
|
| 339 |
title="Attach file"
|
| 340 |
+
{...fileUpload.trigger}
|
| 341 |
>
|
| 342 |
<IconAttachment class="h-4 w-4" />
|
| 343 |
+
<input {...fileUpload.input} />
|
| 344 |
</button>
|
| 345 |
<button
|
| 346 |
type="button"
|
|
|
|
| 371 |
</div>
|
| 372 |
</div>
|
| 373 |
|
| 374 |
+
<div class="mt-2">
|
| 375 |
+
<div class="flex items-center gap-2">
|
| 376 |
+
{#each data.imageIds ?? [] as imgKey (imgKey)}
|
| 377 |
+
{#await images.get(imgKey)}
|
| 378 |
+
<!-- nothing -->
|
| 379 |
+
{:then imgSrc}
|
| 380 |
+
<div class="group/img relative">
|
| 381 |
+
<button
|
| 382 |
+
aria-label="expand"
|
| 383 |
+
class="absolute inset-0 z-10 grid place-items-center rounded-md bg-gray-800/70 text-white opacity-0 group-hover/img:opacity-100"
|
| 384 |
+
onclick={() => previewImage(imgSrc)}
|
| 385 |
+
>
|
| 386 |
+
<IconMaximize />
|
| 387 |
+
</button>
|
| 388 |
+
<img src={imgSrc} alt="uploaded" class="size-12 rounded-md object-cover" />
|
| 389 |
+
<button
|
| 390 |
+
aria-label="remove"
|
| 391 |
+
type="button"
|
| 392 |
+
onclick={async e => {
|
| 393 |
+
e.stopPropagation();
|
| 394 |
+
updateNodeData(id, { imageIds: data.imageIds?.filter(i => i !== imgKey) });
|
| 395 |
+
images.delete(imgKey);
|
| 396 |
+
}}
|
| 397 |
+
class="invisible absolute -top-1 -right-1 z-20 grid size-5 place-items-center rounded-full bg-gray-800 text-xs text-white group-hover/img:visible hover:bg-gray-700"
|
| 398 |
+
>
|
| 399 |
+
✕
|
| 400 |
+
</button>
|
| 401 |
+
</div>
|
| 402 |
+
{/await}
|
| 403 |
+
{/each}
|
| 404 |
+
</div>
|
| 405 |
+
</div>
|
| 406 |
+
|
| 407 |
<!-- Bottom bar with hint and send button (outside textarea) -->
|
| 408 |
<div class="mt-2 flex items-center justify-between">
|
| 409 |
<div class="text-xs text-gray-500">Shift + Enter for newline</div>
|