freddyaboulton HF staff commited on
Commit
5197529
1 Parent(s): e573b81
Files changed (6) hide show
  1. .gitignore +1 -0
  2. app.py +140 -0
  3. requirements.in +5 -0
  4. requirements.txt +288 -0
  5. sandbox.html +43 -0
  6. spinner.html +60 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .env
app.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from gradio_webrtc import WebRTC, ReplyOnPause, AdditionalOutputs
3
+ import numpy as np
4
+ import os
5
+ from twilio.rest import Client
6
+ import base64
7
+ import openai
8
+ import re
9
+ from huggingface_hub import InferenceClient
10
+ from pydub import AudioSegment
11
+ import io
12
+
13
+ from dotenv import load_dotenv
14
+ load_dotenv()
15
+
16
+ hf_client = InferenceClient()
17
+
18
+ spinner_html = open("spinner.html").read()
19
+
20
+
21
+ account_sid = os.environ.get("TWILIO_ACCOUNT_SID")
22
+ auth_token = os.environ.get("TWILIO_AUTH_TOKEN")
23
+
24
+ if account_sid and auth_token:
25
+ client = Client(account_sid, auth_token)
26
+
27
+ token = client.tokens.create()
28
+
29
+ rtc_configuration = {
30
+ "iceServers": token.ice_servers,
31
+ "iceTransportPolicy": "relay",
32
+ }
33
+ else:
34
+ rtc_configuration = None
35
+
36
+ client = openai.OpenAI(
37
+ api_key=os.environ.get("SAMBANOVA_API_KEY"),
38
+ base_url="https://api.sambanova.ai/v1",
39
+ )
40
+
41
+
42
+ system_prompt = "You are an AI coding assistant. Your task is to write single-file HTML applications based on a user's request. Only return the necessary code. Include all necessary imports and styles. You may also be asked to edit your original response."
43
+ user_prompt = "Please write a single-file HTML application to fulfill the following request.\nThe message:{user_message}\nCurrent code you have written:{code}"
44
+
45
+ def extract_html_content(text):
46
+ """
47
+ Extract content including HTML tags.
48
+ """
49
+ match = re.search(r'<!DOCTYPE html>.*?</html>', text, re.DOTALL)
50
+ return match.group(0) if match else None
51
+
52
+
53
+ def audio_to_bytes(audio: tuple[int, np.ndarray]):
54
+ audio_segment = AudioSegment(
55
+ audio[1].squeeze().tobytes(),
56
+ frame_rate=audio[0],
57
+ sample_width=audio[1].dtype.itemsize,
58
+ channels=1
59
+ )
60
+
61
+ # Export the audio segment to MP3 bytes - use a high bitrate to maximise quality
62
+ mp3_io = io.BytesIO()
63
+ audio_segment.export(mp3_io, format="mp3", bitrate="320k")
64
+
65
+ # Get the MP3 bytes
66
+ mp3_bytes = mp3_io.getvalue()
67
+ mp3_io.close()
68
+ return mp3_bytes
69
+
70
+
71
+ def display_in_sandbox(code):
72
+ encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
73
+ data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
74
+ return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"600px\"></iframe>"
75
+
76
+
77
+ def generate(user_message: tuple[int, np.ndarray],
78
+ history: list[dict],
79
+ code: str):
80
+ yield AdditionalOutputs(history, spinner_html)
81
+
82
+ text = hf_client.automatic_speech_recognition(audio_to_bytes(user_message)).text
83
+
84
+ user_msg_formatted = user_prompt.format(user_message=text, code=code)
85
+ history.append({"role": "user", "content": user_msg_formatted})
86
+
87
+ response = client.chat.completions.create(
88
+ model='Meta-Llama-3.1-70B-Instruct',
89
+ messages=history,
90
+ temperature = 0.1,
91
+ top_p = 0.1
92
+ )
93
+
94
+ output = response.choices[0].message.content
95
+ html_code = extract_html_content(output)
96
+ history.append({"role": "assistant", "content": output})
97
+ yield AdditionalOutputs(history, html_code)
98
+
99
+
100
+ with gr.Blocks(css=".code-component {max-height: 500px !important}") as demo:
101
+ history = gr.State([{"role": "system", "content": system_prompt}])
102
+ with gr.Row():
103
+ with gr.Column(scale=1):
104
+ gr.HTML(
105
+ """
106
+ <h1 style='text-align: center'>
107
+ Llama Code Editor
108
+ </h1>
109
+ <h2 style='text-align: center'>
110
+ Powered by SambaNova and Gradio-WebRTC ⚡️
111
+ </h2>
112
+ <p style='text-align: center'>
113
+ Create and edit single-file HTML applications with just your voice!.
114
+ </p>
115
+ <p style='text-align: center'>
116
+ Each conversation is limited to 90 seconds. Once the time limit is up you can rejoin the conversation.
117
+ </p>
118
+ """
119
+ )
120
+ webrtc = WebRTC(rtc_configuration=rtc_configuration,
121
+ mode="send", modality="audio")
122
+ with gr.Column(scale=10):
123
+ with gr.Tabs():
124
+ with gr.Tab("Sandbox"):
125
+ sandbox = gr.HTML(value=open("sandbox.html").read())
126
+ with gr.Tab("Code"):
127
+ code = gr.Code(language="html", max_lines=50, interactive=False, elem_classes="code-component")
128
+ with gr.Tab("Chat"):
129
+ cb = gr.Chatbot(type="messages")
130
+
131
+ webrtc.stream(ReplyOnPause(generate),
132
+ inputs=[webrtc, history, code],
133
+ outputs=[webrtc], time_limit=90)
134
+ webrtc.on_additional_outputs(lambda history, code: (history, code, history),
135
+ outputs=[history, code, cb])
136
+ code.change(display_in_sandbox, code, sandbox, queue=False)
137
+
138
+ if __name__ == "__main__":
139
+ demo.launch()
140
+
requirements.in ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio_webrtc[vad]
2
+ openai
3
+ python-dotenv
4
+ twilio
5
+ numba==0.60.0
requirements.txt ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv pip compile requirements.in -o requirements.txt
3
+ aiofiles==23.2.1
4
+ # via gradio
5
+ aiohappyeyeballs==2.4.3
6
+ # via aiohttp
7
+ aiohttp==3.11.3
8
+ # via
9
+ # aiohttp-retry
10
+ # twilio
11
+ aiohttp-retry==2.8.3
12
+ # via twilio
13
+ aioice==0.9.0
14
+ # via aiortc
15
+ aiortc==1.9.0
16
+ # via gradio-webrtc
17
+ aiosignal==1.3.1
18
+ # via aiohttp
19
+ annotated-types==0.7.0
20
+ # via pydantic
21
+ anyio==4.6.2.post1
22
+ # via
23
+ # gradio
24
+ # httpx
25
+ # openai
26
+ # starlette
27
+ attrs==24.2.0
28
+ # via aiohttp
29
+ audioread==3.0.1
30
+ # via librosa
31
+ av==12.3.0
32
+ # via aiortc
33
+ certifi==2024.8.30
34
+ # via
35
+ # httpcore
36
+ # httpx
37
+ # requests
38
+ cffi==1.17.1
39
+ # via
40
+ # aiortc
41
+ # cryptography
42
+ # pylibsrtp
43
+ # soundfile
44
+ charset-normalizer==3.4.0
45
+ # via requests
46
+ click==8.1.7
47
+ # via
48
+ # typer
49
+ # uvicorn
50
+ coloredlogs==15.0.1
51
+ # via onnxruntime
52
+ cryptography==43.0.3
53
+ # via
54
+ # aiortc
55
+ # pyopenssl
56
+ decorator==5.1.1
57
+ # via librosa
58
+ distro==1.9.0
59
+ # via openai
60
+ dnspython==2.7.0
61
+ # via aioice
62
+ fastapi==0.115.5
63
+ # via gradio
64
+ ffmpy==0.4.0
65
+ # via gradio
66
+ filelock==3.16.1
67
+ # via huggingface-hub
68
+ flatbuffers==24.3.25
69
+ # via onnxruntime
70
+ frozenlist==1.5.0
71
+ # via
72
+ # aiohttp
73
+ # aiosignal
74
+ fsspec==2024.10.0
75
+ # via
76
+ # gradio-client
77
+ # huggingface-hub
78
+ google-crc32c==1.6.0
79
+ # via aiortc
80
+ gradio==5.6.0
81
+ # via gradio-webrtc
82
+ gradio-client==1.4.3
83
+ # via gradio
84
+ gradio-webrtc==0.0.13
85
+ # via -r requirements.in
86
+ h11==0.14.0
87
+ # via
88
+ # httpcore
89
+ # uvicorn
90
+ httpcore==1.0.7
91
+ # via httpx
92
+ httpx==0.27.2
93
+ # via
94
+ # gradio
95
+ # gradio-client
96
+ # openai
97
+ # safehttpx
98
+ huggingface-hub==0.26.2
99
+ # via
100
+ # gradio
101
+ # gradio-client
102
+ humanfriendly==10.0
103
+ # via coloredlogs
104
+ idna==3.10
105
+ # via
106
+ # anyio
107
+ # httpx
108
+ # requests
109
+ # yarl
110
+ ifaddr==0.2.0
111
+ # via aioice
112
+ jinja2==3.1.4
113
+ # via gradio
114
+ jiter==0.7.1
115
+ # via openai
116
+ joblib==1.4.2
117
+ # via
118
+ # librosa
119
+ # scikit-learn
120
+ lazy-loader==0.4
121
+ # via librosa
122
+ librosa==0.10.2.post1
123
+ # via gradio-webrtc
124
+ llvmlite==0.43.0
125
+ # via numba
126
+ markdown-it-py==3.0.0
127
+ # via rich
128
+ markupsafe==2.1.5
129
+ # via
130
+ # gradio
131
+ # jinja2
132
+ mdurl==0.1.2
133
+ # via markdown-it-py
134
+ mpmath==1.3.0
135
+ # via sympy
136
+ msgpack==1.1.0
137
+ # via librosa
138
+ multidict==6.1.0
139
+ # via
140
+ # aiohttp
141
+ # yarl
142
+ numba==0.60.0
143
+ # via
144
+ # -r requirements.in
145
+ # librosa
146
+ numpy==2.0.2
147
+ # via
148
+ # gradio
149
+ # librosa
150
+ # numba
151
+ # onnxruntime
152
+ # pandas
153
+ # scikit-learn
154
+ # scipy
155
+ # soxr
156
+ onnxruntime==1.20.0
157
+ # via gradio-webrtc
158
+ openai==1.54.4
159
+ # via -r requirements.in
160
+ orjson==3.10.11
161
+ # via gradio
162
+ packaging==24.2
163
+ # via
164
+ # gradio
165
+ # gradio-client
166
+ # huggingface-hub
167
+ # lazy-loader
168
+ # onnxruntime
169
+ # pooch
170
+ pandas==2.2.3
171
+ # via gradio
172
+ pillow==11.0.0
173
+ # via gradio
174
+ platformdirs==4.3.6
175
+ # via pooch
176
+ pooch==1.8.2
177
+ # via librosa
178
+ propcache==0.2.0
179
+ # via
180
+ # aiohttp
181
+ # yarl
182
+ protobuf==5.28.3
183
+ # via onnxruntime
184
+ pycparser==2.22
185
+ # via cffi
186
+ pydantic==2.9.2
187
+ # via
188
+ # fastapi
189
+ # gradio
190
+ # openai
191
+ pydantic-core==2.23.4
192
+ # via pydantic
193
+ pydub==0.25.1
194
+ # via gradio
195
+ pyee==12.1.1
196
+ # via aiortc
197
+ pygments==2.18.0
198
+ # via rich
199
+ pyjwt==2.10.0
200
+ # via twilio
201
+ pylibsrtp==0.10.0
202
+ # via aiortc
203
+ pyopenssl==24.2.1
204
+ # via aiortc
205
+ python-dateutil==2.9.0.post0
206
+ # via pandas
207
+ python-dotenv==1.0.1
208
+ # via -r requirements.in
209
+ python-multipart==0.0.12
210
+ # via gradio
211
+ pytz==2024.2
212
+ # via pandas
213
+ pyyaml==6.0.2
214
+ # via
215
+ # gradio
216
+ # huggingface-hub
217
+ requests==2.32.3
218
+ # via
219
+ # huggingface-hub
220
+ # pooch
221
+ # twilio
222
+ rich==13.9.4
223
+ # via typer
224
+ ruff==0.7.4
225
+ # via gradio
226
+ safehttpx==0.1.1
227
+ # via gradio
228
+ scikit-learn==1.5.2
229
+ # via librosa
230
+ scipy==1.14.1
231
+ # via
232
+ # librosa
233
+ # scikit-learn
234
+ semantic-version==2.10.0
235
+ # via gradio
236
+ shellingham==1.5.4
237
+ # via typer
238
+ six==1.16.0
239
+ # via python-dateutil
240
+ sniffio==1.3.1
241
+ # via
242
+ # anyio
243
+ # httpx
244
+ # openai
245
+ soundfile==0.12.1
246
+ # via librosa
247
+ soxr==0.5.0.post1
248
+ # via librosa
249
+ starlette==0.41.3
250
+ # via
251
+ # fastapi
252
+ # gradio
253
+ sympy==1.13.3
254
+ # via onnxruntime
255
+ threadpoolctl==3.5.0
256
+ # via scikit-learn
257
+ tomlkit==0.12.0
258
+ # via gradio
259
+ tqdm==4.67.0
260
+ # via
261
+ # huggingface-hub
262
+ # openai
263
+ twilio==9.3.7
264
+ # via -r requirements.in
265
+ typer==0.13.1
266
+ # via gradio
267
+ typing-extensions==4.12.2
268
+ # via
269
+ # fastapi
270
+ # gradio
271
+ # gradio-client
272
+ # huggingface-hub
273
+ # librosa
274
+ # openai
275
+ # pydantic
276
+ # pydantic-core
277
+ # pyee
278
+ # typer
279
+ tzdata==2024.2
280
+ # via pandas
281
+ urllib3==2.2.3
282
+ # via requests
283
+ uvicorn==0.32.0
284
+ # via gradio
285
+ websockets==12.0
286
+ # via gradio-client
287
+ yarl==1.17.2
288
+ # via aiohttp
sandbox.html ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ justify-content: center;
6
+ min-height: 400px;
7
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4e8ec 100%);
8
+ border-radius: 8px;
9
+ border: 2px dashed #cbd5e1;
10
+ padding: 2rem;
11
+ text-align: center;
12
+ color: #64748b;
13
+ font-family: system-ui, -apple-system, sans-serif;
14
+ ">
15
+ <div style="
16
+ width: 80px;
17
+ height: 80px;
18
+ margin-bottom: 1.5rem;
19
+ border: 3px solid #cbd5e1;
20
+ border-radius: 12px;
21
+ position: relative;
22
+ ">
23
+ <div style="
24
+ position: absolute;
25
+ top: 50%;
26
+ left: 50%;
27
+ transform: translate(-50%, -50%);
28
+ font-size: 2rem;
29
+ ">📦</div>
30
+ </div>
31
+ <h2 style="
32
+ margin: 0 0 0.5rem 0;
33
+ font-size: 1.5rem;
34
+ font-weight: 600;
35
+ color: #475569;
36
+ ">No Application Created</h2>
37
+ <p style="
38
+ margin: 0;
39
+ font-size: 1rem;
40
+ max-width: 300px;
41
+ line-height: 1.5;
42
+ ">Create your first application to get started with the sandbox environment</p>
43
+ </div>
spinner.html ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ justify-content: center;
6
+ min-height: 400px;
7
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
8
+ border-radius: 8px;
9
+ padding: 2rem;
10
+ text-align: center;
11
+ font-family: system-ui, -apple-system, sans-serif;
12
+ ">
13
+ <!-- Spinner container -->
14
+ <div style="
15
+ position: relative;
16
+ width: 64px;
17
+ height: 64px;
18
+ margin-bottom: 1.5rem;
19
+ ">
20
+ <!-- Static ring -->
21
+ <div style="
22
+ position: absolute;
23
+ width: 100%;
24
+ height: 100%;
25
+ border: 4px solid #e2e8f0;
26
+ border-radius: 50%;
27
+ "></div>
28
+ <!-- Animated spinner -->
29
+ <div style="
30
+ position: absolute;
31
+ width: 100%;
32
+ height: 100%;
33
+ border: 4px solid transparent;
34
+ border-top-color: #3b82f6;
35
+ border-radius: 50%;
36
+ animation: spin 1s linear infinite;
37
+ "></div>
38
+ </div>
39
+
40
+ <!-- Text content -->
41
+ <h2 style="
42
+ margin: 0 0 0.5rem 0;
43
+ font-size: 1.25rem;
44
+ font-weight: 600;
45
+ color: #475569;
46
+ ">Generating your application...</h2>
47
+
48
+ <p style="
49
+ margin: 0;
50
+ font-size: 0.875rem;
51
+ color: #64748b;
52
+ ">This may take a few moments</p>
53
+
54
+ <style>
55
+ @keyframes spin {
56
+ 0% { transform: rotate(0deg); }
57
+ 100% { transform: rotate(360deg); }
58
+ }
59
+ </style>
60
+ </div>