Anonumous commited on
Commit
fa68614
·
verified ·
1 Parent(s): 4f2ad89

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -162
app.py CHANGED
@@ -51,10 +51,7 @@ init_repo()
51
  gr.set_static_paths(paths=["."])
52
 
53
  with gr.Blocks(css=LEADERBOARD_CSS, theme=gr.themes.Soft()) as demo:
54
- gr.HTML(
55
- '<img src="/gradio_api/file=Logo.png" '
56
- 'style="display:block; margin:0 auto; width:34%; height:auto;">'
57
- )
58
  gr.HTML(ASSETS_HTML)
59
  gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
60
 
@@ -70,10 +67,7 @@ with gr.Blocks(css=LEADERBOARD_CSS, theme=gr.themes.Soft()) as demo:
70
  ref = gr.Textbox(label="Референсный текст", lines=2)
71
  hyp = gr.Textbox(label="Распознанный текст", lines=2)
72
  with gr.Row():
73
- normalize = gr.Checkbox(
74
- value=True,
75
- label="Нормализовать (нижний регистр, без пунктуации)",
76
- )
77
  btn_calc = gr.Button("Посчитать")
78
  with gr.Row():
79
  out_wer = gr.Number(label="WER, %", precision=2)
@@ -83,198 +77,98 @@ with gr.Blocks(css=LEADERBOARD_CSS, theme=gr.themes.Soft()) as demo:
83
  wer, cer = compute_wer_cer(ref_text or "", hyp_text or "", norm)
84
  return wer, cer
85
 
86
- btn_calc.click(
87
- _ui_compute,
88
- inputs=[ref, hyp, normalize],
89
- outputs=[out_wer, out_cer],
90
- )
91
 
92
  with gr.Tab("📊 Датасеты"):
93
  gr.HTML(dataset_info_html)
94
  gr.HTML(get_datasets_description())
95
 
96
  with gr.Tab("✉️ Отправить результат"):
97
- gr.HTML(get_submit_html())
98
- with gr.Row():
99
- with gr.Column():
100
- model_name = gr.Textbox(
101
- label="Название модели *", placeholder="MyAwesomeASRModel"
102
- )
103
- link = gr.Textbox(
104
- label="Ссылка на модель *",
105
- placeholder="https://huggingface.co/username/model",
106
- )
107
- license_field = gr.Textbox(
108
- label="Лицензия *", placeholder="MIT / Apache-2.0 / Closed"
109
- )
110
- with gr.Column():
111
- metrics_json = gr.TextArea(
112
- label="Метрики JSON *",
113
- placeholder='{"Russian_LibriSpeech": {"wer": 0.1234, "cer": 0.0567}, ...}',
114
- lines=16,
115
- )
116
 
117
- submit_btn = gr.Button("🚀 Отправить")
118
- output_msg = gr.HTML()
119
 
120
  def _alert(kind, text):
121
  return f'<div class="alert {kind}">{text}</div>'
122
 
