smile commited on
Commit
29191d3
·
1 Parent(s): 00e8611

add docker files

Browse files
Files changed (4) hide show
  1. Dockerfile +9 -0
  2. app.py +84 -34
  3. app/templates/error.html +59 -0
  4. app/templates/loading.html +81 -0
Dockerfile ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10.9
2
+
3
+ COPY . .
4
+
5
+ WORKDIR /
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /requirements.txt
8
+
9
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py CHANGED
@@ -1,9 +1,11 @@
1
  from fastapi import FastAPI, Request
2
  from fastapi.templating import Jinja2Templates
3
  from fastapi.staticfiles import StaticFiles
4
- from fastapi.responses import HTMLResponse
5
  import pandas as pd
6
  from pathlib import Path
 
 
7
 
8
  from app.backend.constant import Navigation, ModelProvider, EvaluationMetric, EmbdDtype, EmbdDim, Similarity
9
  from app.backend.data_engine import DataEngine
@@ -17,45 +19,93 @@ app.mount("/static", StaticFiles(directory="app/static"), name="static")
17
  templates = Jinja2Templates(directory="app/templates")
18
 
19
  # Initialize data engine
20
- data_engine = DataEngine()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  @app.get("/", response_class=HTMLResponse)
23
  async def home(request: Request, tab: str = "text"):
24
- # Get initial data based on tab
25
- if tab == "multimodal":
26
- data = data_engine.get_filtered_data(navigation="multimodal")
27
- else:
28
- data = data_engine.get_data()
29
 
