machineuser commited on
Commit
da081e4
·
1 Parent(s): 31674a2

Sync widgets demo

Browse files
packages/widgets/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte CHANGED
@@ -12,13 +12,14 @@
12
  export let size: "small" | "big" = "small";
13
 
14
  let containerSpanEl: HTMLSpanElement;
 
15
  const typingEffectSpeedMs = 12;
16
  const classNamesInput = "whitespace-pre-wrap inline font-normal text-black dark:text-white";
17
  const classNamesOutput = "whitespace-pre-wrap inline text-blue-600 dark:text-blue-400";
18
 
19
- export async function renderTypingEffect(outputTxt: string): Promise<void> {
20
  const spanEl = document.createElement("span");
21
- spanEl.contentEditable = "true";
22
  spanEl.className = classNamesOutput;
23
  containerSpanEl?.appendChild(spanEl);
24
  await tick();
@@ -29,16 +30,21 @@
29
  }
30
  await tick();
31
  // split on whitespace or any other character to correctly render newlines \n
32
- for (const char of outputTxt.split(/(\s|.)/g)) {
33
- await delay(typingEffectSpeedMs);
34
- spanEl.textContent += char;
35
- moveCaretToEnd();
 
 
 
 
 
 
36
  }
37
  updateInnerTextValue();
38
  }
39
 
40
  function moveCaretToEnd() {
41
- containerSpanEl?.focus();
42
  if (containerSpanEl) {
43
  const range = document.createRange();
44
  range.selectNodeContents(containerSpanEl);
@@ -73,6 +79,11 @@
73
  value = containerSpanEl?.textContent ?? "";
74
  }
75
 
 
 
 
 
 
76
  export function setValue(text: string): void {
77
  containerSpanEl.textContent = text;
78
  updateInnerTextValue();
@@ -87,13 +98,16 @@
87
  ? 'min-h-[42px]'
88
  : 'min-h-[144px]'} inline-block max-h-[500px] whitespace-pre-wrap rounded-lg border border-gray-200 shadow-inner outline-none focus:shadow-inner focus:ring focus:ring-blue-200 dark:bg-gray-925"
89
  role="textbox"
90
- contenteditable={!isLoading && !isDisabled}
91
  style="--placeholder: '{isDisabled ? '' : placeholder}'"
92
  spellcheck="false"
93
  dir="auto"
 
 
94
  bind:this={containerSpanEl}
95
  on:paste|preventDefault={handlePaste}
96
  on:input={updateInnerTextValue}
 
 
97
  />
98
  </svelte:fragment>
99
  </WidgetLabel>
 
12
  export let size: "small" | "big" = "small";
13
 
14
  let containerSpanEl: HTMLSpanElement;
15
+ let isOnFocus = false;
16
  const typingEffectSpeedMs = 12;
17
  const classNamesInput = "whitespace-pre-wrap inline font-normal text-black dark:text-white";
18
  const classNamesOutput = "whitespace-pre-wrap inline text-blue-600 dark:text-blue-400";
19
 
20
+ export async function renderTextOutput(outputTxt: string, typingEffect = true): Promise<void> {
21
  const spanEl = document.createElement("span");
22
+ spanEl.contentEditable = isDisabled ? "false" : "true";
23
  spanEl.className = classNamesOutput;
24
  containerSpanEl?.appendChild(spanEl);
25
  await tick();
 
30
  }
31
  await tick();
32
  // split on whitespace or any other character to correctly render newlines \n
33
+ if (typingEffect) {
34
+ for (const char of outputTxt.split(/(\s|.)/g)) {
35
+ await delay(typingEffectSpeedMs);
36
+ spanEl.textContent += char;
37
+ if (isOnFocus) {
38
+ moveCaretToEnd();
39
+ }
40
+ }
41
+ } else {
42
+ spanEl.textContent = outputTxt;
43
  }
44
  updateInnerTextValue();
45
  }
46
 
