Spaces:
Running
Running
# 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", | |
) | |
user_inputs = { | |
"user_direction" : user_direction, | |
"exclusions": exclusions, | |
"serving_size": serving_size, | |
"difficulty": selected_difficulty | |
} | |
def create_detailed_prompt(user_direction, exclusions, serving_size, 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": "string", | |
"description": "clear list of ingredients in the provided recipe, delimited by a semi colon" | |
}, | |
"instructions": { | |
"type": "string", | |
"description": "list of step-by-step instructions to prepare the provided recipe, delimited by a semi colon" | |
} | |
}, | |
"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"**Time To Make:** {loaded_recipe['description']}**") | |
st.subheader("Ingredients:") | |
try: | |
md_ingredients = '' | |
for ingredient in loaded_recipe['ingredients'].split('; '): | |
md_ingredients += "- " + ingredient + "\n" | |
st.markdown(md_ingredients) | |
except: | |
st.text(loaded_recipe['ingredients']) | |
st.subheader("Instructions:") | |
try: | |
md_instructions = '' | |
for instruction in loaded_recipe['instructions'].split('; '): | |
md_instructions += "- " + instruction + "\n" | |
st.markdown(md_instructions) | |
except: | |
st.text(loaded_recipe['instructions']) |