AumCoreAI commited on
Commit
4a52541
·
verified ·
1 Parent(s): 7daf850

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -275
app.py CHANGED
@@ -1,8 +1,8 @@
1
- # app.py - UPDATED WITH CODE FORMATTING & COPY BUTTON (300+ lines)
2
  import os
3
  import uvicorn
4
  from fastapi import FastAPI, Form
5
- from fastapi.responses import HTMLResponse, JSONResponse
6
  from groq import Groq
7
 
8
  # --- CORE INITIALIZATION ---
@@ -12,7 +12,7 @@ client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
12
  # Configuration
13
  USERNAME = "Sanjay"
14
 
15
- # UI WITH ENHANCED CODE FORMATTING
16
  HTML_UI = '''
17
  <!DOCTYPE html>
18
  <html lang="en">
@@ -24,98 +24,97 @@ HTML_UI = '''
24
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
25
  <style>
26
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&family=Fira+Code:wght@400;500&display=swap');
27
-
28
- /* Base Styles */
29
- body {
30
- background-color: #0d1117;
31
- color: #c9d1d9;
32
- font-family: 'Inter', sans-serif;
33
- display: flex;
34
- height: 100vh;
35
- overflow: hidden;
36
- margin: 0;
37
  }
38
-
39
  /* Sidebar */
40
- .sidebar {
41
- width: 260px;
42
- background: #010409;
43
- border-right: 1px solid #30363d;
44
- display: flex;
45
- flex-direction: column;
46
- padding: 15px;
47
- flex-shrink: 0;
48
  }
49
- .nav-item {
50
- padding: 12px;
51
- margin-bottom: 5px;
52
- border-radius: 8px;
53
- cursor: pointer;
54
- display: flex;
55
- align-items: center;
56
- gap: 12px;
57
- color: #8b949e;
58
- transition: all 0.2s ease;
59
  }
60
- .nav-item:hover {
61
- background: #161b22;
62
- color: white;
63
  }
64
- .new-chat-btn {
65
- background: #238636;
66
- color: white !important;
67
- font-weight: 600;
68
- margin-bottom: 20px;
69
  }
70
-
71
  /* Main Chat Area */
72
- .main-chat {
73
- flex: 1;
74
- display: flex;
75
- flex-direction: column;
76
- background: #0d1117;
77
- position: relative;
78
  }
79
- .chat-box {
80
- flex: 1;
81
- overflow-y: auto;
82
- display: flex;
83
- flex-direction: column;
84
- align-items: center;
85
- padding: 60px 20px 120px 20px;
86
- scroll-behavior: smooth;
87
  }
88
- .message-wrapper {
89
- width: 100%;
90
- max-width: 760px;
91
- display: flex;
92
- flex-direction: column;
93
- margin-bottom: 35px;
94
- animation: fadeIn 0.3s ease;
95
  }
96
- @keyframes fadeIn {
97
- from { opacity: 0; transform: translateY(10px); }
98
- to { opacity: 1; transform: translateY(0); }
99
  }
100
-
101
  /* Message Bubbles */
102
- .bubble {
103
- padding: 5px 0;
104
- font-size: 17px;
105
- line-height: 1.8;
106
- width: 100%;
107
- word-wrap: break-word;
108
- white-space: pre-wrap;
109
- }
110
- .user-text {
111
- color: #58a6ff;
112
- font-weight: 600;
113
- letter-spacing: -0.2px;
114
  }
115
- .ai-text {
116
- color: #e6edf3;
117
  }
118
-
119
  /* ENHANCED CODE BLOCK STYLING */
120
  .code-container {
121
  background: #0d1117;
@@ -125,7 +124,6 @@ HTML_UI = '''
125
  overflow: hidden;
126
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
127
  }
128
-
129
  .code-header {
130
  background: #161b22;
131
  padding: 12px 18px;
@@ -134,7 +132,6 @@ HTML_UI = '''
134
  align-items: center;
135
  border-bottom: 1px solid #30363d;
136
  }
