adnandi commited on
Commit
c1a3a37
ยท
1 Parent(s): ac81431

fix error

Browse files
Files changed (4) hide show
  1. README.md +2 -1
  2. app.py +83 -9
  3. dashboard_app/main.py +24 -10
  4. requirements.txt +2 -2
README.md CHANGED
@@ -4,9 +4,10 @@ emoji: ๐Ÿ“ˆ
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 4.19.2
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
  # Trend Summarizer AI
 
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 5.33.0
8
  app_file: app.py
9
  pinned: false
10
+ short_description: AI-powered industry trend analysis dashboard
11
  ---
12
 
13
  # Trend Summarizer AI
app.py CHANGED
@@ -1,30 +1,104 @@
1
  import os
2
  import sys
3
  import nltk
 
4
 
 
 
 
5
  try:
6
  import spaces
7
- @spaces.GPU
8
- def dummy_gpu_task():
9
- return "Bypass ZeroGPU detection"
10
  except ImportError:
11
- pass
12
 
13
- # Pre-download NLTK requirements on startup
14
  print("Downloading NLTK requirements...")
15
  nltk.download('punkt', quiet=True)
16
  nltk.download('punkt_tab', quiet=True)
17
  nltk.download('stopwords', quiet=True)
18
  print("NLTK download complete.")
19
 
20
- # Add current directory to path to allow root imports
21
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
22
 
23
- import uvicorn
24
- from dashboard_app.main import app
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  if __name__ == "__main__":
27
- # Hugging Face Spaces exposes port 7860 by default
28
  port = int(os.environ.get("PORT", 7860))
29
  print(f"Starting server on port {port}...")
30
  uvicorn.run(app, host="0.0.0.0", port=port)
 
1
  import os
2
  import sys
3
  import nltk
4
+ import gradio as gr
5
 
6
+ # --- ZeroGPU compatibility ---
7
+ # HF Spaces with Gradio SDK + ZeroGPU requires at least one @spaces.GPU
8
+ # function that is wired to a Gradio component so ZeroGPU can detect it.
9
  try:
10
  import spaces
11
+ _SPACES_AVAILABLE = True
 
 
12
  except ImportError:
13
+ _SPACES_AVAILABLE = False
14
 
15
+ # --- NLTK downloads (must happen before any NLP imports) ---
16
  print("Downloading NLTK requirements...")
17
  nltk.download('punkt', quiet=True)
18
  nltk.download('punkt_tab', quiet=True)
19
  nltk.download('stopwords', quiet=True)
20
  print("NLTK download complete.")
21
 
22
+ # --- Ensure project root is importable ---
23
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
24
 
25
+ # --- Import the FastAPI application ---
26
+ from dashboard_app.main import app as fastapi_app # noqa: E402
27
 
