jbilcke-hf HF staff commited on
Commit
b93a813
β€’
1 Parent(s): 2ccf6f7

add support for Docker

Browse files
README.md CHANGED
@@ -24,7 +24,7 @@ http://localhost:7860/?prompt=A%20simple%20page%20to%20compute%20the%20BMI%20(us
24
  ```bash
25
  nvm use
26
  npm i
27
- HF_API_TOKEN=******* npm run start
28
  ```
29
 
30
  ## Building and running with Docker
 
24
  ```bash
25
  nvm use
26
  npm i
27
+ npm run start
28
  ```
29
 
30
  ## Building and running with Docker
public/index.html CHANGED
@@ -53,7 +53,7 @@
53
  </p>
54
  <button
55
  class="btn disabled:text-stone-400"
56
- @click="open = true, prompt = promptDraft, state = state === 'stopped' ? 'loading' : 'stopped', state === 'streaming' ? stopGeneration() : true"
57
  :class="promptDraft.length < minPromptSize ? 'btn-neutral' : state === 'stopped' ? 'btn-accent' : 'btn-warning'"
58
  :disabled="promptDraft.length < minPromptSize"
59
  >
@@ -141,16 +141,23 @@
141
  }
142
 
143
  function app() {
 
 
 
144
  return {
145
  open: false,
146
  promptDraft:
147
  new URLSearchParams(window.location.search).get("prompt") || '',
148
  prompt: "",
 
149
  size: 0,
150
  minPromptSize: 16, // if you change this, you will need to also change in src/index.mts
151
  timeoutInSec: 15, // time before we determine something went wrong
152
  state: "stopped",
153
  lastTokenAt: +new Date(),
 
 
 
154
  init() {
155
  setInterval(() => {
156
  if (this.state === "stopped") {
 
53
  </p>
54
  <button
55
  class="btn disabled:text-stone-400"
56
+ @click="open = true, saveToken(token), prompt = promptDraft, state = state === 'stopped' ? 'loading' : 'stopped', state === 'streaming' ? stopGeneration() : true"
57
  :class="promptDraft.length < minPromptSize ? 'btn-neutral' : state === 'stopped' ? 'btn-accent' : 'btn-warning'"
58
  :disabled="promptDraft.length < minPromptSize"
59
  >
 
141
  }
142
 
143
  function app() {
144
+
145
+ const storageKey = "SPACE_FACTORY_ACCESS_TOKEN"
146
+
147
  return {
148
  open: false,
149
  promptDraft:
150
  new URLSearchParams(window.location.search).get("prompt") || '',
151
  prompt: "",
152
+ token: localStorage.getItem(storageKey) || "",
153
  size: 0,
154
  minPromptSize: 16, // if you change this, you will need to also change in src/index.mts
155
  timeoutInSec: 15, // time before we determine something went wrong
156
  state: "stopped",
157
  lastTokenAt: +new Date(),
158
+ saveToken(token) {
159
+ localStorage.setItem(storageKey, token)
160
+ },
161
  init() {
162
  setInterval(() => {
163
  if (this.state === "stopped") {
public/placeholder.html CHANGED
@@ -8,7 +8,7 @@
8
  <div class="hero min-h-screen bg-stone-100">
9
  <div class="hero-content text-center">
10
  <div class="flex flex-col max-w-xl space-y-6">
11
- <h1 class="font-bold text-stone-600 mb-4">Nothing to show here (note: minimum prompt size is 16 characters)</h1>
12
  </div>
13
  </div>
14
  </div>
 
8
  <div class="hero min-h-screen bg-stone-100">
9
  <div class="hero-content text-center">
10
  <div class="flex flex-col max-w-xl space-y-6">
11
+ <h1 class="font-bold text-stone-600 mb-4">Waiting for content..</h1>
12
  </div>
13
  </div>
14
  </div>
src/createSpace.mts CHANGED
@@ -35,7 +35,9 @@ export const createSpace = async (files: RepoFile[], token: string) => {
35
  credentials,
36
  license: "mit",
37
  sdk:
38
- files.some(file => file.path.includes("app.py"))
 
 
39
  ? "streamlit"
40
  : "static" // "streamlit" | "gradio" | "docker" | "static";
41
  });
 
35
  credentials,
36
  license: "mit",
37
  sdk:
38
+ files.some(file => file.path.includes("Dockerfile"))
39
+ ? "docker"
40
+ : files.some(file => file.path.includes("app.py"))
41
  ? "streamlit"
42
  : "static" // "streamlit" | "gradio" | "docker" | "static";
43
  });
src/generateFiles.mts CHANGED
@@ -4,7 +4,9 @@ import { createLlamaPrompt } from './createLlamaPrompt.mts'
4
  import { parseTutorial } from './parseTutorial.mts'
5
  import { getPythonApp} from './getPythonApp.mts'
6
  import { getWebApp } from './getWebApp.mts'
 
7
  import { isPythonAppPrompt } from './isPythonAppPrompt.mts'
 
8
 
9
  export const generateFiles = async (prompt: string, token: string) => {
10
  if (`${prompt}`.length < 2) {
@@ -14,6 +16,8 @@ export const generateFiles = async (prompt: string, token: string) => {
14
  const { prefix, instructions } =
15
  isPythonAppPrompt(prompt)
16
  ? getPythonApp(prompt)
 
 
17
  : getWebApp(prompt)
18
 
19
  const inputs = createLlamaPrompt(instructions) + "\nSure! Here are the source files:\n" + prefix
@@ -60,7 +64,7 @@ let tutorial = prefix
60
 
61
  console.log("analyzing the generated instructions..")
62
  const files = parseTutorial(tutorial).map(({ filename, content }) => ({
63
- path: `${filename || ""}`.trim(),
64
  content: `${content || ""}`
65
  } as RepoFile))
66
  .filter(res => res.path.length && res.content.length)
 
4
  import { parseTutorial } from './parseTutorial.mts'
5
  import { getPythonApp} from './getPythonApp.mts'
6
  import { getWebApp } from './getWebApp.mts'
7
+ import { getReactApp } from './getReactApp.mts'
8
  import { isPythonAppPrompt } from './isPythonAppPrompt.mts'
9
+ import { isReactAppPrompt } from './isReactAppPrompt.mts'
10
 
11
  export const generateFiles = async (prompt: string, token: string) => {
12
  if (`${prompt}`.length < 2) {
 
16
  const { prefix, instructions } =
17
  isPythonAppPrompt(prompt)
18
  ? getPythonApp(prompt)
19
+ : isReactAppPrompt(prompt)
20
+ ? getReactApp(prompt)
21
  : getWebApp(prompt)
22
 
23
  const inputs = createLlamaPrompt(instructions) + "\nSure! Here are the source files:\n" + prefix
 
64
 
65
  console.log("analyzing the generated instructions..")
66
  const files = parseTutorial(tutorial).map(({ filename, content }) => ({
67
+ path: `${filename || ""}`.trim().replace(" ", ""),
68
  content: `${content || ""}`
69
  } as RepoFile))
70
  .filter(res => res.path.length && res.content.length)
src/getReactApp.mts ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { alpine } from "./alpine.mts"
2
+ import { daisy } from "./daisy.mts"
3
+
4
+ export function getReactApp(prompt: string) {
5
+ const prefix = `# In src/main.tsx:\n\`\`\``
6
+ const instructions = [
7
+ {
8
+ role: "system",
9
+ content: [
10
+ `You are a TypeScript developer, expert at crafting NextJS and React applications, using TailwindCSS utility classes.`,
11
+ ].filter(item => item).join("\n")
12
+ },
13
+ {
14
+ role: "user",
15
+ content: `Please write, file by file, the source code for a Next 12 application.
16
+
17
+ The app should be buildable when we call:
18
+
19
+ \`\`\`
20
+ npm install
21
+ npm run start
22
+ \`\`\`
23
+
24
+ And installable using a Dockerfile. Here is an example:
25
+
26
+ \`\`\`
27
+ FROM node:18
28
+ RUN useradd -o -u 1000 user
29
+ USER user
30
+ ENV HOME=/home/user \
31
+ PATH=/home/user/.local/bin:$PATH
32
+ WORKDIR $HOME/app
33
+ COPY --chown=user package*.json $HOME/app
34
+ RUN npm install
35
+ COPY --chown=user . $HOME/app
36
+ EXPOSE 7860
37
+ CMD [ "npm", "run", "start" ]
38
+ \`\`\`
39
+
40
+ Don't forget to write a valid package.json file!
41
+
42
+ Don't forget to write a README.md with the following header:
43
+ \`\`\`
44
+ ---
45
+ license: apache-2.0
46
+ title: <APPNAME>
47
+ sdk: docker
48
+ emoji: πŸ‘¨β€πŸ’»
49
+ colorFrom: yellow
50
+ colorTo: green
51
+ ---
52
+ \`\`\`
53
+
54
+ Of course, you MUST replace <APPNAME> with a good app name!
55
+
56
+ The app is about: ${prompt}`,
57
+ }
58
+ ]
59
+
60
+ return { prefix, instructions }
61
+ }
src/getWebApp.mts CHANGED
@@ -1,30 +1,37 @@
1
  import { alpine } from "./alpine.mts"
 
2
 
3
  export function getWebApp(prompt: string) {
4
- const prefix = "# In index.html:\n```"
 
5
 
6
  const instructions = [
7
  {
8
  role: "system",
9
  content: [
10
  `You are a JavaScript developer, expert at crafting applications using AlpineJS, DaisyUI and Tailwind.`,
11
- `Here is an extract from the alpine documentation:`,
12
- alpine
 
 
13
  ].filter(item => item).join("\n")
14
  },
15
  {
16
  role: "user",
17
  content: `Please write, file by file, the source code for a HTML JS app.
18
 
19
- Remember, these library importats are mandatory:
20
  - AlpineJS (use "https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js")
21
  - DaisyUI (use "https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css")
22
  - Tailwind (use "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio")
23
-
24
- But you can optionally also load those:
25
  - Three.js (use "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js")
26
 
27
- The rest should be written using vanilla javascript
 
 
 
 
 
28
 
29
  Don't forget to write a README.md with the following header:
30
  \`\`\`
 
1
  import { alpine } from "./alpine.mts"
2
+ import { daisy } from "./daisy.mts"
3
 
4
  export function getWebApp(prompt: string) {
5
+ const prefix = `# In index.html:\n\`\`\`
6
+ <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><script defer src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js"></script><script type="module" src="main.js"></script><title>`
7
 
8
  const instructions = [
9
  {
10
  role: "system",
11
  content: [
12
  `You are a JavaScript developer, expert at crafting applications using AlpineJS, DaisyUI and Tailwind.`,
13
+ `Here is an extract from the AlpineJS documentation:`,
14
+ alpine,
15
+ `Here is an extract from the DaisyUI documentation:`,
16
+ daisy
17
  ].filter(item => item).join("\n")
18
  },
19
  {
20
  role: "user",
21
  content: `Please write, file by file, the source code for a HTML JS app.
22
 
23
+ Here are some recommended librairies:
24
  - AlpineJS (use "https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js")
25
  - DaisyUI (use "https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css")
26
  - Tailwind (use "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio")
 
 
27
  - Three.js (use "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js")
28
 
29
+ Those library will be globally exposed thanks to the <script> dependencies, so you do not need to write "import ... from ..".
30
+
31
+ Some remarks:
32
+ - DO NOT USE VUE.JS
33
+
34
+ Rember, you need to write the index.html but also the app.js and/or the style.css files!
35
 
36
  Don't forget to write a README.md with the following header:
37
  \`\`\`
src/isReactAppPrompt.mts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ export function isReactAppPrompt(prompt: string) {
2
+ const lowerCasePrompt = prompt.toLocaleLowerCase()
3
+ return lowerCasePrompt.includes("react")
4
+ || lowerCasePrompt.includes("create react app")
5
+ || lowerCasePrompt.includes("reactjs")
6
+ || lowerCasePrompt.includes("next app")
7
+ || lowerCasePrompt.includes("nextjs app")
8
+ || lowerCasePrompt.includes("nextjs")
9
+ }