Pendrokar commited on
Commit
f5a93f9
β€’
1 Parent(s): 41c75c6

use browser cookie for cached samples

Browse files
Files changed (2) hide show
  1. app.py +53 -29
  2. cookie.js +31 -0
app.py CHANGED
@@ -437,9 +437,9 @@ Vote to help the community find the best available text-to-speech model!
437
  INSTR = """
438
  ## πŸ—³οΈ Vote
439
 
440
- * Input text (English only) to synthesize audio.
441
- * Press ⚑ to get cached samples you have yet to vote on. Fast.
442
- * Press 🎲 to randomly select text for a list. Slow.
443
  * Listen to the two audio clips, one after the other.
444
  * Vote on which audio sounds more natural to you.
445
  * _Note: Model names are revealed after the vote is cast._
@@ -665,7 +665,7 @@ def make_link_to_space(model_name):
665
  title = model_name
666
  else:
667
  style += 'font-style: italic;'
668
- title = 'Disabled for Arena'
669
 
670
  model_basename = model_name
671
  if model_name in HF_SPACES:
@@ -970,8 +970,8 @@ def synthandreturn(text):
970
  attempt_count += 1
971
  print(repr(e))
972
  print(f"{model}: Unable to call API (attempt: {attempt_count})")
973
- # sleep for one second
974
- time.sleep(1)
975
 
976
  # Fetch and store client again
977
  #hf_clients[model] = Client(model, hf_token=hf_token)
@@ -1141,25 +1141,30 @@ def unlock_vote(btn_index, aplayed, bplayed):
1141
  def play_other(bplayed):
1142
  return bplayed
1143
 
1144
- def get_userid(request):
 
 
 
 
 
1145
  if request.username:
1146
  # print('auth by username')
1147
- # by HuggingFace username
1148
- return sha1(bytes(request.username.encode('ascii'))).hexdigest()
1149
  else:
1150
  # print('auth by ip')
1151
- # by IP address
1152
- return sha1(bytes(request.client.host.encode('ascii'))).hexdigest()
1153
- # by browser session hash
1154
- # Issue: Not a cookie, session hash changes on page reload
1155
- # return sha1(bytes(request.session_hash.encode('ascii')), usedforsecurity=False).hexdigest()
 
1156
 
1157
  # Give user a cached audio sample pair they have yet to vote on
1158
- def give_cached_sample(request: gr.Request):
1159
  # add new userid to voting_users from Browser session hash
1160
  # stored only in RAM
1161
- userid = get_userid(request)
1162
- print(f'userid asked for cached: {userid}')
1163
 
1164
  if userid not in voting_users:
1165
  voting_users[userid] = User(userid)
@@ -1183,7 +1188,11 @@ def give_cached_sample(request: gr.Request):
1183
 
1184
  pair = get_next_pair(voting_users[userid])
1185
  if pair is None:
1186
- return [*clear_stuff(), gr.update(interactive=False)]
 
 
 
 
1187
 
1188
  return (
1189
  pair[0].transcript,
@@ -1206,8 +1215,8 @@ def give_cached_sample(request: gr.Request):
1206
  )
1207
 
1208
  # note the vote on cached sample pair
1209
- def voted_on_cached(modelName1: str, modelName2: str, transcript: str, request: gr.Request):
1210
- userid = get_userid(request)
1211
  print(f'userid voted on cached: {userid}')
1212
 
1213
  if userid not in voting_users:
@@ -1242,7 +1251,11 @@ def disable():
1242
  return [gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False)]
1243
  def enable():
1244
  return [gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)]
 
 
1245
  with gr.Blocks() as vote:
 
 
1246
  # sample played, using Checkbox so that JS can fetch the value
1247
  aplayed = gr.Checkbox(visible=False, value=False)
1248
  bplayed = gr.Checkbox(visible=False, value=False)
@@ -1285,7 +1298,7 @@ with gr.Blocks() as vote:
1285
  )
1286
  bbetter = gr.Button("B is better", variant='primary', interactive=False)
1287
  prevmodel2 = gr.HTML(show_label=False, value="Vote to reveal model B", visible=False)
1288
- nxtroundbtn = gr.Button('Next round', visible=False)
1289
  # outputs = [text, btn, r2, model1, model2, prevmodel1, aud1, prevmodel2, aud2, abetter, bbetter]
1290
  outputs = [
1291
  text,
@@ -1320,13 +1333,17 @@ with gr.Blocks() as vote:
1320
  .click(disable, outputs=[btn, abetter, bbetter, cachedt])\
1321
  .then(synthandreturn, inputs=[text], outputs=outputs)\
1322
  .then(enable, outputs=[btn, gr.State(), gr.State(), cachedt])
1323
- nxtroundbtn.click(give_cached_sample, outputs=[*outputs, cachedt])
 
 
 
1324
 
1325
  # fetch a comparison pair from cache
1326
  cachedt\
1327
  .click(disable, outputs=[btn, abetter, bbetter, cachedt])\
1328
- .then(give_cached_sample, outputs=[*outputs, cachedt])\
1329
- .then(enable, outputs=[btn, gr.State(), gr.State(), cachedt])
 
1330
 
1331
  # Allow interaction with the vote buttons only when both audio samples have finished playing
1332
  aud1\
@@ -1352,16 +1369,21 @@ with gr.Blocks() as vote:
1352
  nxt_outputs = [abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
1353
  abetter\
1354
  .click(a_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])\
1355
- .then(voted_on_cached, inputs=[model1, model2, text])
1356
  bbetter\
1357
  .click(b_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])\
1358
- .then(voted_on_cached, inputs=[model1, model2, text])
1359
  # skipbtn.click(b_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
1360
 
1361
  # bothbad.click(both_bad, outputs=outputs, inputs=[model1, model2, useridstate])
1362
  # bothgood.click(both_good, outputs=outputs, inputs=[model1, model2, useridstate])
1363
 
1364
- # vote.load(reload, outputs=[aud1, aud2, model1, model2])
 
 
 
 
 
1365
 
1366
  with gr.Blocks() as about:
1367
  gr.Markdown(ABOUT)
@@ -1372,7 +1394,7 @@ with gr.Blocks() as about:
1372
  # dbtext = gr.Textbox(label="Type \"delete db\" to confirm", placeholder="delete db")
1373
  # ddb = gr.Button("Delete DB")
1374
  # ddb.click(del_db, inputs=dbtext, outputs=ddb)
1375
- with gr.Blocks(theme=theme, css="footer {visibility: hidden}textbox{resize:none}", title="TTS Arena") as demo:
1376
  gr.Markdown(DESCR)
1377
  # gr.TabbedInterface([vote, leaderboard, about, admin], ['Vote', 'Leaderboard', 'About', 'Admin (ONLY IN BETA)'])
1378
  gr.TabbedInterface([vote, leaderboard, about], ['πŸ—³οΈ Vote', 'πŸ† Leaderboard', 'πŸ“„ About'])
@@ -1382,4 +1404,6 @@ with gr.Blocks(theme=theme, css="footer {visibility: hidden}textbox{resize:none}
1382
  gr.Markdown(f"If you use this data in your publication, please cite us!\n\nCopy the BibTeX citation to cite this source:\n\n```bibtext\n{CITATION_TEXT}\n```\n\nPlease remember that all generated audio clips should be assumed unsuitable for redistribution or commercial use.")
1383
 
1384
 
1385
- demo.queue(api_open=False, default_concurrency_limit=40).launch(show_api=False, show_error=True)
 
 
 
437
  INSTR = """
