ai cooking
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

just the string (#527)

Co-authored-by: paul miller <paul.miller>

authored by

Paul Miller
paul miller
and committed by
GitHub
ffa89f0f ba7f1484

+47 -37
+1 -1
go.mod
··· 15 15 github.com/hashicorp/go-retryablehttp v0.7.8 16 16 github.com/invopop/jsonschema v0.13.0 17 17 github.com/joho/godotenv v1.5.1 18 - github.com/openai/openai-go/v3 v3.31.0 18 + github.com/openai/openai-go/v3 v3.33.0 19 19 github.com/sendgrid/rest v2.6.9+incompatible 20 20 github.com/sendgrid/sendgrid-go v3.16.1+incompatible 21 21 github.com/stretchr/testify v1.11.1
+2
go.sum
··· 216 216 github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= 217 217 github.com/openai/openai-go/v3 v3.31.0 h1:3KxL3H+gw6vBkBW6dmcwhbFqP4kyMgmaWTsuRheyF8w= 218 218 github.com/openai/openai-go/v3 v3.31.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo= 219 + github.com/openai/openai-go/v3 v3.33.0 h1:aiETRPoLxnk6y3sIakXAdRCvtcLhdhBqHqIvEdOkEuc= 220 + github.com/openai/openai-go/v3 v3.33.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo= 219 221 github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= 220 222 github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= 221 223 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
+33 -36
internal/ai/client.go
··· 26 26 Body io.Reader 27 27 } 28 28 29 + const ( 30 + defaultRecipeModel = "gpt-5.5" 31 + defaultWineModel = openai.ChatModelGPT5Mini 32 + ) 33 + 29 34 // how close should this be to Input ingredint. Should we also add aisle or just echo productid so we can look it up 30 35 type Ingredient struct { 31 36 Name string `json:"name"` ··· 124 129 oai: aiClient, 125 130 schema: m, 126 131 wineSchema: wine, 127 - model: openai.ChatModelGPT5_4, 128 - wineModel: openai.ChatModelGPT5Mini, 132 + model: defaultRecipeModel, 133 + wineModel: defaultWineModel, 129 134 } 130 135 } 131 136 132 137 const systemMessage = ` 133 - You are a professional chef and recipe developer that wants to help working families cook each night with varied cuisines. 138 + You are a professional chef and recipe developer helping working families cook varied weeknight dinners. 134 139 135 - # Objective 136 - Generate distinct, practical recipes using the provided constraints to maximize ingredient freshness, quality, and value while ensuring meal variety. 140 + # Outcome 141 + Create distinct, practical recipes using the provided sale ingredients, seasonal context, user preferences, and recent-recipe history. 137 142 138 - # Instructions 139 - - Each meal must feature a protein and at least one side of either a vegetable and/or a starch. Include pastas, noodles, stir fry's, stews, braises, curries, casserole and other compositions. 140 - - Recipes should use diverse cooking methods and represent a variety of cuisines. 141 - - Provide clear, step-by-step instructions and an ingredient list for each recipe. Repeat amounts and prep for each recipe in instructions. Details on how ingredients are cut and plated. No prices or wine paring in instructions. 142 - - include a optional wine pairing suggestion for each recipe if appropriate. Suggest a couple of styles. Really put your Sommielier hat on for this. 143 - - Prioritize ingredients that are on sale (the bigger the discount, the higher the priority but be willing to pay for better ingredients). Only use prices given don't invent prices. 144 - - Aim for healthy unless otherwise stated. Calorie estimates must be reasonable for the stated ingredient quantities and servings. 145 - - Aim for an aesthetically and texturally pleasing dish. Think about color (not too monochrome), texture (not all mushy), and plating (how would a restaurant plate this?). 146 - - Suggest at least one recipe that is a little bit richer in terms of price, calories or prep time, be sure to mention in description. 147 - - Suggest at least one recipe that is different ethnic cuisine. 143 + # Recipe Requirements 144 + - Default to 3 recipes for 2 people, under 1 hour, unless the user asks otherwise. 145 + - User instructions override defaults unless they make a recipe unsafe, uncookable, or impossible with the available ingredients. 146 + - Each recipe must include a protein plus at least one vegetable or starch component. 147 + - Use varied cuisines, cooking methods, textures, colors, and plating styles across the set. 148 + - Include pastas, noodles, stir-fries, stews, braises, curries, casseroles, or other compositions when they fit the ingredients. 149 + - Prioritize sale ingredients by value and quality. Only use prices from the input; never invent prices. 150 + - Pantry items are allowed when common and inexpensive. 151 + - Aim for healthy unless otherwise stated. Calorie estimates must be reasonable for the stated quantities and servings. 152 + - Include one richer or more special recipe when it fits the budget and ingredients, and mention that in the description. 153 + - Include wine pairing guidance when useful; otherwise explain briefly why a pairing is not needed. 148 154 149 - # Output Format 150 - - List of recipe each includes: 151 - - title: A short catchy name for the dish. 152 - - description: Try to sell the dish and add some flair. 153 - - cook_time: Estimated cook time (for example: "35 minutes") 154 - - cost_estimate: Estimated total cost in dollars (for example: "$18-24") 155 - - ingredients: should include quantities and price if in input. Can include widely availble pantry items not explicitly listed in user input. 156 - - instructions: Step-by-step starting with prep and ending with plating. Don't prefix with numbers. 157 - - health: Estimated Calorie count and other macro nutrient details. 158 - - drink_pairing: the wine pairing sommielier details. 159 - - wine_styles: Two or fewer consumer-recognizable wine styles for search (for example: "Pinot Noir", "Sauvignon Blanc", "Cabernet Sauvignon"). Must only contain searchable style names: no regions, no parenthetical notes, no commas, no "or", no "*-style blend" phrasing. 155 + # Field Guidance 156 + - title: use a short, appetizing name. 157 + - description: make the dish sound appealing and note what makes it practical, special, or seasonal. 158 + - cook_time: provide a realistic estimate such as "35 minutes". 159 + - cost_estimate: align the range with listed priced ingredients. 160 + - ingredients: include quantities; include prices only when present in the input; common pantry items are allowed. 161 + - instructions: start with prep and end with plating; repeat amounts and prep details; do not include prices; do not prefix steps with numbers. 162 + - health: include plausible calories and macro notes for the stated servings. 163 + - drink_pairing: give concise sommelier guidance tied to the dish. 164 + - wine_styles: at most two searchable consumer wine styles, such as "Pinot Noir" or "Sauvignon Blanc"; no regions, parenthetical notes, commas, "or", or "*-style blend" phrasing. 160 165 161 - # Planning & Verification 162 - - Reference your checklist to ensure variety in cooking methods and cuisines 163 - - Confirm ingredient prioritization matches sale/seasonal data. 164 - - Verify every ingredient line with a price uses the same product and price from input data. 165 - - Recalculate cost estimate from listed priced ingredients and ensure it aligns with cost_estimate. 166 - - Double-check calorie guidance in health against the ingredient list and portion size. 167 - - Read each instruction step in order and ensure the flow is realistic, non-contradictory, and fully cookable 168 - - Verify the liquids reduce in stated time 169 - - Verify technical terms are used correctly. 170 - - Verify the dish have a good appearance after plating` 166 + # Quality Checks 167 + Before responding, ensure recipes are cookable, realistic, non-contradictory, varied, correctly priced, safe, and visually appealing after plating. Do not include these checks in the output.` 171 168 172 169 const recipeImagePromptInstructions = ` 173 170 Generate a realistic overhead food photograph of a single finished plate.
+11
internal/ai/recipe_test.go
··· 64 64 } 65 65 } 66 66 67 + func TestNewClientUsesGPT55ForRecipeFlow(t *testing.T) { 68 + client := NewClient("test-key", "ignored", nil) 69 + 70 + if client.model != "gpt-5.5" { 71 + t.Fatalf("expected primary recipe model to be gpt-5.5, got %q", client.model) 72 + } 73 + if client.wineModel != openai.ChatModelGPT5Mini { 74 + t.Fatalf("expected wine model to remain low-cost mini path, got %q", client.wineModel) 75 + } 76 + } 77 + 67 78 func TestNormalizeWineStyle(t *testing.T) { 68 79 tests := []struct { 69 80 name string