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:
parent
4c8bbdcde2
commit
5c57b3dd1a
28 changed files with 789 additions and 274 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue