shukdevdatta123 commited on
Commit
70115e6
Β·
verified Β·
1 Parent(s): d832884

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -35
app.py CHANGED
@@ -2,8 +2,9 @@ import gradio as gr
2
  import os
3
  from openai import OpenAI
4
  import time
 
5
 
6
- def solve_competitive_problem(problem_statement, language_choice, api_key, progress=gr.Progress()):
7
  """
8
  Generate a solution for a competitive programming problem
9
 
@@ -11,6 +12,7 @@ def solve_competitive_problem(problem_statement, language_choice, api_key, progr
11
  problem_statement (str): The problem statement
12
  language_choice (str): Programming language for the solution
13
  api_key (str): OpenRouter API key
 
14
  progress: Gradio progress tracker
15
 
16
  Returns:
@@ -36,49 +38,41 @@ def solve_competitive_problem(problem_statement, language_choice, api_key, progr
36
  # Create a more detailed prompt with language preference
37
  prompt = f"""
38
  You are an expert competitive programmer. Analyze the following problem and provide a step-by-step solution with explanations and code in {language_choice}.
39
-
40
  Problem:
41
  {problem_statement}
42
-
43
  Your response should include:
44
-
45
  1. Problem Analysis:
46
  - Clear restatement of the problem in your own words
47
  - Identification of input/output formats
48
  - Key constraints and edge cases to consider
49
  - Time and space complexity requirements
50
-
51
  2. Approach:
52
  - High-level strategy to solve the problem
53
  - Why this approach is optimal compared to alternatives
54
  - Any mathematical insights or observations
55
  - Data structures that will be helpful
56
-
57
  3. Algorithm:
58
  - Detailed step-by-step breakdown of the algorithm
59
  - Clear explanation of the logic behind each step
60
  - Time complexity analysis with justification
61
  - Space complexity analysis with justification
62
  - Any optimizations made to improve performance
63
-
64
  4. Implementation:
65
  - Clean, efficient, and well-commented {language_choice} code
66
  - Proper variable naming and code organization
67
  - Error handling and edge case management
68
  - Optimized for both readability and performance
69
-
70
  5. Testing:
71
  - Example test cases with expected outputs
72
  - Edge case testing scenarios
73
  - Explanation of how to verify correctness
74
  - Potential areas where the solution might need improvement
75
-
76
  Format your answer with clear headings and subheadings. Use markdown formatting for better readability.
77
  """
78
 
79
  progress(0.5, "Generating solution...")
80
 
81
- # Call the model
82
  completion = client.chat.completions.create(
83
  extra_headers={
84
  "HTTP-Referer": "https://competitive-programming-assistant.app",
@@ -92,12 +86,17 @@ Format your answer with clear headings and subheadings. Use markdown formatting
92
  }
93
  ],
94
  temperature=0.7,
95
- stream=False
96
  )
97
 
98
- progress(0.9, "Processing response...")
99
-
100
- solution = completion.choices[0].message.content
 
 
 
 
 
101
 
102
  progress(1.0, "Complete!")
103
  return solution
@@ -105,27 +104,142 @@ Format your answer with clear headings and subheadings. Use markdown formatting
105
  except Exception as e:
106
  return f"Error: {str(e)}"
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  # Create a Gradio interface
109
- with gr.Blocks(title="Competitive Programming Assistant", theme=gr.themes.Soft()) as app:
110
- gr.Markdown("""
111
- # πŸ† Competitive Programming Assistant
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- Upload a problem statement from Codeforces, LeetCode, or any competitive programming platform to get:
114
- - Step-by-step analysis
115
- - Optimal solution approach
116
- - Complete code implementation
117
- - Time and space complexity analysis
 
118
 
