diff --git a/docs/docs/documentation/getting-started/faq.md b/docs/docs/documentation/getting-started/faq.md index 7df1f46a5be..0716d9b48a0 100644 --- a/docs/docs/documentation/getting-started/faq.md +++ b/docs/docs/documentation/getting-started/faq.md @@ -26,7 +26,7 @@ Do the following for each recipe you want to intelligently handle ingredients. 6. Click the Edit button/icon again 7. Scroll to the ingredients and you should see new fields for Amount, Unit, Food, and Note. The Note in particular will contain the original text of the Recipe. 8. Click `Parse` and you will be taken to the ingredient parsing page. -9. Choose your parser. The `Natural Language Parser` works very well, but you can also use the `Brute Parser`. +9. Choose your parser. The `Natural Language Parser` works very well, but you can also use the `Brute Parser`, or the `OpenAI Parser` if you've [enabled OpenAI support](./installation/backend-config.md#openai). 10. Click `Parse All`, and your ingredients should be separated out into Units and Foods based on your seeding in Step 1 above. 11. For ingredients where the Unit or Food was not found, you can click a button to accept an automatically suggested Food to add to the database. Or, manually enter the Unit/Food and hit `Enter` (or click `Create`) to add it to the database 12. When done, click `Save All` and you will be taken back to the recipe. Now the Unit and Food fields of the recipe should be filled out. diff --git a/docs/docs/documentation/getting-started/installation/backend-config.md b/docs/docs/documentation/getting-started/installation/backend-config.md index 51ea84f1780..baec1fa44d2 100644 --- a/docs/docs/documentation/getting-started/installation/backend-config.md +++ b/docs/docs/documentation/getting-started/installation/backend-config.md @@ -102,6 +102,20 @@ For usage, see [Usage - OpenID Connect](../authentication/oidc.md) | OIDC_GROUPS_CLAIM | groups | Optional if not using `OIDC_USER_GROUP` or `OIDC_ADMIN_GROUP`. This is the claim Mealie will request from your IdP and will use to compare to `OIDC_USER_GROUP` or `OIDC_ADMIN_GROUP` to allow the user to log in to Mealie or is set as an admin. **Your IdP must be configured to grant this claim**| | OIDC_TLS_CACERTFILE | None | File path to Certificate Authority used to verify server certificate (e.g. `/path/to/ca.crt`) | +### OpenAI + +:octicons-tag-24: v1.7.0 + +Mealie supports various integrations using OpenAI. To enable OpenAI, [you must provide your OpenAI API key](https://platform.openai.com/api-keys). You can tweak how OpenAI is used using these backend settings. Please note that while OpenAI usage is optimized to reduce API costs, you're unlikely to be able to use OpenAI features with the free tier limits. + +| Variables | Default | Description | +| ------------------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------ | +| OPENAI_BASE_URL | None | The base URL for the OpenAI API. If you're not sure, leave this empty to use the standard OpenAI platform | +| OPENAI_API_KEY | None | Your OpenAI API Key. Enables OpenAI-related features | +| OPENAI_MODEL | gpt-4o | Which OpenAI model to use. If you're not sure, leave this empty | +| OPENAI_WORKERS | 2 | Number of OpenAI workers per request. Higher values may increase processing speed, but will incur additional API costs | +| OPENAI_SEND_DATABASE_DATA | True | Whether to send Mealie data to OpenAI to improve request accuracy. This will incur additional API costs | + ### Themeing Setting the following environmental variables will change the theme of the frontend. Note that the themes are the same for all users. This is a break-change when migration from v0.x.x -> 1.x.x. diff --git a/frontend/components/global/BaseOverflowButton.vue b/frontend/components/global/BaseOverflowButton.vue index 28a4ef58eb5..5204bafb855 100644 --- a/frontend/components/global/BaseOverflowButton.vue +++ b/frontend/components/global/BaseOverflowButton.vue @@ -11,44 +11,50 @@ - + - + - + @@ -74,6 +80,7 @@ export interface MenuItem { value?: string; event?: string; divider?: boolean; + hide?:boolean; } export default defineComponent({ diff --git a/frontend/composables/use-users/preferences.ts b/frontend/composables/use-users/preferences.ts index 88b0ba1e92a..52a4d26fdfa 100644 --- a/frontend/composables/use-users/preferences.ts +++ b/frontend/composables/use-users/preferences.ts @@ -1,6 +1,6 @@ import { Ref, useContext } from "@nuxtjs/composition-api"; import { useLocalStorage, useSessionStorage } from "@vueuse/core"; -import { TimelineEventType } from "~/lib/api/types/recipe"; +import { RegisteredParser, TimelineEventType } from "~/lib/api/types/recipe"; export interface UserPrintPreferences { imagePosition: string; @@ -36,6 +36,10 @@ export interface UserTimelinePreferences { types: TimelineEventType[]; } +export interface UserParsingPreferences { + parser: RegisteredParser; +} + export function useUserPrintPreferences(): Ref { const fromStorage = useLocalStorage( "recipe-print-preferences", @@ -116,3 +120,17 @@ export function useTimelinePreferences(): Ref { return fromStorage; } + +export function useParsingPreferences(): Ref { + const fromStorage = useLocalStorage( + "parsing-preferences", + { + parser: "nlp", + }, + { mergeDefaults: true } + // we cast to a Ref because by default it will return an optional type ref + // but since we pass defaults we know all properties are set. + ) as unknown as Ref; + + return fromStorage; +} diff --git a/frontend/lang/messages/en-US.json b/frontend/lang/messages/en-US.json index 84a7e45da67..3637a40ae54 100644 --- a/frontend/lang/messages/en-US.json +++ b/frontend/lang/messages/en-US.json @@ -594,6 +594,7 @@ "select-parser": "Select Parser", "natural-language-processor": "Natural Language Processor", "brute-parser": "Brute Parser", + "openai-parser": "OpenAI Parser", "parse-all": "Parse All", "no-unit": "No unit", "missing-unit": "Create missing unit: {unit}", @@ -764,7 +765,10 @@ "recipe-scraper-version": "Recipe Scraper Version", "oidc-ready": "OIDC Ready", "oidc-ready-error-text": "Not all OIDC Values are configured. This can be ignored if you are not using OIDC Authentication.", - "oidc-ready-success-text": "Required OIDC variables are all set." + "oidc-ready-success-text": "Required OIDC variables are all set.", + "openai-ready": "OpenAI Ready", + "openai-ready-error-text": "Not all OpenAI Values are configured. This can be ignored if you are not using OpenAI features.", + "openai-ready-success-text": "Required OpenAI variables are all set." }, "shopping-list": { "all-lists": "All Lists", @@ -1170,6 +1174,7 @@ "ingredients-natural-language-processor-explanation-2": "It's not perfect, but it yields great results in general and is a good starting point for manually parsing ingredients into individual fields. Alternatively, you can also use the \"Brute\" processor that uses a pattern matching technique to identify ingredients.", "nlp": "NLP", "brute": "Brute", + "openai": "OpenAI", "show-individual-confidence": "Show individual confidence", "ingredient-text": "Ingredient Text", "average-confident": "{0} Confident", diff --git a/frontend/lib/api/types/admin.ts b/frontend/lib/api/types/admin.ts index 36c255b3c22..6fdeec6a2ba 100644 --- a/frontend/lib/api/types/admin.ts +++ b/frontend/lib/api/types/admin.ts @@ -13,6 +13,7 @@ export interface AdminAboutInfo { enableOidc: boolean; oidcRedirect: boolean; oidcProviderName: string; + enableOpenai: boolean; versionLatest: string; apiPort: number; apiDocs: boolean; @@ -40,6 +41,7 @@ export interface AppInfo { enableOidc: boolean; oidcRedirect: boolean; oidcProviderName: string; + enableOpenai: boolean; } export interface AppStartupInfo { isFirstLogin: boolean; @@ -80,6 +82,7 @@ export interface CheckAppConfig { emailReady: boolean; ldapReady: boolean; oidcReady: boolean; + enableOpenai: boolean; baseUrlSet: boolean; isUpToDate: boolean; } diff --git a/frontend/lib/api/types/recipe.ts b/frontend/lib/api/types/recipe.ts index 62da68c8363..23189db6011 100644 --- a/frontend/lib/api/types/recipe.ts +++ b/frontend/lib/api/types/recipe.ts @@ -6,7 +6,7 @@ */ export type ExportTypes = "json"; -export type RegisteredParser = "nlp" | "brute"; +export type RegisteredParser = "nlp" | "brute" | "openai"; export type TimelineEventType = "system" | "info" | "comment"; export type TimelineEventImage = "has image" | "does not have image"; diff --git a/frontend/lib/api/user/recipes/recipe.ts b/frontend/lib/api/user/recipes/recipe.ts index 2a7dd0f4012..c036bcf33cf 100644 --- a/frontend/lib/api/user/recipes/recipe.ts +++ b/frontend/lib/api/user/recipes/recipe.ts @@ -17,7 +17,7 @@ import { } from "~/lib/api/types/recipe"; import { ApiRequestInstance, PaginationData } from "~/lib/api/types/non-generated"; -export type Parser = "nlp" | "brute"; +export type Parser = "nlp" | "brute" | "openai"; export interface CreateAsset { name: string; diff --git a/frontend/pages/admin/parser.vue b/frontend/pages/admin/parser.vue index bb1ac20faef..2290624d679 100644 --- a/frontend/pages/admin/parser.vue +++ b/frontend/pages/admin/parser.vue @@ -13,6 +13,7 @@ {{ $t('admin.nlp') }} {{ $t('admin.brute') }} + {{ $t('admin.openai') }} @@ -63,8 +64,8 @@