jbilcke-hf HF staff commited on
Commit
ef08385
1 Parent(s): b89e77c

big improvement to the quality

Browse files
Files changed (3) hide show
  1. public/index.html +38 -20
  2. src/daisy.mts +4 -5
  3. src/index.mts +23 -20
public/index.html CHANGED
@@ -42,11 +42,11 @@
42
  Examples:
43
 
44
  <a href="/?prompt=a simple page to compute the BMI using metric units" class="text-bold underline">compute my BMI</a>,
45
- <a href="/?prompt=app listing various animals from the savanna, with their photos" class="text-bold underline">photos of animals</a>
46
  </p>
47
  <button
48
  class="btn disabled:text-stone-400"
49
- @click="open = true, prompt = promptDraft, state = state === 'stopped' ? 'loading' : 'stopped'"
50
  :class="promptDraft.length < minPromptSize ? 'btn-neutral' : state === 'stopped' ? 'btn-accent' : 'btn-warning'"
51
  :disabled="promptDraft.length < minPromptSize"
52
  >
@@ -61,30 +61,39 @@
61
  WizardCoder-15B-1.0
62
  </a>
63
  </p>
64
- <p>Powered by 🤗 <a href="https://huggingface.co/inference-endpoints" class="underline" target="_blank">Inference Endpoints</a>.</p>
65
  <p class="py-3 text-stone-700" x-show="state === 'loading'">
66
  Waiting for the stream to begin (might take a few minutes)..
67
  </p>
68
  <p class="py-3 text-stone-700" x-show="state === 'streaming'">
69
- Streamed <span x-text="humanFileSize(size, true, 2)"></span> so far..<br />Note: this version generates up
70
- to 1200 tokens.
71
  </p>
72
  </div>
73
  </div>
74
  </div>
75
  </div>
76
  <div
77
- class="flex transition-[width] delay-150 ease-in-out md:h-screen"
78
  :class="open ? 'w-full md:w-4/6' : 'w-full md:w-0'"
79
  >
80
  <iframe
81
  id="iframe"
82
- class="border-none w-full md:min-h-screen p-4 md:p-8"
83
  :src="!open
84
  ? '/placeholder.html'
85
  : `/app?prompt=${encodeURIComponent(prompt)}`
86
  "
87
  ></iframe>
 
 
 
 
 
 
 
 
 
88
  </div>
89
  </div>
90
  <script>
@@ -118,6 +127,11 @@
118
 
119
  return bytes.toFixed(dp) + " " + units[u];
120
  }
 
 
 
 
 
121
  function app() {
122
  return {
123
  open: false,
@@ -126,7 +140,7 @@
126
  prompt: "",
127
  size: 0,
128
  minPromptSize: 16, // if you change this, you will need to also change in src/index.mts
129
- timeoutInSec: 10, // time before we determine something went wrong
130
  state: "stopped",
131
  lastTokenAt: +new Date(),
132
  init() {
@@ -143,20 +157,24 @@
143
  this.state = "loading";
144
  return;
145
  }
146
- this.size = new Blob([html]).size;
147
  this.state = "streaming";
148
- const lastTokenAt = +new Date();
149
- const elapsed = (lastTokenAt - this.lastTokenAt) / 1000;
150
- this.lastTokenAt = lastTokenAt;
151
- if (elapsed > this.timeoutInSec) {
152
- console.log(`Something went wrong, it took more than ${this.timeoutInSec} seconds to generate a token.`);
153
- this.state = "stopped";
154
- return;
155
  }
156
- if (html.includes("</html>")) {
157
- // console.log('We reached the natural end of the stream, it seems.')
158
- // this.state === 'stopped'
159
- return;
 
 
 
 
160
  }
161
  }, 100);
162
  },
 
42
  Examples:
43
 
44
  <a href="/?prompt=a simple page to compute the BMI using metric units" class="text-bold underline">compute my BMI</a>,
45
+ <a href="/?prompt=app listing various types of llamas with their photos" class="text-bold underline">photos of llamas</a>
46
  </p>
47
  <button
48
  class="btn disabled:text-stone-400"
49
+ @click="open = true, prompt = promptDraft, state = state === 'stopped' ? 'loading' : 'stopped', stopGeneration()"
50
  :class="promptDraft.length < minPromptSize ? 'btn-neutral' : state === 'stopped' ? 'btn-accent' : 'btn-warning'"