119
- Powered by the OlympicCoder model.
 
 
 
 
 
 
 
 
120
  """)
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  with gr.Row():
123
- with gr.Column(scale=2):
124
- api_key_input = gr.Textbox(
125
- placeholder="Enter your OpenRouter API key here",
126
- label="OpenRouter API Key",
127
- type="password"
128
- )
 
 
 
 
 
 
 
129
 
130
  problem_input = gr.Textbox(
131
  placeholder="Paste your competitive programming problem statement here...",
@@ -139,11 +253,12 @@ with gr.Blocks(title="Competitive Programming Assistant", theme=gr.themes.Soft()
139
  label="Programming Language"
140
  )
141
 
142
- submit_btn = gr.Button("Generate Solution", variant="primary")
143
 
144
- with gr.Column(scale=3):
145
  solution_output = gr.Markdown(
146
- label="Generated Solution"
 
147
  )
148
 
149
  with gr.Accordion("About", open=False):
@@ -171,12 +286,80 @@ with gr.Blocks(title="Competitive Programming Assistant", theme=gr.themes.Soft()
171
  5. **Testing** - Example test cases and verification methods
172
  """)
173
 
174
- # Handle form submission
 
 
 
 
 
 
 
 
 
 
 
175
  submit_btn.click(
176
  solve_competitive_problem,
177
- inputs=[problem_input, language, api_key_input],
178
- outputs=solution_output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  # Launch the app
182
  if __name__ == "__main__":
 
2
  import os
3
  from openai import OpenAI
4
  import time
5
+ import json
6
 
7
+ def solve_competitive_problem(problem_statement, language_choice, api_key, remember_api_key, progress=gr.Progress()):
8
  """
9
  Generate a solution for a competitive programming problem
10
 
 
12
  problem_statement (str): The problem statement
13
  language_choice (str): Programming language for the solution
14
  api_key (str): OpenRouter API key
15
+ remember_api_key (bool): Whether to remember the API key
16
  progress: Gradio progress tracker
17
 
18
  Returns:
 
38
  # Create a more detailed prompt with language preference
39
  prompt = f"""
40
  You are an expert competitive programmer. Analyze the following problem and provide a step-by-step solution with explanations and code in {language_choice}.
 
41
  Problem:
42
  {problem_statement}
 
43
  Your response should include:
 
44
  1. Problem Analysis:
45
  - Clear restatement of the problem in your own words
46
  - Identification of input/output formats
47
  - Key constraints and edge cases to consider
48
  - Time and space complexity requirements
 
49
  2. Approach:
50
  - High-level strategy to solve the problem
51
  - Why this approach is optimal compared to alternatives
52
  - Any mathematical insights or observations
53
  - Data structures that will be helpful
 
54
  3. Algorithm:
55
  - Detailed step-by-step breakdown of the algorithm
56
  - Clear explanation of the logic behind each step
57
  - Time complexity analysis with justification
58
  - Space complexity analysis with justification
59
  - Any optimizations made to improve performance
 
60
  4. Implementation:
61
  - Clean, efficient, and well-commented {language_choice} code
62
  - Proper variable naming and code organization
63
  - Error handling and edge case management
64
  - Optimized for both readability and performance
 
65
  5. Testing:
66
  - Example test cases with expected outputs
67
  - Edge case testing scenarios
68
  - Explanation of how to verify correctness
69
  - Potential areas where the solution might need improvement
 
70
  Format your answer with clear headings and subheadings. Use markdown formatting for better readability.
71
  """
72
 
73
  progress(0.5, "Generating solution...")
74
 
75
+ # Call the model with streaming enabled
76
  completion = client.chat.completions.create(
77
  extra_headers={
78
  "HTTP-Referer": "https://competitive-programming-assistant.app",
 
86
  }
87
  ],
88
  temperature=0.7,
89
+ stream=True # Enable streaming for partial results
90
  )
91
 
92
+ # Process streaming response
93
+ solution = ""
94
+ for chunk in completion:
95
+ if chunk.choices[0].delta.content is not None:
96
+ solution += chunk.choices[0].delta.content
97
+ # Update progress and yield partial results
98
+ progress(0.5 + (len(solution) % 500) / 1000, "Generating solution...")
99
+ yield solution
100
 
101
  progress(1.0, "Complete!")
102
  return solution
 
104
  except Exception as e:
105
  return f"Error: {str(e)}"
106
 
107
+ def get_saved_api_key():
108
+ """
109
+ Return a JavaScript snippet that retrieves the saved API key from localStorage
110
+ """
111
+ return """
112
+ function() {
113
+ const savedKey = localStorage.getItem('openrouter_api_key');
114
+ if (savedKey) {
115
+ document.querySelector('#api_key_input input').value = savedKey;
116
+ document.querySelector('#remember_api_key input').checked = true;
117
+ }
118
+ }
119
+ """
120
+
121
+ def save_api_key(api_key, remember):
122
+ """
123
+ Return a JavaScript snippet that saves or removes the API key from localStorage
124
+ """
125
+ return f"""
126
+ function() {{
127
+ if ({str(remember).lower()}) {{
128
+ localStorage.setItem('openrouter_api_key', "{api_key}");
129
+ }} else {{
130
+ localStorage.removeItem('openrouter_api_key');
131
+ }}
132
+ }}
133
+ """
134
+
135
+ # Define theme options
136
+ light_theme = gr.themes.Soft()
137
+ dark_theme = gr.themes.Soft(
138
+ primary_hue="slate",
139
+ secondary_hue="slate",
140
+ neutral_hue="slate",
141
+ text_size=gr.themes.sizes.text_md,
142
+ )
143
+
144
  # Create a Gradio interface
145
+ with gr.Blocks(title="Competitive Programming Assistant", theme=light_theme, css="""
146
+ /* Custom CSS for better responsiveness and styling */
147
+ @media (max-width: 768px) {
148
+ .container { padding: 10px !important; }
149
+ .responsive-padding { padding: 8px !important; }
150
+ }
151
+ .code-block {
152
+ background-color: #f7f7f7;
153
+ border-radius: 4px;
154
+ padding: 10px;
155
+ font-family: monospace;
156
+ }
157
+ .dark-mode .code-block {
158
+ background-color: #2d2d2d;
159
+ color: #f1f1f1;
160
+ }
161
+ /* Custom styling for buttons */
162
+ .action-button {
163
+ margin-top: 10px !important;
164
+ }
165
+ """) as app:
166
+ # JavaScript for theme toggling
167
+ app.load(js="""
168
+ function setupThemeToggle() {
169
+ const themeToggle = document.getElementById('theme-toggle-btn');
170
+ const savedTheme = localStorage.getItem('theme');
171
+
172
+ if (savedTheme === 'dark') {
173
+ document.body.classList.add('dark-mode');
174
+ themeToggle.textContent = 'β˜€οΈ Light Mode';
175
+ }
176
+
177
+ themeToggle.addEventListener('click', function() {
178
+ document.body.classList.toggle('dark-mode');
179
+ const isDark = document.body.classList.contains('dark-mode');
180
+ localStorage.setItem('theme', isDark ? 'dark' : 'light');
181
+ themeToggle.textContent = isDark ? 'β˜€οΈ Light Mode' : 'πŸŒ™ Dark Mode';
182
+
183
+ // Update code block styling
184
+ document.querySelectorAll('pre code').forEach(block => {
185
+ if (isDark) {
186
+ block.style.backgroundColor = '#2d2d2d';
187
+ block.style.color = '#f1f1f1';
188
+ } else {
189
+ block.style.backgroundColor = '#f7f7f7';
190
+ block.style.color = '#333';
191
+ }
192
+ });
193
+ });
194
+ }
195
 
196
+ // Initialize syntax highlighting
197
+ function setupPrism() {
198
+ if (typeof Prism !== 'undefined') {
199
+ Prism.highlightAll();
200
+ }
201
+ }
202
 
203
+ // Apply saved API key on load
204
+ document.addEventListener('DOMContentLoaded', function() {
205
+ setupThemeToggle();
206
+ const savedKey = localStorage.getItem('openrouter_api_key');
207
+ if (savedKey) {
208
+ document.querySelector('#api_key_input input').value = savedKey;
209
+ document.querySelector('#remember_api_key input').checked = true;
210
+ }
211
+ });
212
  """)
213
 
214
+ # App header with theme toggle
215
+ with gr.Row(elem_classes="responsive-padding"):
216
+ gr.Markdown("""
217
+ # πŸ† Competitive Programming Assistant
218
+
219
+ Upload a problem statement from Codeforces, LeetCode, or any competitive programming platform to get:
220
+ - Step-by-step analysis
221
+ - Optimal solution approach
222
+ - Complete code implementation
223
+ - Time and space complexity analysis
224
+
225
+ Powered by the OlympicCoder model.
226
+ """)
227
+ theme_btn = gr.Button("πŸŒ™ Dark Mode", elem_id="theme-toggle-btn")
228
+
229
  with gr.Row():
230
+ with gr.Column(scale=2, elem_classes="responsive-padding"):
231
+ with gr.Group():
232
+ api_key_input = gr.Textbox(
233
+ placeholder="Enter your OpenRouter API key here",
234
+ label="OpenRouter API Key",
235
+ type="password",
236
+ elem_id="api_key_input"
237
+ )
238
+
239
+ remember_api_key = gr.Checkbox(
240
+ label="Remember my API key",
241
+ elem_id="remember_api_key"
242
+ )
243
 
244
  problem_input = gr.Textbox(
245
  placeholder="Paste your competitive programming problem statement here...",
 
253
  label="Programming Language"
254
  )
255
 
256
+ submit_btn = gr.Button("Generate Solution", variant="primary", elem_classes="action-button")
257
 
258
+ with gr.Column(scale=3, elem_classes="responsive-padding"):
259
  solution_output = gr.Markdown(
260
+ label="Generated Solution",
261
+ elem_id="solution-output"
262
  )
263
 
264
  with gr.Accordion("About", open=False):
 
286
  5. **Testing** - Example test cases and verification methods
287
  """)
