Spaces:
Runtime error
Runtime error
Commit
•
4ae6e3c
1
Parent(s):
5443231
add support for images
Browse files- src/index.mts +43 -23
src/index.mts
CHANGED
@@ -1,7 +1,12 @@
|
|
1 |
-
import
|
|
|
|
|
|
|
2 |
import { HfInference } from '@huggingface/inference'
|
3 |
|
4 |
-
import { daisy } from
|
|
|
|
|
5 |
|
6 |
const hfi = new HfInference(process.env.HF_API_TOKEN)
|
7 |
const hf = hfi.endpoint(process.env.HF_ENDPOINT_URL)
|
@@ -12,9 +17,9 @@ const port = 7860
|
|
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(
|
16 |
|
17 |
-
app.use(express.static(
|
18 |
|
19 |
const pending: {
|
20 |
total: number;
|
@@ -33,7 +38,7 @@ const endRequest = (id: string, reason: string) => {
|
|
33 |
console.log(`request ${id} ended (${reason})`)
|
34 |
}
|
35 |
|
36 |
-
app.get(
|
37 |
res.write(JSON.stringify({
|
38 |
nbTotal: pending.total,
|
39 |
nbPending: pending.queue.length,
|
@@ -42,16 +47,7 @@ app.get("/debug", (req, res) => {
|
|
42 |
res.end()
|
43 |
})
|
44 |
|
45 |
-
app.get(
|
46 |
-
|
47 |
-
const model = `${req.query.model || 'OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5'}`
|
48 |
-
|
49 |
-
console.log('model:', model)
|
50 |
-
|
51 |
-
const endpoint = `${req.query.endpoint || ''}`
|
52 |
-
|
53 |
-
console.log('endpoint:', endpoint)
|
54 |
-
|
55 |
if (`${req.query.prompt}`.length < minPromptSize) {
|
56 |
res.write(`prompt too short, please enter at least ${minPromptSize} characters`)
|
57 |
res.end()
|
@@ -63,15 +59,13 @@ app.get("/app", async (req, res) => {
|
|
63 |
|
64 |
pending.queue.push(id)
|
65 |
|
66 |
-
const prefix = `<html><head><link href=
|
67 |
res.write(prefix)
|
68 |
|
69 |
-
req.on(
|
70 |
-
|
71 |
-
endRequest(id, "browser asked to end the connection")
|
72 |
})
|
73 |
|
74 |
-
// for testing we kill after some delay
|
75 |
setTimeout(() => {
|
76 |
endRequest(id, `timed out after ${timeoutInSec}s`)
|
77 |
}, timeoutInSec * 1000)
|
@@ -84,11 +78,13 @@ ${daisy}
|
|
84 |
# Guidelines
|
85 |
- Never repeat the instruction, instead directly write the final code
|
86 |
- Use a color scheme consistent with the brief and theme
|
|
|
|
|
87 |
- You must use Tailwind CSS and Daisy UI for the CSS classes, vanilla JS and Alpine.js for the JS.
|
88 |
-
- All the JS code will be written directly inside the page, using <script type=
|
89 |
- You MUST use English, not Latin! (I repeat: do NOT write lorem ipsum!)
|
90 |
- No need to write code comments, so please make the code compact (short function names etc)
|
91 |
-
- Use a central layout by wrapping everything in a \`<div class=
|
92 |
# HTML output
|
93 |
<html><head></head><body`
|
94 |
|
@@ -108,7 +104,6 @@ ${daisy}
|
|
108 |
break
|
109 |
}
|
110 |
if (result.includes('<|end|>') || result.includes('<|assistant|>')) {
|
111 |
-
// it ended, but we probably don't have a valid HTML
|
112 |
break
|
113 |
}
|
114 |
}
|
@@ -127,5 +122,30 @@ ${daisy}
|
|
127 |
|
128 |
})
|
129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
app.listen(port, () => { console.log(`Open http://localhost:${port}`) })
|
131 |
|
|
|
1 |
+
import { pipeline } from 'stream'
|
2 |
+
import { promisify } from 'util'
|
3 |
+
|
4 |
+
import express from 'express'
|
5 |
import { HfInference } from '@huggingface/inference'
|
6 |
|
7 |
+
import { daisy } from './daisy.mts'
|
8 |
+
|
9 |
+
const pipe = promisify(pipeline)
|
10 |
|
11 |
const hfi = new HfInference(process.env.HF_API_TOKEN)
|
12 |
const hf = hfi.endpoint(process.env.HF_ENDPOINT_URL)
|
|
|
17 |
const minPromptSize = 16 // if you change this, you will need to also change in public/index.html
|
18 |
const timeoutInSec = 30 * 60
|
19 |
|
20 |
+
console.log('timeout set to 30 minutes')
|
21 |
|
22 |
+
app.use(express.static('public'))
|
23 |
|
24 |
const pending: {
|
25 |
total: number;
|
|
|
38 |
console.log(`request ${id} ended (${reason})`)
|
39 |
}
|
40 |
|
41 |
+
app.get('/debug', (req, res) => {
|
42 |
res.write(JSON.stringify({
|
43 |
nbTotal: pending.total,
|
44 |
nbPending: pending.queue.length,
|
|
|
47 |
res.end()
|
48 |
})
|
49 |
|
50 |
+
app.get('/app', async (req, res) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
if (`${req.query.prompt}`.length < minPromptSize) {
|
52 |
res.write(`prompt too short, please enter at least ${minPromptSize} characters`)
|
53 |
res.end()
|
|
|
59 |
|
60 |
pending.queue.push(id)
|
61 |
|
62 |
+
const prefix = `<html><head><link href='https://cdn.jsdelivr.net/npm/daisyui@3.1.6/dist/full.css' rel='stylesheet' type='text/css' /><script defer src='https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js'></script><script src='https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp'></script><title>Generated content</title><body`
|
63 |
res.write(prefix)
|
64 |
|
65 |
+
req.on('close', function() {
|
66 |
+
endRequest(id, 'browser asked to end the connection')
|
|
|
67 |
})
|
68 |
|
|
|
69 |
setTimeout(() => {
|
70 |
endRequest(id, `timed out after ${timeoutInSec}s`)
|
71 |
}, timeoutInSec * 1000)
|
|
|
78 |
# Guidelines
|
79 |
- Never repeat the instruction, instead directly write the final code
|
80 |
- Use a color scheme consistent with the brief and theme
|
81 |
+
- To generate all your images, import from from this route: "/image?prompt=<description or caption of an image, photo or illustration>"
|
82 |
+
- please be descriptive for the prompt, eg describe the scene in a few words (textures, characters, materials, camera type etc)
|
83 |
- You must use Tailwind CSS and Daisy UI for the CSS classes, vanilla JS and Alpine.js for the JS.
|
84 |
+
- All the JS code will be written directly inside the page, using <script type='text/javascript'>...</script>
|
85 |
- You MUST use English, not Latin! (I repeat: do NOT write lorem ipsum!)
|
86 |
- No need to write code comments, so please make the code compact (short function names etc)
|
87 |
+
- Use a central layout by wrapping everything in a \`<div class='flex flex-col items-center'>\`
|
88 |
# HTML output
|
89 |
<html><head></head><body`
|
90 |
|
|
|
104 |
break
|
105 |
}
|
106 |
if (result.includes('<|end|>') || result.includes('<|assistant|>')) {
|
|
|
107 |
break
|
108 |
}
|
109 |
}
|
|
|
122 |
|
123 |
})
|
124 |
|
125 |
+
app.get('/image', async (req, res) => {
|
126 |
+
try {
|
127 |
+
const blob = await hfi.textToImage({
|
128 |
+
inputs: [
|
129 |
+
`${req.query.prompt || 'generic placeholder'}`,
|
130 |
+
'award winning',
|
131 |
+
'high resolution',
|
132 |
+
'beautiful',
|
133 |
+
'[trending on artstation]'
|
134 |
+
].join(','),
|
135 |
+
model: 'stabilityai/stable-diffusion-2',
|
136 |
+
parameters: {
|
137 |
+
negative_prompt: 'blurry, cropped, low quality, ugly',
|
138 |
+
}
|
139 |
+
})
|
140 |
+
const buffer = Buffer.from(await blob.arrayBuffer())
|
141 |
+
res.setHeader('Content-Type', blob.type)
|
142 |
+
res.setHeader('Content-Length', buffer.length)
|
143 |
+
res.end(buffer)
|
144 |
+
} catch (err) {
|
145 |
+
console.error(`Error when generating the image: ${err.message}`);
|
146 |
+
res.status(500).json({ error: 'An error occurred when trying to generate the image' });
|
147 |
+
}
|
148 |
+
})
|
149 |
+
|
150 |
app.listen(port, () => { console.log(`Open http://localhost:${port}`) })
|
151 |
|