···2626 Body io.Reader
2727}
28282929+const (
3030+ defaultRecipeModel = "gpt-5.5"
3131+ defaultWineModel = openai.ChatModelGPT5Mini
3232+)
3333+2934// how close should this be to Input ingredint. Should we also add aisle or just echo productid so we can look it up
3035type Ingredient struct {
3136 Name string `json:"name"`
···124129 oai: aiClient,
125130 schema: m,
126131 wineSchema: wine,
127127- model: openai.ChatModelGPT5_4,
128128- wineModel: openai.ChatModelGPT5Mini,
132132+ model: defaultRecipeModel,
133133+ wineModel: defaultWineModel,
129134 }
130135}
131136132137const systemMessage = `
133133-You are a professional chef and recipe developer that wants to help working families cook each night with varied cuisines.
138138+You are a professional chef and recipe developer helping working families cook varied weeknight dinners.
134139135135-# Objective
136136-Generate distinct, practical recipes using the provided constraints to maximize ingredient freshness, quality, and value while ensuring meal variety.
140140+# Outcome
141141+Create distinct, practical recipes using the provided sale ingredients, seasonal context, user preferences, and recent-recipe history.
137142138138-# Instructions
139139-- 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.
140140-- Recipes should use diverse cooking methods and represent a variety of cuisines.
141141-- 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.
142142-- include a optional wine pairing suggestion for each recipe if appropriate. Suggest a couple of styles. Really put your Sommielier hat on for this.
143143-- 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.
144144-- Aim for healthy unless otherwise stated. Calorie estimates must be reasonable for the stated ingredient quantities and servings.
145145-- 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?).
146146-- 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.
147147-- Suggest at least one recipe that is different ethnic cuisine.
143143+# Recipe Requirements
144144+- Default to 3 recipes for 2 people, under 1 hour, unless the user asks otherwise.
145145+- User instructions override defaults unless they make a recipe unsafe, uncookable, or impossible with the available ingredients.
146146+- Each recipe must include a protein plus at least one vegetable or starch component.
147147+- Use varied cuisines, cooking methods, textures, colors, and plating styles across the set.
148148+- Include pastas, noodles, stir-fries, stews, braises, curries, casseroles, or other compositions when they fit the ingredients.
149149+- Prioritize sale ingredients by value and quality. Only use prices from the input; never invent prices.
150150+- Pantry items are allowed when common and inexpensive.
151151+- Aim for healthy unless otherwise stated. Calorie estimates must be reasonable for the stated quantities and servings.
152152+- Include one richer or more special recipe when it fits the budget and ingredients, and mention that in the description.
153153+- Include wine pairing guidance when useful; otherwise explain briefly why a pairing is not needed.
148154149149-# Output Format
150150-- List of recipe each includes:
151151- - title: A short catchy name for the dish.
152152- - description: Try to sell the dish and add some flair.
153153- - cook_time: Estimated cook time (for example: "35 minutes")
154154- - cost_estimate: Estimated total cost in dollars (for example: "$18-24")
155155- - ingredients: should include quantities and price if in input. Can include widely availble pantry items not explicitly listed in user input.
156156- - instructions: Step-by-step starting with prep and ending with plating. Don't prefix with numbers.
157157- - health: Estimated Calorie count and other macro nutrient details.
158158- - drink_pairing: the wine pairing sommielier details.
159159- - 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.
155155+# Field Guidance
156156+- title: use a short, appetizing name.
157157+- description: make the dish sound appealing and note what makes it practical, special, or seasonal.
158158+- cook_time: provide a realistic estimate such as "35 minutes".
159159+- cost_estimate: align the range with listed priced ingredients.
160160+- ingredients: include quantities; include prices only when present in the input; common pantry items are allowed.
161161+- instructions: start with prep and end with plating; repeat amounts and prep details; do not include prices; do not prefix steps with numbers.
162162+- health: include plausible calories and macro notes for the stated servings.
163163+- drink_pairing: give concise sommelier guidance tied to the dish.
164164+- 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.
160165161161-# Planning & Verification
162162-- Reference your checklist to ensure variety in cooking methods and cuisines
163163-- Confirm ingredient prioritization matches sale/seasonal data.
164164-- Verify every ingredient line with a price uses the same product and price from input data.
165165-- Recalculate cost estimate from listed priced ingredients and ensure it aligns with cost_estimate.
166166-- Double-check calorie guidance in health against the ingredient list and portion size.
167167-- Read each instruction step in order and ensure the flow is realistic, non-contradictory, and fully cookable
168168-- Verify the liquids reduce in stated time
169169-- Verify technical terms are used correctly.
170170-- Verify the dish have a good appearance after plating`
166166+# Quality Checks
167167+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.`
171168172169const recipeImagePromptInstructions = `
173170Generate a realistic overhead food photograph of a single finished plate.
+11
internal/ai/recipe_test.go
···6464 }
6565}
66666767+func TestNewClientUsesGPT55ForRecipeFlow(t *testing.T) {
6868+ client := NewClient("test-key", "ignored", nil)
6969+7070+ if client.model != "gpt-5.5" {
7171+ t.Fatalf("expected primary recipe model to be gpt-5.5, got %q", client.model)
7272+ }
7373+ if client.wineModel != openai.ChatModelGPT5Mini {
7474+ t.Fatalf("expected wine model to remain low-cost mini path, got %q", client.wineModel)
7575+ }
7676+}
7777+6778func TestNormalizeWineStyle(t *testing.T) {
6879 tests := []struct {
6980 name string