Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -7,7 +7,6 @@ import spaces
|
|
7 |
tokenizer = AutoTokenizer.from_pretrained("gpt2")
|
8 |
model = AutoModelForCausalLM.from_pretrained("gpt2")
|
9 |
|
10 |
-
tokenizer.pad_token_id = tokenizer.eos_token_id
|
11 |
print("Loading finished.")
|
12 |
|
13 |
print(f"Is CUDA available: {torch.cuda.is_available()}")
|
@@ -174,22 +173,13 @@ a:before {
|
|
174 |
"""
|
175 |
|
176 |
|
177 |
-
def
|
178 |
-
"""
|
179 |
-
|
180 |
-
html_content = f" <li> <a href='#' class='{('chosen' if node.table is None else '')}' id='{('root' if step==0 else '')}'> <span> <b>{token}</b> </span> "
|
181 |
-
html_content += node.table if node.table is not None else ""
|
182 |
-
html_content += "</a>"
|
183 |
-
if len(node.children.keys()) > 0:
|
184 |
-
html_content += "<ul> "
|
185 |
-
for token, subnode in node.children.items():
|
186 |
-
html_content += generate_nodes(token, subnode, step=step + 1)
|
187 |
-
html_content += "</ul>"
|
188 |
-
html_content += "</li>"
|
189 |
-
return html_content
|
190 |
|
191 |
|
192 |
-
def generate_markdown_table(
|
|
|
|
|
193 |
markdown_table = """
|
194 |
<table>
|
195 |
<tr>
|
@@ -204,21 +194,41 @@ def generate_markdown_table(scores, sequence_prob, top_k=4, chosen_tokens=None):
|
|
204 |
item_class = "chosen"
|
205 |
markdown_table += f"""
|
206 |
<tr class={item_class}>
|
207 |
-
<td>{token}</td>
|
208 |
<td>{scores[token_idx]:.4f}</td>
|
209 |
-
<td>{scores[token_idx] +
|
210 |
</tr>"""
|
211 |
markdown_table += """
|
212 |
</table>"""
|
213 |
return markdown_table
|
214 |
|
215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
def generate_html(start_sentence, original_tree):
|
217 |
|
218 |
-
html_output = """<div class="custom-container">
|
219 |
<div class="tree">
|
220 |
-
<ul>
|
221 |
-
|
|
|
|
|
|
|
|
|
|
|
222 |
|
223 |
html_output += """
|
224 |
</ul>
|
@@ -236,16 +246,21 @@ from dataclasses import dataclass
|
|
236 |
@dataclass
|
237 |
class BeamNode:
|
238 |
cumulative_score: float
|
|
|
239 |
table: str
|
240 |
current_sentence: str
|
241 |
-
children: Dict[
|
242 |
|
243 |
|
244 |
-
def generate_beams(start_sentence, scores, sequences,
|
245 |
-
print(tokenizer.batch_decode(sequences))
|
246 |
sequences = sequences.cpu().numpy()
|
|
|
247 |
original_tree = BeamNode(
|
248 |
-
cumulative_score=0,
|
|
|
|
|
|
|
|
|
249 |
)
|
250 |
n_beams = len(scores[0])
|
251 |
beam_trees = [original_tree] * n_beams
|
@@ -302,6 +317,7 @@ def generate_beams(start_sentence, scores, sequences, beam_indices):
|
|
302 |
markdown_table = generate_markdown_table(
|
303 |
step_scores[beam_ix, :],
|
304 |
current_beam.cumulative_score,
|
|
|
305 |
chosen_tokens=list(selected_tokens["token"].values),
|
306 |
)
|
307 |
beam_trees[beam_ix].table = markdown_table
|
@@ -315,18 +331,18 @@ def generate_beams(start_sentence, scores, sequences, beam_indices):
|
|
315 |
# Update the source tree
|
316 |
source_beam_ix = int(top_df_selected.iloc[beam_ix]["beam_index"])
|
317 |
|
318 |
-
|
319 |
-
|
|
|
|
|
|
|
320 |
table=None,
|
321 |
children={},
|
322 |
current_sentence=beam_trees[source_beam_ix].current_sentence
|
323 |
+ current_token_choice,
|
324 |
-
cumulative_score=
|
325 |
-
+
|
326 |
)
|
327 |
-
assert (
|
328 |
-
len(str(original_tree)) > previous_len
|
329 |
-
), "Original tree has not increased size"
|
330 |
|
331 |
# Reassign all beams at once
|
332 |
beam_trees = [
|
@@ -337,12 +353,12 @@ def generate_beams(start_sentence, scores, sequences, beam_indices):
|
|
337 |
# Advance all beams by one token
|
338 |
for beam_ix in range(n_beams):
|
339 |
current_token_choice_ix = top_df_selected.iloc[beam_ix]["token_index"]
|
340 |
-
|
341 |
-
|
342 |
return original_tree
|
343 |
|
344 |
@spaces.GPU
|
345 |
-
def get_beam_search_html(input_text, number_steps, number_beams):
|
346 |
inputs = tokenizer([input_text], return_tensors="pt")
|
347 |
|
348 |
outputs = model.generate(
|
@@ -351,19 +367,21 @@ def get_beam_search_html(input_text, number_steps, number_beams):
|
|
351 |
num_beams=number_beams,
|
352 |
num_return_sequences=number_beams,
|
353 |
return_dict_in_generate=True,
|
|
|
354 |
output_scores=True,
|
355 |
-
top_k=5,
|
356 |
do_sample=False,
|
357 |
)
|
|
|
|
|
|
|
358 |
|
359 |
original_tree = generate_beams(
|
360 |
input_text,
|
361 |
outputs.scores[:],
|
362 |
outputs.sequences[:, :],
|
363 |
-
|
364 |
)
|
365 |
html = generate_html(input_text, original_tree)
|
366 |
-
print(html)
|
367 |
return html
|
368 |
|
369 |
|
@@ -374,10 +392,12 @@ with gr.Blocks(
|
|
374 |
css=STYLE,
|
375 |
) as demo:
|
376 |
text = gr.Textbox(label="Sentence to decode from", value="Today is")
|
377 |
-
|
378 |
-
|
|
|
|
|
379 |
button = gr.Button()
|
380 |
out = gr.Markdown(label="Output")
|
381 |
-
button.click(get_beam_search_html, inputs=[text, steps, beams], outputs=out)
|
382 |
|
383 |
demo.launch()
|
|
|
7 |
tokenizer = AutoTokenizer.from_pretrained("gpt2")
|
8 |
model = AutoModelForCausalLM.from_pretrained("gpt2")
|
9 |
|
|
|
10 |
print("Loading finished.")
|
11 |
|
12 |
print(f"Is CUDA available: {torch.cuda.is_available()}")
|
|
|
173 |
"""
|
174 |
|
175 |
|
176 |
+
def clean(s):
|
177 |
+
return s.replace("\n", r"\n").replace("\t", r"\t")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
|
180 |
+
def generate_markdown_table(
|
181 |
+
scores, previous_cumul_score, score_divider, top_k=4, chosen_tokens=None
|
182 |
+
):
|
183 |
markdown_table = """
|
184 |
<table>
|
185 |
<tr>
|
|
|
194 |
item_class = "chosen"
|
195 |
markdown_table += f"""
|
196 |
<tr class={item_class}>
|
197 |
+
<td>{clean(token)}</td>
|
198 |
<td>{scores[token_idx]:.4f}</td>
|
199 |
+
<td>{(scores[token_idx] + previous_cumul_score)/score_divider:.4f}</td>
|
200 |
</tr>"""
|
201 |
markdown_table += """
|
202 |
</table>"""
|
203 |
return markdown_table
|
204 |
|
205 |
|
206 |
+
def generate_nodes(token_ix, node, step):
|
207 |
+
"""Recursively generate HTML for the tree nodes."""
|
208 |
+
token = tokenizer.decode([token_ix])
|
209 |
+
html_content = f" <li> <a href='#' class='{('chosen' if node.table is None else '')}'> <span> <b>{token_ix}:<br>{clean(token)}</b> </span> "
|
210 |
+
html_content += node.table if node.table is not None else ""
|
211 |
+
html_content += "</a>"
|
212 |
+
if len(node.children.keys()) > 0:
|
213 |
+
html_content += "<ul> "
|
214 |
+
for token_ix, subnode in node.children.items():
|
215 |
+
html_content += generate_nodes(token_ix, subnode, step=step + 1)
|
216 |
+
html_content += "</ul>"
|
217 |
+
html_content += "</li>"
|
218 |
+
return html_content
|
219 |
+
|
220 |
+
|
221 |
def generate_html(start_sentence, original_tree):
|
222 |
|
223 |
+
html_output = f"""<div class="custom-container">
|
224 |
<div class="tree">
|
225 |
+
<ul>
|
226 |
+
<li> <a href='#' id='root'> <span> <b>{start_sentence}</b> </span> {original_tree.table} </a>"""
|
227 |
+
if len(original_tree.children.keys()) > 0:
|
228 |
+
html_output += "<ul> "
|
229 |
+
for token_ix, subnode in original_tree.children.items():
|
230 |
+
html_output += generate_nodes(token_ix, subnode, step=1)
|
231 |
+
html_output += "</ul>"
|
232 |
|
233 |
html_output += """
|
234 |
</ul>
|
|
|
246 |
@dataclass
|
247 |
class BeamNode:
|
248 |
cumulative_score: float
|
249 |
+
children_score_divider: float
|
250 |
table: str
|
251 |
current_sentence: str
|
252 |
+
children: Dict[int, "BeamNode"]
|
253 |
|
254 |
|
255 |
+
def generate_beams(start_sentence, scores, sequences, length_penalty):
|
|
|
256 |
sequences = sequences.cpu().numpy()
|
257 |
+
input_length = len(tokenizer([start_sentence], return_tensors="pt"))
|
258 |
original_tree = BeamNode(
|
259 |
+
cumulative_score=0,
|
260 |
+
table=None,
|
261 |
+
current_sentence=start_sentence,
|
262 |
+
children={},
|
263 |
+
children_score_divider=((input_length + 1) ** length_penalty),
|
264 |
)
|
265 |
n_beams = len(scores[0])
|
266 |
beam_trees = [original_tree] * n_beams
|
|
|
317 |
markdown_table = generate_markdown_table(
|
318 |
step_scores[beam_ix, :],
|
319 |
current_beam.cumulative_score,
|
320 |
+
current_beam.children_score_divider,
|
321 |
chosen_tokens=list(selected_tokens["token"].values),
|
322 |
)
|
323 |
beam_trees[beam_ix].table = markdown_table
|
|
|
331 |
# Update the source tree
|
332 |
source_beam_ix = int(top_df_selected.iloc[beam_ix]["beam_index"])
|
333 |
|
334 |
+
cumulative_score = (
|
335 |
+
cumulative_scores[source_beam_ix]
|
336 |
+
+ scores[step][source_beam_ix][current_token_choice_ix].numpy()
|
337 |
+
)
|
338 |
+
beam_trees[source_beam_ix].children[current_token_choice_ix] = BeamNode(
|
339 |
table=None,
|
340 |
children={},
|
341 |
current_sentence=beam_trees[source_beam_ix].current_sentence
|
342 |
+ current_token_choice,
|
343 |
+
cumulative_score=cumulative_score,
|
344 |
+
children_score_divider=((input_length + step + 1) ** length_penalty),
|
345 |
)
|
|
|
|
|
|
|
346 |
|
347 |
# Reassign all beams at once
|
348 |
beam_trees = [
|
|
|
353 |
# Advance all beams by one token
|
354 |
for beam_ix in range(n_beams):
|
355 |
current_token_choice_ix = top_df_selected.iloc[beam_ix]["token_index"]
|
356 |
+
beam_trees[beam_ix] = beam_trees[beam_ix].children[current_token_choice_ix]
|
357 |
+
|
358 |
return original_tree
|
359 |
|
360 |
@spaces.GPU
|
361 |
+
def get_beam_search_html(input_text, number_steps, number_beams, length_penalty):
|
362 |
inputs = tokenizer([input_text], return_tensors="pt")
|
363 |
|
364 |
outputs = model.generate(
|
|
|
367 |
num_beams=number_beams,
|
368 |
num_return_sequences=number_beams,
|
369 |
return_dict_in_generate=True,
|
370 |
+
length_penalty=-10.0,
|
371 |
output_scores=True,
|
|
|
372 |
do_sample=False,
|
373 |
)
|
374 |
+
print("Sequences:")
|
375 |
+
print(tokenizer.batch_decode(outputs.sequences))
|
376 |
+
print("Scores:", outputs.sequences_scores)
|
377 |
|
378 |
original_tree = generate_beams(
|
379 |
input_text,
|
380 |
outputs.scores[:],
|
381 |
outputs.sequences[:, :],
|
382 |
+
length_penalty,
|
383 |
)
|
384 |
html = generate_html(input_text, original_tree)
|
|
|
385 |
return html
|
386 |
|
387 |
|
|
|
392 |
css=STYLE,
|
393 |
) as demo:
|
394 |
text = gr.Textbox(label="Sentence to decode from", value="Today is")
|
395 |
+
with gr.Row():
|
396 |
+
steps = gr.Slider(label="Number of steps", minimum=1, maximum=8, step=1, value=4)
|
397 |
+
beams = gr.Slider(label="Number of beams", minimum=2, maximum=4, step=1, value=3)
|
398 |
+
length_penalty = gr.Slider(label="Length penalty", minimum=-5, maximum=5, step=0.5, value=1)
|
399 |
button = gr.Button()
|
400 |
out = gr.Markdown(label="Output")
|
401 |
+
button.click(get_beam_search_html, inputs=[text, steps, beams, length_penalty], outputs=out)
|
402 |
|
403 |
demo.launch()
|