AYI-NEDJIMI's picture
Initial AI Code & Multimodal Explorer Space
858cdbf verified
import gradio as gr
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datasets import load_dataset
# ---------------------------------------------------------------------------
# Data loading
# ---------------------------------------------------------------------------
DATASETS = {
"EN": "AYI-NEDJIMI/ai-code-multimodal-en",
"FR": "AYI-NEDJIMI/ai-code-multimodal-fr",
}
_cache: dict[str, pd.DataFrame] = {}
def get_df(lang: str = "EN") -> pd.DataFrame:
if lang not in _cache:
ds = load_dataset(DATASETS[lang], split="train")
_cache[lang] = ds.to_pandas()
return _cache[lang]
# Pre-load both
for _l in DATASETS:
get_df(_l)
COLS_TABLE = ["name", "vendor", "category", "subcategory", "pricing"]
DETAIL_FIELDS = [
"name", "vendor", "category", "subcategory", "description",
"features", "strengths", "weaknesses", "ide_support",
"privacy_model", "supported_languages", "pricing", "source_url",
]
LABELS = {
"EN": {
"title": "AI Code & Multimodal Explorer",
"tab_explorer": "Tools Explorer",
"tab_details": "Details",
"tab_compare": "Comparison",
"tab_stats": "Statistics",
"search": "Search by name or vendor...",
"category": "Category",
"all_categories": "All categories",
"select_tool": "Select a tool",
"select_tool_a": "Tool A",
"select_tool_b": "Tool B",
"compare_btn": "Compare",
"no_tool": "No tool selected.",
"chart_cat": "Tools by Category",
"chart_vendor": "Top 15 Vendors by Number of Tools",
"chart_pricing": "Pricing Distribution",
"chart_cat_vendor": "Category × Vendor Heatmap",
},
"FR": {
"title": "AI Code & Multimodal Explorer",
"tab_explorer": "Explorateur",
"tab_details": "Détails",
"tab_compare": "Comparaison",
"tab_stats": "Statistiques",
"search": "Rechercher par nom ou éditeur...",
"category": "Catégorie",
"all_categories": "Toutes les catégories",
"select_tool": "Sélectionner un outil",
"select_tool_a": "Outil A",
"select_tool_b": "Outil B",
"compare_btn": "Comparer",
"no_tool": "Aucun outil sélectionné.",
"chart_cat": "Outils par catégorie",
"chart_vendor": "Top 15 éditeurs par nombre d'outils",
"chart_pricing": "Répartition des tarifs",
"chart_cat_vendor": "Carte thermique Catégorie × Éditeur",
},
}
# ---------------------------------------------------------------------------
# Helper functions
# ---------------------------------------------------------------------------
def filter_table(search: str, category: str, lang: str) -> pd.DataFrame:
df = get_df(lang)
if category and category != LABELS[lang]["all_categories"]:
df = df[df["category"] == category]
if search:
mask = (
df["name"].str.contains(search, case=False, na=False)
| df["vendor"].str.contains(search, case=False, na=False)
)
df = df[mask]
return df[COLS_TABLE].reset_index(drop=True)
def get_tool_names(lang: str) -> list[str]:
return sorted(get_df(lang)["name"].dropna().unique().tolist())
def get_categories(lang: str) -> list[str]:
cats = sorted(get_df(lang)["category"].dropna().unique().tolist())
return [LABELS[lang]["all_categories"]] + cats
def tool_detail_md(name: str | None, lang: str) -> str:
if not name:
return LABELS[lang]["no_tool"]
df = get_df(lang)
rows = df[df["name"] == name]
if rows.empty:
return LABELS[lang]["no_tool"]
r = rows.iloc[0]
lines = []
for f in DETAIL_FIELDS:
val = r.get(f, "")
if pd.isna(val) or val == "":
val = "—"
label = f.replace("_", " ").title()
if f == "source_url" and val != "—":
lines.append(f"**{label}:** [{val}]({val})")
else:
lines.append(f"**{label}:** {val}")
return "\n\n".join(lines)
def compare_tools(name_a: str | None, name_b: str | None, lang: str) -> str:
if not name_a or not name_b:
return LABELS[lang]["no_tool"]
md_a = tool_detail_md(name_a, lang)
md_b = tool_detail_md(name_b, lang)
sep = "\n\n---\n\n"
return f"## {name_a}\n\n{md_a}{sep}## {name_b}\n\n{md_b}"
# ---------------------------------------------------------------------------
# Charts
# ---------------------------------------------------------------------------
def chart_category(lang: str):
df = get_df(lang)
counts = df["category"].value_counts().reset_index()
counts.columns = ["category", "count"]
fig = px.bar(
counts, x="category", y="count", color="category",
title=LABELS[lang]["chart_cat"],
color_discrete_sequence=px.colors.qualitative.Set2,
)
fig.update_layout(showlegend=False, template="plotly_white")
return fig
def chart_vendor(lang: str):
df = get_df(lang)
counts = df["vendor"].value_counts().head(15).reset_index()
counts.columns = ["vendor", "count"]
fig = px.bar(
counts, x="count", y="vendor", orientation="h",
title=LABELS[lang]["chart_vendor"],
color="count", color_continuous_scale="Viridis",
)
fig.update_layout(yaxis=dict(autorange="reversed"), template="plotly_white")
return fig
def chart_pricing(lang: str):
df = get_df(lang)
counts = df["pricing"].value_counts().reset_index()
counts.columns = ["pricing", "count"]
fig = px.pie(
counts, names="pricing", values="count",
title=LABELS[lang]["chart_pricing"],
color_discrete_sequence=px.colors.qualitative.Pastel,
)
fig.update_layout(template="plotly_white")
return fig
def chart_heatmap(lang: str):
df = get_df(lang)
ct = pd.crosstab(df["category"], df["vendor"])
top_vendors = df["vendor"].value_counts().head(12).index.tolist()
ct = ct[[v for v in top_vendors if v in ct.columns]]
fig = go.Figure(data=go.Heatmap(
z=ct.values, x=ct.columns.tolist(), y=ct.index.tolist(),
colorscale="YlOrRd",
))
fig.update_layout(
title=LABELS[lang]["chart_cat_vendor"],
template="plotly_white", height=400,
)
return fig
# ---------------------------------------------------------------------------
# Footer
# ---------------------------------------------------------------------------
FOOTER_HTML = """
<div style="text-align:center; padding:20px 0 10px 0; margin-top:30px;
border-top:1px solid #444; font-size:0.9em; color:#aaa;">
<p>Built by <strong>AYI-NEDJIMI Consultants</strong></p>
<p>
<a href="https://ayinedjimi-consultants.fr" target="_blank" style="margin:0 8px;">🌐 Website</a> |
<a href="https://www.linkedin.com/company/ayi-nedjimi" target="_blank" style="margin:0 8px;">LinkedIn</a> |
<a href="https://github.com/AYI-NEDJIMI" target="_blank" style="margin:0 8px;">GitHub</a> |
<a href="https://x.com/AyiNedjimi" target="_blank" style="margin:0 8px;">X / Twitter</a>
</p>
</div>
"""
# ---------------------------------------------------------------------------
# Gradio UI
# ---------------------------------------------------------------------------
theme = gr.themes.Soft(
primary_hue="indigo",
secondary_hue="purple",
font=gr.themes.GoogleFont("Inter"),
)
with gr.Blocks(theme=theme, title="AI Code & Multimodal Explorer") as demo:
lang_state = gr.State("EN")
gr.Markdown("# AI Code & Multimodal Explorer")
with gr.Row():
lang_toggle = gr.Radio(
choices=["EN", "FR"], value="EN", label="Language / Langue",
interactive=True,
)
# ---- Tab: Explorer ----
with gr.Tabs() as tabs:
with gr.TabItem("Tools Explorer", id="explorer"):
with gr.Row():
search_box = gr.Textbox(
label="Search", placeholder="Search by name or vendor...",
scale=3,
)
cat_filter = gr.Dropdown(
choices=get_categories("EN"),
value=LABELS["EN"]["all_categories"],
label="Category", scale=1,
)
explorer_table = gr.Dataframe(
value=filter_table("", LABELS["EN"]["all_categories"], "EN"),
headers=COLS_TABLE,
interactive=False,
wrap=True,
)
# ---- Tab: Details ----
with gr.TabItem("Details", id="details"):
tool_select = gr.Dropdown(
choices=get_tool_names("EN"),
label="Select a tool",
interactive=True,
)
detail_output = gr.Markdown(LABELS["EN"]["no_tool"])
# ---- Tab: Comparison ----
with gr.TabItem("Comparison", id="compare"):
with gr.Row():
tool_a = gr.Dropdown(
choices=get_tool_names("EN"), label="Tool A", scale=1,
)
tool_b = gr.Dropdown(
choices=get_tool_names("EN"), label="Tool B", scale=1,
)
compare_btn = gr.Button("Compare", variant="primary")
compare_output = gr.Markdown(LABELS["EN"]["no_tool"])
# ---- Tab: Statistics ----
with gr.TabItem("Statistics", id="stats"):
with gr.Row():
plot_cat = gr.Plot(value=chart_category("EN"))
plot_vendor = gr.Plot(value=chart_vendor("EN"))
with gr.Row():
plot_pricing = gr.Plot(value=chart_pricing("EN"))
plot_heatmap = gr.Plot(value=chart_heatmap("EN"))
gr.HTML(FOOTER_HTML)
# ---- Callbacks ----
def on_lang_change(lang):
cats = get_categories(lang)
names = get_tool_names(lang)
default_cat = cats[0]
table = filter_table("", default_cat, lang)
return (
lang, # lang_state
gr.update(choices=cats, value=default_cat), # cat_filter
table, # explorer_table
gr.update(choices=names, value=None), # tool_select
LABELS[lang]["no_tool"], # detail_output
gr.update(choices=names, value=None), # tool_a
gr.update(choices=names, value=None), # tool_b
LABELS[lang]["no_tool"], # compare_output
chart_category(lang),
chart_vendor(lang),
chart_pricing(lang),
chart_heatmap(lang),
)
lang_toggle.change(
on_lang_change, inputs=[lang_toggle],
outputs=[
lang_state, cat_filter, explorer_table,
tool_select, detail_output,
tool_a, tool_b, compare_output,
plot_cat, plot_vendor, plot_pricing, plot_heatmap,
],
)
def on_filter(search, category, lang):
return filter_table(search, category, lang)
search_box.change(on_filter, [search_box, cat_filter, lang_state], explorer_table)
cat_filter.change(on_filter, [search_box, cat_filter, lang_state], explorer_table)
tool_select.change(
lambda name, lang: tool_detail_md(name, lang),
[tool_select, lang_state], detail_output,
)
compare_btn.click(
lambda a, b, lang: compare_tools(a, b, lang),
[tool_a, tool_b, lang_state], compare_output,
)
demo.launch()