123
- def build_json_and_submit(name, link_, lic, metrics_str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  name = (name or "").strip()
125
  link_ = (link_ or "").strip()
126
  lic = (lic or "").strip()
127
  if not name:
128
- return (
129
- gr.update(),
130
- _alert("error", "Укажите название модели."),
131
- name,
132
- link_,
133
- lic,
134
- metrics_str,
135
- )
136
- if not link_ or not (
137
- link_.startswith("http://") or link_.startswith("https://")
138
- ):
139
- return (
140
- gr.update(),
141
- _alert(
142
- "error", "Ссылка должна начинаться с http:// или https://"
143
- ),
144
- name,
145
- link_,
146
- lic,
147
- metrics_str,
148
- )
149
  if not lic:
150
- return (
151
- gr.update(),
152
- _alert("error", "Укажите лицензию модели."),
153
- name,
154
- link_,
155
- lic,
156
- metrics_str,
157
- )
158
  try:
159
  metrics = json.loads(metrics_str)
160
  except Exception as e:
161
- return (
162
- gr.update(),
163
- _alert("error", f"Невалидный JSON метрик: {e}"),
164
- name,
165
- link_,
166
- lic,
167
- metrics_str,
168
- )
169
  if not isinstance(metrics, dict):
170
- return (
171
- gr.update(),
172
- _alert(
173
- "error",
174
- "Метрики должны быть объектом JSON с датасетами верхнего уровня.",
175
- ),
176
- name,
177
- link_,
178
- lic,
179
- metrics_str,
180
- )
181
  missing = [ds for ds in DATASETS if ds not in metrics]
182
  extra = [k for k in metrics.keys() if k not in DATASETS]
183
  if missing:
184
- return (
185
- gr.update(),
186
- _alert("error", f"Отсутствуют датасеты: {', '.join(missing)}"),
187
- name,
188
- link_,
189
- lic,
190
- metrics_str,
191
- )
192
  if extra:
193
- return (
194
- gr.update(),
195
- _alert("error", f"Лишние ключи в метриках: {', '.join(extra)}"),
196
- name,
197
- link_,
198
- lic,
199
- metrics_str,
200
- )
201
  for ds in DATASETS:
202
  entry = metrics.get(ds)
203
  if not isinstance(entry, dict):
204
- return (
205
- gr.update(),
206
- _alert(
207
- "error",
208
- f"{ds}: значение должно быть объектом с полями wer и cer",
209
- ),
210
- name,
211
- link_,
212
- lic,
213
- metrics_str,
214
- )
215
  for k in ("wer", "cer"):
216
  v = entry.get(k)
217
  if not isinstance(v, (int, float)):
218
- return (
219
- gr.update(),
220
- _alert("error", f"{ds}: поле {k} должно быть числом"),
221
- name,
222
- link_,
223
- lic,
224
- metrics_str,
225
- )
226
  if not (0 <= float(v) <= 1):
227
- return (
228
- gr.update(),
229
- _alert(
230
- "error",
231
- f"{ds}: поле {k} должно быть в диапазоне [0, 1]",
232
- ),
233
- name,
234
- link_,
235
- lic,
236
- metrics_str,
237
- )
238
- payload = json.dumps(
239
- {
240
- "model_name": name,
241
- "link": link_,
242
- "license": lic,
243
- "metrics": metrics,
244
- },
245
- ensure_ascii=False,
246
- )
247
  updated_html, status_msg, _ = process_submit(payload)
248
  if updated_html is None:
249
  msg = status_msg.replace("Ошибка:", "").strip()
250
- return (
251
- gr.update(),
252
- _alert("error", f"Не удалось добавить: {msg}"),
253
- name,
254
- link_,
255
- lic,
256
- metrics_str,
257
- )
258
- return (
259
- updated_html,
260
- _alert("success", "✅ Результат добавлен в лидерборд."),
261
- "",
262
- "",
263
- "",
264
- "",
265
- )
266
 
267
  submit_btn.click(
268
  build_json_and_submit,
269
  inputs=[model_name, link, license_field, metrics_json],
270
- outputs=[
271
- leaderboard_html,
272
- output_msg,
273
- model_name,
274
- link,
275
- license_field,
276
- metrics_json,
277
- ],
278
  )
279
 
280
  demo.launch()
 
51
  gr.set_static_paths(paths=["."])
52
 
53
  with gr.Blocks(css=LEADERBOARD_CSS, theme=gr.themes.Soft()) as demo:
54
+ gr.HTML('<img src="/gradio_api/file=Logo.png" style="display:block; margin:0 auto; width:34%; height:auto;">')
 
 
 
55
  gr.HTML(ASSETS_HTML)
56
  gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
57
 
 
67
  ref = gr.Textbox(label="Референсный текст", lines=2)
68
  hyp = gr.Textbox(label="Распознанный текст", lines=2)
69
  with gr.Row():
70
+ normalize = gr.Checkbox(value=True, label="Нормализовать (нижний регистр, без пунктуации)")
 
 
 
71
  btn_calc = gr.Button("Посчитать")
72
  with gr.Row():
73
  out_wer = gr.Number(label="WER, %", precision=2)
 
77
  wer, cer = compute_wer_cer(ref_text or "", hyp_text or "", norm)
78
  return wer, cer
79
 
80
+ btn_calc.click(_ui_compute, inputs=[ref, hyp, normalize], outputs=[out_wer, out_cer])
 
 
 
 
81
 
82
  with gr.Tab("📊 Датасеты"):
83
  gr.HTML(dataset_info_html)
84
  gr.HTML(get_datasets_description())
85
 
86
  with gr.Tab("✉️ Отправить результат"):
87
+ # 1) Кнопка входа через HF
88
+ login = gr.LoginButton(size="md")
89
+ auth_note = gr.HTML()
90
+
91
+ # 2) Панель формы, скрыта до входа
92
+ submit_panel = gr.Group(visible=False)
93
+ with submit_panel:
94
+ gr.HTML(get_submit_html())
95
+ with gr.Row():
96
+ with gr.Column():
97
+ model_name = gr.Textbox(label="Название модели *", placeholder="MyAwesomeASRModel")
98
+ link = gr.Textbox(label="Ссылка на модель *", placeholder="https://huggingface.co/username/model")
99
+ license_field = gr.Textbox(label="Лицензия *", placeholder="MIT / Apache-2.0 / Closed")
100
+ with gr.Column():
101
+ metrics_json = gr.TextArea(
102
+ label="Метрики JSON *",
103
+ placeholder='{"Russian_LibriSpeech": {"wer": 0.1234, "cer": 0.0567}, ...}',
104
+ lines=16,
105
+ )
106
 
107
+ submit_btn = gr.Button("🚀 Отправить")
108
+ output_msg = gr.HTML()
109
 
110
  def _alert(kind, text):
111
  return f'<div class="alert {kind}">{text}</div>'
112
 
113
+ # 3) Гейт: показать/скрыть форму в зависимости от профиля
114
+ def gate_visibility(profile: gr.OAuthProfile | None):
115
+ if profile is None:
116
+ return gr.update(visible=False), _alert("error", "Чтобы отправить результат, войдите через Hugging Face выше.")
117
+ return gr.update(visible=True), ""
118
+
119
+ # Проверяем на загрузке страницы и после нажатия на LoginButton
120
+ demo.load(gate_visibility, inputs=None, outputs=[submit_panel, auth_note])
121
+ login.click(lambda: None, outputs=None) # сам клик перенаправит на OAuth; по возврату сработает demo.load
122
+
123
+ # 4) Авторизованный сабмит: профиль инжектится автоматически
124
+ def build_json_and_submit(name, link_, lic, metrics_str, profile: gr.OAuthProfile | None):
125
+ if profile is None:
126
+ return gr.update(), _alert("error", "Нужен вход через Hugging Face."), name, link_, lic, metrics_str
127
+
128
  name = (name or "").strip()
129
  link_ = (link_ or "").strip()
130
  lic = (lic or "").strip()
131
  if not name:
132
+ return gr.update(), _alert("error", "Укажите название модели."), name, link_, lic, metrics_str
133
+ if not link_ or not (link_.startswith("http://") or link_.startswith("https://")):
134
+ return gr.update(), _alert("error", "Ссылка должна начинаться с http:// или https://"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  if not lic:
136
+ return gr.update(), _alert("error", "Укажите лицензию модели."), name, link_, lic, metrics_str
 
 
 
 
 
 
 
137
  try:
138
  metrics = json.loads(metrics_str)
139
  except Exception as e:
140
+ return gr.update(), _alert("error", f"Невалидный JSON метрик: {e}"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
141
  if not isinstance(metrics, dict):
142
+ return gr.update(), _alert("error", "Метрики должны быть объектом JSON с датасетами верхнего уровня."), name, link_, lic, metrics_str
 
 
 
 
 
 
 
 
 
 
143
  missing = [ds for ds in DATASETS if ds not in metrics]
144
  extra = [k for k in metrics.keys() if k not in DATASETS]
145
  if missing:
146
+ return gr.update(), _alert("error", f"Отсутствуют датасеты: {', '.join(missing)}"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
147
  if extra:
148
+ return gr.update(), _alert("error", f"Лишние ключи в метриках: {', '.join(extra)}"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
149
  for ds in DATASETS:
150
  entry = metrics.get(ds)
151
  if not isinstance(entry, dict):
152
+ return gr.update(), _alert("error", f"{ds}: значение должно быть объектом с полями wer и cer"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
 
 
 
153
  for k in ("wer", "cer"):
154
  v = entry.get(k)
155
  if not isinstance(v, (int, float)):
156
+ return gr.update(), _alert("error", f"{ds}: поле {k} должно быть числом"), name, link_, lic, metrics_str
 
 
 
 
 
 
 
157
  if not (0 <= float(v) <= 1):
158
+ return gr.update(), _alert("error", f"{ds}: поле {k} должно быть в диапазоне [0, 1]"), name, link_, lic, metrics_str
159
+
160
+ payload = json.dumps({"model_name": name, "link": link_, "license": lic, "metrics": metrics}, ensure_ascii=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  updated_html, status_msg, _ = process_submit(payload)
162
  if updated_html is None:
163
  msg = status_msg.replace("Ошибка:", "").strip()
164
+ return gr.update(), _alert("error", f"Не удалось добавить: {msg}"), name, link_, lic, metrics_str
165
+
166
+ return updated_html, _alert("success", " Результат добавлен в лидерборд."), "", "", "", ""
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  submit_btn.click(
169
  build_json_and_submit,
170
  inputs=[model_name, link, license_field, metrics_json],
171
+ outputs=[leaderboard_html, output_msg, model_name, link, license_field, metrics_json],
 
 
 
 
 
 
 
172
  )
173
 
174
  demo.launch()