ColinYK commited on
Commit
3903870
·
verified ·
1 Parent(s): 15c1895

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -0
app.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import sys
3
+ import pandas as pd
4
+ import os
5
+ import json
6
+ import shutil
7
+ import zipfile
8
+ import uuid
9
+ import requests
10
+
11
+ TEMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
12
+
13
+ metric_scale = {
14
+ 'human_face_similarity': 1.5,
15
+ 'clip_score': 0.02,
16
+ 'env_clip': 1.5,
17
+ 'other_subject_clip': 1.5,
18
+ 'image_quality': 1,
19
+ 'dynamic_degree': 1,
20
+ 'aesthetic_quality': 1,
21
+ 'motion_smoothness': 1,
22
+ }
23
+
24
+ class ModelResult:
25
+ def __init__(self, data):
26
+ self.name = data['model_name']
27
+ self.project_link = data.get('project_link', None)
28
+ self.result = data['result']
29
+
30
+ def to_dict(self):
31
+ if self.project_link is not None:
32
+ res = {
33
+ 'model_name': f'<a href="{self.project_link}" target="_blank">{self.name}</a>',
34
+ }
35
+ else:
36
+ res = {
37
+ 'model_name': self.name,
38
+ }
39
+ total_score = []
40
+ for metric in self.result.keys():
41
+ res[metric] = round(float(self.result[metric]) - 1e-3, 4)
42
+ total_score.append(self.result[metric] * metric_scale[metric])
43
+ total_score = sum(total_score) / len(total_score)
44
+ res['comprehensive score'] = round(total_score, 4)
45
+ return res
46
+
47
+ def upload_large_zip_stream(zip_path, model_name, org_link, chunk_size=10*1024*1024):
48
+ """Stream upload a large zip file in chunks"""
49
+ file_id = str(uuid.uuid4())
50
+ total_size = os.path.getsize(zip_path)
51
+ total_chunks = (total_size + chunk_size - 1) // chunk_size
52
+
53
+ with open(zip_path, 'rb') as f:
54
+ for chunk_num in range(total_chunks):
55
+ chunk = f.read(chunk_size)
56
+ files = {
57
+ 'file': (os.path.basename(zip_path), chunk, 'application/zip'),
58
+ }
59
+ params = {
60
+ 'chunk_number': int(chunk_num),
61
+ 'total_chunks': int(total_chunks),
62
+ 'file_id': file_id,
63
+ 'model_name': model_name,
64
+ }
65
+
66
+ response = requests.post(
67
+ "http://47.239.99.255/A2Bench_evaluation/update_zip/",
68
+ files=files,
69
+ params=params
70
+ )
71
+ data = response.json()
72
+ print(f"Uploaded chunk {chunk_num+1}/{total_chunks} - {data['progress']}")
73
+
74
+ print("Final upload status:", response.json())
75
+ assert 'unzip_video_path' in response.json(), "Upload failed"
76
+ assert 'unzip_status' in response.json(), "Upload failed"
77
+ unzip_video_path = response.json()['unzip_video_path']
78
+ unzip_status = response.json()['unzip_status']
79
+ if unzip_status == "success":
80
+ return unzip_video_path
81
+ else:
82
+ raise gr.Error("Upload failed")
83
+
84
+ def eval_request(model_name, org_link, result_path):
85
+ params = {
86
+ "model_name": model_name,
87
+ "org_link": org_link,
88
+ "result_path": result_path
89
+ }
90
+ response = requests.post("http://47.239.99.255/A2Bench_evaluation/eval", params=params)
91
+ return response.json()
92
+
93
+ def evaluation(zip_path, model_name, org_link):
94
+ try:
95
+ unzip_video_path = upload_large_zip_stream(zip_path, model_name, org_link)
96
+ if org_link=="":
97
+ org_link = None
98
+ eval_request(model_name, org_link, unzip_video_path)
99
+
100
+ return "Evaluation completed successfully!"
101
+ except Exception as e:
102
+ raise gr.Error(f"Evaluation failed: {str(e)}")
103
+
104
+
105
+
106
+ def load_leaderboard():
107
+ leaderboard_list = []
108
+ file_list = requests.get("http://47.239.99.255/A2Bench_evaluation/load_leaderboard")
109
+ for file in file_list.json():
110
+ leaderboard_list.append(ModelResult(file))
111
+ return leaderboard_list
112
+
113
+ HEADER = ['model_name', 'comprehensive score', 'clip_score', 'human_face_similarity', 'env_clip', 'other_subject_clip', 'image_quality', 'dynamic_degree', 'aesthetic_quality', 'motion_smoothness']
114
+
115
+ def display_table():
116
+ leaderboard_list = load_leaderboard()
117
+ data = {}
118
+ for metric in HEADER:
119
+ data[metric] = []
120
+ for model_result in leaderboard_list:
121
+ result_dict = model_result.to_dict()
122
+ for metric in HEADER:
123
+ data[metric].append(result_dict[metric])
124
+ df = pd.DataFrame(data)
125
+ df = df.sort_values(by='comprehensive score', ascending=False)
126
+ return df
127
+
128
+ _HEADER_ = '''
129
+ <div style="text-align: center; max-width: 650px; margin: 0 auto;">
130
+ <h1 style="font-size: 2.5rem; font-weight: 700; margin-bottom: 1rem; display: contents;">A2-Bench Leaderboard</h1>
131
+ <p style="font-size: 1rem; margin-bottom: 1.5rem;">Paper: <a href='https://arxiv.org/pdf/2504.02436' target='_blank'>SkyReels-A2 </a> | Codes: <a href='https://github.com/SkyworkAI/SkyReels-A2' target='_blank'>GitHub</a> | <a href='https://huggingface.co/Skywork/SkyReels-A2' target='_blank'>HugginceFace</a></p>
132
+ </div>
133
+
134
+ ❗️❗️❗️**LEADERBOARD INTRODUCTION:** ❗️❗️❗️
135
+ This is A2-Bench leaderboard which is used to evaluate the performance of elements-to-video (E2V) generation models.
136
+ We provide an evaluation set containing 50 paired multiple elements (character, object, and background). You can check [evaluation set introduction]() for more details. Each evaluation case includes:
137
+ <ul style="font-size: 0.9rem; margin-top: -0.5rem;">
138
+ <li>Human subject (characters): Includes both male and female subjects, covering generated by Flux, celebrities and ordinary people, additionally, we provide several generated human images</li>
139
+ <li>Non-human subject: Various objects including different types of animals, guitars, racing cars, balls, etc.</li>
140
+ <li>Background image: Diverse environmental settings including ordinary indoor and outdoor scenes and famous background suck as The Great Wall and Yellow Wind Ridge (from Black Myth: Wukong)</li>
141
+ <li>Prompt: "A realistic scene where [human] interacts with [object] in [environment], following physical laws and spatial logic".</li>
142
+ </ul>
143
+ </p>
144
+ <div style="text-align: center; margin: 1rem 0;">
145
+ <h3 style="font-size: 1.2rem; margin-bottom: 0.5rem;">Example Test Case</h3>
146
+ <div style="display: flex; justify-content: center; gap: 1rem; margin: 1rem 0;">
147
+ <img src="https://www.helloimg.com/i/2025/04/07/67f386a7f3717.png" alt="Human Subject Example" style="max-height: 400px; border-radius: 2px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
148
+ <img src="https://www.helloimg.com/i/2025/04/07/67f38681d9c24.jpg" alt="Non-human Subject Example" style="max-height: 400px; border-radius: 2px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
149
+ <img src="https://www.helloimg.com/i/2025/04/07/67f38684117d0.jpg" alt="Background Example" style="max-height: 400px; border-radius: 2px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
150
+ </div>
151
+ <p style="font-size: 0.9rem; margin-top: 0.5rem;">Prompt: A man feeding a bird in the park.</p>
152
+ </div>
153
+
154
+ We provide a set of evaluation metric of elements-to-video models and a leaderboard to show the performance of different models.
155
+ Evaluation metric include:
156
+ - Elements Consistency: Measures character id consistency using arcface human recognition model, and measures object and background consistency using CLIP model.
157
+ - Video Quality: Measures video quality on image quality, dynamic degree, aesthetic quality and motion smoothness.
158
+ - T2V Metrics: Measures text-video consistency using CLIP
159
+
160
+ You can check [Metric Introduction](https://skyworkai.github.io/skyreels-a2.github.io/static/images/bench.png) for more details.
161
+
162
+ The leaderboard ranks the models based on the comprehensive score, which is the weighted average of all the metrics. We give T2V metrics and object consistency metrics higher weights.
163
+ You can click the model name to visit the project page, At meantime, you can upload your model result **zip file** to the leaderboard by clicking the "Evaluation" button. the zip file should include the video result named as "0.mp4", "1.mp4", "2.mp4", etc.
164
+ ''' # noqa E501
165
+
166
+ _CITE_ = r"""
167
+ If A2-Bench is helpful, please help to ⭐ the <a href='https://github.com/SkyworkAI/SkyReels-A2' target='_blank'> Github Repo</a>. Thanks!
168
+ ---
169
+
170
+ 📧 **Contact**
171
+ If you have any questions or feedbacks, feel free to open a discussion or contact <b>[email protected]</b>.
172
+ """ # noqa E501
173
+
174
+ def upload_file(files):
175
+ target_dir = os.path.join(TEMP_DIR, f'{files.name}')
176
+ os.makedirs(target_dir, exist_ok=True)
177
+ shutil.move(files.name, target_dir)
178
+ return target_dir
179
+
180
+ with gr.Blocks(css=".gr-dataframe a {text-decoration: none; color: inherit;}") as demo:
181
+ gr.Markdown(_HEADER_)
182
+ with gr.Group():
183
+ table = gr.DataFrame(
184
+ value=display_table(),
185
+ datatype=['markdown', 'str'],
186
+ interactive=False, # 允许编辑
187
+ headers=HEADER,
188
+ )
189
+ Refresh = gr.Button("Refresh")
190
+ Refresh.click(display_table, outputs=table)
191
+
192
+ with gr.Group():
193
+
194
+ upload_btn = gr.UploadButton("Click to Upload a File", file_types=[".zip"], file_count="single")
195
+ with gr.Row():
196
+ model_name_input = gr.Textbox(label="Model Name", placeholder="Required:Enter your model name")
197
+ org_link_input = gr.Textbox(label="Project Page", placeholder="Optional:Enter project page, will show on leaderboard")
198
+ file_output = gr.File()
199
+ upload_btn.upload(upload_file, upload_btn, file_output)
200
+
201
+ evaluation_btn = gr.Button("Evaluation")
202
+ output_message = gr.Textbox(label="Evaluation Status", interactive=False)
203
+ evaluation_btn.click(
204
+ evaluation,
205
+ inputs=[file_output, model_name_input, org_link_input],
206
+ outputs=output_message,
207
+ api_name="evaluate",
208
+ )
209
+
210
+
211
+
212
+ gr.Markdown(_CITE_)
213
+
214
+
215
+
216
+ if __name__ == "__main__":
217
+ demo.launch()
218
+ # demo.launch(share=True)