Spaces:
Running
Running
File size: 9,592 Bytes
2f84a1a c6714a7 2f84a1a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
import gradio as gr
import pandas as pd
import json
# --- 1. Загрузка и подготовка данных ---
def load_data(json_path='data.json'):
"""Загружает данные из JSON и преобразует их в pandas DataFrame."""
with open(json_path, 'r', encoding='utf-8') as f:
data = json.load(f)
df = pd.DataFrame(data)
# --- ИСПРАВЛЕНИЕ: Преобразуем колонку с датой в формат datetime ---
# dayfirst=True указывает pandas, что в формате ДД/ММ/ГГГГ день идет первым.
df['test_date'] = pd.to_datetime(df['test_date'], dayfirst=True)
return df
# --- 2. Логика фильтрации и обновления таблицы ---
def update_leaderboard(data_df, filter_type, search_query, show_outdated):
"""Фильтрует DataFrame на основе выбранного типа, поискового запроса и флага устаревших данных."""
# Шаг 1: Фильтрация по устаревшим данным
if not show_outdated:
# Скрываем модели с пометкой об устаревших данных
filtered_df = data_df[~data_df['notes'].str.contains('устаревших данных', na=False, case=False)].copy()
else:
filtered_df = data_df.copy()
# Шаг 2: Фильтрация по типу
if filter_type == "Только войсклонинг":
filtered_df = filtered_df[filtered_df['type'] == 'voice_cloning'].copy()
elif filter_type == "Без войсклонинга":
filtered_df = filtered_df[filtered_df['type'] == 'single_speaker'].copy()
# else: "Все модели" - оставляем как есть
# Шаг 3: Фильтрация по поисковому запросу
if search_query:
query = search_query.lower()
filtered_df = filtered_df[
filtered_df['engine'].str.lower().str.contains(query) |
filtered_df['voice'].str.lower().str.contains(query)
]
# Шаг 4: Подготовка DataFrame для отображения
# --- ИСПРАВЛЕНИЕ: Форматируем дату в 'ГГГГ-ММ-ДД' для корректной сортировки в UI ---
# Создаем копию, чтобы не изменять оригинальный DataFrame в gr.State
display_df = filtered_df.copy()
display_df['test_date'] = display_df['test_date'].dt.strftime('%Y-%m-%d')
column_mapping = {
"engine": "Движок", "voice": "Голос", "test_date": "Дата",
"hardware": "Железо", "utmos": "UTMOS (↑)", "cer": "CER (↓)",
"encodec_fad": "FAD (↓)", "similarity_avg": "Похожесть Avg (↑)",
"xrt_gpu": "xRT GPU (↓)", "xrt_cpu": "xRT CPU (↓)", "notes": "Примечания"
}
display_df = display_df[column_mapping.keys()].rename(columns=column_mapping)
return display_df
# --- 3. Создание интерфейса Gradio ---
# Загружаем данные один раз при старте приложения
original_df = load_data()
# Сортируем по-умолчанию по дате (самые новые вверху), скрывая устаревшие
initial_display_df = update_leaderboard(original_df, "Все модели", "", show_outdated=False)
initial_display_df = initial_display_df.sort_values(by="Дата", ascending=False)
with gr.Blocks(theme=gr.themes.Soft(), css="footer {visibility: hidden}") as demo:
gr.Markdown("# 🏆 Лидерборд TTS моделей для русского языка")
gr.Markdown(
"""
Этот лидерборд предназначен для сравнения различных Text-to-Speech моделей.
### Описание метрик:
- **UTMOS (↑)**: Оценка качества речи, основанная на мнении слушателей (Mean Opinion Score). **Больше — лучше.**
- **CER (↓)**: Character Error Rate (коэффициент ошибок по символам). Показывает, насколько часто синтез делает ошибки в произношении. **Меньше — лучше.**
- **FAD (↓)**: Fréchet Audio Distance. Объективная метрика, измеряющая расстояние между распределениями реального и синтезированного аудио. **Меньше — лучше.**
- **Похожесть Avg (↑)**: Средняя оценка схожести голоса с оригиналом при клонировании. **Больше — лучше.**
- **xRT GPU/CPU (↓)**: Real-Time Factor. Во сколько раз синтез быстрее (если < 1) или медленнее (если > 1) реального времени на GPU/CPU. **Меньше — лучше.**
- **Железо**: Тип оборудования, на котором производился тест (Cloud - облачный сервис, Local GPU/CPU - локальное железо, RTX 4090 - конкретная видеокарта).
*Кликните на заголовок колонки для сортировки. По умолчанию отсортировано по дате (сначала новые).*
"""
)
gr.Markdown("✉️ Чтобы добавить свою модель, а также вопросы и предложения пишите в Telegram [@bceloss](https://t.me/bceloss)")
gr.Markdown('✉️ Добавляйтесь в чат "Распознавание и синтез речи" [@speech_recognition_ru](https://t.me/speech_recognition_ru)')
gr.Markdown('👥 Авторы: Nikolay Shmyrev [@nshmyrev](https://t.me/nshmyrev), Denis Petrov [@bceloss](https://t.me/bceloss)')
with gr.Row():
with gr.Column(scale=3):
filter_radio = gr.Radio(
["Все модели", "Только войсклонинг", "Без войсклонинга"],
label="Тип модели",
value="Все модели"
)
with gr.Column(scale=3):
search_box = gr.Textbox(
label="Поиск по названию движка или голоса",
placeholder="Например, Silero, Vosk, Multi..."
)
with gr.Column(scale=2):
show_outdated_checkbox = gr.Checkbox(
label="Показать модели с устаревшими данными",
value=False,
info="⚠️ Данные этих моделей могут быть неточными"
)
# Информационное сообщение о скрытых моделях
outdated_info = gr.Markdown(visible=False)
leaderboard_df = gr.DataFrame(
value=initial_display_df,
interactive=True,
)
# Используем gr.State для передачи полного DataFrame с правильными типами данных
df_state = gr.State(original_df)
def on_change(filter_type, search_query, show_outdated, data_df):
"""Обновляет таблицу и показывает информацию о скрытых моделях."""
updated_df = update_leaderboard(data_df, filter_type, search_query, show_outdated)
# Подсчитываем количество скрытых моделей с устаревшими данными
if not show_outdated:
outdated_count = data_df[data_df['notes'].str.contains('устаревших данных', na=False, case=False)].shape[0]
if outdated_count > 0:
info_text = f"ℹ️ **Скрыто моделей с устаревшими данными: {outdated_count}**. Включите опцию выше, чтобы показать их."
return updated_df, gr.update(value=info_text, visible=True)
return updated_df, gr.update(visible=False)
# Связываем все элементы управления с функцией обновления
filter_radio.change(
fn=on_change,
inputs=[filter_radio, search_box, show_outdated_checkbox, df_state],
outputs=[leaderboard_df, outdated_info]
)
search_box.change(
fn=on_change,
inputs=[filter_radio, search_box, show_outdated_checkbox, df_state],
outputs=[leaderboard_df, outdated_info]
)
show_outdated_checkbox.change(
fn=on_change,
inputs=[filter_radio, search_box, show_outdated_checkbox, df_state],
outputs=[leaderboard_df, outdated_info]
)
# Показываем информацию о скрытых моделях при загрузке
demo.load(
fn=lambda: f"ℹ️ **Скрыто моделей с устаревшими данными: {original_df[original_df['notes'].str.contains('устаревших данных', na=False, case=False)].shape[0]}**. Включите опцию выше, чтобы показать их.",
outputs=outdated_info
)
# --- 4. Запуск приложения ---
if __name__ == "__main__":
demo.launch() |