Spaces:
Running
Running
RichardErkhov
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,20 @@
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
-
|
4 |
|
5 |
-
# Initialize Hugging Face API
|
6 |
-
api = HfApi()
|
7 |
-
|
8 |
-
# Constants
|
9 |
-
GGUF_TAG = "gguf"
|
10 |
CHUNK_SIZE = 1000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
# Clickable links function
|
13 |
def clickable(x, which_one):
|
14 |
if x in ["Not Found", "Unknown"]:
|
15 |
return "Not Found"
|
@@ -18,55 +23,40 @@ def clickable(x, which_one):
|
|
18 |
else:
|
19 |
return f'<a target="_blank" href="https://huggingface.co/{which_one}/{x}" style="color: var(--link-text-color); text-decoration: underline;text-decoration-style: dotted;">{x}</a>'
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
grouped["Author Name"] = grouped["Author Name"].apply(lambda x: clickable(x, "models"))
|
56 |
-
return grouped.sort_values(by="Models_Count", ascending=False)
|
57 |
-
|
58 |
-
all_models_df = fetch_models().sort_values(by="Downloads (30d)", ascending=False)
|
59 |
-
authors_df = prepare_authors_df(all_models_df)
|
60 |
-
|
61 |
-
# Calculate totals
|
62 |
-
total_models_count = len(all_models_df)
|
63 |
-
total_downloads = all_models_df["Downloads (30d)"].sum()
|
64 |
-
total_likes = all_models_df["Likes"].sum()
|
65 |
-
|
66 |
-
def apply_model_filters(search_query, min_downloads, min_likes):
|
67 |
-
df = all_models_df.copy()
|
68 |
-
|
69 |
-
# Extract visible text for filtering purposes:
|
70 |
visible_model_id = df["Model ID"].str.extract(r'>(.*?)<')[0]
|
71 |
visible_author_name = df["Author Name"].str.extract(r'>(.*?)<')[0]
|
72 |
|
@@ -86,8 +76,8 @@ def apply_model_filters(search_query, min_downloads, min_likes):
|
|
86 |
|
87 |
return df
|
88 |
|
89 |
-
def filter_models(search_query, min_downloads, min_likes):
|
90 |
-
filtered = apply_model_filters(search_query, min_downloads, min_likes)
|
91 |
return filtered.iloc[:CHUNK_SIZE], CHUNK_SIZE, filtered
|
92 |
|
93 |
def update_model_table(start_idx, filtered_df):
|
@@ -95,7 +85,7 @@ def update_model_table(start_idx, filtered_df):
|
|
95 |
combined_df = filtered_df.iloc[:new_end].copy()
|
96 |
return combined_df, new_end
|
97 |
|
98 |
-
def apply_author_filters(search_query, min_author_downloads, min_author_likes):
|
99 |
df = authors_df.copy()
|
100 |
|
101 |
# Extract visible text for author filtering:
|
@@ -116,22 +106,62 @@ def apply_author_filters(search_query, min_author_downloads, min_author_likes):
|
|
116 |
|
117 |
return df
|
118 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
|
120 |
with gr.Blocks() as demo:
|
121 |
gr.Markdown(f"""
|
122 |
# 🚀GGUF Tracker🚀
|
123 |
Welcome to 🚀**GGUF Tracker**🚀, a live-updating leaderboard for all things GGUF on 🚀Hugging Face.
|
124 |
-
Stats refresh every hour,
|
125 |
|
126 |
By the way, I’m 🚀Richard Erkhov, and you can check out more of what I’m working on at my [🌟**github**](https://github.com/RichardErkhov),
|
127 |
[🌟**huggingface**](https://huggingface.co/RichardErkhov) or [🌟**erkhov.com**](https://erkhov.com). Go take a look—I think you’ll like what you find.
|
128 |
""")
|
129 |
|
130 |
-
gr.Markdown(
|
131 |
-
|
132 |
-
**Total Models:** {total_models_count} | **Total Downloads (30d):** {total_downloads} | **Total Likes:** {total_likes}
|
133 |
-
""")
|
134 |
-
|
135 |
with gr.Tabs():
|
136 |
with gr.TabItem("Models"):
|
137 |
with gr.Row():
|
@@ -149,13 +179,13 @@ with gr.Blocks() as demo:
|
|
149 |
)
|
150 |
load_more_button = gr.Button("Load More Models")
|
151 |
|
152 |
-
# States
|
153 |
start_idx = gr.State(value=CHUNK_SIZE)
|
154 |
-
filtered_df_state = gr.State(value=all_models_df)
|
155 |
|
156 |
filter_button.click(
|
157 |
fn=filter_models,
|
158 |
-
inputs=[search_query, min_downloads, min_likes],
|
159 |
outputs=[model_table, start_idx, filtered_df_state]
|
160 |
)
|
161 |
load_more_button.click(fn=update_model_table, inputs=[start_idx, filtered_df_state], outputs=[model_table, start_idx])
|
@@ -175,14 +205,32 @@ with gr.Blocks() as demo:
|
|
175 |
datatype=["markdown", "number", "number", "number"]
|
176 |
)
|
177 |
|
178 |
-
def filter_authors(author_search_query, min_author_downloads, min_author_likes):
|
179 |
-
filtered_authors = apply_author_filters(author_search_query, min_author_downloads, min_author_likes)
|
180 |
-
return filtered_authors
|
181 |
-
|
182 |
author_filter_button.click(
|
183 |
fn=filter_authors,
|
184 |
-
inputs=[author_search_query, min_author_downloads, min_author_likes],
|
185 |
outputs=author_table
|
186 |
)
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
+
import requests
|
4 |
|
|
|
|
|
|
|
|
|
|
|
5 |
CHUNK_SIZE = 1000
|
6 |
+
DATA_URL = "https://erkhov.com/huggingspace_data"
|
7 |
+
TIME_URL = "https://erkhov.com/huggingspace_time"
|
8 |
+
|
9 |
+
def fetch_time():
|
10 |
+
response = requests.get(TIME_URL)
|
11 |
+
return response.text.strip() # assume the endpoint returns a raw timestamp or numeric value as string
|
12 |
+
|
13 |
+
def fetch_data():
|
14 |
+
response = requests.get(DATA_URL)
|
15 |
+
data = response.json()
|
16 |
+
return data
|
17 |
|
|
|
18 |
def clickable(x, which_one):
|
19 |
if x in ["Not Found", "Unknown"]:
|
20 |
return "Not Found"
|
|
|
23 |
else:
|
24 |
return f'<a target="_blank" href="https://huggingface.co/{which_one}/{x}" style="color: var(--link-text-color); text-decoration: underline;text-decoration-style: dotted;">{x}</a>'
|
25 |
|
26 |
+
def create_dataframes(data):
|
27 |
+
models_data = data["models"]
|
28 |
+
authors_data = data["authors"]
|
29 |
+
|
30 |
+
# Create DataFrame for models
|
31 |
+
models_df = pd.DataFrame(models_data)
|
32 |
+
models_df.rename(columns={
|
33 |
+
"id": "Model ID",
|
34 |
+
"author": "Author Name",
|
35 |
+
"downloads": "Downloads (30d)",
|
36 |
+
"likes": "Likes",
|
37 |
+
"created_at": "Created At",
|
38 |
+
"last_modified": "Last Modified"
|
39 |
+
}, inplace=True)
|
40 |
+
models_df["Model ID"] = models_df["Model ID"].apply(lambda x: clickable(x, "models"))
|
41 |
+
models_df["Author Name"] = models_df["Author Name"].apply(lambda x: clickable(x, "models"))
|
42 |
+
models_df = models_df.sort_values(by="Downloads (30d)", ascending=False)
|
43 |
+
|
44 |
+
# Create DataFrame for authors
|
45 |
+
authors_df = pd.DataFrame(authors_data)
|
46 |
+
authors_df.rename(columns={
|
47 |
+
"author": "Author Name",
|
48 |
+
"models_count": "Models_Count",
|
49 |
+
"downloads": "Total_Downloads",
|
50 |
+
"likes": "Total_Likes"
|
51 |
+
}, inplace=True)
|
52 |
+
authors_df["Author Name"] = authors_df["Author Name"].apply(lambda x: clickable(x, "models"))
|
53 |
+
authors_df = authors_df.sort_values(by="Models_Count", ascending=False)
|
54 |
+
|
55 |
+
return models_df, authors_df
|
56 |
+
|
57 |
+
def apply_model_filters(models_df, search_query, min_downloads, min_likes):
|
58 |
+
df = models_df.copy()
|
59 |
+
# Extract visible text for filtering
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
visible_model_id = df["Model ID"].str.extract(r'>(.*?)<')[0]
|
61 |
visible_author_name = df["Author Name"].str.extract(r'>(.*?)<')[0]
|
62 |
|
|
|
76 |
|
77 |
return df
|
78 |
|
79 |
+
def filter_models(models_df, search_query, min_downloads, min_likes):
|
80 |
+
filtered = apply_model_filters(models_df, search_query, min_downloads, min_likes)
|
81 |
return filtered.iloc[:CHUNK_SIZE], CHUNK_SIZE, filtered
|
82 |
|
83 |
def update_model_table(start_idx, filtered_df):
|
|
|
85 |
combined_df = filtered_df.iloc[:new_end].copy()
|
86 |
return combined_df, new_end
|
87 |
|
88 |
+
def apply_author_filters(authors_df, search_query, min_author_downloads, min_author_likes):
|
89 |
df = authors_df.copy()
|
90 |
|
91 |
# Extract visible text for author filtering:
|
|
|
106 |
|
107 |
return df
|
108 |
|
109 |
+
def filter_authors(authors_df, author_search_query, min_author_downloads, min_author_likes):
|
110 |
+
filtered_authors = apply_author_filters(authors_df, author_search_query, min_author_downloads, min_author_likes)
|
111 |
+
return filtered_authors
|
112 |
+
|
113 |
+
def refresh_data(last_time, models_df_state, authors_df_state, stats_markdown, model_table, author_table):
|
114 |
+
# Check if time changed
|
115 |
+
current_time = fetch_time()
|
116 |
+
if current_time != last_time and current_time != 0:
|
117 |
+
# Time changed, re-fetch data
|
118 |
+
data = fetch_data()
|
119 |
+
models_df, authors_df = create_dataframes(data)
|
120 |
+
|
121 |
+
total_models_count = data["total_models"]
|
122 |
+
total_downloads = data["total_downloads"]
|
123 |
+
total_likes = models_df["Likes"].sum() if "Likes" in models_df.columns else 0
|
124 |
+
|
125 |
+
# Update stats markdown
|
126 |
+
new_stats_markdown = f"""
|
127 |
+
# GGUF Models and Authors Leaderboard
|
128 |
+
**Total Models:** {total_models_count} | **Total Downloads (30d):** {total_downloads} | **Total Likes:** {total_likes}
|
129 |
+
**Last Updated:** {current_time}
|
130 |
+
"""
|
131 |
+
|
132 |
+
# Update states
|
133 |
+
return current_time, models_df, authors_df, gr.update(value=new_stats_markdown), gr.update(value=models_df.iloc[:CHUNK_SIZE]), gr.update(value=authors_df)
|
134 |
+
else:
|
135 |
+
# No change
|
136 |
+
return last_time, models_df_state, authors_df_state, stats_markdown, model_table, author_table
|
137 |
+
|
138 |
+
# Initial fetch
|
139 |
+
initial_time = fetch_time()
|
140 |
+
data = fetch_data()
|
141 |
+
all_models_df, authors_df = create_dataframes(data)
|
142 |
+
|
143 |
+
total_models_count = data["total_models"]
|
144 |
+
total_downloads = data["total_downloads"]
|
145 |
+
total_likes = all_models_df["Likes"].sum() if "Likes" in all_models_df.columns else 0
|
146 |
+
|
147 |
+
initial_stats_markdown = f"""
|
148 |
+
# GGUF Models and Authors Leaderboard
|
149 |
+
**Total Models:** {total_models_count} | **Total Downloads (30d):** {total_downloads} | **Total Likes:** {total_likes}
|
150 |
+
**Last Updated:** {initial_time}
|
151 |
+
"""
|
152 |
|
153 |
with gr.Blocks() as demo:
|
154 |
gr.Markdown(f"""
|
155 |
# 🚀GGUF Tracker🚀
|
156 |
Welcome to 🚀**GGUF Tracker**🚀, a live-updating leaderboard for all things GGUF on 🚀Hugging Face.
|
157 |
+
Stats refresh every hour on the backend, but this interface checks every 5 minutes for updates.
|
158 |
|
159 |
By the way, I’m 🚀Richard Erkhov, and you can check out more of what I’m working on at my [🌟**github**](https://github.com/RichardErkhov),
|
160 |
[🌟**huggingface**](https://huggingface.co/RichardErkhov) or [🌟**erkhov.com**](https://erkhov.com). Go take a look—I think you’ll like what you find.
|
161 |
""")
|
162 |
|
163 |
+
stats_markdown = gr.Markdown(initial_stats_markdown)
|
164 |
+
|
|
|
|
|
|
|
165 |
with gr.Tabs():
|
166 |
with gr.TabItem("Models"):
|
167 |
with gr.Row():
|
|
|
179 |
)
|
180 |
load_more_button = gr.Button("Load More Models")
|
181 |
|
182 |
+
# States for models
|
183 |
start_idx = gr.State(value=CHUNK_SIZE)
|
184 |
+
filtered_df_state = gr.State(value=all_models_df)
|
185 |
|
186 |
filter_button.click(
|
187 |
fn=filter_models,
|
188 |
+
inputs=[filtered_df_state, search_query, min_downloads, min_likes],
|
189 |
outputs=[model_table, start_idx, filtered_df_state]
|
190 |
)
|
191 |
load_more_button.click(fn=update_model_table, inputs=[start_idx, filtered_df_state], outputs=[model_table, start_idx])
|
|
|
205 |
datatype=["markdown", "number", "number", "number"]
|
206 |
)
|
207 |
|
|
|
|
|
|
|
|
|
208 |
author_filter_button.click(
|
209 |
fn=filter_authors,
|
210 |
+
inputs=[authors_df, author_search_query, min_author_downloads, min_author_likes],
|
211 |
outputs=author_table
|
212 |
)
|
213 |
|
214 |
+
# States for refresh
|
215 |
+
last_hf_time_state = gr.State(value=initial_time)
|
216 |
+
models_df_state = gr.State(value=all_models_df)
|
217 |
+
authors_df_state = gr.State(value=authors_df)
|
218 |
+
|
219 |
+
# Timer to check every 5 minutes = 300 seconds
|
220 |
+
timer = gr.Timer(interval=300, fn=refresh_data, inputs=[
|
221 |
+
last_hf_time_state,
|
222 |
+
models_df_state,
|
223 |
+
authors_df_state,
|
224 |
+
stats_markdown,
|
225 |
+
model_table,
|
226 |
+
author_table
|
227 |
+
], outputs=[
|
228 |
+
last_hf_time_state,
|
229 |
+
models_df_state,
|
230 |
+
authors_df_state,
|
231 |
+
stats_markdown,
|
232 |
+
model_table,
|
233 |
+
author_table
|
234 |
+
])
|
235 |
+
|
236 |
demo.launch()
|