"""Split compound ingredient text into resolved individual names. Uses the ingredient-parser-nlp CRF model which handles coordination resolution: shared noun propagation, multi-way OR/AND lists, and comma-separated alternatives. >>> from utils.ingredient_split import split_ingredient_names >>> split_ingredient_names("cherry or grape tomatoes") ['cherry tomatoes', 'grape tomatoes'] >>> split_ingredient_names("chicken or vegetable broth") ['chicken broth', 'vegetable broth'] """ from __future__ import annotations import re from ingredient_parser import parse_ingredient REPEATED_PREFIX_RE = re.compile(r"\b(\S+(?:-\S+)*)\s+\1\b") def deduplicate_prefix(name: str) -> str: """Fix CRF bug where a shared prefix token is doubled. "day-old day-old sandwich bread" -> "day-old sandwich bread" """ return REPEATED_PREFIX_RE.sub(r"\1", name) def split_ingredient_names(text: str) -> list[str]: """Split a compound ingredient string into resolved individual names. Returns a list of 1+ names. A single-element list means the input was not compound (or the model chose not to split it). """ parsed = parse_ingredient(text) names = [deduplicate_prefix(n.text) for n in parsed.name] if not names: return [text] return names