mishig HF staff commited on
Commit
502cb81
1 Parent(s): bb96856

Created the needed Conversation.svelte component (#10)

Browse files
src/lib/components/Conversation.svelte ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from "svelte";
3
+ import PlaygroundCode from '$lib/components/CodeSnippets.svelte';
4
+ import PlaygroundMessage from '$lib/components/Message.svelte';
5
+
6
+ export let loading;
7
+ export let streamingMessage;
8
+ export let conversations;
9
+ export let conversation;
10
+ export let index;
11
+ export let currentConversation;
12
+ export let viewCode;
13
+ export let messages;
14
+
15
+ const dispatch = createEventDispatcher<{ addMessage: void; deleteMessage: number }>();
16
+
17
+ let messageContainer: HTMLDivElement | null = null;
18
+
19
+ function scrollToBottom() {
20
+ if (messageContainer) {
21
+ messageContainer.scrollTop = messageContainer.scrollHeight;
22
+ }
23
+ }
24
+
25
+ $:{
26
+ if(currentConversation.messages.at(-1)){
27
+ scrollToBottom();
28
+ }
29
+ }
30
+ </script>
31
+ <div
32
+ class="flex max-h-[calc(100dvh-5.8rem)] flex-col overflow-y-auto overflow-x-hidden @container"
33
+ class:pointer-events-none={loading}
34
+ class:animate-pulse={loading && !streamingMessage}
35
+ bind:this={messageContainer}
36
+ >
37
+ {#if conversations.length > 1}
38
+ <div
39
+ class="sticky top-0 flex h-11 flex-none items-center gap-2 whitespace-nowrap rounded-lg border border-gray-200/80 bg-white pl-3 pr-2 text-sm leading-none shadow-sm *:flex-none dark:border-gray-800 dark:bg-gray-800/70 dark:hover:bg-gray-800"
40
+ class:mr-3={index === 0}
41
+ class:mx-3={index === 1}
42
+ >
43
+ <div class="size-3.5 rounded bg-black dark:bg-gray-400"></div>
44
+ <div>{conversation.model}</div>
45
+ <button
46
+ class="ml-auto flex size-6 items-center justify-center rounded bg-gray-50 text-xs hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700"
47
+ on:click={() => (conversations = conversations.filter((_, i) => i !== index))}
48
+ >
49
+
50
+ </button>
51
+ <button
52
+ class=" flex size-6 items-center justify-center rounded bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700"
53
+ >
54
+ <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 32 32"
55
+ ><path
56
+ fill="currentColor"
57
+ d="M27 16.76v-1.53l1.92-1.68A2 2 0 0 0 29.3 11l-2.36-4a2 2 0 0 0-1.73-1a2 2 0 0 0-.64.1l-2.43.82a11.35 11.35 0 0 0-1.31-.75l-.51-2.52a2 2 0 0 0-2-1.61h-4.68a2 2 0 0 0-2 1.61l-.51 2.52a11.48 11.48 0 0 0-1.32.75l-2.38-.86A2 2 0 0 0 6.79 6a2 2 0 0 0-1.73 1L2.7 11a2 2 0 0 0 .41 2.51L5 15.24v1.53l-1.89 1.68A2 2 0 0 0 2.7 21l2.36 4a2 2 0 0 0 1.73 1a2 2 0 0 0 .64-.1l2.43-.82a11.35 11.35 0 0 0 1.31.75l.51 2.52a2 2 0 0 0 2 1.61h4.72a2 2 0 0 0 2-1.61l.51-2.52a11.48 11.48 0 0 0 1.32-.75l2.42.82a2 2 0 0 0 .64.1a2 2 0 0 0 1.73-1l2.28-4a2 2 0 0 0-.41-2.51ZM25.21 24l-3.43-1.16a8.86 8.86 0 0 1-2.71 1.57L18.36 28h-4.72l-.71-3.55a9.36 9.36 0 0 1-2.7-1.57L6.79 24l-2.36-4l2.72-2.4a8.9 8.9 0 0 1 0-3.13L4.43 12l2.36-4l3.43 1.16a8.86 8.86 0 0 1 2.71-1.57L13.64 4h4.72l.71 3.55a9.36 9.36 0 0 1 2.7 1.57L25.21 8l2.36 4l-2.72 2.4a8.9 8.9 0 0 1 0 3.13L27.57 20Z"
58
+ /><path
59
+ fill="currentColor"
60
+ d="M16 22a6 6 0 1 1 6-6a5.94 5.94 0 0 1-6 6Zm0-10a3.91 3.91 0 0 0-4 4a3.91 3.91 0 0 0 4 4a3.91 3.91 0 0 0 4-4a3.91 3.91 0 0 0-4-4Z"
61
+ /></svg
62
+ >
63
+ </button>
64
+ </div>
65
+ {/if}
66
+ {#if !viewCode}
67
+ {#each messages as message, i}
68
+ <PlaygroundMessage
69
+ class="border-b"
70
+ {message}
71
+ on:delete={() => dispatch("deleteMessage", i)}
72
+ autofocus={conversations.length === 1 && !loading && i === messages.length - 1}
73
+ />
74
+ {/each}
75
+
76
+ <button
77
+ class="flex px-6 py-6 hover:bg-gray-50 dark:hover:bg-gray-800/50"
78
+ on:click={() => dispatch("addMessage")}
79
+ disabled={loading}
80
+ >
81
+ <div class="flex items-center gap-2 !p-0 text-sm font-semibold">
82
+ <svg
83
+ xmlns="http://www.w3.org/2000/svg"
84
+ width="1em"
85
+ height="1em"
86
+ viewBox="0 0 32 32"
87
+ class="text-lg"
88
+ ><path
89
+ fill="currentColor"
90
+ d="M16 2A14.172 14.172 0 0 0 2 16a14.172 14.172 0 0 0 14 14a14.172 14.172 0 0 0 14-14A14.172 14.172 0 0 0 16 2Zm8 15h-7v7h-2v-7H8v-2h7V8h2v7h7Z"
91
+ /><path fill="none" d="M24 17h-7v7h-2v-7H8v-2h7V8h2v7h7v2z" /></svg
92
+ >Add message
93
+ </div>
94
+ </button>
95
+ {:else}
96
+ <PlaygroundCode {...currentConversation} {...currentConversation.config} />
97
+ {/if}
98
+ </div>
src/routes/+page.svelte CHANGED
@@ -6,10 +6,10 @@
6
  handleStreamingResponse,
7
  handleNonStreamingResponse
8
  } from '$lib/components/playgroundUtils';
9
- import PlaygroundMessage from '$lib/components/Message.svelte';
10
  import PlaygroundOptions from '$lib/components/GenerationConfig.svelte';
11
  import PlaygroundTokenModal from '$lib/components/HFTokenModal.svelte';
12
  import PlaygroundModelSelector from '$lib/components/ModelSelector.svelte';
 
13
  import { onDestroy, onMount } from 'svelte';
14
  import { type ModelEntry } from "@huggingface/hub";
15
  import { type ChatCompletionInputMessage } from "@huggingface/tasks";
@@ -43,7 +43,6 @@
43
  let streamingMessage: ChatCompletionInputMessage | null = null;
44
  let tokens = 0;
45
  let latency = 0;
46
- let messageContainer: HTMLDivElement | null = null;
47
  let abortController: AbortController | null = null;
48
  let waitForNonStreaming = true;
49
 
@@ -142,7 +141,6 @@
142
  streamingMessage.content = content;
143
  currentConversation.messages = [...currentConversation.messages];
144
  conversations = conversations;
145
- scrollToBottom();
146
  }
147
  },
148
  abortController
@@ -162,7 +160,6 @@
162
  if(waitForNonStreaming){
163
  currentConversation.messages = [...currentConversation.messages, newMessage];
164
  conversations = conversations;
165
- scrollToBottom();
166
  }
167
  }