438
  ## πŸ—³οΈ Vote
439
 
440
+ * Input text (πŸ‡ΊπŸ‡Έ English only) to synthesize audio.
441
+ * Press ⚑ to get cached sample pairs you've yet to vote on. (Fast πŸ‡)
442
+ * Press 🎲 to randomly use text from a preselected list. (Slow 🐌)
443
  * Listen to the two audio clips, one after the other.
444
  * Vote on which audio sounds more natural to you.
445
  * _Note: Model names are revealed after the vote is cast._
 
665
  title = model_name
666
  else:
667
  style += 'font-style: italic;'
668
+ title = 'Got disabled for Arena (See AVAILABLE_MODELS within code for why)'
669
 
670
  model_basename = model_name
671
  if model_name in HF_SPACES:
 
970
  attempt_count += 1
971
  print(repr(e))
972
  print(f"{model}: Unable to call API (attempt: {attempt_count})")
973
+ # sleep for three seconds
974
+ time.sleep(3)
975
 
976
  # Fetch and store client again
977
  #hf_clients[model] = Client(model, hf_token=hf_token)
 
1141
  def play_other(bplayed):
1142
  return bplayed
1143
 
1144
+ def get_userid(session_hash: str, request):
1145
+ # JS cookie
1146
+ if (session_hash != ''):
1147
+ # print('auth by session cookie')
1148
+ return sha1(bytes(session_hash.encode('ascii')), usedforsecurity=False).hexdigest()
1149
+
1150
  if request.username:
