akhaliq HF Staff commited on
Commit
4507a25
·
1 Parent(s): 5d2566d

update transformers js

Browse files
Files changed (1) hide show
  1. app.py +271 -20
app.py CHANGED
@@ -58,6 +58,71 @@ Always respond with code that can be executed or rendered directly.
58
 
59
  Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text. Do NOT add the language name at the top of the code output."""
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  GENERIC_SYSTEM_PROMPT = """You are an expert {language} developer. Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Output ONLY the code inside a ``` code block, and do not include any explanations or extra text. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible. Do NOT add the language name at the top of the code output."""
62
 
63
  # System prompt with search capability
@@ -222,6 +287,10 @@ DEMO_LIST = [
222
  {
223
  "title": "Search/Replace Example",
224
  "description": "Generate HTML first, then ask: 'Change the title to My New Title' or 'Add a blue background to the body'"
 
 
 
 
225
  }
226
  ]
227
 
@@ -331,6 +400,47 @@ def remove_code_block(text):
331
  return lines[1] if len(lines) > 1 else ''
332
  return text.strip()
333
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  def history_render(history: History):
335
  return gr.update(visible=True), history
336
 
@@ -980,6 +1090,8 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
980
  # Use language-specific prompt
981
  if language == "html":
982
  system_prompt = HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else HTML_SYSTEM_PROMPT
 
 
983
  else:
984
  system_prompt = GENERIC_SYSTEM_PROMPT_WITH_SEARCH.format(language=language) if enable_search else GENERIC_SYSTEM_PROMPT.format(language=language)
985
 
@@ -1040,35 +1152,75 @@ This will help me create a better design for you."""
1040
  chunk.choices[0].delta.content is not None
1041
  ):
1042
  content += chunk.choices[0].delta.content
1043
- clean_code = remove_code_block(content)
1044
  search_status = " (with web search)" if enable_search and tavily_client else ""
1045
- if has_existing_html:
1046
- # Fallback: If the model returns a full HTML file, use it directly
1047
- if clean_code.strip().startswith("<!DOCTYPE html>") or clean_code.strip().startswith("<html"):
 
 
 
1048
  yield {
1049
- code_output: gr.update(value=clean_code, language=get_gradio_language(language)),
1050
  history_output: history_to_chatbot_messages(_history),
1051
- sandbox: send_to_sandbox(clean_code) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1052
  }
1053
  else:
1054
- last_html = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
1055
- modified_html = apply_search_replace_changes(last_html, clean_code)
1056
- clean_html = remove_code_block(modified_html)
1057
  yield {
1058
- code_output: gr.update(value=clean_html, language=get_gradio_language(language)),
1059
  history_output: history_to_chatbot_messages(_history),
1060
- sandbox: send_to_sandbox(clean_html) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1061
  }
1062
  else:
1063
- yield {
1064
- code_output: gr.update(value=clean_code, language=get_gradio_language(language)),
1065
- history_output: history_to_chatbot_messages(_history),
1066
- sandbox: send_to_sandbox(clean_code) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1067
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1068
  # Skip chunks with empty choices (end of stream)
1069
  # Do not treat as error
1070
  # Handle response based on whether this is a modification or new generation
1071
- if has_existing_html:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1072
  # Fallback: If the model returns a full HTML file, use it directly
1073
  final_code = remove_code_block(content)
1074
  if final_code.strip().startswith("<!DOCTYPE html>") or final_code.strip().startswith("<html"):
@@ -1186,7 +1338,7 @@ with gr.Blocks(
1186
  )
1187
  # Language dropdown for code generation
1188
  language_choices = [
1189
- "html", "python", "c", "cpp", "markdown", "latex", "json", "css", "javascript", "jinja2", "typescript", "yaml", "dockerfile", "shell", "r", "sql", "sql-msSQL", "sql-mySQL", "sql-mariaDB", "sql-sqlite", "sql-cassandra", "sql-plSQL", "sql-hive", "sql-pgSQL", "sql-gql", "sql-gpSQL", "sql-sparkSQL", "sql-esper"
1190
  ]
1191
  language_dropdown = gr.Dropdown(
1192
  choices=language_choices,
@@ -1222,7 +1374,8 @@ with gr.Blocks(
1222
  sdk_choices = [
1223
  ("Gradio (Python)", "gradio"),
1224
  ("Streamlit (Python)", "streamlit"),
1225
- ("Static (HTML)", "static")
 
1226
  ]
1227
  sdk_dropdown = gr.Dropdown(
1228
  choices=[x[0] for x in sdk_choices],
@@ -1293,11 +1446,27 @@ with gr.Blocks(
1293
  def update_code_language(language):
1294
  return gr.update(language=get_gradio_language(language))
1295
 
 
 
 
 
 
 
 
 
1296
  language_dropdown.change(update_code_language, inputs=language_dropdown, outputs=code_output)
 
1297
 
1298
  def preview_logic(code, language):
1299
  if language == "html":
1300
  return send_to_sandbox(code)
 
 
 
 
 
 
 
1301
  else:
1302
  return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
1303
 
@@ -1342,7 +1511,8 @@ with gr.Blocks(
1342
  sdk_map = {
1343
  "Gradio (Python)": "gradio",
1344
  "Streamlit (Python)": "docker", # Use 'docker' for Streamlit Spaces
1345
- "Static (HTML)": "static"
 
1346
  }
1347
  sdk = sdk_map.get(sdk_name, "gradio")
1348
  api = HfApi(token=token.token)
@@ -1394,6 +1564,87 @@ with gr.Blocks(
1394
 
1395
  except Exception as e:
1396
  return gr.update(value=f"Error duplicating Streamlit space: {e}", visible=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1397
  # Other SDKs (existing logic)
1398
  if sdk == "static":
1399
  file_name = "index.html"
 
58
 
59
  Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text. Do NOT add the language name at the top of the code output."""
60
 
61
+ TRANSFORMERS_JS_SYSTEM_PROMPT = """You are an expert web developer creating a transformers.js application. You will generate THREE separate files: index.html, index.js, and style.css.
62
+
63
+ IMPORTANT: You MUST output ALL THREE files in the following format:
64
+
65
+ ```html
66
+ <!-- index.html content here -->
67
+ ```
68
+
69
+ ```javascript
70
+ // index.js content here
71
+ ```
72
+
73
+ ```css
74
+ /* style.css content here */
75
+ ```
76
+
77
+ Requirements:
78
+ 1. Create a modern, responsive web application using transformers.js
79
+ 2. Use the transformers.js library for AI/ML functionality
80
+ 3. Create a clean, professional UI with good user experience
81
+ 4. Make the application fully responsive for mobile devices
82
+ 5. Use modern CSS practices and JavaScript ES6+ features
83
+ 6. Include proper error handling and loading states
84
+ 7. Follow accessibility best practices
85
+
86
+ The index.html should contain the basic HTML structure and link to the CSS and JS files.
87
+ The index.js should contain all the JavaScript logic including transformers.js integration.
88
+ The style.css should contain all the styling for the application.
89
+
90
+ Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
91
+
92
+ TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert web developer creating a transformers.js application. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies for transformers.js.
93
+
94
+ You will generate THREE separate files: index.html, index.js, and style.css.
95
+
96
+ IMPORTANT: You MUST output ALL THREE files in the following format:
97
+
98
+ ```html
99
+ <!-- index.html content here -->
100
+ ```
101
+
102
+ ```javascript
103
+ // index.js content here
104
+ ```
105
+
106
+ ```css
107
+ /* style.css content here */
108
+ ```
109
+
110
+ Requirements:
111
+ 1. Create a modern, responsive web application using transformers.js
112
+ 2. Use the transformers.js library for AI/ML functionality
113
+ 3. Use web search to find current best practices and latest transformers.js features
114
+ 4. Create a clean, professional UI with good user experience
115
+ 5. Make the application fully responsive for mobile devices
116
+ 6. Use modern CSS practices and JavaScript ES6+ features
117
+ 7. Include proper error handling and loading states
118
+ 8. Follow accessibility best practices
119
+
120
+ The index.html should contain the basic HTML structure and link to the CSS and JS files.
121
+ The index.js should contain all the JavaScript logic including transformers.js integration.
122
+ The style.css should contain all the styling for the application.
123
+
124
+ Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
125
+
126
  GENERIC_SYSTEM_PROMPT = """You are an expert {language} developer. Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Output ONLY the code inside a ``` code block, and do not include any explanations or extra text. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible. Do NOT add the language name at the top of the code output."""
127
 
128
  # System prompt with search capability
 
287
  {
288
  "title": "Search/Replace Example",
289
  "description": "Generate HTML first, then ask: 'Change the title to My New Title' or 'Add a blue background to the body'"
290
+ },
291
+ {
292
+ "title": "Transformers.js App",
293
+ "description": "Create a transformers.js application with AI/ML functionality using the transformers.js library"
294
  }
295
  ]
296
 
 
400
  return lines[1] if len(lines) > 1 else ''
401
  return text.strip()
402
 
403
+ def parse_transformers_js_output(text):
404
+ """Parse transformers.js output and extract the three files (index.html, index.js, style.css)"""
405
+ files = {
406
+ 'index.html': '',
407
+ 'index.js': '',
408
+ 'style.css': ''
409
+ }
410
+
411
+ # Patterns to match the three code blocks
412
+ html_pattern = r'```html\s*\n([\s\S]+?)\n```'
413
+ js_pattern = r'```javascript\s*\n([\s\S]+?)\n```'
414
+ css_pattern = r'```css\s*\n([\s\S]+?)\n```'
415
+
416
+ # Extract HTML content
417
+ html_match = re.search(html_pattern, text, re.IGNORECASE)
418
+ if html_match:
419
+ files['index.html'] = html_match.group(1).strip()
420
+
421
+ # Extract JavaScript content
422
+ js_match = re.search(js_pattern, text, re.IGNORECASE)
423
+ if js_match:
424
+ files['index.js'] = js_match.group(1).strip()
425
+
426
+ # Extract CSS content
427
+ css_match = re.search(css_pattern, text, re.IGNORECASE)
428
+ if css_match:
429
+ files['style.css'] = css_match.group(1).strip()
430
+
431
+ return files
432
+
433
+ def format_transformers_js_output(files):
434
+ """Format the three files into a single display string"""
435
+ output = []
436
+ output.append("=== index.html ===")
437
+ output.append(files['index.html'])
438
+ output.append("\n=== index.js ===")
439
+ output.append(files['index.js'])
440
+ output.append("\n=== style.css ===")
441
+ output.append(files['style.css'])
442
+ return '\n'.join(output)
443
+
444
  def history_render(history: History):
445
  return gr.update(visible=True), history
446
 
 
1090
  # Use language-specific prompt
1091
  if language == "html":
1092
  system_prompt = HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else HTML_SYSTEM_PROMPT
1093
+ elif language == "transformers.js":
1094
+ system_prompt = TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH if enable_search else TRANSFORMERS_JS_SYSTEM_PROMPT
1095
  else:
1096
  system_prompt = GENERIC_SYSTEM_PROMPT_WITH_SEARCH.format(language=language) if enable_search else GENERIC_SYSTEM_PROMPT.format(language=language)
1097
 
 
1152
  chunk.choices[0].delta.content is not None
1153
  ):
1154
  content += chunk.choices[0].delta.content
 
1155
  search_status = " (with web search)" if enable_search and tavily_client else ""
1156
+
1157
+ # Handle transformers.js output differently
1158
+ if language == "transformers.js":
1159
+ files = parse_transformers_js_output(content)
1160
+ if files['index.html'] and files['index.js'] and files['style.css']:
1161
+ formatted_output = format_transformers_js_output(files)
1162
  yield {
1163
+ code_output: gr.update(value=formatted_output, language="html"),
1164
  history_output: history_to_chatbot_messages(_history),
1165
+ sandbox: send_to_sandbox(files['index.html']) if files['index.html'] else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1166
  }
1167
  else:
1168
+ # Still streaming, show partial content
 
 
1169
  yield {
1170
+ code_output: gr.update(value=content, language="html"),
1171
  history_output: history_to_chatbot_messages(_history),
1172
+ sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Generating transformers.js app...</div>",
1173
  }
1174
  else:
1175
+ clean_code = remove_code_block(content)
1176
+ if has_existing_html:
1177
+ # Fallback: If the model returns a full HTML file, use it directly
1178
+ if clean_code.strip().startswith("<!DOCTYPE html>") or clean_code.strip().startswith("<html"):
1179
+ yield {
1180
+ code_output: gr.update(value=clean_code, language=get_gradio_language(language)),
1181
+ history_output: history_to_chatbot_messages(_history),
1182
+ sandbox: send_to_sandbox(clean_code) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1183
+ }
1184
+ else:
1185
+ last_html = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
1186
+ modified_html = apply_search_replace_changes(last_html, clean_code)
1187
+ clean_html = remove_code_block(modified_html)
1188
+ yield {
1189
+ code_output: gr.update(value=clean_html, language=get_gradio_language(language)),
1190
+ history_output: history_to_chatbot_messages(_history),
1191
+ sandbox: send_to_sandbox(clean_html) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1192
+ }
1193
+ else:
1194
+ yield {
1195
+ code_output: gr.update(value=clean_code, language=get_gradio_language(language)),
1196
+ history_output: history_to_chatbot_messages(_history),
1197
+ sandbox: send_to_sandbox(clean_code) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
1198
+ }
1199
  # Skip chunks with empty choices (end of stream)
1200
  # Do not treat as error
1201
  # Handle response based on whether this is a modification or new generation
1202
+ if language == "transformers.js":
1203
+ # Handle transformers.js output
1204
+ files = parse_transformers_js_output(content)
1205
+ if files['index.html'] and files['index.js'] and files['style.css']:
1206
+ formatted_output = format_transformers_js_output(files)
1207
+ _history.append([query, formatted_output])
1208
+ yield {
1209
+ code_output: formatted_output,
1210
+ history: _history,
1211
+ sandbox: send_to_sandbox(files['index.html']),
1212
+ history_output: history_to_chatbot_messages(_history),
1213
+ }
1214
+ else:
1215
+ # Fallback if parsing failed
1216
+ _history.append([query, content])
1217
+ yield {
1218
+ code_output: content,
1219
+ history: _history,
1220
+ sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Error parsing transformers.js output. Please try again.</div>",
1221
+ history_output: history_to_chatbot_messages(_history),
1222
+ }
1223
+ elif has_existing_html:
1224
  # Fallback: If the model returns a full HTML file, use it directly
1225
  final_code = remove_code_block(content)
1226
  if final_code.strip().startswith("<!DOCTYPE html>") or final_code.strip().startswith("<html"):
 
1338
  )
1339
  # Language dropdown for code generation
1340
  language_choices = [
1341
+ "html", "python", "c", "cpp", "markdown", "latex", "json", "css", "javascript", "jinja2", "typescript", "yaml", "dockerfile", "shell", "r", "sql", "sql-msSQL", "sql-mySQL", "sql-mariaDB", "sql-sqlite", "sql-cassandra", "sql-plSQL", "sql-hive", "sql-pgSQL", "sql-gql", "sql-gpSQL", "sql-sparkSQL", "sql-esper", "transformers.js"
1342
  ]
1343
  language_dropdown = gr.Dropdown(
1344
  choices=language_choices,
 
1374
  sdk_choices = [
1375
  ("Gradio (Python)", "gradio"),
1376
  ("Streamlit (Python)", "streamlit"),
1377
+ ("Static (HTML)", "static"),
1378
+ ("Transformers.js", "transformers.js")
1379
  ]
1380
  sdk_dropdown = gr.Dropdown(
1381
  choices=[x[0] for x in sdk_choices],
 
1446
  def update_code_language(language):
1447
  return gr.update(language=get_gradio_language(language))
1448
 
1449
+ def update_sdk_based_on_language(language):
1450
+ if language == "transformers.js":
1451
+ return gr.update(value="Transformers.js")
1452
+ elif language == "html":
1453
+ return gr.update(value="Static (HTML)")
1454
+ else:
1455
+ return gr.update(value="Gradio (Python)")
1456
+
1457
  language_dropdown.change(update_code_language, inputs=language_dropdown, outputs=code_output)
1458
+ language_dropdown.change(update_sdk_based_on_language, inputs=language_dropdown, outputs=sdk_dropdown)
1459
 
1460
  def preview_logic(code, language):
1461
  if language == "html":
1462
  return send_to_sandbox(code)
1463
+ elif language == "transformers.js":
1464
+ # For transformers.js, extract the HTML part for preview
1465
+ files = parse_transformers_js_output(code)
1466
+ if files['index.html']:
1467
+ return send_to_sandbox(files['index.html'])
1468
+ else:
1469
+ return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
1470
  else:
1471
  return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
1472
 
 
1511
  sdk_map = {
1512
  "Gradio (Python)": "gradio",
1513
  "Streamlit (Python)": "docker", # Use 'docker' for Streamlit Spaces
1514
+ "Static (HTML)": "static",
1515
+ "Transformers.js": "static" # Transformers.js uses static SDK
1516
  }
1517
  sdk = sdk_map.get(sdk_name, "gradio")
1518
  api = HfApi(token=token.token)
 
1564
 
1565
  except Exception as e:
1566
  return gr.update(value=f"Error duplicating Streamlit space: {e}", visible=True)
1567
+ # Transformers.js logic
1568
+ elif sdk_name == "Transformers.js":
1569
+ try:
1570
+ # Use duplicate_space to create a transformers.js template space
1571
+ from huggingface_hub import duplicate_space
1572
+
1573
+ # Duplicate the transformers.js template space
1574
+ duplicated_repo = duplicate_space(
1575
+ from_id="static-templates/transformers.js",
1576
+ to_id=space_name.strip(),
1577
+ token=token.token,
1578
+ exist_ok=True
1579
+ )
1580
+
1581
+ # Parse the transformers.js output to get the three files
1582
+ files = parse_transformers_js_output(code)
1583
+
1584
+ if not files['index.html'] or not files['index.js'] or not files['style.css']:
1585
+ return gr.update(value="Error: Could not parse transformers.js output. Please regenerate the code.", visible=True)
1586
+
1587
+ # Upload the three files to the duplicated space
1588
+ import tempfile
1589
+
1590
+ # Upload index.html
1591
+ with tempfile.NamedTemporaryFile("w", suffix=".html", delete=False) as f:
1592
+ f.write(files['index.html'])
1593
+ temp_path = f.name
1594
+
1595
+ try:
1596
+ api.upload_file(
1597
+ path_or_fileobj=temp_path,
1598
+ path_in_repo="index.html",
1599
+ repo_id=repo_id,
1600
+ repo_type="space"
1601
+ )
1602
+ except Exception as e:
1603
+ return gr.update(value=f"Error uploading index.html: {e}", visible=True)
1604
+ finally:
1605
+ import os
1606
+ os.unlink(temp_path)
1607
+
1608
+ # Upload index.js
1609
+ with tempfile.NamedTemporaryFile("w", suffix=".js", delete=False) as f:
1610
+ f.write(files['index.js'])
1611
+ temp_path = f.name
1612
+
1613
+ try:
1614
+ api.upload_file(
1615
+ path_or_fileobj=temp_path,
1616
+ path_in_repo="index.js",
1617
+ repo_id=repo_id,
1618
+ repo_type="space"
1619
+ )
1620
+ except Exception as e:
1621
+ return gr.update(value=f"Error uploading index.js: {e}", visible=True)
1622
+ finally:
1623
+ import os
1624
+ os.unlink(temp_path)
1625
+
1626
+ # Upload style.css
1627
+ with tempfile.NamedTemporaryFile("w", suffix=".css", delete=False) as f:
1628
+ f.write(files['style.css'])
1629
+ temp_path = f.name
1630
+
1631
+ try:
1632
+ api.upload_file(
1633
+ path_or_fileobj=temp_path,
1634
+ path_in_repo="style.css",
1635
+ repo_id=repo_id,
1636
+ repo_type="space"
1637
+ )
1638
+ space_url = f"https://huggingface.co/spaces/{repo_id}"
1639
+ return gr.update(value=f"✅ Deployed! [Open your Transformers.js Space here]({space_url})", visible=True)
1640
+ except Exception as e:
1641
+ return gr.update(value=f"Error uploading style.css: {e}", visible=True)
1642
+ finally:
1643
+ import os
1644
+ os.unlink(temp_path)
1645
+
1646
+ except Exception as e:
1647
+ return gr.update(value=f"Error duplicating Transformers.js space: {e}", visible=True)
1648
  # Other SDKs (existing logic)
1649
  if sdk == "static":
1650
  file_name = "index.html"