1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

feat: OpenAI Ingredient Parsing (#3581)

This commit is contained in:
Michael Genson 2024-05-22 04:45:07 -05:00 committed by GitHub
parent 4c8bbdcde2
commit 5c57b3dd1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 789 additions and 274 deletions

View file

@ -1,3 +1,5 @@
import asyncio
import json
import shutil
from dataclasses import dataclass
from fractions import Fraction
@ -20,10 +22,11 @@ from mealie.schema.recipe.recipe_ingredient import (
SaveIngredientUnit,
)
from mealie.schema.user.user import GroupBase
from mealie.services.openai import OpenAIService
from mealie.services.parser_services import RegisteredParser, get_parser
from mealie.services.parser_services.crfpp.processor import CRFIngredient, convert_list_to_crf_model
from mealie.services.parser_services.openai.parser import OpenAIIngredient, OpenAIIngredients
from tests.utils.factories import random_int, random_string
from tests.utils.fixture_schemas import TestUser
@dataclass
@ -223,8 +226,9 @@ def test_brute_parser(
comment: str,
):
with session_context() as session:
loop = asyncio.get_event_loop()
parser = get_parser(RegisteredParser.brute, unique_local_group_id, session)
parsed = parser.parse_one(input)
parsed = loop.run_until_complete(parser.parse_one(input))
ing = parsed.ingredient
if ing.quantity:
@ -430,3 +434,43 @@ def test_parser_ingredient_match(
assert parsed_ingredient.ingredient.unit is None or isinstance(
parsed_ingredient.ingredient.unit, CreateIngredientUnit
)
def test_openai_parser(
unique_local_group_id: UUID4,
parsed_ingredient_data: tuple[list[IngredientFood], list[IngredientUnit]], # required so database is populated
monkeypatch: pytest.MonkeyPatch,
):
ingredient_count = random_int(10, 20)
async def mock_get_response(self, prompt: str, message: str, *args, **kwargs) -> str | None:
inputs = json.loads(message)
data = OpenAIIngredients(
ingredients=[
OpenAIIngredient(
input=input,
confidence=1,
quantity=random_int(0, 10),
unit=random_string(),
food=random_string(),
note=random_string(),
)
for input in inputs
]
)
return data.model_dump_json()
monkeypatch.setattr(OpenAIService, "get_response", mock_get_response)
with session_context() as session:
loop = asyncio.get_event_loop()
parser = get_parser(RegisteredParser.openai, unique_local_group_id, session)
inputs = [random_string() for _ in range(ingredient_count)]
parsed = loop.run_until_complete(parser.parse(inputs))
# since OpenAI is mocked, we don't need to validate the data, we just need to make sure parsing works
# and that it preserves order
assert len(parsed) == ingredient_count
for input, output in zip(inputs, parsed, strict=True):
assert output.input == input