Skip to content

Add R-based EPUB cookbook ingestion and knowledge pipeline - #4

Open
charles-hebert wants to merge 1 commit into
mainfrom
codex/convert-instructions-to-r-script
Open

Add R-based EPUB cookbook ingestion and knowledge pipeline#4
charles-hebert wants to merge 1 commit into
mainfrom
codex/convert-instructions-to-r-script

Conversation

@charles-hebert

Copy link
Copy Markdown
Owner

Motivation

  • Provide an R implementation of an end-to-end EPUB cookbook ingestion pipeline that creates a structured recipe database and supports ingredient search, substitutions, meal planning, and semantic recipe search.
  • Replace the originally-provided Python instructions with an R script to fit environments or users preferring an R-based toolchain.
  • Persist parsed and normalized recipe data into PostgreSQL with pgvector for vector embeddings to enable semantic search and fridge-based suggestions.

Description

  • Adds epub_cookbook_ingestor.r, an R script that implements EPUB extraction, LLM-powered recipe parsing, ingredient normalization, alias upserts, and insertion into a PostgreSQL schema defined in SCHEMA_SQL (includes vector extension and recipe_embeddings with a VECTOR(384) column).
  • Integrates OpenAI chat calls via httr2 in openai_chat_json() and uses LLM prompts for recipe JSON extraction and canonical ingredient normalization in parse_recipes_with_llm() and canonicalize_ingredient().
  • Implements graph builders (build_ingredient_graph(), build_substitution_graph()), meal planning and shopping list helpers (meal_plan(), shopping_list()), and embedding/semantic search functions that call Python sentence-transformers via reticulate (embed_recipes(), semantic_search()).
  • Adds a CLI entrypoint (main()), environment-driven configuration via CONFIG (expects OPENAI_API_KEY and PostgreSQL env vars), and an n8n workflow markdown generator (write_n8n_workflow_markdown()).

Testing

  • Attempted an R parse check using Rscript -e "parse(file='epub_cookbook_ingestor.r'); cat('OK\n')" which failed because Rscript is not installed in the current environment (automated parse test failed).
  • No further automated tests were executed in this environment; runtime integration (database connectivity, OpenAI calls, and Python embedding via reticulate) should be validated in a host environment with Rscript, PostgreSQL with vector extension, and OPENAI_API_KEY configured.

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 82a981aec7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread epub_cookbook_ingestor.r
Comment on lines +247 to +250
"SELECT ir.id, ir.recipe_id, ir.raw_text
FROM ingredients_raw ir
LEFT JOIN ingredients i ON i.recipe_id = ir.recipe_id AND i.name = ir.raw_text
ORDER BY ir.id"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Filter out already-normalized ingredient rows

normalize_ingredients() currently selects every ingredients_raw record on each run because the LEFT JOIN is not followed by a filter like WHERE i.id IS NULL, so refreshes keep reprocessing old rows. Because ingredients has no unique key that matches the insert shape, the later ON CONFLICT DO NOTHING will not prevent duplicate ingredient rows, and downstream scoring/quantity calculations (e.g., meal planning and shopping lists) will drift upward after each rerun.

Useful? React with 👍 / 👎.

Comment thread epub_cookbook_ingestor.r
Comment on lines +149 to +155
prompt <- paste(
"Extract recipes from this text. Return strict JSON with key recipes.",
"Each recipe must include: title, ingredients (array of strings),",
"instructions (array of strings), servings, time_minutes.",
"If uncertain, return best effort and keep fields nullable.",
"Text:", raw_text
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Chunk EPUB text before calling recipe extraction model

parse_recipes_with_llm() sends the full EPUB text in a single prompt ("Text:", raw_text) and never uses the existing split_recipe_blocks() helper, so larger cookbooks can exceed chat completion context/request limits and fail extraction entirely. This makes ingestion brittle for full-book inputs, which are the primary use case of this script.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant