akhaliq HF Staff commited on
Commit
4d1fa6f
·
verified ·
1 Parent(s): 6390c39

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. app.py +360 -0
  2. requirements.txt +3 -0
  3. utils.py +63 -0
app.py ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import random
3
+ import time
4
+ from typing import Dict, List, Tuple, Optional
5
+ import json
6
+
7
+ # Mock LLM UI generators (simulating different LLM responses)
8
+ def generate_ui_llm1(prompt: str, style: str = "modern") -> str:
9
+ """Simulate LLM 1 generating UI code"""
10
+ time.sleep(0.5) # Simulate API call
11
+
12
+ ui_templates = {
13
+ "form": f"""
14
+ with gr.Blocks() as ui1:
15
+ gr.Markdown("# {prompt.title()} - Generated by LLM 1")
16
+ gr.Textbox(label="Name", placeholder="Enter your name")
17
+ gr.Number(label="Age", minimum=1, maximum=120)
18
+ gr.Dropdown(["Option A", "Option B", "Option C"], label="Choice")
19
+ gr.Button("Submit", variant="primary")
20
+ """,
21
+ "dashboard": f"""
22
+ with gr.Blocks() as ui1:
23
+ gr.Markdown("## {prompt.title()} Dashboard - LLM 1")
24
+ with gr.Row():
25
+ with gr.Column():
26
+ gr.Number(label="Metric 1", value=42)
27
+ gr.Number(label="Metric 2", value=128)
28
+ with gr.Column():
29
+ gr.BarPlot(value={{"categories": ["A", "B", "C"], "values": [10, 20, 30]}})
30
+ gr.Button("Refresh Data")
31
+ """,
32
+ "chat": f"""
33
+ with gr.Blocks() as ui1:
34
+ gr.Markdown("# {prompt.title()} Chat - LLM 1")
35
+ chatbot = gr.Chatbot()
36
+ msg = gr.Textbox(label="Message", placeholder="Type your message...")
37
+ gr.Button("Send")
38
+ """,
39
+ "data": f"""
40
+ with gr.Blocks() as ui1:
41
+ gr.Markdown("## {prompt.title()} Data View - LLM 1")
42
+ gr.Dataframe(
43
+ headers=["Name", "Score", "Status"],
44
+ value=[["Alice", 95, "Active"], ["Bob", 87, "Pending"], ["Charlie", 92, "Active"]]
45
+ )
46
+ gr.Button("Export")
47
+ """
48
+ }
49
+
50
+ # Choose template based on prompt keywords
51
+ keywords = prompt.lower()
52
+ if "form" in keywords or "input" in keywords:
53
+ return ui_templates["form"]
54
+ elif "dashboard" in keywords or "metric" in keywords or "chart" in keywords:
55
+ return ui_templates["dashboard"]
56
+ elif "chat" in keywords or "message" in keywords:
57
+ return ui_templates["chat"]
58
+ else:
59
+ return ui_templates["data"]
60
+
61
+ def generate_ui_llm2(prompt: str, style: str = "minimal") -> str:
62
+ """Simulate LLM 2 generating UI code"""
63
+ time.sleep(0.5) # Simulate API call
64
+
65
+ ui_templates = {
66
+ "form": f'''
67
+ with gr.Blocks() as ui2:
68
+ gr.Markdown(f"### {prompt.title()} - LLM 2 Design")
69
+ with gr.Group():
70
+ gr.Textbox(label="Full Name", info="Enter your full name")
71
+ gr.Slider(1, 100, value=25, label="Age Range")
72
+ gr.Radio(["Choice 1", "Choice 2", "Choice 3"], label="Selection")
73
+ with gr.Row():
74
+ gr.Button("Submit", variant="primary")
75
+ gr.Button("Reset")
76
+ ''',
77
+ "dashboard": f'''
78
+ with gr.Blocks() as ui2:
79
+ gr.Markdown(f"## {prompt.title()} Analytics - LLM 2")
80
+ with gr.Row():
81
+ gr.LinePlot(value={{"x": [1,2,3,4], "y": [10,20,15,25]}})
82
+ gr.ScatterPlot(value={{"x": [1,2,3,4], "y": [5,15,10,20]}})
83
+ gr.Number(label="Total", value=100)
84
+ ''',
85
+ "chat": f'''
86
+ with gr.Blocks() as ui2:
87
+ gr.Markdown(f"# {prompt.title()} Assistant - LLM 2")
88
+ with gr.Row():
89
+ with gr.Column(scale=3):
90
+ chatbot = gr.Chatbot(height=400)
91
+ with gr.Column(scale=1):
92
+ gr.Dropdown(["Greeting", "Question", "Feedback"], label="Quick Actions")
93
+ msg = gr.Textbox(label="Your input", placeholder="Ask anything...")
94
+ ''',
95
+ "data": f'''
96
+ with gr.Blocks() as ui2:
97
+ gr.Markdown(f"## {prompt.title()} Explorer - LLM 2")
98
+ gr.JSON(value={{"data": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]}})
99
+ gr.FileExplorer()
100
+ '''
101
+ }
102
+
103
+ # Choose template based on prompt keywords
104
+ keywords = prompt.lower()
105
+ if "form" in keywords or "input" in keywords:
106
+ return ui_templates["form"]
107
+ elif "dashboard" in keywords or "metric" in keywords or "chart" in keywords:
108
+ return ui_templates["dashboard"]
109
+ elif "chat" in keywords or "message" in keywords:
110
+ return ui_templates["chat"]
111
+ else:
112
+ return ui_templates["data"]
113
+
114
+ class UIArena:
115
+ def __init__(self):
116
+ self.votes: Dict[str, int] = {"LLM 1": 0, "LLM 2": 0, "Tie": 0}
117
+ self.current_comparison: Optional[Tuple[str, str]] = None
118
+
119
+ def generate_comparison(self, prompt: str) -> Tuple[str, str, str]:
120
+ """Generate UI code from both LLMs and update comparison"""
121
+ ui1_code = generate_ui_llm1(prompt)
122
+ ui2_code = generate_ui_llm2(prompt)
123
+
124
+ self.current_comparison = (ui1_code, ui2_code)
125
+
126
+ # Create visual previews (simplified for demonstration)
127
+ preview1 = self.create_preview(ui1_code, "LLM 1")
128
+ preview2 = self.create_preview(ui2_code, "LLM 2")
129
+
130
+ return preview1, preview2, f"Comparison generated for: '{prompt}'"
131
+
132
+ def create_preview(self, ui_code: str, llm_name: str) -> str:
133
+ """Create a visual preview of the UI code"""
134
+ return f"""
135
+ ### {llm_name} Generated UI
136
+
137
+ {ui_code}
138
+ **Style Analysis:**
139
+ - Components: {ui_code.count('gr.') - ui_code.count('gr.Blocks')}
140
+ - Layout: {'Row & Column' if 'Row' in ui_code and 'Column' in ui_code else 'Single Column'}
141
+ - Variants: {'Yes' if 'variant=' in ui_code else 'No'}
142
+ """
143
+
144
+ def vote(self, choice: str) -> Tuple[str, str, str]:
145
+ """Register a vote"""
146
+ if choice in self.votes:
147
+ self.votes[choice] += 1
148
+
149
+ total_votes = sum(self.votes.values())
150
+ if total_votes == 0:
151
+ stats_text = "No votes yet"
152
+ else:
153
+ stats_text = "## Voting Results\n\n"
154
+ for model, votes in self.votes.items():
155
+ percentage = (votes / total_votes) * 100
156
+ stats_text += f"**{model}**: {votes} votes ({percentage:.1f}%)\n"
157
+
158
+ return f"Voted for {choice}!", stats_text, ""
159
+
160
+ def get_stats(self) -> str:
161
+ """Get current voting statistics"""
162
+ total_votes = sum(self.votes.values())
163
+ if total_votes == 0:
164
+ return "No votes recorded yet. Generate a comparison and vote!"
165
+
166
+ stats = "## 📊 UI Arena Statistics\n\n"
167
+ for model, votes in self.votes.items():
168
+ percentage = (votes / total_votes) * 100
169
+ bar_length = int(percentage / 5)
170
+ bar = "█" * bar_length + "░" * (20 - bar_length)
171
+ stats += f"**{model}**: {votes} votes ({percentage:.1f}%)\n"
172
+ stats += f"`{bar}`\n\n"
173
+
174
+ stats += f"**Total Votes**: {total_votes}\n"
175
+
176
+ if total_votes > 0:
177
+ winner = max(self.votes, key=self.votes.get)
178
+ if self.votes[winner] == max(self.votes.values()):
179
+ stats += f"**Current Leader**: {winner}"
180
+
181
+ return stats
182
+
183
+ def reset_arena(self) -> Tuple[str, str, str, str]:
184
+ """Reset the arena"""
185
+ self.votes = {"LLM 1": 0, "LLM 2": 0, "Tie": 0}
186
+ self.current_comparison = None
187
+ return "", "", "Arena reset. Ready for new comparisons!", self.get_stats()
188
+
189
+ # Initialize arena
190
+ arena = UIArena()
191
+
192
+ def create_demo():
193
+ """Create the main demo interface"""
194
+
195
+ # Custom CSS for better layout
196
+ custom_css = """
197
+ .arena-container {
198
+ border: 2px solid #e0e0e0;
199
+ border-radius: 10px;
200
+ padding: 20px;
201
+ margin: 10px;
202
+ }
203
+ .comparison-box {
204
+ min-height: 400px;
205
+ border: 1px solid #d0d0d0;
206
+ border-radius: 8px;
207
+ padding: 15px;
208
+ background: #f9f9f9;
209
+ }
210
+ .vote-button {
211
+ margin: 5px;
212
+ min-width: 120px;
213
+ }
214
+ """
215
+
216
+ with gr.Blocks() as demo:
217
+ gr.HTML("""
218
+ <div style='text-align: center; margin-bottom: 20px;'>
219
+ <h1>🏟️ UI Arena</h1>
220
+ <p>Compare UIs generated by two different LLMs side by side</p>
221
+ <p><a href='https://huggingface.co/spaces/akhaliq/anycoder' target='_blank'>Built with anycoder</a></p>
222
+ </div>
223
+ """)
224
+
225
+ with gr.Row():
226
+ with gr.Column(scale=2):
227
+ gr.Markdown("## 🎯 Generate Comparison")
228
+
229
+ with gr.Row():
230
+ prompt_input = gr.Textbox(
231
+ label="UI Description Prompt",
232
+ placeholder="Describe the UI you want to generate (e.g., 'Create a user registration form', 'Build a metrics dashboard')",
233
+ lines=2
234
+ )
235
+
236
+ with gr.Row():
237
+ generate_btn = gr.Button("🚀 Generate UIs", variant="primary", scale=2)
238
+ reset_btn = gr.Button("🔄 Reset Arena", variant="secondary", scale=1)
239
+
240
+ status_output = gr.Textbox(label="Status", interactive=False)
241
+
242
+ with gr.Column(scale=1):
243
+ gr.Markdown("## 📈 Live Statistics")
244
+ stats_display = gr.Markdown(arena.get_stats())
245
+
246
+ gr.Markdown("---")
247
+
248
+ with gr.Row():
249
+ gr.Markdown("## 🔬 Side-by-Side Comparison", elem_classes="arena-container")
250
+
251
+ with gr.Row():
252
+ with gr.Column():
253
+ gr.Markdown("### LLM 1 Output", elem_id="llm1-header")
254
+ ui1_output = gr.Markdown(
255
+ "Waiting for generation...",
256
+ elem_classes=["comparison-box"]
257
+ )
258
+
259
+ with gr.Column():
260
+ gr.Markdown("### LLM 2 Output", elem_id="llm2-header")
261
+ ui2_output = gr.Markdown(
262
+ "Waiting for generation...",
263
+ elem_classes=["comparison-box"]
264
+ )
265
+
266
+ with gr.Row():
267
+ gr.Markdown("## 🗳️ Vote for Your Favorite")
268
+
269
+ with gr.Row():
270
+ vote_status = gr.Textbox(label="Vote Status", interactive=False)
271
+
272
+ with gr.Row():
273
+ with gr.Column():
274
+ vote_llm1_btn = gr.Button("👍 Vote for LLM 1", variant="primary", elem_classes=["vote-button"])
275
+
276
+ with gr.Column():
277
+ vote_tie_btn = gr.Button("🤝 It's a Tie", variant="secondary", elem_classes=["vote-button"])
278
+
279
+ with gr.Column():
280
+ vote_llm2_btn = gr.Button("👍 Vote for LLM 2", variant="primary", elem_classes=["vote-button"])
281
+
282
+ # Event handlers
283
+ generate_btn.click(
284
+ fn=arena.generate_comparison,
285
+ inputs=[prompt_input],
286
+ outputs=[ui1_output, ui2_output, status_output]
287
+ ).then(
288
+ fn=arena.get_stats,
289
+ outputs=[stats_display]
290
+ )
291
+
292
+ reset_btn.click(
293
+ fn=arena.reset_arena,
294
+ outputs=[ui1_output, ui2_output, status_output, stats_display]
295
+ )
296
+
297
+ vote_llm1_btn.click(
298
+ fn=lambda: arena.vote("LLM 1"),
299
+ outputs=[vote_status, stats_display, ui1_output]
300
+ )
301
+
302
+ vote_llm2_btn.click(
303
+ fn=lambda: arena.vote("LLM 2"),
304
+ outputs=[vote_status, stats_display, ui2_output]
305
+ )
306
+
307
+ vote_tie_btn.click(
308
+ fn=lambda: arena.vote("Tie"),
309
+ outputs=[vote_status, stats_display, ui1_output]
310
+ )
311
+
312
+ # Auto-refresh stats periodically
313
+ timer = gr.Timer(2)
314
+ timer.tick(fn=arena.get_stats, outputs=[stats_display])
315
+
316
+ return demo
317
+
318
+ # Create and launch the demo
319
+ if __name__ == "__main__":
320
+ demo = create_demo()
321
+ demo.launch(
322
+ theme=gr.themes.Soft(
323
+ primary_hue="blue",
324
+ secondary_hue="indigo",
325
+ neutral_hue="slate",
326
+ text_size="lg",
327
+ spacing_size="lg",
328
+ radius_size="md"
329
+ ),
330
+ css="""
331
+ .arena-container {
332
+ border: 2px solid #e0e0e0;
333
+ border-radius: 10px;
334
+ padding: 20px;
335
+ margin: 10px;
336
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
337
+ color: white;
338
+ }
339
+ .comparison-box {
340
+ min-height: 400px;
341
+ border: 1px solid #d0d0d0;
342
+ border-radius: 8px;
343
+ padding: 15px;
344
+ background: #f8f9fa;
345
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
346
+ }
347
+ .vote-button {
348
+ margin: 5px;
349
+ min-width: 120px;
350
+ transition: all 0.3s ease;
351
+ }
352
+ .vote-button:hover {
353
+ transform: translateY(-2px);
354
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
355
+ }
356
+ """,
357
+ footer_links=[
358
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
359
+ ]
360
+ )
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=6.0
2
+ requests
3
+ Pillow
utils.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import time
3
+ from typing import Dict, List, Tuple, Optional
4
+
5
+ def analyze_ui_code(ui_code: str) -> Dict[str, any]:
6
+ """Analyze UI code and extract metrics"""
7
+ return {
8
+ "components": ui_code.count('gr.') - ui_code.count('gr.Blocks'),
9
+ "has_rows": 'Row' in ui_code,
10
+ "has_columns": 'Column' in ui_code,
11
+ "has_variants": 'variant=' in ui_code,
12
+ "has_interactive_elements": any(comp in ui_code for comp in ['Button', 'Textbox', 'Slider', 'Dropdown']),
13
+ "code_lines": len(ui_code.split('\n')),
14
+ "complexity": "High" if ui_code.count('gr.') > 10 else "Medium" if ui_code.count('gr.') > 5 else "Low"
15
+ }
16
+
17
+ def get_style_tips(ui_code: str) -> List[str]:
18
+ """Generate style improvement tips based on UI code"""
19
+ tips = []
20
+
21
+ if 'Row' not in ui_code and 'Column' not in ui_code:
22
+ tips.append("Consider using Rows and Columns for better layout organization")
23
+
24
+ if 'variant=' not in ui_code and 'Button' in ui_code:
25
+ tips.append("Add variants to buttons for visual hierarchy")
26
+
27
+ if 'info=' not in ui_code and 'Textbox' in ui_code:
28
+ tips.append("Add info text to input components for better UX")
29
+
30
+ if ui_code.count('gr.') < 5:
31
+ tips.append("Add more components for a richer interface")
32
+
33
+ return tips
34
+
35
+ def simulate_llm_response_time(model_name: str) -> float:
36
+ """Simulate different response times for different LLMs"""
37
+ base_times = {"LLM 1": 0.5, "LLM 2": 0.7}
38
+ return base_times.get(model_name, 0.6) + random.uniform(-0.1, 0.2)
39
+
40
+ def generate_comparison_insights(ui1_code: str, ui2_code: str) -> str:
41
+ """Generate insights comparing two UI codes"""
42
+ analysis1 = analyze_ui_code(ui1_code)
43
+ analysis2 = analyze_ui_code(ui2_code)
44
+
45
+ insights = "## 🔍 Comparison Insights\n\n"
46
+
47
+ if analysis1["components"] > analysis2["components"]:
48
+ insights += f"• LLM 1 created a more complex UI with {analysis1['components']} components vs {analysis2['components']}\n"
49
+ elif analysis2["components"] > analysis1["components"]:
50
+ insights += f"• LLM 2 created a more complex UI with {analysis2['components']} components vs {analysis1['components']}\n"
51
+ else:
52
+ insights += f"• Both LLMs created UIs with {analysis1['components']} components\n"
53
+
54
+ if analysis1["has_rows"] and analysis1["has_columns"]:
55
+ insights += "• LLM 1 uses advanced layout with Rows and Columns\n"
56
+
57
+ if analysis2["has_rows"] and analysis2["has_columns"]:
58
+ insights += "• LLM 2 uses advanced layout with Rows and Columns\n"
59
+
60
+ if analysis1["complexity"] != analysis2["complexity"]:
61
+ insights += f"• Complexity difference: LLM 1 ({analysis1['complexity']}) vs LLM 2 ({analysis2['complexity']})\n"
62
+
63
+ return insights