51
  :disabled="promptDraft.length < minPromptSize"
52
  >
 
61
  WizardCoder-15B-1.0
62
  </a>
63
  </p>
64
+ <p>Powered by 🤗 <a href="https://huggingface.co/inference-endpoints" class="underline" target="_blank">Inference Endpoints</a></p>
65
  <p class="py-3 text-stone-700" x-show="state === 'loading'">
66
  Waiting for the stream to begin (might take a few minutes)..
67
  </p>
68
  <p class="py-3 text-stone-700" x-show="state === 'streaming'">
69
+ Content size: <span x-text="humanFileSize(size, true, 2)"></span><br />Note: this version generates up
70
+ to 1150 tokens.
71
  </p>
72
  </div>
73
  </div>
74
  </div>
75
  </div>
76
  <div
77
+ class="flex flex-col transition-[width] delay-150 ease-in-out md:h-screen"
78
  :class="open ? 'w-full md:w-4/6' : 'w-full md:w-0'"
79
  >
80
  <iframe
81
  id="iframe"
82
+ class="border-none w-full md:min-h-screen"
83
  :src="!open
84
  ? '/placeholder.html'
85
  : `/app?prompt=${encodeURIComponent(prompt)}`
86
  "
87
  ></iframe>
88
+
89
+ <div
90
+ x-show="state !== 'stopped'"
91
+ class="flex w-full -mt-20 items-end justify-center pointer-events-none">
92
+ <div class="flex flex-row py-3 px-8 text-center bg-stone-200 text-stone-600 rounded-md shadow-md">
93
+ <div class="animate-bounce duration-150 mr-1">🤖</div>
94
+ <div>Generating your app..</div>
95
+ </div>
96
+ </div>
97
  </div>
98
  </div>
99
  <script>
 
127
 
128
  return bytes.toFixed(dp) + " " + units[u];
129
  }
130
+
131
+ function stopGeneration() {
132
+ document?.getElementById("iframe")?.stop();
133
+ }
134
+
135
  function app() {
136
  return {
137
  open: false,
 
140
  prompt: "",
141
  size: 0,
142
  minPromptSize: 16, // if you change this, you will need to also change in src/index.mts
143
+ timeoutInSec: 5, // time before we determine something went wrong
144
  state: "stopped",
145
  lastTokenAt: +new Date(),
146
  init() {
 
157
  this.state = "loading";
158
  return;
159
  }
160
+
161
  this.state = "streaming";
162
+
163
+ const now = +new Date();
164
+ const newSize = new Blob([html]).size;
165
+ const hasChanged = newSize !== this.size;
166
+
167
+ if (hasChanged) {
168
+ this.lastTokenAt = now;
169
  }
170
+
171
+ this.size = newSize;
172
+
173
+ const timeSinceLastUpdate = (now - this.lastTokenAt) / 1000;
174
+
175
+ if (timeSinceLastUpdate > this.timeoutInSec) {
176
+ console.log(`no changed detected for the past ${this.timeoutInSec} seconds -> considering we're done`);
177
+ this.state = "stopped";
178
  }
179
  }, 100);
180
  },
src/daisy.mts CHANGED
@@ -1,8 +1,7 @@
1
- export const daisy = `## DaisyUI docs
2
- ### To create a nice layout, wrap each article in:
3
  <article class="prose"></article>
4
- ### Use appropriate CSS classes
5
  <button class="btn ..">
6
  <table class="table ..">
7
- <footer class="footer ..">
8
- `
 
1
+ export const daisy = `# DaisyUI docs
2
+ ## To create a nice layout, wrap each article in:
3
  <article class="prose"></article>
4
+ ## Use appropriate CSS classes
5
  <button class="btn ..">
6
  <table class="table ..">
7
+ <footer class="footer ..">`
 
src/index.mts CHANGED
@@ -10,7 +10,7 @@ const app = express()
10
  const port = 7860
11
 
12
  const minPromptSize = 16 // if you change this, you will need to also change in public/index.html
13
- const timeoutInSec = 30 * 60
14
 
15
  console.log('timeout set to 30 minutes')
16
 