28
+ # --- Define a GPU-decorated function wired to Gradio ---
29
+ # ZeroGPU needs to see a @spaces.GPU function connected to the Gradio app.
30
+ def _gpu_health_check():
31
+ """Health check function โ€” GPU is allocated on-demand when called."""
32
+ return "โœ… GPU tersedia dan siap digunakan."
33
+
34
+ if _SPACES_AVAILABLE:
35
+ _gpu_health_check = spaces.GPU(_gpu_health_check)
36
+
37
+ # --- Build the Gradio Blocks app ---
38
+ # This serves as the shell that HF Spaces expects.
39
+ # It auto-redirects users to the real FastAPI dashboard.
40
+
41
+ REDIRECT_HTML = """
42
+ <div id="landing-container" style="
43
+ display:flex; flex-direction:column; align-items:center; justify-content:center;
44
+ min-height:80vh; font-family:'Inter',system-ui,sans-serif; background:#0f172a;
45
+ color:#e2e8f0; text-align:center; padding:2rem;
46
+ ">
47
+ <div style="
48
+ background:linear-gradient(135deg,#1e293b,#334155);
49
+ border:1px solid #475569; border-radius:16px;
50
+ padding:3rem 2.5rem; max-width:520px; width:100%;
51
+ box-shadow:0 25px 50px -12px rgba(0,0,0,0.5);
52
+ ">
53
+ <div style="font-size:3rem; margin-bottom:1rem;">๐Ÿ“ˆ</div>
54
+ <h1 style="font-size:1.75rem; font-weight:700; margin:0 0 0.5rem 0;
55
+ background:linear-gradient(135deg,#60a5fa,#a78bfa);
56
+ -webkit-background-clip:text; -webkit-text-fill-color:transparent;">
57
+ TrendAI Summarizer
58
+ </h1>
59
+ <p style="color:#94a3b8; margin:0 0 2rem 0; font-size:0.95rem; line-height:1.6;">
60
+ Dashboard analisis tren industri berbasis AI.<br>
61
+ Klik tombol di bawah untuk membuka dashboard.
62
+ </p>
63
+ <a href="/dashboard.html" target="_top" style="
64
+ display:inline-block; padding:0.75rem 2rem;
65
+ background:linear-gradient(135deg,#3b82f6,#6366f1);
66
+ color:white; text-decoration:none; border-radius:10px;
67
+ font-weight:600; font-size:1rem;
68
+ transition:transform 0.2s, box-shadow 0.2s;
69
+ box-shadow:0 4px 14px rgba(99,102,241,0.4);
70
+ " onmouseover="this.style.transform='translateY(-2px)';this.style.boxShadow='0 8px 20px rgba(99,102,241,0.5)'"
71
+ onmouseout="this.style.transform='none';this.style.boxShadow='0 4px 14px rgba(99,102,241,0.4)'">
72
+ ๐Ÿš€ Buka Dashboard
73
+ </a>
74
+ <p style="color:#64748b; margin-top:1.5rem; font-size:0.8rem;">
75
+ Atau akses API docs di <a href="/docs" target="_top" style="color:#60a5fa;">/docs</a>
76
+ </p>
77
+ </div>
78
+ </div>
79
+ """
80
+
81
+ with gr.Blocks(
82
+ title="TrendAI Summarizer",
83
+ theme=gr.themes.Base(),
84
+ css="body { margin: 0; padding: 0; background: #0f172a; }"
85
+ ) as demo:
86
+ gr.HTML(REDIRECT_HTML)
87
+ # Hidden button to wire the @spaces.GPU function into Gradio's event system
88
+ with gr.Row(visible=False):
89
+ gpu_btn = gr.Button("GPU Check")
90
+ gpu_output = gr.Textbox()
91
+ gpu_btn.click(fn=_gpu_health_check, inputs=None, outputs=gpu_output)
92
+
93
+ # --- Mount Gradio onto the FastAPI app ---
94
+ # This keeps all FastAPI routes (/api/*, /dashboard.html, static files)
95
+ # functional while Gradio handles ZeroGPU detection at "/"
96
+ app = gr.mount_gradio_app(fastapi_app, demo, path="/gradio")
97
+
98
+ # --- Entry point ---
99
+ # HF Spaces runs `python app.py` directly. Uvicorn serves everything.
100
  if __name__ == "__main__":
101
+ import uvicorn
102
  port = int(os.environ.get("PORT", 7860))
103
  print(f"Starting server on port {port}...")
104
  uvicorn.run(app, host="0.0.0.0", port=port)
dashboard_app/main.py CHANGED
@@ -4,13 +4,7 @@ import json
4
  import asyncio
5
  import logging
6
 
7
- try:
8
- import spaces
9
- @spaces.GPU
10
- def dummy_gpu_task_main():
11
- return "Bypass ZeroGPU detection in main"
12
- except ImportError:
13
- pass
14
  from typing import List, Optional, Dict, Any
15
  from datetime import datetime, timedelta
16
  from fastapi import FastAPI, BackgroundTasks, HTTPException, Query, Response, status
@@ -70,9 +64,20 @@ app = FastAPI(
70
  )
71
 
72
  # CORS Policy configuration
 
 
 
 
 
 
 
 
 
 
 
