Eeppa commited on
Commit
6953393
·
verified ·
1 Parent(s): 0d19d5e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +372 -179
app.py CHANGED
@@ -1,235 +1,428 @@
1
  import gradio as gr
2
- from model_utils import CodeThinkingAssistant
 
3
  import time
 
 
 
4
 
5
- # Initialize the assistant
6
- # IMPORTANT: Replace with your fine-tuned model ID after training
7
- MODEL_ID = "meta-llama/Llama-3.2-1B-Instruct" # CHANGE THIS to your model after fine-tuning
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
- print("🚀 Initializing Llama 3.2 Codex Assistant...")
10
- assistant = CodeThinkingAssistant(MODEL_ID)
11
- print("✅ Ready to help with coding!")
12
 
13
- # Custom CSS for better UI
14
  custom_css = """
15
  <style>
16
- .thinking-mode {
17
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18
- padding: 2px;
19
- border-radius: 10px;
 
20
  }
21
- .fast-mode {
22
- background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
23
- padding: 2px;
24
- border-radius: 10px;
25
  }
26
- .thinking-box {
27
- background-color: #f0f4ff;
28
- border-left: 4px solid #667eea;
29
- padding: 10px;
30
- margin: 10px 0;
31
- border-radius: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  font-family: monospace;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
- .code-box {
35
- background-color: #1e1e1e;
36
- color: #d4d4d4;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  padding: 15px;
38
- border-radius: 5px;
39
- font-family: 'Courier New', monospace;
40
  overflow-x: auto;
 
 
 
41
  }
42
- footer {
43
- visibility: visible;
44
- text-align: center;
45
- margin-top: 20px;
46
- font-size: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
  </style>
49
  """
50
 
51
- def format_code_output(code: str) -> str:
52
- """Format code for display"""
53
- return f'<div class="code-box"><pre>{code}</pre></div>'
54
-
55
- def format_thinking_output(thinking: str) -> str:
56
- """Format thinking process for display"""
57
- return f'<div class="thinking-box">💭 <strong>Thinking process:</strong><br>{thinking}</div>'
58
-
59
- def respond(
60
- message: str,
61
- history: list,
62
- thinking_mode: bool,
63
- reasoning_style: str,
64
- temperature: float,
65
- max_tokens: int
66
- ):
67
- """Main response function for Gradio chat"""
68
-
69
- if not message.strip():
70
- yield "Please enter a coding question or task."
71
- return
72
-
73
- # Show thinking indicator
74
- yield "🤔 Thinking" + "." * 3
75
-
76
- try:
77
- if thinking_mode:
78
- if reasoning_style == "Step-by-step thinking":
79
- result = assistant.generate_with_thinking(
80
- message,
81
- max_thought_tokens=300,
82
- max_code_tokens=max_tokens
83
- )
84
- else: # Chain-of-thought
85
- result = assistant.generate_with_chain_of_thought(message)
86
-
87
- # Format output with both thinking and code
88
- formatted_output = ""
89
- if result.get("thinking"):
90
- formatted_output += format_thinking_output(result["thinking"])
91
- if result.get("code"):
92
- formatted_output += "\n\n" + format_code_output(result["code"])
93
-
94
- yield formatted_output
95
- else:
96
- # Fast mode
97
- code = assistant.generate_fast(message, max_tokens=max_tokens)
98
- yield format_code_output(code)
99
-
100
- except Exception as e:
101
- yield f"❌ Error: {str(e)}\n\nPlease make sure the model is loaded correctly."
102
-
103
- # Build the Gradio interface
104
- with gr.Blocks(css=custom_css, title="Llama 3.2 Codex - AI Coding Assistant") as demo:
105
-
106
  gr.Markdown("""
107
- # 🤖 Llama 3.2 1B Codex
108
 
109
- ### Your AI Pair Programmer with Thinking Mode
 
 
110
 
111
- Built with Llama 3.2 - Specialized for code generation with explicit reasoning.
112
  """)
113
 
114
- with gr.Row():
115
- with gr.Column(scale=2):
116
- # Chat interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  chatbot = gr.Chatbot(
118
- label="Code Assistant",
119
  height=500,
120
  bubble_full_width=False
121
  )
122
 
123
  with gr.Row():
124
  msg = gr.Textbox(
125
- label="Ask for code help",
126
- placeholder="Example: 'Write a function to sort a list of dictionaries by a key' or 'Explain this algorithm...'",
127
- scale=4
 
128
  )
129
  send_btn = gr.Button("Send", variant="primary", scale=1)
