Spaces:
Running
Running
sample caching
Browse files- app/cookie.js +30 -0
- app/synth.py +28 -21
- app/ui.py +1 -0
- app/ui_vote.py +37 -27
- app/vote.py +45 -33
app/cookie.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
window.getArenaCookie = function getArenaCookie(cname) {
|
2 |
+
let name = cname + "=";
|
3 |
+
let decodedCookie = decodeURIComponent(window.document.cookie);
|
4 |
+
let ca = decodedCookie.split(';');
|
5 |
+
for (let i = 0; i < ca.length; i++) {
|
6 |
+
let c = ca[i];
|
7 |
+
while (c.charAt(0) == ' ') {
|
8 |
+
c = c.substring(1);
|
9 |
+
}
|
10 |
+
if (c.indexOf(name) == 0) {
|
11 |
+
return c.substring(name.length, c.length);
|
12 |
+
}
|
13 |
+
}
|
14 |
+
return "";
|
15 |
+
}
|
16 |
+
|
17 |
+
window.setArenaCookie = function setArenaCookie(cname, cvalue, exdays) {
|
18 |
+
const d = new Date();
|
19 |
+
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
20 |
+
let expires = "expires=" + d.toUTCString();
|
21 |
+
window.document.cookie = cname + "=" + cvalue + ";" + expires + "; path=/; SameSite=None; Secure";
|
22 |
+
}
|
23 |
+
|
24 |
+
if (window.getArenaCookie('session').length == 0)
|
25 |
+
{
|
26 |
+
const d = new Date();
|
27 |
+
// store cookie for 90 days, about the time the the cached audio should be deleted
|
28 |
+
window.setArenaCookie('session', d.getTime().toString(), 90);
|
29 |
+
console.log('Session cookie created')
|
30 |
+
}
|
app/synth.py
CHANGED
@@ -3,6 +3,7 @@ from .models import *
|
|
3 |
from .utils import *
|
4 |
from .config import *
|
5 |
from .init import *
|
|
|
6 |
|
7 |
import gradio as gr
|
8 |
from pydub import AudioSegment
|
@@ -203,6 +204,28 @@ def synthandreturn(text, autoplay, request: gr.Request):
|
|
203 |
|
204 |
return inputs
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
mdl1k = mdl1
|
207 |
mdl2k = mdl2
|
208 |
print(mdl1k, mdl2k)
|
@@ -222,10 +245,10 @@ def synthandreturn(text, autoplay, request: gr.Request):
|
|
222 |
):
|
223 |
# run Zero-GPU spaces one at a time
|
224 |
predict_and_update_result(text, mdl1k, results, request)
|
225 |
-
|
226 |
|
227 |
predict_and_update_result(text, mdl2k, results, request)
|
228 |
-
|
229 |
else:
|
230 |
# use multithreading
|
231 |
thread1 = threading.Thread(target=predict_and_update_result, args=(text, mdl1k, results, request))
|
@@ -240,8 +263,8 @@ def synthandreturn(text, autoplay, request: gr.Request):
|
|
240 |
thread2.join(120)
|
241 |
|
242 |
# cache the result
|
243 |
-
|
244 |
-
|
245 |
|
246 |
print(f"Retrieving models {mdl1k} and {mdl2k} from API")
|
247 |
return (
|
@@ -358,24 +381,8 @@ def synthandreturn_battle(text, mdl1, mdl2, autoplay):
|
|
358 |
gr.update(visible=False), #nxt round btn
|
359 |
)
|
360 |
|
361 |
-
# Unlock vote
|
362 |
-
|
363 |
-
def unlock_vote(btn_index, aplayed, bplayed):
|
364 |
-
# sample played
|
365 |
-
if btn_index == 0:
|
366 |
-
aplayed = gr.State(value=True)
|
367 |
-
if btn_index == 1:
|
368 |
-
bplayed = gr.State(value=True)
|
369 |
-
|
370 |
-
# both audio samples played
|
371 |
-
if bool(aplayed) and bool(bplayed):
|
372 |
-
print('Both audio samples played, voting unlocked')
|
373 |
-
return [gr.update(interactive=True), gr.update(interactive=True), gr.update(), gr.update()]
|
374 |
-
|
375 |
-
return [gr.update(), gr.update(), aplayed, bplayed]
|
376 |
-
|
377 |
def randomsent():
|
378 |
-
return random.choice(sents), '🎲'
|
379 |
def randomsent_battle():
|
380 |
return tuple(randomsent()) + tuple(random_m())
|
381 |
def clear_stuff():
|
|
|
3 |
from .utils import *
|
4 |
from .config import *
|
5 |
from .init import *
|
6 |
+
from .sample_caching import *
|
7 |
|
8 |
import gradio as gr
|
9 |
from pydub import AudioSegment
|
|
|
204 |
|
205 |
return inputs
|
206 |
|
207 |
+
def _cache_sample(text, model):
|
208 |
+
# skip caching if not hardcoded sentence
|
209 |
+
if (text not in sents):
|
210 |
+
return False
|
211 |
+
|
212 |
+
already_cached = False
|
213 |
+
# check if already cached
|
214 |
+
for cached_sample in cached_samples:
|
215 |
+
# TODO:replace cached with newer version
|
216 |
+
if (cached_sample.transcript == text and cached_sample.modelName == model):
|
217 |
+
already_cached = True
|
218 |
+
return True
|
219 |
+
|
220 |
+
if (already_cached):
|
221 |
+
return False
|
222 |
+
|
223 |
+
try:
|
224 |
+
cached_samples.append(Sample(results[model], text, model))
|
225 |
+
except:
|
226 |
+
print('Error when trying to cache sample')
|
227 |
+
return False
|
228 |
+
|
229 |
mdl1k = mdl1
|
230 |
mdl2k = mdl2
|
231 |
print(mdl1k, mdl2k)
|
|
|
245 |
):
|
246 |
# run Zero-GPU spaces one at a time
|
247 |
predict_and_update_result(text, mdl1k, results, request)
|
248 |
+
_cache_sample(text, mdl1k)
|
249 |
|
250 |
predict_and_update_result(text, mdl2k, results, request)
|
251 |
+
_cache_sample(text, mdl2k)
|
252 |
else:
|
253 |
# use multithreading
|
254 |
thread1 = threading.Thread(target=predict_and_update_result, args=(text, mdl1k, results, request))
|
|
|
263 |
thread2.join(120)
|
264 |
|
265 |
# cache the result
|
266 |
+
for model in [mdl1k, mdl2k]:
|
267 |
+
_cache_sample(text, model)
|
268 |
|
269 |
print(f"Retrieving models {mdl1k} and {mdl2k} from API")
|
270 |
return (
|
|
|
381 |
gr.update(visible=False), #nxt round btn
|
382 |
)
|
383 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
def randomsent():
|
385 |
+
return '⚡', random.choice(sents), '🎲'
|
386 |
def randomsent_battle():
|
387 |
return tuple(randomsent()) + tuple(random_m())
|
388 |
def clear_stuff():
|
app/ui.py
CHANGED
@@ -33,6 +33,7 @@ document.addEventListener('keypress', shortcuts, false);
|
|
33 |
|
34 |
"""
|
35 |
head_js += shortcut_js
|
|
|
36 |
head_js += '</script>'
|
37 |
|
38 |
with gr.Blocks() as about:
|
|
|
33 |
|
34 |
"""
|
35 |
head_js += shortcut_js
|
36 |
+
head_js += open("app/cookie.js").read()
|
37 |
head_js += '</script>'
|
38 |
|
39 |
with gr.Blocks() as about:
|
app/ui_vote.py
CHANGED
@@ -3,37 +3,23 @@ from .config import *
|
|
3 |
from .synth import *
|
4 |
from .vote import *
|
5 |
from .messages import *
|
|
|
6 |
|
7 |
blur_text_js = 'document.getElementById("arena-text-input").classList.add("blurred-text")'
|
8 |
unblur_text_js = 'document.getElementById("arena-text-input").classList.remove("blurred-text")'
|
9 |
|
10 |
def disable():
|
11 |
-
return [gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False)]
|
12 |
def enable():
|
13 |
-
return [gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)]
|
14 |
def blur_text():
|
15 |
return gr.update(elem_classes=['blurred-text'])
|
16 |
def unblur_text():
|
17 |
return gr.update(elem_classes=[])
|
18 |
|
19 |
-
def unlock_vote(autoplay, btn_index, aplayed, bplayed):
|
20 |
-
if autoplay == False:
|
21 |
-
return [gr.update(), gr.update(), aplayed, bplayed]
|
22 |
-
|
23 |
-
# sample played
|
24 |
-
if btn_index == 0:
|
25 |
-
aplayed = True
|
26 |
-
if btn_index == 1:
|
27 |
-
bplayed = True
|
28 |
-
|
29 |
-
# both audio samples played
|
30 |
-
if bool(aplayed) and bool(bplayed):
|
31 |
-
# print('Both audio samples played, voting unlocked')
|
32 |
-
return [gr.update(interactive=True), gr.update(interactive=True), True, True]
|
33 |
-
|
34 |
-
return [gr.update(), gr.update(), aplayed, bplayed]
|
35 |
-
|
36 |
with gr.Blocks() as vote:
|
|
|
|
|
37 |
# sample played, using Checkbox so that JS can fetch the value
|
38 |
aplayed = gr.Checkbox(visible=False, value=False)
|
39 |
bplayed = gr.Checkbox(visible=False, value=False)
|
@@ -42,6 +28,7 @@ with gr.Blocks() as vote:
|
|
42 |
gr.Markdown(INSTR)
|
43 |
with gr.Group():
|
44 |
with gr.Row():
|
|
|
45 |
text = gr.Textbox(
|
46 |
container=False,
|
47 |
show_label=False,
|
@@ -54,7 +41,7 @@ with gr.Blocks() as vote:
|
|
54 |
)
|
55 |
randomt = gr.Button('🎲', scale=0, min_width=0, variant='tool')
|
56 |
randomt\
|
57 |
-
.click(randomsent, outputs=[text, randomt])\
|
58 |
.then(None, js="() => "+ unblur_text_js)
|
59 |
btn = gr.Button("Synthesize", variant='primary')
|
60 |
model1 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=False)
|
@@ -138,19 +125,26 @@ with gr.Blocks() as vote:
|
|
138 |
gr.update(visible=False), #nxt round btn"""
|
139 |
# , concurrency_count=1, concurrency_id="sync_queue"
|
140 |
btn\
|
141 |
-
.click(disable, outputs=[btn, abetter, bbetter])\
|
142 |
.then(synthandreturn, inputs=[text, autoplay], outputs=outputs)\
|
143 |
-
.then(enable, outputs=[btn, gr.State(), gr.State()])\
|
144 |
.then(None, js="() => "+ unblur_text_js)
|
145 |
# Next Round ; blur text
|
146 |
nxtroundbtn\
|
147 |
.click(clear_stuff, outputs=outputs)\
|
148 |
-
.then(
|
149 |
-
.then(
|
150 |
-
.then(enable, outputs=[btn, gr.State(), gr.State()])
|
151 |
# blur text
|
152 |
nxtroundbtn.click(None, js="() => "+ blur_text_js)
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
# Allow interaction with the vote buttons only when both audio samples have finished playing
|
155 |
aud1\
|
156 |
.stop(
|
@@ -174,5 +168,21 @@ with gr.Blocks() as vote:
|
|
174 |
aud2.stop(None, inputs=[aplayed], js="(a) => a ? "+ unblur_text_js +" : 0;")
|
175 |
|
176 |
nxt_outputs = [abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
|
177 |
-
abetter
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
from .synth import *
|
4 |
from .vote import *
|
5 |
from .messages import *
|
6 |
+
from .sample_caching import *
|
7 |
|
8 |
blur_text_js = 'document.getElementById("arena-text-input").classList.add("blurred-text")'
|
9 |
unblur_text_js = 'document.getElementById("arena-text-input").classList.remove("blurred-text")'
|
10 |
|
11 |
def disable():
|
12 |
+
return [gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False)]
|
13 |
def enable():
|
14 |
+
return [gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)]
|
15 |
def blur_text():
|
16 |
return gr.update(elem_classes=['blurred-text'])
|
17 |
def unblur_text():
|
18 |
return gr.update(elem_classes=[])
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
with gr.Blocks() as vote:
|
21 |
+
session_hash = gr.Textbox(visible=False, value='')
|
22 |
+
|
23 |
# sample played, using Checkbox so that JS can fetch the value
|
24 |
aplayed = gr.Checkbox(visible=False, value=False)
|
25 |
bplayed = gr.Checkbox(visible=False, value=False)
|
|
|
28 |
gr.Markdown(INSTR)
|
29 |
with gr.Group():
|
30 |
with gr.Row():
|
31 |
+
cachedt = gr.Button('⚡', scale=0, min_width=0, variant='tool', interactive=True)
|
32 |
text = gr.Textbox(
|
33 |
container=False,
|
34 |
show_label=False,
|
|
|
41 |
)
|
42 |
randomt = gr.Button('🎲', scale=0, min_width=0, variant='tool')
|
43 |
randomt\
|
44 |
+
.click(randomsent, outputs=[cachedt, text, randomt])\
|
45 |
.then(None, js="() => "+ unblur_text_js)
|
46 |
btn = gr.Button("Synthesize", variant='primary')
|
47 |
model1 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=False)
|
|
|
125 |
gr.update(visible=False), #nxt round btn"""
|
126 |
# , concurrency_count=1, concurrency_id="sync_queue"
|
127 |
btn\
|
128 |
+
.click(disable, outputs=[btn, abetter, bbetter, cachedt])\
|
129 |
.then(synthandreturn, inputs=[text, autoplay], outputs=outputs)\
|
130 |
+
.then(enable, outputs=[btn, gr.State(), gr.State(), gr.State()])\
|
131 |
.then(None, js="() => "+ unblur_text_js)
|
132 |
# Next Round ; blur text
|
133 |
nxtroundbtn\
|
134 |
.click(clear_stuff, outputs=outputs)\
|
135 |
+
.then(disable, outputs=[btn, abetter, bbetter, cachedt])\
|
136 |
+
.then(give_cached_sample, inputs=[session_hash], outputs=[*outputs, cachedt])\
|
137 |
+
.then(enable, outputs=[btn, gr.State(), gr.State(), gr.State()])
|
138 |
# blur text
|
139 |
nxtroundbtn.click(None, js="() => "+ blur_text_js)
|
140 |
|
141 |
+
# fetch a comparison pair from cache
|
142 |
+
cachedt\
|
143 |
+
.click(disable, outputs=[btn, abetter, bbetter, cachedt])\
|
144 |
+
.then(give_cached_sample, inputs=[session_hash], outputs=[*outputs, cachedt])\
|
145 |
+
.then(enable, outputs=[btn, gr.State(), gr.State(), gr.State()])
|
146 |
+
# TODO: await download of sample before allowing playback
|
147 |
+
|
148 |
# Allow interaction with the vote buttons only when both audio samples have finished playing
|
149 |
aud1\
|
150 |
.stop(
|
|
|
168 |
aud2.stop(None, inputs=[aplayed], js="(a) => a ? "+ unblur_text_js +" : 0;")
|
169 |
|
170 |
nxt_outputs = [abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
|
171 |
+
abetter\
|
172 |
+
.click(a_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate, text])\
|
173 |
+
.then(voted_on_cached, inputs=[model1, model2, text, session_hash], outputs=[])
|
174 |
+
bbetter\
|
175 |
+
.click(b_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate, text])\
|
176 |
+
.then(voted_on_cached, inputs=[model1, model2, text, session_hash], outputs=[])
|
177 |
+
|
178 |
+
# get session cookie
|
179 |
+
vote\
|
180 |
+
.load(
|
181 |
+
None,
|
182 |
+
None,
|
183 |
+
session_hash,
|
184 |
+
js="() => { return getArenaCookie('session') }",
|
185 |
+
)
|
186 |
+
# give a cached sample pair to voter; .then() did not work here
|
187 |
+
vote\
|
188 |
+
.load(give_cached_sample, inputs=[session_hash, autoplay], outputs=[*outputs, cachedt])
|
app/vote.py
CHANGED
@@ -60,56 +60,68 @@ def b_is_better_battle(model1, model2, userid):
|
|
60 |
|
61 |
# A/B better
|
62 |
|
63 |
-
def a_is_better(model1, model2, userid,
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
raise gr.Error('Sorry, please try voting again.')
|
|
|
|
|
67 |
userid = mkuuid(userid)
|
68 |
if model1 and model2:
|
69 |
conn = get_db()
|
70 |
cursor = conn.cursor()
|
71 |
-
|
72 |
-
if
|
73 |
-
|
74 |
-
conn.commit()
|
75 |
else:
|
|
|
|
|
|
|
76 |
conn.commit()
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
userid = mkuuid(userid)
|
86 |
-
if model1 and model2:
|
87 |
-
conn = get_db()
|
88 |
-
cursor = conn.cursor()
|
89 |
-
cursor.execute('INSERT INTO votelog (username, chosen, rejected) VALUES (?, ?, ?)', (str(userid), model2, model1,))
|
90 |
-
if scheduler:
|
91 |
-
with scheduler.lock:
|
92 |
-
conn.commit()
|
93 |
else:
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
return reload(model1, model2, userid, chose_b=True)
|
99 |
|
100 |
-
|
101 |
|
|
|
102 |
def reload(chosenmodel1=None, chosenmodel2=None, userid=None, chose_a=False, chose_b=False):
|
|
|
|
|
103 |
out = [
|
104 |
gr.update(interactive=False, visible=False),
|
105 |
gr.update(interactive=False, visible=False)
|
106 |
]
|
|
|
107 |
if chose_a == True:
|
108 |
-
out.append(gr.update(value=f'Your vote: {chosenmodel1}',
|
109 |
-
out.append(gr.update(value=f'{chosenmodel2}',
|
110 |
else:
|
111 |
-
out.append(gr.update(value=f'{chosenmodel1}',
|
112 |
-
out.append(gr.update(value=f'Your vote: {chosenmodel2}',
|
113 |
out.append(gr.update(visible=True))
|
114 |
return out
|
115 |
|
|
|
60 |
|
61 |
# A/B better
|
62 |
|
63 |
+
def a_is_better(model1, model2, userid, text):
|
64 |
+
return is_better(model1, model2, userid, text, True)
|
65 |
+
def b_is_better(model1, model2, userid, text):
|
66 |
+
return is_better(model1, model2, userid, text, False)
|
67 |
+
|
68 |
+
def is_better(model1, model2, userid, text, chose_a):
|
69 |
+
if(
|
70 |
+
(
|
71 |
+
not model1 in AVAILABLE_MODELS.keys()
|
72 |
+
and not model1 in AVAILABLE_MODELS.values()
|
73 |
+
)
|
74 |
+
or (
|
75 |
+
not model2 in AVAILABLE_MODELS.keys()
|
76 |
+
and not model2 in AVAILABLE_MODELS.values()
|
77 |
+
)
|
78 |
+
):
|
79 |
raise gr.Error('Sorry, please try voting again.')
|
80 |
+
|
81 |
+
# userid is unique for each cast vote pair
|
82 |
userid = mkuuid(userid)
|
83 |
if model1 and model2:
|
84 |
conn = get_db()
|
85 |
cursor = conn.cursor()
|
86 |
+
sql_query = 'INSERT INTO votelog (username, chosen, rejected) VALUES (?, ?, ?)'
|
87 |
+
if chose_a:
|
88 |
+
cursor.execute(sql_query, (str(userid), model1, model2))
|
|
|
89 |
else:
|
90 |
+
cursor.execute(sql_query, (str(userid), model2, model1))
|
91 |
+
|
92 |
+
with scheduler.lock:
|
93 |
conn.commit()
|
94 |
+
# also retrieve primary key ID
|
95 |
+
cursor.execute('SELECT last_insert_rowid()')
|
96 |
+
votelogid = cursor.fetchone()[0]
|
97 |
+
cursor.close()
|
98 |
+
|
99 |
+
if chose_a:
|
100 |
+
upvote_model(model1, str(userid))
|
101 |
+
downvote_model(model2, str(userid))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
else:
|
103 |
+
upvote_model(model2, str(userid))
|
104 |
+
downvote_model(model1, str(userid))
|
105 |
+
log_text(text)
|
106 |
+
# log_text(text, votelogid)
|
|
|
107 |
|
108 |
+
return reload(model1, model2, userid, chose_a=chose_a, chose_b=(not chose_a))
|
109 |
|
110 |
+
# Reload
|
111 |
def reload(chosenmodel1=None, chosenmodel2=None, userid=None, chose_a=False, chose_b=False):
|
112 |
+
# chosenmodel1 = make_link_to_space(chosenmodel1)
|
113 |
+
# chosenmodel2 = make_link_to_space(chosenmodel2)
|
114 |
out = [
|
115 |
gr.update(interactive=False, visible=False),
|
116 |
gr.update(interactive=False, visible=False)
|
117 |
]
|
118 |
+
style = 'text-align: center; font-size: 1rem; margin-bottom: 0; padding: var(--input-padding)'
|
119 |
if chose_a == True:
|
120 |
+
out.append(gr.update(value=f'<p style="{style}">Your vote: {chosenmodel1}</p>', visible=True))
|
121 |
+
out.append(gr.update(value=f'<p style="{style}">{chosenmodel2}</p>', visible=True))
|
122 |
else:
|
123 |
+
out.append(gr.update(value=f'<p style="{style}">{chosenmodel1}</p>', visible=True))
|
124 |
+
out.append(gr.update(value=f'<p style="{style}">Your vote: {chosenmodel2}</p>', visible=True))
|
125 |
out.append(gr.update(visible=True))
|
126 |
return out
|
127 |
|