137
-
138
  .code-lang {
139
  color: #79c0ff;
140
  font-family: 'Fira Code', monospace;
@@ -144,13 +141,11 @@ HTML_UI = '''
144
  align-items: center;
145
  gap: 8px;
146
  }
147
-
148
  .code-lang::before {
149
  content: "✦";
150
  color: #7ee787;
151
  font-size: 12px;
152
  }
153
-
154
  .copy-btn {
155
  background: #238636;
156
  color: white;
@@ -166,149 +161,18 @@ HTML_UI = '''
166
  align-items: center;
167
  gap: 6px;
168
  }
169
-
170
  .copy-btn:hover {
171
  background: #2ea043;
172
  transform: translateY(-1px);
173
  }
174
-
175
  .copy-btn:active {
176
  transform: translateY(0);
177
  }
178
-
179
  .copy-btn.copied {
180
  background: #7ee787;
181
  color: #0d1117;
182
  }
183
-
184
- .code-container pre {
185
- background: transparent;
186
- border: none;
187
- margin: 0;
188
- padding: 20px;
189
- overflow-x: auto;
190
- scrollbar-width: thin;
191
- scrollbar-color: #30363d #0d1117;
192
- }
193
-
194
- .code-container pre::-webkit-scrollbar {
195
- height: 8px;
196
- }
197
-
198
- .code-container pre::-webkit-scrollbar-track {
199
- background: #0d1117;
200
- border-radius: 4px;
201
- }
202
-
203
- .code-container pre::-webkit-scrollbar-thumb {
204
- background: #30363d;
205
- border-radius: 4px;
206
- }
207
-
208
- .code-container pre::-webkit-scrollbar-thumb:hover {
209
- background: #484f58;
210
- }
211
-
212
- .code-container code {
213
- color: #79c0ff;
214
- font-size: 14.5px;
215
- line-height: 1.7;
216
- font-family: 'Fira Code', monospace;
217
- }
218
-
219
- /* Syntax Highlighting */
220
- .code-container .keyword { color: #ff7b72; }
221
- .code-container .function { color: #d2a8ff; }
222
- .code-container .string { color: #a5d6ff; }
223
- .code-container .comment { color: #8b949e; font-style: italic; }
224
- .code-container .number { color: #79c0ff; }
225
- .code-container .operator { color: #ff7b72; }
226
-
227
- /* Input Area */
228
- .input-area {
229
- position: absolute;
230
- bottom: 0;
231
- left: 0;
232
- width: 100%;
233
- background: linear-gradient(transparent, #0d1117 40%);
234
- padding-bottom: 30px;
235
- }
236
- .input-container {
237
- max-width: 800px;
238
- margin: 0 auto;
239
- background: #161b22;
240
- border: 1px solid #30363d;
241
- border-radius: 16px;
242
- padding: 14px 20px;
243
- display: flex;
244
- align-items: flex-end;
245
- gap: 14px;
246
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
247
- }
248
- #user-input {
249
- background: transparent;
250
- flex: 1;
251
- outline: none;
252
- border: none;
253
- color: white;
254
- font-size: 16px;
255
- resize: none;
256
- max-height: 200px;
257
- min-height: 32px;
258
- line-height: 1.5;
259
- padding: 4px 0;
260
- font-family: 'Inter', sans-serif;
261
- }
262
- .send-btn {
263
- color: #58a6ff;
264
- transition: transform 0.1s ease;
265
- margin-bottom: 6px;
266
- background: transparent;
267
- border: none;
268
- cursor: pointer;
269
- font-size: 18px;
270
- }
271
- .send-btn:hover {
272
- color: #79c0ff;
273
- transform: scale(1.1);
274
- }
275
- .send-btn:active {
276
- transform: scale(0.95);
277
- }
278
-
279
- /* Error Messages */
280
- .error-message {
281
- color: #f85149;
282
- background: rgba(248, 81, 73, 0.1);
283
- border: 1px solid rgba(248, 81, 73, 0.3);
284
- padding: 12px 16px;
285
- border-radius: 8px;
286
- font-weight: 500;
287
- margin: 10px 0;
288
- }
289
-
290
- /* Loading Animation */
291
- .typing-indicator {
292
- display: flex;
293
- gap: 4px;
294
- padding: 10px 0;
295
- }
296
-
297
- .typing-dot {
298
- width: 8px;
299
- height: 8px;
300
- background: #58a6ff;
301
- border-radius: 50%;
302
- animation: typingAnimation 1.4s infinite ease-in-out;
303
- }
304
-
305
- .typing-dot:nth-child(1) { animation-delay: -0.32s; }
306
- .typing-dot:nth-child(2) { animation-delay: -0.16s; }
307
-
308
- @keyframes typingAnimation {
309
- 0%, 80%, 100% { transform: scale(0); }
310
- 40% { transform: scale(1); }
311
- }
312
  </style>
313
  </head>
314
  <body>
@@ -324,10 +188,10 @@ HTML_UI = '''
324
  <div class="nav-item"><i class="fas fa-cog"></i> Settings</div>
325
  </div>
326
  </div>
327
-
328
  <div class="main-chat">
329
  <div id="chat-log" class="chat-box"></div>
330
-
331
  <div class="input-area">
332
  <div class="input-container">
333
  <textarea id="user-input" rows="1"
@@ -341,25 +205,24 @@ HTML_UI = '''
341
  </div>
342
  </div>
343
  </div>
344
-
345
  <script>
346
  // Utility Functions
347
  function resizeInput(el) {
348
  el.style.height = 'auto';
349
  el.style.height = el.scrollHeight + 'px';
350
  }
351
-
352
  function handleKey(e) {
353
  if (e.key === 'Enter' && !e.shiftKey) {
354
  e.preventDefault();
355
  send();
356
  }
357
  }
358
-
359
  // Code Block Formatter with Syntax Highlighting
360
  function formatCodeBlocks(text) {
361
- // Process Python code blocks
362
- let formatted = text.replace(/```python\s*([\s\S]*?)```/g,
363
  `<div class="code-container">
364
  <div class="code-header">
365
  <div class="code-lang">Python</div>
@@ -370,8 +233,7 @@ HTML_UI = '''
370
  <pre><code class="language-python">$1</code></pre>
371
  </div>`
372
  );
373
-
374
- // Process generic code blocks (no language specified)
375
  formatted = formatted.replace(/```\s*([\s\S]*?)```/g,
376
  `<div class="code-container">
377
  <div class="code-header">
@@ -383,24 +245,19 @@ HTML_UI = '''
383
  <pre><code>$1</code></pre>
384
  </div>`
385
  );
386
-
387
  return formatted;
388
  }
389
-
390
  // Copy Code Function
391
  function copyCode(button) {
392
  const codeBlock = button.parentElement.nextElementSibling;
393
  const codeText = codeBlock.innerText;
394
-
395
  navigator.clipboard.writeText(codeText).then(() => {
396
  const originalHTML = button.innerHTML;
397
  const originalClass = button.className;
398
-
399
- // Visual feedback
400
  button.innerHTML = '<i class="fas fa-check"></i> Copied!';
401
  button.className = 'copy-btn copied';
402
-
403
- // Revert after 2 seconds
404
  setTimeout(() => {
405
  button.innerHTML = originalHTML;
406
  button.className = originalClass;
@@ -413,7 +270,7 @@ HTML_UI = '''
413
  }, 2000);
414
  });
415
  }
416
-
417
  // Reset Memory Confirmation
418
  async function confirmReset() {
419
  if(confirm("Sanjay bhai, kya aap sach mein saari memory delete karna chahte hain?")) {
@@ -427,25 +284,25 @@ HTML_UI = '''
427
  }
428
  }
429
  }
430
-
431
  // Main Send Function with Enhanced Features
432
  async function send() {
433
  const input = document.getElementById('user-input');
434
  const log = document.getElementById('chat-log');
435
  const text = input.value.trim();
436
-
437
  if(!text) return;
438
-
439
  // Add user message
440
  log.innerHTML += `
441
  <div class="message-wrapper">
442
  <div class="bubble user-text">${text}</div>
443
  </div>`;
444
-
445
  // Clear and resize input
446
  input.value = '';
447
  input.style.height = 'auto';
448
-
449
  // Add typing indicator
450
  const typingId = 'typing-' + Date.now();
451
  log.innerHTML += `
@@ -456,37 +313,37 @@ HTML_UI = '''
456
  <div class="typing-dot"></div>
457
  </div>
458
  </div>`;
459
-
460
  // Scroll to bottom
461
  log.scrollTop = log.scrollHeight;
462
-
463
  try {
464
  const res = await fetch('/chat', {
465
  method: 'POST',
466
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
467
  body: 'message=' + encodeURIComponent(text)
468
  });
469
-
470
  const data = await res.json();
471
-
472
  // Remove typing indicator
473
  const typingElem = document.getElementById(typingId);
474
  if (typingElem) typingElem.remove();
475
-
476
  // Format response with enhanced code blocks
477
  let formatted = formatCodeBlocks(data.response);
478
-
479
  // Add AI response
480
  log.innerHTML += `
481
  <div class="message-wrapper">
482
  <div class="bubble ai-text">${formatted}</div>
483
  </div>`;
484
-
485
  } catch (e) {
486
  // Remove typing indicator on error
487
  const typingElem = document.getElementById(typingId);
488
  if (typingElem) typingElem.remove();
489
-
490
  log.innerHTML += `
491
  <div class="message-wrapper">
492
  <div class="error-message">
@@ -495,11 +352,11 @@ HTML_UI = '''
495
  </div>
496
  </div>`;
497
  }
498
-
499
  // Scroll to bottom
500
  log.scrollTop = log.scrollHeight;
501
  }
502
-
503
  // Auto-focus input on load
504
  document.addEventListener('DOMContentLoaded', () => {
505
  const input = document.getElementById('user-input');
@@ -508,8 +365,7 @@ HTML_UI = '''
508
  </script>
509
  </body>
510
  </html>
511
- '''
512
-
513
  @app.get("/", response_class=HTMLResponse)
514
  async def get_ui():
515
  return HTML_UI
@@ -526,15 +382,6 @@ async def reset():
526
 
527
  @app.post("/chat")
528
  async def chat(message: str = Form(...)):
529
- # ✅ LANGUAGE DETECTION
530
- from language_detector import detect_input_language, get_system_prompt
531
- from memory_db import tidb_memory # ✅ TiDB IMPORT
532
-
533
- lang_mode = detect_input_language(message)
534
- system_prompt = get_system_prompt(lang_mode, USERNAME)
535
- @app.post("/chat")
536
- async def chat(message: str = Form(...)):
537
- # ✅ LANGUAGE DETECTION
538
  from language_detector import detect_input_language, get_system_prompt, generate_basic_code
539
  from memory_db import tidb_memory # ✅ TiDB IMPORT
540
 
@@ -557,46 +404,41 @@ async def chat(message: str = Form(...)):
557
  print(f"⚠️ TiDB save error (code): {e}")
558
  return {"response": code_response}
559
 
560
- # ✅ GET HISTORY FROM TiDB (instead of JSON)
561
  recent_chats = []
562
  try:
563
  recent_chats = tidb_memory.get_recent_chats(limit=10)
564
  except Exception as e:
565
  print(f"⚠️ TiDB history fetch error: {e}")
566
- # Fallback to empty history if TiDB fails
567
-
568
  # Build messages for AI
569
  api_messages = [{"role": "system", "content": system_prompt}]
570
-
571
- # Add conversation history from TiDB
572
  for chat_row in recent_chats:
573
  user_input, ai_response, _ = chat_row
574
  api_messages.append({"role": "user", "content": user_input})
575
  api_messages.append({"role": "assistant", "content": ai_response})
576
-
577
- # Add current message
578
  api_messages.append({"role": "user", "content": message})
579
-
580
  try:
581
  # Get AI response
582
  completion = client.chat.completions.create(
583
  model="llama-3.3-70b-versatile",
584
  messages=api_messages,
585
  temperature=0.3,
586
- max_tokens=1000, # Increased for better code responses
587
  )
588
-
589
  ai_response = completion.choices[0].message.content.strip()
590
-
591
  # ✅ SAVE TO TiDB
592
  try:
593
  tidb_memory.save_chat(message, ai_response, lang_mode)
594
  print(f"✅ Chat saved to TiDB - Language: {lang_mode}")
595
  except Exception as e:
596
  print(f"⚠️ TiDB save error: {e}")
597
-
598
  return {"response": ai_response}
599
-
600
  except Exception as e:
601
  error_msg = f"System Error: {str(e)}"
602
  print(f"❌ API Error: {error_msg}")
@@ -612,5 +454,5 @@ if __name__ == "__main__":
612
  print(f"💾 Database: TiDB Cloud")
613
  print(f"🎨 UI Features: Code formatting + Copy button")
614
  print("=" * 60)
615
-
616
- uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")
 
1
+ # app.py - Part 1/4
2
  import os
3
  import uvicorn
4
  from fastapi import FastAPI, Form
5
+ from fastapi.responses import HTMLResponse
6
  from groq import Groq
7
 
8
  # --- CORE INITIALIZATION ---
 
12
  # Configuration
13
  USERNAME = "Sanjay"
14
 
15
+ # HTML UI with enhanced code formatting
16
  HTML_UI = '''
17
  <!DOCTYPE html>
18
  <html lang="en">
 
24
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
25
  <style>
26
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&family=Fira+Code:wght@400;500&display=swap');
27
+
28
+ body {
29
+ background-color: #0d1117;
30
+ color: #c9d1d9;
31
+ font-family: 'Inter', sans-serif;
32
+ display: flex;
33
+ height: 100vh;
34
+ overflow: hidden;
35
+ margin: 0;
 
36
  }
37
+
38
  /* Sidebar */
39
+ .sidebar {
40
+ width: 260px;
41
+ background: #010409;
42
+ border-right: 1px solid #30363d;
43
+ display: flex;
44
+ flex-direction: column;
45
+ padding: 15px;
46
+ flex-shrink: 0;
47
  }
48
+ .nav-item {
49
+ padding: 12px;
50
+ margin-bottom: 5px;
51
+ border-radius: 8px;
52
+ cursor: pointer;
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 12px;
56
+ color: #8b949e;
57
+ transition: all 0.2s ease;
58
  }
59
+ .nav-item:hover {
60
+ background: #161b22;
61
+ color: white;
62
  }
63
+ .new-chat-btn {
64
+ background: #238636;
65
+ color: white !important;
66
+ font-weight: 600;
67
+ margin-bottom: 20px;
68
  }
69
+
70
  /* Main Chat Area */
71
+ .main-chat {
72
+ flex: 1;
73
+ display: flex;
74
+ flex-direction: column;
75
+ background: #0d1117;
76
+ position: relative;
77
  }
78
+ .chat-box {
79
+ flex: 1;
80
+ overflow-y: auto;
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ padding: 60px 20px 120px 20px;
85
+ scroll-behavior: smooth;
86
  }
87
+ .message-wrapper {
88
+ width: 100%;
89
+ max-width: 760px;
90
+ display: flex;
91
+ flex-direction: column;
92
+ margin-bottom: 35px;
93
+ animation: fadeIn 0.3s ease;
94
  }
95
+ @keyframes fadeIn {
96
+ from { opacity: 0; transform: translateY(10px); }
97
+ to { opacity: 1; transform: translateY(0); }
98
  }
99
+
100
  /* Message Bubbles */
101
+ .bubble {
102
+ padding: 5px 0;
103
+ font-size: 17px;
104
+ line-height: 1.8;
105
+ width: 100%;
106
+ word-wrap: break-word;
107
+ white-space: pre-wrap;
108
+ }
109
+ .user-text {
110
+ color: #58a6ff;
111
+ font-weight: 600;
112
+ letter-spacing: -0.2px;
113
  }
114
+ .ai-text {
115
+ color: #e6edf3;
116
  }
117
+
118
  /* ENHANCED CODE BLOCK STYLING */
119
  .code-container {
120
  background: #0d1117;
 
124
  overflow: hidden;
125
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
126
  }
 
127
  .code-header {
128
  background: #161b22;
129
  padding: 12px 18px;
 
132
  align-items: center;
133
  border-bottom: 1px solid #30363d;
134
  }
 
135
  .code-lang {
136
  color: #79c0ff;
137
  font-family: 'Fira Code', monospace;
 
141
  align-items: center;
142
  gap: 8px;
143
  }
 
144
  .code-lang::before {
145
  content: "✦";
146
  color: #7ee787;
147
  font-size: 12px;
148
  }
 
149
  .copy-btn {
150
  background: #238636;
151
  color: white;
 
161
  align-items: center;
162
  gap: 6px;
163
  }
 
164
  .copy-btn:hover {
165
  background: #2ea043;
166
  transform: translateY(-1px);
167
  }
 
168
  .copy-btn:active {
169
  transform: translateY(0);
170
  }
 
171
  .copy-btn.copied {
172
  background: #7ee787;
173
  color: #0d1117;
174
  }
175
+ # app.py - Part 2/4 (continuation)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  </style>
177
  </head>
178
  <body>
 
188
  <div class="nav-item"><i class="fas fa-cog"></i> Settings</div>
189
  </div>
190
  </div>
191
+
192
  <div class="main-chat">
193
  <div id="chat-log" class="chat-box"></div>
194
+
195
  <div class="input-area">
196
  <div class="input-container">
197
  <textarea id="user-input" rows="1"
 
205
  </div>
206
  </div>
207
  </div>
208
+
209
  <script>
210
  // Utility Functions
211
  function resizeInput(el) {
212
  el.style.height = 'auto';
213
  el.style.height = el.scrollHeight + 'px';
214
  }
215
+
216
  function handleKey(e) {
217
  if (e.key === 'Enter' && !e.shiftKey) {
218
  e.preventDefault();
219
  send();
220
  }
221
  }
222
+
223
  // Code Block Formatter with Syntax Highlighting
224
  function formatCodeBlocks(text) {
225
+ let formatted = text.replace(/```python\s*([\s\S]*?)```/g,
 
226
  `<div class="code-container">
227
  <div class="code-header">
228
  <div class="code-lang">Python</div>
 
233
  <pre><code class="language-python">$1</code></pre>
234
  </div>`
235
  );
236
+
 
237
  formatted = formatted.replace(/```\s*([\s\S]*?)```/g,
238
  `<div class="code-container">
239
  <div class="code-header">
 
245
  <pre><code>$1</code></pre>
246
  </div>`
247
  );
248
+
249
  return formatted;
250
  }
251
+
252
  // Copy Code Function
253
  function copyCode(button) {
254
  const codeBlock = button.parentElement.nextElementSibling;
255
  const codeText = codeBlock.innerText;
 
256
  navigator.clipboard.writeText(codeText).then(() => {
257
  const originalHTML = button.innerHTML;
258
  const originalClass = button.className;
 
 
259
  button.innerHTML = '<i class="fas fa-check"></i> Copied!';
260
  button.className = 'copy-btn copied';
 
 
261
  setTimeout(() => {
262
  button.innerHTML = originalHTML;
263
  button.className = originalClass;
 
270
  }, 2000);
271
  });
272
  }
273
+
274
  // Reset Memory Confirmation
275
  async function confirmReset() {
276
  if(confirm("Sanjay bhai, kya aap sach mein saari memory delete karna chahte hain?")) {
 
284
  }
285
  }
286
  }
287
+ # app.py - Part 3/4 (continuation)
288
  // Main Send Function with Enhanced Features
289
  async function send() {
290
  const input = document.getElementById('user-input');
291
  const log = document.getElementById('chat-log');
292
  const text = input.value.trim();
293
+
294
  if(!text) return;
295
+
296
  // Add user message
297
  log.innerHTML += `
298
  <div class="message-wrapper">
299
  <div class="bubble user-text">${text}</div>
300
  </div>`;
301
+
302
  // Clear and resize input
303
  input.value = '';
304
  input.style.height = 'auto';
305
+
306
  // Add typing indicator
307
  const typingId = 'typing-' + Date.now();
308
  log.innerHTML += `
 
313
  <div class="typing-dot"></div>
314
  </div>
315
  </div>`;
316
+
317
  // Scroll to bottom
318
  log.scrollTop = log.scrollHeight;
319
+
320
  try {
321
  const res = await fetch('/chat', {
322
  method: 'POST',
323
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
324
  body: 'message=' + encodeURIComponent(text)
325
  });
326
+
327
  const data = await res.json();
328
+
329
  // Remove typing indicator
330
  const typingElem = document.getElementById(typingId);
331
  if (typingElem) typingElem.remove();
332
+
333
  // Format response with enhanced code blocks
334
  let formatted = formatCodeBlocks(data.response);
335
+
336
  // Add AI response
337
  log.innerHTML += `
338
  <div class="message-wrapper">
339
  <div class="bubble ai-text">${formatted}</div>
340
  </div>`;
341
+
342
  } catch (e) {
343
  // Remove typing indicator on error
344
  const typingElem = document.getElementById(typingId);
345
  if (typingElem) typingElem.remove();
346
+
347
  log.innerHTML += `
348
  <div class="message-wrapper">
349
  <div class="error-message">
 
352
  </div>
353
  </div>`;
354
  }
355
+
356
  // Scroll to bottom
357
  log.scrollTop = log.scrollHeight;
358
  }
359
+
360
  // Auto-focus input on load
361
  document.addEventListener('DOMContentLoaded', () => {
362
  const input = document.getElementById('user-input');
 
365
  </script>
366
  </body>
367
  </html>
368
+ # app.py - Part 4/4 (backend + run)
 
369
  @app.get("/", response_class=HTMLResponse)
370
  async def get_ui():
371
  return HTML_UI
 
382
 
383
  @app.post("/chat")
384
  async def chat(message: str = Form(...)):
 
 
 
 
 
 
 
 
 
385
  from language_detector import detect_input_language, get_system_prompt, generate_basic_code
386
  from memory_db import tidb_memory # ✅ TiDB IMPORT
387
 
 
404
  print(f"⚠️ TiDB save error (code): {e}")
405
  return {"response": code_response}
406
 
407
+ # ✅ GET HISTORY FROM TiDB
408
  recent_chats = []
409
  try:
410
  recent_chats = tidb_memory.get_recent_chats(limit=10)
411
  except Exception as e:
412
  print(f"⚠️ TiDB history fetch error: {e}")
413
+
 
414
  # Build messages for AI
415
  api_messages = [{"role": "system", "content": system_prompt}]
 
 
416
  for chat_row in recent_chats:
417
  user_input, ai_response, _ = chat_row
418
  api_messages.append({"role": "user", "content": user_input})
419
  api_messages.append({"role": "assistant", "content": ai_response})
 
 
420
  api_messages.append({"role": "user", "content": message})
421
+
422
  try:
423
  # Get AI response
424
  completion = client.chat.completions.create(
425
  model="llama-3.3-70b-versatile",
426
  messages=api_messages,
427
  temperature=0.3,
428
+ max_tokens=1000,
429
  )
430
+
431
  ai_response = completion.choices[0].message.content.strip()
432
+
433
  # ✅ SAVE TO TiDB
434
  try:
435
  tidb_memory.save_chat(message, ai_response, lang_mode)
436
  print(f"✅ Chat saved to TiDB - Language: {lang_mode}")
437
  except Exception as e:
438
  print(f"⚠️ TiDB save error: {e}")
439
+
440
  return {"response": ai_response}
441
+
442
  except Exception as e:
443
  error_msg = f"System Error: {str(e)}"
444
  print(f"❌ API Error: {error_msg}")
 
454
  print(f"💾 Database: TiDB Cloud")
455
  print(f"🎨 UI Features: Code formatting + Copy button")
456
  print("=" * 60)
457
+
458
+ uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")