130
 
131
  with gr.Row():
132
  clear_btn = gr.Button("Clear Chat")
133
- example_btn = gr.Button("Load Example")
 
 
 
 
 
 
134
 
135
- with gr.Column(scale=1):
136
- gr.Markdown("### ⚙️ Settings")
137
-
138
- thinking_mode = gr.Checkbox(
139
- label="🧠 Enable Thinking Mode",
140
- value=True,
141
- info="Shows reasoning process before generating code"
142
- )
143
-
144
- reasoning_style = gr.Radio(
145
- choices=["Step-by-step thinking", "Chain-of-thought"],
146
- value="Step-by-step thinking",
147
- label="Reasoning style",
148
- visible=True
149
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
- temperature = gr.Slider(
152
- minimum=0.1,
153
- maximum=1.5,
154
- value=0.7,
155
- step=0.1,
156
- label="Temperature (creativity)",
157
- info="Lower = more focused, Higher = more creative"
158
- )
159
 
160
- max_tokens = gr.Slider(
161
- minimum=100,
162
- maximum=1500,
163
- value=600,
164
- step=50,
165
- label="Max response length",
166
- info="Maximum tokens in response"
167
- )
 
 
 
 
 
 
 
168
 
169
- gr.Markdown("""
170
- ---
171
- ### 📌 Tips
172
- - **Thinking Mode ON**: Best for complex problems
173
- - **Thinking Mode OFF**: Faster responses for simple code
174
- - Be specific in your requests
175
- - Ask for explanations or optimizations
176
- """)
177
-
178
- # Example prompts
179
- examples = gr.Examples(
180
- examples=[
181
- "Write a Python function to find the longest common prefix in a list of strings",
182
- "Implement a binary search tree with insert and search methods",
183
- "Explain the difference between deep and shallow copy in Python with examples",
184
- "Write a recursive function to generate all permutations of a string",
185
- "Create a decorator that measures function execution time",
186
- "Implement a simple URL shortener using dictionary",
187
- "Write a function to check if two strings are anagrams",
188
- "Create a class for a bank account with deposit, withdraw, and interest calculation"
189
- ],
190
- inputs=msg,
191
- label="Example Prompts (click to try)"
192
- )
193
 
194
  # Event handlers
195
- def respond_wrapper(message, history, thinking_mode, reasoning_style, temperature, max_tokens):
196
- response_generator = respond(message, history, thinking_mode, reasoning_style, temperature, max_tokens)
197
- for response in response_generator:
198
- history.append((message, response))
199
- yield history, ""
200
- # Reset after yielding
201
- history = []
202
- yield history, ""
203
-
204
- # Wire up the events
205
  send_btn.click(
206
  respond,
207
- [msg, chatbot, thinking_mode, reasoning_style, temperature, max_tokens],
208
  [chatbot, msg]
209
  )
210
 
211
  msg.submit(
212
  respond,
213
- [msg, chatbot, thinking_mode, reasoning_style, temperature, max_tokens],
214
  [chatbot, msg]
215
  )
216
 
217
- clear_btn.click(lambda: None, None, chatbot, queue=False)
218
 
219
- example_btn.click(
220
- lambda: "Write a function to check if a string is a palindrome (ignoring spaces, punctuation, and case)",
221
- None,
222
- msg
 
223
  )
224
-
225
- # Footer with required attribution
226
- gr.Markdown("""
227
- ---
228
- <footer>
229
- <b>Built with Llama</b> • Llama 3.2 1B Codex • <a href="https://llama.meta.com/" target="_blank">Meta Llama 3.2</a><br>
230
- Licensed under <a href="/LICENSE.txt">Llama 3.2 Community License</a>
231
- </footer>
232
- """)
233
 
234
  if __name__ == "__main__":
235
  demo.launch(share=True)
 
1
  import gradio as gr
2
+ import torch
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
4
  import time
5
+ from typing import Dict, List, Tuple
6
+ from code_shower import CodeShower
7
+ from file_manager import FileManager
8
 
9
+ class DualModeAssistant:
10
+ def __init__(self):
11
+ print("🔄 Loading Llama 3.2 (General purpose)...")
12
+ self.llama_model_id = "meta-llama/Llama-3.2-1B-Instruct"
13
+ self.llama_pipe = pipeline(
14
+ "text-generation",
15
+ model=self.llama_model_id,
16
+ torch_dtype=torch.bfloat16,
17
+ device_map="auto",
18
+ token=True # Uses HF_TOKEN from env if available
19
+ )
20
+
21
+ print("💻 Loading Maincoder (Code specialist)...")
22
+ self.codex_model_id = "maincode/maincoder-1b"
23
+ self.codex_pipe = pipeline(
24
+ "text-generation",
25
+ model=self.codex_model_id,
26
+ torch_dtype=torch.bfloat16,
27
+ device_map="auto"
28
+ )
29
+
30
+ self.current_mode = "codex"
31
+ self.file_manager = FileManager()
32
+
33
+ def generate_with_thinking(self, prompt: str, mode: str, history: List = None) -> Dict:
34
+ """Generate with thinking process"""
35
+
36
+ self.current_mode = mode
37
+
38
+ # Choose model
39
+ if mode == "codex":
40
+ pipe = self.codex_pipe
41
+ system_prompt = """You are Maincoder, a specialized coding assistant.
42
+ When asked to write code, always output complete files with their filenames as markdown code blocks.
43
+ Example format:
44
+ ```python app.py
45
+ print("Hello")
46
+ html
47
+ <h1>Hello</h1>
48
+ ```"""
49
+ else:
50
+ pipe = self.llama_pipe
51
+ system_prompt = "You are a helpful general assistant. Answer questions thoroughly."
52
+
53
+ # Build messages
54
+ messages = [
55
+ {"role": "system", "content": system_prompt},
56
+ {"role": "user", "content": prompt}
57
+ ]
58
+
59
+ # Add conversation history if provided
60
+ if history:
61
+ for h in history[-4:]: # Last 4 exchanges
62
+ if isinstance(h, dict):
63
+ messages.append(h)
64
+
65
+ # Generate thinking (using system prompt to encourage reasoning)
66
+ full_response = pipe(
67
+ messages,
68
+ max_new_tokens=1000,
69
+ temperature=0.7,
70
+ do_sample=True,
71
+ top_p=0.95
72
+ )[0]['generated_text']
73
+
74
+ # Extract the assistant's response
75
+ if isinstance(full_response, list):
76
+ assistant_msg = full_response[-1].get('content', '')
77
+ else:
78
+ # Parse the full text
79
+ assistant_msg = full_response
80
+
81
+ # Detect and extract code blocks for file tree
82
+ files = self.file_manager.extract_files_from_code(assistant_msg)
83
+
84
+ return {
85
+ "response": assistant_msg,
86
+ "model_used": "Codex (Coding Specialist)" if mode == "codex" else "Llama (General)",
87
+ "files": files
88
+ }
89
 
90
+ # Initialize components
91
+ assistant = DualModeAssistant()
92
+ code_shower = CodeShower()
93
 
94
+ # Custom CSS
95
  custom_css = """
96
  <style>
97
+ /* Main layout */
98
+ .main-container {
99
+ display: flex;
100
+ gap: 20px;
101
+ height: 100vh;
102
  }
103
+
104
+ .chat-panel {
105
+ flex: 1;
106
+ min-width: 400px;
107
  }
108
+
109
+ .code-panel {
110
+ width: 450px;
111
+ border-left: 1px solid #ddd;
112
+ padding-left: 15px;
113
+ overflow-y: auto;
114
+ }
115
+
116
+ /* File tree styling */
117
+ .file-tree {
118
+ max-height: 300px;
119
+ overflow-y: auto;
120
+ border: 1px solid #e0e0e0;
121
+ border-radius: 8px;
122
+ background: #fafafa;
123
+ }
124
+
125
+ .file-item {
126
+ display: flex;
127
+ align-items: center;
128
+ padding: 8px 12px;
129
+ border-bottom: 1px solid #eee;
130
+ cursor: pointer;
131
+ transition: background 0.2s;
132
+ }
133
+
134
+ .file-item:hover {
135
+ background: #f0f0f0;
136
+ }
137
+
138
+ .file-item.active {
139
+ background: #e3f2fd;
140
+ border-left: 3px solid #2196f3;
141
+ }
142
+
143
+ .file-logo {
144
+ font-size: 1.2em;
145
+ margin-right: 10px;
146
+ }
147
+
148
+ .file-name {
149
+ flex: 1;
150
  font-family: monospace;
151
+ font-size: 0.9em;
152
+ }
153
+
154
+ .file-badge {
155
+ font-size: 0.7em;
156
+ padding: 2px 6px;
157
+ border-radius: 10px;
158
+ background: #e0e0e0;
159
+ margin-left: 8px;
160
+ }
161
+
162
+ .file-delete {
163
+ background: none;
164
+ border: none;
165
+ cursor: pointer;
166
+ opacity: 0.5;
167
+ margin-left: 8px;
168
  }
169
+
170
+ .file-delete:hover {
171
+ opacity: 1;
172
+ }
173
+
174
+ .file-tree-empty {
175
+ padding: 20px;
176
+ text-align: center;
177
+ color: #999;
178
+ }
179
+
180
+ /* Preview area */
181
+ .preview-container {
182
+ border: 1px solid #ddd;
183
+ border-radius: 8px;
184
+ overflow: hidden;
185
+ background: white;
186
+ }
187
+
188
+ .preview-placeholder, .preview-error {
189
+ padding: 40px;
190
+ text-align: center;
191
+ color: #999;
192
+ background: #f9f9f9;
193
+ border-radius: 8px;
194
+ }
195
+
196
+ /* Code viewer */
197
+ .code-viewer {
198
+ background: #1e1e1e;
199
+ border-radius: 8px;
200
+ overflow: hidden;
201
+ }
202
+
203
+ .code-header {
204
+ display: flex;
205
+ justify-content: space-between;
206
+ padding: 8px 12px;
207
+ background: #2d2d2d;
208
+ color: white;
209
+ border-bottom: 1px solid #444;
210
+ }
211
+
212
+ .code-block {
213
+ margin: 0;
214
  padding: 15px;
 
 
215
  overflow-x: auto;
216
+ font-family: 'Courier New', monospace;
217
+ font-size: 13px;
218
+ line-height: 1.4;
219
  }
220
+
221
+ .copy-btn {
222
+ background: #007bff;
223
+ border: none;
224
+ color: white;
225
+ padding: 4px 12px;
226
+ border-radius: 4px;
227
+ cursor: pointer;
228
+ }
229
+
230
+ .copy-btn:hover {
231
+ background: #0056b3;
232
+ }
233
+
234
+ /* Thinking mode bubble */
235
+ .thinking-bubble {
236
+ background: #f0f4ff;
237
+ border-left: 4px solid #667eea;
238
+ padding: 10px 15px;
239
+ margin: 10px 0;
240
+ border-radius: 8px;
241
+ font-style: italic;
242
+ color: #555;
243
+ }
244
+
245
+ /* Chat messages */
246
+ .message {
247
+ margin-bottom: 15px;
248
+ }
249
+
250
+ .user-message {
251
+ background: #e3f2fd;
252
+ padding: 10px;
253
+ border-radius: 10px;
254
+ margin-left: 20%;
255
+ }
256
+
257
+ .assistant-message {
258
+ background: #f5f5f5;
259
+ padding: 10px;
260
+ border-radius: 10px;
261
+ margin-right: 20%;
262
+ }
263
+
264
+ /* Responsive */
265
+ @media (max-width: 800px) {
266
+ .code-panel {
267
+ display: none;
268
+ }
269
+ .chat-panel {
270
+ min-width: 100%;
271
+ }
272
  }
273
  </style>
274
  """
275
 
276
+ # Create the Gradio interface
277
+ with gr.Blocks(css=custom_css, title="Llama Codex - Dual Mode Assistant", theme=gr.themes.Soft()) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  gr.Markdown("""
279
+ # �� Llama Codex - Dual Mode AI Coding Assistant
280
 
281
+ **Switch between two specialized AI modes:**
282
+ - 🧠 **Llama Mode**: General conversations, explanations, Q&A
283
+ - 💻 **Codex Mode**: Specialized coding with file extraction and previews
284
 
285
+ > 💡 Inspired by DeepSeek-R1 - both modes show their reasoning process before responding!
286
  """)
287
 
288
+ with gr.Row(elem_classes="main-container"):
289
+ # Left panel: Chat
290
+ with gr.Column(elem_classes="chat-panel", scale=2):
291
+ with gr.Row():
292
+ mode_selector = gr.Radio(
293
+ choices=["💻 Codex Mode (Coding Specialist)", "🧠 Llama Mode (General)"],
294
+ label="Select AI Mode",
295
+ value="💻 Codex Mode (Coding Specialist)",
296
+ interactive=True
297
+ )
298
+
299
+ with gr.Row():
300
+ thinking_toggle = gr.Checkbox(
301
+ label="🧠 Show Thinking Process",
302
+ value=True,
303
+ info="Shows the AI's reasoning before the final answer"
304
+ )
305
+
306
  chatbot = gr.Chatbot(
307
+ label="Assistant",
308
  height=500,
309
  bubble_full_width=False
310
  )
311
 
312
  with gr.Row():
313
  msg = gr.Textbox(
314
+ label="Your message",
315
+ placeholder="Ask me to write code, explain concepts, or help debug...",
316
+ scale=4,
317
+ lines=3
318
  )
319
  send_btn = gr.Button("Send", variant="primary", scale=1)
320
 
321
  with gr.Row():
322
  clear_btn = gr.Button("Clear Chat")
323
+ gr.Markdown("""
324
+ **Example prompts:**
325
+ - "Write a Python function to calculate fibonacci"
326
+ - "Create an HTML game of Snake"
327
+ - "Explain how recursion works"
328
+ - "Debug this: `for i in range(10) print(i)`"
329
+ """)
330
 
331
+ # Right panel: Code Shower
332
+ with gr.Column(elem_classes="code-panel", scale=1):
333
+ code_shower_ui = code_shower.create_ui()
334
+
335
+ # Footer with attribution
336
+ gr.Markdown("""
337
+ ---
338
+ <footer style="text-align: center;">
339
+ <b>Built with Llama</b> • Llama 3.2 1B + Maincoder 1B • <a href="https://llama.meta.com/" target="_blank">Meta Llama 3.2</a>
340
+ </footer>
341
+ """)
342
+
343
+ # State for conversation history
344
+ conversation_history = gr.State([])
345
+
346
+ # Helper functions
347
+ def get_model_mode(radio_value: str) -> str:
348
+ return "codex" if "Codex" in radio_value else "llama"
349
+
350
+ def respond(message, history, mode_radio, show_thinking):
351
+ if not message.strip():
352
+ yield history + [("", "Please enter a message.")], ""
353
+ return
354
+
355
+ # Show thinking indicator
356
+ thinking_msg = "🤔 Thinking" + "." * 3
357
+ yield history + [("", thinking_msg)], ""
358
+
359
+ # Get mode
360
+ mode = get_model_mode(mode_radio)
361
+
362
+ # Generate response
363
+ result = assistant.generate_with_thinking(message, mode, history)
364
+
365
+ # Format response
366
+ if show_thinking:
367
+ # Extract thinking from response (simple heuristic)
368
+ response_parts = result["response"].split("\n\n")
369
+ thinking_text = "No explicit thinking shown"
370
 
371
+ # Simple thinking extraction - you can enhance this
372
+ if "think" in result["response"].lower() or "step" in result["response"].lower():
373
+ thinking_text = result["response"][:300] + "..."
 
 
 
 
 
374
 
375
+ formatted = f"""<div class="thinking-bubble">
376
+ 💭 **Thinking process ({result['model_used']}):**
377
+ {thinking_text}
378
+ </div>
379
+
380
+ **Response:**
381
+ {result["response"]}"""
382
+ else:
383
+ formatted = result["response"]
384
+
385
+ # Update code shower with extracted files
386
+ if result.get("files") and code_shower:
387
+ # Update file tree
388
+ code_shower.current_files = result["files"]
389
+ file_tree_html = code_shower.update_files_display()
390
 
391
+ # Update code_shower_ui components
392
+ if result["files"]:
393
+ first_file = list(result["files"].keys())[0]
394
+ preview, code_view, code_content = code_shower.display_file(first_file)
395
+ # Note: In full implementation, update the UI components here
396
+ # For this example, we'll just update the file tree
397
+
398
+ # Update chat
399
+ new_history = history + [(message, formatted)]
400
+ yield new_history, ""
401
+
402
+ def clear_chat():
403
+ return [], ""
 
 
 
 
 
 
 
 
 
 
 
404
 
405
  # Event handlers
 
 
 
 
 
 
 
 
 
 
406
  send_btn.click(
407
  respond,
408
+ [msg, chatbot, mode_selector, thinking_toggle],
409
  [chatbot, msg]
410
  )
411
 
412
  msg.submit(
413
  respond,
414
+ [msg, chatbot, mode_selector, thinking_toggle],
415
  [chatbot, msg]
416
  )
417
 
418
+ clear_btn.click(clear_chat, None, [chatbot, msg])
419
 
420
+ # Code shower event handlers
421
+ code_shower_ui["add_file_btn"].click(
422
+ code_shower.add_new_file,
423
+ [code_shower_ui["new_lang"], code_shower_ui["new_filename"]],
424
+ [code_shower_ui["file_tree"], code_shower_ui["preview_area"], code_shower_ui["code_area"], msg]
425
  )
 
 
 
 
 
 
 
 
 
426
 
427
  if __name__ == "__main__":
428
  demo.launch(share=True)