Made it more general and nicer

This commit is contained in:
Julian van der Horst 2024-11-04 13:16:54 +01:00
commit 96d1ec6b0b
6 changed files with 34 additions and 36 deletions

View file

@ -166,9 +166,9 @@ export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
return await this.requests.post<ParsedIngredient[]>(routes.recipesParseIngredients, { parser, ingredients });
}
async convertUnits(parser: Parser, ingredients: Array<string>, user_prompt: string) {
async convertUnits(parser: Parser, ingredients: Array<string>, convert_to: "metric" | "imperial") {
parser = "openai";
return await this.requests.post<ParsedIngredient[]>(routes.recipesConvertUnits, { parser, ingredients, user_prompt });
return await this.requests.post<ParsedIngredient[]>(routes.recipesConvertUnits, { parser, ingredients, convert_to });
}
async parseIngredient(parser: Parser, ingredient: string) {

View file

@ -22,22 +22,14 @@
:items="availableParsers"
/>
</div>
<div v-if="parser === 'openai'" class="d-flex align-center mb-n4">
<div class="mb-4">USer prompt:</div>
<v-textarea
v-model="userPrompt"
class="mx-2 mb-4"
placeholder="Enter a prompt for the OpenAI parser"
/>
</div>
</BaseCardSectionTitle>
<div class="d-flex mt-n3 mb-4 justify-end" style="gap: 5px">
<BaseButton color="info" :disabled="parserLoading" @click="convertUnits">
<template #icon> {{ $globals.icons.foods }}</template>
convert units
</BaseButton>
<BaseButton cancel class="mr-auto" @click="$router.go(-1)"></BaseButton>
<BaseButton color="info" :disabled="parserLoading" @click="convertUnits">
<template #icon> {{ $globals.icons.cog}}</template>
Parse and convert units (Metric)
</BaseButton>
<BaseButton color="info" :disabled="parserLoading" @click="fetchParsed">
<template #icon> {{ $globals.icons.foods }}</template>
{{ $tc("recipe.parser.parse-all") }}
@ -195,8 +187,6 @@ export default defineComponent({
parserPreferences.value.parser = val;
});
const userPrompt = ref<string | null>(null);
function processIngredientError(ing: ParsedIngredient, index: number): Error {
const unitError = !checkForUnit(ing.ingredient.unit);
const foodError = !checkForFood(ing.ingredient.food);
@ -263,13 +253,13 @@ export default defineComponent({
}
async function convertUnits() {
if (!recipe.value || !recipe.value.recipeIngredient || !userPrompt.value) {
if (!recipe.value || !recipe.value.recipeIngredient) {
return;
}
const raw = recipe.value.recipeIngredient.map((ing) => ing.note ?? "");
parserLoading.value = true;
const { data } = await api.recipes.convertUnits(parser.value, raw, userPrompt.value);
const { data } = await api.recipes.convertUnits(parser.value, raw, "metric");
parserLoading.value = false;
if (data) {
@ -419,7 +409,6 @@ export default defineComponent({
return {
parser,
userPrompt,
availableParsers,
saveAll,
createFood,

View file

@ -2,7 +2,7 @@ from fastapi import APIRouter
from mealie.routes._base import BaseUserController, controller
from mealie.schema.recipe import ParsedIngredient
from mealie.schema.recipe.recipe_ingredient import IngredientRequest, IngredientsRequest, IngredientsConvertRequest
from mealie.schema.recipe.recipe_ingredient import IngredientRequest, IngredientsConvertRequest, IngredientsRequest
from mealie.services.parser_services import get_parser
router = APIRouter(prefix="/parser")
@ -22,8 +22,6 @@ class IngredientParserController(BaseUserController):
return await parser.parse(ingredients.ingredients)
@router.post("/convert-units", response_model=list[ParsedIngredient])
async def parse_ingredients(self, ingredients: IngredientsConvertRequest):
print("df")
async def parse_and_convert_ingredients(self, ingredients: IngredientsConvertRequest):
parser = get_parser(ingredients.parser, self.group_id, self.session)
return await parser.convert_units(ingredients.ingredients, ingredients.user_prompt)
return await parser.convert_units(ingredients.ingredients, ingredients.convert_to.value)

View file

@ -342,10 +342,16 @@ class IngredientsRequest(MealieModel):
parser: RegisteredParser = RegisteredParser.nlp
ingredients: list[str]
class ConvertTo(enum.Enum):
metric = "metric"
imperial = "imperial"
class IngredientsConvertRequest(MealieModel):
parser: RegisteredParser = RegisteredParser.openai
ingredients: list[str]
user_prompt: str
convert_to: ConvertTo
class IngredientRequest(MealieModel):

View file

@ -1,4 +1,4 @@
You are a bot that converts units of ingredients in recipes. You will receive a list of one or more ingredients, each containing one or more of the following components: quantity, unit, food, and note. Their definitions are stated in the JSON schema below. While parsing the ingredients, there are some things to keep in mind:
You are a bot that parses and converts units of ingredients in recipes. You will receive a list of one or more ingredients, each containing one or more of the following components: quantity, unit, food, and note. Their definitions are stated in the JSON schema below. While parsing the ingredients, there are some things to keep in mind:
- If you cannot accurately determine the quantity, unit, food, or note, you should place everything into the note field and leave everything else empty. It's better to err on the side of putting everything in the note field than being wrong
- You may receive recipe ingredients from multiple different languages. You should adhere to the grammar rules of the input language when trying to parse the ingredient string
- Sometimes foods or units will be in their singular, plural, or other grammatical forms. You must interpret all of them appropriately
@ -8,11 +8,14 @@ You are a bot that converts units of ingredients in recipes. You will receive a
- Sometimes quantities can be given a range, such as "3-5" or "1 to 2" or "three or four". In this instance, choose the lower quantity; do not try to average or otherwise calculate the quantity. For instance, if the input it "2-3 lbs of chicken breast" the quantity should be "2"
- Any text that does not appear in the unit or food must appear in the notes. No text should be left off. The only exception for this is if a quantity is converted from text into a number. For instance, if you convert "2 dozen" into the number "24", you should not put the word "dozen" into any other field
It is imperative that you do not create any data or otherwise make up any information, you may approximate the conversion however. Failure to adhere to this rule is illegal and will result in harsh punishment. If you are unsure, place the entire string into the note section of the response. Do not make things up.
You will receive whether you should convert from imperial to metric or the other way around. These are the rules you should follow when converting the units:
- When converting from units such as cups you can approximate the answer.
- When converting the units you should use units such as liters, ml or cl for liquid ingredients. Example: 100ml of milk, 2l of stock.
- When converting the units you should use units such as grams, kg or mg for solid ingredients. Example: 10g of salt, 300gr of mozzarella.
- You should also convert length measurements to measurements like meter, cm and mm. Even when these measurements are in the note field. Example: '1/8 inch thick slices' should be '3mm thick slices'.
- Teaspoons and pinches you can keep the same.
- When converting round up the numbers which make sense depending on the size of the ingredient. For example, if you have 1/3 cup of sugar, you should round it to 70mg of sugar.
It is imperative that you do not create any data or otherwise make up any information, however you may approximate the conversion. Failure to adhere to this rule is illegal and will result in harsh punishment. If you are unsure, place the entire string into the note section of the response. Do not make things up.
Below you will receive the JSON schema for your response. Your response must be in valid JSON in the below schema as provided. You must respond in this JSON schema; failure to do so is illegal. It is imperative that you follow the schema precisely to avoid punishment. You must follow the JSON schema.
The user message that you receive will be the list of one or more recipe ingredients for you to parse. Your response should have exactly one item for each item provided. For instance, if you receive 12 items to parse, then your response should be an array of 12 parsed items.
The user message will also include a prompt indicating their preferred units of measurement. The user message may also specify their country
or region, infer the preferred units from the country or region and add them to the preferred units list. You should convert all units to the preferred units.

View file

@ -4,6 +4,7 @@ from collections.abc import Awaitable
from mealie.schema.openai.recipe_ingredient import OpenAIIngredient, OpenAIIngredients
from mealie.schema.recipe.recipe_ingredient import (
ConvertTo,
CreateIngredientFood,
CreateIngredientUnit,
IngredientConfidence,
@ -109,7 +110,7 @@ class OpenAIParser(ABCIngredientParser):
response = await self._parse(ingredients)
return [self._convert_ingredient(ing) for ing in response.ingredients]
async def convert_units(self, ingredients: list[str], user_prompt: str) -> list[ParsedIngredient]:
async def convert_units(self, ingredients: list[str], convert_to: ConvertTo) -> list[ParsedIngredient]:
service = OpenAIService()
data_injections = [
OpenAIDataInjection(
@ -120,10 +121,11 @@ class OpenAIParser(ABCIngredientParser):
),
value=OpenAIIngredients,
),
OpenAIDataInjection(description="User Prompt containing the preferences of the user", value=user_prompt),
OpenAIDataInjection(
description="The direction to which you should convert. You should convert to:", value=convert_to
),
]
prompt = service.get_prompt("recipes.convert-recipe-units", data_injections=data_injections)
print(prompt)
# chunk ingredients and send each chunk to its own worker
ingredient_chunks = self._chunk_messages(ingredients, n=service.workers)
tasks: list[Awaitable[str | None]] = []
@ -149,7 +151,7 @@ class OpenAIParser(ABCIngredientParser):
if not responses:
raise Exception("No response from OpenAI")
res = OpenAIIngredients(
res = OpenAIIngredients(
ingredients=[ingredient for response in responses for ingredient in response.ingredients]
)