Merge pull request #445 from kartik6/community-contributions-branch
week 1 - smart recipe grocery assistant
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# imports\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from openai import OpenAI\n",
|
||||
"from IPython.display import Markdown, display"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "1",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Load environment variables in a file called .env\n",
|
||||
"\n",
|
||||
"load_dotenv()\n",
|
||||
"api_key = os.getenv('OPENAI_API_KEY')\n",
|
||||
"\n",
|
||||
"# Check the key\n",
|
||||
"\n",
|
||||
"if not api_key:\n",
|
||||
" print(\"No API key was found - please head over to the troubleshooting notebook in this folder to identify & fix!\")\n",
|
||||
"elif not api_key.startswith(\"sk-proj-\"):\n",
|
||||
" print(\"An API key was found, but it doesn't start sk-proj-; please check you're using the right key - see troubleshooting notebook\")\n",
|
||||
"elif api_key.strip() != api_key:\n",
|
||||
" print(\"An API key was found, but it looks like it might have space or tab characters at the start or end - please remove them - see troubleshooting notebook\")\n",
|
||||
"else:\n",
|
||||
" print(\"API key found and looks good so far!\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "2",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"openai = OpenAI()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Let's just make sure the model is loaded\n",
|
||||
"!ollama pull llama3.2\n",
|
||||
"import ollama\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "4",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# System prompt - defines the AI's behavior\n",
|
||||
"SYSTEM_PROMPT = \"\"\"You are a helpful cooking assistant that provides ingredient lists for recipes.\n",
|
||||
"Format your response as clean markdown with this structure:\n",
|
||||
"\n",
|
||||
"# [Dish Name]\n",
|
||||
"**Serves:** [number] people \n",
|
||||
"**Cook Time:** [estimated time]\n",
|
||||
"\n",
|
||||
"## Shopping List\n",
|
||||
"- [ ] [amount] [unit] [ingredient]\n",
|
||||
"- [ ] [amount] [unit] [ingredient]\n",
|
||||
"\n",
|
||||
"Guidelines:\n",
|
||||
"- Use common grocery store measurements (cups, lbs, oz, pieces, cans, etc.)\n",
|
||||
"- Round to practical shopping amounts (1.5 lbs instead of 1.47 lbs)\n",
|
||||
"- Group similar items when logical (all spices together)\n",
|
||||
"- Include pantry staples only if they're essential (salt, oil, etc.)\n",
|
||||
"- Assume basic seasonings are available unless recipe-specific\n",
|
||||
"- For produce, specify size when important (large onion, medium tomatoes)\n",
|
||||
"- Keep optional items at the end of similar item groups or end of the list\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def get_recipe_openai(dish_name: str, num_people: int):\n",
|
||||
" \"\"\"Get scaled recipe ingredients using system and user prompts\"\"\"\n",
|
||||
"\n",
|
||||
" user_prompt = f\"Give me the ingredients needed to make {dish_name} for {num_people} people.\"\n",
|
||||
" \n",
|
||||
" try:\n",
|
||||
" response = openai.chat.completions.create(\n",
|
||||
" model=\"gpt-4o-mini\",\n",
|
||||
" messages=[\n",
|
||||
" {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n",
|
||||
" {\"role\": \"user\", \"content\": user_prompt}\n",
|
||||
" ],\n",
|
||||
" max_tokens=400\n",
|
||||
" )\n",
|
||||
" \n",
|
||||
" return response.choices[0].message.content\n",
|
||||
" \n",
|
||||
" except Exception as e:\n",
|
||||
" return f\"❌ Error: Failed to get recipe - {str(e)}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"OLLAMA_MODEL = \"llama3.2\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def get_recipe_ollama(dish_name: str, num_people: int):\n",
|
||||
" \"\"\"Get recipe using Ollama API\"\"\"\n",
|
||||
" user_prompt = f\"Give me the ingredients needed to make {dish_name} for {num_people} people.\"\n",
|
||||
" \n",
|
||||
" messages = [\n",
|
||||
" {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n",
|
||||
" {\"role\": \"user\", \"content\": user_prompt}\n",
|
||||
" ]\n",
|
||||
" \n",
|
||||
" try:\n",
|
||||
" response = ollama.chat(model=OLLAMA_MODEL, messages=messages)\n",
|
||||
" return response['message']['content']\n",
|
||||
" except Exception as e:\n",
|
||||
" return f\"❌ Ollama Error: {str(e)}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def print_shopping_list(recipe_markdown):\n",
|
||||
" \"\"\"Print the markdown response\"\"\"\n",
|
||||
" display(Markdown(recipe_markdown))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9",
|
||||
"metadata": {
|
||||
"editable": true,
|
||||
"slideshow": {
|
||||
"slide_type": ""
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(\"🍳 Recipe Scaler & Grocery List Maker\")\n",
|
||||
"print(\"=\" * 40)\n",
|
||||
" \n",
|
||||
"ai_service_choice = input(\"\\nChoose AI service (1 for OpenAI, 2 for Ollama): \").strip()\n",
|
||||
"\n",
|
||||
"dish = input(\"What dish do you want to make? \")\n",
|
||||
"num_people = int(input(\"How many people? \"))\n",
|
||||
" \n",
|
||||
"print(f\"\\n🔍 Getting recipe for {dish}...\")\n",
|
||||
" \n",
|
||||
"# Get and display recipe\n",
|
||||
"if ai_service_choice == '1':\n",
|
||||
" print(\"Using OpenAI API...\")\n",
|
||||
" recipe_markdown = get_recipe_openai(dish, num_people)\n",
|
||||
"else:\n",
|
||||
" print(\"Using Ollama (local)...\")\n",
|
||||
" recipe_markdown = get_recipe_ollama(dish, num_people)\n",
|
||||
"\n",
|
||||
"print_shopping_list(recipe_markdown)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.13"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user