fix(detection+tandoor): handle stepless Instagram recipes
Some checks failed
Build & Push Docker Image / test-and-build (push) Failing after 33s

Many Instagram recipe posts list ingredients without preparation steps,
directing users to the 'link in bio' for the full recipe.

- Detection prompt: removed step requirement entirely — title + 2
  ingredients is sufficient to detect a recipe
- tandoor.ts: when steps array is null/empty, create a single
  placeholder step so all ingredients are preserved in Tandoor

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Giancarmine Salucci
2026-05-13 02:45:21 +02:00
parent d09bf80088
commit a389b0db15
2 changed files with 18 additions and 14 deletions

View File

@@ -9,19 +9,17 @@
export const RECIPE_DETECTION_PROMPT = `You are a recipe detector for social media posts. export const RECIPE_DETECTION_PROMPT = `You are a recipe detector for social media posts.
Your task: Determine if the text contains a recipe or cooking instructions. Your task: Determine if the text contains recipe content (ingredients list, cooking info, or dish preparation).
REQUIREMENTS FOR "YES" — text must have ALL of: SAY "yes" if the text has:
1. A dish name or title 1. A dish name or title
2. At least 3 ingredients (quantities are NOT required — social media posts often omit them) 2. At least 2 ingredients (quantities optional — many posts omit them)
3. At least 1 cooking or preparation step
IGNORE: Steps are NOT required — many Instagram posts list only ingredients and link to the full recipe elsewhere.
- Hashtags (#recipe, #food, etc.)
- Mentions (@username) SAY "no" only if the text has NO ingredients at all (e.g. pure food appreciation posts, restaurant reviews, memes).
- Emojis
- Like counts, comments, social metadata IGNORE: hashtags, @mentions, emojis, "save this", "follow me", "link in bio" phrases.
- Promotional text ("follow me", "save this", "tag a friend")
OUTPUT: Answer with ONLY 'yes' or 'no' - nothing else. OUTPUT: Answer with ONLY 'yes' or 'no' - nothing else.
@@ -30,11 +28,14 @@ EXAMPLES:
Text: "🍝 Pasta al Pomodoro Ingredients: pasta, tomatoes, garlic. Boil pasta. Sauté garlic. Add tomatoes. Mix! #italianfood @chef" Text: "🍝 Pasta al Pomodoro Ingredients: pasta, tomatoes, garlic. Boil pasta. Sauté garlic. Add tomatoes. Mix! #italianfood @chef"
Answer: yes Answer: yes
Text: "Panini al Latte Ingredienti: 250g farina, 35g zucchero, 8g lievito, 130g latte, 1 uovo, 40g burro, gocce di cioccolato. Trovi la ricetta completa al link in bio."
Answer: yes
Text: "Amazing dinner tonight! 😍 So delicious! 🔥 #foodporn" Text: "Amazing dinner tonight! 😍 So delicious! 🔥 #foodporn"
Answer: no Answer: no
Text: "Brioche velocissime Per 7 brioche: rotolo di pasta sfoglia, prosciutto cotto, provola. Arrotola la sfoglia con i ripieni, taglia in pezzi, inforna a 180°C." Text: "Best restaurant in Milano! You have to try it 🙌"
Answer: yes Answer: no
`; `;
export const RECIPE_EXTRACTION_PROMPT = `You are an EXPERT RECIPE EXTRACTOR specialized in parsing recipes from social media posts. export const RECIPE_EXTRACTION_PROMPT = `You are an EXPERT RECIPE EXTRACTOR specialized in parsing recipes from social media posts.

View File

@@ -234,10 +234,13 @@ function parseAmount(amountStr: string): number | null {
* Includes ingredients partitioned across steps * Includes ingredients partitioned across steps
*/ */
function buildTandoorRecipeDTO(recipe: ExtractedRecipe): TandoorRecipeDTO { function buildTandoorRecipeDTO(recipe: ExtractedRecipe): TandoorRecipeDTO {
const stepCount = recipe.steps?.length || 1; // When the caption has no steps (e.g. "full recipe at link in bio"), create
// a single placeholder step so ingredients are preserved in Tandoor.
const recipeSteps = recipe.steps?.length ? recipe.steps : ['Vedi la ricetta completa al link in bio.'];
const stepCount = recipeSteps.length;
const ingredientPartitions = partitionIngredientsAcrossSteps(recipe.ingredients || [], stepCount); const ingredientPartitions = partitionIngredientsAcrossSteps(recipe.ingredients || [], stepCount);
const steps: TandoorRecipeDTO['steps'] = (recipe.steps || []).map((instruction, index) => { const steps: TandoorRecipeDTO['steps'] = recipeSteps.map((instruction, index) => {
// Map ingredients, converting unparseable amounts to 1 q.b. // Map ingredients, converting unparseable amounts to 1 q.b.
const mappedIngredients = (ingredientPartitions[index] || []).map((ing) => { const mappedIngredients = (ingredientPartitions[index] || []).map((ing) => {
const amount = parseAmount(ing.amount); const amount = parseAmount(ing.amount);