@@ -54,7 +54,7 @@ app.get('/app', async (req, res) => {
54
 
55
  pending.queue.push(id)
56
 
57
- const prefix = `<html><head><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css" rel="stylesheet" type="text/css" /><script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script><script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script><title>Generated content</title><body>`
58
  res.write(prefix)
59
 
60
  req.on('close', function() {
@@ -67,23 +67,22 @@ app.get('/app', async (req, res) => {
67
 
68
 
69
  const finalPrompt = `# Task
70
- Generate the following: ${req.query.prompt}
71
- # API Doc
72
  ${daisy}
73
- # Guidelines
74
- - Never repeat the instructions, instead write the final code
75
- - To generate images use the /image endpoint: <img src="/image?prompt=caption of the photo" />
76
- - Only generate a few images, and be descriptive for photo caption, use at last 10 words.
77
- - You must use TailwindCSS utility classes (Tailwind is already injected in the page).
78
- - Write application logic inside a JS <script></script> tag
79
- - This is not a demo app, so you MUST use English, no Latin! Write in English!
80
- - Use a central layout to wrap everything in a <div class='flex flex-col items-center'>
81
- # Output
82
  <html>
83
  <head>
84
- <title>Site</title>
85
  </head>
86
- <body>`
87
 
88
  try {
89
  let result = ''
@@ -91,7 +90,9 @@ ${daisy}
91
  inputs: finalPrompt,
92
  parameters: {
93
  do_sample: true,
94
- max_new_tokens: 1200,
 
 
95
  return_full_text: false,
96
  }
97
  })) {
@@ -127,15 +128,17 @@ app.get('/image', async (req, res) => {
127
  try {
128
  const blob = await hfi.textToImage({
129
  inputs: [
130
- `${req.query.prompt || 'generic placeholder'}`,
131
  'award winning',
132
  'high resolution',
 
 
133
  'beautiful',
134
  '[trending on artstation]'
135
- ].join(','),
136
- model: 'stabilityai/stable-diffusion-2',
137
  parameters: {
138
- negative_prompt: 'blurry, cropped, low quality, ugly',
139
  }
140
  })
141
  const buffer = Buffer.from(await blob.arrayBuffer())
 
10
  const port = 7860
11
 
12
  const minPromptSize = 16 // if you change this, you will need to also change in public/index.html
13
+ const timeoutInSec = 10 * 60
14
 
15
  console.log('timeout set to 30 minutes')
16
 
 
54
 
55
  pending.queue.push(id)
56
 
57
+ const prefix = `<html><head><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css" rel="stylesheet" type="text/css" /><script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script><script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script><title>Generated content</title><body class="p-4 md:p-8">`
58
  res.write(prefix)
59
 
60
  req.on('close', function() {
 
67
 
68
 
69
  const finalPrompt = `# Task
70
+ Generate ${req.query.prompt}
 
71
  ${daisy}
72
+ # Orders
73
+ Never repeat those instructions, instead write the final code!
74
+ To generate images from captions call the /image API: <img src="/image?caption=photo of something in some place" />!
75
+ Only generate a few images and use descriptive photo captions with at least 10 words!
76
+ You must use TailwindCSS utility classes (Tailwind is already injected in the page)!
77
+ Write application logic inside a JS <script></script> tag!
78
+ This is not a demo app, so you MUST use English, no Latin! Write in English!
79
+ Use a central layout to wrap everything in a <div class='flex flex-col items-center'>
80
+ # Out
81
  <html>
82
  <head>
83
+ <title>App</title>
84
  </head>
85
+ <body class="p-4 md:p-8">`
86
 
87
  try {
88
  let result = ''
 
90
  inputs: finalPrompt,
91
  parameters: {
92
  do_sample: true,
93
+
94
+ // hard limit for max_new_tokens is 1512
95
+ max_new_tokens: 1150,
96
  return_full_text: false,
97
  }
98
  })) {
 
128
  try {
129
  const blob = await hfi.textToImage({
130
  inputs: [
131
+ `${req.query.caption || 'generic placeholder'}`,
132
  'award winning',
133
  'high resolution',
134
+ 'photo realistic',
135
+ 'intricate details',
136
  'beautiful',
137
  '[trending on artstation]'
138
+ ].join(', '),
139
+ model: 'stabilityai/stable-diffusion-2-1',
140
  parameters: {
141
+ negative_prompt: 'blurry, artificial, cropped, low quality, ugly',
142
  }
143
  })
144
  const buffer = Buffer.from(await blob.arrayBuffer())