jucendrero commited on
Commit
9e46f6d
1 Parent(s): 89ce915

First functional version

Browse files
Files changed (5) hide show
  1. .gitattributes +0 -1
  2. README.md +3 -3
  3. app.py +158 -0
  4. requirements.txt +3 -0
  5. 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: green
5
- colorTo: blue
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
+ '''