Files
Epicure/apps/web/lib/ai/features/estimate-nutrition.ts
T
Arnaud d9d58fd01a feat(ai): Vercel AI SDK provider factory with BYOK and per-use-case model prefs
Provider factory (OpenAI/Anthropic/OpenRouter/Ollama). generateObject for all outputs.
Features: recipe generation, photo-to-recipe vision, variations, drink/meal pairings,
ingredient substitution, recipe adaptation, nutrition analysis, URL import, meal plan gen.
User BYOK keys (AES-256-GCM). Per-use-case model preferences (text/vision/mealPlan).
Site-level key override via admin settings.
2026-07-01 08:10:19 +02:00

60 lines
2.0 KiB
TypeScript

import { generateObject } from "ai";
import { z } from "zod";
import { resolveModel, type AiConfig } from "../factory";
const NutritionSchema = z.object({
perServing: z.object({
calories: z.number().describe("Total calories per serving (kcal)"),
proteinG: z.number().describe("Protein in grams per serving"),
carbsG: z.number().describe("Total carbohydrates in grams per serving"),
fatG: z.number().describe("Total fat in grams per serving"),
fiberG: z.number().describe("Dietary fiber in grams per serving"),
sodiumMg: z.number().describe("Sodium in milligrams per serving"),
}),
});
export type NutritionEstimate = z.infer<typeof NutritionSchema>;
export async function estimateNutrition(
recipe: {
title: string;
baseServings: number;
ingredients: Array<{
rawName: string;
quantity?: string | number | null;
unit?: string | null;
}>;
},
config?: AiConfig
): Promise<NutritionEstimate> {
const model = resolveModel(config);
const ingredientList = recipe.ingredients
.map((i) => {
const parts: string[] = [];
if (i.quantity) parts.push(String(i.quantity));
if (i.unit) parts.push(i.unit);
parts.push(i.rawName);
return `- ${parts.join(" ")}`;
})
.join("\n");
const { object } = await generateObject({
model,
schema: NutritionSchema,
system:
"You are an expert nutritionist with deep knowledge of food composition and nutritional values. Estimate nutrition data accurately based on ingredients, quantities, and typical cooking methods. When quantities are not specified, use typical serving amounts. Provide realistic estimates based on standard nutritional databases.",
prompt: `Estimate the nutritional content per serving for the following recipe.
Recipe: ${recipe.title}
Servings: ${recipe.baseServings}
Ingredients:
${ingredientList}
Calculate nutrition values per single serving (total divided by ${recipe.baseServings} servings).`,
});
return object;
}