Spaces:
Runtime error
Runtime error
| # imports | |
| import streamlit as st | |
| import numpy as np | |
| import pandas as pd | |
| import re | |
| import json | |
| import openai | |
| openai.api_key = st.secrets["open_ai_key"] | |
| # state management | |
| if 'gpt_response' not in st.session_state: | |
| st.session_state.gpt_response = None | |
| # app | |
| st.title("Let's get cooking") | |
| user_direction = st.text_area( | |
| "What do you want to cook? Describe anything - a dish, cuisine, event, or vibe.", | |
| placeholder="quick snack, asian style bowl with either noodles or rice, something italian", | |
| ) | |
| serving_size = st.number_input( | |
| "How many people are you cooking for?", | |
| min_value=1, | |
| max_value=100, | |
| value=2, | |
| step=1 | |
| ) | |
| difficulty_dictionary = { | |
| "Quick & Easy": { | |
| "description": "Easy recipes with straightforward instructions. Ideal for beginners or those seeking quick and simple cooking.", | |
| }, | |
| "Intermediate": { | |
| "description": "Recipes with some intricate steps that invite a little challenge. Perfect for regular cooks wanting to expand their repertoire with new ingredients and techniques.", | |
| }, | |
| "Professional": { | |
| "description": "Complex recipes that demand a high level of skill and precision. Suited for seasoned cooks aspiring to professional-level sophistication and creativity.", | |
| } | |
| } | |
| selected_difficulty = st.radio( | |
| "Choose a difficulty level for your recipe.", | |
| [ | |
| list(difficulty_dictionary.keys())[0], | |
| list(difficulty_dictionary.keys())[1], | |
| list(difficulty_dictionary.keys())[2] | |
| ], | |
| captions = [ | |
| difficulty_dictionary["Quick & Easy"]["description"], | |
| difficulty_dictionary["Intermediate"]["description"], | |
| difficulty_dictionary["Professional"]["description"] | |
| ] | |
| ) | |
| exclusions = st.text_area( | |
| "Any ingredients you want to exclude?", | |
| placeholder="gluten, dairy, nuts, cilantro", | |
| ) | |
| fancy_exclusions ="" | |
| if selected_difficulty == "Professional": | |
| exclude_fancy = st.checkbox( | |
| "Exclude cliche professional ingredients? (gold leaf, truffle)", | |
| value=True) | |
| fancy_exclusions = "gold leaf, truffle" | |
| user_inputs = { | |
| "user_direction" : user_direction, | |
| "exclusions": f"{exclusions}, {fancy_exclusions}", | |
| "serving_size": serving_size, | |
| "difficulty": selected_difficulty | |
| } | |
| def create_detailed_prompt(user_inputs['user_direction'], user_inputs['exclusions'], user_inputs['serving_size'], user_inputs['difficulty']): | |
| if difficulty == "Quick and Easy": | |
| prompt = ( | |
| f"Please provide a 'Quick and Easy' recipe for {user_direction} with a serving size of {serving_size}. " | |
| f"It should require as few ingredients as possible and should be ready as little time as possible. " | |
| f"The steps should be simple, and the ingredients should be commonly found in a household pantry. " | |
| f"Ensure to exclude {exclusions} from the recipe." | |
| ) | |
| elif difficulty == "Intermediate": | |
| prompt = ( | |
| f"I'm looking for a recipe for a classic {user_direction} with a serving size of {serving_size} that offers a bit of a cooking challenge " | |
| f"but doesn't require professional skills.The recipe should feature traditional ingredients and techniques that are authentic to its cuisine. " | |
| f"Please provide a step-by-step guide that explains the process in detail. " | |
| f"Ensure to exclude {exclusions} from the recipe." | |
| ) | |
| elif difficulty == "Professional": | |
| prompt = ( | |
| f"Create an advanced recipe for {user_direction} with a serving size of {serving_size} that pushes the boundaries of culinary arts." | |
| f"This recipe should integrate unique ingredients, advanced cooking techniques, and innovative presentations." | |
| f"I'm aiming for a dish that could be served at a high-end restaurant or would impress at a gourmet food competition." | |
| f"Please detail the preparation and cooking process, considering that complexity and creativity are more important than prep and cooking time. " | |
| f"Ensure to exclude {exclusions} from the recipe." | |
| ) | |
| return prompt | |
| def generate_recipe(user_inputs): | |
| with st.spinner('Building the perfect recipe for you...'): | |
| functions = [ | |
| { | |
| "name": "provide_recipe", | |
| "description": "Provides a detailed recipe strictly adhering to the user input/specifications, especially ingredient exclusions and the recipe difficulty", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "name": { | |
| "type": "string", | |
| "description": "A creative name for the recipe" | |
| }, | |
| "description": { | |
| "type": "string", | |
| "description": "a brief one-sentence description of the provided recipe" | |
| }, | |
| "ingredients": { | |
| "type": "array", | |
| "items": { | |
| "type": "object", | |
| "properties": { | |
| "name": { | |
| "type": "string", | |
| "description": "Name of the ingredient" | |
| } | |
| } | |
| } | |
| }, | |
| "instructions": { | |
| "type": "array", | |
| "items": { | |
| "type": "object", | |
| "properties": { | |
| "step_number": { | |
| "type": "number", | |
| "description": "The sequence number of this step" | |
| }, | |
| "instruction": { | |
| "type": "string", | |
| "description": "Detailed description of what to do in this step" | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| "required": [ | |
| "name", | |
| "description", | |
| "ingredients", | |
| "instructions" | |
| ], | |
| }, | |
| } | |
| ] | |
| prompt = create_detailed_prompt(user_inputs['user_direction'], user_inputs['exclusions'], user_inputs['serving_size'], user_inputs['difficulty']) | |
| messages = [{"role": "user", "content": prompt}] | |
| st.session_state.gpt_response = openai.ChatCompletion.create( | |
| model="gpt-4", | |
| messages=messages, | |
| temperature=0.75, | |
| top_p=0.75, | |
| functions=functions, | |
| function_call={"name":"provide_recipe"}, # auto is default, but we'll be explicit | |
| ) | |
| st.button(label='Submit', on_click=generate_recipe, kwargs=dict(user_inputs=user_inputs)) | |
| if st.session_state.gpt_response is not None: | |
| st.divider() | |
| loaded_recipe = json.loads(st.session_state.gpt_response['choices'][0]['message']["function_call"]["arguments"]) | |
| st.header(loaded_recipe['name']) | |
| # st.write(f"**Serving Size: {loaded_recipe['recipe_serving_size']}**") | |
| st.write(f"**Description:** {loaded_recipe['description']}") | |
| st.subheader("Ingredients:") | |
| try: | |
| md_ingredients = '' | |
| for ingredient in loaded_recipe['ingredients']: | |
| md_ingredients += f"- {ingredient['name']} \n" | |
| st.markdown(md_ingredients) | |
| except: | |
| st.write(loaded_recipe['ingredients']) | |
| st.subheader("Instructions:") | |
| try: | |
| md_instructions = '' | |
| for instruction in loaded_recipe['instructions']: | |
| md_instructions += f"{instruction['step_number']}. {instruction['instruction']} \n" | |
| st.markdown(md_instructions) | |
| except: | |
| st.write(loaded_recipe['instructions']) |