288
 
289
+ # Load saved API key on page load
290
+ app.load(fn=None, inputs=None, outputs=None, js=get_saved_api_key())
291
+
292
+ # Handle API key saving when checkbox changes
293
+ remember_api_key.change(
294
+ fn=None,
295
+ inputs=[api_key_input, remember_api_key],
296
+ outputs=None,
297
+ js=lambda api_key, remember: save_api_key(api_key, remember)
298
+ )
299
+
300
+ # Handle form submission with streaming
301
  submit_btn.click(
302
  solve_competitive_problem,
303
+ inputs=[problem_input, language, api_key_input, remember_api_key],
304
+ outputs=solution_output,
305
+ js="""
306
+ function(problem, language, api_key, remember) {
307
+ // Before submission, save API key if requested
308
+ if (remember) {
309
+ localStorage.setItem('openrouter_api_key', api_key);
310
+ }
311
+
312
+ // Clear existing solution
313
+ document.getElementById('solution-output').innerHTML = 'Generating solution...';
314
+
315
+ // Enable syntax highlighting when solution loads
316
+ setTimeout(function() {
317
+ if (typeof Prism !== 'undefined') {
318
+ Prism.highlightAll();
319
+ }
320
+ }, 1000);
321
+ }
322
+ """
323
  )
