···133133 - Step-by-step instructions starting with prep. Don't prefix with numbers.
134134 - Estimated Calorie count and other nutrient health tips.
135135 - Optional wine pairing guidance.
136136- - Three wine or less wine styles.
136136+ - Two or less simple, brief wine styles that can be searched for. No embelishment in this field.
137137138138# Planning & Verification
139139- Reference your checklist to ensure variety in cooking methods and cuisines
···243243 return nil, err
244244 }
245245 client := openai.NewClient(option.WithAPIKey(c.apiKey))
246246- input := []responses.ResponseInputItemUnionParam{}
247247- input = append(input, user(fmt.Sprintf("Recipe title: %s", recipeTitle)))
248248- input = append(input, user(fmt.Sprintf("Candidate wines in TSV format:\n%s", wineTSV.String())))
246246+ input := []responses.ResponseInputItemUnionParam{user(fmt.Sprintf("Candidate wines:\n%s", wineTSV.String()))}
249247 params := responses.ResponseNewParams{
250248 Model: c.model,
251249 Instructions: openai.String(
252252- "Act as a sommelier. Select 1 to 2 wines from the provided TSV that pair well with the recipe title. " +
253253- "Return JSON with commentary (string) and wines (array). " +
254254- "Size wine appropriately to people eating. Price according to the meal fanciness" +
250250+ "Act as a sommelier. Select 1 to 2 wines from the provided TSV that pair well with the recipe " + recipeTitle + "." +
251251+ "Return JSON with wines (ingredient array) and commentary about why those particular wines work well" +
252252+ "Pick wine sizes appropriate to number of people. Price according to the meal fanciness" +
255253 "For each wine include name and optionally quantity/price when available from TSV.",
256254 ),
257255 Input: responses.ResponseNewParamsInputUnion{
+5-4
internal/recipes/generator.go
···7373 return &ai.WineSelection{Commentary: "no wines styles for recipe", Wines: []ai.Ingredient{}}, nil
7474 }
7575 dateStr := date.Format("2006-01-02")
7676+ logger := slog.With("location", location, "date", dateStr)
7677 wines, err := asParallel(styles, func(style string) ([]kroger.Ingredient, error) {
7778 cacheKey := wineIngredientsCacheKey(style, location, date)
7879 winesOfStyle, err := g.io.IngredientsFromCache(ctx, cacheKey)
7980 if err == nil {
8080- slog.InfoContext(ctx, "Serving cached wines for style", "style", style, "location", location, "date", dateStr, "count", len(winesOfStyle))
8181+ logger.InfoContext(ctx, "Serving cached wines for style", "style", style, "count", len(winesOfStyle))
8182 return winesOfStyle, nil
8283 }
8384 if !errors.Is(err, cache.ErrNotFound) {
8484- slog.ErrorContext(ctx, "Failed to read cached wines for style", "style", style, "location", location, "date", dateStr, "error", err)
8585+ logger.ErrorContext(ctx, "Failed to read cached wines for style", "style", style, "error", err)
8586 }
86878787- slog.InfoContext(ctx, "Picking wine for style", "style", style)
8888 winesOfStyle, err = g.GetIngredients(ctx, location, Filter(style, []string{"*"}, false), 0)
8989 if err != nil {
9090 slog.ErrorContext(ctx, "Failed to get ingredients for wine style", "style", style, "error", err)
9191 return nil, fmt.Errorf("failed to get ingredients for style %q: %w", style, err)
9292 }
9393+ logger.InfoContext(ctx, "Found wines.", "style", style, "count", len(winesOfStyle))
93949495 if err := g.io.SaveIngredients(ctx, cacheKey, winesOfStyle); err != nil {
9595- slog.ErrorContext(ctx, "Failed to cache wines for style", "style", style, "location", location, "date", dateStr, "error", err)
9696+ logger.ErrorContext(ctx, "Failed to cache wines for style", "style", style, "error", err)
9697 }
9798 return winesOfStyle, nil
9899 })