testrro commited on
Commit
7a2e71e
·
verified ·
1 Parent(s): b0cd107

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +505 -0
app.py ADDED
@@ -0,0 +1,505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pandas as pd
4
+ from datetime import datetime
5
+ import random
6
+ from collections import defaultdict
7
+ import math
8
+ import os
9
+ import traceback
10
+
11
+ # ==================== কনফিগারেশন ====================
12
+ CONFIG = {
13
+ "HISTORY_LIMIT": 1000,
14
+ "PINK_THRESHOLD": 3.0,
15
+ "BIG_PINK_THRESHOLD": 5.0,
16
+ }
17
+
18
+ # ==================== ডেটা লোড ও টাইম-ভিত্তিক পরিসংখ্যান ====================
19
+ TIME_STATS = None
20
+
21
+ def load_time_statistics():
22
+ global TIME_STATS
23
+ try:
24
+ # ডেটা ফাইলের পাথ
25
+ data_path = 'data/aviator_Rounds_history_scrp.xlsx'
26
+ if os.path.exists(data_path):
27
+ df = pd.read_excel(data_path, sheet_name='scraping rounds crash')
28
+ df = df[['ROUNDS', 'TIME ROUND']].dropna()
29
+ df['multiplier'] = pd.to_numeric(df['ROUNDS'], errors='coerce')
30
+ df = df.dropna()
31
+ df['hour'] = pd.to_datetime(df['TIME ROUND'], format='%H:%M').dt.hour
32
+
33
+ stats = df.groupby('hour')['multiplier'].agg(['mean', 'std', 'count']).to_dict('index')
34
+ for h in range(24):
35
+ if h not in stats:
36
+ stats[h] = {'mean': 1.8, 'std': 1.0, 'count': 0}
37
+ TIME_STATS = stats
38
+ print(f"✅ সময় পরিসংখ্যান লোড হয়েছে। মোট রেকর্ড: {len(df)}")
39
+ else:
40
+ print("⚠️ এক্সেল ফাইল পাওয়া যায়নি। ডিফল্ট পরিসংখ্যান ব্যবহার করা হবে।")
41
+ TIME_STATS = {h: {'mean': 1.8, 'std': 1.0, 'count': 100} for h in range(24)}
42
+ except Exception as e:
43
+ print(f"ডেটা লোড করতে সমস্যা: {e}")
44
+ TIME_STATS = {h: {'mean': 1.8, 'std': 1.0, 'count': 100} for h in range(24)}
45
+
46
+ load_time_statistics()
47
+
48
+ # ==================== স্ট্যাটিস্টিক্যাল মডেল V1-V5 ====================
49
+
50
+ class StatisticalModelV1:
51
+ """V1: বেসিক স্ট্যাটিস্টিক্যাল + আউটলায়ার রিমুভাল"""
52
+ def predict(self, history):
53
+ recent = history[:15]
54
+ if len(recent) < 3:
55
+ return {'prediction': 1.5, 'confidence': 0.3}
56
+
57
+ # আউটলায়ার রিমুভাল (IQR)
58
+ q1, q3 = np.percentile(recent, [25, 75])
59
+ iqr = q3 - q1
60
+ filtered = [x for x in recent if (q1 - 1.5*iqr) <= x <= (q3 + 1.5*iqr)]
61
+ if len(filtered) < 3:
62
+ filtered = recent
63
+
64
+ # ওয়েটেড ট্রেন্ড
65
+ x = np.arange(len(filtered))
66
+ weights = np.linspace(1.5, 0.5, len(filtered))
67
+ weights /= weights.sum()
68
+
69
+ weighted_mean_x = np.average(x, weights=weights)
70
+ weighted_mean_y = np.average(filtered, weights=weights)
71
+
72
+ numerator = np.sum(weights * (x - weighted_mean_x) * (filtered - weighted_mean_y))
73
+ denominator = np.sum(weights * (x - weighted_mean_x)**2)
74
+ trend = numerator / denominator if denominator != 0 else 0
75
+
76
+ prediction = np.median(filtered) + trend * 1.5
77
+
78
+ # কনফিডেন্স
79
+ cv = np.std(filtered) / (np.mean(filtered) + 0.1)
80
+ confidence = min(0.85, 0.5 + len(filtered)/len(recent)*0.3 - cv*0.2)
81
+
82
+ return {'prediction': float(prediction), 'confidence': float(confidence)}
83
+
84
+ class StatisticalModelV2:
85
+ """V2: মাল্টি-টাইমফ্রেম"""
86
+ def predict(self, history):
87
+ timeframes = {'short': history[:5], 'medium': history[:10], 'long': history[:20]}
88
+ preds, confs = [], []
89
+
90
+ for name, data in timeframes.items():
91
+ if len(data) < 3:
92
+ continue
93
+
94
+ ma_3 = np.mean(data[:3]) if len(data)>=3 else np.mean(data)
95
+ ma_5 = np.mean(data[:5]) if len(data)>=5 else ma_3
96
+
97
+ ema = data[0]
98
+ alpha = 0.3
99
+ for v in data[1:]:
100
+ ema = alpha*v + (1-alpha)*ema
101
+
102
+ x = np.arange(len(data))
103
+ trend = np.polyfit(x, data, 1)[0]
104
+
105
+ base = np.mean([ma_3, ma_5, ema])
106
+ preds.append(base + trend * len(data) / 10)
107
+ confs.append(min(0.9, 0.5 + len(data)/40))
108
+
109
+ if not preds:
110
+ return {'prediction': 1.5, 'confidence': 0.3}
111
+
112
+ weights = {'short':0.5, 'medium':0.3, 'long':0.2}
113
+ final_pred = 0
114
+ total_weight = 0
115
+
116
+ for i, name in enumerate(timeframes.keys()):
117
+ if i < len(preds):
118
+ w = weights.get(name, 0.2) * confs[i]
119
+ final_pred += preds[i] * w
120
+ total_weight += w
121
+
122
+ final_pred /= total_weight if total_weight else 1
123
+ confidence = np.mean(confs) * 0.9
124
+
125
+ return {'prediction': float(final_pred), 'confidence': float(confidence)}
126
+
127
+ class StatisticalModelV3:
128
+ """V3: সাইকেল ডিটেকশন"""
129
+ def detect_cycles(self, history):
130
+ if len(history) < 10:
131
+ return None
132
+
133
+ cycles = []
134
+ for period in range(3, 7):
135
+ corrs = []
136
+ for i in range(len(history) - period*2):
137
+ seg1 = history[i:i+period]
138
+ seg2 = history[i+period:i+period*2]
139
+ if len(seg1) == len(seg2):
140
+ corr = np.corrcoef(seg1, seg2)[0,1]
141
+ if not np.isnan(corr):
142
+ corrs.append(abs(corr))
143
+ if corrs and np.mean(corrs) > 0.6:
144
+ cycles.append({'period': period, 'strength': float(np.mean(corrs))})
145
+
146
+ return cycles if cycles else None
147
+
148
+ def predict(self, history):
149
+ recent = history[:20]
150
+ cycles = self.detect_cycles(recent)
151
+ cycle_pred = None
152
+
153
+ if cycles:
154
+ best = max(cycles, key=lambda x: x['strength'])
155
+ period = best['period']
156
+ if len(recent) > period:
157
+ next_val = recent[period:period+1]
158
+ if next_val:
159
+ cycle_pred = next_val[0] * (1 + best['strength'] * 0.1)
160
+
161
+ base_pred = np.median(recent)
162
+ if cycle_pred:
163
+ base_pred = (base_pred + cycle_pred) / 2
164
+
165
+ prediction = max(1.05, min(12.0, base_pred))
166
+ confidence = min(0.9, 0.5 + len(recent)/40 + (0.15 if cycles else 0))
167
+
168
+ return {'prediction': float(prediction), 'confidence': float(confidence)}
169
+
170
+ class StatisticalModelV4:
171
+ """V4: এডাপটিভ লার্নিং"""
172
+ def __init__(self):
173
+ self.performance = []
174
+ self.bias = 0
175
+ self.volatility_regime = 'normal'
176
+
177
+ def detect_volatility(self, history):
178
+ if len(history) < 10:
179
+ return 'normal'
180
+ recent_vol = np.std(history[:5])
181
+ long_vol = np.std(history[:20]) if len(history)>=20 else recent_vol
182
+
183
+ if recent_vol > long_vol * 1.5:
184
+ return 'high'
185
+ elif recent_vol < long_vol * 0.5:
186
+ return 'low'
187
+ else:
188
+ return 'normal'
189
+
190
+ def predict(self, history):
191
+ recent = history[:15]
192
+ self.volatility_regime = self.detect_volatility(history)
193
+
194
+ mean_val, median_val = np.mean(recent), np.median(recent)
195
+
196
+ x = np.arange(len(recent))
197
+ weights = np.exp(-0.2 * x)
198
+ weights /= weights.sum()
199
+
200
+ weighted_mean_x = np.average(x, weights=weights)
201
+ weighted_mean_y = np.average(recent, weights=weights)
202
+
203
+ numerator = np.sum(weights * (x - weighted_mean_x) * (recent - weighted_mean_y))
204
+ denominator = np.sum(weights * (x - weighted_mean_x)**2)
205
+ trend = numerator / denominator if denominator != 0 else 0
206
+
207
+ preds = {'mean': mean_val, 'median': median_val, 'trend': median_val + trend * len(recent) * 0.5}
208
+ w = {'mean': 0.3, 'median': 0.4, 'trend': 0.3}
209
+
210
+ if self.volatility_regime == 'high':
211
+ w['median'] *= 1.5
212
+ elif self.volatility_regime == 'low':
213
+ w['trend'] *= 1.3
214
+
215
+ total = sum(w.values())
216
+ for k in w:
217
+ w[k] /= total
218
+
219
+ prediction = sum(preds[k] * w[k] for k in preds) + self.bias
220
+
221
+ confidence = 0.5 + len(recent)/30
222
+ if self.volatility_regime == 'high':
223
+ confidence *= 0.8
224
+ elif self.volatility_regime == 'low':
225
+ confidence *= 1.2
226
+
227
+ if self.performance:
228
+ recent_perf = np.mean(self.performance[-10:]) if len(self.performance)>=10 else np.mean(self.performance)
229
+ confidence *= (1 + recent_perf * 0.1)
230
+
231
+ confidence = min(0.9, confidence)
232
+
233
+ return {'prediction': float(max(1.05, min(12.0, prediction))), 'confidence': float(confidence)}
234
+
235
+ def update(self, actual, predicted):
236
+ error = abs(actual - predicted) / actual
237
+ acc = max(0, 1 - error)
238
+ self.performance.append(acc)
239
+ if len(self.performance) > 100:
240
+ self.performance = self.performance[-100:]
241
+ self.bias += (actual - predicted) * 0.01
242
+
243
+ class StatisticalModelV5:
244
+ """V5: র‍্যান্ডম ফরেস্ট সিমুলেশন"""
245
+ def __init__(self):
246
+ self.n_estimators = 10
247
+
248
+ def predict(self, history):
249
+ if len(history) < 10:
250
+ return {'prediction': 1.5, 'confidence': 0.5}
251
+
252
+ recent = history[:10]
253
+ trees = []
254
+
255
+ for _ in range(self.n_estimators):
256
+ idx = np.random.choice(len(recent), size=len(recent), replace=True)
257
+ sample = [recent[i] for i in idx]
258
+ if np.random.random() > 0.5:
259
+ trees.append(np.mean(sample))
260
+ else:
261
+ trees.append(np.median(sample))
262
+
263
+ pred = float(np.mean(trees))
264
+ return {'prediction': pred, 'confidence': 0.7}
265
+
266
+ # ==================== V6 মডেল (টাইম-ভিত্তিক) ====================
267
+
268
+ class StatisticalModelV6:
269
+ """V6: টাইম-অফ-ডে অ্যাডজাস্টমেন্ট"""
270
+ def __init__(self, time_stats):
271
+ self.time_stats = time_stats
272
+
273
+ def predict(self, history, current_hour=None):
274
+ if current_hour is None:
275
+ current_hour = datetime.now().hour
276
+
277
+ stats = self.time_stats.get(current_hour, {'mean': 1.8, 'std': 1.0})
278
+ base_pred = np.median(history[:5]) if len(history)>=5 else 1.5
279
+
280
+ alpha = 0.3
281
+ prediction = base_pred * (1 - alpha) + stats['mean'] * alpha
282
+ confidence = min(0.85, 0.5 + stats.get('count', 100) / 500)
283
+
284
+ return {'prediction': float(prediction), 'confidence': float(confidence), 'hour': current_hour}
285
+
286
+ # ==================== এনসেম্বল প্রেডিক্টর ====================
287
+
288
+ class EnsemblePredictorV6:
289
+ def __init__(self, time_stats):
290
+ self.models = {
291
+ 'v1': StatisticalModelV1(),
292
+ 'v2': StatisticalModelV2(),
293
+ 'v3': StatisticalModelV3(),
294
+ 'v4': StatisticalModelV4(),
295
+ 'v5': StatisticalModelV5(),
296
+ 'v6': StatisticalModelV6(time_stats)
297
+ }
298
+ self.ensemble_weights = {'v1':0.2, 'v2':0.2, 'v3':0.15, 'v4':0.15, 'v5':0.15, 'v6':0.15}
299
+ self.performance = defaultdict(list)
300
+
301
+ def predict(self, history):
302
+ if len(history) < 5:
303
+ return self._default_prediction(f"মাত্র {len(history)}টি রাউন্ড, ৫টি প্রয়োজন")
304
+
305
+ current_hour = datetime.now().hour
306
+ preds = {}
307
+ confs = {}
308
+
309
+ for name, model in self.models.items():
310
+ if name == 'v6':
311
+ res = model.predict(history, current_hour)
312
+ else:
313
+ res = model.predict(history)
314
+ preds[name] = res['prediction']
315
+ confs[name] = res.get('confidence', 0.5)
316
+
317
+ # ওয়েট আপডেট
318
+ for name in self.ensemble_weights:
319
+ if name in self.performance and self.performance[name]:
320
+ recent_acc = np.mean(self.performance[name][-20:]) if len(self.performance[name])>=20 else np.mean(self.performance[name])
321
+ self.ensemble_weights[name] = 0.1 + recent_acc * 0.8
322
+
323
+ total = sum(self.ensemble_weights.values())
324
+ for name in self.ensemble_weights:
325
+ self.ensemble_weights[name] /= total
326
+
327
+ final_pred = 0
328
+ total_weight = 0
329
+ for name, pred in preds.items():
330
+ weight = self.ensemble_weights.get(name, 0.2) * confs[name]
331
+ final_pred += pred * weight
332
+ total_weight += weight
333
+
334
+ final_pred /= total_weight if total_weight else 1
335
+
336
+ # মার্কেট স্টেট
337
+ recent = history[:10]
338
+ vol = np.std(recent) / (np.mean(recent)+0.1)
339
+ if vol > 0.5:
340
+ state = "অস্থির 🌪️"
341
+ elif vol < 0.2:
342
+ state = "স্থিতিশীল ✨"
343
+ else:
344
+ state = "সাধারণ ➡️"
345
+
346
+ confidence = np.mean(list(confs.values())) * 0.9
347
+ if vol < 0.2:
348
+ confidence *= 1.1
349
+ elif vol > 0.5:
350
+ confidence *= 0.9
351
+ confidence = min(0.95, confidence)
352
+
353
+ # প্রেডিকশন ইন্টারভ্যাল
354
+ all_preds = list(preds.values())
355
+ std = np.std(all_preds) if len(all_preds)>1 else 0.2
356
+ spread = std * (2 - confidence)
357
+ spread = max(0.1, min(1.5, spread))
358
+ interval = (max(1.01, final_pred - spread/2), final_pred + spread/2)
359
+
360
+ # ডিসিশন
361
+ if final_pred > 3.0:
362
+ decision = "বড় 🚀"
363
+ elif final_pred > 1.8:
364
+ decision = "মাঝারি 💪"
365
+ else:
366
+ decision = "ছোট 🎯"
367
+
368
+ hour_stats = TIME_STATS.get(current_hour, {'mean':1.8, 'count':0})
369
+ time_info = f"বর্তমান ঘণ্টা: {current_hour}:00 – ঐতিহাসিক গড়: {hour_stats['mean']:.2f}x (ডাটা: {hour_stats['count']}টি)"
370
+
371
+ summary = (
372
+ f"🎯 **প্রেডিকশন ইন্টারভ্যাল**: {interval[0]:.2f}x – {interval[1]:.2f}x\n"
373
+ f"📊 **এক্সপেক্টেড মাল্টিপ্লায়ার**: {final_pred:.2f}x\n"
374
+ f"📈 **কনফিডেন্স**: {confidence*100:.1f}%\n"
375
+ f"⚡ **মার্কেট স্টেট**: {state}\n"
376
+ f"🎲 **ডিসিশন**: {decision}\n"
377
+ f"⏰ **টাইম ফিচার**: {time_info}\n"
378
+ f"📌 **ডাটা পয়েন্ট**: {len(history)}টি রাউন্ড"
379
+ )
380
+
381
+ return {
382
+ 'summary': summary,
383
+ 'prediction': final_pred,
384
+ 'interval': interval,
385
+ 'confidence': confidence,
386
+ 'decision': decision,
387
+ 'analysis': state,
388
+ 'hour': current_hour
389
+ }
390
+
391
+ def _default_prediction(self, msg):
392
+ return {
393
+ 'summary': f"⚠️ {msg}\n\n📊 ডিফল্ট প্রেডিকশন: 1.50x (কনফিডেন্স 30%)",
394
+ 'prediction': 1.5,
395
+ 'interval': (1.3, 1.7),
396
+ 'confidence': 0.3,
397
+ 'decision': 'ছোট 🎯',
398
+ 'analysis': 'অপ্রতুল ডাটা'
399
+ }
400
+
401
+ # ==================== অ্যাপ্লিকেশন ক্লাস ====================
402
+
403
+ class AviatorPredictorApp:
404
+ def __init__(self):
405
+ self.history = []
406
+ self.model = EnsemblePredictorV6(TIME_STATS)
407
+
408
+ def add_round(self, multiplier):
409
+ if multiplier <= 0:
410
+ return self.get_all_outputs(error="ইনভ্যালিড মাল্টিপ্লায়ার (১.০ এর বেশি দিন)")
411
+
412
+ self.history.insert(0, float(multiplier))
413
+ if len(self.history) > CONFIG["HISTORY_LIMIT"]:
414
+ self.history = self.history[:CONFIG["HISTORY_LIMIT"]]
415
+
416
+ return self.get_all_outputs()
417
+
418
+ def reset(self):
419
+ self.history = []
420
+ for _ in range(20):
421
+ self.history.append(round(random.uniform(1.0, 3.5), 2))
422
+ self.history.sort(reverse=True)
423
+ return self.get_all_outputs()
424
+
425
+ def get_all_outputs(self, error=None):
426
+ if error:
427
+ table = [[i+1, "?.??x"] for i in range(min(20, len(self.history)))] or [[1, "1.00x"]]
428
+ return [table, f"⚠️ {error}"]
429
+
430
+ pred_result = self.model.predict(self.history)
431
+ table = [[i+1, f"{val:.2f}x"] for i, val in enumerate(self.history[:50])]
432
+ return [table, pred_result['summary']]
433
+
434
+ # ==================== কাস্টম CSS ====================
435
+
436
+ CUSTOM_CSS = """
437
+ .gradio-container {
438
+ background: #0a0a0f !important;
439
+ color: #ffffff !important;
440
+ font-family: 'Inter', sans-serif !important;
441
+ }
442
+ footer {visibility: hidden}
443
+ h1 {
444
+ color: #00d4ff !important;
445
+ text-align: center;
446
+ margin-bottom: 20px;
447
+ text-shadow: 0 0 10px #00d4ff;
448
+ }
449
+ .gr-box {
450
+ border: 1px solid #333 !important;
451
+ background: rgba(255,255,255,0.05) !important;
452
+ }
453
+ .gr-button-primary {
454
+ background: linear-gradient(135deg, #00d4ff, #0088ff) !important;
455
+ border: none !important;
456
+ }
457
+ .gr-button-secondary {
458
+ background: rgba(255,255,255,0.1) !important;
459
+ border: 1px solid #00d4ff !important;
460
+ margin-top: 20px !important;
461
+ }
462
+ .gr-dataframe {
463
+ background: rgba(255,255,255,0.05) !important;
464
+ }
465
+ """
466
+
467
+ # ==================== গ্র্যাডিও ইন্টারফেস ====================
468
+
469
+ app = AviatorPredictorApp()
470
+ app.reset()
471
+
472
+ with gr.Blocks(css=CUSTOM_CSS, theme='dark', title="AVOLD V6 Predictor") as demo:
473
+ gr.HTML("""
474
+ <div style="text-align: center; margin-bottom: 20px;">
475
+ <h1 style="color: #00d4ff; font-size: 48px; margin: 0;">✈️ AVOLD V6</h1>
476
+ <p style="color: #888; font-size: 14px;">সময়-ভিত্তিক এভিয়েটর প্রেডিক্টর – ৬টি মডেলের এনসেম্বল</p>
477
+ </div>
478
+ """)
479
+
480
+ with gr.Row():
481
+ inp = gr.Number(label="নতুন মাল্টিপ্লায়ার", value=1.0, step=0.1, minimum=1.0)
482
+ add_btn = gr.Button("➕ যোগ করুন", variant="primary")
483
+
484
+ prediction_box = gr.Textbox(label="🧠 প্রেডিকশন রিপোর্ট", lines=10, interactive=False)
485
+ rounds_table = gr.Dataframe(label="📜 শেষ ৫০ রাউন্ড", headers=["রাউন্ড", "মাল্টিপ্লায়ার"], row_count=10)
486
+ reset_btn = gr.Button("🔄 রিসেট ডাটা", variant="secondary")
487
+
488
+ add_btn.click(
489
+ fn=app.add_round,
490
+ inputs=inp,
491
+ outputs=[rounds_table, prediction_box]
492
+ )
493
+
494
+ reset_btn.click(
495
+ fn=app.reset,
496
+ outputs=[rounds_table, prediction_box]
497
+ )
498
+
499
+ demo.load(
500
+ fn=app.get_all_outputs,
501
+ outputs=[rounds_table, prediction_box]
502
+ )
503
+
504
+ if __name__ == "__main__":
505
+ demo.launch(server_name="0.0.0.0", server_port=7860)