73
  app.add_middleware(
74
  CORSMiddleware,
75
- allow_origins=["http://localhost:3000", "http://localhost:5173", "http://127.0.0.1:3000", "http://127.0.0.1:5173", "http://localhost:8001", "http://127.0.0.1:8001"],
76
  allow_credentials=True,
77
  allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
78
  allow_headers=["*"],
@@ -83,16 +88,25 @@ app.add_middleware(
83
  async def add_security_headers(request, call_next):
84
  response = await call_next(request)
85
  response.headers["X-Content-Type-Options"] = "nosniff"
86
- response.headers["X-Frame-Options"] = "SAMEORIGIN"
 
 
 
87
  response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
88
  # Content-Security-Policy (CSP) - Allow static resources, Tailwind CDN, Google Fonts, and images
 
 
 
 
 
89
  response.headers["Content-Security-Policy"] = (
90
  "default-src 'self'; "
91
  "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com; "
92
  "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
93
  "font-src 'self' https://fonts.gstatic.com; "
94
  "img-src 'self' data: https://lh3.googleusercontent.com; "
95
- "connect-src 'self';"
 
96
  )
97
  return response
98
 
 
4
  import asyncio
5
  import logging
6
 
7
+
 
 
 
 
 
 
8
  from typing import List, Optional, Dict, Any
9
  from datetime import datetime, timedelta
10
  from fastapi import FastAPI, BackgroundTasks, HTTPException, Query, Response, status
 
64
  )
65
 
66
  # CORS Policy configuration
67
+ # Determine allowed origins โ€” include HF Spaces domains for deployment
68
+ _ALLOWED_ORIGINS = [
69
+ "http://localhost:3000", "http://localhost:5173",
70
+ "http://127.0.0.1:3000", "http://127.0.0.1:5173",
71
+ "http://localhost:8001", "http://127.0.0.1:8001",
72
+ ]
73
+ # Add the HF Spaces origin if running on Spaces
74
+ _HF_SPACE = os.environ.get("SPACE_HOST")
75
+ if _HF_SPACE:
76
+ _ALLOWED_ORIGINS.append(f"https://{_HF_SPACE}")
77
+
78
  app.add_middleware(
79
  CORSMiddleware,
80
+ allow_origins=_ALLOWED_ORIGINS,
81
  allow_credentials=True,
82
  allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
83
  allow_headers=["*"],
 
88
  async def add_security_headers(request, call_next):
89
  response = await call_next(request)
90
  response.headers["X-Content-Type-Options"] = "nosniff"
91
+ # On HF Spaces, skip X-Frame-Options so Gradio can iframe dashboard pages;
92
+ # CSP frame-ancestors handles framing security instead.
93
+ if not os.environ.get("SPACE_HOST"):
94
+ response.headers["X-Frame-Options"] = "SAMEORIGIN"
95
  response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
96
  # Content-Security-Policy (CSP) - Allow static resources, Tailwind CDN, Google Fonts, and images
97
+ # Build CSP โ€” allow HF Spaces domain for frame-ancestors so Gradio can iframe dashboard pages
98
+ hf_host = os.environ.get("SPACE_HOST", "")
99
+ frame_ancestors = "'self'"
100
+ if hf_host:
101
+ frame_ancestors += f" https://{hf_host}"
102
  response.headers["Content-Security-Policy"] = (
103
  "default-src 'self'; "
104
  "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com; "
105
  "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
106
  "font-src 'self' https://fonts.gstatic.com; "
107
  "img-src 'self' data: https://lh3.googleusercontent.com; "
108
+ "connect-src 'self'; "
109
+ f"frame-ancestors {frame_ancestors};"
110
  )
111
  return response
112
 
requirements.txt CHANGED
@@ -6,7 +6,6 @@ Sastrawi
6
  networkx
7
  transformers
8
  torch
9
- streamlit
10
  rouge-score
11
  pandas
12
  numpy
@@ -19,5 +18,6 @@ feedparser
19
  requests
20
  python-multipart
21
  jinja2
 
22
  spaces
23
- huggingface_hub==0.23.2
 
6
  networkx
7
  transformers
8
  torch
 
9
  rouge-score
10
  pandas
11
  numpy
 
18
  requests
19
  python-multipart
20
  jinja2
21
+ gradio>=5.0.0
22
  spaces
23
+ huggingface_hub