Spaces:
Sleeping
Sleeping
Commit
·
c5fed00
1
Parent(s):
8b23f41
implement basic structure by resource type
Browse files- .gitignore +2 -1
- app.py +53 -57
- datasets_resource.py +178 -0
- events_resource.py +178 -0
- initiatives_resource.py +178 -0
- models_resource.py +178 -0
- requirements.txt +3 -0
- shared_tasks_resource.py +178 -0
.gitignore
CHANGED
|
@@ -1 +1,2 @@
|
|
| 1 |
-
venv
|
|
|
|
|
|
| 1 |
+
venv/
|
| 2 |
+
__pycache__/
|
app.py
CHANGED
|
@@ -1,68 +1,64 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
import pandas as pd
|
| 3 |
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
|
|
|
|
|
|
| 6 |
|
| 7 |
-
|
| 8 |
-
if search_query == "":
|
| 9 |
-
return df
|
| 10 |
-
else:
|
| 11 |
-
# Filter the dataframe based on the search query
|
| 12 |
-
filtered_df = df[
|
| 13 |
-
df.apply(
|
| 14 |
-
lambda row: row.astype(str)
|
| 15 |
-
.str.contains(search_query, case=False)
|
| 16 |
-
.any(),
|
| 17 |
-
axis=1,
|
| 18 |
-
)
|
| 19 |
-
]
|
| 20 |
-
return filtered_df
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
with gr.Blocks() as app:
|
| 24 |
-
|
| 25 |
gr.Markdown(
|
| 26 |
"""
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
)
|
| 34 |
-
with gr.Accordion(label="Leer más", open=False, visible=False):
|
| 35 |
-
gr.Markdown(
|
| 36 |
-
"""
|
| 37 |
-
En los últimos años han surgido iniciativas para impulsar el PLN en español. El objetivo de esta lista es dar a conocer los recursos creados por estas iniciativas y facilitar la formación de personas apasionadas por el PLN en todo el mundo.
|
| 38 |
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
Estructura:
|
| 42 |
-
- Recurso: Nombre del recurso
|
| 43 |
-
- Categoría: Charla, taller aplicado, notebook, artículo de blog
|
| 44 |
-
- Etiqueta: LLM, traducción, ética, ...
|
| 45 |
-
- Creado por: Organización o persona que lo ha creado/organizado
|
| 46 |
-
- Web: Página web del recurso
|
| 47 |
-
"""
|
| 48 |
-
)
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
)
|
| 56 |
-
with gr.Row():
|
| 57 |
-
table = gr.Dataframe(
|
| 58 |
-
value=df,
|
| 59 |
-
label="Recursos de PLN en español",
|
| 60 |
-
show_label=False,
|
| 61 |
-
interactive=False,
|
| 62 |
-
wrap=False,
|
| 63 |
-
# column_widths=["30%", "15%", "20%", "15%", "15%"],
|
| 64 |
-
)
|
| 65 |
-
search_box.change(fn=update_table, inputs=search_box, outputs=table)
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
-
app
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
|
| 3 |
+
# Import the resource type modules
|
| 4 |
+
import datasets_resource
|
| 5 |
+
import events_resource
|
| 6 |
+
import initiatives_resource
|
| 7 |
+
import models_resource
|
| 8 |
+
import shared_tasks_resource
|
| 9 |
|
| 10 |
+
# Create the main Gradio interface
|
| 11 |
+
with gr.Blocks(title="Recursos de PLN en español", theme=gr.themes.Soft()) as app:
|
| 12 |
|
| 13 |
+
# Header
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
gr.Markdown(
|
| 15 |
"""
|
| 16 |
+
# 🚀 Recursos de PLN en español
|
| 17 |
+
|
| 18 |
+
Descubre y contribuye con recursos gratuitos online de PLN en español.
|
| 19 |
+
|
| 20 |
+
Explora datasets, modelos, tareas compartidas, eventos e iniciativas. ¡Ayúdanos a expandir esta colección para hacerla lo más completa posible!
|
| 21 |
+
"""
|
| 22 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
# Main tabs for resource types
|
| 25 |
+
with gr.Tabs() as main_tabs:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
+
# Create tabs for each resource type
|
| 28 |
+
datasets_tab = datasets_resource.create_tab()
|
| 29 |
+
models_tab = models_resource.create_tab()
|
| 30 |
+
shared_tasks_tab = shared_tasks_resource.create_tab()
|
| 31 |
+
events_tab = events_resource.create_tab()
|
| 32 |
+
initiatives_tab = initiatives_resource.create_tab()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
+
# Footer
|
| 35 |
+
gr.Markdown(
|
| 36 |
+
"""
|
| 37 |
+
---
|
| 38 |
+
|
| 39 |
+
### 📖 About
|
| 40 |
+
|
| 41 |
+
Esta plataforma forma parte de la iniciativa [SomosNLP](https://somosnlp.org) para democratizar el acceso
|
| 42 |
+
a recursos de procesamiento de lenguaje natural en español.
|
| 43 |
+
|
| 44 |
+
**¿Cómo contribuir?**
|
| 45 |
+
1. Ve a la pestaña del tipo de recurso que quieras añadir
|
| 46 |
+
2. Haz clic en la sub-pestaña "Contribute"
|
| 47 |
+
3. Haz login con tu cuenta de Hugging Face
|
| 48 |
+
4. Rellena el formulario con la información del recurso
|
| 49 |
+
5. ¡Envía tu contribución!
|
| 50 |
+
|
| 51 |
+
Los recursos enviados se almacenan en datasets públicos de Hugging Face y están disponibles para toda la comunidad.
|
| 52 |
+
|
| 53 |
+
**Tipos de recursos:**
|
| 54 |
+
- **Datasets**: Conjuntos de datos para entrenar y evaluar modelos de PLN
|
| 55 |
+
- **Models**: Modelos pre-entrenados y fine-tuned para tareas de PLN
|
| 56 |
+
- **Shared Tasks**: Competiciones y evaluaciones compartidas
|
| 57 |
+
- **Events**: Conferencias, workshops, charlas y eventos relacionados con PLN
|
| 58 |
+
- **Initiatives**: Proyectos, organizaciones e iniciativas que impulsan el PLN en español
|
| 59 |
+
"""
|
| 60 |
+
)
|
| 61 |
|
| 62 |
+
# Launch the app
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
app.launch(share=False, server_name="0.0.0.0", server_port=7860)
|
datasets_resource.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timezone
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from datasets import Dataset, load_dataset
|
| 6 |
+
|
| 7 |
+
# Dataset configuration
|
| 8 |
+
DATASET_NAME = "somosnlp/recursos-pln-es-datasets"
|
| 9 |
+
RESOURCE_TYPE = "datasets"
|
| 10 |
+
RESOURCE_TITLE = "Datasets"
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_data() -> pd.DataFrame:
|
| 14 |
+
"""Load data from HuggingFace dataset or return empty DataFrame."""
|
| 15 |
+
try:
|
| 16 |
+
dataset = load_dataset(DATASET_NAME, split="train")
|
| 17 |
+
return dataset.to_pandas()
|
| 18 |
+
except Exception as e:
|
| 19 |
+
print(f"Could not load {RESOURCE_TYPE} dataset: {e}")
|
| 20 |
+
# Return empty DataFrame with required columns
|
| 21 |
+
return pd.DataFrame(
|
| 22 |
+
columns=["name", "url", "country", "submitted_by", "date_submitted"]
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def search_and_filter_data(df: pd.DataFrame, search_query: str) -> pd.DataFrame:
|
| 27 |
+
"""Filter dataframe based on search query."""
|
| 28 |
+
if search_query == "":
|
| 29 |
+
return df
|
| 30 |
+
else:
|
| 31 |
+
filtered_df = df[
|
| 32 |
+
df.apply(
|
| 33 |
+
lambda row: row.astype(str)
|
| 34 |
+
.str.contains(search_query, case=False)
|
| 35 |
+
.any(),
|
| 36 |
+
axis=1,
|
| 37 |
+
)
|
| 38 |
+
]
|
| 39 |
+
return filtered_df
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def check_login(profile: gr.OAuthProfile | None) -> bool:
|
| 43 |
+
"""Check if a user is logged in."""
|
| 44 |
+
return profile is not None
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def submit_resource(name: str, url: str, country: str, profile: gr.OAuthProfile | None):
|
| 48 |
+
"""Submit a new resource to the corresponding dataset."""
|
| 49 |
+
|
| 50 |
+
# Check if user is logged in
|
| 51 |
+
if not check_login(profile):
|
| 52 |
+
return "❌ Error: You need to be logged in to submit a resource."
|
| 53 |
+
|
| 54 |
+
# Validate inputs
|
| 55 |
+
if not name or not url or not country:
|
| 56 |
+
return "❌ Error: All fields (name, url, country) are required."
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
username = profile.username
|
| 60 |
+
current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 61 |
+
|
| 62 |
+
# Create new row data
|
| 63 |
+
new_data = {
|
| 64 |
+
"name": name,
|
| 65 |
+
"url": url,
|
| 66 |
+
"country": country,
|
| 67 |
+
"submitted_by": username,
|
| 68 |
+
"date_submitted": current_time,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Try to load existing dataset, or create new one
|
| 72 |
+
try:
|
| 73 |
+
existing_dataset = load_dataset(DATASET_NAME, split="train")
|
| 74 |
+
existing_df = existing_dataset.to_pandas()
|
| 75 |
+
# Add new row
|
| 76 |
+
updated_df = pd.concat(
|
| 77 |
+
[existing_df, pd.DataFrame([new_data])], ignore_index=True
|
| 78 |
+
)
|
| 79 |
+
except:
|
| 80 |
+
# Create new dataset if it doesn't exist
|
| 81 |
+
updated_df = pd.DataFrame([new_data])
|
| 82 |
+
|
| 83 |
+
# Convert back to Dataset and push to hub
|
| 84 |
+
updated_dataset = Dataset.from_pandas(updated_df)
|
| 85 |
+
updated_dataset.push_to_hub(
|
| 86 |
+
DATASET_NAME,
|
| 87 |
+
commit_message=f"Add {name} by {username}",
|
| 88 |
+
token=True, # Use the user's token
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
return f"✅ Success: {name} has been submitted successfully!"
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
return f"❌ Error: Failed to submit resource. {str(e)}"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def create_all_tab():
|
| 98 |
+
"""Create the 'All' tab for this resource type."""
|
| 99 |
+
with gr.TabItem("📋 All", id=f"{RESOURCE_TYPE}_all"):
|
| 100 |
+
gr.Markdown(f"### All {RESOURCE_TITLE}")
|
| 101 |
+
|
| 102 |
+
search_box = gr.Textbox(
|
| 103 |
+
placeholder=f"Search {RESOURCE_TYPE}...",
|
| 104 |
+
label="Filter the table",
|
| 105 |
+
show_label=False,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
# Load initial data
|
| 109 |
+
initial_df = load_data()
|
| 110 |
+
|
| 111 |
+
table = gr.Dataframe(
|
| 112 |
+
value=initial_df,
|
| 113 |
+
label=RESOURCE_TITLE,
|
| 114 |
+
show_label=False,
|
| 115 |
+
interactive=False,
|
| 116 |
+
wrap=True,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Connect search functionality
|
| 120 |
+
search_box.change(
|
| 121 |
+
fn=lambda query: search_and_filter_data(initial_df, query),
|
| 122 |
+
inputs=search_box,
|
| 123 |
+
outputs=table,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Refresh button to reload data
|
| 127 |
+
refresh_btn = gr.Button("🔄 Refresh Data", variant="secondary")
|
| 128 |
+
refresh_btn.click(fn=lambda: load_data(), outputs=table)
|
| 129 |
+
|
| 130 |
+
return table
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_contribute_tab():
|
| 134 |
+
"""Create the 'Contribute' tab for this resource type."""
|
| 135 |
+
with gr.TabItem("➕ Contribute", id=f"{RESOURCE_TYPE}_contribute"):
|
| 136 |
+
gr.Markdown(f"### Contribute a New {RESOURCE_TITLE[:-1]}")
|
| 137 |
+
|
| 138 |
+
# Login section
|
| 139 |
+
gr.Markdown("Please log in to contribute resources:")
|
| 140 |
+
login_button = gr.LoginButton(elem_id=f"{RESOURCE_TYPE}-oauth-button")
|
| 141 |
+
|
| 142 |
+
gr.Markdown("Please fill in the information below to add a new dataset:")
|
| 143 |
+
|
| 144 |
+
with gr.Column():
|
| 145 |
+
name_input = gr.Textbox(
|
| 146 |
+
label="Name",
|
| 147 |
+
placeholder="Enter the name of the dataset",
|
| 148 |
+
info="The name or title of the resource",
|
| 149 |
+
)
|
| 150 |
+
url_input = gr.Textbox(
|
| 151 |
+
label="URL", placeholder="https://...", info="Link to the resource"
|
| 152 |
+
)
|
| 153 |
+
country_input = gr.Textbox(
|
| 154 |
+
label="Country",
|
| 155 |
+
placeholder="e.g., Spain, Mexico, Argentina",
|
| 156 |
+
info="Country of origin or primary focus",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
submit_btn = gr.Button(f"Submit {RESOURCE_TITLE[:-1]}", variant="primary")
|
| 160 |
+
result_msg = gr.Markdown()
|
| 161 |
+
|
| 162 |
+
# Submit function
|
| 163 |
+
submit_btn.click(
|
| 164 |
+
fn=submit_resource,
|
| 165 |
+
inputs=[name_input, url_input, country_input],
|
| 166 |
+
outputs=[result_msg],
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
return name_input, url_input, country_input, submit_btn, result_msg
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def create_tab():
|
| 173 |
+
"""Create the complete tab for this resource type."""
|
| 174 |
+
with gr.TabItem(f"📊 {RESOURCE_TITLE}", id=RESOURCE_TYPE):
|
| 175 |
+
with gr.Tabs():
|
| 176 |
+
table = create_all_tab()
|
| 177 |
+
inputs = create_contribute_tab()
|
| 178 |
+
return table, inputs
|
events_resource.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timezone
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from datasets import Dataset, load_dataset
|
| 6 |
+
|
| 7 |
+
# Dataset configuration
|
| 8 |
+
DATASET_NAME = "somosnlp/recursos-pln-es-events"
|
| 9 |
+
RESOURCE_TYPE = "events"
|
| 10 |
+
RESOURCE_TITLE = "Events"
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_data() -> pd.DataFrame:
|
| 14 |
+
"""Load data from HuggingFace dataset or return empty DataFrame."""
|
| 15 |
+
try:
|
| 16 |
+
dataset = load_dataset(DATASET_NAME, split="train")
|
| 17 |
+
return dataset.to_pandas()
|
| 18 |
+
except Exception as e:
|
| 19 |
+
print(f"Could not load {RESOURCE_TYPE} dataset: {e}")
|
| 20 |
+
# Return empty DataFrame with required columns
|
| 21 |
+
return pd.DataFrame(
|
| 22 |
+
columns=["name", "url", "country", "submitted_by", "date_submitted"]
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def search_and_filter_data(df: pd.DataFrame, search_query: str) -> pd.DataFrame:
|
| 27 |
+
"""Filter dataframe based on search query."""
|
| 28 |
+
if search_query == "":
|
| 29 |
+
return df
|
| 30 |
+
else:
|
| 31 |
+
filtered_df = df[
|
| 32 |
+
df.apply(
|
| 33 |
+
lambda row: row.astype(str)
|
| 34 |
+
.str.contains(search_query, case=False)
|
| 35 |
+
.any(),
|
| 36 |
+
axis=1,
|
| 37 |
+
)
|
| 38 |
+
]
|
| 39 |
+
return filtered_df
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def check_login(profile: gr.OAuthProfile | None) -> bool:
|
| 43 |
+
"""Check if a user is logged in."""
|
| 44 |
+
return profile is not None
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def submit_resource(name: str, url: str, country: str, profile: gr.OAuthProfile | None):
|
| 48 |
+
"""Submit a new resource to the corresponding dataset."""
|
| 49 |
+
|
| 50 |
+
# Check if user is logged in
|
| 51 |
+
if not check_login(profile):
|
| 52 |
+
return "❌ Error: You need to be logged in to submit a resource."
|
| 53 |
+
|
| 54 |
+
# Validate inputs
|
| 55 |
+
if not name or not url or not country:
|
| 56 |
+
return "❌ Error: All fields (name, url, country) are required."
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
username = profile.username
|
| 60 |
+
current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 61 |
+
|
| 62 |
+
# Create new row data
|
| 63 |
+
new_data = {
|
| 64 |
+
"name": name,
|
| 65 |
+
"url": url,
|
| 66 |
+
"country": country,
|
| 67 |
+
"submitted_by": username,
|
| 68 |
+
"date_submitted": current_time,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Try to load existing dataset, or create new one
|
| 72 |
+
try:
|
| 73 |
+
existing_dataset = load_dataset(DATASET_NAME, split="train")
|
| 74 |
+
existing_df = existing_dataset.to_pandas()
|
| 75 |
+
# Add new row
|
| 76 |
+
updated_df = pd.concat(
|
| 77 |
+
[existing_df, pd.DataFrame([new_data])], ignore_index=True
|
| 78 |
+
)
|
| 79 |
+
except:
|
| 80 |
+
# Create new dataset if it doesn't exist
|
| 81 |
+
updated_df = pd.DataFrame([new_data])
|
| 82 |
+
|
| 83 |
+
# Convert back to Dataset and push to hub
|
| 84 |
+
updated_dataset = Dataset.from_pandas(updated_df)
|
| 85 |
+
updated_dataset.push_to_hub(
|
| 86 |
+
DATASET_NAME,
|
| 87 |
+
commit_message=f"Add {name} by {username}",
|
| 88 |
+
token=True, # Use the user's token
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
return f"✅ Success: {name} has been submitted successfully!"
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
return f"❌ Error: Failed to submit resource. {str(e)}"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def create_all_tab():
|
| 98 |
+
"""Create the 'All' tab for this resource type."""
|
| 99 |
+
with gr.TabItem("📋 All", id=f"{RESOURCE_TYPE}_all"):
|
| 100 |
+
gr.Markdown(f"### All {RESOURCE_TITLE}")
|
| 101 |
+
|
| 102 |
+
search_box = gr.Textbox(
|
| 103 |
+
placeholder=f"Search {RESOURCE_TYPE}...",
|
| 104 |
+
label="Filter the table",
|
| 105 |
+
show_label=False,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
# Load initial data
|
| 109 |
+
initial_df = load_data()
|
| 110 |
+
|
| 111 |
+
table = gr.Dataframe(
|
| 112 |
+
value=initial_df,
|
| 113 |
+
label=RESOURCE_TITLE,
|
| 114 |
+
show_label=False,
|
| 115 |
+
interactive=False,
|
| 116 |
+
wrap=True,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Connect search functionality
|
| 120 |
+
search_box.change(
|
| 121 |
+
fn=lambda query: search_and_filter_data(initial_df, query),
|
| 122 |
+
inputs=search_box,
|
| 123 |
+
outputs=table,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Refresh button to reload data
|
| 127 |
+
refresh_btn = gr.Button("🔄 Refresh Data", variant="secondary")
|
| 128 |
+
refresh_btn.click(fn=lambda: load_data(), outputs=table)
|
| 129 |
+
|
| 130 |
+
return table
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_contribute_tab():
|
| 134 |
+
"""Create the 'Contribute' tab for this resource type."""
|
| 135 |
+
with gr.TabItem("➕ Contribute", id=f"{RESOURCE_TYPE}_contribute"):
|
| 136 |
+
gr.Markdown(f"### Contribute a New {RESOURCE_TITLE[:-1]}")
|
| 137 |
+
|
| 138 |
+
# Login section
|
| 139 |
+
gr.Markdown("Please log in to contribute resources:")
|
| 140 |
+
login_button = gr.LoginButton(elem_id=f"{RESOURCE_TYPE}-oauth-button")
|
| 141 |
+
|
| 142 |
+
gr.Markdown("Please fill in the information below to add a new event:")
|
| 143 |
+
|
| 144 |
+
with gr.Column():
|
| 145 |
+
name_input = gr.Textbox(
|
| 146 |
+
label="Name",
|
| 147 |
+
placeholder="Enter the name of the event",
|
| 148 |
+
info="The name or title of the resource",
|
| 149 |
+
)
|
| 150 |
+
url_input = gr.Textbox(
|
| 151 |
+
label="URL", placeholder="https://...", info="Link to the resource"
|
| 152 |
+
)
|
| 153 |
+
country_input = gr.Textbox(
|
| 154 |
+
label="Country",
|
| 155 |
+
placeholder="e.g., Spain, Mexico, Argentina",
|
| 156 |
+
info="Country of origin or primary focus",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
submit_btn = gr.Button(f"Submit {RESOURCE_TITLE[:-1]}", variant="primary")
|
| 160 |
+
result_msg = gr.Markdown()
|
| 161 |
+
|
| 162 |
+
# Submit function
|
| 163 |
+
submit_btn.click(
|
| 164 |
+
fn=submit_resource,
|
| 165 |
+
inputs=[name_input, url_input, country_input],
|
| 166 |
+
outputs=[result_msg],
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
return name_input, url_input, country_input, submit_btn, result_msg
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def create_tab():
|
| 173 |
+
"""Create the complete tab for this resource type."""
|
| 174 |
+
with gr.TabItem(f"📅 {RESOURCE_TITLE}", id=RESOURCE_TYPE):
|
| 175 |
+
with gr.Tabs():
|
| 176 |
+
table = create_all_tab()
|
| 177 |
+
inputs = create_contribute_tab()
|
| 178 |
+
return table, inputs
|
initiatives_resource.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timezone
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from datasets import Dataset, load_dataset
|
| 6 |
+
|
| 7 |
+
# Dataset configuration
|
| 8 |
+
DATASET_NAME = "somosnlp/recursos-pln-es-initiatives"
|
| 9 |
+
RESOURCE_TYPE = "initiatives"
|
| 10 |
+
RESOURCE_TITLE = "Initiatives"
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_data() -> pd.DataFrame:
|
| 14 |
+
"""Load data from HuggingFace dataset or return empty DataFrame."""
|
| 15 |
+
try:
|
| 16 |
+
dataset = load_dataset(DATASET_NAME, split="train")
|
| 17 |
+
return dataset.to_pandas()
|
| 18 |
+
except Exception as e:
|
| 19 |
+
print(f"Could not load {RESOURCE_TYPE} dataset: {e}")
|
| 20 |
+
# Return empty DataFrame with required columns
|
| 21 |
+
return pd.DataFrame(
|
| 22 |
+
columns=["name", "url", "country", "submitted_by", "date_submitted"]
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def search_and_filter_data(df: pd.DataFrame, search_query: str) -> pd.DataFrame:
|
| 27 |
+
"""Filter dataframe based on search query."""
|
| 28 |
+
if search_query == "":
|
| 29 |
+
return df
|
| 30 |
+
else:
|
| 31 |
+
filtered_df = df[
|
| 32 |
+
df.apply(
|
| 33 |
+
lambda row: row.astype(str)
|
| 34 |
+
.str.contains(search_query, case=False)
|
| 35 |
+
.any(),
|
| 36 |
+
axis=1,
|
| 37 |
+
)
|
| 38 |
+
]
|
| 39 |
+
return filtered_df
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def check_login(profile: gr.OAuthProfile | None) -> bool:
|
| 43 |
+
"""Check if a user is logged in."""
|
| 44 |
+
return profile is not None
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def submit_resource(name: str, url: str, country: str, profile: gr.OAuthProfile | None):
|
| 48 |
+
"""Submit a new resource to the corresponding dataset."""
|
| 49 |
+
|
| 50 |
+
# Check if user is logged in
|
| 51 |
+
if not check_login(profile):
|
| 52 |
+
return "❌ Error: You need to be logged in to submit a resource."
|
| 53 |
+
|
| 54 |
+
# Validate inputs
|
| 55 |
+
if not name or not url or not country:
|
| 56 |
+
return "❌ Error: All fields (name, url, country) are required."
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
username = profile.username
|
| 60 |
+
current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 61 |
+
|
| 62 |
+
# Create new row data
|
| 63 |
+
new_data = {
|
| 64 |
+
"name": name,
|
| 65 |
+
"url": url,
|
| 66 |
+
"country": country,
|
| 67 |
+
"submitted_by": username,
|
| 68 |
+
"date_submitted": current_time,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Try to load existing dataset, or create new one
|
| 72 |
+
try:
|
| 73 |
+
existing_dataset = load_dataset(DATASET_NAME, split="train")
|
| 74 |
+
existing_df = existing_dataset.to_pandas()
|
| 75 |
+
# Add new row
|
| 76 |
+
updated_df = pd.concat(
|
| 77 |
+
[existing_df, pd.DataFrame([new_data])], ignore_index=True
|
| 78 |
+
)
|
| 79 |
+
except:
|
| 80 |
+
# Create new dataset if it doesn't exist
|
| 81 |
+
updated_df = pd.DataFrame([new_data])
|
| 82 |
+
|
| 83 |
+
# Convert back to Dataset and push to hub
|
| 84 |
+
updated_dataset = Dataset.from_pandas(updated_df)
|
| 85 |
+
updated_dataset.push_to_hub(
|
| 86 |
+
DATASET_NAME,
|
| 87 |
+
commit_message=f"Add {name} by {username}",
|
| 88 |
+
token=True, # Use the user's token
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
return f"✅ Success: {name} has been submitted successfully!"
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
return f"❌ Error: Failed to submit resource. {str(e)}"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def create_all_tab():
|
| 98 |
+
"""Create the 'All' tab for this resource type."""
|
| 99 |
+
with gr.TabItem("📋 All", id=f"{RESOURCE_TYPE}_all"):
|
| 100 |
+
gr.Markdown(f"### All {RESOURCE_TITLE}")
|
| 101 |
+
|
| 102 |
+
search_box = gr.Textbox(
|
| 103 |
+
placeholder=f"Search {RESOURCE_TYPE}...",
|
| 104 |
+
label="Filter the table",
|
| 105 |
+
show_label=False,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
# Load initial data
|
| 109 |
+
initial_df = load_data()
|
| 110 |
+
|
| 111 |
+
table = gr.Dataframe(
|
| 112 |
+
value=initial_df,
|
| 113 |
+
label=RESOURCE_TITLE,
|
| 114 |
+
show_label=False,
|
| 115 |
+
interactive=False,
|
| 116 |
+
wrap=True,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Connect search functionality
|
| 120 |
+
search_box.change(
|
| 121 |
+
fn=lambda query: search_and_filter_data(initial_df, query),
|
| 122 |
+
inputs=search_box,
|
| 123 |
+
outputs=table,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Refresh button to reload data
|
| 127 |
+
refresh_btn = gr.Button("🔄 Refresh Data", variant="secondary")
|
| 128 |
+
refresh_btn.click(fn=lambda: load_data(), outputs=table)
|
| 129 |
+
|
| 130 |
+
return table
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_contribute_tab():
|
| 134 |
+
"""Create the 'Contribute' tab for this resource type."""
|
| 135 |
+
with gr.TabItem("➕ Contribute", id=f"{RESOURCE_TYPE}_contribute"):
|
| 136 |
+
gr.Markdown(f"### Contribute a New {RESOURCE_TITLE[:-1]}")
|
| 137 |
+
|
| 138 |
+
# Login section
|
| 139 |
+
gr.Markdown("Please log in to contribute resources:")
|
| 140 |
+
login_button = gr.LoginButton(elem_id=f"{RESOURCE_TYPE}-oauth-button")
|
| 141 |
+
|
| 142 |
+
gr.Markdown("Please fill in the information below to add a new initiative:")
|
| 143 |
+
|
| 144 |
+
with gr.Column():
|
| 145 |
+
name_input = gr.Textbox(
|
| 146 |
+
label="Name",
|
| 147 |
+
placeholder="Enter the name of the initiative",
|
| 148 |
+
info="The name or title of the resource",
|
| 149 |
+
)
|
| 150 |
+
url_input = gr.Textbox(
|
| 151 |
+
label="URL", placeholder="https://...", info="Link to the resource"
|
| 152 |
+
)
|
| 153 |
+
country_input = gr.Textbox(
|
| 154 |
+
label="Country",
|
| 155 |
+
placeholder="e.g., Spain, Mexico, Argentina",
|
| 156 |
+
info="Country of origin or primary focus",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
submit_btn = gr.Button(f"Submit {RESOURCE_TITLE[:-1]}", variant="primary")
|
| 160 |
+
result_msg = gr.Markdown()
|
| 161 |
+
|
| 162 |
+
# Submit function
|
| 163 |
+
submit_btn.click(
|
| 164 |
+
fn=submit_resource,
|
| 165 |
+
inputs=[name_input, url_input, country_input],
|
| 166 |
+
outputs=[result_msg],
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
return name_input, url_input, country_input, submit_btn, result_msg
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def create_tab():
|
| 173 |
+
"""Create the complete tab for this resource type."""
|
| 174 |
+
with gr.TabItem(f"🌟 {RESOURCE_TITLE}", id=RESOURCE_TYPE):
|
| 175 |
+
with gr.Tabs():
|
| 176 |
+
table = create_all_tab()
|
| 177 |
+
inputs = create_contribute_tab()
|
| 178 |
+
return table, inputs
|
models_resource.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timezone
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from datasets import Dataset, load_dataset
|
| 6 |
+
|
| 7 |
+
# Dataset configuration
|
| 8 |
+
DATASET_NAME = "somosnlp/recursos-pln-es-models"
|
| 9 |
+
RESOURCE_TYPE = "models"
|
| 10 |
+
RESOURCE_TITLE = "Models"
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_data() -> pd.DataFrame:
|
| 14 |
+
"""Load data from HuggingFace dataset or return empty DataFrame."""
|
| 15 |
+
try:
|
| 16 |
+
dataset = load_dataset(DATASET_NAME, split="train")
|
| 17 |
+
return dataset.to_pandas()
|
| 18 |
+
except Exception as e:
|
| 19 |
+
print(f"Could not load {RESOURCE_TYPE} dataset: {e}")
|
| 20 |
+
# Return empty DataFrame with required columns
|
| 21 |
+
return pd.DataFrame(
|
| 22 |
+
columns=["name", "url", "country", "submitted_by", "date_submitted"]
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def search_and_filter_data(df: pd.DataFrame, search_query: str) -> pd.DataFrame:
|
| 27 |
+
"""Filter dataframe based on search query."""
|
| 28 |
+
if search_query == "":
|
| 29 |
+
return df
|
| 30 |
+
else:
|
| 31 |
+
filtered_df = df[
|
| 32 |
+
df.apply(
|
| 33 |
+
lambda row: row.astype(str)
|
| 34 |
+
.str.contains(search_query, case=False)
|
| 35 |
+
.any(),
|
| 36 |
+
axis=1,
|
| 37 |
+
)
|
| 38 |
+
]
|
| 39 |
+
return filtered_df
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def check_login(profile: gr.OAuthProfile | None) -> bool:
|
| 43 |
+
"""Check if a user is logged in."""
|
| 44 |
+
return profile is not None
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def submit_resource(name: str, url: str, country: str, profile: gr.OAuthProfile | None):
|
| 48 |
+
"""Submit a new resource to the corresponding dataset."""
|
| 49 |
+
|
| 50 |
+
# Check if user is logged in
|
| 51 |
+
if not check_login(profile):
|
| 52 |
+
return "❌ Error: You need to be logged in to submit a resource."
|
| 53 |
+
|
| 54 |
+
# Validate inputs
|
| 55 |
+
if not name or not url or not country:
|
| 56 |
+
return "❌ Error: All fields (name, url, country) are required."
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
username = profile.username
|
| 60 |
+
current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 61 |
+
|
| 62 |
+
# Create new row data
|
| 63 |
+
new_data = {
|
| 64 |
+
"name": name,
|
| 65 |
+
"url": url,
|
| 66 |
+
"country": country,
|
| 67 |
+
"submitted_by": username,
|
| 68 |
+
"date_submitted": current_time,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Try to load existing dataset, or create new one
|
| 72 |
+
try:
|
| 73 |
+
existing_dataset = load_dataset(DATASET_NAME, split="train")
|
| 74 |
+
existing_df = existing_dataset.to_pandas()
|
| 75 |
+
# Add new row
|
| 76 |
+
updated_df = pd.concat(
|
| 77 |
+
[existing_df, pd.DataFrame([new_data])], ignore_index=True
|
| 78 |
+
)
|
| 79 |
+
except:
|
| 80 |
+
# Create new dataset if it doesn't exist
|
| 81 |
+
updated_df = pd.DataFrame([new_data])
|
| 82 |
+
|
| 83 |
+
# Convert back to Dataset and push to hub
|
| 84 |
+
updated_dataset = Dataset.from_pandas(updated_df)
|
| 85 |
+
updated_dataset.push_to_hub(
|
| 86 |
+
DATASET_NAME,
|
| 87 |
+
commit_message=f"Add {name} by {username}",
|
| 88 |
+
token=True, # Use the user's token
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
return f"✅ Success: {name} has been submitted successfully!"
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
return f"❌ Error: Failed to submit resource. {str(e)}"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def create_all_tab():
|
| 98 |
+
"""Create the 'All' tab for this resource type."""
|
| 99 |
+
with gr.TabItem("📋 All", id=f"{RESOURCE_TYPE}_all"):
|
| 100 |
+
gr.Markdown(f"### All {RESOURCE_TITLE}")
|
| 101 |
+
|
| 102 |
+
search_box = gr.Textbox(
|
| 103 |
+
placeholder=f"Search {RESOURCE_TYPE}...",
|
| 104 |
+
label="Filter the table",
|
| 105 |
+
show_label=False,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
# Load initial data
|
| 109 |
+
initial_df = load_data()
|
| 110 |
+
|
| 111 |
+
table = gr.Dataframe(
|
| 112 |
+
value=initial_df,
|
| 113 |
+
label=RESOURCE_TITLE,
|
| 114 |
+
show_label=False,
|
| 115 |
+
interactive=False,
|
| 116 |
+
wrap=True,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Connect search functionality
|
| 120 |
+
search_box.change(
|
| 121 |
+
fn=lambda query: search_and_filter_data(initial_df, query),
|
| 122 |
+
inputs=search_box,
|
| 123 |
+
outputs=table,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Refresh button to reload data
|
| 127 |
+
refresh_btn = gr.Button("🔄 Refresh Data", variant="secondary")
|
| 128 |
+
refresh_btn.click(fn=lambda: load_data(), outputs=table)
|
| 129 |
+
|
| 130 |
+
return table
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_contribute_tab():
|
| 134 |
+
"""Create the 'Contribute' tab for this resource type."""
|
| 135 |
+
with gr.TabItem("➕ Contribute", id=f"{RESOURCE_TYPE}_contribute"):
|
| 136 |
+
gr.Markdown(f"### Contribute a New {RESOURCE_TITLE[:-1]}")
|
| 137 |
+
|
| 138 |
+
# Login section
|
| 139 |
+
gr.Markdown("Please log in to contribute resources:")
|
| 140 |
+
login_button = gr.LoginButton(elem_id=f"{RESOURCE_TYPE}-oauth-button")
|
| 141 |
+
|
| 142 |
+
gr.Markdown("Please fill in the information below to add a new model:")
|
| 143 |
+
|
| 144 |
+
with gr.Column():
|
| 145 |
+
name_input = gr.Textbox(
|
| 146 |
+
label="Name",
|
| 147 |
+
placeholder="Enter the name of the model",
|
| 148 |
+
info="The name or title of the resource",
|
| 149 |
+
)
|
| 150 |
+
url_input = gr.Textbox(
|
| 151 |
+
label="URL", placeholder="https://...", info="Link to the resource"
|
| 152 |
+
)
|
| 153 |
+
country_input = gr.Textbox(
|
| 154 |
+
label="Country",
|
| 155 |
+
placeholder="e.g., Spain, Mexico, Argentina",
|
| 156 |
+
info="Country of origin or primary focus",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
submit_btn = gr.Button(f"Submit {RESOURCE_TITLE[:-1]}", variant="primary")
|
| 160 |
+
result_msg = gr.Markdown()
|
| 161 |
+
|
| 162 |
+
# Submit function
|
| 163 |
+
submit_btn.click(
|
| 164 |
+
fn=submit_resource,
|
| 165 |
+
inputs=[name_input, url_input, country_input],
|
| 166 |
+
outputs=[result_msg],
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
return name_input, url_input, country_input, submit_btn, result_msg
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def create_tab():
|
| 173 |
+
"""Create the complete tab for this resource type."""
|
| 174 |
+
with gr.TabItem(f"🤖 {RESOURCE_TITLE}", id=RESOURCE_TYPE):
|
| 175 |
+
with gr.Tabs():
|
| 176 |
+
table = create_all_tab()
|
| 177 |
+
inputs = create_contribute_tab()
|
| 178 |
+
return table, inputs
|
requirements.txt
CHANGED
|
@@ -1,2 +1,5 @@
|
|
| 1 |
gradio==4.26.0
|
| 2 |
pandas==2.2.1
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
gradio==4.26.0
|
| 2 |
pandas==2.2.1
|
| 3 |
+
huggingface_hub>=0.20.0
|
| 4 |
+
datasets>=2.17.0
|
| 5 |
+
gradio[oauth]
|
shared_tasks_resource.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timezone
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from datasets import Dataset, load_dataset
|
| 6 |
+
|
| 7 |
+
# Dataset configuration
|
| 8 |
+
DATASET_NAME = "somosnlp/recursos-pln-es-shared-tasks"
|
| 9 |
+
RESOURCE_TYPE = "shared_tasks"
|
| 10 |
+
RESOURCE_TITLE = "Shared Tasks"
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_data() -> pd.DataFrame:
|
| 14 |
+
"""Load data from HuggingFace dataset or return empty DataFrame."""
|
| 15 |
+
try:
|
| 16 |
+
dataset = load_dataset(DATASET_NAME, split="train")
|
| 17 |
+
return dataset.to_pandas()
|
| 18 |
+
except Exception as e:
|
| 19 |
+
print(f"Could not load {RESOURCE_TYPE} dataset: {e}")
|
| 20 |
+
# Return empty DataFrame with required columns
|
| 21 |
+
return pd.DataFrame(
|
| 22 |
+
columns=["name", "url", "country", "submitted_by", "date_submitted"]
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def search_and_filter_data(df: pd.DataFrame, search_query: str) -> pd.DataFrame:
|
| 27 |
+
"""Filter dataframe based on search query."""
|
| 28 |
+
if search_query == "":
|
| 29 |
+
return df
|
| 30 |
+
else:
|
| 31 |
+
filtered_df = df[
|
| 32 |
+
df.apply(
|
| 33 |
+
lambda row: row.astype(str)
|
| 34 |
+
.str.contains(search_query, case=False)
|
| 35 |
+
.any(),
|
| 36 |
+
axis=1,
|
| 37 |
+
)
|
| 38 |
+
]
|
| 39 |
+
return filtered_df
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def check_login(profile: gr.OAuthProfile | None) -> bool:
|
| 43 |
+
"""Check if a user is logged in."""
|
| 44 |
+
return profile is not None
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def submit_resource(name: str, url: str, country: str, profile: gr.OAuthProfile | None):
|
| 48 |
+
"""Submit a new resource to the corresponding dataset."""
|
| 49 |
+
|
| 50 |
+
# Check if user is logged in
|
| 51 |
+
if not check_login(profile):
|
| 52 |
+
return "❌ Error: You need to be logged in to submit a resource."
|
| 53 |
+
|
| 54 |
+
# Validate inputs
|
| 55 |
+
if not name or not url or not country:
|
| 56 |
+
return "❌ Error: All fields (name, url, country) are required."
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
username = profile.username
|
| 60 |
+
current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 61 |
+
|
| 62 |
+
# Create new row data
|
| 63 |
+
new_data = {
|
| 64 |
+
"name": name,
|
| 65 |
+
"url": url,
|
| 66 |
+
"country": country,
|
| 67 |
+
"submitted_by": username,
|
| 68 |
+
"date_submitted": current_time,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Try to load existing dataset, or create new one
|
| 72 |
+
try:
|
| 73 |
+
existing_dataset = load_dataset(DATASET_NAME, split="train")
|
| 74 |
+
existing_df = existing_dataset.to_pandas()
|
| 75 |
+
# Add new row
|
| 76 |
+
updated_df = pd.concat(
|
| 77 |
+
[existing_df, pd.DataFrame([new_data])], ignore_index=True
|
| 78 |
+
)
|
| 79 |
+
except:
|
| 80 |
+
# Create new dataset if it doesn't exist
|
| 81 |
+
updated_df = pd.DataFrame([new_data])
|
| 82 |
+
|
| 83 |
+
# Convert back to Dataset and push to hub
|
| 84 |
+
updated_dataset = Dataset.from_pandas(updated_df)
|
| 85 |
+
updated_dataset.push_to_hub(
|
| 86 |
+
DATASET_NAME,
|
| 87 |
+
commit_message=f"Add {name} by {username}",
|
| 88 |
+
token=True, # Use the user's token
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
return f"✅ Success: {name} has been submitted successfully!"
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
return f"❌ Error: Failed to submit resource. {str(e)}"
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def create_all_tab():
|
| 98 |
+
"""Create the 'All' tab for this resource type."""
|
| 99 |
+
with gr.TabItem("📋 All", id=f"{RESOURCE_TYPE}_all"):
|
| 100 |
+
gr.Markdown(f"### All {RESOURCE_TITLE}")
|
| 101 |
+
|
| 102 |
+
search_box = gr.Textbox(
|
| 103 |
+
placeholder=f"Search {RESOURCE_TYPE}...",
|
| 104 |
+
label="Filter the table",
|
| 105 |
+
show_label=False,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
# Load initial data
|
| 109 |
+
initial_df = load_data()
|
| 110 |
+
|
| 111 |
+
table = gr.Dataframe(
|
| 112 |
+
value=initial_df,
|
| 113 |
+
label=RESOURCE_TITLE,
|
| 114 |
+
show_label=False,
|
| 115 |
+
interactive=False,
|
| 116 |
+
wrap=True,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Connect search functionality
|
| 120 |
+
search_box.change(
|
| 121 |
+
fn=lambda query: search_and_filter_data(initial_df, query),
|
| 122 |
+
inputs=search_box,
|
| 123 |
+
outputs=table,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Refresh button to reload data
|
| 127 |
+
refresh_btn = gr.Button("🔄 Refresh Data", variant="secondary")
|
| 128 |
+
refresh_btn.click(fn=lambda: load_data(), outputs=table)
|
| 129 |
+
|
| 130 |
+
return table
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_contribute_tab():
|
| 134 |
+
"""Create the 'Contribute' tab for this resource type."""
|
| 135 |
+
with gr.TabItem("➕ Contribute", id=f"{RESOURCE_TYPE}_contribute"):
|
| 136 |
+
gr.Markdown(f"### Contribute a New {RESOURCE_TITLE[:-1]}")
|
| 137 |
+
|
| 138 |
+
# Login section
|
| 139 |
+
gr.Markdown("Please log in to contribute resources:")
|
| 140 |
+
login_button = gr.LoginButton(elem_id=f"{RESOURCE_TYPE}-oauth-button")
|
| 141 |
+
|
| 142 |
+
gr.Markdown("Please fill in the information below to add a new shared task:")
|
| 143 |
+
|
| 144 |
+
with gr.Column():
|
| 145 |
+
name_input = gr.Textbox(
|
| 146 |
+
label="Name",
|
| 147 |
+
placeholder="Enter the name of the shared task",
|
| 148 |
+
info="The name or title of the resource",
|
| 149 |
+
)
|
| 150 |
+
url_input = gr.Textbox(
|
| 151 |
+
label="URL", placeholder="https://...", info="Link to the resource"
|
| 152 |
+
)
|
| 153 |
+
country_input = gr.Textbox(
|
| 154 |
+
label="Country",
|
| 155 |
+
placeholder="e.g., Spain, Mexico, Argentina",
|
| 156 |
+
info="Country of origin or primary focus",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
submit_btn = gr.Button(f"Submit {RESOURCE_TITLE[:-1]}", variant="primary")
|
| 160 |
+
result_msg = gr.Markdown()
|
| 161 |
+
|
| 162 |
+
# Submit function
|
| 163 |
+
submit_btn.click(
|
| 164 |
+
fn=submit_resource,
|
| 165 |
+
inputs=[name_input, url_input, country_input],
|
| 166 |
+
outputs=[result_msg],
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
return name_input, url_input, country_input, submit_btn, result_msg
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def create_tab():
|
| 173 |
+
"""Create the complete tab for this resource type."""
|
| 174 |
+
with gr.TabItem(f"🏆 {RESOURCE_TITLE}", id=RESOURCE_TYPE):
|
| 175 |
+
with gr.Tabs():
|
| 176 |
+
table = create_all_tab()
|
| 177 |
+
inputs = create_contribute_tab()
|
| 178 |
+
return table, inputs
|