47
  function moveCaretToEnd() {
 
48
  if (containerSpanEl) {
49
  const range = document.createRange();
50
  range.selectNodeContents(containerSpanEl);
 
79
  value = containerSpanEl?.textContent ?? "";
80
  }
81
 
82
+ function onFocus() {
83
+ isOnFocus = true;
84
+ moveCaretToEnd();
85
+ }
86
+
87
  export function setValue(text: string): void {
88
  containerSpanEl.textContent = text;
89
  updateInnerTextValue();
 
98
  ? 'min-h-[42px]'
99
  : 'min-h-[144px]'} inline-block max-h-[500px] whitespace-pre-wrap rounded-lg border border-gray-200 shadow-inner outline-none focus:shadow-inner focus:ring focus:ring-blue-200 dark:bg-gray-925"
100
  role="textbox"
 
101
  style="--placeholder: '{isDisabled ? '' : placeholder}'"
102
  spellcheck="false"
103
  dir="auto"
104
+ contenteditable
105
+ class:pointer-events-none={isLoading || isDisabled}
106
  bind:this={containerSpanEl}
107
  on:paste|preventDefault={handlePaste}
108
  on:input={updateInnerTextValue}
109
+ on:focus={onFocus}
110
+ on:blur={() => (isOnFocus = false)}
111
  />
112
  </svelte:fragment>
113
  </WidgetLabel>
packages/widgets/src/lib/components/InferenceWidget/widgets/TextGenerationWidget/TextGenerationWidget.svelte CHANGED
@@ -39,7 +39,7 @@
39
  let outputJson: string;
40
  let text = "";
41
  let warning: string = "";
42
- let renderTypingEffect: (outputTxt: string) => Promise<void>;
43
  let inferenceTimer: any;
44
  let setTextAreaValue: (text: string) => void;
45
  let decodingStrategy: "sampling" | "greedy" = "sampling";
@@ -80,7 +80,12 @@
80
  updateUrl({ text: trimmedValue });
81
  }
82
 
83
- const requestBody = { inputs: trimmedValue, parameters: {} as unknown };
 
 
 
 
 
84
  addInferenceParameters(requestBody, model);
85
 
86
  if (model.id === "bigscience/bloom") {
@@ -133,7 +138,7 @@
133
  if (outputWithoutInput.length === 0) {
134
  warning = "No text was generated";
135
  } else {
136
- await renderTypingEffect(outputWithoutInput);
137
  }
138
  }
139
  } else if (res.status === "loading-model") {
@@ -165,7 +170,7 @@
165
  function renderExampleOutput(output: string) {
166
  // if output doesn't start with space, add space in front of output
167
  const prefix = /^\s/.test(output) ? "" : " ";
168
- renderTypingEffect(prefix + output);
169
  }
170
 
171
  function applyWidgetExample(sample: WidgetExampleTextInput<WidgetExampleOutputText>, opts: ExampleRunOpts = {}) {
@@ -207,7 +212,7 @@
207
  {isLoading}
208
  {isDisabled}
209
  size="big"
210
- bind:renderTypingEffect
211
  />
212
  {#if model.id === "bigscience/bloom"}
213
  <WidgetBloomDecoding bind:decodingStrategy />
 
39
  let outputJson: string;
40
  let text = "";
41
  let warning: string = "";
42
+ let renderTextOutput: (outputTxt: string, typingEffect?: boolean) => Promise<void>;
43
  let inferenceTimer: any;
44
  let setTextAreaValue: (text: string) => void;
45
  let decodingStrategy: "sampling" | "greedy" = "sampling";
 
80
  updateUrl({ text: trimmedValue });
81
  }
82
 
83
+ const parameters = {} as any;
84
+ if (model?.pipeline_tag === "text-generation") {
85
+ // todo: until streaming is supported https://github.com/huggingface/huggingface.js/issues/410
86
+ parameters["max_new_tokens"] = 20;
87
+ }
88
+ const requestBody = { inputs: trimmedValue, parameters };
89
  addInferenceParameters(requestBody, model);
90
 
91
  if (model.id === "bigscience/bloom") {
 
138
  if (outputWithoutInput.length === 0) {
139
  warning = "No text was generated";
140
  } else {
141
+ await renderTextOutput(outputWithoutInput);
142
  }
143
  }
144
  } else if (res.status === "loading-model") {
 
170
  function renderExampleOutput(output: string) {
171
  // if output doesn't start with space, add space in front of output
172
  const prefix = /^\s/.test(output) ? "" : " ";
173
+ renderTextOutput(prefix + output, false);
174
  }
175
 
176
  function applyWidgetExample(sample: WidgetExampleTextInput<WidgetExampleOutputText>, opts: ExampleRunOpts = {}) {
 
212
  {isLoading}
213
  {isDisabled}
214
  size="big"
215
+ bind:renderTextOutput
216
  />
217
  {#if model.id === "bigscience/bloom"}
218
  <WidgetBloomDecoding bind:decodingStrategy />