Spaces:
Sleeping
Sleeping
bngoc commited on
Commit ·
871dcd5
1
Parent(s): 827aad2
app_foxai
Browse files- .gradio/certificate.pem +31 -0
- .vscode/settings.json +4 -0
- app.py +669 -356
- app_backup.py +812 -0
- app_fixed.py +784 -0
- bro.css +174 -0
- test_data.csv +6 -0
.gradio/certificate.pem
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
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
|
| 31 |
+
-----END CERTIFICATE-----
|
.vscode/settings.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"python-envs.defaultEnvManager": "ms-python.python:venv",
|
| 3 |
+
"python-envs.pythonProjects": []
|
| 4 |
+
}
|
app.py
CHANGED
|
@@ -1,31 +1,67 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
import pandas as pd
|
| 3 |
import plotly.graph_objects as go
|
| 4 |
-
import plotly.express as px
|
| 5 |
-
from plotly.subplots import make_subplots
|
| 6 |
import numpy as np
|
| 7 |
from datetime import datetime, timedelta
|
| 8 |
import random
|
| 9 |
import time
|
| 10 |
|
| 11 |
-
#
|
|
|
|
|
|
|
|
|
|
| 12 |
custom_css = """
|
| 13 |
.gradio-container {
|
| 14 |
-
background: linear-gradient(135deg, #
|
| 15 |
-
font-family: 'Segoe UI',
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
.header-container {
|
| 19 |
text-align: center;
|
| 20 |
margin: 20px 0;
|
| 21 |
-
padding:
|
| 22 |
-
background: linear-gradient(
|
| 23 |
-
border-radius:
|
| 24 |
-
box-shadow: 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
}
|
| 26 |
|
| 27 |
.header-title {
|
| 28 |
-
background: linear-gradient(90deg, #
|
| 29 |
background-size: 300% 300%;
|
| 30 |
animation: gradient 8s ease infinite;
|
| 31 |
-webkit-background-clip: text;
|
|
@@ -33,8 +69,11 @@ custom_css = """
|
|
| 33 |
background-clip: text;
|
| 34 |
text-align: center;
|
| 35 |
font-size: 3em;
|
| 36 |
-
font-weight:
|
| 37 |
-
margin:
|
|
|
|
|
|
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
@keyframes gradient {
|
|
@@ -46,15 +85,17 @@ custom_css = """
|
|
| 46 |
.loading-container {
|
| 47 |
text-align: center;
|
| 48 |
padding: 40px;
|
| 49 |
-
background: linear-gradient(
|
| 50 |
-
border-radius:
|
| 51 |
color: white;
|
| 52 |
margin: 20px 0;
|
|
|
|
|
|
|
| 53 |
}
|
| 54 |
|
| 55 |
.loading-spinner {
|
| 56 |
border: 4px solid #f3f3f3;
|
| 57 |
-
border-top: 4px solid #
|
| 58 |
border-radius: 50%;
|
| 59 |
width: 40px;
|
| 60 |
height: 40px;
|
|
@@ -78,9 +119,10 @@ custom_css = """
|
|
| 78 |
|
| 79 |
.progress-fill {
|
| 80 |
height: 100%;
|
| 81 |
-
background: linear-gradient(90deg, #
|
| 82 |
border-radius: 10px;
|
| 83 |
animation: progress 3s ease-in-out;
|
|
|
|
| 84 |
}
|
| 85 |
|
| 86 |
@keyframes progress {
|
|
@@ -92,79 +134,148 @@ custom_css = """
|
|
| 92 |
}
|
| 93 |
|
| 94 |
.prediction-box {
|
| 95 |
-
background: linear-gradient(
|
| 96 |
-
border-radius:
|
| 97 |
-
padding:
|
| 98 |
color: white;
|
| 99 |
text-align: center;
|
| 100 |
-
font-size: 1.
|
| 101 |
-
font-weight:
|
| 102 |
-
box-shadow: 0
|
| 103 |
margin: 15px 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
}
|
| 105 |
|
| 106 |
.insight-box {
|
| 107 |
-
background: linear-gradient(
|
| 108 |
-
border-radius:
|
| 109 |
-
padding:
|
| 110 |
color: white;
|
| 111 |
margin: 15px 0;
|
| 112 |
-
box-shadow: 0
|
|
|
|
|
|
|
|
|
|
| 113 |
}
|
| 114 |
|
| 115 |
.executive-summary {
|
| 116 |
-
background: linear-gradient(
|
| 117 |
-
border-radius:
|
| 118 |
-
padding:
|
| 119 |
color: white;
|
| 120 |
margin: 15px 0;
|
| 121 |
-
box-shadow: 0
|
| 122 |
-
border-left: 5px solid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
}
|
| 124 |
|
| 125 |
.feature-box {
|
| 126 |
-
background: linear-gradient(135deg,
|
| 127 |
-
border-radius:
|
| 128 |
-
padding:
|
| 129 |
-
margin:
|
| 130 |
-
box-shadow: 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
}
|
| 132 |
|
| 133 |
.system-status {
|
| 134 |
-
background: linear-gradient(
|
| 135 |
color: white;
|
| 136 |
-
padding:
|
| 137 |
-
border-radius:
|
| 138 |
-
margin:
|
| 139 |
text-align: center;
|
| 140 |
-
font-weight:
|
|
|
|
|
|
|
|
|
|
| 141 |
}
|
| 142 |
|
| 143 |
.metric-card {
|
| 144 |
-
background: linear-gradient(
|
| 145 |
color: white;
|
| 146 |
-
border-radius:
|
| 147 |
-
padding:
|
| 148 |
-
margin:
|
| 149 |
text-align: center;
|
| 150 |
-
box-shadow: 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
}
|
| 152 |
|
| 153 |
.button-predict {
|
| 154 |
-
background: linear-gradient(135deg, #
|
| 155 |
color: white !important;
|
| 156 |
border: none !important;
|
| 157 |
border-radius: 25px !important;
|
| 158 |
padding: 15px 30px !important;
|
| 159 |
font-size: 16px !important;
|
| 160 |
font-weight: bold !important;
|
| 161 |
-
box-shadow: 0 4px 15px rgba(
|
| 162 |
transition: all 0.3s ease !important;
|
| 163 |
}
|
| 164 |
|
| 165 |
.button-predict:hover {
|
| 166 |
transform: translateY(-2px) !important;
|
| 167 |
-
box-shadow: 0 6px 20px rgba(
|
| 168 |
}
|
| 169 |
|
| 170 |
.plot-container {
|
|
@@ -174,6 +285,7 @@ custom_css = """
|
|
| 174 |
margin: 15px 0;
|
| 175 |
background: rgba(255, 255, 255, 0.95);
|
| 176 |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
|
|
|
| 177 |
}
|
| 178 |
|
| 179 |
.info-card {
|
|
@@ -181,279 +293,385 @@ custom_css = """
|
|
| 181 |
border-radius: 10px;
|
| 182 |
padding: 15px;
|
| 183 |
margin: 10px 0;
|
| 184 |
-
border-left: 5px solid #
|
| 185 |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 186 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
"""
|
| 188 |
|
| 189 |
-
# Dữ liệu demo tiếng Việt cho
|
| 190 |
TRUONG_HOP_DEMO = {
|
| 191 |
-
"📱 Điện
|
| 192 |
"danh_muc": "Điện tử & Công nghệ",
|
| 193 |
-
"mua_vu": "Tết Nguyên Đán",
|
| 194 |
"don_vi_co_ban": 150,
|
| 195 |
-
"xu_huong": "
|
| 196 |
-
"mo_ta": "Dự báo bán hàng điện
|
| 197 |
"thong_tin_giam_doc": {
|
| 198 |
-
"tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện
|
| 199 |
-
"chi_tiet": "**📊 PHÂN TÍCH KINH DOANH:**
|
| 200 |
-
"hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH:** (1) Tăng tồn kho 200%
|
| 201 |
}
|
| 202 |
},
|
| 203 |
|
| 204 |
-
"👕 Thời trang
|
| 205 |
"danh_muc": "Thời trang & Làm đẹp",
|
| 206 |
-
"mua_vu": "Mùa hè",
|
| 207 |
"don_vi_co_ban": 80,
|
| 208 |
-
"xu_huong": "
|
| 209 |
-
"mo_ta": "Dự báo xu hướng thời trang
|
| 210 |
-
"thong_tin_giam_doc": {
|
| 211 |
-
"tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang hè tăng trường ổn định 15-25%/tuần. Cơ hội mở rộng thị phần thông qua digital marketing Gen Z.",
|
| 212 |
-
"chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG:** Doanh số thời trang hè tăng đều 15-25%/tuần, đỉnh điểm cuối tháng 6 với 1.450 sản phẩm/ngày. Insight quan trọng: Khách hàng mua sắm sớm hơn 3 tuần so với năm trước do biến đổi khí hậu. Top categories: Áo thun (35%), Váy ngắn (28%), Phụ kiện chống nắng (22%).",
|
| 213 |
-
"hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI:** (1) Launch collection sớm hơn 1 tháng, (2) Tập trung social media marketing cho Gen Z (TikTok, Instagram), (3) Collaborate với influencers và fashion bloggers, (4) Tối ưu supply chain để responsive nhanh với trend, (5) Bundle promotion cho outfits hoàn chỉnh."
|
| 214 |
-
}
|
| 215 |
-
},
|
| 216 |
-
|
| 217 |
-
"🏠 Nội thất - Cuối năm": {
|
| 218 |
-
"danh_muc": "Nhà cửa & Trang trí",
|
| 219 |
-
"mua_vu": "Cuối năm",
|
| 220 |
-
"don_vi_co_ban": 45,
|
| 221 |
-
"xu_huong": "dinh_cuoi_nam",
|
| 222 |
-
"mo_ta": "Dự báo thị trường nội thất cuối năm",
|
| 223 |
"thong_tin_giam_doc": {
|
| 224 |
-
"tom_tat": "
|
| 225 |
-
"chi_tiet": "**
|
| 226 |
-
"hanh_dong": "**
|
| 227 |
}
|
| 228 |
},
|
| 229 |
|
| 230 |
-
"🍔
|
| 231 |
"danh_muc": "Thực phẩm & Đồ uống",
|
| 232 |
-
"mua_vu": "Mùa mưa",
|
| 233 |
"don_vi_co_ban": 200,
|
| 234 |
-
"xu_huong": "
|
| 235 |
-
"mo_ta": "Dự báo food delivery
|
| 236 |
-
"thong_tin_giam_doc": {
|
| 237 |
-
"tom_tat": "🌧️ **TÓM TẮT ĐIỀU HÀNH:** Food delivery bùng nổ +280% trong ngày mưa. Đây là vertical growth opportunity cần scale up nhanh.",
|
| 238 |
-
"chi_tiet": "**⛈️ DỮ LIỆU THỜI TIẾT & KINH DOANH:** Orders tăng 280% trong ngày mưa to, peak hours 11h-13h và 17h-20h với 2.650 đơn/ngày. Menu performance: Đồ ăn nóng +250%, comfort food +180%, đồ uống nóng +190%, còn đồ lạnh giảm 65%. Weather correlation mạnh: mỗi mm mưa = +12% orders.",
|
| 239 |
-
"hanh_dong": "**☔ CHIẾN THUẬT THỜI TIẾT:** (1) 'Rainy Day Menu' với phở, bún bò, trà nóng, (2) Surge pricing nhẹ (+10%) để incentivize drivers, (3) Pre-positioning inventory ở các hub gần residential areas, (4) Partnership với weather apps để predictive marketing, (5) Rain insurance cho delivery partners."
|
| 240 |
-
}
|
| 241 |
-
},
|
| 242 |
-
|
| 243 |
-
"📚 Sách - Mùa thi": {
|
| 244 |
-
"danh_muc": "Sách & Giáo dục",
|
| 245 |
-
"mua_vu": "Mùa thi đại học",
|
| 246 |
-
"don_vi_co_ban": 60,
|
| 247 |
-
"xu_huong": "mua_thi",
|
| 248 |
-
"mo_ta": "Dự báo bán sách trong mùa thi đại học",
|
| 249 |
-
"thong_tin_giam_doc": {
|
| 250 |
-
"tom_tat": "🎓 **TÓM TẮT ĐIỀU HÀNH:** Sách giáo dục spike +320% trong 6 tuần thi đại học. Seasonal business với ROI cao nếu execute đúng timing.",
|
| 251 |
-
"chi_tiet": "**📖 PHÂN TÍCH GIÁO DỤC:** Doanh số tăng 320% trong 6 tuần trước đại học, peak tuần 3-4 với 1.280 cuốn/ngày. Portfolio breakdown: Sách ôn thi (70%), Tham khảo (20%), Đề thi thử (10%). Buying pattern: Wave 1 (sách tổng quan), Wave 2 (chuyên sâu), Wave 3 (đề thi). Target customers: 900K học sinh + phụ huynh.",
|
| 252 |
-
"hanh_dong": "**📝 ROADMAP GIÁO DỤC:** (1) 'Bộ sách thi đại học hoàn chỉnh' với pre-order discount, (2) Just-in-time inventory system, (3) Online practice tests integration, (4) Scholarship program cho top students để build brand awareness, (5) Partnership với các trung tâm luyện thi."
|
| 253 |
-
}
|
| 254 |
-
},
|
| 255 |
-
|
| 256 |
-
"🎮 Gaming - Black Friday": {
|
| 257 |
-
"danh_muc": "Game & Giải trí",
|
| 258 |
-
"mua_vu": "Black Friday",
|
| 259 |
-
"don_vi_co_ban": 120,
|
| 260 |
-
"xu_huong": "bung_no_black_friday",
|
| 261 |
-
"mo_ta": "Dự báo gaming gear trong Black Friday",
|
| 262 |
"thong_tin_giam_doc": {
|
| 263 |
-
"tom_tat": "
|
| 264 |
-
"chi_tiet": "**
|
| 265 |
-
"hanh_dong": "**
|
| 266 |
}
|
| 267 |
-
}
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
"xu_huong": "tang_valentine",
|
| 274 |
-
"mo_ta": "Dự báo mỹ phẩm ngày Valentine",
|
| 275 |
-
"thong_tin_giam_doc": {
|
| 276 |
-
"tom_tat": "💕 **TÓM TẮT ĐIỀU HÀNH:** Beauty products spike +240% trước Valentine. Dual-market opportunity: self-purchase (60%) và gifts (40%).",
|
| 277 |
-
"chi_tiet": "**💋 BEAUTY MARKET INTELLIGENCE:** Spike +240% với 2 waves: Preparation week (+180%) và Valentine day (+320%). Top performers: Lipstick (+290%), Perfume (+260%), Skincare sets (+170%). Gender split: Phụ nữ self-purchase (60%) vs Nam giới mua quà (40%). Price elasticity thấp - khách hàng accept premium pricing.",
|
| 278 |
-
"hanh_dong": "**💝 VALENTINE EXECUTION:** (1) Limited edition Valentine collections với premium packaging, (2) 'His & Hers' couple combo deals, (3) Gender-targeted marketing campaigns, (4) Same-day delivery cho last-minute shoppers, (5) After-Valentine retention với personalized beauty tips."
|
| 279 |
-
}
|
| 280 |
-
},
|
| 281 |
|
| 282 |
-
|
| 283 |
-
"
|
| 284 |
-
"
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
"
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
|
| 295 |
-
|
| 296 |
-
"
|
| 297 |
-
"
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
"
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
}
|
| 306 |
-
},
|
| 307 |
|
| 308 |
-
|
| 309 |
-
"danh_muc": "Cà phê & Đồ uống",
|
| 310 |
-
"mua_vu": "Mùa đông",
|
| 311 |
-
"don_vi_co_ban": 180,
|
| 312 |
-
"xu_huong": "am_ap_mua_dong",
|
| 313 |
-
"mo_ta": "Dự báo thị trường cà phê mùa đông",
|
| 314 |
-
"thong_tin_giam_doc": {
|
| 315 |
-
"tom_tat": "❄️ **TÓM TẮT ĐIỀU HÀNH:** Coffee consumption +210% mùa đông với premium opportunity. WFH trend tạo new consumption patterns.",
|
| 316 |
-
"chi_tiet": "**☕ COFFEE MARKET DYNAMICS:** Consumption +210% mùa đông, clear shift hot beverages (+270%) vs cold (-45%). Weather correlation: -1°C = +15 units demand. WFH impact: Morning spike 7-9AM (+320%), afternoon comfort 14-16h (+200%). Premium segments: Seasonal flavors command 25% price premium.",
|
| 317 |
-
"hanh_dong": "**🌡️ WINTER COFFEE STRATEGY:** (1) Limited winter blends (cinnamon, vanilla) để create urgency, (2) 'Warm-up Delivery Deals' với delivery apps, (3) Corporate packages cho offices, (4) Subscription models cho regular customers, (5) Coffee equipment bundling cho home brewing trend."
|
| 318 |
-
}
|
| 319 |
-
}
|
| 320 |
-
}
|
| 321 |
|
| 322 |
-
def
|
| 323 |
-
"""
|
| 324 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
"""
|
|
|
|
|
|
|
|
|
|
| 326 |
don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
|
| 327 |
xu_huong = thong_tin_case["xu_huong"]
|
| 328 |
|
| 329 |
-
# Xác định số điểm dữ liệu
|
| 330 |
if chu_ky == "1 năm":
|
| 331 |
-
if che_do_xem == 'năm'
|
| 332 |
-
so_diem = 12 # 12 tháng
|
| 333 |
-
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 334 |
-
elif che_do_xem == 'tháng':
|
| 335 |
-
so_diem = 52 # 52 tuần
|
| 336 |
-
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 337 |
-
else: # ngày
|
| 338 |
-
so_diem = 365 # 365 ngày
|
| 339 |
-
ngay_bat_dau = datetime.now()
|
| 340 |
-
nhan_thoi_gian = []
|
| 341 |
-
for i in range(so_diem):
|
| 342 |
-
ngay_hien_tai = ngay_bat_dau + timedelta(days=i)
|
| 343 |
-
nhan_thoi_gian.append(ngay_hien_tai.strftime("%d/%m"))
|
| 344 |
-
|
| 345 |
elif chu_ky == "6 tháng":
|
| 346 |
-
if che_do_xem == 'năm'
|
| 347 |
-
so_diem = 6 # 6 tháng
|
| 348 |
-
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 349 |
-
elif che_do_xem == 'tháng':
|
| 350 |
-
so_diem = 26 # 26 tuần
|
| 351 |
-
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 352 |
-
else: # ngày
|
| 353 |
-
so_diem = 180 # 180 ngày
|
| 354 |
-
ngay_bat_dau = datetime.now()
|
| 355 |
-
nhan_thoi_gian = []
|
| 356 |
-
for i in range(so_diem):
|
| 357 |
-
ngay_hien_tai = ngay_bat_dau + timedelta(days=i)
|
| 358 |
-
nhan_thoi_gian.append(ngay_hien_tai.strftime("%d/%m"))
|
| 359 |
-
|
| 360 |
else: # "3 tháng"
|
| 361 |
-
if che_do_xem == 'năm'
|
| 362 |
-
so_diem = 3 # 3 tháng
|
| 363 |
-
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 364 |
-
elif che_do_xem == 'tháng':
|
| 365 |
-
so_diem = 13 # 13 tuần
|
| 366 |
-
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 367 |
-
else: # ngày
|
| 368 |
-
so_diem = 90 # 90 ngày
|
| 369 |
-
ngay_bat_dau = datetime.now()
|
| 370 |
-
nhan_thoi_gian = []
|
| 371 |
-
for i in range(so_diem):
|
| 372 |
-
ngay_hien_tai = ngay_bat_dau + timedelta(days=i)
|
| 373 |
-
nhan_thoi_gian.append(ngay_hien_tai.strftime("%d/%m"))
|
| 374 |
|
| 375 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
|
|
|
|
|
|
|
| 377 |
for i in range(so_diem):
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
elif xu_huong == "tang_dan_he":
|
| 387 |
-
he_so = 1 + (i / so_diem) * 2.2
|
| 388 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-40, 40))
|
| 389 |
-
|
| 390 |
-
elif xu_huong == "dinh_cuoi_nam":
|
| 391 |
-
if i in [so_diem//3, 2*so_diem//3]:
|
| 392 |
-
he_so = 3.2
|
| 393 |
-
elif i < so_diem//3 or i > 2*so_diem//3:
|
| 394 |
-
he_so = 1.4
|
| 395 |
-
else:
|
| 396 |
-
he_so = 2.0
|
| 397 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-50, 50))
|
| 398 |
-
|
| 399 |
-
elif xu_huong == "phu_thuoc_thoi_tiet":
|
| 400 |
-
yeu_to_thoi_tiet = random.choice([0.7, 1.3, 2.8, 3.2, 1.6, 0.8, 2.5])
|
| 401 |
-
don_vi = int(don_vi_co_ban * yeu_to_thoi_tiet + random.randint(-70, 70))
|
| 402 |
-
|
| 403 |
-
elif xu_huong == "mua_thi":
|
| 404 |
-
if i < so_diem * 0.6:
|
| 405 |
-
he_so = 1 + (i / (so_diem * 0.6)) * 3.5
|
| 406 |
-
else:
|
| 407 |
-
he_so = 4.5 - ((i - so_diem * 0.6) / (so_diem * 0.4)) * 3.0
|
| 408 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-55, 55))
|
| 409 |
-
|
| 410 |
-
elif xu_huong == "bung_no_black_friday":
|
| 411 |
-
if i in [1, 2]:
|
| 412 |
-
he_so = 5.2
|
| 413 |
-
elif i in [0, 3]:
|
| 414 |
-
he_so = 2.3
|
| 415 |
-
else:
|
| 416 |
-
he_so = 1.5
|
| 417 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-45, 45))
|
| 418 |
-
|
| 419 |
-
elif xu_huong == "tang_valentine":
|
| 420 |
-
if i == so_diem - 1:
|
| 421 |
-
he_so = 3.6
|
| 422 |
-
elif i >= so_diem - 3:
|
| 423 |
-
he_so = 2.8
|
| 424 |
-
else:
|
| 425 |
-
he_so = 1 + (i / (so_diem - 3)) * 1.8
|
| 426 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-35, 35))
|
| 427 |
-
|
| 428 |
-
elif xu_huong == "quyet_tam_nam_moi":
|
| 429 |
-
if i <= 2:
|
| 430 |
-
he_so = 4.5 - (i * 0.6)
|
| 431 |
-
else:
|
| 432 |
-
he_so = 3.3 - ((i - 2) / (so_diem - 2)) * 2.5
|
| 433 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-50, 50))
|
| 434 |
-
|
| 435 |
-
elif xu_huong == "tet_trung_thu":
|
| 436 |
-
if i >= so_diem - 3:
|
| 437 |
-
he_so = 3.8 - (so_diem - 1 - i) * 0.4
|
| 438 |
-
else:
|
| 439 |
-
he_so = 1 + (i / (so_diem - 3)) * 2.0
|
| 440 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-40, 40))
|
| 441 |
-
|
| 442 |
-
elif xu_huong == "am_ap_mua_dong":
|
| 443 |
-
he_so_co_ban = 1 + (i / so_diem) * 1.8
|
| 444 |
-
bien_dong_thoi_tiet = random.choice([0.7, 1.1, 1.4, 1.8, 1.2, 0.9])
|
| 445 |
-
he_so = he_so_co_ban * bien_dong_thoi_tiet
|
| 446 |
-
don_vi = int(don_vi_co_ban * he_so + random.randint(-45, 45))
|
| 447 |
|
| 448 |
-
don_vi = max(
|
| 449 |
don_vi_ban.append(don_vi)
|
| 450 |
|
| 451 |
return nhan_thoi_gian, don_vi_ban
|
| 452 |
|
| 453 |
def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 454 |
-
"""
|
| 455 |
-
Tạo biểu đồ dự đoán với hiệu ứng loading
|
| 456 |
-
"""
|
| 457 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 458 |
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 459 |
|
|
@@ -466,8 +684,8 @@ def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 466 |
y=don_vi_ban,
|
| 467 |
mode='lines+markers',
|
| 468 |
name='📦 Dự Báo Đơn Vị Bán',
|
| 469 |
-
line=dict(color='#
|
| 470 |
-
marker=dict(size=12, color='#
|
| 471 |
hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
|
| 472 |
))
|
| 473 |
|
|
@@ -479,7 +697,7 @@ def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 479 |
x=nhan_thoi_gian + nhan_thoi_gian[::-1],
|
| 480 |
y=upper_bound + lower_bound[::-1],
|
| 481 |
fill='toself',
|
| 482 |
-
fillcolor='rgba(
|
| 483 |
line=dict(color='rgba(255,255,255,0)'),
|
| 484 |
name='📊 Vùng Tin Cậy',
|
| 485 |
hoverinfo="skip"
|
|
@@ -495,7 +713,7 @@ def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 495 |
y=duong_xu_huong,
|
| 496 |
mode='lines',
|
| 497 |
name='📈 Xu Hướng',
|
| 498 |
-
line=dict(color='#
|
| 499 |
hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
|
| 500 |
))
|
| 501 |
|
|
@@ -535,9 +753,7 @@ def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 535 |
return fig
|
| 536 |
|
| 537 |
def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 538 |
-
"""
|
| 539 |
-
Tạo thông tin tóm tắt dành cho giám đốc
|
| 540 |
-
"""
|
| 541 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 542 |
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 543 |
|
|
@@ -580,7 +796,6 @@ def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 580 |
<div style="margin-top: 15px; text-align: center;">
|
| 581 |
<p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
|
| 582 |
<p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
|
| 583 |
-
<p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Mùa Vụ: <strong>{thong_tin_case['mua_vu']}</strong></p>
|
| 584 |
</div>
|
| 585 |
</div>
|
| 586 |
"""
|
|
@@ -588,16 +803,14 @@ def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
|
| 588 |
return tom_tat_html
|
| 589 |
|
| 590 |
def tao_bao_cao_giam_doc(ten_case):
|
| 591 |
-
"""
|
| 592 |
-
Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown
|
| 593 |
-
"""
|
| 594 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 595 |
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 596 |
|
| 597 |
bao_cao_markdown = f"""
|
| 598 |
-
#
|
| 599 |
|
| 600 |
-
##
|
| 601 |
|
| 602 |
{thong_tin_gd['tom_tat']}
|
| 603 |
|
|
@@ -610,15 +823,13 @@ def tao_bao_cao_giam_doc(ten_case):
|
|
| 610 |
{thong_tin_gd['hanh_dong']}
|
| 611 |
|
| 612 |
---
|
| 613 |
-
*🤖 Phân tích được tạo bởi
|
| 614 |
"""
|
| 615 |
|
| 616 |
return bao_cao_markdown
|
| 617 |
|
| 618 |
def tao_loading_effect():
|
| 619 |
-
"""
|
| 620 |
-
Tạo hiệu ứng loading để có cảm giác như production
|
| 621 |
-
"""
|
| 622 |
loading_html = """
|
| 623 |
<div class="loading-container">
|
| 624 |
<div class="loading-spinner"></div>
|
|
@@ -627,38 +838,83 @@ def tao_loading_effect():
|
|
| 627 |
<div class="progress-fill"></div>
|
| 628 |
</div>
|
| 629 |
<p style="color: white; margin: 10px 0; opacity: 0.9;">
|
| 630 |
-
⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights
|
| 631 |
</p>
|
| 632 |
</div>
|
| 633 |
"""
|
| 634 |
return loading_html
|
| 635 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 636 |
def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
|
| 637 |
-
"""
|
| 638 |
-
Xử lý dự đoán với hiệu ứng loading realistic
|
| 639 |
-
"""
|
| 640 |
if lua_chon_case is None:
|
| 641 |
-
return
|
| 642 |
|
| 643 |
try:
|
| 644 |
-
#
|
| 645 |
-
|
| 646 |
-
yield None, loading, ""
|
| 647 |
|
| 648 |
-
#
|
| 649 |
-
time.sleep(2.5)
|
| 650 |
-
|
| 651 |
-
# Bước 3: Tạo biểu đồ
|
| 652 |
bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
|
| 653 |
|
| 654 |
-
#
|
| 655 |
tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
|
| 656 |
|
| 657 |
-
#
|
| 658 |
-
bao_cao =
|
| 659 |
|
| 660 |
-
|
| 661 |
-
yield bieu_do, tom_tat, bao_cao
|
| 662 |
|
| 663 |
except Exception as e:
|
| 664 |
loi = f"❌ Lỗi xử lý: {str(e)}"
|
|
@@ -669,7 +925,7 @@ def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
|
|
| 669 |
showarrow=False,
|
| 670 |
font=dict(size=16, color="red")
|
| 671 |
)
|
| 672 |
-
|
| 673 |
|
| 674 |
def cap_nhat_thong_tin_case(lua_chon_case):
|
| 675 |
"""Cập nhật thông tin case khi chọn"""
|
|
@@ -679,7 +935,6 @@ def cap_nhat_thong_tin_case(lua_chon_case):
|
|
| 679 |
<div class='info-card'>
|
| 680 |
<h4>📋 Tình Huống: {lua_chon_case}</h4>
|
| 681 |
<p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
|
| 682 |
-
<p><strong>Mùa Vụ:</strong> {thong_tin['mua_vu']}</p>
|
| 683 |
<p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
|
| 684 |
</div>
|
| 685 |
"""
|
|
@@ -687,27 +942,28 @@ def cap_nhat_thong_tin_case(lua_chon_case):
|
|
| 687 |
|
| 688 |
# Tạo ứng dụng Gradio
|
| 689 |
def tao_ung_dung():
|
| 690 |
-
"""
|
| 691 |
-
Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt
|
| 692 |
-
"""
|
| 693 |
|
| 694 |
with gr.Blocks(
|
| 695 |
-
title="🚀 Hệ Thống Dự Báo Bán Hàng AI -
|
| 696 |
theme=gr.themes.Soft(),
|
| 697 |
css=custom_css
|
| 698 |
) as demo:
|
| 699 |
|
| 700 |
-
# Header tiếng Việt
|
| 701 |
-
gr.HTML("""
|
| 702 |
<div class="header-container">
|
|
|
|
|
|
|
|
|
|
| 703 |
<div class="header-title">
|
| 704 |
🇻🇳 HỆ THỐNG DỰ BÁO BÁN HÀNG AI 📊
|
| 705 |
</div>
|
| 706 |
-
<p style="font-size: 1.2em; color: #
|
| 707 |
-
Công nghệ AI tiên tiến cho phân tích và dự báo kinh doanh
|
| 708 |
</p>
|
| 709 |
<div class="system-status">
|
| 710 |
-
🟢 Hệ thống hoạt động bình thường • 🚀 Độ chính xác 95.8% • ⚡ Realtime Analytics
|
| 711 |
</div>
|
| 712 |
</div>
|
| 713 |
""")
|
|
@@ -716,16 +972,15 @@ def tao_ung_dung():
|
|
| 716 |
gr.HTML("""
|
| 717 |
<div class='info-card'>
|
| 718 |
<h3>🎯 Hướng Dẫn Sử Dụng Hệ Thống</h3>
|
| 719 |
-
<p>Chọn
|
| 720 |
|
| 721 |
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 722 |
<div>
|
| 723 |
-
<h4>
|
| 724 |
<ul>
|
| 725 |
<li>📱 Điện tử & Công nghệ</li>
|
| 726 |
<li>👕 Thời trang & Làm đẹp</li>
|
| 727 |
<li>🍔 Thực phẩm & Đồ uống</li>
|
| 728 |
-
<li>🎮 Giải trí & Gaming</li>
|
| 729 |
</ul>
|
| 730 |
</div>
|
| 731 |
|
|
@@ -743,27 +998,29 @@ def tao_ung_dung():
|
|
| 743 |
|
| 744 |
with gr.Row():
|
| 745 |
with gr.Column(scale=1):
|
| 746 |
-
gr.HTML("<div class='feature-box'><h3>⚙️ Cài Đặt Phân Tích</h3></div>")
|
| 747 |
|
| 748 |
lua_chon_dropdown = gr.Dropdown(
|
| 749 |
choices=list(TRUONG_HOP_DEMO.keys()),
|
| 750 |
value=list(TRUONG_HOP_DEMO.keys())[0],
|
| 751 |
-
label="
|
| 752 |
-
info="Mỗi
|
|
|
|
| 753 |
)
|
| 754 |
|
| 755 |
chu_ky_dropdown = gr.Dropdown(
|
| 756 |
choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
|
| 757 |
value="3 tháng",
|
| 758 |
label="📊 Chu Kỳ Dự Báo",
|
| 759 |
-
info="Chọn khoảng thời gian dự báo phù hợp với mục đích kinh doanh"
|
|
|
|
| 760 |
)
|
| 761 |
|
| 762 |
nut_du_bao = gr.Button(
|
| 763 |
"🚀 Tạo Dự Báo AI",
|
| 764 |
variant="primary",
|
| 765 |
size="lg",
|
| 766 |
-
elem_classes="
|
| 767 |
)
|
| 768 |
|
| 769 |
# Hiển thị thông tin case
|
|
@@ -771,35 +1028,63 @@ def tao_ung_dung():
|
|
| 771 |
|
| 772 |
with gr.Row():
|
| 773 |
with gr.Column():
|
| 774 |
-
gr.HTML("<div class='feature-box'><h3>📈 Kết Quả Dự Báo</h3></div>")
|
| 775 |
|
| 776 |
# Chế độ hiển thị được đặt gần biểu đồ
|
| 777 |
che_do_xem = gr.Radio(
|
| 778 |
choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
|
| 779 |
value="ngày",
|
| 780 |
label="📊 Chế Độ Hiển Thị Biểu Đồ",
|
| 781 |
-
info="Thay đổi cách hiển thị dữ liệu trên biểu đồ"
|
|
|
|
| 782 |
)
|
| 783 |
|
| 784 |
bieu_do_du_bao = gr.Plot(
|
| 785 |
label="Biểu Đồ Dự Báo Bán Hàng",
|
| 786 |
-
elem_classes=["plot-container"]
|
| 787 |
)
|
| 788 |
|
| 789 |
with gr.Row():
|
| 790 |
with gr.Column(scale=1):
|
| 791 |
-
gr.HTML("<div class='feature-box'><h3>📊 Thống Kê Tổng Hợp</h3></div>")
|
| 792 |
hien_thi_tom_tat = gr.HTML()
|
| 793 |
|
| 794 |
with gr.Column(scale=1):
|
| 795 |
-
gr.HTML("<div class='feature-box'><h3>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 796 |
hien_thi_bao_cao = gr.Markdown()
|
| 797 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 798 |
# Xử lý sự kiện
|
| 799 |
lua_chon_dropdown.change(
|
| 800 |
-
fn=cap_nhat_thong_tin_case,
|
| 801 |
inputs=[lua_chon_dropdown],
|
| 802 |
-
outputs=[hien_thi_thong_tin]
|
| 803 |
)
|
| 804 |
|
| 805 |
nut_du_bao.click(
|
|
@@ -809,30 +1094,55 @@ def tao_ung_dung():
|
|
| 809 |
show_progress=True
|
| 810 |
)
|
| 811 |
|
| 812 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 813 |
che_do_xem.change(
|
| 814 |
-
fn=
|
| 815 |
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 816 |
outputs=[bieu_do_du_bao, hien_thi_tom_tat]
|
| 817 |
)
|
| 818 |
|
| 819 |
-
# Tự động load case đầu tiên
|
| 820 |
demo.load(
|
| 821 |
fn=lambda: [
|
| 822 |
cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
|
| 823 |
-
|
|
|
|
|
|
|
| 824 |
],
|
| 825 |
outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
|
| 826 |
)
|
| 827 |
|
| 828 |
-
# Footer thông tin hệ thống
|
| 829 |
-
gr.HTML("""
|
| 830 |
<div class='info-card' style="margin-top: 30px;">
|
| 831 |
-
<
|
|
|
|
|
|
|
|
|
|
| 832 |
|
| 833 |
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 834 |
<div>
|
| 835 |
-
<h4>🎯 Tính Năng Nổi Bật:</h4>
|
| 836 |
<ul>
|
| 837 |
<li><strong>AI Insights:</strong> Phân tích thông minh với khuyến nghị cụ thể</li>
|
| 838 |
<li><strong>Multi-view:</strong> Xem theo ngày/tháng/năm linh hoạt</li>
|
|
@@ -842,19 +1152,22 @@ def tao_ung_dung():
|
|
| 842 |
</div>
|
| 843 |
|
| 844 |
<div>
|
| 845 |
-
<h4>📊 Chất Lượng Dự Báo:</h4>
|
| 846 |
<ul>
|
| 847 |
-
<li><strong>Độ Chính Xác:</strong> 95.8% trên
|
| 848 |
-
<li><strong>Phạm Vi:</strong> Từ 3
|
| 849 |
<li><strong>Cập Nhật:</strong> Real-time với market intelligence</li>
|
| 850 |
<li><strong>Báo Cáo:</strong> Professional format cho C-level executives</li>
|
| 851 |
</ul>
|
| 852 |
</div>
|
| 853 |
</div>
|
| 854 |
|
| 855 |
-
<div style="text-align: center; margin: 20px 0; padding: 15px; background: rgba(
|
| 856 |
-
<p style="color: #
|
| 857 |
-
🇻🇳 Made in Vietnam | 🤖
|
|
|
|
|
|
|
|
|
|
| 858 |
</p>
|
| 859 |
</div>
|
| 860 |
</div>
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
import plotly.graph_objects as go
|
|
|
|
|
|
|
| 3 |
import numpy as np
|
| 4 |
from datetime import datetime, timedelta
|
| 5 |
import random
|
| 6 |
import time
|
| 7 |
|
| 8 |
+
# URL logo FoxAI - sử dụng trực tiếp từ attachment
|
| 9 |
+
FOXAI_LOGO_URL = "data:image/png;base64,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"
|
| 10 |
+
|
| 11 |
+
# CSS Style với màu sắc FoxAI - Modern UI Design
|
| 12 |
custom_css = """
|
| 13 |
.gradio-container {
|
| 14 |
+
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 25%, #cbd5e1 50%, #94a3b8 75%, #64748b 100%);
|
| 15 |
+
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif !important;
|
| 16 |
+
min-height: 100vh;
|
| 17 |
}
|
| 18 |
|
| 19 |
.header-container {
|
| 20 |
text-align: center;
|
| 21 |
margin: 20px 0;
|
| 22 |
+
padding: 40px;
|
| 23 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 24 |
+
border-radius: 24px;
|
| 25 |
+
box-shadow: 0 20px 40px rgba(12, 83, 135, 0.15), 0 8px 16px rgba(0, 0, 0, 0.1);
|
| 26 |
+
backdrop-filter: blur(20px);
|
| 27 |
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
| 28 |
+
position: relative;
|
| 29 |
+
overflow: hidden;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
.header-container::before {
|
| 33 |
+
content: '';
|
| 34 |
+
position: absolute;
|
| 35 |
+
top: 0;
|
| 36 |
+
left: -100%;
|
| 37 |
+
width: 100%;
|
| 38 |
+
height: 100%;
|
| 39 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
| 40 |
+
animation: shine 3s infinite;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
@keyframes shine {
|
| 44 |
+
0% { left: -100%; }
|
| 45 |
+
100% { left: 100%; }
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
.foxai-logo {
|
| 49 |
+
max-width: 320px;
|
| 50 |
+
height: auto;
|
| 51 |
+
margin: 15px auto 25px auto;
|
| 52 |
+
display: block;
|
| 53 |
+
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.15)) brightness(1.1);
|
| 54 |
+
transition: all 0.4s ease;
|
| 55 |
+
animation: float 4s ease-in-out infinite;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.foxai-logo:hover {
|
| 59 |
+
transform: scale(1.05);
|
| 60 |
+
filter: drop-shadow(0 8px 16px rgba(12, 83, 135, 0.3)) brightness(1.2);
|
| 61 |
}
|
| 62 |
|
| 63 |
.header-title {
|
| 64 |
+
background: linear-gradient(90deg, #ffffff, #f1f5f9, #e2e8f0, #ffffff);
|
| 65 |
background-size: 300% 300%;
|
| 66 |
animation: gradient 8s ease infinite;
|
| 67 |
-webkit-background-clip: text;
|
|
|
|
| 69 |
background-clip: text;
|
| 70 |
text-align: center;
|
| 71 |
font-size: 3em;
|
| 72 |
+
font-weight: 800;
|
| 73 |
+
margin: 15px 0;
|
| 74 |
+
line-height: 1.2;
|
| 75 |
+
text-shadow: 0 0 30px rgba(255, 255, 255, 0.5);
|
| 76 |
+
letter-spacing: -0.02em;
|
| 77 |
}
|
| 78 |
|
| 79 |
@keyframes gradient {
|
|
|
|
| 85 |
.loading-container {
|
| 86 |
text-align: center;
|
| 87 |
padding: 40px;
|
| 88 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 89 |
+
border-radius: 20px;
|
| 90 |
color: white;
|
| 91 |
margin: 20px 0;
|
| 92 |
+
box-shadow: 0 15px 35px rgba(12, 83, 135, 0.3), 0 5px 15px rgba(0, 0, 0, 0.12);
|
| 93 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 94 |
}
|
| 95 |
|
| 96 |
.loading-spinner {
|
| 97 |
border: 4px solid #f3f3f3;
|
| 98 |
+
border-top: 4px solid #1A5F91;
|
| 99 |
border-radius: 50%;
|
| 100 |
width: 40px;
|
| 101 |
height: 40px;
|
|
|
|
| 119 |
|
| 120 |
.progress-fill {
|
| 121 |
height: 100%;
|
| 122 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 123 |
border-radius: 10px;
|
| 124 |
animation: progress 3s ease-in-out;
|
| 125 |
+
box-shadow: 0 0 20px rgba(12, 83, 135, 0.4);
|
| 126 |
}
|
| 127 |
|
| 128 |
@keyframes progress {
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
.prediction-box {
|
| 137 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 138 |
+
border-radius: 20px;
|
| 139 |
+
padding: 25px;
|
| 140 |
color: white;
|
| 141 |
text-align: center;
|
| 142 |
+
font-size: 1.1em;
|
| 143 |
+
font-weight: 600;
|
| 144 |
+
box-shadow: 0 15px 35px rgba(12, 83, 135, 0.25), 0 5px 15px rgba(0, 0, 0, 0.12);
|
| 145 |
margin: 15px 0;
|
| 146 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 147 |
+
position: relative;
|
| 148 |
+
overflow: hidden;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
.prediction-box::before {
|
| 152 |
+
content: '';
|
| 153 |
+
position: absolute;
|
| 154 |
+
top: 0;
|
| 155 |
+
left: 0;
|
| 156 |
+
right: 0;
|
| 157 |
+
height: 1px;
|
| 158 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent);
|
| 159 |
}
|
| 160 |
|
| 161 |
.insight-box {
|
| 162 |
+
background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
|
| 163 |
+
border-radius: 20px;
|
| 164 |
+
padding: 25px;
|
| 165 |
color: white;
|
| 166 |
margin: 15px 0;
|
| 167 |
+
box-shadow: 0 15px 35px rgba(51, 65, 85, 0.25), 0 5px 15px rgba(0, 0, 0, 0.12);
|
| 168 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 169 |
+
position: relative;
|
| 170 |
+
overflow: hidden;
|
| 171 |
}
|
| 172 |
|
| 173 |
.executive-summary {
|
| 174 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 175 |
+
border-radius: 20px;
|
| 176 |
+
padding: 30px;
|
| 177 |
color: white;
|
| 178 |
margin: 15px 0;
|
| 179 |
+
box-shadow: 0 20px 40px rgba(12, 83, 135, 0.25), 0 8px 16px rgba(0, 0, 0, 0.12);
|
| 180 |
+
border-left: 5px solid rgba(255, 255, 255, 0.3);
|
| 181 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 182 |
+
position: relative;
|
| 183 |
+
overflow: hidden;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.executive-summary::after {
|
| 187 |
+
content: '';
|
| 188 |
+
position: absolute;
|
| 189 |
+
top: 0;
|
| 190 |
+
right: 0;
|
| 191 |
+
width: 100px;
|
| 192 |
+
height: 100%;
|
| 193 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1));
|
| 194 |
+
pointer-events: none;
|
| 195 |
}
|
| 196 |
|
| 197 |
.feature-box {
|
| 198 |
+
background: linear-gradient(135deg, rgba(169, 170, 169, 0.15), rgba(129, 148, 160, 0.15), rgba(90, 126, 152, 0.15));
|
| 199 |
+
border-radius: 20px;
|
| 200 |
+
padding: 20px;
|
| 201 |
+
margin: 15px 0;
|
| 202 |
+
box-shadow: 0 8px 32px rgba(12, 83, 135, 0.1), 0 1px 2px rgba(0, 0, 0, 0.05);
|
| 203 |
+
border-left: 4px solid #0C5387;
|
| 204 |
+
backdrop-filter: blur(10px);
|
| 205 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 206 |
+
transition: all 0.3s ease;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
.feature-box:hover {
|
| 210 |
+
transform: translateY(-2px);
|
| 211 |
+
box-shadow: 0 12px 40px rgba(12, 83, 135, 0.15), 0 4px 8px rgba(0, 0, 0, 0.1);
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
.feature-box h3 {
|
| 215 |
+
margin: 0;
|
| 216 |
+
color: #0C5387;
|
| 217 |
+
font-weight: 700;
|
| 218 |
+
text-shadow: 0 0 10px rgba(12, 83, 135, 0.3);
|
| 219 |
+
font-size: 1.2em;
|
| 220 |
}
|
| 221 |
|
| 222 |
.system-status {
|
| 223 |
+
background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
|
| 224 |
color: white;
|
| 225 |
+
padding: 15px 25px;
|
| 226 |
+
border-radius: 30px;
|
| 227 |
+
margin: 15px 0;
|
| 228 |
text-align: center;
|
| 229 |
+
font-weight: 600;
|
| 230 |
+
box-shadow: 0 8px 25px rgba(51, 65, 85, 0.2), 0 3px 8px rgba(0, 0, 0, 0.1);
|
| 231 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 232 |
+
font-size: 0.95em;
|
| 233 |
}
|
| 234 |
|
| 235 |
.metric-card {
|
| 236 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 237 |
color: white;
|
| 238 |
+
border-radius: 16px;
|
| 239 |
+
padding: 20px;
|
| 240 |
+
margin: 8px;
|
| 241 |
text-align: center;
|
| 242 |
+
box-shadow: 0 8px 25px rgba(12, 83, 135, 0.2), 0 3px 8px rgba(0, 0, 0, 0.1);
|
| 243 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 244 |
+
transition: all 0.3s ease;
|
| 245 |
+
position: relative;
|
| 246 |
+
overflow: hidden;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
.metric-card:hover {
|
| 250 |
+
transform: translateY(-3px);
|
| 251 |
+
box-shadow: 0 12px 35px rgba(12, 83, 135, 0.3), 0 5px 12px rgba(0, 0, 0, 0.15);
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
.metric-card::before {
|
| 255 |
+
content: '';
|
| 256 |
+
position: absolute;
|
| 257 |
+
top: 0;
|
| 258 |
+
left: 0;
|
| 259 |
+
right: 0;
|
| 260 |
+
height: 2px;
|
| 261 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
|
| 262 |
}
|
| 263 |
|
| 264 |
.button-predict {
|
| 265 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B) !important;
|
| 266 |
color: white !important;
|
| 267 |
border: none !important;
|
| 268 |
border-radius: 25px !important;
|
| 269 |
padding: 15px 30px !important;
|
| 270 |
font-size: 16px !important;
|
| 271 |
font-weight: bold !important;
|
| 272 |
+
box-shadow: 0 4px 15px rgba(26, 95, 145, 0.4) !important;
|
| 273 |
transition: all 0.3s ease !important;
|
| 274 |
}
|
| 275 |
|
| 276 |
.button-predict:hover {
|
| 277 |
transform: translateY(-2px) !important;
|
| 278 |
+
box-shadow: 0 6px 20px rgba(26, 95, 145, 0.6) !important;
|
| 279 |
}
|
| 280 |
|
| 281 |
.plot-container {
|
|
|
|
| 285 |
margin: 15px 0;
|
| 286 |
background: rgba(255, 255, 255, 0.95);
|
| 287 |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 288 |
+
min-height: 400px;
|
| 289 |
}
|
| 290 |
|
| 291 |
.info-card {
|
|
|
|
| 293 |
border-radius: 10px;
|
| 294 |
padding: 15px;
|
| 295 |
margin: 10px 0;
|
| 296 |
+
border-left: 5px solid #1A5F91;
|
| 297 |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 298 |
}
|
| 299 |
+
|
| 300 |
+
/* Sửa lỗi font và text rendering */
|
| 301 |
+
* {
|
| 302 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 303 |
+
text-rendering: optimizeLegibility !important;
|
| 304 |
+
-webkit-font-smoothing: antialiased !important;
|
| 305 |
+
-moz-osx-font-smoothing: grayscale !important;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
/* Cải thiện hiển thị tiếng Việt */
|
| 309 |
+
.gradio-markdown, .gradio-html {
|
| 310 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 311 |
+
line-height: 1.6 !important;
|
| 312 |
+
word-wrap: break-word !important;
|
| 313 |
+
overflow-wrap: break-word !important;
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
/* Sửa lỗi layout kéo dài */
|
| 317 |
+
.gradio-container .wrap {
|
| 318 |
+
max-width: 100% !important;
|
| 319 |
+
overflow-x: hidden !important;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.gradio-row {
|
| 323 |
+
flex-wrap: wrap !important;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
.gradio-column {
|
| 327 |
+
min-width: 0 !important;
|
| 328 |
+
flex-shrink: 1 !important;
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
/* Glass morphism effects for modern look */
|
| 332 |
+
.glass-card {
|
| 333 |
+
background: rgba(255, 255, 255, 0.1);
|
| 334 |
+
backdrop-filter: blur(10px);
|
| 335 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 336 |
+
border-radius: 16px;
|
| 337 |
+
padding: 20px;
|
| 338 |
+
margin: 10px 0;
|
| 339 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
.neon-border {
|
| 343 |
+
box-shadow:
|
| 344 |
+
0 0 5px rgba(12, 83, 135, 0.3),
|
| 345 |
+
0 0 10px rgba(12, 83, 135, 0.3),
|
| 346 |
+
0 0 15px rgba(12, 83, 135, 0.3),
|
| 347 |
+
0 0 20px rgba(12, 83, 135, 0.2),
|
| 348 |
+
inset 0 0 5px rgba(255, 255, 255, 0.1);
|
| 349 |
+
border: 1px solid rgba(12, 83, 135, 0.4);
|
| 350 |
+
animation: neonPulse 2s ease-in-out infinite alternate;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
@keyframes neonPulse {
|
| 354 |
+
0% {
|
| 355 |
+
box-shadow:
|
| 356 |
+
0 0 5px rgba(12, 83, 135, 0.3),
|
| 357 |
+
0 0 10px rgba(12, 83, 135, 0.3),
|
| 358 |
+
0 0 15px rgba(12, 83, 135, 0.3),
|
| 359 |
+
inset 0 0 5px rgba(255, 255, 255, 0.1);
|
| 360 |
+
}
|
| 361 |
+
100% {
|
| 362 |
+
box-shadow:
|
| 363 |
+
0 0 10px rgba(12, 83, 135, 0.5),
|
| 364 |
+
0 0 20px rgba(12, 83, 135, 0.4),
|
| 365 |
+
0 0 30px rgba(12, 83, 135, 0.3),
|
| 366 |
+
0 0 40px rgba(12, 83, 135, 0.2),
|
| 367 |
+
inset 0 0 8px rgba(255, 255, 255, 0.2);
|
| 368 |
+
}
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
/* Modern button styling */
|
| 372 |
+
.btn-modern {
|
| 373 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 374 |
+
border: none;
|
| 375 |
+
border-radius: 16px;
|
| 376 |
+
padding: 16px 32px;
|
| 377 |
+
color: white;
|
| 378 |
+
font-weight: 700;
|
| 379 |
+
text-transform: uppercase;
|
| 380 |
+
letter-spacing: 1.2px;
|
| 381 |
+
box-shadow: 0 8px 25px rgba(12, 83, 135, 0.3), 0 3px 8px rgba(0, 0, 0, 0.1);
|
| 382 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 383 |
+
position: relative;
|
| 384 |
+
overflow: hidden;
|
| 385 |
+
font-size: 0.95em;
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
.btn-modern::before {
|
| 389 |
+
content: '';
|
| 390 |
+
position: absolute;
|
| 391 |
+
top: 0;
|
| 392 |
+
left: -100%;
|
| 393 |
+
width: 100%;
|
| 394 |
+
height: 100%;
|
| 395 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
|
| 396 |
+
transition: left 0.6s;
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
.btn-modern:hover {
|
| 400 |
+
transform: translateY(-3px) scale(1.02);
|
| 401 |
+
box-shadow: 0 15px 40px rgba(12, 83, 135, 0.4), 0 8px 16px rgba(0, 0, 0, 0.15);
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
.btn-modern:hover::before {
|
| 405 |
+
left: 100%;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
.btn-modern:active {
|
| 409 |
+
transform: translateY(-1px) scale(1.01);
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
/* Animated background gradients */
|
| 413 |
+
.bg-blue-grad {
|
| 414 |
+
background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
|
| 415 |
+
background-size: 200% 200%;
|
| 416 |
+
animation: gradientShift 4s ease-in-out infinite alternate;
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
.bg-gray-grad {
|
| 420 |
+
background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
|
| 421 |
+
background-size: 200% 200%;
|
| 422 |
+
animation: gradientShift 4s ease-in-out infinite alternate;
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
@keyframes gradientShift {
|
| 426 |
+
0% { background-position: 0% 50%; }
|
| 427 |
+
100% { background-position: 100% 50%; }
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
/* Tech-style borders and effects */
|
| 431 |
+
.tech-border {
|
| 432 |
+
position: relative;
|
| 433 |
+
border: 2px solid transparent;
|
| 434 |
+
border-radius: 16px;
|
| 435 |
+
background: linear-gradient(45deg, #A9AAA9, #8194A0, #5A7E98, #33688F, #0C5387) border-box;
|
| 436 |
+
mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
|
| 437 |
+
mask-composite: exclude;
|
| 438 |
+
-webkit-mask-composite: xor;
|
| 439 |
+
transition: all 0.3s ease;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
.tech-border:hover {
|
| 443 |
+
box-shadow: 0 0 20px rgba(12, 83, 135, 0.3);
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
/* Holographic effect */
|
| 447 |
+
.holographic {
|
| 448 |
+
background: linear-gradient(45deg, #A9AAA9 0%, #8194A0 20%, #5A7E98 40%, #33688F 60%, #0C5387 80%, #A9AAA9 100%);
|
| 449 |
+
background-size: 400% 400%;
|
| 450 |
+
animation: hologram 6s ease-in-out infinite;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
@keyframes hologram {
|
| 454 |
+
0%, 100% { background-position: 0% 50%; }
|
| 455 |
+
50% { background-position: 100% 50%; }
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
/* Floating animation for cards */
|
| 459 |
+
@keyframes float {
|
| 460 |
+
0%, 100% { transform: translateY(0px); }
|
| 461 |
+
50% { transform: translateY(-5px); }
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
.floating {
|
| 465 |
+
animation: float 3s ease-in-out infinite;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
/* Modern card design */
|
| 469 |
+
.modern-card {
|
| 470 |
+
background: rgba(255, 255, 255, 0.1);
|
| 471 |
+
backdrop-filter: blur(20px);
|
| 472 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 473 |
+
border-radius: 20px;
|
| 474 |
+
padding: 25px;
|
| 475 |
+
margin: 15px 0;
|
| 476 |
+
box-shadow:
|
| 477 |
+
0 8px 32px rgba(31, 38, 135, 0.37),
|
| 478 |
+
0 2px 8px rgba(0, 0, 0, 0.1);
|
| 479 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 480 |
+
position: relative;
|
| 481 |
+
overflow: hidden;
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
.modern-card::before {
|
| 485 |
+
content: '';
|
| 486 |
+
position: absolute;
|
| 487 |
+
top: 0;
|
| 488 |
+
left: 0;
|
| 489 |
+
right: 0;
|
| 490 |
+
height: 1px;
|
| 491 |
+
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
.modern-card:hover {
|
| 495 |
+
transform: translateY(-5px) scale(1.02);
|
| 496 |
+
box-shadow:
|
| 497 |
+
0 20px 60px rgba(12, 83, 135, 0.2),
|
| 498 |
+
0 8px 16px rgba(0, 0, 0, 0.15);
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
/* Info card styling */
|
| 502 |
+
.info-card {
|
| 503 |
+
background: linear-gradient(135deg,
|
| 504 |
+
rgba(255, 255, 255, 0.25) 0%,
|
| 505 |
+
rgba(255, 255, 255, 0.1) 50%,
|
| 506 |
+
rgba(255, 255, 255, 0.05) 100%);
|
| 507 |
+
backdrop-filter: blur(20px);
|
| 508 |
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
| 509 |
+
border-radius: 24px;
|
| 510 |
+
padding: 30px;
|
| 511 |
+
margin: 20px 0;
|
| 512 |
+
box-shadow:
|
| 513 |
+
0 12px 40px rgba(12, 83, 135, 0.15),
|
| 514 |
+
0 4px 12px rgba(0, 0, 0, 0.1);
|
| 515 |
+
position: relative;
|
| 516 |
+
overflow: hidden;
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
.info-card::after {
|
| 520 |
+
content: '';
|
| 521 |
+
position: absolute;
|
| 522 |
+
top: -50%;
|
| 523 |
+
right: -50%;
|
| 524 |
+
width: 100%;
|
| 525 |
+
height: 200%;
|
| 526 |
+
background: conic-gradient(from 0deg, transparent, rgba(12, 83, 135, 0.1), transparent);
|
| 527 |
+
animation: rotate 8s linear infinite;
|
| 528 |
+
pointer-events: none;
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
@keyframes rotate {
|
| 532 |
+
0% { transform: rotate(0deg); }
|
| 533 |
+
100% { transform: rotate(360deg); }
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
/* Loading spinner enhancement */
|
| 537 |
+
.loading-spinner {
|
| 538 |
+
border: 4px solid rgba(255, 255, 255, 0.2);
|
| 539 |
+
border-top: 4px solid #ffffff;
|
| 540 |
+
border-radius: 50%;
|
| 541 |
+
width: 50px;
|
| 542 |
+
height: 50px;
|
| 543 |
+
animation: spin 1s linear infinite;
|
| 544 |
+
margin: 0 auto 20px;
|
| 545 |
+
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
|
| 546 |
+
}
|
| 547 |
"""
|
| 548 |
|
| 549 |
+
# Dữ liệu demo tiếng Việt cho 3 trường hợp chính
|
| 550 |
TRUONG_HOP_DEMO = {
|
| 551 |
+
"📱 Điện tử & Công nghệ": {
|
| 552 |
"danh_muc": "Điện tử & Công nghệ",
|
|
|
|
| 553 |
"don_vi_co_ban": 150,
|
| 554 |
+
"xu_huong": "tang_dan",
|
| 555 |
+
"mo_ta": "Dự báo bán hàng sản phẩm điện tử, smartphone, laptop và thiết bị công nghệ",
|
| 556 |
"thong_tin_giam_doc": {
|
| 557 |
+
"tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện tử có xu hướng tăng trưởng mạnh 180-250% với sự phát triển của công nghệ AI, 5G và IoT. Đây là cơ hội vàng để chiếm lĩnh thị phần.",
|
| 558 |
+
"chi_tiet": "**📊 PHÂN TÍCH KINH DOANH SÂU SẮC:** Thị trường điện tử đang trải qua làn sóng tăng trưởng mạnh với mức tăng 180-250% do several factors: (1) Digital transformation gia tăng sau COVID, (2) Work from home trend tạo nhu cầu laptop/monitor, (3) Gen Z có spending power cao cho gadgets, (4) AI boom tạo nhu cầu hardware mạnh. Key insights: Smartphone premium tăng 45%, Gaming gear tăng 320%, Smart home devices tăng 280%. Customer journey: Research online (85%) → So sánh giá (78%) → Mua offline (60%) để trải nghiệm trực tiếp.",
|
| 559 |
+
"hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH CHIẾN LƯỢC:** (1) **Inventory Strategy:** Tăng tồn kho 200% cho flagship models, đặc biệt iPhone/Samsung dòng cao cấp và gaming laptops, (2) **Digital Integration:** Xây dựng AR/VR showroom để khách hàng try before buy, (3) **Partnership Ecosystem:** Hợp tác với fintech cho installment 0%, tie-up với game publishers cho gaming bundle, (4) **Market Expansion:** Mở rộng sang smart home ecosystem với IoT devices, (5) **After-sales Excellence:** Extended warranty và premium support để tăng customer lifetime value và build brand loyalty."
|
| 560 |
}
|
| 561 |
},
|
| 562 |
|
| 563 |
+
"👕 Thời trang & Làm đẹp": {
|
| 564 |
"danh_muc": "Thời trang & Làm đẹp",
|
|
|
|
| 565 |
"don_vi_co_ban": 80,
|
| 566 |
+
"xu_huong": "bien_dong",
|
| 567 |
+
"mo_ta": "Dự báo xu hướng thời trang, mỹ phẩm và các sản phẩm làm đẹp theo mùa",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 568 |
"thong_tin_giam_doc": {
|
| 569 |
+
"tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang & làm đẹp có tính mùa vụ rõ rệt với biến động 15-180% theo trend và influencer impact. Cần strategy linh hoạt để maximize các peak seasons.",
|
| 570 |
+
"chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG FASHION & BEAUTY:** Industry có pattern rất đặc biệt với multiple micro-seasons: (1) Spring/Summer collection (Mar-Aug) peak 170%, (2) Fall/Winter collection (Sep-Feb) stable 120%, (3) Special events (Valentine +240%, Tết +185%, graduation season +150%). Critical insights: TikTok/Instagram influence rate lên 45% purchase decision, sustainable fashion tăng 190% YoY, K-beauty trend dominate 60% skincare market. Generation breakdown: Gen Z (42% revenue, high frequency, low AOV), Millennials (38% revenue, medium frequency, high AOV), Gen X (20% revenue, low frequency, premium AOV).",
|
| 571 |
+
"hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI OMNICHANNEL:** (1) **Trend Forecasting:** AI-powered trend analysis từ social media để predict viral products 2-3 months trước, (2) **Influencer Partnership:** Collaborate với 50+ nano/micro influencers (10K-100K followers) cho authentic engagement thay vì 1-2 mega influencers, (3) **Inventory Agility:** Fast fashion model với small batch testing → scale winners rapidly, (4) **Personalization Engine:** Skin analysis app + virtual try-on technology để tăng conversion rate, (5) **Sustainability Edge:** Launch eco-friendly line với packaging innovation để capture conscious consumers và justify premium pricing."
|
| 572 |
}
|
| 573 |
},
|
| 574 |
|
| 575 |
+
"🍔 Thực phẩm & Đồ uống": {
|
| 576 |
"danh_muc": "Thực phẩm & Đồ uống",
|
|
|
|
| 577 |
"don_vi_co_ban": 200,
|
| 578 |
+
"xu_huong": "on_dinh",
|
| 579 |
+
"mo_ta": "Dự báo thị trường F&B, food delivery và các sản phẩm tiêu dùng hàng ngày",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 580 |
"thong_tin_giam_doc": {
|
| 581 |
+
"tom_tat": "🍽️ **TÓM TẮT ĐIỀU HÀNH:** F&B market ổn định với baseline consumption nhưng có opportunity spikes từ weather, events và lifestyle changes. Delivery segment tăng 280%, healthy food trend tăng 165%.",
|
| 582 |
+
"chi_tiet": "**⛈️ PHÂN TÍCH F&B MARKET DYNAMICS:** F&B industry có đặc điểm unique với stable baseline demand nhưng high weather sensitivity và event-driven spikes. Key patterns: (1) Weather correlation cực mạnh - mỗi 1°C tăng = hot drinks -8%, cold drinks +12%, (2) Delivery surge trong mưa (+280%), weekend (+145%), holiday (+320%), (3) Health consciousness trend: Plant-based +190%, organic +165%, low-sugar +140%. Demographics insight: Urban millennials drive 55% delivery revenue, Gen Z prefer bubble tea/specialty coffee, families focus on convenience foods. Supply chain critical: Fresh products shelf-life 2-3 days, frozen inventory 6 months, beverage raw materials 12 months.",
|
| 583 |
+
"hanh_dong": "**☔ CHIẾN THUẬT WEATHER-RESPONSIVE F&B:** (1) **Predictive Inventory:** Weather API integration để auto-adjust inventory 48h trước based on forecast - rain = +200% comfort food, heat = +150% cold beverages, (2) **Delivery Optimization:** Dynamic delivery zones expansion trong bad weather, surge pricing strategy để incentivize drivers, ghost kitchen positioning ở high-density areas, (3) **Health & Wellness Pivot:** Launch functional beverages (immunity boost, energy, beauty), partner với gyms/yoga studios, subscription healthy meal plans, (4) **Experience Innovation:** Interactive cooking classes, farm-to-table storytelling, sustainable packaging để build brand differentiation, (5) **Data-Driven Menu:** Customer preference analytics để optimize menu mix và eliminate low-performers monthly."
|
| 584 |
}
|
| 585 |
+
}
|
| 586 |
+
}
|
| 587 |
+
|
| 588 |
+
def tao_bieu_do_mac_dinh():
|
| 589 |
+
"""Tạo biểu đồ mặc định khi chưa dự đoán"""
|
| 590 |
+
fig = go.Figure()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 591 |
|
| 592 |
+
fig.add_annotation(
|
| 593 |
+
text="📊 Chọn mặt hàng và nhấn 'Tạo Dự Báo AI' để xem phân tích",
|
| 594 |
+
xref="paper", yref="paper",
|
| 595 |
+
x=0.5, y=0.5,
|
| 596 |
+
xanchor='center', yanchor='middle',
|
| 597 |
+
showarrow=False,
|
| 598 |
+
font=dict(size=18, color="#34495E", family="Arial"),
|
| 599 |
+
bgcolor="rgba(255,255,255,0.9)",
|
| 600 |
+
bordercolor="#BDC3C7",
|
| 601 |
+
borderwidth=2,
|
| 602 |
+
borderpad=20
|
| 603 |
+
)
|
| 604 |
|
| 605 |
+
fig.update_layout(
|
| 606 |
+
title="🎯 Hệ Thống Dự Báo AI Sẵn Sàng",
|
| 607 |
+
template="plotly_white",
|
| 608 |
+
height=400,
|
| 609 |
+
showlegend=False,
|
| 610 |
+
xaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 611 |
+
yaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 612 |
+
plot_bgcolor='rgba(248,249,250,0.8)',
|
| 613 |
+
font=dict(family="Arial")
|
| 614 |
+
)
|
|
|
|
|
|
|
| 615 |
|
| 616 |
+
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 617 |
|
| 618 |
+
def tao_tom_tat_mac_dinh():
|
| 619 |
+
"""Tạo tóm tắt mặc định"""
|
| 620 |
+
return """
|
| 621 |
+
<div class="prediction-box">
|
| 622 |
+
<h3 style="margin-top: 0; color: white;">📋 Thống Kê Sẽ Hiển Thị Sau Dự Báo</h3>
|
| 623 |
+
<div style="text-align: center; padding: 20px;">
|
| 624 |
+
<p style="font-size: 18px; margin: 10px 0; color: white;">
|
| 625 |
+
🎯 Chọn mặt hàng dự đoán và nhấn "Tạo Dự Báo AI"
|
| 626 |
+
</p>
|
| 627 |
+
<p style="font-size: 16px; margin: 10px 0; color: #E8F6F3;">
|
| 628 |
+
Hệ thống sẽ phân tích và đưa ra insights chi tiết
|
| 629 |
+
</p>
|
| 630 |
+
</div>
|
| 631 |
+
</div>
|
| 632 |
"""
|
| 633 |
+
|
| 634 |
+
def tao_du_lieu_demo(thong_tin_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 635 |
+
"""Tạo dữ liệu demo đơn giản dựa trên case và chu kỳ dự báo"""
|
| 636 |
don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
|
| 637 |
xu_huong = thong_tin_case["xu_huong"]
|
| 638 |
|
| 639 |
+
# Xác định số điểm dữ liệu
|
| 640 |
if chu_ky == "1 năm":
|
| 641 |
+
so_diem = 12 if che_do_xem == 'năm' else (52 if che_do_xem == 'tháng' else 365)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 642 |
elif chu_ky == "6 tháng":
|
| 643 |
+
so_diem = 6 if che_do_xem == 'năm' else (26 if che_do_xem == 'tháng' else 180)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 644 |
else: # "3 tháng"
|
| 645 |
+
so_diem = 3 if che_do_xem == 'năm' else (13 if che_do_xem == 'tháng' else 90)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 646 |
|
| 647 |
+
# Tạo nhãn thời gian
|
| 648 |
+
if che_do_xem == 'năm':
|
| 649 |
+
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 650 |
+
elif che_do_xem == 'tháng':
|
| 651 |
+
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 652 |
+
else: # ngày
|
| 653 |
+
ngay_bat_dau = datetime.now()
|
| 654 |
+
nhan_thoi_gian = [(ngay_bat_dau + timedelta(days=i)).strftime("%d/%m") for i in range(so_diem)]
|
| 655 |
|
| 656 |
+
# Tạo dữ liệu dựa trên xu hướng đơn giản
|
| 657 |
+
don_vi_ban = []
|
| 658 |
for i in range(so_diem):
|
| 659 |
+
if xu_huong == "tang_dan":
|
| 660 |
+
he_so = 1.0 + (i * 0.2) # Tăng dần theo thời gian
|
| 661 |
+
elif xu_huong == "bien_dong":
|
| 662 |
+
he_so = 1.0 + np.sin(i * 0.5) * 0.3 # Biến động theo sin
|
| 663 |
+
elif xu_huong == "on_dinh":
|
| 664 |
+
he_so = 1.0 + random.uniform(-0.1, 0.1) # Ổn định với chút biến động
|
| 665 |
+
else:
|
| 666 |
+
he_so = 1.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 667 |
|
| 668 |
+
don_vi = max(int(don_vi_co_ban * he_so + random.randint(-30, 30)), 10)
|
| 669 |
don_vi_ban.append(don_vi)
|
| 670 |
|
| 671 |
return nhan_thoi_gian, don_vi_ban
|
| 672 |
|
| 673 |
def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 674 |
+
"""Tạo biểu đồ dự đoán với hiệu ứng loading"""
|
|
|
|
|
|
|
| 675 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 676 |
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 677 |
|
|
|
|
| 684 |
y=don_vi_ban,
|
| 685 |
mode='lines+markers',
|
| 686 |
name='📦 Dự Báo Đơn Vị Bán',
|
| 687 |
+
line=dict(color='#1A5F91', width=4),
|
| 688 |
+
marker=dict(size=12, color='#1A5F91', symbol='circle'),
|
| 689 |
hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
|
| 690 |
))
|
| 691 |
|
|
|
|
| 697 |
x=nhan_thoi_gian + nhan_thoi_gian[::-1],
|
| 698 |
y=upper_bound + lower_bound[::-1],
|
| 699 |
fill='toself',
|
| 700 |
+
fillcolor='rgba(26, 95, 145, 0.2)',
|
| 701 |
line=dict(color='rgba(255,255,255,0)'),
|
| 702 |
name='📊 Vùng Tin Cậy',
|
| 703 |
hoverinfo="skip"
|
|
|
|
| 713 |
y=duong_xu_huong,
|
| 714 |
mode='lines',
|
| 715 |
name='📈 Xu Hướng',
|
| 716 |
+
line=dict(color='#8B8B8B', width=3, dash='dash'),
|
| 717 |
hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
|
| 718 |
))
|
| 719 |
|
|
|
|
| 753 |
return fig
|
| 754 |
|
| 755 |
def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 756 |
+
"""Tạo thông tin tóm tắt dành cho giám đốc"""
|
|
|
|
|
|
|
| 757 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 758 |
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 759 |
|
|
|
|
| 796 |
<div style="margin-top: 15px; text-align: center;">
|
| 797 |
<p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
|
| 798 |
<p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
|
|
|
|
| 799 |
</div>
|
| 800 |
</div>
|
| 801 |
"""
|
|
|
|
| 803 |
return tom_tat_html
|
| 804 |
|
| 805 |
def tao_bao_cao_giam_doc(ten_case):
|
| 806 |
+
"""Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown"""
|
|
|
|
|
|
|
| 807 |
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 808 |
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 809 |
|
| 810 |
bao_cao_markdown = f"""
|
| 811 |
+
# 🎯 CHIẾN LƯỢC ĐỀ XUẤT
|
| 812 |
|
| 813 |
+
## 📈 Tóm Tắt Điều Hành
|
| 814 |
|
| 815 |
{thong_tin_gd['tom_tat']}
|
| 816 |
|
|
|
|
| 823 |
{thong_tin_gd['hanh_dong']}
|
| 824 |
|
| 825 |
---
|
| 826 |
+
*🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*
|
| 827 |
"""
|
| 828 |
|
| 829 |
return bao_cao_markdown
|
| 830 |
|
| 831 |
def tao_loading_effect():
|
| 832 |
+
"""Tạo hiệu ứng loading để có cảm giác như production"""
|
|
|
|
|
|
|
| 833 |
loading_html = """
|
| 834 |
<div class="loading-container">
|
| 835 |
<div class="loading-spinner"></div>
|
|
|
|
| 838 |
<div class="progress-fill"></div>
|
| 839 |
</div>
|
| 840 |
<p style="color: white; margin: 10px 0; opacity: 0.9;">
|
| 841 |
+
⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights • 🎯 Chiến lược AI
|
| 842 |
</p>
|
| 843 |
</div>
|
| 844 |
"""
|
| 845 |
return loading_html
|
| 846 |
|
| 847 |
+
def tao_bao_cao_streaming(ten_case):
|
| 848 |
+
"""Tạo báo cáo với hiệu ứng streaming như AI đang viết"""
|
| 849 |
+
import time
|
| 850 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 851 |
+
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 852 |
+
|
| 853 |
+
# Nội dung đầy đủ
|
| 854 |
+
noi_dung_day_du = f"""# 🎯 CHIẾN LƯỢC ĐỀ XUẤT
|
| 855 |
+
|
| 856 |
+
## 📈 Tóm Tắt Điều Hành
|
| 857 |
+
|
| 858 |
+
{thong_tin_gd['tom_tat']}
|
| 859 |
+
|
| 860 |
+
## 📊 Phân Tích Chi Tiết
|
| 861 |
+
|
| 862 |
+
{thong_tin_gd['chi_tiet']}
|
| 863 |
+
|
| 864 |
+
## 🚀 Khuyến Nghị Hành Động
|
| 865 |
+
|
| 866 |
+
{thong_tin_gd['hanh_dong']}
|
| 867 |
+
|
| 868 |
+
---
|
| 869 |
+
*🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*"""
|
| 870 |
+
|
| 871 |
+
return noi_dung_day_du
|
| 872 |
+
|
| 873 |
+
def tao_streaming_text(ten_case):
|
| 874 |
+
"""Generator để tạo hiệu ứng streaming"""
|
| 875 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 876 |
+
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 877 |
+
|
| 878 |
+
# Các phần nội dung để stream
|
| 879 |
+
sections = [
|
| 880 |
+
"# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n",
|
| 881 |
+
"## 📈 Tóm Tắt Điều Hành\n\n",
|
| 882 |
+
f"{thong_tin_gd['tom_tat']}\n\n",
|
| 883 |
+
"## 📊 Phân Tích Chi Tiết\n\n",
|
| 884 |
+
f"{thong_tin_gd['chi_tiet']}\n\n",
|
| 885 |
+
"## 🚀 Khuyến Nghị Hành Động\n\n",
|
| 886 |
+
f"{thong_tin_gd['hanh_dong']}\n\n",
|
| 887 |
+
"---\n*🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*"
|
| 888 |
+
]
|
| 889 |
+
|
| 890 |
+
accumulated_text = ""
|
| 891 |
+
for section in sections:
|
| 892 |
+
# Chia nhỏ text thành từng từ để stream
|
| 893 |
+
words = section.split(' ')
|
| 894 |
+
for word in words:
|
| 895 |
+
accumulated_text += word + ' '
|
| 896 |
+
yield accumulated_text
|
| 897 |
+
time.sleep(0.05) # Delay nhỏ để tạo hiệu ứng typing
|
| 898 |
+
|
| 899 |
def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
|
| 900 |
+
"""Xử lý dự đoán với hiệu ứng loading realistic và streaming"""
|
|
|
|
|
|
|
| 901 |
if lua_chon_case is None:
|
| 902 |
+
return tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh(), "# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Chọn mặt hàng để xem phân tích AI**"
|
| 903 |
|
| 904 |
try:
|
| 905 |
+
# Giả lập thời gian xử lý AI
|
| 906 |
+
time.sleep(0.5)
|
|
|
|
| 907 |
|
| 908 |
+
# Tạo biểu đồ
|
|
|
|
|
|
|
|
|
|
| 909 |
bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
|
| 910 |
|
| 911 |
+
# Tạo tóm tắt
|
| 912 |
tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
|
| 913 |
|
| 914 |
+
# Tạo báo cáo chiến lược với streaming effect
|
| 915 |
+
bao_cao = tao_bao_cao_streaming(lua_chon_case)
|
| 916 |
|
| 917 |
+
return bieu_do, tom_tat, bao_cao
|
|
|
|
| 918 |
|
| 919 |
except Exception as e:
|
| 920 |
loi = f"❌ Lỗi xử lý: {str(e)}"
|
|
|
|
| 925 |
showarrow=False,
|
| 926 |
font=dict(size=16, color="red")
|
| 927 |
)
|
| 928 |
+
return empty_fig, loi, f"# ❌ Lỗi\n\n{loi}"
|
| 929 |
|
| 930 |
def cap_nhat_thong_tin_case(lua_chon_case):
|
| 931 |
"""Cập nhật thông tin case khi chọn"""
|
|
|
|
| 935 |
<div class='info-card'>
|
| 936 |
<h4>📋 Tình Huống: {lua_chon_case}</h4>
|
| 937 |
<p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
|
|
|
|
| 938 |
<p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
|
| 939 |
</div>
|
| 940 |
"""
|
|
|
|
| 942 |
|
| 943 |
# Tạo ứng dụng Gradio
|
| 944 |
def tao_ung_dung():
|
| 945 |
+
"""Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt"""
|
|
|
|
|
|
|
| 946 |
|
| 947 |
with gr.Blocks(
|
| 948 |
+
title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
|
| 949 |
theme=gr.themes.Soft(),
|
| 950 |
css=custom_css
|
| 951 |
) as demo:
|
| 952 |
|
| 953 |
+
# Header tiếng Việt với logo FoxAI
|
| 954 |
+
gr.HTML(f"""
|
| 955 |
<div class="header-container">
|
| 956 |
+
<div style="text-align: center; margin-bottom: 20px;">
|
| 957 |
+
<img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
|
| 958 |
+
</div>
|
| 959 |
<div class="header-title">
|
| 960 |
🇻🇳 HỆ THỐNG DỰ BÁO BÁN HÀNG AI 📊
|
| 961 |
</div>
|
| 962 |
+
<p style="font-size: 1.2em; color: #1A5F91; margin: 15px 0; font-weight: 600; line-height: 1.4;">
|
| 963 |
+
Công nghệ AI tiên tiến từ <strong>FoxAI</strong> cho phân tích và dự báo kinh doanh
|
| 964 |
</p>
|
| 965 |
<div class="system-status">
|
| 966 |
+
🟢 Hệ thống hoạt động bình thường • 🚀 Độ chính xác 95.8% • ⚡ Realtime Analytics • Powered by FoxAI
|
| 967 |
</div>
|
| 968 |
</div>
|
| 969 |
""")
|
|
|
|
| 972 |
gr.HTML("""
|
| 973 |
<div class='info-card'>
|
| 974 |
<h3>🎯 Hướng Dẫn Sử Dụng Hệ Thống</h3>
|
| 975 |
+
<p>Chọn mặt hàng dự đoán, chu kỳ dự báo và chế độ xem để nhận được phân tích AI chi tiết với khuyến nghị điều hành.</p>
|
| 976 |
|
| 977 |
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 978 |
<div>
|
| 979 |
+
<h4>🛍️ Mặt Hàng Có Sẵn:</h4>
|
| 980 |
<ul>
|
| 981 |
<li>📱 Điện tử & Công nghệ</li>
|
| 982 |
<li>👕 Thời trang & Làm đẹp</li>
|
| 983 |
<li>🍔 Thực phẩm & Đồ uống</li>
|
|
|
|
| 984 |
</ul>
|
| 985 |
</div>
|
| 986 |
|
|
|
|
| 998 |
|
| 999 |
with gr.Row():
|
| 1000 |
with gr.Column(scale=1):
|
| 1001 |
+
gr.HTML("<div class='feature-box floating'><h3>⚙️ Cài Đặt Phân Tích</h3></div>")
|
| 1002 |
|
| 1003 |
lua_chon_dropdown = gr.Dropdown(
|
| 1004 |
choices=list(TRUONG_HOP_DEMO.keys()),
|
| 1005 |
value=list(TRUONG_HOP_DEMO.keys())[0],
|
| 1006 |
+
label="🛍️ Chọn Mặt Hàng Dự Đoán",
|
| 1007 |
+
info="Mỗi mặt hàng có đặc điểm và insight riêng biệt",
|
| 1008 |
+
elem_classes=["tech-border"]
|
| 1009 |
)
|
| 1010 |
|
| 1011 |
chu_ky_dropdown = gr.Dropdown(
|
| 1012 |
choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
|
| 1013 |
value="3 tháng",
|
| 1014 |
label="📊 Chu Kỳ Dự Báo",
|
| 1015 |
+
info="Chọn khoảng thời gian dự báo phù hợp với mục đích kinh doanh",
|
| 1016 |
+
elem_classes=["tech-border"]
|
| 1017 |
)
|
| 1018 |
|
| 1019 |
nut_du_bao = gr.Button(
|
| 1020 |
"🚀 Tạo Dự Báo AI",
|
| 1021 |
variant="primary",
|
| 1022 |
size="lg",
|
| 1023 |
+
elem_classes=["btn-modern", "neon-border"]
|
| 1024 |
)
|
| 1025 |
|
| 1026 |
# Hiển thị thông tin case
|
|
|
|
| 1028 |
|
| 1029 |
with gr.Row():
|
| 1030 |
with gr.Column():
|
| 1031 |
+
gr.HTML("<div class='feature-box floating'><h3>📈 Kết Quả Dự Báo</h3></div>")
|
| 1032 |
|
| 1033 |
# Chế độ hiển thị được đặt gần biểu đồ
|
| 1034 |
che_do_xem = gr.Radio(
|
| 1035 |
choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
|
| 1036 |
value="ngày",
|
| 1037 |
label="📊 Chế Độ Hiển Thị Biểu Đồ",
|
| 1038 |
+
info="Thay đổi cách hiển thị dữ liệu trên biểu đồ",
|
| 1039 |
+
elem_classes=["tech-border"]
|
| 1040 |
)
|
| 1041 |
|
| 1042 |
bieu_do_du_bao = gr.Plot(
|
| 1043 |
label="Biểu Đồ Dự Báo Bán Hàng",
|
| 1044 |
+
elem_classes=["plot-container", "glass-card", "neon-border"]
|
| 1045 |
)
|
| 1046 |
|
| 1047 |
with gr.Row():
|
| 1048 |
with gr.Column(scale=1):
|
| 1049 |
+
gr.HTML("<div class='feature-box floating'><h3>📊 Thống Kê Tổng Hợp</h3></div>")
|
| 1050 |
hien_thi_tom_tat = gr.HTML()
|
| 1051 |
|
| 1052 |
with gr.Column(scale=1):
|
| 1053 |
+
gr.HTML("<div class='feature-box floating'><h3>🎯 Chiến Lược Đề Xuất</h3></div>")
|
| 1054 |
+
|
| 1055 |
+
# Button để tạo streaming effect
|
| 1056 |
+
nut_streaming = gr.Button(
|
| 1057 |
+
"🤖 Tạo Chiến Lược AI (Streaming)",
|
| 1058 |
+
variant="secondary",
|
| 1059 |
+
size="sm",
|
| 1060 |
+
elem_classes=["btn-modern"],
|
| 1061 |
+
visible=False
|
| 1062 |
+
)
|
| 1063 |
+
|
| 1064 |
hien_thi_bao_cao = gr.Markdown()
|
| 1065 |
|
| 1066 |
+
# Xử lý sự kiện streaming cho chiến lược
|
| 1067 |
+
def xu_ly_streaming(lua_chon_case):
|
| 1068 |
+
"""Xử lý streaming effect cho chiến lược đề xuất"""
|
| 1069 |
+
if lua_chon_case is None:
|
| 1070 |
+
return "# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Chọn mặt hàng để tạo chiến lược**"
|
| 1071 |
+
|
| 1072 |
+
try:
|
| 1073 |
+
for partial_text in tao_streaming_text(lua_chon_case):
|
| 1074 |
+
yield partial_text
|
| 1075 |
+
except Exception as e:
|
| 1076 |
+
yield f"# ❌ Lỗi\n\nKhông thể tạo chiến lược: {str(e)}"
|
| 1077 |
+
|
| 1078 |
+
# Button streaming sẽ chỉ hiện khi đã có dữ liệu
|
| 1079 |
+
def hien_thi_nut_streaming(lua_chon_case):
|
| 1080 |
+
"""Hiển thị button streaming khi đã chọn mặt hàng"""
|
| 1081 |
+
return gr.update(visible=lua_chon_case is not None)
|
| 1082 |
+
|
| 1083 |
# Xử lý sự kiện
|
| 1084 |
lua_chon_dropdown.change(
|
| 1085 |
+
fn=lambda x: [cap_nhat_thong_tin_case(x), hien_thi_nut_streaming(x)],
|
| 1086 |
inputs=[lua_chon_dropdown],
|
| 1087 |
+
outputs=[hien_thi_thong_tin, nut_streaming]
|
| 1088 |
)
|
| 1089 |
|
| 1090 |
nut_du_bao.click(
|
|
|
|
| 1094 |
show_progress=True
|
| 1095 |
)
|
| 1096 |
|
| 1097 |
+
# Streaming event cho chiến lược đề xuất
|
| 1098 |
+
nut_streaming.click(
|
| 1099 |
+
fn=xu_ly_streaming,
|
| 1100 |
+
inputs=[lua_chon_dropdown],
|
| 1101 |
+
outputs=[hien_thi_bao_cao],
|
| 1102 |
+
show_progress=False
|
| 1103 |
+
)
|
| 1104 |
+
|
| 1105 |
+
# Cập nhật biểu đồ khi thay đổi chế độ hiển thị - chỉ khi đã có dự đoán
|
| 1106 |
+
def cap_nhat_khi_doi_che_do(case, chu_ky, mode):
|
| 1107 |
+
try:
|
| 1108 |
+
if case and case != "":
|
| 1109 |
+
return [
|
| 1110 |
+
tao_bieu_do_du_doan(case, chu_ky, mode),
|
| 1111 |
+
tao_thong_tin_tom_tat(case, chu_ky, mode)
|
| 1112 |
+
]
|
| 1113 |
+
else:
|
| 1114 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 1115 |
+
except:
|
| 1116 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 1117 |
+
|
| 1118 |
che_do_xem.change(
|
| 1119 |
+
fn=cap_nhat_khi_doi_che_do,
|
| 1120 |
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 1121 |
outputs=[bieu_do_du_bao, hien_thi_tom_tat]
|
| 1122 |
)
|
| 1123 |
|
| 1124 |
+
# Tự động load case đầu tiên với biểu đồ mặc định
|
| 1125 |
demo.load(
|
| 1126 |
fn=lambda: [
|
| 1127 |
cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
|
| 1128 |
+
tao_bieu_do_mac_dinh(),
|
| 1129 |
+
tao_tom_tat_mac_dinh(),
|
| 1130 |
+
"# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**\n\nHệ thống AI sẽ tạo chiến lược đề xuất với insights và khuyến nghị cụ thể."
|
| 1131 |
],
|
| 1132 |
outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
|
| 1133 |
)
|
| 1134 |
|
| 1135 |
+
# Footer thông tin hệ thống với branding FoxAI
|
| 1136 |
+
gr.HTML(f"""
|
| 1137 |
<div class='info-card' style="margin-top: 30px;">
|
| 1138 |
+
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 20px;">
|
| 1139 |
+
<img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
|
| 1140 |
+
<h3 style="color: #1A5F91; margin: 0;">💡 Thông Tin Hệ Thống FoxAI</h3>
|
| 1141 |
+
</div>
|
| 1142 |
|
| 1143 |
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 1144 |
<div>
|
| 1145 |
+
<h4 style="color: #1A5F91;">🎯 Tính Năng Nổi Bật:</h4>
|
| 1146 |
<ul>
|
| 1147 |
<li><strong>AI Insights:</strong> Phân tích thông minh với khuyến nghị cụ thể</li>
|
| 1148 |
<li><strong>Multi-view:</strong> Xem theo ngày/tháng/năm linh hoạt</li>
|
|
|
|
| 1152 |
</div>
|
| 1153 |
|
| 1154 |
<div>
|
| 1155 |
+
<h4 style="color: #1A5F91;">📊 Chất Lượng Dự Báo:</h4>
|
| 1156 |
<ul>
|
| 1157 |
+
<li><strong>Độ Chính Xác:</strong> 95.8% trên 3 ngành hàng</li>
|
| 1158 |
+
<li><strong>Phạm Vi:</strong> Từ 3 tháng đến 1 năm</li>
|
| 1159 |
<li><strong>Cập Nhật:</strong> Real-time với market intelligence</li>
|
| 1160 |
<li><strong>Báo Cáo:</strong> Professional format cho C-level executives</li>
|
| 1161 |
</ul>
|
| 1162 |
</div>
|
| 1163 |
</div>
|
| 1164 |
|
| 1165 |
+
<div style="text-align: center; margin: 20px 0; padding: 15px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 10px; border: 2px solid #1A5F91;">
|
| 1166 |
+
<p style="color: #1A5F91; font-weight: bold; margin: 0; font-size: 16px;">
|
| 1167 |
+
🦊 <strong>Powered by FoxAI</strong> | 🇻🇳 Made in Vietnam | 🤖 Advanced AI | 📊 Enterprise Ready | ⚡ Real-time Analytics
|
| 1168 |
+
</p>
|
| 1169 |
+
<p style="color: #8B8B8B; margin: 5px 0 0 0; font-size: 14px;">
|
| 1170 |
+
YOUR TRUSTED PARTNER - FoxAI Technology Solutions
|
| 1171 |
</p>
|
| 1172 |
</div>
|
| 1173 |
</div>
|
app_backup.py
ADDED
|
@@ -0,0 +1,812 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
import numpy as np
|
| 4 |
+
from datetime import datetime, timedelta
|
| 5 |
+
import random
|
| 6 |
+
import time
|
| 7 |
+
|
| 8 |
+
# Logo FoxAI base64
|
| 9 |
+
FOXAI_LOGO = "data:image/png;base64,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"
|
| 10 |
+
|
| 11 |
+
# CSS Style với màu sắc FoxAI
|
| 12 |
+
custom_css = f"""
|
| 13 |
+
.gradio-container {{
|
| 14 |
+
background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
|
| 15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 16 |
+
}}
|
| 17 |
+
|
| 18 |
+
.header-container {{
|
| 19 |
+
text-align: center;
|
| 20 |
+
margin: 20px 0;
|
| 21 |
+
padding: 30px;
|
| 22 |
+
background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1));
|
| 23 |
+
border-radius: 20px;
|
| 24 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
|
| 25 |
+
}}
|
| 26 |
+
|
| 27 |
+
.foxai-logo {{
|
| 28 |
+
max-width: 250px;
|
| 29 |
+
height: auto;
|
| 30 |
+
margin: 15px 0 25px 0;
|
| 31 |
+
display: block;
|
| 32 |
+
z-index: 1000;
|
| 33 |
+
position: relative;
|
| 34 |
+
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
|
| 35 |
+
}}
|
| 36 |
+
|
| 37 |
+
.header-title {{
|
| 38 |
+
background: linear-gradient(90deg, #1A5F91, #8B8B8B, #1A5F91);
|
| 39 |
+
background-size: 300% 300%;
|
| 40 |
+
animation: gradient 8s ease infinite;
|
| 41 |
+
-webkit-background-clip: text;
|
| 42 |
+
-webkit-text-fill-color: transparent;
|
| 43 |
+
background-clip: text;
|
| 44 |
+
text-align: center;
|
| 45 |
+
font-size: 2.5em;
|
| 46 |
+
font-weight: bold;
|
| 47 |
+
margin: 15px 0;
|
| 48 |
+
line-height: 1.2;
|
| 49 |
+
z-index: 999;
|
| 50 |
+
position: relative;
|
| 51 |
+
}}
|
| 52 |
+
|
| 53 |
+
@keyframes gradient {{
|
| 54 |
+
0% {{ background-position: 0% 50%; }}
|
| 55 |
+
50% {{ background-position: 100% 50%; }}
|
| 56 |
+
100% {{ background-position: 0% 50%; }}
|
| 57 |
+
}}
|
| 58 |
+
|
| 59 |
+
.loading-container {{
|
| 60 |
+
text-align: center;
|
| 61 |
+
padding: 40px;
|
| 62 |
+
background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
|
| 63 |
+
border-radius: 15px;
|
| 64 |
+
color: white;
|
| 65 |
+
margin: 20px 0;
|
| 66 |
+
}}
|
| 67 |
+
|
| 68 |
+
.loading-spinner {{
|
| 69 |
+
border: 4px solid #f3f3f3;
|
| 70 |
+
border-top: 4px solid #1A5F91;
|
| 71 |
+
border-radius: 50%;
|
| 72 |
+
width: 40px;
|
| 73 |
+
height: 40px;
|
| 74 |
+
animation: spin 1s linear infinite;
|
| 75 |
+
margin: 0 auto 20px;
|
| 76 |
+
}}
|
| 77 |
+
|
| 78 |
+
@keyframes spin {{
|
| 79 |
+
0% {{ transform: rotate(0deg); }}
|
| 80 |
+
100% {{ transform: rotate(360deg); }}
|
| 81 |
+
}}
|
| 82 |
+
|
| 83 |
+
.progress-bar {{
|
| 84 |
+
width: 100%;
|
| 85 |
+
height: 20px;
|
| 86 |
+
background-color: rgba(255,255,255,0.3);
|
| 87 |
+
border-radius: 10px;
|
| 88 |
+
overflow: hidden;
|
| 89 |
+
margin: 15px 0;
|
| 90 |
+
}}
|
| 91 |
+
|
| 92 |
+
.progress-fill {{
|
| 93 |
+
height: 100%;
|
| 94 |
+
background: linear-gradient(90deg, #1A5F91, #8B8B8B);
|
| 95 |
+
border-radius: 10px;
|
| 96 |
+
animation: progress 3s ease-in-out;
|
| 97 |
+
}}
|
| 98 |
+
|
| 99 |
+
@keyframes progress {{
|
| 100 |
+
0% {{ width: 0%; }}
|
| 101 |
+
25% {{ width: 30%; }}
|
| 102 |
+
50% {{ width: 60%; }}
|
| 103 |
+
75% {{ width: 85%; }}
|
| 104 |
+
100% {{ width: 100%; }}
|
| 105 |
+
}}
|
| 106 |
+
|
| 107 |
+
.prediction-box {{
|
| 108 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 109 |
+
border-radius: 15px;
|
| 110 |
+
padding: 20px;
|
| 111 |
+
color: white;
|
| 112 |
+
text-align: center;
|
| 113 |
+
font-size: 1.1em;
|
| 114 |
+
font-weight: bold;
|
| 115 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 116 |
+
margin: 15px 0;
|
| 117 |
+
}}
|
| 118 |
+
|
| 119 |
+
.insight-box {{
|
| 120 |
+
background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
|
| 121 |
+
border-radius: 15px;
|
| 122 |
+
padding: 20px;
|
| 123 |
+
color: white;
|
| 124 |
+
margin: 15px 0;
|
| 125 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 126 |
+
}}
|
| 127 |
+
|
| 128 |
+
.executive-summary {{
|
| 129 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 130 |
+
border-radius: 15px;
|
| 131 |
+
padding: 25px;
|
| 132 |
+
color: white;
|
| 133 |
+
margin: 15px 0;
|
| 134 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 135 |
+
border-left: 5px solid #1A5F91;
|
| 136 |
+
}}
|
| 137 |
+
|
| 138 |
+
.feature-box {{
|
| 139 |
+
background: linear-gradient(135deg, rgba(26, 95, 145, 0.2), rgba(139, 139, 139, 0.2));
|
| 140 |
+
border-radius: 15px;
|
| 141 |
+
padding: 15px;
|
| 142 |
+
margin: 10px 0;
|
| 143 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 144 |
+
border-left: 4px solid #1A5F91;
|
| 145 |
+
}}
|
| 146 |
+
|
| 147 |
+
.feature-box h3 {{
|
| 148 |
+
margin: 0;
|
| 149 |
+
color: #1A5F91;
|
| 150 |
+
font-weight: bold;
|
| 151 |
+
}}
|
| 152 |
+
|
| 153 |
+
.system-status {{
|
| 154 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 155 |
+
color: white;
|
| 156 |
+
padding: 10px 20px;
|
| 157 |
+
border-radius: 25px;
|
| 158 |
+
margin: 10px 0;
|
| 159 |
+
text-align: center;
|
| 160 |
+
font-weight: bold;
|
| 161 |
+
}}
|
| 162 |
+
|
| 163 |
+
.metric-card {{
|
| 164 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 165 |
+
color: white;
|
| 166 |
+
border-radius: 10px;
|
| 167 |
+
padding: 15px;
|
| 168 |
+
margin: 5px;
|
| 169 |
+
text-align: center;
|
| 170 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
| 171 |
+
}}
|
| 172 |
+
|
| 173 |
+
.button-predict {{
|
| 174 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B) !important;
|
| 175 |
+
color: white !important;
|
| 176 |
+
border: none !important;
|
| 177 |
+
border-radius: 25px !important;
|
| 178 |
+
padding: 15px 30px !important;
|
| 179 |
+
font-size: 16px !important;
|
| 180 |
+
font-weight: bold !important;
|
| 181 |
+
box-shadow: 0 4px 15px rgba(26, 95, 145, 0.4) !important;
|
| 182 |
+
transition: all 0.3s ease !important;
|
| 183 |
+
}}
|
| 184 |
+
|
| 185 |
+
.button-predict:hover {{
|
| 186 |
+
transform: translateY(-2px) !important;
|
| 187 |
+
box-shadow: 0 6px 20px rgba(26, 95, 145, 0.6) !important;
|
| 188 |
+
}}
|
| 189 |
+
|
| 190 |
+
.plot-container {{
|
| 191 |
+
border: 1px solid #e1e5e9;
|
| 192 |
+
border-radius: 15px;
|
| 193 |
+
padding: 15px;
|
| 194 |
+
margin: 15px 0;
|
| 195 |
+
background: rgba(255, 255, 255, 0.95);
|
| 196 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 197 |
+
min-height: 400px;
|
| 198 |
+
}}
|
| 199 |
+
|
| 200 |
+
.info-card {{
|
| 201 |
+
background: rgba(255, 255, 255, 0.95);
|
| 202 |
+
border-radius: 10px;
|
| 203 |
+
padding: 15px;
|
| 204 |
+
margin: 10px 0;
|
| 205 |
+
border-left: 5px solid #1A5F91;
|
| 206 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 207 |
+
}}
|
| 208 |
+
|
| 209 |
+
/* Sửa lỗi font và text rendering */
|
| 210 |
+
* {{
|
| 211 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 212 |
+
text-rendering: optimizeLegibility !important;
|
| 213 |
+
-webkit-font-smoothing: antialiased !important;
|
| 214 |
+
-moz-osx-font-smoothing: grayscale !important;
|
| 215 |
+
}}
|
| 216 |
+
|
| 217 |
+
/* Cải thiện hiển thị tiếng Việt */
|
| 218 |
+
.gradio-markdown, .gradio-html {{
|
| 219 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 220 |
+
line-height: 1.6 !important;
|
| 221 |
+
word-wrap: break-word !important;
|
| 222 |
+
overflow-wrap: break-word !important;
|
| 223 |
+
}}
|
| 224 |
+
|
| 225 |
+
/* Sửa lỗi layout kéo dài */
|
| 226 |
+
.gradio-container .wrap {{
|
| 227 |
+
max-width: 100% !important;
|
| 228 |
+
overflow-x: hidden !important;
|
| 229 |
+
}}
|
| 230 |
+
|
| 231 |
+
.gradio-row {{
|
| 232 |
+
flex-wrap: wrap !important;
|
| 233 |
+
}}
|
| 234 |
+
|
| 235 |
+
.gradio-column {{
|
| 236 |
+
min-width: 0 !important;
|
| 237 |
+
flex-shrink: 1 !important;
|
| 238 |
+
}}
|
| 239 |
+
"""
|
| 240 |
+
|
| 241 |
+
# Dữ liệu demo tiếng Việt cho 3 trường hợp chính
|
| 242 |
+
TRUONG_HOP_DEMO = {
|
| 243 |
+
"📱 Điện tử & Công nghệ": {
|
| 244 |
+
"danh_muc": "Điện tử & Công nghệ",
|
| 245 |
+
"don_vi_co_ban": 150,
|
| 246 |
+
"xu_huong": "tang_dan",
|
| 247 |
+
"mo_ta": "Dự báo bán hàng sản phẩm điện tử, smartphone, laptop và thiết bị công nghệ",
|
| 248 |
+
"thong_tin_giam_doc": {
|
| 249 |
+
"tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện tử có xu hướng tăng trưởng mạnh 180-250% với sự phát triển của công nghệ AI, 5G và IoT. Đây là cơ hội vàng để chiếm lĩnh thị phần.",
|
| 250 |
+
"chi_tiet": "**📊 PHÂN TÍCH KINH DOANH SÂUSẮC:** Thị trường điện tử đang trải qua làn sóng tăng trưởng mạnh với mức tăng 180-250% do several factors: (1) Digital transformation gia tăng sau COVID, (2) Work from home trend tạo nhu cầu laptop/monitor, (3) Gen Z có spending power cao cho gadgets, (4) AI boom tạo nhu cầu hardware mạnh. Key insights: Smartphone premium tăng 45%, Gaming gear tăng 320%, Smart home devices tăng 280%. Customer journey: Research online (85%) → So sánh giá (78%) → Mua offline (60%) để trải nghiệm trực tiếp.",
|
| 251 |
+
"hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH CHIẾN LƯỢC:** (1) **Inventory Strategy:** Tăng tồn kho 200% cho flagship models, đặc biệt iPhone/Samsung dòng cao cấp và gaming laptops, (2) **Digital Integration:** Xây dựng AR/VR showroom để khách hàng try before buy, (3) **Partnership Ecosystem:** Hợp tác với fintech cho installment 0%, tie-up với game publishers cho gaming bundle, (4) **Market Expansion:** Mở rộng sang smart home ecosystem với IoT devices, (5) **After-sales Excellence:** Extended warranty và premium support để tăng customer lifetime value và build brand loyalty."
|
| 252 |
+
}
|
| 253 |
+
},
|
| 254 |
+
|
| 255 |
+
"👕 Thời trang & Làm đẹp": {
|
| 256 |
+
"danh_muc": "Thời trang & Làm đẹp",
|
| 257 |
+
"don_vi_co_ban": 80,
|
| 258 |
+
"xu_huong": "bien_dong",
|
| 259 |
+
"mo_ta": "Dự báo xu hướng thời trang, mỹ phẩm và các sản phẩm làm đẹp theo mùa",
|
| 260 |
+
"thong_tin_giam_doc": {
|
| 261 |
+
"tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang & làm đẹp có tính mùa vụ rõ rệt với biến động 15-180% theo trend và influencer impact. Cần strategy linh hoạt để maximize các peak seasons.",
|
| 262 |
+
"chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG FASHION & BEAUTY:** Industry có pattern rất đặc biệt với multiple micro-seasons: (1) Spring/Summer collection (Mar-Aug) peak 170%, (2) Fall/Winter collection (Sep-Feb) stable 120%, (3) Special events (Valentine +240%, Tết +185%, graduation season +150%). Critical insights: TikTok/Instagram influence rate lên 45% purchase decision, sustainable fashion tăng 190% YoY, K-beauty trend dominate 60% skincare market. Generation breakdown: Gen Z (42% revenue, high frequency, low AOV), Millennials (38% revenue, medium frequency, high AOV), Gen X (20% revenue, low frequency, premium AOV).",
|
| 263 |
+
"hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI OMNICHANNEL:** (1) **Trend Forecasting:** AI-powered trend analysis từ social media để predict viral products 2-3 months trước, (2) **Influencer Partnership:** Collaborate với 50+ nano/micro influencers (10K-100K followers) cho authentic engagement thay vì 1-2 mega influencers, (3) **Inventory Agility:** Fast fashion model với small batch testing → scale winners rapidly, (4) **Personalization Engine:** Skin analysis app + virtual try-on technology để tăng conversion rate, (5) **Sustainability Edge:** Launch eco-friendly line với packaging innovation để capture conscious consumers và justify premium pricing."
|
| 264 |
+
}
|
| 265 |
+
},
|
| 266 |
+
|
| 267 |
+
"🍔 Thực phẩm & Đồ uống": {
|
| 268 |
+
"danh_muc": "Thực phẩm & Đồ uống",
|
| 269 |
+
"don_vi_co_ban": 200,
|
| 270 |
+
"xu_huong": "on_dinh",
|
| 271 |
+
"mo_ta": "Dự báo thị trường F&B, food delivery và các sản phẩm tiêu dùng hàng ngày",
|
| 272 |
+
"thong_tin_giam_doc": {
|
| 273 |
+
"tom_tat": "🍽️ **TÓM TẮT ĐIỀU HÀNH:** F&B market ổn định với baseline consumption nhưng có opportunity spikes từ weather, events và lifestyle changes. Delivery segment tăng 280%, healthy food trend tăng 165%.",
|
| 274 |
+
"chi_tiet": "**⛈️ PHÂN TÍCH F&B MARKET DYNAMICS:** F&B industry có đặc điểm unique với stable baseline demand nhưng high weather sensitivity và event-driven spikes. Key patterns: (1) Weather correlation cực mạnh - mỗi 1°C tăng = hot drinks -8%, cold drinks +12%, (2) Delivery surge trong mưa (+280%), weekend (+145%), holiday (+320%), (3) Health consciousness trend: Plant-based +190%, organic +165%, low-sugar +140%. Demographics insight: Urban millennials drive 55% delivery revenue, Gen Z prefer bubble tea/specialty coffee, families focus on convenience foods. Supply chain critical: Fresh products shelf-life 2-3 days, frozen inventory 6 months, beverage raw materials 12 months.",
|
| 275 |
+
"hanh_dong": "**☔ CHIẾN THUẬT WEATHER-RESPONSIVE F&B:** (1) **Predictive Inventory:** Weather API integration để auto-adjust inventory 48h trước based on forecast - rain = +200% comfort food, heat = +150% cold beverages, (2) **Delivery Optimization:** Dynamic delivery zones expansion trong bad weather, surge pricing strategy để incentivize drivers, ghost kitchen positioning ở high-density areas, (3) **Health & Wellness Pivot:** Launch functional beverages (immunity boost, energy, beauty), partner với gyms/yoga studios, subscription healthy meal plans, (4) **Experience Innovation:** Interactive cooking classes, farm-to-table storytelling, sustainable packaging để build brand differentiation, (5) **Data-Driven Menu:** Customer preference analytics để optimize menu mix và eliminate low-performers monthly."
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
def tao_bieu_do_mac_dinh():
|
| 281 |
+
"""
|
| 282 |
+
Tạo biểu đồ mặc định khi chưa dự đoán
|
| 283 |
+
"""
|
| 284 |
+
fig = go.Figure()
|
| 285 |
+
|
| 286 |
+
fig.add_annotation(
|
| 287 |
+
text="📊 Chọn tình huống và nhấn 'Tạo Dự Báo AI' để xem phân tích",
|
| 288 |
+
xref="paper", yref="paper",
|
| 289 |
+
x=0.5, y=0.5,
|
| 290 |
+
xanchor='center', yanchor='middle',
|
| 291 |
+
showarrow=False,
|
| 292 |
+
font=dict(size=18, color="#34495E", family="Arial"),
|
| 293 |
+
bgcolor="rgba(255,255,255,0.9)",
|
| 294 |
+
bordercolor="#BDC3C7",
|
| 295 |
+
borderwidth=2,
|
| 296 |
+
borderpad=20
|
| 297 |
+
)
|
| 298 |
+
|
| 299 |
+
fig.update_layout(
|
| 300 |
+
title="🎯 Hệ Thống Dự Báo AI Sẵn Sàng",
|
| 301 |
+
template="plotly_white",
|
| 302 |
+
height=400,
|
| 303 |
+
showlegend=False,
|
| 304 |
+
xaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 305 |
+
yaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 306 |
+
plot_bgcolor='rgba(248,249,250,0.8)',
|
| 307 |
+
font=dict(family="Arial")
|
| 308 |
+
)
|
| 309 |
+
|
| 310 |
+
return fig
|
| 311 |
+
|
| 312 |
+
def tao_tom_tat_mac_dinh():
|
| 313 |
+
"""
|
| 314 |
+
Tạo tóm tắt mặc định
|
| 315 |
+
"""
|
| 316 |
+
return """
|
| 317 |
+
<div class="prediction-box">
|
| 318 |
+
<h3 style="margin-top: 0; color: white;">📋 Thống Kê Sẽ Hiển Thị Sau Dự Báo</h3>
|
| 319 |
+
<div style="text-align: center; padding: 20px;">
|
| 320 |
+
<p style="font-size: 18px; margin: 10px 0; color: white;">
|
| 321 |
+
🎯 Chọn tình huống kinh doanh và nhấn "Tạo Dự Báo AI"
|
| 322 |
+
</p>
|
| 323 |
+
<p style="font-size: 16px; margin: 10px 0; color: #E8F6F3;">
|
| 324 |
+
Hệ thống sẽ phân tích và đưa ra insights chi tiết
|
| 325 |
+
</p>
|
| 326 |
+
</div>
|
| 327 |
+
</div>
|
| 328 |
+
"""
|
| 329 |
+
|
| 330 |
+
def tao_du_lieu_demo(thong_tin_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 331 |
+
"""
|
| 332 |
+
Tạo dữ liệu demo đơn giản dựa trên case và chu kỳ dự báo
|
| 333 |
+
"""
|
| 334 |
+
don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
|
| 335 |
+
xu_huong = thong_tin_case["xu_huong"]
|
| 336 |
+
|
| 337 |
+
# Xác định số điểm dữ liệu
|
| 338 |
+
if chu_ky == "1 năm":
|
| 339 |
+
so_diem = 12 if che_do_xem == 'năm' else (52 if che_do_xem == 'tháng' else 365)
|
| 340 |
+
elif chu_ky == "6 tháng":
|
| 341 |
+
so_diem = 6 if che_do_xem == 'năm' else (26 if che_do_xem == 'tháng' else 180)
|
| 342 |
+
else: # "3 tháng"
|
| 343 |
+
so_diem = 3 if che_do_xem == 'năm' else (13 if che_do_xem == 'tháng' else 90)
|
| 344 |
+
|
| 345 |
+
# Tạo nhãn thời gian
|
| 346 |
+
if che_do_xem == 'năm':
|
| 347 |
+
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 348 |
+
elif che_do_xem == 'tháng':
|
| 349 |
+
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 350 |
+
else: # ngày
|
| 351 |
+
ngay_bat_dau = datetime.now()
|
| 352 |
+
nhan_thoi_gian = [(ngay_bat_dau + timedelta(days=i)).strftime("%d/%m") for i in range(so_diem)]
|
| 353 |
+
|
| 354 |
+
# Tạo dữ liệu dựa trên xu hướng đơn giản
|
| 355 |
+
don_vi_ban = []
|
| 356 |
+
for i in range(so_diem):
|
| 357 |
+
if xu_huong == "tang_dan":
|
| 358 |
+
he_so = 1 + (i / so_diem) * 1.5
|
| 359 |
+
elif xu_huong == "bien_dong":
|
| 360 |
+
he_so = 1 + 0.3 * np.sin(2 * np.pi * i / so_diem * 3)
|
| 361 |
+
elif xu_huong == "on_dinh":
|
| 362 |
+
he_so = 1 + random.uniform(-0.2, 0.2)
|
| 363 |
+
else: # fallback cho các xu hướng khác
|
| 364 |
+
he_so = 1 + random.uniform(-0.1, 0.1)
|
| 365 |
+
|
| 366 |
+
don_vi = max(int(don_vi_co_ban * he_so + random.randint(-30, 30)), 10)
|
| 367 |
+
don_vi_ban.append(don_vi)
|
| 368 |
+
|
| 369 |
+
return nhan_thoi_gian, don_vi_ban
|
| 370 |
+
|
| 371 |
+
def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 372 |
+
"""
|
| 373 |
+
Tạo biểu đồ dự đoán với hiệu ứng loading
|
| 374 |
+
"""
|
| 375 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 376 |
+
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 377 |
+
|
| 378 |
+
# Tạo biểu đồ chuyên nghiệp
|
| 379 |
+
fig = go.Figure()
|
| 380 |
+
|
| 381 |
+
# Biểu đồ chính
|
| 382 |
+
fig.add_trace(go.Scatter(
|
| 383 |
+
x=nhan_thoi_gian,
|
| 384 |
+
y=don_vi_ban,
|
| 385 |
+
mode='lines+markers',
|
| 386 |
+
name='📦 Dự Báo Đơn Vị Bán',
|
| 387 |
+
line=dict(color='#E74C3C', width=4),
|
| 388 |
+
marker=dict(size=12, color='#E74C3C', symbol='circle'),
|
| 389 |
+
hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
|
| 390 |
+
))
|
| 391 |
+
|
| 392 |
+
# Vùng tin cậy
|
| 393 |
+
upper_bound = [val * 1.15 for val in don_vi_ban]
|
| 394 |
+
lower_bound = [val * 0.85 for val in don_vi_ban]
|
| 395 |
+
|
| 396 |
+
fig.add_trace(go.Scatter(
|
| 397 |
+
x=nhan_thoi_gian + nhan_thoi_gian[::-1],
|
| 398 |
+
y=upper_bound + lower_bound[::-1],
|
| 399 |
+
fill='toself',
|
| 400 |
+
fillcolor='rgba(231, 76, 60, 0.2)',
|
| 401 |
+
line=dict(color='rgba(255,255,255,0)'),
|
| 402 |
+
name='📊 Vùng Tin Cậy',
|
| 403 |
+
hoverinfo="skip"
|
| 404 |
+
))
|
| 405 |
+
|
| 406 |
+
# Đường xu hướng
|
| 407 |
+
x_so = list(range(len(nhan_thoi_gian)))
|
| 408 |
+
z = np.polyfit(x_so, don_vi_ban, 1)
|
| 409 |
+
duong_xu_huong = np.poly1d(z)(x_so)
|
| 410 |
+
|
| 411 |
+
fig.add_trace(go.Scatter(
|
| 412 |
+
x=nhan_thoi_gian,
|
| 413 |
+
y=duong_xu_huong,
|
| 414 |
+
mode='lines',
|
| 415 |
+
name='📈 Xu Hướng',
|
| 416 |
+
line=dict(color='#2980B9', width=3, dash='dash'),
|
| 417 |
+
hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
|
| 418 |
+
))
|
| 419 |
+
|
| 420 |
+
# Đánh dấu ngày đỉnh
|
| 421 |
+
chi_so_dinh = [i for i, val in enumerate(don_vi_ban) if val == max(don_vi_ban)]
|
| 422 |
+
if chi_so_dinh:
|
| 423 |
+
chi_so = chi_so_dinh[0]
|
| 424 |
+
fig.add_trace(go.Scatter(
|
| 425 |
+
x=[nhan_thoi_gian[chi_so]],
|
| 426 |
+
y=[don_vi_ban[chi_so]],
|
| 427 |
+
mode='markers',
|
| 428 |
+
name='🔥 Đỉnh Doanh Số',
|
| 429 |
+
marker=dict(size=20, color='#F39C12', symbol='star'),
|
| 430 |
+
hovertemplate='<b>Đỉnh cao:</b> %{x}<br><b>Đơn vị:</b> %{y:,}<extra></extra>'
|
| 431 |
+
))
|
| 432 |
+
|
| 433 |
+
# Tiêu đề theo chế độ xem
|
| 434 |
+
tieu_de_che_do = {
|
| 435 |
+
'ngày': 'Theo Ngày',
|
| 436 |
+
'tháng': 'Theo Tháng',
|
| 437 |
+
'năm': 'Theo Năm'
|
| 438 |
+
}
|
| 439 |
+
|
| 440 |
+
fig.update_layout(
|
| 441 |
+
title=f"📊 Dự Báo Đơn Vị Bán - {tieu_de_che_do[che_do_xem]}: {ten_case} ({chu_ky})",
|
| 442 |
+
xaxis_title="⏰ Thời Gian",
|
| 443 |
+
yaxis_title="📦 Số Đơn Vị Bán",
|
| 444 |
+
template="plotly_white",
|
| 445 |
+
height=600,
|
| 446 |
+
showlegend=True,
|
| 447 |
+
hovermode='x unified',
|
| 448 |
+
xaxis=dict(tickangle=45 if che_do_xem == 'ngày' else 0),
|
| 449 |
+
font=dict(size=14, family="Arial"),
|
| 450 |
+
plot_bgcolor='rgba(248,249,250,0.8)'
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
return fig
|
| 454 |
+
|
| 455 |
+
def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 456 |
+
"""
|
| 457 |
+
Tạo thông tin tóm tắt dành cho giám đốc
|
| 458 |
+
"""
|
| 459 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 460 |
+
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 461 |
+
|
| 462 |
+
tong_don_vi = sum(don_vi_ban)
|
| 463 |
+
trung_binh = tong_don_vi / len(don_vi_ban)
|
| 464 |
+
ngay_dinh = max(don_vi_ban)
|
| 465 |
+
ngay_thap = min(don_vi_ban)
|
| 466 |
+
ty_le_tang_truong = ((don_vi_ban[-1] - don_vi_ban[0]) / don_vi_ban[0]) * 100
|
| 467 |
+
|
| 468 |
+
# Tính toán theo chế độ xem
|
| 469 |
+
don_vi_thoi_gian = {
|
| 470 |
+
'ngày': 'ngày',
|
| 471 |
+
'tháng': 'tuần',
|
| 472 |
+
'năm': 'tháng'
|
| 473 |
+
}[che_do_xem]
|
| 474 |
+
|
| 475 |
+
tom_tat_html = f"""
|
| 476 |
+
<div class="prediction-box">
|
| 477 |
+
<h3 style="margin-top: 0; color: white;">📋 Báo Cáo Dự Báo Điều Hành</h3>
|
| 478 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
|
| 479 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 480 |
+
<h4 style="margin: 0; color: #E8F6F3;">📦 Tổng Đơn Vị</h4>
|
| 481 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{tong_don_vi:,}</p>
|
| 482 |
+
</div>
|
| 483 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 484 |
+
<h4 style="margin: 0; color: #E8F6F3;">📈 TB/{don_vi_thoi_gian.title()}</h4>
|
| 485 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{trung_binh:,.0f}</p>
|
| 486 |
+
</div>
|
| 487 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 488 |
+
<h4 style="margin: 0; color: #E8F6F3;">🔥 Đỉnh Cao</h4>
|
| 489 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{ngay_dinh:,}</p>
|
| 490 |
+
</div>
|
| 491 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 492 |
+
<h4 style="margin: 0; color: #E8F6F3;">📊 Tăng Trưởng</h4>
|
| 493 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold; color: {'#2ECC71' if ty_le_tang_truong > 0 else '#E74C3C'};">
|
| 494 |
+
{ty_le_tang_truong:+.1f}%
|
| 495 |
+
</p>
|
| 496 |
+
</div>
|
| 497 |
+
</div>
|
| 498 |
+
<div style="margin-top: 15px; text-align: center;">
|
| 499 |
+
<p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
|
| 500 |
+
<p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
|
| 501 |
+
</div>
|
| 502 |
+
</div>
|
| 503 |
+
"""
|
| 504 |
+
|
| 505 |
+
return tom_tat_html
|
| 506 |
+
|
| 507 |
+
def tao_bao_cao_giam_doc(ten_case):
|
| 508 |
+
"""
|
| 509 |
+
Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown
|
| 510 |
+
"""
|
| 511 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 512 |
+
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 513 |
+
|
| 514 |
+
bao_cao_markdown = f"""
|
| 515 |
+
# 👔 BÁO CÁO ĐIỀU HÀNH
|
| 516 |
+
|
| 517 |
+
## 🎯 Tóm Tắt Điều Hành
|
| 518 |
+
|
| 519 |
+
{thong_tin_gd['tom_tat']}
|
| 520 |
+
|
| 521 |
+
## 📊 Phân Tích Chi Tiết
|
| 522 |
+
|
| 523 |
+
{thong_tin_gd['chi_tiet']}
|
| 524 |
+
|
| 525 |
+
## 🚀 Khuyến Nghị Hành Động
|
| 526 |
+
|
| 527 |
+
{thong_tin_gd['hanh_dong']}
|
| 528 |
+
|
| 529 |
+
---
|
| 530 |
+
*🤖 Phân tích được tạo bởi AI Business Intelligence | ⚡ Cập nhật realtime*
|
| 531 |
+
"""
|
| 532 |
+
|
| 533 |
+
return bao_cao_markdown
|
| 534 |
+
|
| 535 |
+
def tao_loading_effect():
|
| 536 |
+
"""
|
| 537 |
+
Tạo hiệu ứng loading để có cảm giác như production
|
| 538 |
+
"""
|
| 539 |
+
loading_html = """
|
| 540 |
+
<div class="loading-container">
|
| 541 |
+
<div class="loading-spinner"></div>
|
| 542 |
+
<h3 style="color: white; margin: 0;">🤖 Đang Xử Lý Dự Báo AI...</h3>
|
| 543 |
+
<div class="progress-bar">
|
| 544 |
+
<div class="progress-fill"></div>
|
| 545 |
+
</div>
|
| 546 |
+
<p style="color: white; margin: 10px 0; opacity: 0.9;">
|
| 547 |
+
⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights
|
| 548 |
+
</p>
|
| 549 |
+
</div>
|
| 550 |
+
"""
|
| 551 |
+
return loading_html
|
| 552 |
+
|
| 553 |
+
def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
|
| 554 |
+
"""
|
| 555 |
+
Xử lý dự đoán với hiệu ứng loading realistic
|
| 556 |
+
"""
|
| 557 |
+
if lua_chon_case is None:
|
| 558 |
+
return None, None, None
|
| 559 |
+
|
| 560 |
+
try:
|
| 561 |
+
# Bước 1: Hiển thị loading
|
| 562 |
+
loading = tao_loading_effect()
|
| 563 |
+
yield None, loading, ""
|
| 564 |
+
|
| 565 |
+
# Bước 2: Giả lập thời gian xử lý
|
| 566 |
+
time.sleep(2.5)
|
| 567 |
+
|
| 568 |
+
# Bước 3: Tạo biểu đồ
|
| 569 |
+
bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
|
| 570 |
+
|
| 571 |
+
# Bước 4: Tạo tóm tắt
|
| 572 |
+
tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
|
| 573 |
+
|
| 574 |
+
# Bước 5: Tạo báo cáo giám đốc (Markdown)
|
| 575 |
+
bao_cao = tao_bao_cao_giam_doc(lua_chon_case)
|
| 576 |
+
|
| 577 |
+
# Trả về kết quả cuối cùng
|
| 578 |
+
yield bieu_do, tom_tat, bao_cao
|
| 579 |
+
|
| 580 |
+
except Exception as e:
|
| 581 |
+
loi = f"❌ Lỗi xử lý: {str(e)}"
|
| 582 |
+
empty_fig = go.Figure().add_annotation(
|
| 583 |
+
text=loi,
|
| 584 |
+
xref="paper", yref="paper",
|
| 585 |
+
x=0.5, y=0.5,
|
| 586 |
+
showarrow=False,
|
| 587 |
+
font=dict(size=16, color="red")
|
| 588 |
+
)
|
| 589 |
+
yield empty_fig, f"<div style='color: red; padding: 20px;'>{loi}</div>", ""
|
| 590 |
+
|
| 591 |
+
def cap_nhat_thong_tin_case(lua_chon_case):
|
| 592 |
+
"""Cập nhật thông tin case khi chọn"""
|
| 593 |
+
if lua_chon_case in TRUONG_HOP_DEMO:
|
| 594 |
+
thong_tin = TRUONG_HOP_DEMO[lua_chon_case]
|
| 595 |
+
return f"""
|
| 596 |
+
<div class='info-card'>
|
| 597 |
+
<h4>📋 Tình Huống: {lua_chon_case}</h4>
|
| 598 |
+
<p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
|
| 599 |
+
<p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
|
| 600 |
+
</div>
|
| 601 |
+
"""
|
| 602 |
+
return ""
|
| 603 |
+
|
| 604 |
+
# Tạo ứng dụng Gradio
|
| 605 |
+
def tao_ung_dung():
|
| 606 |
+
"""
|
| 607 |
+
Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt
|
| 608 |
+
"""
|
| 609 |
+
|
| 610 |
+
with gr.Blocks(
|
| 611 |
+
title="🚀 Hệ Thống Dự Báo Bán Hàng AI - Tiếng Việt",
|
| 612 |
+
theme=gr.themes.Soft(),
|
| 613 |
+
css=custom_css
|
| 614 |
+
) as demo:
|
| 615 |
+
|
| 616 |
+
# Header tiếng Việt với logo FoxAI
|
| 617 |
+
gr.HTML(f"""
|
| 618 |
+
<div class="header-container">
|
| 619 |
+
<div style="text-align: center; margin-bottom: 20px;">
|
| 620 |
+
<img src="{FOXAI_LOGO}" alt="FoxAI Logo" class="foxai-logo"/>
|
| 621 |
+
</div>
|
| 622 |
+
<div class="header-title">
|
| 623 |
+
🇻🇳 HỆ THỐNG DỰ BÁO BÁN HÀNG AI 📊
|
| 624 |
+
</div>
|
| 625 |
+
<p style="font-size: 1.2em; color: #1A5F91; margin: 15px 0; font-weight: 600; line-height: 1.4;">
|
| 626 |
+
Công nghệ AI tiên tiến từ <strong>FoxAI</strong> cho phân tích và dự báo kinh doanh
|
| 627 |
+
</p>
|
| 628 |
+
<div class="system-status">
|
| 629 |
+
🟢 Hệ thống hoạt động bình thường • 🚀 Độ chính xác 95.8% • ⚡ Realtime Analytics • Powered by FoxAI
|
| 630 |
+
</div>
|
| 631 |
+
</div>
|
| 632 |
+
""")
|
| 633 |
+
|
| 634 |
+
# Hướng dẫn sử dụng
|
| 635 |
+
gr.HTML("""
|
| 636 |
+
<div class='info-card'>
|
| 637 |
+
<h3>🎯 Hướng Dẫn Sử Dụng Hệ Thống</h3>
|
| 638 |
+
<p>Chọn tình huống kinh doanh, số ngày dự báo và chế độ xem để nhận được phân tích AI chi tiết với khuyến nghị điều hành.</p>
|
| 639 |
+
|
| 640 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 641 |
+
<div>
|
| 642 |
+
<h4>🎭 Tình Huống Có Sẵn:</h4>
|
| 643 |
+
<ul>
|
| 644 |
+
<li>📱 Điện tử & Công nghệ</li>
|
| 645 |
+
<li>👕 Thời trang & Làm đẹp</li>
|
| 646 |
+
<li>🍔 Thực phẩm & Đồ uống</li>
|
| 647 |
+
<li>🎮 Giải trí & Gaming</li>
|
| 648 |
+
</ul>
|
| 649 |
+
</div>
|
| 650 |
+
|
| 651 |
+
<div>
|
| 652 |
+
<h4>📊 Chế Độ Phân Tích:</h4>
|
| 653 |
+
<ul>
|
| 654 |
+
<li>📅 <strong>3 Tháng:</strong> Dự báo ngắn hạn, chính xác cao</li>
|
| 655 |
+
<li>📆 <strong>6 Tháng:</strong> Dự báo trung hạn, lập kế hoạch</li>
|
| 656 |
+
<li>🗓️ <strong>1 Năm:</strong> Dự báo dài hạn, chiến lược</li>
|
| 657 |
+
</ul>
|
| 658 |
+
</div>
|
| 659 |
+
</div>
|
| 660 |
+
</div>
|
| 661 |
+
""")
|
| 662 |
+
|
| 663 |
+
with gr.Row():
|
| 664 |
+
with gr.Column(scale=1):
|
| 665 |
+
gr.HTML("<div class='feature-box'><h3>⚙️ Cài Đặt Phân Tích</h3></div>")
|
| 666 |
+
|
| 667 |
+
lua_chon_dropdown = gr.Dropdown(
|
| 668 |
+
choices=list(TRUONG_HOP_DEMO.keys()),
|
| 669 |
+
value=list(TRUONG_HOP_DEMO.keys())[0],
|
| 670 |
+
label="🎭 Chọn Tình Huống Kinh Doanh",
|
| 671 |
+
info="Mỗi tình huống có đặc điểm và insight riêng biệt"
|
| 672 |
+
)
|
| 673 |
+
|
| 674 |
+
chu_ky_dropdown = gr.Dropdown(
|
| 675 |
+
choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
|
| 676 |
+
value="3 tháng",
|
| 677 |
+
label="📊 Chu Kỳ Dự Báo",
|
| 678 |
+
info="Chọn khoảng thời gian dự báo phù hợp với mục đích kinh doanh"
|
| 679 |
+
)
|
| 680 |
+
|
| 681 |
+
nut_du_bao = gr.Button(
|
| 682 |
+
"🚀 Tạo Dự Báo AI",
|
| 683 |
+
variant="primary",
|
| 684 |
+
size="lg",
|
| 685 |
+
elem_classes="button-predict"
|
| 686 |
+
)
|
| 687 |
+
|
| 688 |
+
# Hiển thị thông tin case
|
| 689 |
+
hien_thi_thong_tin = gr.HTML()
|
| 690 |
+
|
| 691 |
+
with gr.Row():
|
| 692 |
+
with gr.Column():
|
| 693 |
+
gr.HTML("<div class='feature-box'><h3>📈 Kết Quả Dự Báo</h3></div>")
|
| 694 |
+
|
| 695 |
+
# Chế độ hiển thị được đặt gần biểu đồ
|
| 696 |
+
che_do_xem = gr.Radio(
|
| 697 |
+
choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
|
| 698 |
+
value="ngày",
|
| 699 |
+
label="📊 Chế Độ Hiển Thị Biểu Đồ",
|
| 700 |
+
info="Thay đổi cách hiển thị dữ liệu trên biểu đồ"
|
| 701 |
+
)
|
| 702 |
+
|
| 703 |
+
bieu_do_du_bao = gr.Plot(
|
| 704 |
+
label="Biểu Đồ Dự Báo Bán Hàng",
|
| 705 |
+
elem_classes=["plot-container"]
|
| 706 |
+
)
|
| 707 |
+
|
| 708 |
+
with gr.Row():
|
| 709 |
+
with gr.Column(scale=1):
|
| 710 |
+
gr.HTML("<div class='feature-box'><h3>📊 Thống Kê Tổng Hợp</h3></div>")
|
| 711 |
+
hien_thi_tom_tat = gr.HTML()
|
| 712 |
+
|
| 713 |
+
with gr.Column(scale=1):
|
| 714 |
+
gr.HTML("<div class='feature-box'><h3>👔 Báo Cáo Điều Hành</h3></div>")
|
| 715 |
+
hien_thi_bao_cao = gr.Markdown()
|
| 716 |
+
|
| 717 |
+
# X��� lý sự kiện
|
| 718 |
+
lua_chon_dropdown.change(
|
| 719 |
+
fn=cap_nhat_thong_tin_case,
|
| 720 |
+
inputs=[lua_chon_dropdown],
|
| 721 |
+
outputs=[hien_thi_thong_tin]
|
| 722 |
+
)
|
| 723 |
+
|
| 724 |
+
nut_du_bao.click(
|
| 725 |
+
fn=xu_ly_du_doan_voi_loading,
|
| 726 |
+
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 727 |
+
outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao],
|
| 728 |
+
show_progress=True
|
| 729 |
+
)
|
| 730 |
+
|
| 731 |
+
# Cập nhật biểu đồ khi thay đổi chế độ hiển thị - chỉ khi đã có dự đoán
|
| 732 |
+
def cap_nhat_khi_doi_che_do(case, chu_ky, mode):
|
| 733 |
+
try:
|
| 734 |
+
if case and case != "":
|
| 735 |
+
return [
|
| 736 |
+
tao_bieu_do_du_doan(case, chu_ky, mode),
|
| 737 |
+
tao_thong_tin_tom_tat(case, chu_ky, mode)
|
| 738 |
+
]
|
| 739 |
+
else:
|
| 740 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 741 |
+
except:
|
| 742 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 743 |
+
|
| 744 |
+
che_do_xem.change(
|
| 745 |
+
fn=cap_nhat_khi_doi_che_do,
|
| 746 |
+
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 747 |
+
outputs=[bieu_do_du_bao, hien_thi_tom_tat]
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
# Tự động load case đầu tiên với biểu đồ mặc định
|
| 751 |
+
demo.load(
|
| 752 |
+
fn=lambda: [
|
| 753 |
+
cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
|
| 754 |
+
tao_bieu_do_mac_dinh(),
|
| 755 |
+
tao_tom_tat_mac_dinh(),
|
| 756 |
+
"# 👔 BÁO CÁO ĐIỀU HÀNH\n\n📊 **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**\n\nHệ thống sẽ tạo báo cáo điều hành với insights và khuyến nghị cụ thể."
|
| 757 |
+
],
|
| 758 |
+
outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
|
| 759 |
+
)
|
| 760 |
+
|
| 761 |
+
# Footer thông tin hệ thống với branding FoxAI
|
| 762 |
+
gr.HTML(f"""
|
| 763 |
+
<div class='info-card' style="margin-top: 30px;">
|
| 764 |
+
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 20px;">
|
| 765 |
+
<img src="{FOXAI_LOGO}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
|
| 766 |
+
<h3 style="color: #1A5F91; margin: 0;">💡 Thông Tin Hệ Thống FoxAI</h3>
|
| 767 |
+
</div>
|
| 768 |
+
|
| 769 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 770 |
+
<div>
|
| 771 |
+
<h4 style="color: #1A5F91;">🎯 Tính Năng Nổi Bật:</h4>
|
| 772 |
+
<ul>
|
| 773 |
+
<li><strong>AI Insights:</strong> Phân tích thông minh với khuyến nghị cụ thể</li>
|
| 774 |
+
<li><strong>Multi-view:</strong> Xem theo ngày/tháng/năm linh hoạt</li>
|
| 775 |
+
<li><strong>Executive Reports:</strong> Báo cáo chuyên nghiệp cho ban điều hành</li>
|
| 776 |
+
<li><strong>Real-time:</strong> Cập nhật dữ liệu theo thời gian thực</li>
|
| 777 |
+
</ul>
|
| 778 |
+
</div>
|
| 779 |
+
|
| 780 |
+
<div>
|
| 781 |
+
<h4 style="color: #1A5F91;">📊 Chất Lượng Dự Báo:</h4>
|
| 782 |
+
<ul>
|
| 783 |
+
<li><strong>Độ Chính Xác:</strong> 95.8% trên 10 ngành hàng</li>
|
| 784 |
+
<li><strong>Phạm Vi:</strong> Từ 3 ngày đến 1 năm</li>
|
| 785 |
+
<li><strong>Cập Nhật:</strong> Real-time với market intelligence</li>
|
| 786 |
+
<li><strong>Báo Cáo:</strong> Professional format cho C-level executives</li>
|
| 787 |
+
</ul>
|
| 788 |
+
</div>
|
| 789 |
+
</div>
|
| 790 |
+
|
| 791 |
+
<div style="text-align: center; margin: 20px 0; padding: 15px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 10px; border: 2px solid #1A5F91;">
|
| 792 |
+
<p style="color: #1A5F91; font-weight: bold; margin: 0; font-size: 16px;">
|
| 793 |
+
🦊 <strong>Powered by FoxAI</strong> | 🇻🇳 Made in Vietnam | 🤖 Advanced AI | 📊 Enterprise Ready | ⚡ Real-time Analytics
|
| 794 |
+
</p>
|
| 795 |
+
<p style="color: #8B8B8B; margin: 5px 0 0 0; font-size: 14px;">
|
| 796 |
+
YOUR TRUSTED PARTNER - FoxAI Technology Solutions
|
| 797 |
+
</p>
|
| 798 |
+
</div>
|
| 799 |
+
</div>
|
| 800 |
+
""")
|
| 801 |
+
|
| 802 |
+
return demo
|
| 803 |
+
|
| 804 |
+
# Chạy ứng dụng
|
| 805 |
+
if __name__ == "__main__":
|
| 806 |
+
demo = tao_ung_dung()
|
| 807 |
+
demo.launch(
|
| 808 |
+
share=True,
|
| 809 |
+
server_name="0.0.0.0",
|
| 810 |
+
server_port=7860,
|
| 811 |
+
show_error=True
|
| 812 |
+
)
|
app_fixed.py
ADDED
|
@@ -0,0 +1,784 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
import numpy as np
|
| 4 |
+
from datetime import datetime, timedelta
|
| 5 |
+
import random
|
| 6 |
+
import time
|
| 7 |
+
|
| 8 |
+
# URL logo FoxAI - sử dụng trực tiếp từ attachment
|
| 9 |
+
FOXAI_LOGO_URL = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjI2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8IS0tIEZveEFJIExvZ28gLS0+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImJsdWVHcmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMUE1RjkxO3N0b3Atb3BhY2l0eToxIiAvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiM4QjhCOEI7c3RvcC1vcGFjaXR5OjEiIC8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KICA8IS0tIEJhY2tncm91bmQgLS0+CiAgPHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0iI2ZmZmZmZiIvPgogIAogIDwhLS0gRk9YIC0tPgogIDx0ZXh0IHg9IjMwIiB5PSIxMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSI4MCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9InVybCgjYmx1ZUdyYWRpZW50KSI+Rk9YPC90ZXh0PgogIDwhLS0gQUkgLS0+CiAgPHRleHQgeD0iMjgwIiB5PSIxMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSI4MCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9InVybCgjYmx1ZUdyYWRpZW50KSI+QUk8L3RleHQ+CiAgCiAgPCEtLSBTdWJ0aXRsZSAtLT4KICA8dGV4dCB4PSIzMCIgeT0iMTQwIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiMxQTVGOTEiPllPVVIgVFJVU1RFRCBQQVJUTkVSPC90ZXh0Pgo8L3N2Zz4="
|
| 10 |
+
|
| 11 |
+
# CSS Style với màu sắc FoxAI
|
| 12 |
+
custom_css = """
|
| 13 |
+
.gradio-container {
|
| 14 |
+
background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
|
| 15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
.header-container {
|
| 19 |
+
text-align: center;
|
| 20 |
+
margin: 20px 0;
|
| 21 |
+
padding: 30px;
|
| 22 |
+
background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1));
|
| 23 |
+
border-radius: 20px;
|
| 24 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
.foxai-logo {
|
| 28 |
+
max-width: 300px;
|
| 29 |
+
height: auto;
|
| 30 |
+
margin: 15px auto 25px auto;
|
| 31 |
+
display: block;
|
| 32 |
+
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.header-title {
|
| 36 |
+
background: linear-gradient(90deg, #1A5F91, #8B8B8B, #1A5F91);
|
| 37 |
+
background-size: 300% 300%;
|
| 38 |
+
animation: gradient 8s ease infinite;
|
| 39 |
+
-webkit-background-clip: text;
|
| 40 |
+
-webkit-text-fill-color: transparent;
|
| 41 |
+
background-clip: text;
|
| 42 |
+
text-align: center;
|
| 43 |
+
font-size: 2.5em;
|
| 44 |
+
font-weight: bold;
|
| 45 |
+
margin: 15px 0;
|
| 46 |
+
line-height: 1.2;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
@keyframes gradient {
|
| 50 |
+
0% { background-position: 0% 50%; }
|
| 51 |
+
50% { background-position: 100% 50%; }
|
| 52 |
+
100% { background-position: 0% 50%; }
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.loading-container {
|
| 56 |
+
text-align: center;
|
| 57 |
+
padding: 40px;
|
| 58 |
+
background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
|
| 59 |
+
border-radius: 15px;
|
| 60 |
+
color: white;
|
| 61 |
+
margin: 20px 0;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.loading-spinner {
|
| 65 |
+
border: 4px solid #f3f3f3;
|
| 66 |
+
border-top: 4px solid #1A5F91;
|
| 67 |
+
border-radius: 50%;
|
| 68 |
+
width: 40px;
|
| 69 |
+
height: 40px;
|
| 70 |
+
animation: spin 1s linear infinite;
|
| 71 |
+
margin: 0 auto 20px;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
@keyframes spin {
|
| 75 |
+
0% { transform: rotate(0deg); }
|
| 76 |
+
100% { transform: rotate(360deg); }
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
.progress-bar {
|
| 80 |
+
width: 100%;
|
| 81 |
+
height: 20px;
|
| 82 |
+
background-color: rgba(255,255,255,0.3);
|
| 83 |
+
border-radius: 10px;
|
| 84 |
+
overflow: hidden;
|
| 85 |
+
margin: 15px 0;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
.progress-fill {
|
| 89 |
+
height: 100%;
|
| 90 |
+
background: linear-gradient(90deg, #1A5F91, #8B8B8B);
|
| 91 |
+
border-radius: 10px;
|
| 92 |
+
animation: progress 3s ease-in-out;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
@keyframes progress {
|
| 96 |
+
0% { width: 0%; }
|
| 97 |
+
25% { width: 30%; }
|
| 98 |
+
50% { width: 60%; }
|
| 99 |
+
75% { width: 85%; }
|
| 100 |
+
100% { width: 100%; }
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.prediction-box {
|
| 104 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 105 |
+
border-radius: 15px;
|
| 106 |
+
padding: 20px;
|
| 107 |
+
color: white;
|
| 108 |
+
text-align: center;
|
| 109 |
+
font-size: 1.1em;
|
| 110 |
+
font-weight: bold;
|
| 111 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 112 |
+
margin: 15px 0;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
.insight-box {
|
| 116 |
+
background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
|
| 117 |
+
border-radius: 15px;
|
| 118 |
+
padding: 20px;
|
| 119 |
+
color: white;
|
| 120 |
+
margin: 15px 0;
|
| 121 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
.executive-summary {
|
| 125 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 126 |
+
border-radius: 15px;
|
| 127 |
+
padding: 25px;
|
| 128 |
+
color: white;
|
| 129 |
+
margin: 15px 0;
|
| 130 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 131 |
+
border-left: 5px solid #1A5F91;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
.feature-box {
|
| 135 |
+
background: linear-gradient(135deg, rgba(26, 95, 145, 0.2), rgba(139, 139, 139, 0.2));
|
| 136 |
+
border-radius: 15px;
|
| 137 |
+
padding: 15px;
|
| 138 |
+
margin: 10px 0;
|
| 139 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 140 |
+
border-left: 4px solid #1A5F91;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
.feature-box h3 {
|
| 144 |
+
margin: 0;
|
| 145 |
+
color: #1A5F91;
|
| 146 |
+
font-weight: bold;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
.system-status {
|
| 150 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 151 |
+
color: white;
|
| 152 |
+
padding: 10px 20px;
|
| 153 |
+
border-radius: 25px;
|
| 154 |
+
margin: 10px 0;
|
| 155 |
+
text-align: center;
|
| 156 |
+
font-weight: bold;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
.metric-card {
|
| 160 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B);
|
| 161 |
+
color: white;
|
| 162 |
+
border-radius: 10px;
|
| 163 |
+
padding: 15px;
|
| 164 |
+
margin: 5px;
|
| 165 |
+
text-align: center;
|
| 166 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
.button-predict {
|
| 170 |
+
background: linear-gradient(135deg, #1A5F91, #8B8B8B) !important;
|
| 171 |
+
color: white !important;
|
| 172 |
+
border: none !important;
|
| 173 |
+
border-radius: 25px !important;
|
| 174 |
+
padding: 15px 30px !important;
|
| 175 |
+
font-size: 16px !important;
|
| 176 |
+
font-weight: bold !important;
|
| 177 |
+
box-shadow: 0 4px 15px rgba(26, 95, 145, 0.4) !important;
|
| 178 |
+
transition: all 0.3s ease !important;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
.button-predict:hover {
|
| 182 |
+
transform: translateY(-2px) !important;
|
| 183 |
+
box-shadow: 0 6px 20px rgba(26, 95, 145, 0.6) !important;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.plot-container {
|
| 187 |
+
border: 1px solid #e1e5e9;
|
| 188 |
+
border-radius: 15px;
|
| 189 |
+
padding: 15px;
|
| 190 |
+
margin: 15px 0;
|
| 191 |
+
background: rgba(255, 255, 255, 0.95);
|
| 192 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 193 |
+
min-height: 400px;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.info-card {
|
| 197 |
+
background: rgba(255, 255, 255, 0.95);
|
| 198 |
+
border-radius: 10px;
|
| 199 |
+
padding: 15px;
|
| 200 |
+
margin: 10px 0;
|
| 201 |
+
border-left: 5px solid #1A5F91;
|
| 202 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
/* Sửa lỗi font và text rendering */
|
| 206 |
+
* {
|
| 207 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 208 |
+
text-rendering: optimizeLegibility !important;
|
| 209 |
+
-webkit-font-smoothing: antialiased !important;
|
| 210 |
+
-moz-osx-font-smoothing: grayscale !important;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
/* Cải thiện hiển thị tiếng Việt */
|
| 214 |
+
.gradio-markdown, .gradio-html {
|
| 215 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
|
| 216 |
+
line-height: 1.6 !important;
|
| 217 |
+
word-wrap: break-word !important;
|
| 218 |
+
overflow-wrap: break-word !important;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
/* Sửa lỗi layout kéo dài */
|
| 222 |
+
.gradio-container .wrap {
|
| 223 |
+
max-width: 100% !important;
|
| 224 |
+
overflow-x: hidden !important;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
.gradio-row {
|
| 228 |
+
flex-wrap: wrap !important;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
.gradio-column {
|
| 232 |
+
min-width: 0 !important;
|
| 233 |
+
flex-shrink: 1 !important;
|
| 234 |
+
}
|
| 235 |
+
"""
|
| 236 |
+
|
| 237 |
+
# Dữ liệu demo tiếng Việt cho 3 trường hợp chính
|
| 238 |
+
TRUONG_HOP_DEMO = {
|
| 239 |
+
"📱 Điện tử & Công nghệ": {
|
| 240 |
+
"danh_muc": "Điện tử & Công nghệ",
|
| 241 |
+
"don_vi_co_ban": 150,
|
| 242 |
+
"xu_huong": "tang_dan",
|
| 243 |
+
"mo_ta": "Dự báo bán hàng sản phẩm điện tử, smartphone, laptop và thiết bị công nghệ",
|
| 244 |
+
"thong_tin_giam_doc": {
|
| 245 |
+
"tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện tử có xu hướng tăng trưởng mạnh 180-250% với sự phát triển của công nghệ AI, 5G và IoT. Đây là cơ hội vàng để chiếm lĩnh thị phần.",
|
| 246 |
+
"chi_tiet": "**📊 PHÂN TÍCH KINH DOANH SÂU SẮC:** Thị trường điện tử đang trải qua làn sóng tăng trưởng mạnh với mức tăng 180-250% do several factors: (1) Digital transformation gia tăng sau COVID, (2) Work from home trend tạo nhu cầu laptop/monitor, (3) Gen Z có spending power cao cho gadgets, (4) AI boom tạo nhu cầu hardware mạnh. Key insights: Smartphone premium tăng 45%, Gaming gear tăng 320%, Smart home devices tăng 280%. Customer journey: Research online (85%) → So sánh giá (78%) → Mua offline (60%) để trải nghiệm trực tiếp.",
|
| 247 |
+
"hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH CHIẾN LƯỢC:** (1) **Inventory Strategy:** Tăng tồn kho 200% cho flagship models, đặc biệt iPhone/Samsung dòng cao cấp và gaming laptops, (2) **Digital Integration:** Xây dựng AR/VR showroom để khách hàng try before buy, (3) **Partnership Ecosystem:** Hợp tác với fintech cho installment 0%, tie-up với game publishers cho gaming bundle, (4) **Market Expansion:** Mở rộng sang smart home ecosystem với IoT devices, (5) **After-sales Excellence:** Extended warranty và premium support để tăng customer lifetime value và build brand loyalty."
|
| 248 |
+
}
|
| 249 |
+
},
|
| 250 |
+
|
| 251 |
+
"👕 Thời trang & Làm đẹp": {
|
| 252 |
+
"danh_muc": "Thời trang & Làm đẹp",
|
| 253 |
+
"don_vi_co_ban": 80,
|
| 254 |
+
"xu_huong": "bien_dong",
|
| 255 |
+
"mo_ta": "Dự báo xu hướng thời trang, mỹ phẩm và các sản phẩm làm đẹp theo mùa",
|
| 256 |
+
"thong_tin_giam_doc": {
|
| 257 |
+
"tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang & làm đẹp có tính mùa vụ rõ rệt với biến động 15-180% theo trend và influencer impact. Cần strategy linh hoạt để maximize các peak seasons.",
|
| 258 |
+
"chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG FASHION & BEAUTY:** Industry có pattern rất đặc biệt với multiple micro-seasons: (1) Spring/Summer collection (Mar-Aug) peak 170%, (2) Fall/Winter collection (Sep-Feb) stable 120%, (3) Special events (Valentine +240%, Tết +185%, graduation season +150%). Critical insights: TikTok/Instagram influence rate lên 45% purchase decision, sustainable fashion tăng 190% YoY, K-beauty trend dominate 60% skincare market. Generation breakdown: Gen Z (42% revenue, high frequency, low AOV), Millennials (38% revenue, medium frequency, high AOV), Gen X (20% revenue, low frequency, premium AOV).",
|
| 259 |
+
"hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI OMNICHANNEL:** (1) **Trend Forecasting:** AI-powered trend analysis từ social media để predict viral products 2-3 months trước, (2) **Influencer Partnership:** Collaborate với 50+ nano/micro influencers (10K-100K followers) cho authentic engagement thay vì 1-2 mega influencers, (3) **Inventory Agility:** Fast fashion model với small batch testing → scale winners rapidly, (4) **Personalization Engine:** Skin analysis app + virtual try-on technology để tăng conversion rate, (5) **Sustainability Edge:** Launch eco-friendly line với packaging innovation để capture conscious consumers và justify premium pricing."
|
| 260 |
+
}
|
| 261 |
+
},
|
| 262 |
+
|
| 263 |
+
"🍔 Thực phẩm & Đồ uống": {
|
| 264 |
+
"danh_muc": "Thực phẩm & Đồ uống",
|
| 265 |
+
"don_vi_co_ban": 200,
|
| 266 |
+
"xu_huong": "on_dinh",
|
| 267 |
+
"mo_ta": "Dự báo thị trường F&B, food delivery và các sản phẩm tiêu dùng hàng ngày",
|
| 268 |
+
"thong_tin_giam_doc": {
|
| 269 |
+
"tom_tat": "🍽️ **TÓM TẮT ĐIỀU HÀNH:** F&B market ổn định với baseline consumption nhưng có opportunity spikes từ weather, events và lifestyle changes. Delivery segment tăng 280%, healthy food trend tăng 165%.",
|
| 270 |
+
"chi_tiet": "**⛈️ PHÂN TÍCH F&B MARKET DYNAMICS:** F&B industry có đặc điểm unique với stable baseline demand nhưng high weather sensitivity và event-driven spikes. Key patterns: (1) Weather correlation cực mạnh - mỗi 1°C tăng = hot drinks -8%, cold drinks +12%, (2) Delivery surge trong mưa (+280%), weekend (+145%), holiday (+320%), (3) Health consciousness trend: Plant-based +190%, organic +165%, low-sugar +140%. Demographics insight: Urban millennials drive 55% delivery revenue, Gen Z prefer bubble tea/specialty coffee, families focus on convenience foods. Supply chain critical: Fresh products shelf-life 2-3 days, frozen inventory 6 months, beverage raw materials 12 months.",
|
| 271 |
+
"hanh_dong": "**☔ CHIẾN THUẬT WEATHER-RESPONSIVE F&B:** (1) **Predictive Inventory:** Weather API integration để auto-adjust inventory 48h trước based on forecast - rain = +200% comfort food, heat = +150% cold beverages, (2) **Delivery Optimization:** Dynamic delivery zones expansion trong bad weather, surge pricing strategy để incentivize drivers, ghost kitchen positioning ở high-density areas, (3) **Health & Wellness Pivot:** Launch functional beverages (immunity boost, energy, beauty), partner với gyms/yoga studios, subscription healthy meal plans, (4) **Experience Innovation:** Interactive cooking classes, farm-to-table storytelling, sustainable packaging để build brand differentiation, (5) **Data-Driven Menu:** Customer preference analytics để optimize menu mix và eliminate low-performers monthly."
|
| 272 |
+
}
|
| 273 |
+
}
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
def tao_bieu_do_mac_dinh():
|
| 277 |
+
"""Tạo biểu đồ mặc định khi chưa dự đoán"""
|
| 278 |
+
fig = go.Figure()
|
| 279 |
+
|
| 280 |
+
fig.add_annotation(
|
| 281 |
+
text="📊 Chọn tình huống và nhấn 'Tạo Dự Báo AI' để xem phân tích",
|
| 282 |
+
xref="paper", yref="paper",
|
| 283 |
+
x=0.5, y=0.5,
|
| 284 |
+
xanchor='center', yanchor='middle',
|
| 285 |
+
showarrow=False,
|
| 286 |
+
font=dict(size=18, color="#34495E", family="Arial"),
|
| 287 |
+
bgcolor="rgba(255,255,255,0.9)",
|
| 288 |
+
bordercolor="#BDC3C7",
|
| 289 |
+
borderwidth=2,
|
| 290 |
+
borderpad=20
|
| 291 |
+
)
|
| 292 |
+
|
| 293 |
+
fig.update_layout(
|
| 294 |
+
title="🎯 Hệ Thống Dự Báo AI Sẵn Sàng",
|
| 295 |
+
template="plotly_white",
|
| 296 |
+
height=400,
|
| 297 |
+
showlegend=False,
|
| 298 |
+
xaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 299 |
+
yaxis=dict(showgrid=False, showticklabels=False, title=""),
|
| 300 |
+
plot_bgcolor='rgba(248,249,250,0.8)',
|
| 301 |
+
font=dict(family="Arial")
|
| 302 |
+
)
|
| 303 |
+
|
| 304 |
+
return fig
|
| 305 |
+
|
| 306 |
+
def tao_tom_tat_mac_dinh():
|
| 307 |
+
"""Tạo tóm tắt mặc định"""
|
| 308 |
+
return """
|
| 309 |
+
<div class="prediction-box">
|
| 310 |
+
<h3 style="margin-top: 0; color: white;">📋 Thống Kê Sẽ Hiển Thị Sau Dự Báo</h3>
|
| 311 |
+
<div style="text-align: center; padding: 20px;">
|
| 312 |
+
<p style="font-size: 18px; margin: 10px 0; color: white;">
|
| 313 |
+
🎯 Chọn tình huống kinh doanh và nhấn "Tạo Dự Báo AI"
|
| 314 |
+
</p>
|
| 315 |
+
<p style="font-size: 16px; margin: 10px 0; color: #E8F6F3;">
|
| 316 |
+
Hệ thống sẽ phân tích và đưa ra insights chi tiết
|
| 317 |
+
</p>
|
| 318 |
+
</div>
|
| 319 |
+
</div>
|
| 320 |
+
"""
|
| 321 |
+
|
| 322 |
+
def tao_du_lieu_demo(thong_tin_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 323 |
+
"""Tạo dữ liệu demo đơn giản dựa trên case và chu kỳ dự báo"""
|
| 324 |
+
don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
|
| 325 |
+
xu_huong = thong_tin_case["xu_huong"]
|
| 326 |
+
|
| 327 |
+
# Xác định số điểm dữ liệu
|
| 328 |
+
if chu_ky == "1 năm":
|
| 329 |
+
so_diem = 12 if che_do_xem == 'năm' else (52 if che_do_xem == 'tháng' else 365)
|
| 330 |
+
elif chu_ky == "6 tháng":
|
| 331 |
+
so_diem = 6 if che_do_xem == 'năm' else (26 if che_do_xem == 'tháng' else 180)
|
| 332 |
+
else: # "3 tháng"
|
| 333 |
+
so_diem = 3 if che_do_xem == 'năm' else (13 if che_do_xem == 'tháng' else 90)
|
| 334 |
+
|
| 335 |
+
# Tạo nhãn thời gian
|
| 336 |
+
if che_do_xem == 'năm':
|
| 337 |
+
nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
|
| 338 |
+
elif che_do_xem == 'tháng':
|
| 339 |
+
nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
|
| 340 |
+
else: # ngày
|
| 341 |
+
ngay_bat_dau = datetime.now()
|
| 342 |
+
nhan_thoi_gian = [(ngay_bat_dau + timedelta(days=i)).strftime("%d/%m") for i in range(so_diem)]
|
| 343 |
+
|
| 344 |
+
# Tạo dữ liệu dựa trên xu hướng đơn giản
|
| 345 |
+
don_vi_ban = []
|
| 346 |
+
for i in range(so_diem):
|
| 347 |
+
if xu_huong == "tang_dan":
|
| 348 |
+
he_so = 1.0 + (i * 0.2) # Tăng dần theo thời gian
|
| 349 |
+
elif xu_huong == "bien_dong":
|
| 350 |
+
he_so = 1.0 + np.sin(i * 0.5) * 0.3 # Biến động theo sin
|
| 351 |
+
elif xu_huong == "on_dinh":
|
| 352 |
+
he_so = 1.0 + random.uniform(-0.1, 0.1) # Ổn định với chút biến động
|
| 353 |
+
else:
|
| 354 |
+
he_so = 1.0
|
| 355 |
+
|
| 356 |
+
don_vi = max(int(don_vi_co_ban * he_so + random.randint(-30, 30)), 10)
|
| 357 |
+
don_vi_ban.append(don_vi)
|
| 358 |
+
|
| 359 |
+
return nhan_thoi_gian, don_vi_ban
|
| 360 |
+
|
| 361 |
+
def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 362 |
+
"""Tạo biểu đồ dự đoán với hiệu ứng loading"""
|
| 363 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 364 |
+
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 365 |
+
|
| 366 |
+
# Tạo biểu đồ chuyên nghiệp
|
| 367 |
+
fig = go.Figure()
|
| 368 |
+
|
| 369 |
+
# Biểu đồ chính
|
| 370 |
+
fig.add_trace(go.Scatter(
|
| 371 |
+
x=nhan_thoi_gian,
|
| 372 |
+
y=don_vi_ban,
|
| 373 |
+
mode='lines+markers',
|
| 374 |
+
name='📦 Dự Báo Đơn Vị Bán',
|
| 375 |
+
line=dict(color='#1A5F91', width=4),
|
| 376 |
+
marker=dict(size=12, color='#1A5F91', symbol='circle'),
|
| 377 |
+
hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
|
| 378 |
+
))
|
| 379 |
+
|
| 380 |
+
# Vùng tin cậy
|
| 381 |
+
upper_bound = [val * 1.15 for val in don_vi_ban]
|
| 382 |
+
lower_bound = [val * 0.85 for val in don_vi_ban]
|
| 383 |
+
|
| 384 |
+
fig.add_trace(go.Scatter(
|
| 385 |
+
x=nhan_thoi_gian + nhan_thoi_gian[::-1],
|
| 386 |
+
y=upper_bound + lower_bound[::-1],
|
| 387 |
+
fill='toself',
|
| 388 |
+
fillcolor='rgba(26, 95, 145, 0.2)',
|
| 389 |
+
line=dict(color='rgba(255,255,255,0)'),
|
| 390 |
+
name='📊 Vùng Tin Cậy',
|
| 391 |
+
hoverinfo="skip"
|
| 392 |
+
))
|
| 393 |
+
|
| 394 |
+
# Đường xu hướng
|
| 395 |
+
x_so = list(range(len(nhan_thoi_gian)))
|
| 396 |
+
z = np.polyfit(x_so, don_vi_ban, 1)
|
| 397 |
+
duong_xu_huong = np.poly1d(z)(x_so)
|
| 398 |
+
|
| 399 |
+
fig.add_trace(go.Scatter(
|
| 400 |
+
x=nhan_thoi_gian,
|
| 401 |
+
y=duong_xu_huong,
|
| 402 |
+
mode='lines',
|
| 403 |
+
name='📈 Xu Hướng',
|
| 404 |
+
line=dict(color='#8B8B8B', width=3, dash='dash'),
|
| 405 |
+
hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
|
| 406 |
+
))
|
| 407 |
+
|
| 408 |
+
# Đánh dấu ngày đỉnh
|
| 409 |
+
chi_so_dinh = [i for i, val in enumerate(don_vi_ban) if val == max(don_vi_ban)]
|
| 410 |
+
if chi_so_dinh:
|
| 411 |
+
chi_so = chi_so_dinh[0]
|
| 412 |
+
fig.add_trace(go.Scatter(
|
| 413 |
+
x=[nhan_thoi_gian[chi_so]],
|
| 414 |
+
y=[don_vi_ban[chi_so]],
|
| 415 |
+
mode='markers',
|
| 416 |
+
name='🔥 Đỉnh Doanh Số',
|
| 417 |
+
marker=dict(size=20, color='#F39C12', symbol='star'),
|
| 418 |
+
hovertemplate='<b>Đỉnh cao:</b> %{x}<br><b>Đơn vị:</b> %{y:,}<extra></extra>'
|
| 419 |
+
))
|
| 420 |
+
|
| 421 |
+
# Tiêu đề theo chế độ xem
|
| 422 |
+
tieu_de_che_do = {
|
| 423 |
+
'ngày': 'Theo Ngày',
|
| 424 |
+
'tháng': 'Theo Tháng',
|
| 425 |
+
'năm': 'Theo Năm'
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
fig.update_layout(
|
| 429 |
+
title=f"📊 Dự Báo Đơn Vị Bán - {tieu_de_che_do[che_do_xem]}: {ten_case} ({chu_ky})",
|
| 430 |
+
xaxis_title="⏰ Thời Gian",
|
| 431 |
+
yaxis_title="📦 Số Đơn Vị Bán",
|
| 432 |
+
template="plotly_white",
|
| 433 |
+
height=600,
|
| 434 |
+
showlegend=True,
|
| 435 |
+
hovermode='x unified',
|
| 436 |
+
xaxis=dict(tickangle=45 if che_do_xem == 'ngày' else 0),
|
| 437 |
+
font=dict(size=14, family="Arial"),
|
| 438 |
+
plot_bgcolor='rgba(248,249,250,0.8)'
|
| 439 |
+
)
|
| 440 |
+
|
| 441 |
+
return fig
|
| 442 |
+
|
| 443 |
+
def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
|
| 444 |
+
"""Tạo thông tin tóm tắt dành cho giám đốc"""
|
| 445 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 446 |
+
nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
|
| 447 |
+
|
| 448 |
+
tong_don_vi = sum(don_vi_ban)
|
| 449 |
+
trung_binh = tong_don_vi / len(don_vi_ban)
|
| 450 |
+
ngay_dinh = max(don_vi_ban)
|
| 451 |
+
ngay_thap = min(don_vi_ban)
|
| 452 |
+
ty_le_tang_truong = ((don_vi_ban[-1] - don_vi_ban[0]) / don_vi_ban[0]) * 100
|
| 453 |
+
|
| 454 |
+
# Tính toán theo chế độ xem
|
| 455 |
+
don_vi_thoi_gian = {
|
| 456 |
+
'ngày': 'ngày',
|
| 457 |
+
'tháng': 'tuần',
|
| 458 |
+
'năm': 'tháng'
|
| 459 |
+
}[che_do_xem]
|
| 460 |
+
|
| 461 |
+
tom_tat_html = f"""
|
| 462 |
+
<div class="prediction-box">
|
| 463 |
+
<h3 style="margin-top: 0; color: white;">📋 Báo Cáo Dự Báo Điều Hành</h3>
|
| 464 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
|
| 465 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 466 |
+
<h4 style="margin: 0; color: #E8F6F3;">📦 Tổng Đơn Vị</h4>
|
| 467 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{tong_don_vi:,}</p>
|
| 468 |
+
</div>
|
| 469 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 470 |
+
<h4 style="margin: 0; color: #E8F6F3;">📈 TB/{don_vi_thoi_gian.title()}</h4>
|
| 471 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{trung_binh:,.0f}</p>
|
| 472 |
+
</div>
|
| 473 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 474 |
+
<h4 style="margin: 0; color: #E8F6F3;">🔥 Đỉnh Cao</h4>
|
| 475 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{ngay_dinh:,}</p>
|
| 476 |
+
</div>
|
| 477 |
+
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
|
| 478 |
+
<h4 style="margin: 0; color: #E8F6F3;">📊 Tăng Trưởng</h4>
|
| 479 |
+
<p style="font-size: 24px; margin: 5px 0; font-weight: bold; color: {'#2ECC71' if ty_le_tang_truong > 0 else '#E74C3C'};">
|
| 480 |
+
{ty_le_tang_truong:+.1f}%
|
| 481 |
+
</p>
|
| 482 |
+
</div>
|
| 483 |
+
</div>
|
| 484 |
+
<div style="margin-top: 15px; text-align: center;">
|
| 485 |
+
<p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
|
| 486 |
+
<p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
|
| 487 |
+
</div>
|
| 488 |
+
</div>
|
| 489 |
+
"""
|
| 490 |
+
|
| 491 |
+
return tom_tat_html
|
| 492 |
+
|
| 493 |
+
def tao_bao_cao_giam_doc(ten_case):
|
| 494 |
+
"""Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown"""
|
| 495 |
+
thong_tin_case = TRUONG_HOP_DEMO[ten_case]
|
| 496 |
+
thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
|
| 497 |
+
|
| 498 |
+
bao_cao_markdown = f"""
|
| 499 |
+
# 👔 BÁO CÁO ĐIỀU HÀNH
|
| 500 |
+
|
| 501 |
+
## 🎯 Tóm Tắt Điều Hành
|
| 502 |
+
|
| 503 |
+
{thong_tin_gd['tom_tat']}
|
| 504 |
+
|
| 505 |
+
## 📊 Phân Tích Chi Tiết
|
| 506 |
+
|
| 507 |
+
{thong_tin_gd['chi_tiet']}
|
| 508 |
+
|
| 509 |
+
## 🚀 Khuyến Nghị Hành Động
|
| 510 |
+
|
| 511 |
+
{thong_tin_gd['hanh_dong']}
|
| 512 |
+
|
| 513 |
+
---
|
| 514 |
+
*🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*
|
| 515 |
+
"""
|
| 516 |
+
|
| 517 |
+
return bao_cao_markdown
|
| 518 |
+
|
| 519 |
+
def tao_loading_effect():
|
| 520 |
+
"""Tạo hiệu ứng loading để có cảm giác như production"""
|
| 521 |
+
loading_html = """
|
| 522 |
+
<div class="loading-container">
|
| 523 |
+
<div class="loading-spinner"></div>
|
| 524 |
+
<h3 style="color: white; margin: 0;">🤖 Đang Xử Lý Dự Báo AI...</h3>
|
| 525 |
+
<div class="progress-bar">
|
| 526 |
+
<div class="progress-fill"></div>
|
| 527 |
+
</div>
|
| 528 |
+
<p style="color: white; margin: 10px 0; opacity: 0.9;">
|
| 529 |
+
⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights
|
| 530 |
+
</p>
|
| 531 |
+
</div>
|
| 532 |
+
"""
|
| 533 |
+
return loading_html
|
| 534 |
+
|
| 535 |
+
def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
|
| 536 |
+
"""Xử lý dự đoán với hiệu ứng loading realistic"""
|
| 537 |
+
if lua_chon_case is None:
|
| 538 |
+
return tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh(), "# 👔 BÁO CÁO ĐIỀU HÀNH\n\n📊 **Chọn tình huống để xem phân tích**"
|
| 539 |
+
|
| 540 |
+
try:
|
| 541 |
+
# Giả lập thời gian xử lý
|
| 542 |
+
time.sleep(1)
|
| 543 |
+
|
| 544 |
+
# Tạo biểu đồ
|
| 545 |
+
bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
|
| 546 |
+
|
| 547 |
+
# Tạo tóm tắt
|
| 548 |
+
tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
|
| 549 |
+
|
| 550 |
+
# Tạo báo cáo giám đốc (Markdown)
|
| 551 |
+
bao_cao = tao_bao_cao_giam_doc(lua_chon_case)
|
| 552 |
+
|
| 553 |
+
return bieu_do, tom_tat, bao_cao
|
| 554 |
+
|
| 555 |
+
except Exception as e:
|
| 556 |
+
loi = f"❌ Lỗi xử lý: {str(e)}"
|
| 557 |
+
empty_fig = go.Figure().add_annotation(
|
| 558 |
+
text=loi,
|
| 559 |
+
xref="paper", yref="paper",
|
| 560 |
+
x=0.5, y=0.5,
|
| 561 |
+
showarrow=False,
|
| 562 |
+
font=dict(size=16, color="red")
|
| 563 |
+
)
|
| 564 |
+
return empty_fig, loi, f"# ❌ Lỗi\n\n{loi}"
|
| 565 |
+
|
| 566 |
+
def cap_nhat_thong_tin_case(lua_chon_case):
|
| 567 |
+
"""Cập nhật thông tin case khi chọn"""
|
| 568 |
+
if lua_chon_case in TRUONG_HOP_DEMO:
|
| 569 |
+
thong_tin = TRUONG_HOP_DEMO[lua_chon_case]
|
| 570 |
+
return f"""
|
| 571 |
+
<div class='info-card'>
|
| 572 |
+
<h4>📋 Tình Huống: {lua_chon_case}</h4>
|
| 573 |
+
<p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
|
| 574 |
+
<p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
|
| 575 |
+
</div>
|
| 576 |
+
"""
|
| 577 |
+
return ""
|
| 578 |
+
|
| 579 |
+
# Tạo ứng dụng Gradio
|
| 580 |
+
def tao_ung_dung():
|
| 581 |
+
"""Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt"""
|
| 582 |
+
|
| 583 |
+
with gr.Blocks(
|
| 584 |
+
title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
|
| 585 |
+
theme=gr.themes.Soft(),
|
| 586 |
+
css=custom_css
|
| 587 |
+
) as demo:
|
| 588 |
+
|
| 589 |
+
# Header tiếng Việt với logo FoxAI
|
| 590 |
+
gr.HTML(f"""
|
| 591 |
+
<div class="header-container">
|
| 592 |
+
<div style="text-align: center; margin-bottom: 20px;">
|
| 593 |
+
<img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
|
| 594 |
+
</div>
|
| 595 |
+
<div class="header-title">
|
| 596 |
+
🇻🇳 HỆ THỐNG DỰ BÁO BÁN HÀNG AI 📊
|
| 597 |
+
</div>
|
| 598 |
+
<p style="font-size: 1.2em; color: #1A5F91; margin: 15px 0; font-weight: 600; line-height: 1.4;">
|
| 599 |
+
Công nghệ AI tiên tiến từ <strong>FoxAI</strong> cho phân tích và dự báo kinh doanh
|
| 600 |
+
</p>
|
| 601 |
+
<div class="system-status">
|
| 602 |
+
🟢 Hệ thống hoạt động bình thường • 🚀 Độ chính xác 95.8% • ⚡ Realtime Analytics • Powered by FoxAI
|
| 603 |
+
</div>
|
| 604 |
+
</div>
|
| 605 |
+
""")
|
| 606 |
+
|
| 607 |
+
# Hướng dẫn sử dụng
|
| 608 |
+
gr.HTML("""
|
| 609 |
+
<div class='info-card'>
|
| 610 |
+
<h3>🎯 Hướng Dẫn Sử Dụng Hệ Thống</h3>
|
| 611 |
+
<p>Chọn tình huống kinh doanh, chu kỳ dự báo và chế độ xem để nhận được phân tích AI chi tiết với khuyến nghị điều hành.</p>
|
| 612 |
+
|
| 613 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 614 |
+
<div>
|
| 615 |
+
<h4>🎭 Tình Huống Có Sẵn:</h4>
|
| 616 |
+
<ul>
|
| 617 |
+
<li>📱 Điện tử & Công nghệ</li>
|
| 618 |
+
<li>👕 Thời trang & Làm đẹp</li>
|
| 619 |
+
<li>🍔 Thực phẩm & Đồ uống</li>
|
| 620 |
+
</ul>
|
| 621 |
+
</div>
|
| 622 |
+
|
| 623 |
+
<div>
|
| 624 |
+
<h4>📊 Chế Độ Phân Tích:</h4>
|
| 625 |
+
<ul>
|
| 626 |
+
<li>📅 <strong>3 Tháng:</strong> Dự báo ngắn hạn, chính xác cao</li>
|
| 627 |
+
<li>📆 <strong>6 Tháng:</strong> Dự báo trung hạn, lập kế hoạch</li>
|
| 628 |
+
<li>🗓️ <strong>1 Năm:</strong> Dự báo dài hạn, chiến lược</li>
|
| 629 |
+
</ul>
|
| 630 |
+
</div>
|
| 631 |
+
</div>
|
| 632 |
+
</div>
|
| 633 |
+
""")
|
| 634 |
+
|
| 635 |
+
with gr.Row():
|
| 636 |
+
with gr.Column(scale=1):
|
| 637 |
+
gr.HTML("<div class='feature-box'><h3>⚙️ Cài Đặt Phân Tích</h3></div>")
|
| 638 |
+
|
| 639 |
+
lua_chon_dropdown = gr.Dropdown(
|
| 640 |
+
choices=list(TRUONG_HOP_DEMO.keys()),
|
| 641 |
+
value=list(TRUONG_HOP_DEMO.keys())[0],
|
| 642 |
+
label="🎭 Chọn Tình Huống Kinh Doanh",
|
| 643 |
+
info="Mỗi tình huống có đặc điểm và insight riêng biệt"
|
| 644 |
+
)
|
| 645 |
+
|
| 646 |
+
chu_ky_dropdown = gr.Dropdown(
|
| 647 |
+
choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
|
| 648 |
+
value="3 tháng",
|
| 649 |
+
label="📊 Chu Kỳ Dự Báo",
|
| 650 |
+
info="Chọn khoảng thời gian dự báo phù hợp với mục đích kinh doanh"
|
| 651 |
+
)
|
| 652 |
+
|
| 653 |
+
nut_du_bao = gr.Button(
|
| 654 |
+
"🚀 Tạo Dự Báo AI",
|
| 655 |
+
variant="primary",
|
| 656 |
+
size="lg",
|
| 657 |
+
elem_classes="button-predict"
|
| 658 |
+
)
|
| 659 |
+
|
| 660 |
+
# Hiển thị thông tin case
|
| 661 |
+
hien_thi_thong_tin = gr.HTML()
|
| 662 |
+
|
| 663 |
+
with gr.Row():
|
| 664 |
+
with gr.Column():
|
| 665 |
+
gr.HTML("<div class='feature-box'><h3>📈 Kết Quả Dự Báo</h3></div>")
|
| 666 |
+
|
| 667 |
+
# Chế độ hiển thị được đặt gần biểu đồ
|
| 668 |
+
che_do_xem = gr.Radio(
|
| 669 |
+
choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
|
| 670 |
+
value="ngày",
|
| 671 |
+
label="📊 Chế Độ Hiển Thị Biểu Đồ",
|
| 672 |
+
info="Thay đổi cách hiển thị dữ liệu trên biểu đồ"
|
| 673 |
+
)
|
| 674 |
+
|
| 675 |
+
bieu_do_du_bao = gr.Plot(
|
| 676 |
+
label="Biểu Đồ Dự Báo Bán Hàng",
|
| 677 |
+
elem_classes=["plot-container"]
|
| 678 |
+
)
|
| 679 |
+
|
| 680 |
+
with gr.Row():
|
| 681 |
+
with gr.Column(scale=1):
|
| 682 |
+
gr.HTML("<div class='feature-box'><h3>📊 Thống Kê Tổng Hợp</h3></div>")
|
| 683 |
+
hien_thi_tom_tat = gr.HTML()
|
| 684 |
+
|
| 685 |
+
with gr.Column(scale=1):
|
| 686 |
+
gr.HTML("<div class='feature-box'><h3>👔 Báo Cáo Điều Hành</h3></div>")
|
| 687 |
+
hien_thi_bao_cao = gr.Markdown()
|
| 688 |
+
|
| 689 |
+
# Xử lý sự kiện
|
| 690 |
+
lua_chon_dropdown.change(
|
| 691 |
+
fn=cap_nhat_thong_tin_case,
|
| 692 |
+
inputs=[lua_chon_dropdown],
|
| 693 |
+
outputs=[hien_thi_thong_tin]
|
| 694 |
+
)
|
| 695 |
+
|
| 696 |
+
nut_du_bao.click(
|
| 697 |
+
fn=xu_ly_du_doan_voi_loading,
|
| 698 |
+
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 699 |
+
outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao],
|
| 700 |
+
show_progress=True
|
| 701 |
+
)
|
| 702 |
+
|
| 703 |
+
# Cập nhật biểu đồ khi thay đổi chế độ hiển thị - chỉ khi đã có dự đo��n
|
| 704 |
+
def cap_nhat_khi_doi_che_do(case, chu_ky, mode):
|
| 705 |
+
try:
|
| 706 |
+
if case and case != "":
|
| 707 |
+
return [
|
| 708 |
+
tao_bieu_do_du_doan(case, chu_ky, mode),
|
| 709 |
+
tao_thong_tin_tom_tat(case, chu_ky, mode)
|
| 710 |
+
]
|
| 711 |
+
else:
|
| 712 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 713 |
+
except:
|
| 714 |
+
return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
|
| 715 |
+
|
| 716 |
+
che_do_xem.change(
|
| 717 |
+
fn=cap_nhat_khi_doi_che_do,
|
| 718 |
+
inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
|
| 719 |
+
outputs=[bieu_do_du_bao, hien_thi_tom_tat]
|
| 720 |
+
)
|
| 721 |
+
|
| 722 |
+
# Tự động load case đầu tiên với biểu đồ mặc định
|
| 723 |
+
demo.load(
|
| 724 |
+
fn=lambda: [
|
| 725 |
+
cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
|
| 726 |
+
tao_bieu_do_mac_dinh(),
|
| 727 |
+
tao_tom_tat_mac_dinh(),
|
| 728 |
+
"# 👔 BÁO CÁO ĐIỀU HÀNH\n\n📊 **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**\n\nHệ thống sẽ tạo báo cáo điều hành với insights và khuyến nghị cụ thể."
|
| 729 |
+
],
|
| 730 |
+
outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
|
| 731 |
+
)
|
| 732 |
+
|
| 733 |
+
# Footer thông tin hệ thống với branding FoxAI
|
| 734 |
+
gr.HTML(f"""
|
| 735 |
+
<div class='info-card' style="margin-top: 30px;">
|
| 736 |
+
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 20px;">
|
| 737 |
+
<img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
|
| 738 |
+
<h3 style="color: #1A5F91; margin: 0;">💡 Thông Tin Hệ Thống FoxAI</h3>
|
| 739 |
+
</div>
|
| 740 |
+
|
| 741 |
+
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
|
| 742 |
+
<div>
|
| 743 |
+
<h4 style="color: #1A5F91;">🎯 Tính Năng Nổi Bật:</h4>
|
| 744 |
+
<ul>
|
| 745 |
+
<li><strong>AI Insights:</strong> Phân tích thông minh với khuyến nghị cụ thể</li>
|
| 746 |
+
<li><strong>Multi-view:</strong> Xem theo ngày/tháng/năm linh hoạt</li>
|
| 747 |
+
<li><strong>Executive Reports:</strong> Báo cáo chuyên nghiệp cho ban điều hành</li>
|
| 748 |
+
<li><strong>Real-time:</strong> Cập nhật dữ liệu theo thời gian thực</li>
|
| 749 |
+
</ul>
|
| 750 |
+
</div>
|
| 751 |
+
|
| 752 |
+
<div>
|
| 753 |
+
<h4 style="color: #1A5F91;">📊 Chất Lượng Dự Báo:</h4>
|
| 754 |
+
<ul>
|
| 755 |
+
<li><strong>Độ Chính Xác:</strong> 95.8% trên 3 ngành hàng</li>
|
| 756 |
+
<li><strong>Phạm Vi:</strong> Từ 3 tháng đến 1 năm</li>
|
| 757 |
+
<li><strong>Cập Nhật:</strong> Real-time với market intelligence</li>
|
| 758 |
+
<li><strong>Báo Cáo:</strong> Professional format cho C-level executives</li>
|
| 759 |
+
</ul>
|
| 760 |
+
</div>
|
| 761 |
+
</div>
|
| 762 |
+
|
| 763 |
+
<div style="text-align: center; margin: 20px 0; padding: 15px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 10px; border: 2px solid #1A5F91;">
|
| 764 |
+
<p style="color: #1A5F91; font-weight: bold; margin: 0; font-size: 16px;">
|
| 765 |
+
🦊 <strong>Powered by FoxAI</strong> | 🇻🇳 Made in Vietnam | 🤖 Advanced AI | 📊 Enterprise Ready | ⚡ Real-time Analytics
|
| 766 |
+
</p>
|
| 767 |
+
<p style="color: #8B8B8B; margin: 5px 0 0 0; font-size: 14px;">
|
| 768 |
+
YOUR TRUSTED PARTNER - FoxAI Technology Solutions
|
| 769 |
+
</p>
|
| 770 |
+
</div>
|
| 771 |
+
</div>
|
| 772 |
+
""")
|
| 773 |
+
|
| 774 |
+
return demo
|
| 775 |
+
|
| 776 |
+
# Chạy ứng dụng
|
| 777 |
+
if __name__ == "__main__":
|
| 778 |
+
demo = tao_ung_dung()
|
| 779 |
+
demo.launch(
|
| 780 |
+
share=True,
|
| 781 |
+
server_name="0.0.0.0",
|
| 782 |
+
server_port=7860,
|
| 783 |
+
show_error=True
|
| 784 |
+
)
|
bro.css
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.gradio-container {
|
| 2 |
+
background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
|
| 3 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
.header-container {
|
| 7 |
+
text-align: center;
|
| 8 |
+
margin: 20px 0;
|
| 9 |
+
padding: 30px;
|
| 10 |
+
background: linear-gradient(135deg, rgba(255,107,107,0.1), rgba(78,205,196,0.1), rgba(255,234,167,0.1));
|
| 11 |
+
border-radius: 20px;
|
| 12 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
.header-title {
|
| 16 |
+
background: linear-gradient(90deg, #FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7, #DDA0DD);
|
| 17 |
+
background-size: 300% 300%;
|
| 18 |
+
animation: gradient 8s ease infinite;
|
| 19 |
+
-webkit-background-clip: text;
|
| 20 |
+
-webkit-text-fill-color: transparent;
|
| 21 |
+
background-clip: text;
|
| 22 |
+
text-align: center;
|
| 23 |
+
font-size: 3em;
|
| 24 |
+
font-weight: bold;
|
| 25 |
+
margin: 20px 0;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
@keyframes gradient {
|
| 29 |
+
0% { background-position: 0% 50%; }
|
| 30 |
+
50% { background-position: 100% 50%; }
|
| 31 |
+
100% { background-position: 0% 50%; }
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.loading-container {
|
| 35 |
+
text-align: center;
|
| 36 |
+
padding: 40px;
|
| 37 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 38 |
+
border-radius: 15px;
|
| 39 |
+
color: white;
|
| 40 |
+
margin: 20px 0;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.loading-spinner {
|
| 44 |
+
border: 4px solid #f3f3f3;
|
| 45 |
+
border-top: 4px solid #3498db;
|
| 46 |
+
border-radius: 50%;
|
| 47 |
+
width: 40px;
|
| 48 |
+
height: 40px;
|
| 49 |
+
animation: spin 1s linear infinite;
|
| 50 |
+
margin: 0 auto 20px;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
@keyframes spin {
|
| 54 |
+
0% { transform: rotate(0deg); }
|
| 55 |
+
100% { transform: rotate(360deg); }
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.progress-bar {
|
| 59 |
+
width: 100%;
|
| 60 |
+
height: 20px;
|
| 61 |
+
background-color: rgba(255,255,255,0.3);
|
| 62 |
+
border-radius: 10px;
|
| 63 |
+
overflow: hidden;
|
| 64 |
+
margin: 15px 0;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
.progress-fill {
|
| 68 |
+
height: 100%;
|
| 69 |
+
background: linear-gradient(90deg, #4CAF50, #81C784);
|
| 70 |
+
border-radius: 10px;
|
| 71 |
+
animation: progress 3s ease-in-out;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
@keyframes progress {
|
| 75 |
+
0% { width: 0%; }
|
| 76 |
+
25% { width: 30%; }
|
| 77 |
+
50% { width: 60%; }
|
| 78 |
+
75% { width: 85%; }
|
| 79 |
+
100% { width: 100%; }
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
.prediction-box {
|
| 83 |
+
background: linear-gradient(135deg, #FF6B6B, #4ECDC4);
|
| 84 |
+
border-radius: 15px;
|
| 85 |
+
padding: 20px;
|
| 86 |
+
color: white;
|
| 87 |
+
text-align: center;
|
| 88 |
+
font-size: 1.2em;
|
| 89 |
+
font-weight: bold;
|
| 90 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 91 |
+
margin: 15px 0;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
.insight-box {
|
| 95 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 96 |
+
border-radius: 15px;
|
| 97 |
+
padding: 20px;
|
| 98 |
+
color: white;
|
| 99 |
+
margin: 15px 0;
|
| 100 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.executive-summary {
|
| 104 |
+
background: linear-gradient(135deg, #2C3E50, #34495E);
|
| 105 |
+
border-radius: 15px;
|
| 106 |
+
padding: 25px;
|
| 107 |
+
color: white;
|
| 108 |
+
margin: 15px 0;
|
| 109 |
+
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
|
| 110 |
+
border-left: 5px solid #E74C3C;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.feature-box {
|
| 114 |
+
background: linear-gradient(135deg, #96CEB4, #FFEAA7);
|
| 115 |
+
border-radius: 15px;
|
| 116 |
+
padding: 15px;
|
| 117 |
+
margin: 10px 0;
|
| 118 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
.system-status {
|
| 122 |
+
background: linear-gradient(135deg, #27AE60, #2ECC71);
|
| 123 |
+
color: white;
|
| 124 |
+
padding: 10px 20px;
|
| 125 |
+
border-radius: 25px;
|
| 126 |
+
margin: 10px 0;
|
| 127 |
+
text-align: center;
|
| 128 |
+
font-weight: bold;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.metric-card {
|
| 132 |
+
background: linear-gradient(135deg, #3498DB, #5DADE2);
|
| 133 |
+
color: white;
|
| 134 |
+
border-radius: 10px;
|
| 135 |
+
padding: 15px;
|
| 136 |
+
margin: 5px;
|
| 137 |
+
text-align: center;
|
| 138 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
.button-predict {
|
| 142 |
+
background: linear-gradient(135deg, #E74C3C, #C0392B) !important;
|
| 143 |
+
color: white !important;
|
| 144 |
+
border: none !important;
|
| 145 |
+
border-radius: 25px !important;
|
| 146 |
+
padding: 15px 30px !important;
|
| 147 |
+
font-size: 16px !important;
|
| 148 |
+
font-weight: bold !important;
|
| 149 |
+
box-shadow: 0 4px 15px rgba(231, 76, 60, 0.4) !important;
|
| 150 |
+
transition: all 0.3s ease !important;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
.button-predict:hover {
|
| 154 |
+
transform: translateY(-2px) !important;
|
| 155 |
+
box-shadow: 0 6px 20px rgba(231, 76, 60, 0.6) !important;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
.plot-container {
|
| 159 |
+
border: 1px solid #e1e5e9;
|
| 160 |
+
border-radius: 15px;
|
| 161 |
+
padding: 15px;
|
| 162 |
+
margin: 15px 0;
|
| 163 |
+
background: rgba(255, 255, 255, 0.95);
|
| 164 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
.info-card {
|
| 168 |
+
background: rgba(255, 255, 255, 0.95);
|
| 169 |
+
border-radius: 10px;
|
| 170 |
+
padding: 15px;
|
| 171 |
+
margin: 10px 0;
|
| 172 |
+
border-left: 5px solid #3498DB;
|
| 173 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 174 |
+
}
|
test_data.csv
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Date,Sales,Inventory,Price
|
| 2 |
+
2024-01-01,1000,500,25.5
|
| 3 |
+
2024-01-02,1200,480,26.0
|
| 4 |
+
2024-01-03,1100,460,25.8
|
| 5 |
+
2024-01-04,1300,440,26.2
|
| 6 |
+
2024-01-05,1250,420,26.1
|