324
+
325
+ # Add JS for syntax highlighting
326
+ app.load(js="""
327
+ // Load Prism.js for syntax highlighting
328
+ const prismScript = document.createElement('script');
329
+ prismScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/prism.min.js';
330
+ document.head.appendChild(prismScript);
331
+
332
+ const prismCss = document.createElement('link');
333
+ prismCss.rel = 'stylesheet';
334
+ prismCss.href = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/themes/prism.min.css';
335
+ document.head.appendChild(prismCss);
336
+
337
+ // Load additional language support
338
+ const languages = ['python', 'cpp', 'java', 'javascript'];
339
+ languages.forEach(lang => {
340
+ const script = document.createElement('script');
341
+ script.src = `https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/components/prism-${lang}.min.js`;
342
+ document.head.appendChild(script);
343
+ });
344
+
345
+ // Observe DOM changes to apply syntax highlighting to new content
346
+ const observer = new MutationObserver(mutations => {
347
+ mutations.forEach(mutation => {
348
+ if (mutation.addedNodes.length) {
349
+ setTimeout(() => {
350
+ if (typeof Prism !== 'undefined') {
351
+ Prism.highlightAll();
352
+ }
353
+ }, 100);
354
+ }
355
+ });
356
+ });
357
+
358
+ observer.observe(document.getElementById('solution-output'), {
359
+ childList: true,
360
+ subtree: true
361
+ });
362
+ """)
363
 
364
  # Launch the app
365
  if __name__ == "__main__":