Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# --- START OF FINAL
|
| 2 |
|
| 3 |
import gradio as gr
|
| 4 |
import pandas as pd
|
|
@@ -17,48 +17,49 @@ TAG_FILTER_CHOICES = [ "Audio & Speech", "Time series", "Robotics", "Music", "Vi
|
|
| 17 |
PIPELINE_TAGS = [ 'text-generation', 'text-to-image', 'text-classification', 'text2text-generation', 'audio-to-audio', 'feature-extraction', 'image-classification', 'translation', 'reinforcement-learning', 'fill-mask', 'text-to-speech', 'automatic-speech-recognition', 'image-text-to-text', 'token-classification', 'sentence-similarity', 'question-answering', 'image-feature-extraction', 'summarization', 'zero-shot-image-classification', 'object-detection', 'image-segmentation', 'image-to-image', 'image-to-text', 'audio-classification', 'visual-question-answering', 'text-to-video', 'zero-shot-classification', 'depth-estimation', 'text-ranking', 'image-to-video', 'multiple-choice', 'unconditional-image-generation', 'video-classification', 'text-to-audio', 'time-series-forecasting', 'any-to-any', 'video-text-to-text', 'table-question-answering' ]
|
| 18 |
|
| 19 |
# --- Custom HTML, CSS, and JavaScript for the Slider ---
|
|
|
|
| 20 |
custom_slider_js = """
|
| 21 |
-
function createCustomSlider() {
|
| 22 |
-
const paramChoices =
|
| 23 |
const slider = document.getElementById('noui-slider-container');
|
| 24 |
-
if (slider.noUiSlider) {
|
| 25 |
slider.noUiSlider.destroy();
|
| 26 |
-
}
|
| 27 |
-
noUiSlider.create(slider, {
|
| 28 |
start: [0, paramChoices.length - 1],
|
| 29 |
connect: true,
|
| 30 |
step: 1,
|
| 31 |
-
range: { 'min': 0, 'max': paramChoices.length - 1 },
|
| 32 |
-
pips: {
|
| 33 |
mode: 'values',
|
| 34 |
values: Array.from(Array(paramChoices.length).keys()),
|
| 35 |
density: 100 / (paramChoices.length - 1),
|
| 36 |
-
format: { to: function(value) { return paramChoices[value]; } }
|
| 37 |
-
}
|
| 38 |
-
});
|
| 39 |
|
| 40 |
const paramRangeStateInput = document.querySelector('#param-range-state-js textarea');
|
| 41 |
-
slider.noUiSlider.on('update', function (values) {
|
| 42 |
const intValues = values.map(v => parseInt(v, 10));
|
| 43 |
const newValue = JSON.stringify(intValues);
|
| 44 |
-
if (paramRangeStateInput.value !== newValue) {
|
| 45 |
paramRangeStateInput.value = newValue;
|
| 46 |
-
const event = new Event('input', { bubbles: true });
|
| 47 |
paramRangeStateInput.dispatchEvent(event);
|
| 48 |
-
}
|
| 49 |
-
});
|
| 50 |
|
| 51 |
-
function highlightPips(values) {
|
| 52 |
const intValues = values.map(v => parseInt(v, 10));
|
| 53 |
-
document.querySelectorAll('.noUi-value').forEach((pip, index) => {
|
| 54 |
const pipIsSelected = index >= intValues[0] && index <= intValues[1];
|
| 55 |
pip.style.fontWeight = pipIsSelected ? 'bold' : 'normal';
|
| 56 |
pip.style.color = pipIsSelected ? '#000' : '#777';
|
| 57 |
-
});
|
| 58 |
-
}
|
| 59 |
slider.noUiSlider.on('update', highlightPips);
|
| 60 |
highlightPips([0, paramChoices.length - 1]);
|
| 61 |
-
}
|
| 62 |
"""
|
| 63 |
|
| 64 |
def load_models_data():
|
|
@@ -103,7 +104,7 @@ def make_treemap_data(df, count_by, top_k=25, tag_filter=None, pipeline_filter=N
|
|
| 103 |
filtered_df = filtered_df[~filtered_df["organization"].isin(skip_orgs)]
|
| 104 |
if filtered_df.empty: return pd.DataFrame()
|
| 105 |
if count_by not in filtered_df.columns: filtered_df[count_by] = 0.0
|
| 106 |
-
filtered_df[count_by] = pd.to_numeric(filtered_df[count_by], errors=
|
| 107 |
org_totals = filtered_df.groupby("organization")[count_by].sum().nlargest(top_k, keep='first')
|
| 108 |
top_orgs_list = org_totals.index.tolist()
|
| 109 |
treemap_data = filtered_df[filtered_df["organization"].isin(top_orgs_list)][["id", "organization", count_by]].copy()
|
|
@@ -125,12 +126,9 @@ custom_head = """
|
|
| 125 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js"></script>
|
| 126 |
"""
|
| 127 |
|
| 128 |
-
# --- MODIFIED: Added emoji to the browser tab title ---
|
| 129 |
with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_head) as demo:
|
| 130 |
models_data_state = gr.State(pd.DataFrame())
|
| 131 |
loading_complete_state = gr.State(False)
|
| 132 |
-
|
| 133 |
-
# --- MODIFIED: Removed the main title from the page body for a cleaner look ---
|
| 134 |
|
| 135 |
with gr.Row():
|
| 136 |
with gr.Column(scale=1):
|
|
@@ -221,8 +219,15 @@ with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_he
|
|
| 221 |
plot_stats_md = f"## Plot Statistics\n- **Models shown**: {total_items_in_plot:,}\n- **Total {metric_choice}**: {int(total_value_in_plot):,}"
|
| 222 |
return plotly_fig, plot_stats_md
|
| 223 |
|
| 224 |
-
demo.load(
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
generate_plot_button.click(
|
| 228 |
fn=ui_generate_plot_controller,
|
|
@@ -235,4 +240,4 @@ if __name__ == "__main__":
|
|
| 235 |
print(f"Application starting...")
|
| 236 |
demo.queue().launch()
|
| 237 |
|
| 238 |
-
# --- END OF FINAL
|
|
|
|
| 1 |
+
# --- START OF FINAL, CORRECTED FILE app.py ---
|
| 2 |
|
| 3 |
import gradio as gr
|
| 4 |
import pandas as pd
|
|
|
|
| 17 |
PIPELINE_TAGS = [ 'text-generation', 'text-to-image', 'text-classification', 'text2text-generation', 'audio-to-audio', 'feature-extraction', 'image-classification', 'translation', 'reinforcement-learning', 'fill-mask', 'text-to-speech', 'automatic-speech-recognition', 'image-text-to-text', 'token-classification', 'sentence-similarity', 'question-answering', 'image-feature-extraction', 'summarization', 'zero-shot-image-classification', 'object-detection', 'image-segmentation', 'image-to-image', 'image-to-text', 'audio-classification', 'visual-question-answering', 'text-to-video', 'zero-shot-classification', 'depth-estimation', 'text-ranking', 'image-to-video', 'multiple-choice', 'unconditional-image-generation', 'video-classification', 'text-to-audio', 'time-series-forecasting', 'any-to-any', 'video-text-to-text', 'table-question-answering' ]
|
| 18 |
|
| 19 |
# --- Custom HTML, CSS, and JavaScript for the Slider ---
|
| 20 |
+
# Using a placeholder for the choices to be safely injected from Python
|
| 21 |
custom_slider_js = """
|
| 22 |
+
function createCustomSlider() {{
|
| 23 |
+
const paramChoices = {js_param_choices}; // This will be replaced by Python
|
| 24 |
const slider = document.getElementById('noui-slider-container');
|
| 25 |
+
if (slider.noUiSlider) {{
|
| 26 |
slider.noUiSlider.destroy();
|
| 27 |
+
}}
|
| 28 |
+
noUiSlider.create(slider, {{
|
| 29 |
start: [0, paramChoices.length - 1],
|
| 30 |
connect: true,
|
| 31 |
step: 1,
|
| 32 |
+
range: {{ 'min': 0, 'max': paramChoices.length - 1 }},
|
| 33 |
+
pips: {{
|
| 34 |
mode: 'values',
|
| 35 |
values: Array.from(Array(paramChoices.length).keys()),
|
| 36 |
density: 100 / (paramChoices.length - 1),
|
| 37 |
+
format: {{ to: function(value) {{ return paramChoices[value]; }} }}
|
| 38 |
+
}}
|
| 39 |
+
}});
|
| 40 |
|
| 41 |
const paramRangeStateInput = document.querySelector('#param-range-state-js textarea');
|
| 42 |
+
slider.noUiSlider.on('update', function (values) {{
|
| 43 |
const intValues = values.map(v => parseInt(v, 10));
|
| 44 |
const newValue = JSON.stringify(intValues);
|
| 45 |
+
if (paramRangeStateInput.value !== newValue) {{
|
| 46 |
paramRangeStateInput.value = newValue;
|
| 47 |
+
const event = new Event('input', {{ bubbles: true }});
|
| 48 |
paramRangeStateInput.dispatchEvent(event);
|
| 49 |
+
}}
|
| 50 |
+
}});
|
| 51 |
|
| 52 |
+
function highlightPips(values) {{
|
| 53 |
const intValues = values.map(v => parseInt(v, 10));
|
| 54 |
+
document.querySelectorAll('.noUi-value').forEach((pip, index) => {{
|
| 55 |
const pipIsSelected = index >= intValues[0] && index <= intValues[1];
|
| 56 |
pip.style.fontWeight = pipIsSelected ? 'bold' : 'normal';
|
| 57 |
pip.style.color = pipIsSelected ? '#000' : '#777';
|
| 58 |
+
}});
|
| 59 |
+
}}
|
| 60 |
slider.noUiSlider.on('update', highlightPips);
|
| 61 |
highlightPips([0, paramChoices.length - 1]);
|
| 62 |
+
}}
|
| 63 |
"""
|
| 64 |
|
| 65 |
def load_models_data():
|
|
|
|
| 104 |
filtered_df = filtered_df[~filtered_df["organization"].isin(skip_orgs)]
|
| 105 |
if filtered_df.empty: return pd.DataFrame()
|
| 106 |
if count_by not in filtered_df.columns: filtered_df[count_by] = 0.0
|
| 107 |
+
filtered_df[count_by] = pd.to_numeric(filtered_df[count_by], errors='coerce').fillna(0.0)
|
| 108 |
org_totals = filtered_df.groupby("organization")[count_by].sum().nlargest(top_k, keep='first')
|
| 109 |
top_orgs_list = org_totals.index.tolist()
|
| 110 |
treemap_data = filtered_df[filtered_df["organization"].isin(top_orgs_list)][["id", "organization", count_by]].copy()
|
|
|
|
| 126 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js"></script>
|
| 127 |
"""
|
| 128 |
|
|
|
|
| 129 |
with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_head) as demo:
|
| 130 |
models_data_state = gr.State(pd.DataFrame())
|
| 131 |
loading_complete_state = gr.State(False)
|
|
|
|
|
|
|
| 132 |
|
| 133 |
with gr.Row():
|
| 134 |
with gr.Column(scale=1):
|
|
|
|
| 219 |
plot_stats_md = f"## Plot Statistics\n- **Models shown**: {total_items_in_plot:,}\n- **Total {metric_choice}**: {int(total_value_in_plot):,}"
|
| 220 |
return plotly_fig, plot_stats_md
|
| 221 |
|
| 222 |
+
# --- FINAL FIX: Use the `js` parameter in demo.load() instead of the deprecated `_js` in .then() ---
|
| 223 |
+
# We also safely format the Python list into a JS array using json.dumps
|
| 224 |
+
final_js = custom_slider_js.format(js_param_choices=json.dumps(PARAM_CHOICES))
|
| 225 |
+
demo.load(
|
| 226 |
+
fn=ui_load_data_controller,
|
| 227 |
+
inputs=[],
|
| 228 |
+
outputs=[models_data_state, loading_complete_state, data_info_md, status_message_md],
|
| 229 |
+
js=f"() => {{ {final_js} }}" # Wrap the JS in a function to be executed on load
|
| 230 |
+
)
|
| 231 |
|
| 232 |
generate_plot_button.click(
|
| 233 |
fn=ui_generate_plot_controller,
|
|
|
|
| 240 |
print(f"Application starting...")
|
| 241 |
demo.queue().launch()
|
| 242 |
|
| 243 |
+
# --- END OF FINAL, CORRECTED FILE app.py ---
|