30
- # Convert data to list for template rendering
31
- data_list = data.values.tolist()
32
- columns = data.columns.tolist()
33
-
34
- return templates.TemplateResponse("index.html", {
35
- "request": request,
36
- "active_tab": tab,
37
- "data": data_list,
38
- "columns": columns,
39
- "navigations": [e.value for e in Navigation],
40
- "embd_types": [e.value for e in EmbdDtype],
41
- "embd_dims": [e.value for e in EmbdDim],
42
- "similarities": [e.value for e in Similarity]
43
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
  @app.post("/api/filter")
46
  async def filter_data(filters: dict):
47
- # Apply filters to data
48
- data = data_engine.get_filtered_data(
49
- navigation=filters.get('navigation'),
50
- embd_type=filters.get('embd_type'),
51
- embd_dims=filters.get('embd_dims'),
52
- similarity=filters.get('similarity')
53
- )
54
 
55
- # Convert to list for JSON response
56
- return data.values.tolist()
57
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
- if __name__ == "__main__":
60
- import uvicorn
61
- uvicorn.run(app, host="0.0.0.0", port=7890)
 
1
  from fastapi import FastAPI, Request
2
  from fastapi.templating import Jinja2Templates
3
  from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import HTMLResponse, JSONResponse
5
  import pandas as pd
6
  from pathlib import Path
7
+ import asyncio
8
+ import time
9
 
10
  from app.backend.constant import Navigation, ModelProvider, EvaluationMetric, EmbdDtype, EmbdDim, Similarity
11
  from app.backend.data_engine import DataEngine
 
19
  templates = Jinja2Templates(directory="app/templates")
20
 
21
  # Initialize data engine
22
+ data_engine = None
23
+ initialization_start_time = None
24
+
25
+ async def initialize_data_engine():
26
+ global data_engine, initialization_start_time
27
+ if data_engine is None and initialization_start_time is None:
28
+ initialization_start_time = time.time()
29
+ try:
30
+ data_engine = DataEngine()
31
+ print("Successfully initialized DataEngine")
32
+ except Exception as e:
33
+ print(f"Error initializing DataEngine: {str(e)}")
34
+ finally:
35
+ initialization_start_time = None
36
+
37
+ @app.on_event("startup")
38
+ async def startup_event():
39
+ asyncio.create_task(initialize_data_engine())
40
+
41
+ @app.get("/health")
42
+ async def health():
43
+ if data_engine is not None:
44
+ return {"status": "healthy", "initialized": True}
45
+ elif initialization_start_time is not None:
46
+ return {"status": "initializing", "initialized": False, "elapsed_time": time.time() - initialization_start_time}
47
+ else:
48
+ return {"status": "not_initialized", "initialized": False}
49
 
50
  @app.get("/", response_class=HTMLResponse)
51
  async def home(request: Request, tab: str = "text"):
52
+ if data_engine is None:
53
+ return templates.TemplateResponse("loading.html", {"request": request})
 
 
 
54
 
55
+ try:
56
+ # Get initial data based on tab
57
+ if tab == "multimodal":
58
+ data = data_engine.get_filtered_data(navigation="multimodal")
59
+ else:
60
+ data = data_engine.get_data()
61
+
62
+ # Convert data to list for template rendering
63
+ data_list = data.values.tolist()
64
+ columns = data.columns.tolist()
65
+
66
+ return templates.TemplateResponse("index.html", {
67
+ "request": request,
68
+ "active_tab": tab,
69
+ "data": data_list,
70
+ "columns": columns,
71
+ "navigations": [e.value for e in Navigation],
72
+ "embd_types": [e.value for e in EmbdDtype],
73
+ "embd_dims": [e.value for e in EmbdDim],
74
+ "similarities": [e.value for e in Similarity]
75
+ })
76
+ except Exception as e:
77
+ print(f"Error in home route: {str(e)}")
78
+ return templates.TemplateResponse("error.html", {
79
+ "request": request,
80
+ "error": str(e)
81
+ })
82
 
83
  @app.post("/api/filter")
84
  async def filter_data(filters: dict):
85
+ if data_engine is None:
86
+ return JSONResponse(
87
+ status_code=503,
88
+ content={"error": "Service is still initializing"}
89
+ )
 
 
90
 
91
+ try:
92
+ # Apply filters to data
93
+ data = data_engine.get_filtered_data(
94
+ navigation=filters.get('navigation'),
95
+ embd_type=filters.get('embd_type'),
96
+ embd_dims=filters.get('embd_dims'),
97
+ similarity=filters.get('similarity')
98
+ )
99
+
100
+ # Convert to list for JSON response
101
+ return data.values.tolist()
102
+ except Exception as e:
103
+ print(f"Error in filter route: {str(e)}")
104
+ return JSONResponse(
105
+ status_code=500,
106
+ content={"error": str(e)}
107
+ )
108
 
109
+ # if __name__ == "__main__":
110
+ # import uvicorn
111
+ # uvicorn.run(app, host="0.0.0.0", port=7891)
app/templates/error.html ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MTEB Leaderboard - Error</title>
7
+ <!-- Semi Design CSS -->
8
+ <link rel="stylesheet" href="https://unpkg.com/@douyinfe/semi-ui/dist/css/semi.min.css">
9
+ <!-- Custom CSS -->
10
+ <link rel="stylesheet" href="{{ url_for('static', path='css/style.css') }}">
11
+ <style>
12
+ .error-container {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ justify-content: center;
17
+ min-height: 100vh;
18
+ text-align: center;
19
+ padding: 20px;
20
+ }
21
+
22
+ .error-icon {
23
+ font-size: 48px;
24
+ color: #e74c3c;
25
+ margin: 20px 0;
26
+ }
27
+
28
+ .error-message {
29
+ font-size: 1.2em;
30
+ margin: 10px 0;
31
+ color: #666;
32
+ }
33
+
34
+ .retry-button {
35
+ margin-top: 20px;
36
+ padding: 10px 20px;
37
+ background-color: #3498db;
38
+ color: white;
39
+ border: none;
40
+ border-radius: 4px;
41
+ cursor: pointer;
42
+ text-decoration: none;
43
+ }
44
+
45
+ .retry-button:hover {
46
+ background-color: #2980b9;
47
+ }
48
+ </style>
49
+ </head>
50
+ <body>
51
+ <div class="error-container">
52
+ <h1>MTEB Leaderboard</h1>
53
+ <div class="error-icon">⚠️</div>
54
+ <h2>An Error Occurred</h2>
55
+ <p class="error-message">{{ error }}</p>
56
+ <a href="/" class="retry-button">Retry</a>
57
+ </div>
58
+ </body>
59
+ </html>
app/templates/loading.html ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MTEB Leaderboard - Loading</title>
7
+ <!-- Semi Design CSS -->
8
+ <link rel="stylesheet" href="https://unpkg.com/@douyinfe/semi-ui/dist/css/semi.min.css">
9
+ <!-- Custom CSS -->
10
+ <link rel="stylesheet" href="{{ url_for('static', path='css/style.css') }}">
11
+ <style>
12
+ .loading-container {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ justify-content: center;
17
+ min-height: 100vh;
18
+ text-align: center;
19
+ padding: 20px;
20
+ }
21
+
22
+ .loading-spinner {
23
+ border: 4px solid #f3f3f3;
24
+ border-top: 4px solid #3498db;
25
+ border-radius: 50%;
26
+ width: 50px;
27
+ height: 50px;
28
+ animation: spin 1s linear infinite;
29
+ margin: 20px 0;
30
+ }
31
+
32
+ @keyframes spin {
33
+ 0% { transform: rotate(0deg); }
34
+ 100% { transform: rotate(360deg); }
35
+ }
36
+
37
+ .loading-text {
38
+ font-size: 1.2em;
39
+ margin: 10px 0;
40
+ }
41
+
42
+ #loading-status {
43
+ color: #666;
44
+ margin-top: 10px;
45
+ }
46
+ </style>
47
+ </head>
48
+ <body>
49
+ <div class="loading-container">
50
+ <h1>MTEB Leaderboard</h1>
51
+ <div class="loading-spinner"></div>
52
+ <p class="loading-text">Loading data...</p>
53
+ <p id="loading-status">Please wait while we initialize the service</p>
54
+ </div>
55
+
56
+ <script>
57
+ async function checkStatus() {
58
+ try {
59
+ const response = await fetch('/health');
60
+ const data = await response.json();
61
+
62
+ if (data.initialized) {
63
+ window.location.reload();
64
+ } else {
65
+ const status = document.getElementById('loading-status');
66
+ if (data.status === 'initializing') {
67
+ status.textContent = `Initializing... (${Math.round(data.elapsed_time)}s)`;
68
+ } else {
69
+ status.textContent = 'Waiting for initialization...';
70
+ }
71
+ }
72
+ } catch (error) {
73
+ console.error('Error checking status:', error);
74
+ }
75
+ }
76
+
77
+ // Check status every 2 seconds
78
+ setInterval(checkStatus, 2000);
79
+ </script>
80
+ </body>
81
+ </html>