Commit
·
9e46f6d
1
Parent(s):
89ce915
First functional version
Browse files- .gitattributes +0 -1
- README.md +3 -3
- app.py +158 -0
- requirements.txt +3 -0
- resources.py +17 -0
.gitattributes
CHANGED
@@ -21,7 +21,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
21 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
22 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
23 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
25 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
26 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
27 |
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
|
|
21 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
22 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
23 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
|
|
24 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
25 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
26 |
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
---
|
2 |
title: Gastronomia_para_to2
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
sdk_version: 2.9.0
|
8 |
app_file: app.py
|
|
|
1 |
---
|
2 |
title: Gastronomia_para_to2
|
3 |
+
emoji: 👩🏻🍳🍳🍳🧑🏻🍳
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: gray
|
6 |
sdk: gradio
|
7 |
sdk_version: 2.9.0
|
8 |
app_file: app.py
|
app.py
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
3 |
+
import re
|
4 |
+
from resources import banner, error_html_response
|
5 |
+
|
6 |
+
model_checkpoint = 'gastronomia-para-to2/gastronomia_para_to2'
|
7 |
+
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
|
8 |
+
model = AutoModelForCausalLM.from_pretrained(model_checkpoint)
|
9 |
+
|
10 |
+
special_tokens = [
|
11 |
+
'<INPUT_START>',
|
12 |
+
'<NEXT_INPUT>',
|
13 |
+
'<INPUT_END>',
|
14 |
+
'<TITLE_START>',
|
15 |
+
'<TITLE_END>',
|
16 |
+
'<INGR_START>',
|
17 |
+
'<NEXT_INGR>',
|
18 |
+
'<INGR_END>',
|
19 |
+
'<INSTR_START>',
|
20 |
+
'<NEXT_INSTR>',
|
21 |
+
'<INSTR_END>']
|
22 |
+
|
23 |
+
def frame_html_response(html_response):
|
24 |
+
return f"""<iframe style="width: 100%; height: 800px" name="result" allow="midi; geolocation; microphone; camera;
|
25 |
+
display-capture; encrypted-media;" sandbox="allow-modals allow-forms
|
26 |
+
allow-scripts allow-same-origin allow-popups
|
27 |
+
allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
|
28 |
+
allowpaymentrequest="" frameborder="0" srcdoc='{html_response}'></iframe>"""
|
29 |
+
|
30 |
+
|
31 |
+
def check_special_tokens_order(pre_output):
|
32 |
+
return (pre_output.find('<INPUT_START>') <
|
33 |
+
pre_output.find('<NEXT_INPUT>') <=
|
34 |
+
pre_output.rfind('<NEXT_INPUT>') <
|
35 |
+
pre_output.find('<INPUT_END>') <
|
36 |
+
pre_output.find('<INGR_START>') <
|
37 |
+
pre_output.find('<NEXT_INGR>') <=
|
38 |
+
pre_output.rfind('<NEXT_INGR>') <
|
39 |
+
pre_output.find('<INGR_END>') <
|
40 |
+
pre_output.find('<INSTR_START>') <
|
41 |
+
pre_output.find('<NEXT_INSTR>') <=
|
42 |
+
pre_output.rfind('<NEXT_INSTR>') <
|
43 |
+
pre_output.find('<INSTR_END>') <
|
44 |
+
pre_output.find('<TITLE_START>') <
|
45 |
+
pre_output.find('<TITLE_END>'))
|
46 |
+
|
47 |
+
|
48 |
+
def make_html_response(title, ingredients, instructions):
|
49 |
+
ingredients_html_list = '<ul><li>' + '</li><li>'.join(ingredients) + '</li></ul>'
|
50 |
+
instructions_html_list = '<ol><li>' + '</li><li>'.join(instructions) + '</li></ol>'
|
51 |
+
|
52 |
+
html_response = f'''
|
53 |
+
<!DOCTYPE html>
|
54 |
+
<html>
|
55 |
+
<body>
|
56 |
+
<h1>{title}</h1>
|
57 |
+
|
58 |
+
<h2>Ingredientes</h2>
|
59 |
+
{ingredients_html_list}
|
60 |
+
|
61 |
+
<h2>Instrucciones</h2>
|
62 |
+
{instructions_html_list}
|
63 |
+
|
64 |
+
</body>
|
65 |
+
</html>
|
66 |
+
'''
|
67 |
+
return html_response
|
68 |
+
|
69 |
+
|
70 |
+
def rerun_model_output(pre_output):
|
71 |
+
if pre_output is None:
|
72 |
+
return True
|
73 |
+
elif not '<RECIPE_END>' in pre_output:
|
74 |
+
print('<RECIPE_END> not in pre_output')
|
75 |
+
return True
|
76 |
+
pre_output_trimmed = pre_output[:pre_output.find('<RECIPE_END>')]
|
77 |
+
if not all(special_token in pre_output_trimmed for special_token in special_tokens):
|
78 |
+
print('Not all special tokens are in preoutput')
|
79 |
+
return True
|
80 |
+
elif not check_special_tokens_order(pre_output_trimmed):
|
81 |
+
print('Special tokens are unordered in preoutput')
|
82 |
+
return True
|
83 |
+
elif len(pre_output_trimmed.split())<75:
|
84 |
+
print('Length of the recipe is <75')
|
85 |
+
return True
|
86 |
+
else:
|
87 |
+
return False
|
88 |
+
|
89 |
+
|
90 |
+
def generate_output(tokenized_input):
|
91 |
+
pre_output = None
|
92 |
+
while rerun_model_output(pre_output):
|
93 |
+
output = model.generate(**tokenized_input,
|
94 |
+
max_length=600,
|
95 |
+
do_sample=True,
|
96 |
+
top_p=0.92,
|
97 |
+
top_k=50,
|
98 |
+
# no_repeat_ngram_size=2,
|
99 |
+
num_return_sequences=3)
|
100 |
+
pre_output = tokenizer.decode(output[0], skip_special_tokens=False)
|
101 |
+
pre_output_trimmed = pre_output[:pre_output.find('<RECIPE_END>')]
|
102 |
+
return pre_output_trimmed
|
103 |
+
|
104 |
+
|
105 |
+
def check_wrong_ingredients(ingredients):
|
106 |
+
if ingredients is None:
|
107 |
+
return True
|
108 |
+
if any(ingredient.startswith('De') for ingredient in ingredients):
|
109 |
+
print('At least one ingredient starts with De')
|
110 |
+
return True
|
111 |
+
|
112 |
+
|
113 |
+
def make_recipe(input_ingredients):
|
114 |
+
input_ingredients = re.sub(' y ', ', ', input_ingredients)
|
115 |
+
input = '<RECIPE_START> '
|
116 |
+
input += '<INPUT_START> ' + ' <NEXT_INPUT> '.join(input_ingredients.split(', ')) + ' <INPUT_END> '
|
117 |
+
input += '<INGR_START> '
|
118 |
+
tokenized_input = tokenizer(input, return_tensors='pt')
|
119 |
+
|
120 |
+
output_ingredients = None
|
121 |
+
i = 0
|
122 |
+
while check_wrong_ingredients(output_ingredients):
|
123 |
+
if i == 4:
|
124 |
+
return frame_html_response(error_html_response)
|
125 |
+
pre_output_trimmed = generate_output(tokenized_input)
|
126 |
+
output_ingredients = re.search('<INGR_START> (.*) <INGR_END>', pre_output_trimmed).group(1)
|
127 |
+
output_ingredients = output_ingredients.split(' <NEXT_INGR> ')
|
128 |
+
output_ingredients = list(set([output_ingredient.strip() for output_ingredient in output_ingredients]))
|
129 |
+
output_ingredients = [output_ing.capitalize() for output_ing in output_ingredients]
|
130 |
+
i += 1
|
131 |
+
|
132 |
+
output_title = re.search('<TITLE_START> (.*) <TITLE_END>', pre_output_trimmed).group(1).strip().capitalize()
|
133 |
+
output_instructions = re.search('<INSTR_START> (.*) <INSTR_END>', pre_output_trimmed).group(1)
|
134 |
+
output_instructions = output_instructions.split(' <NEXT_INSTR> ')
|
135 |
+
|
136 |
+
html_response = make_html_response(output_title, output_ingredients, output_instructions)
|
137 |
+
|
138 |
+
return frame_html_response(html_response)
|
139 |
+
|
140 |
+
|
141 |
+
iface = gr.Interface(
|
142 |
+
fn=make_recipe,
|
143 |
+
inputs=
|
144 |
+
[
|
145 |
+
gr.inputs.Textbox(lines=1, placeholder='ingrediente_1, ingrediente_2, ..., ingrediente_n',
|
146 |
+
label='Dime con qué ingredientes quieres que cocinemos hoy y te sugeriremos una receta tan pronto como nuestros fogones estén libres'),
|
147 |
+
],
|
148 |
+
outputs=
|
149 |
+
[
|
150 |
+
gr.outputs.HTML(label="¡Esta es mi propuesta para ti! ¡Buen provecho!")
|
151 |
+
],
|
152 |
+
examples=
|
153 |
+
[
|
154 |
+
['salmón, zumo de naranja, aceite de oliva, sal, pimienta'],
|
155 |
+
['harina, azúcar, huevos, chocolate, levadura Royal']
|
156 |
+
],
|
157 |
+
description=banner)
|
158 |
+
iface.launch(enable_queue=True)
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
transformers
|
3 |
+
torch
|
resources.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
banner = """
|
2 |
+
<img src="https://huggingface.co/spaces/gastronomia-para-to2/gastronomia_para_to2/resolve/main/Gastronomia_para_to2_logo.jpg" style="max-width: 100%; max-height: 90%; object-fit: fill">
|
3 |
+
"""
|
4 |
+
|
5 |
+
error_html_response = f'''
|
6 |
+
<!DOCTYPE html>
|
7 |
+
<html>
|
8 |
+
<body>
|
9 |
+
<h2>Ups... </h2>
|
10 |
+
|
11 |
+
Nuestro chef está encontrando dificultades para crear una receta con los ingredientes que has indicado.
|
12 |
+
Echa un vistazo a tu nevera y prueba a añadir algún ingrediente más.
|
13 |
+
¡Seguro que esta vez conseguimos sugerirte una receta exquisita!
|
14 |
+
|
15 |
+
</body>
|
16 |
+
</html>
|
17 |
+
'''
|