1151
  # print('auth by username')
1152
+ # by HuggingFace username - requires `auth` to be enabled therefore denying access to anonymous users
1153
+ return sha1(bytes(request.username.encode('ascii')), usedforsecurity=False).hexdigest()
1154
  else:
1155
  # print('auth by ip')
1156
+ # by IP address - unreliable when gradio within HTML iframe
1157
+ # return sha1(bytes(request.client.host.encode('ascii')), usedforsecurity=False).hexdigest()
1158
+ # by browser session cookie - Gradio on HF is run in an HTML iframe, access to parent session required to reach session token
1159
+ # return sha1(bytes(request.headers.encode('ascii'))).hexdigest()
1160
+ # by browser session hash - Not a cookie, session hash changes on page reload
1161
+ return sha1(bytes(request.session_hash.encode('ascii')), usedforsecurity=False).hexdigest()
1162
 
1163
  # Give user a cached audio sample pair they have yet to vote on
1164
+ def give_cached_sample(session_hash: str, request: gr.Request):
1165
  # add new userid to voting_users from Browser session hash
1166
  # stored only in RAM
1167
+ userid = get_userid(session_hash, request)
 
1168
 
1169
  if userid not in voting_users:
1170
  voting_users[userid] = User(userid)
 
1188
 
1189
  pair = get_next_pair(voting_users[userid])
1190
  if pair is None:
1191
+ return [
1192
+ *clear_stuff(),
1193
+ # disable get cached sample button
1194
+ gr.update(interactive=False)
1195
+ ]
1196
 
1197
  return (
1198
  pair[0].transcript,
 
1215
  )
1216
 
1217
  # note the vote on cached sample pair
1218
+ def voted_on_cached(modelName1: str, modelName2: str, transcript: str, session_hash: str, request: gr.Request):
1219
+ userid = get_userid(session_hash, request)
1220
  print(f'userid voted on cached: {userid}')
1221
 
1222
  if userid not in voting_users:
 
1251
  return [gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False)]
1252
  def enable():
1253
  return [gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)]
1254
+
1255
+
1256
  with gr.Blocks() as vote:
1257
+ session_hash = gr.Textbox(visible=False, value='')
1258
+
1259
  # sample played, using Checkbox so that JS can fetch the value
1260
  aplayed = gr.Checkbox(visible=False, value=False)
1261
  bplayed = gr.Checkbox(visible=False, value=False)
 
1298
  )
1299
  bbetter = gr.Button("B is better", variant='primary', interactive=False)
1300
  prevmodel2 = gr.HTML(show_label=False, value="Vote to reveal model B", visible=False)
1301
+ nxtroundbtn = gr.Button('⚑ Next round', visible=False)
1302
  # outputs = [text, btn, r2, model1, model2, prevmodel1, aud1, prevmodel2, aud2, abetter, bbetter]