168
 
@@ -177,7 +174,6 @@
177
  loading = false;
178
  streamingMessage = null;
179
  abortController = null;
180
- scrollToBottom();
181
  }
182
  }
183
 
@@ -186,12 +182,6 @@
186
  submit();
187
  }
188
  }
189
-
190
- function scrollToBottom() {
191
- if (messageContainer) {
192
- messageContainer.scrollTop = messageContainer.scrollHeight;
193
- }
194
- }
195
  </script>
196
 
197
  <svelte:window on:keydown={onKeydown} />
@@ -239,74 +229,19 @@
239
  : '*:w-full'} dark:divide-gray-800"
240
  >
241
  {#each conversations as conversation, index}
242
- <div
243
- class="flex max-h-[calc(100dvh-5.8rem)] flex-col overflow-y-auto overflow-x-hidden @container"
244
- class:pointer-events-none={loading}
245
- class:animate-pulse={loading && !streamingMessage}
246
- bind:this={messageContainer}
247
- >
248
- {#if conversations.length > 1}
249
- <div
250
- class="sticky top-0 flex h-11 flex-none items-center gap-2 whitespace-nowrap rounded-lg border border-gray-200/80 bg-white pl-3 pr-2 text-sm leading-none shadow-sm *:flex-none dark:border-gray-800 dark:bg-gray-800/70 dark:hover:bg-gray-800"
251
- class:mr-3={index === 0}
252
- class:mx-3={index === 1}
253
- >
254
- <div class="size-3.5 rounded bg-black dark:bg-gray-400"></div>
255
- <div>{conversation.model}</div>
256
- <button
257
- class="ml-auto flex size-6 items-center justify-center rounded bg-gray-50 text-xs hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700"
258
- on:click={() => (conversations = conversations.filter((_, i) => i !== index))}
259
- >
260
-
261
- </button>
262
- <button
263
- class=" flex size-6 items-center justify-center rounded bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700"
264
- >
265
- <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 32 32"
266
- ><path
267
- fill="currentColor"
268
- d="M27 16.76v-1.53l1.92-1.68A2 2 0 0 0 29.3 11l-2.36-4a2 2 0 0 0-1.73-1a2 2 0 0 0-.64.1l-2.43.82a11.35 11.35 0 0 0-1.31-.75l-.51-2.52a2 2 0 0 0-2-1.61h-4.68a2 2 0 0 0-2 1.61l-.51 2.52a11.48 11.48 0 0 0-1.32.75l-2.38-.86A2 2 0 0 0 6.79 6a2 2 0 0 0-1.73 1L2.7 11a2 2 0 0 0 .41 2.51L5 15.24v1.53l-1.89 1.68A2 2 0 0 0 2.7 21l2.36 4a2 2 0 0 0 1.73 1a2 2 0 0 0 .64-.1l2.43-.82a11.35 11.35 0 0 0 1.31.75l.51 2.52a2 2 0 0 0 2 1.61h4.72a2 2 0 0 0 2-1.61l.51-2.52a11.48 11.48 0 0 0 1.32-.75l2.42.82a2 2 0 0 0 .64.1a2 2 0 0 0 1.73-1l2.28-4a2 2 0 0 0-.41-2.51ZM25.21 24l-3.43-1.16a8.86 8.86 0 0 1-2.71 1.57L18.36 28h-4.72l-.71-3.55a9.36 9.36 0 0 1-2.7-1.57L6.79 24l-2.36-4l2.72-2.4a8.9 8.9 0 0 1 0-3.13L4.43 12l2.36-4l3.43 1.16a8.86 8.86 0 0 1 2.71-1.57L13.64 4h4.72l.71 3.55a9.36 9.36 0 0 1 2.7 1.57L25.21 8l2.36 4l-2.72 2.4a8.9 8.9 0 0 1 0 3.13L27.57 20Z"
269
- /><path
270
- fill="currentColor"
271
- d="M16 22a6 6 0 1 1 6-6a5.94 5.94 0 0 1-6 6Zm0-10a3.91 3.91 0 0 0-4 4a3.91 3.91 0 0 0 4 4a3.91 3.91 0 0 0 4-4a3.91 3.91 0 0 0-4-4Z"
272
- /></svg
273
- >
274
- </button>
275
- </div>
276
- {/if}
277
- {#if !viewCode}
278
- {#each messages as message, i}
279
- <PlaygroundMessage
280
- class="border-b"
281
- {message}
282
- on:delete={() => deleteMessage(i)}
283
- autofocus={conversations.length === 1 && !loading && i === messages.length - 1}
284
- />
285
- {/each}
286
 
287
- <button
288
- class="flex px-6 py-6 hover:bg-gray-50 dark:hover:bg-gray-800/50"
289
- on:click={addMessage}
290
- disabled={loading}
291
- >
292
- <div class="flex items-center gap-2 !p-0 text-sm font-semibold">
293
- <svg
294
- xmlns="http://www.w3.org/2000/svg"
295
- width="1em"
296
- height="1em"
297
- viewBox="0 0 32 32"
298
- class="text-lg"
299
- ><path
300
- fill="currentColor"
301
- d="M16 2A14.172 14.172 0 0 0 2 16a14.172 14.172 0 0 0 14 14a14.172 14.172 0 0 0 14-14A14.172 14.172 0 0 0 16 2Zm8 15h-7v7h-2v-7H8v-2h7V8h2v7h7Z"
302
- /><path fill="none" d="M24 17h-7v7h-2v-7H8v-2h7V8h2v7h7v2z" /></svg
303
- >Add message
304
- </div>
305
- </button>
306
- {:else}
307
- <PlaygroundCode {...currentConversation} {...currentConversation.config} />
308
- {/if}
309
- </div>
310
  {/each}
311
  </div>
312
  <div
 
6
  handleStreamingResponse,
7
  handleNonStreamingResponse
8
  } from '$lib/components/playgroundUtils';
 
9
  import PlaygroundOptions from '$lib/components/GenerationConfig.svelte';
10
  import PlaygroundTokenModal from '$lib/components/HFTokenModal.svelte';
11
  import PlaygroundModelSelector from '$lib/components/ModelSelector.svelte';
12
+ import Conversation from '$lib/components/Conversation.svelte';
13
  import { onDestroy, onMount } from 'svelte';
14
  import { type ModelEntry } from "@huggingface/hub";
15
  import { type ChatCompletionInputMessage } from "@huggingface/tasks";
 
43
  let streamingMessage: ChatCompletionInputMessage | null = null;
44
  let tokens = 0;
45
  let latency = 0;
 
46
  let abortController: AbortController | null = null;
47
  let waitForNonStreaming = true;
48
 
 
141
  streamingMessage.content = content;
142
  currentConversation.messages = [...currentConversation.messages];
143
  conversations = conversations;
 
144
  }
145
  },
146
  abortController
 
160
  if(waitForNonStreaming){
161
  currentConversation.messages = [...currentConversation.messages, newMessage];
162
  conversations = conversations;
 
163
  }
164
  }
165
 
 
174
  loading = false;
175
  streamingMessage = null;
176
  abortController = null;
 
177
  }
178
  }
179
 
 
182
  submit();
183
  }
184
  }
 
 
 
 
 
 
185
  </script>
186
 
187
  <svelte:window on:keydown={onKeydown} />
 
229
  : '*:w-full'} dark:divide-gray-800"
230
  >
231
  {#each conversations as conversation, index}
232
+ <Conversation
233
+ {loading}
234
+ {streamingMessage}
235
+ {conversations}
236
+ {conversation}
237
+ {index}
238
+ {currentConversation}
239
+ {viewCode}
240
+ {messages}
241
+ on:addMessage={addMessage}
242
+ on:deleteMessage={(e) => deleteMessage(e.detail)}
243
+ />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  {/each}
246
  </div>
247
  <div