From 3b920babe3f9dffda7c07f0509cdabc9f356d9b1 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Sat, 16 Oct 2021 16:06:13 -0800 Subject: [PATCH] =?UTF-8?q?=20feat:=20=E2=9C=A8=20Add=20brute=20strategy?= =?UTF-8?q?=20to=20ingredient=20processor=20(#744)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix UI column width * words * update parser to support diff strats * add new model url * make button more visible * fix nutrition error * feat(backend): :sparkles: add 'brute' strategy for parsing ingredients * satisfy linter * update UI for creation page * feat(backend): :sparkles: log 422 errors in detail when not in PRODUCTION * add strategy selector Co-authored-by: Hayden --- Dockerfile | 2 +- frontend/api/class-interfaces/recipes.ts | 47 +++- .../components/global/BaseOverflowButton.vue | 82 ++++++ frontend/pages/admin/parser.vue | 137 +++++++--- .../pages/recipe/_slug/ingredient-parser.vue | 233 ++++++++++++++++-- frontend/pages/recipe/create.vue | 31 ++- frontend/pages/user/profile/edit.vue | 4 +- frontend/utils/icons/icons.ts | 2 + mealie/app.py | 3 + mealie/db/models/recipe/recipe.py | 2 +- mealie/routes/handlers.py | 33 +++ mealie/routes/parser/ingredient_parser.py | 22 +- mealie/schema/recipe/recipe_ingredient.py | 35 ++- mealie/services/parser_services/__init__.py | 1 + .../parser_services/_helpers/__init__.py | 1 + .../parser_services/_helpers/string_utils.py | 23 ++ .../parser_services/brute/__init__.py | 1 + .../services/parser_services/brute/process.py | 204 +++++++++++++++ .../parser_services/crfpp/__init__.py | 1 + .../parser_services/crfpp/pre_processor.py | 40 ++- .../parser_services/crfpp/processor.py | 20 +- .../services/parser_services/crfpp/utils.py | 38 ++- .../parser_services/ingredient_parser.py | 75 +++++- .../ingredient_parser_service.py | 11 +- ...pp_parser.py => test_ingredient_parser.py} | 44 +++- 25 files changed, 961 insertions(+), 131 deletions(-) create mode 100644 frontend/components/global/BaseOverflowButton.vue create mode 100644 mealie/routes/handlers.py create mode 100644 mealie/services/parser_services/_helpers/__init__.py create mode 100644 mealie/services/parser_services/_helpers/string_utils.py create mode 100644 mealie/services/parser_services/brute/__init__.py create mode 100644 mealie/services/parser_services/brute/process.py rename tests/unit_tests/{test_crfpp_parser.py => test_ingredient_parser.py} (50%) diff --git a/Dockerfile b/Dockerfile index e45ad49fc882..1c8012b6e286 100644 --- a/Dockerfile +++ b/Dockerfile @@ -106,7 +106,7 @@ COPY --from=builder-base $POETRY_HOME $POETRY_HOME COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH # copy CRF++ Binary from crfpp -ENV CRF_MODEL_URL=https://github.com/hay-kot/mealie-nlp-model/releases/download/v1.0.0/model.crfmodel +ENV CRF_MODEL_URL=https://github.com/mealie-recipes/nlp-model/releases/download/v1.0.0/model.crfmodel ENV LD_LIBRARY_PATH=/usr/local/lib COPY --from=crfpp /usr/local/lib/ /usr/local/lib diff --git a/frontend/api/class-interfaces/recipes.ts b/frontend/api/class-interfaces/recipes.ts index 9e2926b65ef4..b9f58bfe1500 100644 --- a/frontend/api/class-interfaces/recipes.ts +++ b/frontend/api/class-interfaces/recipes.ts @@ -22,6 +22,43 @@ const routes = { recipesSlugCommentsId: (slug: string, id: number) => `${prefix}/recipes/${slug}/comments/${id}`, }; +export type Parser = "nlp" | "brute"; + +export interface Confidence { + average?: number; + comment?: number; + name?: number; + unit?: number; + quantity?: number; + food?: number; +} + +export interface Unit { + name: string; + description: string; + fraction: boolean; + abbreviation: string; +} + +export interface Food { + name: string; + description: string; +} + +export interface Ingredient { + title: string; + note: string; + unit: Unit; + food: Food; + disableAmount: boolean; + quantity: number; +} + +export interface ParsedIngredient { + confidence: Confidence; + ingredient: Ingredient; +} + export class RecipeAPI extends BaseCRUDAPI { baseRoute: string = routes.recipesBase; itemRoute = routes.recipesRecipeSlug; @@ -84,11 +121,13 @@ export class RecipeAPI extends BaseCRUDAPI { return await this.requests.delete(routes.recipesSlugCommentsId(slug, id)); } - async parseIngredients(ingredients: Array) { - return await this.requests.post(routes.recipesParseIngredients, { ingredients }); + async parseIngredients(parser: Parser, ingredients: Array) { + parser = parser || "nlp"; + return await this.requests.post(routes.recipesParseIngredients, { parser, ingredients }); } - async parseIngredient(ingredient: string) { - return await this.requests.post(routes.recipesParseIngredient, { ingredient }); + async parseIngredient(parser: Parser, ingredient: string) { + parser = parser || "nlp"; + return await this.requests.post(routes.recipesParseIngredient, { parser, ingredient }); } } diff --git a/frontend/components/global/BaseOverflowButton.vue b/frontend/components/global/BaseOverflowButton.vue new file mode 100644 index 000000000000..c288cd4c568b --- /dev/null +++ b/frontend/components/global/BaseOverflowButton.vue @@ -0,0 +1,82 @@ + + + + + + \ No newline at end of file diff --git a/frontend/pages/admin/parser.vue b/frontend/pages/admin/parser.vue index f2fd4c1d5bff..8a4c7bd20f79 100644 --- a/frontend/pages/admin/parser.vue +++ b/frontend/pages/admin/parser.vue @@ -1,18 +1,28 @@ - \ No newline at end of file diff --git a/frontend/pages/recipe/create.vue b/frontend/pages/recipe/create.vue index dfd0ce876871..a74f76547315 100644 --- a/frontend/pages/recipe/create.vue +++ b/frontend/pages/recipe/create.vue @@ -7,11 +7,8 @@ Select one of the various ways to create a recipe - - From URL - Create - Import Zip - + +
@@ -127,7 +124,7 @@