def respond_to_step(text, recipe_id): """Respond to: 'what is step <X>?' """ # Which step is required? match = re.search('step[s]? (?P<step_num>\w+)', text) step_str = match.group('step_num') try: step_num = int(step_str) except ValueError: step_num = text2int(step_str) # What are the steps in the recipe? recipe_info_str = json.loads(get_recipe_info(recipe_id)) recipe_info = recipe_info_str['response'] raw_instructions = recipe_info["Instructions"].replace('\r', '').replace('\n', '') instructions = raw_instructions.split('. ') num_instructions = len(instructions) # Construct response if step_num > num_instructions: response = "Step %d does not exist. There are %d steps." % (step_num, num_instructions) else: response = instructions[step_num-1] return json.dumps({'response' : response})
def respond_to_step_use(text, recipe_id): """Respond to where do i use <X>? """ # What is the ingredient? # Detect by simple pattern matching match = re.search('where do i use (?P<ing>[\w -]+)', text) query_ingredient = match.group('ing') # Clean up recipe tokens # a. tokenize the ingredients recipe_tokens = nltk.word_tokenize(query_ingredient) # b. stem the tokens recipe_tokens = set([stemmer.stem(token) for token in recipe_tokens]) # c. remove stop words recipe_tokens = set([token for token in recipe_tokens if token not in stop]) # Iterate over steps, find relevant steps, add with a score # What are the steps in the recipe? recipe_info_str = json.loads(get_recipe_info(recipe_id)) recipe_info = recipe_info_str['response'] raw_instructions = recipe_info["Instructions"].replace('\r', '').replace('\n', '') instructions = raw_instructions.split('. ') num_instructions = len(instructions) candidates = [] for idx, instruc in enumerate(instructions): instruc_tokens = nltk.word_tokenize(instruc) instruc_tokens = [stemmer.stem(token) for token in instruc_tokens] instruc_tokens = set([token for token in instruc_tokens if token not in stop]) num_matches = len(instruc_tokens & recipe_tokens) step_num = idx + 1 if num_matches > 0: candidates += [(instruc, step_num, num_matches), ] candidates = sorted(candidates, key=lambda x:x[1]) if len(candidates) == 0: response = '%s not used in any step.' % query_ingredient elif len(candidates) == 1: instruc, step_num, num_matches = candidates[0] response = 'In step %d. %s' % (step_num, instruc) else: # Get list of steps where its used steps_used = [str(cand[1]) for cand in candidates] response = 'In steps ' + ', '.join(steps_used) + '. ' for instruc, step_num, num_matches in candidates: response += 'In step %d. %s' % (step_num, instruc) return json.dumps({'response' : response})
def respond_to_cal(text, recipe_id): """Respond to how many calories does this contain """ # Get Recipe recipe_info = json.loads(get_recipe_info(recipe_id))['response'] calories = recipe_info.get("Calories", None) if calories is None: response = "Sorry, I don't know many calories this dish contains." else: response = "This dish contains %s kilocalories. Yay." % calories return json.dumps({'response' : response})
def respond_to_duration(text, recipe_id): """Respond to how long do i <X> <X> can be "bake the cake", or whatever """ # Detect <X> by simple pattern matching match = re.search('how long do i (?P<action>[\w\s -]+)', text) query_action = match.group('action') # Get tokens action_tokens = recipe_tokens = nltk.word_tokenize(query_action) action_tokens = set([stemmer.stem(token) for token in action_tokens]) action_tokens = set([token for token in action_tokens if token not in stop]) # Iterate over steps, find relevant steps, add with a score # What are the steps in the recipe? recipe_info_str = json.loads(get_recipe_info(recipe_id)) recipe_info = recipe_info_str['response'] raw_instructions = recipe_info["Instructions"].replace('\r', '').replace('\n', '') instructions = raw_instructions.split('.') num_instructions = len(instructions) # Compare each instruction with a 'duration' keyword dur_kw = set(['minutes', 'minut', 'minute', 'mins', 'min', 'seconds', 'second', 'secs', 'sec']) candidates = [] for idx, instruc in enumerate(instructions): instruc_tokens = nltk.word_tokenize(instruc) instruc_tokens = [stemmer.stem(token) for token in instruc_tokens] instruc_tokens = set([token for token in instruc_tokens if token not in stop]) is_duration_instruc = len(instruc_tokens & dur_kw) > 0 if is_duration_instruc: # Calculate score num_matches = len(instruc_tokens & action_tokens) candidates += [(instruc, num_matches), ] candidates = sorted(candidates, key=lambda x: -x[1]) if len(candidates) == 0: response = 'error' else: most_relev_instruc = candidates[0][0] response = most_relev_instruc return json.dumps({'response' : response})
def respond_to_ing_qty(text, recipe_id): """Respond to: 'how much <X> is required?' """ # What is the ingredient? # Detect by simple pattern matching match = re.search('how (much|many) (?P<ing>[\w -]+)', text) query_ingredient = match.group('ing') # What are the ingredients in this recipe? recipe_info_str = json.loads(get_recipe_info(recipe_id)) recipe_info = recipe_info_str['response'] # List of 'ingredient' dicts ingredients = recipe_info["Ingredients"] # Create a dict {ingredient_name -> quantity} ing_dct = {} for ing in ingredients: name = ing['Name'].lower() quantity = ing['Quantity'] units = ing.get('Unit', '') ing_dct[name] = (quantity, units) # What's the quantity required? # Clean up recipe tokens # a. tokenize the ingredients recipe_tokens = nltk.word_tokenize(query_ingredient) # b. stem the tokens recipe_tokens = set([stemmer.stem(token) for token in recipe_tokens]) candidates = [] for dct_ing in ing_dct: query_tokens = nltk.word_tokenize(dct_ing) query_tokens = set([stemmer.stem(token) for token in query_tokens]) num_matches = len(recipe_tokens & query_tokens) if num_matches > 0: candidates += [(dct_ing, num_matches)] candidates = sorted(candidates, key=lambda x:-x[1]) if len(candidates) == 0: response = "%s is not necessary" % query_ingredient #elif len(candidates) == 1: else: response = "%s %s required" % ing_dct[candidates[0][0]] #else: # response = "Did you mean %s? %s %s required" % (candidates[0][0], ing_dct[candidates[0][0]][0], ing_dct[candidates[0][0]][1]) return json.dumps({'response' : response})
def get_recipes_info(): """ @return: a JSON RecipeList object """ recipe_id = int(request.args.get('recipe_id')) return get_recipe_info(recipe_id)