gstaff commited on
Commit
bc91045
β€’
1 Parent(s): a0bda8f

Add initial app files.

Browse files
Files changed (4) hide show
  1. README.md +16 -5
  2. app.py +190 -0
  3. gradio-lite-playground.html +28 -0
  4. requirements.txt +1 -0
README.md CHANGED
@@ -1,12 +1,23 @@
1
  ---
2
- title: KiteWind
3
- emoji: πŸƒ
4
- colorFrom: purple
5
- colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 3.50.2
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: KiteWind Chat-assisted Web App Creator
3
+ emoji: πŸͺπŸƒ
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
  sdk_version: 3.50.2
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # KiteWind πŸͺπŸƒ
13
+ <h4>Chat-assisted web app creator by <a href="https://huggingface.co/gstaff">@gstaff</a></h4>
14
+
15
+ ## Features
16
+ - Run your app in the browser with gradio-lite!
17
+ - Customize using voice requests and chat-assisted development!
18
+ - Export as a standalone HTML file or copy a snippet to use in another webpage!
19
+
20
+ ## Current Limitations
21
+ - Only gradio-lite apps using the python standard libraries and gradio are supported
22
+ - The chat hasn't been tuned on gradio library data; it may make mistakes
23
+ - The app needs to fully reload each time it is changed
app.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import gradio as gr
4
+ import re
5
+ import whisper
6
+ import requests
7
+
8
+ HF_TOKEN = os.getenv("HF_TOKEN")
9
+
10
+ API_URL = "https://api-inference.huggingface.co/models/HuggingFaceH4/zephyr-7b-beta"
11
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
12
+
13
+ code_pattern = r'```python\n(.*?)```'
14
+
15
+ starting_app_code = """import gradio as gr
16
+
17
+ def greet(name):
18
+ return "Hello " + name + "!"
19
+
20
+ with gr.Blocks(theme="monochrome") as demo:
21
+ name = gr.Textbox(label="Name", value="World")
22
+ output = gr.Textbox(label="Output Box")
23
+ greet_btn = gr.Button("Greet")
24
+ greet_btn.click(fn=greet, inputs=name, outputs=output)
25
+ name.submit(fn=greet, inputs=name, outputs=output)
26
+
27
+ if __name__ == "__main__":
28
+ demo.css = "footer {visibility: hidden}"
29
+ demo.launch()
30
+ """
31
+
32
+ html_template = Path('gradio-lite-playground.html').read_text()
33
+ pattern = r"# APP CODE START(.*?)# APP CODE END"
34
+
35
+ load_js = f"""() => {{
36
+ const htmlString = '<iframe class="my-frame" width="100%" height="512px" src="about:blank"></iframe>';
37
+ const parser = new DOMParser();
38
+ const doc = parser.parseFromString(htmlString, 'text/html');
39
+ const iframe = doc.querySelector('.my-frame');
40
+ const div = document.getElementById('demoDiv');
41
+ div.appendChild(iframe);
42
+
43
+ const frame = document.querySelector('.my-frame');
44
+ frame.contentWindow.document.open('text/html', 'replace');
45
+ frame.contentWindow.document.write(`{html_template}`);
46
+ frame.contentWindow.document.close();
47
+ }}"""
48
+
49
+ # TODO: Works but is inefficient because the iframe has to be reloaded each time
50
+ update_iframe_js = f"""(code) => {{
51
+ console.log(`UPDATING CODE`);
52
+ console.log(code)
53
+ const pattern = /# APP CODE START(.*?)# APP CODE END/gs;
54
+ const template = `{html_template}`;
55
+ const completedTemplate = template.replace(pattern, code);
56
+
57
+ console.log(completedTemplate);
58
+
59
+ const oldFrame = document.querySelector('.my-frame');
60
+ oldFrame.remove();
61
+
62
+ const htmlString = '<iframe class="my-frame" width="100%" height="512px" src="about:blank"></iframe>';
63
+ const parser = new DOMParser();
64
+ const doc = parser.parseFromString(htmlString, 'text/html');
65
+ const iframe = doc.querySelector('.my-frame');
66
+ const div = document.getElementById('demoDiv');
67
+ div.appendChild(iframe);
68
+
69
+ const frame = document.querySelector('.my-frame');
70
+ frame.contentWindow.document.open('text/html', 'replace');
71
+ frame.contentWindow.document.write(completedTemplate);
72
+ frame.contentWindow.document.close();
73
+ console.log(`UPDATE DONE`);
74
+ }}"""
75
+
76
+ copy_snippet_js = f"""async (code) => {{
77
+ console.log(`DOWNLOADING CODE`);
78
+ const pattern = /# APP CODE START(.*?)# APP CODE END/gs;
79
+ const template = `<div id="KiteWindApp">\n<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
80
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
81
+ <gradio-lite>\n# APP CODE START\n\n# APP CODE END\n</gradio-lite>\n</div>\n`;
82
+ // Step 1: Generate the HTML content
83
+ const completedTemplate = template.replace(pattern, code);
84
+
85
+ const snippet = completedTemplate;
86
+ console.log(snippet);
87
+
88
+ await navigator.clipboard.writeText(snippet);
89
+
90
+ console.log(`COPY DONE`);
91
+ }}"""
92
+
93
+ download_code_js = f"""(code) => {{
94
+ console.log(`DOWNLOADING CODE`);
95
+ const pattern = /# APP CODE START(.*?)# APP CODE END/gs;
96
+ const template = `{html_template}`;
97
+ // Step 1: Generate the HTML content
98
+ const completedTemplate = template.replace(pattern, code);
99
+
100
+ // Step 2: Create a Blob from the HTML content
101
+ const blob = new Blob([completedTemplate], {{ type: "text/html" }});
102
+
103
+ // Step 3: Create a URL for the Blob
104
+ const url = URL.createObjectURL(blob);
105
+
106
+ // Step 4: Create a download link
107
+ const downloadLink = document.createElement("a");
108
+ downloadLink.href = url;
109
+ downloadLink.download = "gradio-lite-app.html"; // Specify the filename for the download
110
+
111
+ // Step 5: Trigger a click event on the download link
112
+ downloadLink.click();
113
+
114
+ // Clean up by revoking the URL
115
+ URL.revokeObjectURL(url);
116
+
117
+ console.log(`DOWNLOAD DONE`);
118
+ }}"""
119
+
120
+
121
+ def query(payload):
122
+ response = requests.post(API_URL, headers=headers, json=payload)
123
+ return response.json()
124
+
125
+
126
+ def generate_text(code, prompt):
127
+ print(f"Calling API with prompt:\n{prompt}")
128
+ prompt = f"```python\n{code}```\nGiven the code above return only updated code for the following request:\n{prompt}\n<|assistant|>"
129
+ params = {"max_new_tokens": 512}
130
+ output = query({
131
+ "inputs": prompt,
132
+ "parameters": params,
133
+ })
134
+ print(f'API RESPONSE\n{output[0]["generated_text"]}')
135
+ assistant_reply = output[0]["generated_text"].split('<|assistant|>')[1]
136
+ match = re.search(code_pattern, assistant_reply, re.DOTALL)
137
+ new_code = match.group(1)
138
+ print(new_code)
139
+ # TODO: error handling here
140
+ return assistant_reply, new_code
141
+
142
+
143
+ model = whisper.load_model('medium')
144
+
145
+
146
+ def transcribe(audio):
147
+ result = model.transcribe(audio, language='en', verbose=False)
148
+ return result["text"]
149
+
150
+
151
+ with gr.Blocks() as demo:
152
+ gr.Markdown("<h1 align=\"center\">KiteWind πŸͺοΏ½οΏ½οΏ½</h1>")
153
+ gr.Markdown("<h4 align=\"center\">Chat-assisted web app creator by <a href=\"https://huggingface.co/gstaff\">@gstaff</a></h4>")
154
+ with gr.Row():
155
+ with gr.Column():
156
+ gr.Markdown("## 1. Run your app in the browser!")
157
+ html = gr.HTML(value='<div id="demoDiv"></div>')
158
+ gr.Markdown("## 2. Customize using voice requests!")
159
+ with gr.Row():
160
+ with gr.Column():
161
+ with gr.Group():
162
+ in_audio = gr.Audio(label="Record a voice request", source='microphone', type='filepath')
163
+ in_prompt = gr.Textbox(label="Or type a text request and press Enter",
164
+ placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Hola\n- Put the reversed name output into a separate textbox\n- Change the theme from monochrome to soft")
165
+ out_text = gr.TextArea(label="Chat Assistant Response")
166
+ clear = gr.ClearButton([in_prompt, in_audio, out_text])
167
+ with gr.Column():
168
+ code_area = gr.Code(label="App Code - You can also edit directly and then click Update App", language='python', value=starting_app_code)
169
+ update_btn = gr.Button("Update App", variant="primary")
170
+ update_btn.click(None, inputs=code_area, outputs=None, _js=update_iframe_js)
171
+ in_prompt.submit(generate_text, [code_area, in_prompt], [out_text, code_area]).then(None, inputs=code_area, outputs=None, _js=update_iframe_js)
172
+ in_audio.stop_recording(transcribe, [in_audio], [in_prompt]).then(generate_text, [code_area, in_prompt], [out_text, code_area]).then(None, inputs=code_area, outputs=None, _js=update_iframe_js)
173
+ with gr.Row():
174
+ with gr.Column():
175
+ gr.Markdown("## 3. Export your app to share!")
176
+ copy_snippet_btn = gr.Button("Copy app snippet to paste in another page")
177
+ copy_snippet_btn.click(None, code_area, None, _js=copy_snippet_js)
178
+ download_btn = gr.Button("Download app as a standalone file")
179
+ download_btn.click(None, code_area, None, _js=download_code_js)
180
+ with gr.Row():
181
+ with gr.Column():
182
+ gr.Markdown("## Current limitations")
183
+ with gr.Accordion("Click to view", open=False):
184
+ gr.Markdown("- Only gradio-lite apps using the python standard libraries and gradio are supported\n- The chat hasn't been tuned on gradio library data; it may make mistakes\n- The app needs to fully reload each time it is changed")
185
+
186
+ demo.load(None, None, None, _js=load_js)
187
+ demo.css = "footer {visibility: hidden}"
188
+
189
+ if __name__ == "__main__":
190
+ demo.queue().launch()
gradio-lite-playground.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
4
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
5
+ </head>
6
+ <body>
7
+ <gradio-lite id="KiteWindApp">
8
+ # APP CODE START
9
+ import gradio as gr
10
+
11
+ def greet(name):
12
+ return "Hello " + name + "!"
13
+
14
+ with gr.Blocks(theme="monochrome") as demo:
15
+ name = gr.Textbox(label="Name", value="World")
16
+ output = gr.Textbox(label="Output Box")
17
+ greet_btn = gr.Button("Greet")
18
+ greet_btn.click(fn=greet, inputs=name, outputs=output)
19
+ name.submit(fn=greet, inputs=name, outputs=output)
20
+
21
+ if __name__ == "__main__":
22
+ demo.css = "footer {visibility: hidden}"
23
+ demo.launch()
24
+
25
+ # APP CODE END
26
+ </gradio-lite>
27
+ </body>
28
+ </html>
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ openai-whisper