Tofu/scripts/import-recipes/extraction/RECIPE_SCHEMA.js
2026-09-18 01:41:02 +02:00

62 lines
2.6 KiB
JavaScript

// JSON schema handed to `output_config.format`, so the answer is guaranteed to
// parse. The descriptions repeat the hard rules: the schema travels with every
// request, and a field description is read right where the model fills it in.
// Structured outputs require `additionalProperties: false` on every object and
// accept no numeric or string constraints - nullability is expressed with
// `anyOf`.
export const RECIPE_SCHEMA = {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Title of the recipe, as written in the document.'
},
recipeYield: {
anyOf: [{ type: 'string' }, { type: 'null' }],
description: 'Yield as written, for example "4 personnes". null when the document does not state one.'
},
recipeIngredient: {
type: 'array',
items: { type: 'string' },
description: 'One entry per ingredient line, EXACTLY as written in the document: not reworded, not corrected, not converted. This is the text that gets printed.'
},
parsedIngredients: {
type: 'array',
description: 'The same lines split up, only so a shopping list can be added up and search can work. Same order and same count as recipeIngredient.',
items: {
type: 'object',
properties: {
raw: {
type: 'string',
description: 'Character for character identical to recipeIngredient at the same index.'
},
name: {
type: 'string',
description: 'The ingredient alone, without quantity, unit or preparation.'
},
quantity: {
anyOf: [{ type: 'number' }, { type: 'null' }],
description: 'Number stated on the line, or null. Never a number the document does not state, and never a conversion of "une poignée" or "un filet" into grams.'
},
unit: {
anyOf: [{ type: 'string' }, { type: 'null' }],
description: 'Unit as written, including imprecise ones such as "poignée", "filet", "pincée". null when the line states none.'
},
imprecise: {
type: 'boolean',
description: 'true when the line gives no measurable amount ("une poignée", "un filet", "au goût", "quelques").'
}
},
required: ['raw', 'name', 'quantity', 'unit', 'imprecise'],
additionalProperties: false
}
},
recipeInstructions: {
type: 'array',
items: { type: 'string' },
description: 'One entry per step, as written in the document.'
}
},
required: ['name', 'recipeYield', 'recipeIngredient', 'parsedIngredients', 'recipeInstructions'],
additionalProperties: false
}