Shirpi commited on
Commit
72cca92
·
verified ·
1 Parent(s): 1867d4f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -62
app.py CHANGED
@@ -4,10 +4,15 @@ import time
4
  import json
5
  import base64
6
  import io
 
7
  from PIL import Image
8
  from flask import Flask, request, jsonify, render_template_string, Response
9
  import google.generativeai as genai
10
 
 
 
 
 
11
  # ==========================================
12
  # 👇 API KEYS SETUP 👇
13
  # ==========================================
@@ -44,14 +49,17 @@ RULES:
44
 
45
  # --- 🧬 MODEL & FILE HANDLING ---
46
  def get_working_model(key):
47
- genai.configure(api_key=key)
48
  try:
 
49
  models = list(genai.list_models())
50
  chat_models = [m for m in models if 'generateContent' in m.supported_generation_methods]
 
 
51
  for m in chat_models:
52
  if "flash" in m.name.lower() and "1.5" in m.name: return m.name
53
  for m in chat_models:
54
  if "pro" in m.name.lower() and "1.5" in m.name: return m.name
 
55
  if chat_models: return chat_models[0].name
56
  except: return None
57
  return None
@@ -104,16 +112,6 @@ def generate_with_retry(prompt, image_data=None, file_text=None, history_message
104
 
105
  return "⚠️ System Busy. Please try again."
106
 
107
- # --- PWA MANIFEST ---
108
- @app.route('/manifest.json')
109
- def manifest():
110
- data = {
111
- "name": "Student's AI", "short_name": "StudentAI", "start_url": "/", "display": "standalone",
112
- "orientation": "portrait", "background_color": "#09090b", "theme_color": "#09090b",
113
- "icons": [{"src": "https://cdn-icons-png.flaticon.com/512/4712/4712035.png", "sizes": "192x192", "type": "image/png"}]
114
- }
115
- return Response(json.dumps(data), mimetype='application/json')
116
-
117
  # --- UI TEMPLATE ---
118
  HTML_TEMPLATE = """
119
  <!DOCTYPE html>
@@ -138,7 +136,7 @@ HTML_TEMPLATE = """
138
  <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
139
  <script type="module">
140
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
141
- mermaid.initialize({ startOnLoad: false, theme: 'dark',securityLevel: 'loose' });
142
  window.mermaid = mermaid;
143
  </script>
144
 
@@ -152,7 +150,7 @@ HTML_TEMPLATE = """
152
 
153
  #app-container { display: flex; flex-direction: column; height: 100dvh; position: relative; }
154
 
155
- /* HEADER (Professional) */
156
  header {
157
  height: 70px; padding: 0 20px;
158
  background: rgba(9,9,11, 0.98);
@@ -168,32 +166,28 @@ HTML_TEMPLATE = """
168
  .menu-btn:active { transform: scale(0.95); background: #222; }
169
  .app-title { font-size: 24px; font-weight: 800; letter-spacing: -0.5px; color: #fff; }
170
 
171
- /* SIDEBAR (Top to Bottom Animation) */
172
  #sidebar {
173
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
174
  background: var(--bg); z-index: 100;
175
  display: flex; flex-direction: column; padding: 25px;
176
  padding-top: calc(70px + env(safe-area-inset-top));
177
- transform: translateY(-100%); /* Start hidden above */
178
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
179
  }
180
  #sidebar.open { transform: translateY(0); }
181
 
182
- /* Sidebar Elements */
183
  .user-info { margin-bottom: 30px; font-size: 20px; font-weight: 700; color: #fff; display: flex; align-items: center; gap: 15px; }
184
  .new-chat-btn {
185
  width: 100%; padding: 15px; background: #fff; color: #000; border: none;
186
  border-radius: 12px; font-weight: 700; font-size: 16px; cursor: pointer; margin-bottom: 25px;
187
- display: flex; justify-content: center; align-items: center;
188
  }
189
- .new-chat-btn:active { transform: scale(0.98); opacity: 0.9; }
190
 
191
  .history-label { color: var(--dim); font-size: 13px; font-weight: 600; margin-bottom: 10px; letter-spacing: 1px; text-transform: uppercase; }
192
  #history-list {
193
  flex: 1; overflow-y: auto; background: var(--card); border-radius: 16px;
194
  padding: 10px; border: 1px solid var(--border);
195
  }
196
-
197
  .history-item {
198
  display: flex; justify-content: space-between; align-items: center;
199
  padding: 15px; border-bottom: 1px solid #222; cursor: pointer; color: #a1a1aa;
@@ -202,13 +196,10 @@ HTML_TEMPLATE = """
202
  .history-item:last-child { border-bottom: none; }
203
  .history-item:active { background: #222; color: #fff; }
204
  .h-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
205
-
206
- /* Action Logos (Hidden by default, shown on long press/active) */
207
  .h-actions { display: none; gap: 15px; }
208
  .history-item.active-mode .h-actions { display: flex; }
209
  .h-icon { font-size: 16px; color: #fff; padding: 5px; }
210
 
211
- /* BRANDING */
212
  .brand-section { text-align: center; margin-top: 20px; padding-bottom: env(safe-area-inset-bottom); }
213
  .brand-name { font-family: 'Outfit', sans-serif; font-weight: 600; font-size: 12px; color: var(--dim); letter-spacing: 2px; margin-bottom: 10px; opacity: 0.6; }
214
  .logout-btn { color: #ef4444; cursor: pointer; font-size: 15px; font-weight: 600; padding: 10px; }
@@ -229,17 +220,14 @@ HTML_TEMPLATE = """
229
  .ai-msg { text-align: left; }
230
  .ai-content { user-select: text; color: #d4d4d8; }
231
  .ai-content strong { color: #fff; font-weight: 700; }
232
- .ai-content h1, .ai-content h2, .ai-content h3 { margin-top: 20px; color: #fff; font-weight: 700; }
233
 
234
- /* Code Blocks (Colored) */
235
  pre { background: #1e1e1e !important; border-radius: 12px; padding: 15px; overflow-x: auto; margin: 15px 0; border: 1px solid #333; }
236
  code { font-family: 'JetBrains Mono', monospace; font-size: 14px; }
237
 
238
- /* Math & Diagrams */
239
  .mjx-chtml { background: #18181b; padding: 10px; border-radius: 8px; border: 1px solid #333; overflow-x: auto; margin: 10px 0; text-align: center; }
240
  .mermaid { background: #111; padding: 15px; border-radius: 10px; text-align: center; margin: 15px 0; }
241
 
242
- /* Action LOGOS (Big & Spaced) */
243
  .msg-actions { margin-top: 10px; opacity: 0; transition: opacity 0.2s; display: flex; gap: 20px; align-items: center; }
244
  .user-msg .msg-actions { justify-content: flex-end; }
245
  .msg:hover .msg-actions { opacity: 1; }
@@ -259,25 +247,12 @@ HTML_TEMPLATE = """
259
  .icon-btn:hover { background: #333; color: #fff; }
260
  .send-btn { background: #fff; color: #000; width: 38px; height: 38px; border-radius: 50%; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 18px; }
261
 
262
- /* SMALL CURVED PREVIEW */
263
- #preview-area {
264
- position: absolute; bottom: 85px; left: 20px;
265
- display: none; z-index: 70;
266
- }
267
- .preview-box {
268
- width: 60px; height: 60px; border-radius: 12px; border: 2px solid #fff;
269
- background: #222; overflow: hidden; position: relative;
270
- box-shadow: 0 4px 12px rgba(0,0,0,0.5);
271
- }
272
  .preview-img { width: 100%; height: 100%; object-fit: cover; }
273
  .preview-file-icon { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 24px; color: #fff; }
274
- .remove-preview {
275
- position: absolute; top: -8px; right: -8px; background: red; color: white;
276
- border-radius: 50%; width: 20px; height: 20px; font-size: 12px;
277
- cursor: pointer; border: none; display: flex; align-items: center; justify-content: center;
278
- }
279
 
280
- /* LOGIN */
281
  #login-overlay { position: fixed; inset: 0; background: #000; z-index: 2000; display: flex; align-items: center; justify-content: center; }
282
  .login-box { width: 90%; max-width: 350px; text-align: center; padding: 40px; border: 1px solid var(--border); border-radius: 20px; background: #0a0a0a; }
283
  </style>
@@ -294,17 +269,12 @@ HTML_TEMPLATE = """
294
 
295
  <div id="sidebar">
296
  <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
297
- <div class="user-info">
298
- <span id="display-name">User</span>
299
- </div>
300
  <div class="menu-btn" onclick="toggleSidebar()"><i class="fas fa-times"></i></div>
301
  </div>
302
-
303
  <button class="new-chat-btn" onclick="newChat()">New Chat</button>
304
-
305
  <div class="history-label">Chat History</div>
306
  <div id="history-list"></div>
307
-
308
  <div class="brand-section">
309
  <div class="brand-name">Designed by Shirpi</div>
310
  <div class="logout-btn" onclick="handleLogout()">Log Out</div>
@@ -315,15 +285,14 @@ HTML_TEMPLATE = """
315
  <header>
316
  <div class="menu-btn" onclick="toggleSidebar()"><i class="fas fa-bars"></i></div>
317
  <span class="app-title">Student's AI</span>
318
- <div style="width:40px;"></div> </header>
 
319
 
320
  <div id="chat-box"></div>
321
 
322
  <div class="input-wrapper">
323
  <div id="preview-area">
324
- <div class="preview-box">
325
- <div id="preview-visual"></div>
326
- </div>
327
  <button class="remove-preview" onclick="clearAttachment()">×</button>
328
  </div>
329
 
@@ -364,7 +333,7 @@ HTML_TEMPLATE = """
364
  if(!currentChatId) {
365
  const box = document.getElementById("chat-box");
366
  if(box.innerHTML === "") {
367
- box.innerHTML = `<div class="msg ai-msg"><div class="ai-content"><h1>Hi ${currentUser},</h1><p>How can I help you with your <strong>Studies</strong> today?</p></div></div>`;
368
  }
369
  }
370
  }
@@ -426,7 +395,7 @@ HTML_TEMPLATE = """
426
  const imgData = currentAttachment.type === 'image' ? currentAttachment.data : null;
427
  const fileText = currentAttachment.type === 'file' ? currentAttachment.data : null;
428
 
429
- input.value = ''; input.style.height = 'auto';
430
  clearAttachment();
431
  scrollToBottom();
432
 
@@ -480,11 +449,11 @@ HTML_TEMPLATE = """
480
  function editMessage(oldText) { document.getElementById('input').value = oldText; document.getElementById('input').focus(); }
481
  function regenerate(text) { document.getElementById('input').value = text; send(); }
482
 
483
- // --- HISTORY (LONG PRESS) ---
484
  function handleHistoryTouchStart(e, cid, title) {
485
  longPressTimer = setTimeout(() => {
486
  e.target.closest('.history-item').classList.add('active-mode');
487
- }, 600); // 0.6s hold
488
  }
489
  function handleHistoryTouchEnd(e) { clearTimeout(longPressTimer); }
490
 
@@ -518,10 +487,9 @@ HTML_TEMPLATE = """
518
  } catch(e) {}
519
  }
520
 
521
- // --- ANIMATION & HIGHLIGHT ---
522
  async function typeWriter(element, markdownText) {
523
  element.innerHTML = marked.parse(markdownText);
524
- hljs.highlightAll(); // Highlight Code
525
  if (window.MathJax) await MathJax.typesetPromise([element]);
526
  if (window.mermaid) {
527
  const m = element.querySelectorAll('code.language-mermaid');
@@ -538,7 +506,7 @@ HTML_TEMPLATE = """
538
  const r = await fetch('/new_chat', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({username:currentUser})});
539
  const d = await r.json(); currentChatId = d.chat_id; loadHistory();
540
  document.getElementById('sidebar').classList.remove('open');
541
- showApp(); // Reset Intro
542
  }
543
  async function loadChat(cid) {
544
  currentChatId = cid; const res = await fetch('/get_chat', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({username:currentUser, chat_id:cid})});
@@ -629,15 +597,20 @@ def chat():
629
  save_db(user_db)
630
  return jsonify({"response": reply, "new_title": new_title})
631
 
 
632
  @app.route('/manifest.json')
633
  def manifest():
634
  data = {
635
- "name": "Student's AI", "short_name": "StudentAI", "start_url": "/", "display": "standalone",
636
- "orientation": "portrait", "background_color": "#09090b", "theme_color": "#09090b",
 
 
 
 
 
637
  "icons": [{"src": "https://cdn-icons-png.flaticon.com/512/4712/4712035.png", "sizes": "192x192", "type": "image/png"}]
638
  }
639
  return Response(json.dumps(data), mimetype='application/json')
640
 
641
  if __name__ == '__main__':
642
  app.run(host='0.0.0.0', port=7860)
643
-
 
4
  import json
5
  import base64
6
  import io
7
+ import warnings
8
  from PIL import Image
9
  from flask import Flask, request, jsonify, render_template_string, Response
10
  import google.generativeai as genai
11
 
12
+ # --- FIX: IGNORE DEPRECATION WARNINGS ---
13
+ # Idhu Google 'FutureWarning' error-a ignore panna sollum
14
+ warnings.filterwarnings("ignore")
15
+
16
  # ==========================================
17
  # 👇 API KEYS SETUP 👇
18
  # ==========================================
 
49
 
50
  # --- 🧬 MODEL & FILE HANDLING ---
51
  def get_working_model(key):
 
52
  try:
53
+ genai.configure(api_key=key)
54
  models = list(genai.list_models())
55
  chat_models = [m for m in models if 'generateContent' in m.supported_generation_methods]
56
+
57
+ # Priority Order
58
  for m in chat_models:
59
  if "flash" in m.name.lower() and "1.5" in m.name: return m.name
60
  for m in chat_models:
61
  if "pro" in m.name.lower() and "1.5" in m.name: return m.name
62
+
63
  if chat_models: return chat_models[0].name
64
  except: return None
65
  return None
 
112
 
113
  return "⚠️ System Busy. Please try again."
114
 
 
 
 
 
 
 
 
 
 
 
115
  # --- UI TEMPLATE ---
116
  HTML_TEMPLATE = """
117
  <!DOCTYPE html>
 
136
  <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
137
  <script type="module">
138
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
139
+ mermaid.initialize({ startOnLoad: false, theme: 'dark', securityLevel: 'loose' });
140
  window.mermaid = mermaid;
141
  </script>
142
 
 
150
 
151
  #app-container { display: flex; flex-direction: column; height: 100dvh; position: relative; }
152
 
153
+ /* HEADER */
154
  header {
155
  height: 70px; padding: 0 20px;
156
  background: rgba(9,9,11, 0.98);
 
166
  .menu-btn:active { transform: scale(0.95); background: #222; }
167
  .app-title { font-size: 24px; font-weight: 800; letter-spacing: -0.5px; color: #fff; }
168
 
169
+ /* SIDEBAR */
170
  #sidebar {
171
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
172
  background: var(--bg); z-index: 100;
173
  display: flex; flex-direction: column; padding: 25px;
174
  padding-top: calc(70px + env(safe-area-inset-top));
175
+ transform: translateY(-100%);
176
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
177
  }
178
  #sidebar.open { transform: translateY(0); }
179
 
 
180
  .user-info { margin-bottom: 30px; font-size: 20px; font-weight: 700; color: #fff; display: flex; align-items: center; gap: 15px; }
181
  .new-chat-btn {
182
  width: 100%; padding: 15px; background: #fff; color: #000; border: none;
183
  border-radius: 12px; font-weight: 700; font-size: 16px; cursor: pointer; margin-bottom: 25px;
 
184
  }
 
185
 
186
  .history-label { color: var(--dim); font-size: 13px; font-weight: 600; margin-bottom: 10px; letter-spacing: 1px; text-transform: uppercase; }
187
  #history-list {
188
  flex: 1; overflow-y: auto; background: var(--card); border-radius: 16px;
189
  padding: 10px; border: 1px solid var(--border);
190
  }
 
191
  .history-item {
192
  display: flex; justify-content: space-between; align-items: center;
193
  padding: 15px; border-bottom: 1px solid #222; cursor: pointer; color: #a1a1aa;
 
196
  .history-item:last-child { border-bottom: none; }
197
  .history-item:active { background: #222; color: #fff; }
198
  .h-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
 
 
199
  .h-actions { display: none; gap: 15px; }
200
  .history-item.active-mode .h-actions { display: flex; }
201
  .h-icon { font-size: 16px; color: #fff; padding: 5px; }
202
 
 
203
  .brand-section { text-align: center; margin-top: 20px; padding-bottom: env(safe-area-inset-bottom); }
204
  .brand-name { font-family: 'Outfit', sans-serif; font-weight: 600; font-size: 12px; color: var(--dim); letter-spacing: 2px; margin-bottom: 10px; opacity: 0.6; }
205
  .logout-btn { color: #ef4444; cursor: pointer; font-size: 15px; font-weight: 600; padding: 10px; }
 
220
  .ai-msg { text-align: left; }
221
  .ai-content { user-select: text; color: #d4d4d8; }
222
  .ai-content strong { color: #fff; font-weight: 700; }
223
+ .ai-content h1, .ai-content h2 { margin-top: 20px; color: #fff; font-weight: 700; }
224
 
 
225
  pre { background: #1e1e1e !important; border-radius: 12px; padding: 15px; overflow-x: auto; margin: 15px 0; border: 1px solid #333; }
226
  code { font-family: 'JetBrains Mono', monospace; font-size: 14px; }
227
 
 
228
  .mjx-chtml { background: #18181b; padding: 10px; border-radius: 8px; border: 1px solid #333; overflow-x: auto; margin: 10px 0; text-align: center; }
229
  .mermaid { background: #111; padding: 15px; border-radius: 10px; text-align: center; margin: 15px 0; }
230
 
 
231
  .msg-actions { margin-top: 10px; opacity: 0; transition: opacity 0.2s; display: flex; gap: 20px; align-items: center; }
232
  .user-msg .msg-actions { justify-content: flex-end; }
233
  .msg:hover .msg-actions { opacity: 1; }
 
247
  .icon-btn:hover { background: #333; color: #fff; }
248
  .send-btn { background: #fff; color: #000; width: 38px; height: 38px; border-radius: 50%; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 18px; }
249
 
250
+ #preview-area { position: absolute; bottom: 85px; left: 20px; display: none; z-index: 70; }
251
+ .preview-box { width: 60px; height: 60px; border-radius: 12px; border: 2px solid #fff; background: #222; overflow: hidden; position: relative; box-shadow: 0 4px 12px rgba(0,0,0,0.5); }
 
 
 
 
 
 
 
 
252
  .preview-img { width: 100%; height: 100%; object-fit: cover; }
253
  .preview-file-icon { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 24px; color: #fff; }
254
+ .remove-preview { position: absolute; top: -8px; right: -8px; background: red; color: white; border-radius: 50%; width: 20px; height: 20px; font-size: 12px; cursor: pointer; border: none; display: flex; align-items: center; justify-content: center; }
 
 
 
 
255
 
 
256
  #login-overlay { position: fixed; inset: 0; background: #000; z-index: 2000; display: flex; align-items: center; justify-content: center; }
257
  .login-box { width: 90%; max-width: 350px; text-align: center; padding: 40px; border: 1px solid var(--border); border-radius: 20px; background: #0a0a0a; }
258
  </style>
 
269
 
270
  <div id="sidebar">
271
  <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
272
+ <div class="user-info"><span id="display-name">User</span></div>
 
 
273
  <div class="menu-btn" onclick="toggleSidebar()"><i class="fas fa-times"></i></div>
274
  </div>
 
275
  <button class="new-chat-btn" onclick="newChat()">New Chat</button>
 
276
  <div class="history-label">Chat History</div>
277
  <div id="history-list"></div>
 
278
  <div class="brand-section">
279
  <div class="brand-name">Designed by Shirpi</div>
280
  <div class="logout-btn" onclick="handleLogout()">Log Out</div>
 
285
  <header>
286
  <div class="menu-btn" onclick="toggleSidebar()"><i class="fas fa-bars"></i></div>
287
  <span class="app-title">Student's AI</span>
288
+ <div style="width:40px;"></div>
289
+ </header>
290
 
291
  <div id="chat-box"></div>
292
 
293
  <div class="input-wrapper">
294
  <div id="preview-area">
295
+ <div class="preview-box"><div id="preview-visual"></div></div>
 
 
296
  <button class="remove-preview" onclick="clearAttachment()">×</button>
297
  </div>
298
 
 
333
  if(!currentChatId) {
334
  const box = document.getElementById("chat-box");
335
  if(box.innerHTML === "") {
336
+ box.innerHTML = `<div class="msg ai-msg"><div class="ai-content"><h1>Hi ${currentUser},</h1><p>Ready to master your <strong>Studies</strong> today?</p></div></div>`;
337
  }
338
  }
339
  }
 
395
  const imgData = currentAttachment.type === 'image' ? currentAttachment.data : null;
396
  const fileText = currentAttachment.type === 'file' ? currentAttachment.data : null;
397
 
398
+ input.value = ''; input.style.height= 'auto';
399
  clearAttachment();
400
  scrollToBottom();
401
 
 
449
  function editMessage(oldText) { document.getElementById('input').value = oldText; document.getElementById('input').focus(); }
450
  function regenerate(text) { document.getElementById('input').value = text; send(); }
451
 
452
+ // --- HISTORY LOGIC ---
453
  function handleHistoryTouchStart(e, cid, title) {
454
  longPressTimer = setTimeout(() => {
455
  e.target.closest('.history-item').classList.add('active-mode');
456
+ }, 600);
457
  }
458
  function handleHistoryTouchEnd(e) { clearTimeout(longPressTimer); }
459
 
 
487
  } catch(e) {}
488
  }
489
 
 
490
  async function typeWriter(element, markdownText) {
491
  element.innerHTML = marked.parse(markdownText);
492
+ hljs.highlightAll();
493
  if (window.MathJax) await MathJax.typesetPromise([element]);
494
  if (window.mermaid) {
495
  const m = element.querySelectorAll('code.language-mermaid');
 
506
  const r = await fetch('/new_chat', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({username:currentUser})});
507
  const d = await r.json(); currentChatId = d.chat_id; loadHistory();
508
  document.getElementById('sidebar').classList.remove('open');
509
+ showApp();
510
  }
511
  async function loadChat(cid) {
512
  currentChatId = cid; const res = await fetch('/get_chat', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({username:currentUser, chat_id:cid})});
 
597
  save_db(user_db)
598
  return jsonify({"response": reply, "new_title": new_title})
599
 
600
+ # --- PWA CONFIG FOR FULLSCREEN ---
601
  @app.route('/manifest.json')
602
  def manifest():
603
  data = {
604
+ "name": "Student's AI",
605
+ "short_name": "StudentAI",
606
+ "start_url": "/",
607
+ "display": "standalone",
608
+ "orientation": "portrait",
609
+ "background_color": "#09090b",
610
+ "theme_color": "#09090b",
611
  "icons": [{"src": "https://cdn-icons-png.flaticon.com/512/4712/4712035.png", "sizes": "192x192", "type": "image/png"}]
612
  }
613
  return Response(json.dumps(data), mimetype='application/json')
614
 
615
  if __name__ == '__main__':
616
  app.run(host='0.0.0.0', port=7860)