Skip to main content

AI provider

Most of Norish works without AI. With an AI provider you also get:

  • a fallback for pages the recipe scraper can't read
  • image import from photos and screenshots
  • video import from social media
  • recipe enrichment: tags, allergies, categories, nutrition, provenance, step ingredients and pictures
  • metric and US conversion by AI, next to the built-in one

Enable AI

Set AI_ENABLED=true and a provider, or do the same under Settings => Admin. Any OpenAI-compatible API works, like OpenAI, Azure OpenAI, OpenRouter, Ollama or LM Studio.

docker-compose.yml (environment)
AI_ENABLED: "true"
AI_PROVIDER: openai
AI_MODEL: gpt-6-luna
AI_API_KEY: <your-api-key>
# For an OpenAI-compatible endpoint (Azure, OpenRouter, Ollama, …):
# AI_ENDPOINT: https://your-endpoint/v1
VariableDescriptionDefault
AI_ENABLEDEnable AI features globallyfalse
AI_PROVIDERAI provideropenai
AI_ENDPOINTCustom OpenAI-compatible endpoint(empty)
AI_MODELDefault modelgpt-6-luna
AI_API_KEYAPI key for the provider(empty)
AI_TEMPERATUREGeneration temperature1.0
AI_MAX_TOKENSMaximum tokens for model responses10000
AI_TIMEOUT_MSMaximum time for an AI response (ms)300000

What an OpenAI-compatible endpoint has to support

Norish asks for structured output with response_format: json_schema, and falls back to JSON mode with response_format: json_object. An endpoint that supports neither doesn't work.

Recipe enrichment

Automatic enrichment

Under Settings => Admin => AI you choose which enrichments run on every new recipe. What each one leaves alone is listed under What enrichment leaves alone.

SwitchWhat it doesDefault
Auto-taggingAdds tags, never removes anyOff
Allergy detectionAdds allergy tags for your household's allergiesOn
Auto-categorizationSets meal categories on recipes without anyOff
Nutrition estimationFills in calories, fat, carbs and protein when one of them is missingOff
Recipe provenanceWorks out the country, region, cuisines and a short noteOff
Ingredient linkingLinks ingredients to steps that have noneOff
Image generationDraws a picture for new recipes without any imageOff

New ingredients

Automatic for new ingredients runs on every ingredient a recipe, grocery or pantry item adds to the catalogue. Both options are off by default.

OptionWhat it does
Clean the nameCleans the name right away
Draw an iconDraws an icon when neither the ingredient nor its parent has one. Needs an image provider

Tag strategy

Tag strategy decides which tags auto-tagging may use:

StrategyBehaviour
Predefined tags onlyOnly the built-in tag list
Predefined + existing tagsAlso tags already used by recipes on this instance
AI can create new tagsCreates new tags when needed

Cuisine strategy

Cuisine strategy decides whether provenance may add to your cuisine list:

StrategyBehaviour
Only existing cuisinesPick from the list, anything else is discarded
AI can add new cuisinesPick from the list, or add an entry that is missing

The default is Only existing cuisines. Either way, the AI's answers are matched against the list first, so a misspelling lands on the existing cuisine. Manage the list under Settings => Admin => AI & processing => Cuisines.

Image generation

Image generation has its own provider, because many AI providers, like Anthropic, Mistral, DeepSeek, Groq and Perplexity, have no image model. You can also use an Ollama server running an image model. Set it up under Settings => Admin => AI & processing => Image generation:

FieldNotes
Image providerOpenAI, Google AI, Azure OpenAI, Ollama, LM Studio, or a generic OpenAI-compatible endpoint.
Endpoint URLFor Ollama, LM Studio and generic endpoints; optional custom resource URL for Azure
API keyFor the cloud providers
Image modelMust be an image model, e.g. gpt-image-1-mini, gemini-2.5-flash-image or Ollama's x/z-image-turbo.

When the image provider is the same as your AI provider, it reuses the AI endpoint and API key.

The image provider also draws ingredient icons.

Decision Model

A Decision Model is a model trained to answer closed questions fast and cheaply. Norish uses it to spot recipes on imported pages, to make some enrichment decisions, and to check what the AI provider adds. Only models that adhere to TypeSafe's API are supported.

Set it up under Settings => Admin => AI & processing => Decision model:

FieldNotes
ProviderDisabled or TypeSafe AI
API keyFrom your TypeSafe AI account
ModelDefaults to jev-latest
Endpoint URLOptional. A proxy, gateway or self-hosted server that speaks TypeSafe's API. Empty uses https://api.typesafe.ai/v1
Use the decision model forAuto-categorization, Auto-tagging, Allergy detection, Recipe Provenance, Grocery linking, Validate enrichments. All are on by default

What each use does:

  • Auto-categorization decides whether a recipe is breakfast, lunch, dinner or a snack.
  • Auto-tagging decides each tag under Predefined tags only. Under the other strategies it checks each new tag.
  • Allergy detection asks one question per household allergy.
  • Recipe Provenance picks the country, and the cuisines under Only existing cuisines. The AI provider writes the region and the note.
  • Grocery linking picks a shop product, see Prices.
  • Validate enrichments checks everything an enrichment adds before it is saved.
  • Import triage checks whether a page holds a recipe. It is always on when a Decision Model is set up.

When the Decision Model isn't sure, or fails, Norish asks the AI provider instead. The job queues show which models a job used.

Enriching existing recipes

Automatic enrichment only runs on new recipes. To catch up the rest, use Settings => Admin => AI & processing => Bulk enrichment => Enrich all recipes. It runs every enabled enrichment on every recipe, which may cost a lot.

The dialog also has Overwrite existing data. It redoes categories, nutrition, provenance and step ingredients even where a recipe already has them, and that can't be undone. Tags and allergies are only ever added to. On a large library this costs a lot more.

Prompts

You can edit every prompt Norish uses under Settings => Admin.

Video import

Video import downloads the video with yt-dlp, transcribes the audio and has the AI provider read the recipe from it. Links from YouTube, Instagram, TikTok, Facebook, Pinterest, X, Threads, Snapchat, Vimeo, Dailymotion, Douyin, Bilibili and RedNote count as videos.

VariableDescriptionDefault
VIDEO_PARSING_ENABLEDEnable video parsingfalse
VIDEO_MAX_LENGTH_SECONDSMaximum accepted video length120
YT_DLP_VERSIONyt-dlp release for development purposes (the Docker image ships its own)2026.08.19
YT_DLP_BIN_DIRFolder containing the yt-dlp binary./.runtime/bin (dev), /app/bin (prod)
YT_DLP_PROXYHTTP/SOCKS proxy URL for yt-dlp downloads(empty)

Transcription

Transcription turns a video's audio into text.

VariableDescriptionDefault
TRANSCRIPTION_PROVIDERTranscription providerdisabled
TRANSCRIPTION_ENDPOINTTranscription endpoint (local/custom providers)(empty)
TRANSCRIPTION_API_KEYTranscription API key(empty)
TRANSCRIPTION_MODELTranscription modelwhisper-1

When the endpoint or API key is empty, transcription uses the AI provider's.