SHAH-MEER commited on
Commit
470233e
Β·
verified Β·
1 Parent(s): ca686f2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +514 -0
app.py ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from openai import OpenAI
3
+ import anthropic
4
+ import gradio as gr
5
+
6
+ # ENVIRONMENT - Modified for Hugging Face Spaces
7
+ open_api_key = os.getenv('OPENAI_API_KEY')
8
+ anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')
9
+ deepseek_api_key = os.getenv('DEEPSEEK_API_KEY')
10
+
11
+ # Initialize clients with error handling
12
+ try:
13
+ openai = OpenAI(api_key=open_api_key) if open_api_key else None
14
+ claude = anthropic.Anthropic(api_key=anthropic_api_key) if anthropic_api_key else None
15
+ deepseek = OpenAI(api_key=deepseek_api_key, base_url="https://api.deepseek.com/v1") if deepseek_api_key else None
16
+ except Exception as e:
17
+ print(f"Warning: API client initialization failed: {e}")
18
+ openai = claude = deepseek = None
19
+
20
+ OPENAI_MODEL = "gpt-4o-mini"
21
+ CLAUDE_MODEL = "claude-3-haiku-20240307"
22
+ DEEPSEEK_MODEL = 'deepseek-coder'
23
+
24
+ system_message = (
25
+ "You are an assistant that adds docstrings to functions and comments to code where necessary. "
26
+ "Do not modify the code itself β€” only add docstrings and explanatory comments. "
27
+ "The functionality of the code must remain exactly the same. "
28
+ "Do not explain your reasoning or what additions you made β€” just add docstrings and comments to the code. "
29
+ "Return only the modified version of the code, with no extra explanations or comments beyond what was asked."
30
+ )
31
+
32
+ def user_prompt_for(code):
33
+ user_prompt = (
34
+ "Add comments to the following code.\n"
35
+ "DO NOT change the functionality of the code.\n\n"
36
+ f"{code}"
37
+ )
38
+ return user_prompt
39
+
40
+ def messages_for(code):
41
+ return [
42
+ {"role": "system", "content": system_message},
43
+ {"role": "user", "content": user_prompt_for(code)}
44
+ ]
45
+
46
+ def stream_gpt(code):
47
+ if not openai:
48
+ yield "Error: OpenAI API key not configured. Please add OPENAI_API_KEY to the Space secrets."
49
+ return
50
+
51
+ try:
52
+ stream = openai.chat.completions.create(
53
+ model=OPENAI_MODEL,
54
+ messages=messages_for(code),
55
+ stream=True
56
+ )
57
+ result = ''
58
+ for chunk in stream:
59
+ fragment = chunk.choices[0].delta.content or ""
60
+ result += fragment
61
+ yield result.replace('```python\n','').replace('```','')
62
+ except Exception as e:
63
+ yield f"Error with OpenAI API: {str(e)}"
64
+
65
+ def stream_deepseek(code):
66
+ if not deepseek:
67
+ yield "Error: DeepSeek API key not configured. Please add DEEPSEEK_API_KEY to the Space secrets."
68
+ return
69
+
70
+ try:
71
+ stream = deepseek.chat.completions.create(
72
+ model=DEEPSEEK_MODEL,
73
+ messages=messages_for(code),
74
+ stream=True
75
+ )
76
+ result = ''
77
+ for chunk in stream:
78
+ fragment = chunk.choices[0].delta.content or ""
79
+ result += fragment
80
+ yield result.replace('```python\n','').replace('```','')
81
+ except Exception as e:
82
+ yield f"Error with DeepSeek API: {str(e)}"
83
+
84
+ def stream_claude(code):
85
+ if not claude:
86
+ yield "Error: Anthropic API key not configured. Please add ANTHROPIC_API_KEY to the Space secrets."
87
+ return
88
+
89
+ try:
90
+ result = claude.messages.stream(
91
+ model=CLAUDE_MODEL,
92
+ max_tokens=2000,
93
+ system=system_message,
94
+ messages=[{"role": "user", "content": user_prompt_for(code)}]
95
+ )
96
+ reply = ''
97
+ with result as stream:
98
+ for text in stream.text_stream:
99
+ reply += text
100
+ yield reply.replace('```python\n','').replace('```','')
101
+ except Exception as e:
102
+ yield f"Error with Claude API: {str(e)}"
103
+
104
+ python_hard = """
105
+ def lcg(seed, a=1664525, c=1013904223, m=2**32):
106
+ value = seed
107
+ while True:
108
+ value = (a * value + c) % m
109
+ yield value
110
+
111
+ def max_subarray_sum(n, seed, min_val, max_val):
112
+ lcg_gen = lcg(seed)
113
+ random_numbers = [next(lcg_gen) % (max_val - min_val + 1) + min_val for _ in range(n)]
114
+ max_sum = float('-inf')
115
+ for i in range(n):
116
+ current_sum = 0
117
+ for j in range(i, n):
118
+ current_sum += random_numbers[j]
119
+ if current_sum > max_sum:
120
+ max_sum = current_sum
121
+ return max_sum
122
+
123
+ def total_max_subarray_sum(n, initial_seed, min_val, max_val):
124
+ total_sum = 0
125
+ lcg_gen = lcg(initial_seed)
126
+ for _ in range(20):
127
+ seed = next(lcg_gen)
128
+ total_sum += max_subarray_sum(n, seed, min_val, max_val)
129
+ return total_sum
130
+
131
+ # Parameters
132
+ n = 10000 # Number of random numbers
133
+ initial_seed = 42 # Initial seed for the LCG
134
+ min_val = -10 # Minimum value of random numbers
135
+ max_val = 10 # Maximum value of random numbers
136
+
137
+ # Timing the function
138
+ import time
139
+ start_time = time.time()
140
+ result = total_max_subarray_sum(n, initial_seed, min_val, max_val)
141
+ end_time = time.time()
142
+
143
+ print("Total Maximum Subarray Sum (20 runs):", result)
144
+ print("Execution Time: {:.6f} seconds".format(end_time - start_time))
145
+ """
146
+
147
+ def docstring(python, model):
148
+ if model=="GPT":
149
+ result = stream_gpt(python)
150
+ elif model=="Claude":
151
+ result = stream_claude(python)
152
+ elif model == "DeepSeek":
153
+ result = stream_deepseek(python)
154
+ else:
155
+ yield "Error: Unknown model selected"
156
+ return
157
+
158
+ for stream_so_far in result:
159
+ yield stream_so_far
160
+
161
+ system_message_unit_test = (
162
+ "You are an assistant that generates Python unit test code for the given code. "
163
+ "Do not modify the original code β€” only write test cases that thoroughly cover the functionality. "
164
+ "Use the standard unittest framework syntax. "
165
+ "Return only the test code, no explanations or additional text. "
166
+ "The tests should be clear, concise, and runnable as-is."
167
+ )
168
+
169
+ def user_prompt_unit_test(code: str) -> str:
170
+ return (
171
+ "Write Python unit tests for the following code using the unittest module. "
172
+ "Do not change the original code. Only add test cases to verify its behavior.\n\n"
173
+ f"{code}"
174
+ )
175
+
176
+ def messages_for_test(code):
177
+ return [
178
+ {"role": "system", "content": system_message_unit_test},
179
+ {"role": "user", "content": user_prompt_unit_test(code)}
180
+ ]
181
+
182
+ def stream_gpt_test(code):
183
+ if not openai:
184
+ yield "Error: OpenAI API key not configured. Please add OPENAI_API_KEY to the Space secrets."
185
+ return
186
+
187
+ try:
188
+ stream = openai.chat.completions.create(
189
+ model=OPENAI_MODEL,
190
+ messages=messages_for_test(code),
191
+ stream=True
192
+ )
193
+ result = ''
194
+ for chunk in stream:
195
+ fragment = chunk.choices[0].delta.content or ""
196
+ result += fragment
197
+ yield result.replace('```python\n','').replace('```','')
198
+ except Exception as e:
199
+ yield f"Error with OpenAI API: {str(e)}"
200
+
201
+ def stream_deepseek_test(code):
202
+ if not deepseek:
203
+ yield "Error: DeepSeek API key not configured. Please add DEEPSEEK_API_KEY to the Space secrets."
204
+ return
205
+
206
+ try:
207
+ stream = deepseek.chat.completions.create(
208
+ model=DEEPSEEK_MODEL,
209
+ messages=messages_for_test(code),
210
+ stream=True
211
+ )
212
+ result = ''
213
+ for chunk in stream:
214
+ fragment = chunk.choices[0].delta.content or ""
215
+ result += fragment
216
+ yield result.replace('```python\n','').replace('```','')
217
+ except Exception as e:
218
+ yield f"Error with DeepSeek API: {str(e)}"
219
+
220
+ def stream_claude_test(code):
221
+ if not claude:
222
+ yield "Error: Anthropic API key not configured. Please add ANTHROPIC_API_KEY to the Space secrets."
223
+ return
224
+
225
+ try:
226
+ result = claude.messages.stream(
227
+ model=CLAUDE_MODEL,
228
+ max_tokens=2000,
229
+ system=system_message_unit_test,
230
+ messages=[{"role": "user", "content": user_prompt_unit_test(code)}]
231
+ )
232
+ reply = ''
233
+ with result as stream:
234
+ for text in stream.text_stream:
235
+ reply += text
236
+ yield reply.replace('```python\n','').replace('```','')
237
+ except Exception as e:
238
+ yield f"Error with Claude API: {str(e)}"
239
+
240
+ def unit_test(python, model):
241
+ if model=="GPT":
242
+ result = stream_gpt_test(python)
243
+ elif model=="Claude":
244
+ result = stream_claude_test(python)
245
+ elif model == "DeepSeek":
246
+ result = stream_deepseek_test(python)
247
+ else:
248
+ yield "Error: Unknown model selected"
249
+ return
250
+
251
+ for stream_so_far in result:
252
+ yield stream_so_far
253
+
254
+ test_case = """def add(a, b):
255
+ return a + b
256
+
257
+ def divide(a, b):
258
+ if b == 0:
259
+ raise ValueError("Cannot divide by zero")
260
+ return a / b"""
261
+
262
+ system_message_explaio = (
263
+ "You are a helpful assistant that explains Python code in clear, beginner-friendly terms. "
264
+ "Break down the logic, describe the purpose of functions and classes, and clarify complex parts. "
265
+ "Use simple language, bullet points, and examples where appropriate. "
266
+ "Do not modify or rewrite the code. Just explain what it does and how it works."
267
+ )
268
+
269
+ def user_prompt_explaio(code: str) -> str:
270
+ return (
271
+ "Explain the following Python code in simple terms. "
272
+ "Provide an overview of what the code does and explain any functions, loops, or logic used.\n\n"
273
+ f"{code}"
274
+ )
275
+
276
+ def messages_for_explaio(code):
277
+ return [
278
+ {"role": "system", "content": system_message_explaio},
279
+ {"role": "user", "content": user_prompt_explaio(code)}
280
+ ]
281
+
282
+ def stream_gpt_explain(code):
283
+ if not openai:
284
+ yield "Error: OpenAI API key not configured. Please add OPENAI_API_KEY to the Space secrets."
285
+ return
286
+
287
+ try:
288
+ stream = openai.chat.completions.create(
289
+ model=OPENAI_MODEL,
290
+ messages=messages_for_explaio(code),
291
+ stream=True
292
+ )
293
+ result = ''
294
+ for chunk in stream:
295
+ fragment = chunk.choices[0].delta.content or ""
296
+ result += fragment
297
+ yield result.replace('```python\n','').replace('```','')
298
+ except Exception as e:
299
+ yield f"Error with OpenAI API: {str(e)}"
300
+
301
+ def stream_deepseek_explain(code):
302
+ if not deepseek:
303
+ yield "Error: DeepSeek API key not configured. Please add DEEPSEEK_API_KEY to the Space secrets."
304
+ return
305
+
306
+ try:
307
+ stream = deepseek.chat.completions.create(
308
+ model=DEEPSEEK_MODEL,
309
+ messages=messages_for_explaio(code),
310
+ stream=True
311
+ )
312
+ result = ''
313
+ for chunk in stream:
314
+ fragment = chunk.choices[0].delta.content or ""
315
+ result += fragment
316
+ yield result.replace('```python\n','').replace('```','')
317
+ except Exception as e:
318
+ yield f"Error with DeepSeek API: {str(e)}"
319
+
320
+ def stream_claude_explain(code):
321
+ if not claude:
322
+ yield "Error: Anthropic API key not configured. Please add ANTHROPIC_API_KEY to the Space secrets."
323
+ return
324
+
325
+ try:
326
+ result = claude.messages.stream(
327
+ model=CLAUDE_MODEL,
328
+ max_tokens=2000,
329
+ system=system_message_explaio,
330
+ messages=[{"role": "user", "content": user_prompt_explaio(code)}]
331
+ )
332
+ reply = ''
333
+ with result as stream:
334
+ for text in stream.text_stream:
335
+ reply += text
336
+ yield reply.replace('```python\n','').replace('```','')
337
+ except Exception as e:
338
+ yield f"Error with Claude API: {str(e)}"
339
+
340
+ def explain_code(code, model):
341
+ if model=="GPT":
342
+ result = stream_gpt_explain(code)
343
+ elif model=="Claude":
344
+ result = stream_claude_explain(code)
345
+ elif model == "DeepSeek":
346
+ result = stream_deepseek_explain(code)
347
+ else:
348
+ yield "Error: Unknown model selected"
349
+ return
350
+
351
+ for stream_so_far in result:
352
+ yield stream_so_far
353
+
354
+ python_example = """
355
+ class ExpressionError(Exception):
356
+ pass
357
+
358
+ class ExpressionEvaluator:
359
+ def __init__(self, expression):
360
+ self.expression = expression.replace(" ", "")
361
+
362
+ def evaluate(self):
363
+ try:
364
+ return self._evaluate_expression(self.expression)
365
+ except ZeroDivisionError:
366
+ raise ExpressionError("Division by zero is not allowed.")
367
+ except Exception as e:
368
+ raise ExpressionError(f"Invalid expression: {e}")
369
+
370
+ def _evaluate_expression(self, expr):
371
+ if expr.isdigit():
372
+ return int(expr)
373
+
374
+ for op in ['+', '-', '*', '/']:
375
+ depth = 0
376
+ for i in range(len(expr) - 1, -1, -1):
377
+ if expr[i] == ')':
378
+ depth += 1
379
+ elif expr[i] == '(':
380
+ depth -= 1
381
+ elif depth == 0 and expr[i] == op:
382
+ left = self._evaluate_expression(expr[:i])
383
+ right = self._evaluate_expression(expr[i + 1:])
384
+ return self._apply_operator(op, left, right)
385
+
386
+ if expr[0] == '(' and expr[-1] == ')':
387
+ return self._evaluate_expression(expr[1:-1])
388
+
389
+ raise ExpressionError("Malformed expression")
390
+
391
+ def _apply_operator(self, op, a, b):
392
+ if op == '+':
393
+ return a + b
394
+ elif op == '-':
395
+ return a - b
396
+ elif op == '*':
397
+ return a * b
398
+ elif op == '/':
399
+ if b == 0:
400
+ raise ZeroDivisionError()
401
+ return a / b
402
+ else:
403
+ raise ExpressionError(f"Unsupported operator: {op}")
404
+ """
405
+
406
+ MODEL_OPTIONS = ["GPT", "Claude", "DeepSeek"]
407
+
408
+ # Create Gradio interface
409
+ with gr.Blocks(title="Code Assistant", theme=gr.themes.Soft()) as ui:
410
+ gr.Markdown("# πŸ€– Code Assistant")
411
+ gr.Markdown("*Enhance your Python code with AI-powered documentation, testing, and explanations*")
412
+
413
+ # Add API key status information
414
+ with gr.Row():
415
+ api_status = []
416
+ if openai: api_status.append("βœ… OpenAI")
417
+ else: api_status.append("❌ OpenAI")
418
+ if claude: api_status.append("βœ… Claude")
419
+ else: api_status.append("❌ Claude")
420
+ if deepseek: api_status.append("βœ… DeepSeek")
421
+ else: api_status.append("❌ DeepSeek")
422
+
423
+ gr.Markdown(f"**API Status:** {' | '.join(api_status)}")
424
+
425
+ with gr.Tabs():
426
+ # Docstring Adder Tab
427
+ with gr.Tab("πŸ“ DocoBot"):
428
+ gr.Markdown("### Auto-Generate Docstrings & Comments")
429
+ with gr.Row():
430
+ docu_code_input = gr.Code(
431
+ label="Input Code",
432
+ language="python",
433
+ lines=20,
434
+ value=python_hard
435
+ )
436
+ docu_output = gr.Code(
437
+ label="Output Code with Docstrings",
438
+ language="python",
439
+ lines=20,
440
+ interactive=False
441
+ )
442
+ with gr.Row():
443
+ docu_model_select = gr.Dropdown(
444
+ MODEL_OPTIONS,
445
+ value="DeepSeek",
446
+ label="Select Model"
447
+ )
448
+ with gr.Row():
449
+ docu_convert_btn = gr.Button("Add Docstrings", variant="primary")
450
+ docu_clear_btn = gr.Button("Clear")
451
+
452
+ docu_convert_btn.click(
453
+ fn=docstring,
454
+ inputs=[docu_code_input, docu_model_select],
455
+ outputs=[docu_output]
456
+ )
457
+ docu_clear_btn.click(
458
+ fn=lambda: ("", ""),
459
+ inputs=[],
460
+ outputs=[docu_code_input, docu_output]
461
+ )
462
+
463
+ # Unit Test Case Adder Tab
464
+ with gr.Tab("πŸ§ͺ TestoBot"):
465
+ gr.Markdown("### Instantly Add Unit Tests to Your Code")
466
+ with gr.Row():
467
+ test_code_input = gr.Code(
468
+ label="Input Code",
469
+ language="python",
470
+ lines=20,
471
+ value=test_case
472
+ )
473
+ test_output = gr.Code(
474
+ label="Output Code with Unit Tests",
475
+ language="python",
476
+ lines=20,
477
+ interactive=False
478
+ )
479
+ with gr.Row():
480
+ test_model_select = gr.Dropdown(
481
+ MODEL_OPTIONS,
482
+ value="DeepSeek",
483
+ label="Select Model"
484
+ )
485
+ with gr.Row():
486
+ test_convert_btn = gr.Button("Add Unit Tests", variant="primary")
487
+ test_clear_btn = gr.Button("Clear")
488
+
489
+ test_convert_btn.click(
490
+ fn=unit_test,
491
+ inputs=[test_code_input, test_model_select],
492
+ outputs=[test_output]
493
+ )
494
+ test_clear_btn.click(
495
+ fn=lambda: ("", ""),
496
+ inputs=[],
497
+ outputs=[test_code_input, test_output]
498
+ )
499
+
500
+ with gr.Tab("🧠 ExplaioBot"):
501
+ gr.Markdown("### Understand Your Code")
502
+ with gr.Row():
503
+ code = gr.Code(label="Your Code", lines=20, language='python', value=python_example)
504
+ output = gr.Textbox(label="Explanation", lines=35)
505
+ with gr.Row():
506
+ model = gr.Dropdown(["GPT", "Claude", "DeepSeek"], value="DeepSeek", label="Select Model")
507
+ with gr.Row():
508
+ explain_btn = gr.Button("πŸ” Explain Code", variant="primary")
509
+
510
+ explain_btn.click(fn=explain_code, inputs=[code, model], outputs=[output])
511
+
512
+ # Launch the app
513
+ if __name__ == "__main__":
514
+ ui.launch()