d9d58fd01a
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.
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import { generateObject } from "ai";
|
|
import { z } from "zod";
|
|
import { resolveModel, type AiConfig } from "../factory";
|
|
|
|
const SubstitutionsSchema = z.object({
|
|
substitutions: z.array(z.object({
|
|
name: z.string(),
|
|
ratio: z.string(),
|
|
note: z.string(),
|
|
flavorImpact: z.enum(["minimal", "moderate", "significant"]),
|
|
})),
|
|
});
|
|
|
|
export type Substitution = z.infer<typeof SubstitutionsSchema>["substitutions"][number];
|
|
|
|
export async function substituteIngredient(
|
|
ingredient: string,
|
|
recipeContext: string,
|
|
config?: AiConfig
|
|
): Promise<Substitution[]> {
|
|
const model = resolveModel(config);
|
|
|
|
const { object } = await generateObject({
|
|
model,
|
|
schema: SubstitutionsSchema,
|
|
system:
|
|
"You are a professional chef specializing in ingredient substitutions. Provide practical, commonly available substitutes. For each substitute: name what to use, the ratio (e.g. '1:1', '3/4 the amount'), and a brief note on technique adjustments. Rate the flavor impact honestly.",
|
|
prompt: `Suggest 3-4 substitutes for "${ingredient}" in this recipe context: ${recipeContext}`,
|
|
});
|
|
|
|
return object.substitutions;
|
|
}
|