1303
  outputs = [
1304
  text,
 
1333
  .click(disable, outputs=[btn, abetter, bbetter, cachedt])\
1334
  .then(synthandreturn, inputs=[text], outputs=outputs)\
1335
  .then(enable, outputs=[btn, gr.State(), gr.State(), cachedt])
1336
+ nxtroundbtn\
1337
+ .click(disable, outputs=[btn, abetter, bbetter, cachedt])\
1338
+ .then(give_cached_sample, inputs=[session_hash], outputs=[*outputs, cachedt])\
1339
+ .then(enable, outputs=[btn, gr.State(), gr.State(), gr.State()])
1340
 
1341
  # fetch a comparison pair from cache
1342
  cachedt\
1343
  .click(disable, outputs=[btn, abetter, bbetter, cachedt])\
1344
+ .then(give_cached_sample, inputs=[session_hash], outputs=[*outputs, cachedt])\
1345
+ .then(enable, outputs=[btn, gr.State(), gr.State(), gr.State()])
1346
+ # TODO: await download of sample before allowing playback
1347
 
1348
  # Allow interaction with the vote buttons only when both audio samples have finished playing
1349
  aud1\
 
1369
  nxt_outputs = [abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
1370
  abetter\
1371
  .click(a_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])\
1372
+ .then(voted_on_cached, inputs=[model1, model2, text, session_hash])
1373
  bbetter\
1374
  .click(b_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])\
1375
+ .then(voted_on_cached, inputs=[model1, model2, text, session_hash])
1376
  # skipbtn.click(b_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
1377
 
1378
  # bothbad.click(both_bad, outputs=outputs, inputs=[model1, model2, useridstate])
1379
  # bothgood.click(both_good, outputs=outputs, inputs=[model1, model2, useridstate])
1380
 
1381
+ vote.load(
1382
+ None,
1383
+ None,
1384
+ session_hash,
1385
+ js="() => { return getArenaCookie('session') }",
1386
+ )
1387
 
1388
  with gr.Blocks() as about:
1389
  gr.Markdown(ABOUT)
 
1394
  # dbtext = gr.Textbox(label="Type \"delete db\" to confirm", placeholder="delete db")
1395
  # ddb = gr.Button("Delete DB")
1396
  # ddb.click(del_db, inputs=dbtext, outputs=ddb)
1397
+ with gr.Blocks(theme=theme, css="footer {visibility: hidden}textbox{resize:none}", js="cookie.js", title="TTS Arena") as demo:
1398
  gr.Markdown(DESCR)
1399
  # gr.TabbedInterface([vote, leaderboard, about, admin], ['Vote', 'Leaderboard', 'About', 'Admin (ONLY IN BETA)'])
1400
  gr.TabbedInterface([vote, leaderboard, about], ['πŸ—³οΈ Vote', 'πŸ† Leaderboard', 'πŸ“„ About'])
 
1404
  gr.Markdown(f"If you use this data in your publication, please cite us!\n\nCopy the BibTeX citation to cite this source:\n\n```bibtext\n{CITATION_TEXT}\n```\n\nPlease remember that all generated audio clips should be assumed unsuitable for redistribution or commercial use.")
1405
 
1406
 
1407
+ demo\
1408
+ .queue(api_open=False, default_concurrency_limit=40)\
1409
+ .launch(show_api=False, show_error=True)
cookie.js ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function () {
2
+ window.getArenaCookie = function getArenaCookie(cname) {
3
+ let name = cname + "=";
4
+ let decodedCookie = decodeURIComponent(window.document.cookie);
5
+ let ca = decodedCookie.split(';');
6
+ for (let i = 0; i < ca.length; i++) {
7
+ let c = ca[i];
8
+ while (c.charAt(0) == ' ') {
9
+ c = c.substring(1);
10
+ }
11
+ if (c.indexOf(name) == 0) {
12
+ return c.substring(name.length, c.length);
13
+ }
14
+ }
15
+ return "";
16
+ }
17
+
18
+ window.setArenaCookie = function setArenaCookie(cname, cvalue, exdays) {
19
+ const d = new Date();
20
+ d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
21
+ let expires = "expires=" + d.toUTCString();
22
+ window.document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
23
+ }
24
+
25
+ if (window.getArenaCookie('session').length == 0)
26
+ {
27
+ const d = new Date();
28
+ window.setArenaCookie('session', d.getTime().toString(), 90);
29
+ console.log('Session cookie created')
30
+ }
31
+ }