Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -32,7 +32,7 @@ def generate_dummy_spaces(count):
|
|
32 |
# Function to fetch Zero-GPU (CPU-based) Spaces from Huggingface with pagination
|
33 |
def fetch_trending_spaces(offset=0, limit=72):
|
34 |
"""
|
35 |
-
|
36 |
GPU๊ฐ ์๋(=CPU ์ ์ฉ) ์คํ์ด์ค๋ง ํํฐ๋ง
|
37 |
"""
|
38 |
try:
|
@@ -40,7 +40,6 @@ def fetch_trending_spaces(offset=0, limit=72):
|
|
40 |
params = {
|
41 |
"limit": 10000, # ๋ ๋ง์ด ๊ฐ์ ธ์ค๊ธฐ
|
42 |
"hardware": "cpu" # <-- Zero GPU(=CPU) ํํฐ ์ ์ฉ
|
43 |
-
# "sort": "trending", # ํ์์ ์ถ๊ฐ (HF API ์ง์ ์ฌ๋ถ์ ๋ฐ๋ผ)
|
44 |
}
|
45 |
response = requests.get(url, params=params, timeout=30)
|
46 |
|
@@ -54,6 +53,10 @@ def fetch_trending_spaces(offset=0, limit=72):
|
|
54 |
and space.get('id', '').split('/', 1)[0] != 'None'
|
55 |
]
|
56 |
|
|
|
|
|
|
|
|
|
57 |
# Slice according to requested offset and limit
|
58 |
start = min(offset, len(filtered_spaces))
|
59 |
end = min(offset + limit, len(filtered_spaces))
|
@@ -109,8 +112,9 @@ def transform_url(owner, name):
|
|
109 |
# Get space details
|
110 |
def get_space_details(space_data, index, offset):
|
111 |
"""
|
112 |
-
์๋ณธ ์ฝ๋์์ ์์ :
|
113 |
- description, avatar_url, author_name ๋ฑ ์ถ๊ฐ ํ๋๋ฅผ ์ถ์ถ
|
|
|
|
|
114 |
"""
|
115 |
try:
|
116 |
if '/' in space_data.get('id', ''):
|
@@ -151,7 +155,7 @@ def get_space_details(space_data, index, offset):
|
|
151 |
'description': short_desc,
|
152 |
'avatar_url': avatar_url,
|
153 |
'author_name': author_name,
|
154 |
-
'rank': offset + index + 1
|
155 |
}
|
156 |
except Exception as e:
|
157 |
print(f"Error processing space data: {e}")
|
@@ -172,24 +176,26 @@ def get_space_details(space_data, index, offset):
|
|
172 |
# Get owner statistics from all spaces
|
173 |
def get_owner_stats(all_spaces):
|
174 |
"""
|
175 |
-
|
|
|
176 |
"""
|
|
|
|
|
|
|
177 |
owners = []
|
178 |
-
for space in
|
179 |
if '/' in space.get('id', ''):
|
180 |
owner, _ = space.get('id', '').split('/', 1)
|
181 |
else:
|
182 |
owner = space.get('owner', '')
|
183 |
-
|
184 |
-
if owner != 'None':
|
185 |
owners.append(owner)
|
186 |
|
187 |
-
# Count occurrences of each owner
|
188 |
owner_counts = Counter(owners)
|
189 |
|
190 |
# Get top 30 owners by count
|
191 |
top_owners = owner_counts.most_common(30)
|
192 |
-
|
193 |
return top_owners
|
194 |
|
195 |
# Homepage route
|
@@ -200,7 +206,7 @@ def home():
|
|
200 |
"""
|
201 |
return render_template('index.html')
|
202 |
|
203 |
-
# Zero-GPU spaces API
|
204 |
@app.route('/api/trending-spaces', methods=['GET'])
|
205 |
def trending_spaces():
|
206 |
"""
|
@@ -230,7 +236,7 @@ def trending_spaces():
|
|
230 |
|
231 |
results.append(space_info)
|
232 |
|
233 |
-
# Get owner statistics
|
234 |
top_owners = get_owner_stats(spaces_data.get('all_spaces', []))
|
235 |
|
236 |
return jsonify({
|
@@ -933,7 +939,7 @@ if __name__ == '__main__':
|
|
933 |
</div>
|
934 |
<div class="mac-content">
|
935 |
<div class="stats-header">
|
936 |
-
<div class="stats-title">Top 30 Creators by Count
|
937 |
<button id="statsToggle" class="stats-toggle">Show Stats</button>
|
938 |
</div>
|
939 |
<div id="statsContent" class="stats-content">
|
@@ -1130,7 +1136,7 @@ if __name__ == '__main__':
|
|
1130 |
data: {
|
1131 |
labels: labels,
|
1132 |
datasets: [{
|
1133 |
-
label: 'Number of Spaces',
|
1134 |
data: data,
|
1135 |
backgroundColor: colors,
|
1136 |
borderColor: colors.map(color => color.replace('0.7', '1')),
|
@@ -1303,7 +1309,6 @@ if __name__ == '__main__':
|
|
1303 |
container.appendChild(errorPlaceholder);
|
1304 |
}
|
1305 |
|
1306 |
-
// ์ฌ๊ธฐ์๋ถํฐ ์นด๋ HTML ๊ตฌ์กฐ (Zero-GPU ์ ์ฉ) ๋ ๋๋ง
|
1307 |
function renderGrid(spaces) {
|
1308 |
elements.gridContainer.innerHTML = '';
|
1309 |
|
@@ -1332,12 +1337,11 @@ if __name__ == '__main__':
|
|
1332 |
const headerDiv = document.createElement('div');
|
1333 |
headerDiv.className = 'grid-header';
|
1334 |
|
1335 |
-
|
1336 |
// space-header (์์ + ์ ๋ชฉ + Zero GPU ๋ฐฐ์ง)
|
1337 |
const spaceHeader = document.createElement('div');
|
1338 |
spaceHeader.className = 'space-header';
|
1339 |
|
1340 |
-
// ์์ ๋ฐฐ์ง
|
1341 |
const rankBadge = document.createElement('div');
|
1342 |
rankBadge.className = 'rank-badge';
|
1343 |
rankBadge.textContent = `#${rank}`;
|
@@ -1347,8 +1351,7 @@ if __name__ == '__main__':
|
|
1347 |
const titleWrapper = document.createElement('div');
|
1348 |
titleWrapper.style.display = 'flex';
|
1349 |
titleWrapper.style.alignItems = 'center';
|
1350 |
-
titleWrapper.style.marginLeft = '8px';
|
1351 |
-
|
1352 |
|
1353 |
const titleEl = document.createElement('h3');
|
1354 |
titleEl.className = 'space-title';
|
@@ -1375,10 +1378,10 @@ if __name__ == '__main__':
|
|
1375 |
// ์ผ์ชฝ: rank + author
|
1376 |
const leftMeta = document.createElement('div');
|
1377 |
|
1378 |
-
const
|
1379 |
-
|
1380 |
-
|
1381 |
-
leftMeta.appendChild(
|
1382 |
|
1383 |
const authorSpan = document.createElement('span');
|
1384 |
authorSpan.className = 'author-name';
|
@@ -1680,4 +1683,3 @@ if __name__ == '__main__':
|
|
1680 |
|
1681 |
# Flask ์ฑ ์คํ (ํฌํธ 7860)
|
1682 |
app.run(host='0.0.0.0', port=7860)
|
1683 |
-
|
|
|
32 |
# Function to fetch Zero-GPU (CPU-based) Spaces from Huggingface with pagination
|
33 |
def fetch_trending_spaces(offset=0, limit=72):
|
34 |
"""
|
35 |
+
hardware=cpu ํ๋ผ๋ฏธํฐ๋ฅผ ์ถ๊ฐํ์ฌ
|
36 |
GPU๊ฐ ์๋(=CPU ์ ์ฉ) ์คํ์ด์ค๋ง ํํฐ๋ง
|
37 |
"""
|
38 |
try:
|
|
|
40 |
params = {
|
41 |
"limit": 10000, # ๋ ๋ง์ด ๊ฐ์ ธ์ค๊ธฐ
|
42 |
"hardware": "cpu" # <-- Zero GPU(=CPU) ํํฐ ์ ์ฉ
|
|
|
43 |
}
|
44 |
response = requests.get(url, params=params, timeout=30)
|
45 |
|
|
|
53 |
and space.get('id', '').split('/', 1)[0] != 'None'
|
54 |
]
|
55 |
|
56 |
+
# ์ ์ฒด ๋ชฉ๋ก์ ๋ํด "๊ธ๋ก๋ฒ ๋ญํฌ"๋ฅผ ๋งค๊ธด๋ค (1๋ถํฐ ์์)
|
57 |
+
for i, sp in enumerate(filtered_spaces):
|
58 |
+
sp['global_rank'] = i + 1
|
59 |
+
|
60 |
# Slice according to requested offset and limit
|
61 |
start = min(offset, len(filtered_spaces))
|
62 |
end = min(offset + limit, len(filtered_spaces))
|
|
|
112 |
# Get space details
|
113 |
def get_space_details(space_data, index, offset):
|
114 |
"""
|
|
|
115 |
- description, avatar_url, author_name ๋ฑ ์ถ๊ฐ ํ๋๋ฅผ ์ถ์ถ
|
116 |
+
- rank๋ ํ์ฌ ํ์ด์ง ๋ด offset ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐ
|
117 |
+
(๋จ, Top 500 ๊ณ์ฐ์ global_rank ์ฌ์ฉ)
|
118 |
"""
|
119 |
try:
|
120 |
if '/' in space_data.get('id', ''):
|
|
|
155 |
'description': short_desc,
|
156 |
'avatar_url': avatar_url,
|
157 |
'author_name': author_name,
|
158 |
+
'rank': offset + index + 1 # ํ์ฌ ํ์ด์ง์์์ ํ์์ฉ ๋ญํฌ
|
159 |
}
|
160 |
except Exception as e:
|
161 |
print(f"Error processing space data: {e}")
|
|
|
176 |
# Get owner statistics from all spaces
|
177 |
def get_owner_stats(all_spaces):
|
178 |
"""
|
179 |
+
์์ 500์(global_rank <= 500) ์ด๋ด์ ๋ฐฐ์น๋ ์คํ์ด์ค๋ค์ owner๋ฅผ ์ถ์ถํด,
|
180 |
+
๊ฐ owner๊ฐ ๋ช ๋ฒ ๋ฑ์ฅํ๋์ง ์ผ ๋ค ์์ 30๋ช
๋ง ๋ฐํ
|
181 |
"""
|
182 |
+
# Top 500
|
183 |
+
top_500 = [s for s in all_spaces if s.get('global_rank', 999999) <= 500]
|
184 |
+
|
185 |
owners = []
|
186 |
+
for space in top_500:
|
187 |
if '/' in space.get('id', ''):
|
188 |
owner, _ = space.get('id', '').split('/', 1)
|
189 |
else:
|
190 |
owner = space.get('owner', '')
|
191 |
+
if owner and owner != 'None':
|
|
|
192 |
owners.append(owner)
|
193 |
|
194 |
+
# Count occurrences of each owner in top 500
|
195 |
owner_counts = Counter(owners)
|
196 |
|
197 |
# Get top 30 owners by count
|
198 |
top_owners = owner_counts.most_common(30)
|
|
|
199 |
return top_owners
|
200 |
|
201 |
# Homepage route
|
|
|
206 |
"""
|
207 |
return render_template('index.html')
|
208 |
|
209 |
+
# Zero-GPU spaces API
|
210 |
@app.route('/api/trending-spaces', methods=['GET'])
|
211 |
def trending_spaces():
|
212 |
"""
|
|
|
236 |
|
237 |
results.append(space_info)
|
238 |
|
239 |
+
# Get owner statistics (Top 500 โ Top 30)
|
240 |
top_owners = get_owner_stats(spaces_data.get('all_spaces', []))
|
241 |
|
242 |
return jsonify({
|
|
|
939 |
</div>
|
940 |
<div class="mac-content">
|
941 |
<div class="stats-header">
|
942 |
+
<div class="stats-title">Top 30 Creators by Count in Top 500</div>
|
943 |
<button id="statsToggle" class="stats-toggle">Show Stats</button>
|
944 |
</div>
|
945 |
<div id="statsContent" class="stats-content">
|
|
|
1136 |
data: {
|
1137 |
labels: labels,
|
1138 |
datasets: [{
|
1139 |
+
label: 'Number of Spaces in Top 500',
|
1140 |
data: data,
|
1141 |
backgroundColor: colors,
|
1142 |
borderColor: colors.map(color => color.replace('0.7', '1')),
|
|
|
1309 |
container.appendChild(errorPlaceholder);
|
1310 |
}
|
1311 |
|
|
|
1312 |
function renderGrid(spaces) {
|
1313 |
elements.gridContainer.innerHTML = '';
|
1314 |
|
|
|
1337 |
const headerDiv = document.createElement('div');
|
1338 |
headerDiv.className = 'grid-header';
|
1339 |
|
|
|
1340 |
// space-header (์์ + ์ ๋ชฉ + Zero GPU ๋ฐฐ์ง)
|
1341 |
const spaceHeader = document.createElement('div');
|
1342 |
spaceHeader.className = 'space-header';
|
1343 |
|
1344 |
+
// ์์ ๋ฐฐ์ง
|
1345 |
const rankBadge = document.createElement('div');
|
1346 |
rankBadge.className = 'rank-badge';
|
1347 |
rankBadge.textContent = `#${rank}`;
|
|
|
1351 |
const titleWrapper = document.createElement('div');
|
1352 |
titleWrapper.style.display = 'flex';
|
1353 |
titleWrapper.style.alignItems = 'center';
|
1354 |
+
titleWrapper.style.marginLeft = '8px';
|
|
|
1355 |
|
1356 |
const titleEl = document.createElement('h3');
|
1357 |
titleEl.className = 'space-title';
|
|
|
1378 |
// ์ผ์ชฝ: rank + author
|
1379 |
const leftMeta = document.createElement('div');
|
1380 |
|
1381 |
+
const rankBadge2 = document.createElement('div');
|
1382 |
+
rankBadge2.className = 'rank-badge';
|
1383 |
+
rankBadge2.textContent = `#${rank}`;
|
1384 |
+
leftMeta.appendChild(rankBadge2);
|
1385 |
|
1386 |
const authorSpan = document.createElement('span');
|
1387 |
authorSpan.className = 'author-name';
|
|
|
1683 |
|
1684 |
# Flask ์ฑ ์คํ (ํฌํธ 7860)
|
1685 |
app.run(host='0.0.0.0', port=7860)
|
|