111 lines
4.3 KiB
Text
111 lines
4.3 KiB
Text
|
|
# AI image generation pipeline configuration
|
||
|
|
#
|
||
|
|
# Consumed exclusively by scripts/content/generate-images.nu (dev tooling).
|
||
|
|
# NOT merged into site/config/index.ncl — this is not a runtime site config.
|
||
|
|
#
|
||
|
|
# Load: nickel export --format json site/config/image-generation.ncl
|
||
|
|
# | from json | get image_generation
|
||
|
|
#
|
||
|
|
# Sensitive values (OPENAI_API_KEY, GEMINI_API_KEY, ZAI_TOKEN) live in .env — never inline here.
|
||
|
|
# The active `provider` selects which key the pipeline reads.
|
||
|
|
|
||
|
|
let ProviderContract = std.contract.from_validator (fun value =>
|
||
|
|
# openai: dall-e-3 / gpt-image-1 via /v1/images/generations
|
||
|
|
# gemini: gemini-2.5-flash-image (nano-banana) via :generateContent
|
||
|
|
# zhipu: glm-image (async via task_id) via /api/paas/v4/async/images/generations
|
||
|
|
if value == "openai" || value == "gemini" || value == "zhipu" then 'Ok
|
||
|
|
else ('Error "Must be 'openai', 'gemini' or 'zhipu'")
|
||
|
|
) in
|
||
|
|
|
||
|
|
let ImageSizeContract = std.contract.from_validator (fun value =>
|
||
|
|
# openai/gemini use these dimensions verbatim; zhipu uses 1280x1280
|
||
|
|
# (1024x1024 -> 1:1, 1792x1024 -> 16:9, 1024x1792 -> 9:16 for openai/gemini).
|
||
|
|
if (std.is_string value) && (
|
||
|
|
value == "1024x1024" ||
|
||
|
|
value == "1024x1792" ||
|
||
|
|
value == "1792x1024" ||
|
||
|
|
value == "1280x1280"
|
||
|
|
) then 'Ok
|
||
|
|
else ('Error "Must be a valid image dimension: 1024x1024, 1024x1792, 1792x1024 or 1280x1280 (zhipu)")
|
||
|
|
) in
|
||
|
|
|
||
|
|
let ImageQualityContract = std.contract.from_validator (fun value =>
|
||
|
|
# dall-e-3: "standard" | "hd"
|
||
|
|
# gpt-image-1: "low" | "medium" | "high"
|
||
|
|
# gemini: "standard" (no quality tiers; value is ignored by the backend)
|
||
|
|
# zhipu: "standard" (no quality tiers; value is ignored by the backend)
|
||
|
|
if value == "standard" || value == "hd" || value == "low" || value == "medium" || value == "high" then 'Ok
|
||
|
|
else ('Error "Must be 'standard', 'hd' (dall-e-3) or 'low', 'medium', 'high' (gpt-image-1)")
|
||
|
|
) in
|
||
|
|
|
||
|
|
let NonEmptyString = std.contract.from_validator (fun value =>
|
||
|
|
if (std.is_string value) && (std.string.length value > 0) then 'Ok
|
||
|
|
else ('Error "Must be a non-empty string")
|
||
|
|
) in
|
||
|
|
|
||
|
|
let ImageSizesContract = {
|
||
|
|
thumbnail | String | ImageSizeContract,
|
||
|
|
feature | String | ImageSizeContract,
|
||
|
|
} in
|
||
|
|
|
||
|
|
let ImageStylesContract = {
|
||
|
|
blog | String | NonEmptyString,
|
||
|
|
recipes | String | NonEmptyString,
|
||
|
|
activities | String | NonEmptyString,
|
||
|
|
projects | String | NonEmptyString,
|
||
|
|
} in
|
||
|
|
|
||
|
|
let ImageGenerationConfig = {
|
||
|
|
provider
|
||
|
|
| String
|
||
|
|
| ProviderContract
|
||
|
|
| doc "Provider backend: 'openai' (dall-e-3 / gpt-image-1), 'gemini' (gemini-2.5-flash-image / nano-banana), 'zhipu' (glm-image)",
|
||
|
|
|
||
|
|
model
|
||
|
|
| String
|
||
|
|
| NonEmptyString
|
||
|
|
| doc "Image model. openai: 'dall-e-3' (hd/standard) | 'gpt-image-1' (low/medium/high). gemini: 'gemini-2.5-flash-image'. zhipu: 'glm-image'",
|
||
|
|
|
||
|
|
quality
|
||
|
|
| String
|
||
|
|
| ImageQualityContract
|
||
|
|
| doc "dall-e-3: 'standard' | 'hd' gpt-image-1: 'low' | 'medium' | 'high' gemini/zhipu: 'standard' (ignored)",
|
||
|
|
|
||
|
|
templates_dir
|
||
|
|
| String
|
||
|
|
| NonEmptyString
|
||
|
|
| doc "Path to Tera prompt template files relative to project root",
|
||
|
|
|
||
|
|
sizes
|
||
|
|
| ImageSizesContract
|
||
|
|
| doc "DALL-E image dimensions per image type",
|
||
|
|
|
||
|
|
styles
|
||
|
|
| ImageStylesContract
|
||
|
|
| doc "Visual style directives per content type — appended to every prompt",
|
||
|
|
} in
|
||
|
|
|
||
|
|
{
|
||
|
|
image_generation = {
|
||
|
|
# provider = "openai" -> model "dall-e-3" | "gpt-image-1"
|
||
|
|
# provider = "gemini" -> model "gemini-2.5-flash-image", quality "standard"
|
||
|
|
# provider = "zhipu" -> model "glm-image", size "1280x1280" (only size supported)
|
||
|
|
provider = "openai",
|
||
|
|
model = "dall-e-3",
|
||
|
|
quality = "hd",
|
||
|
|
templates_dir = "site/templates/image-prompts",
|
||
|
|
|
||
|
|
sizes = {
|
||
|
|
thumbnail = "1024x1024",
|
||
|
|
feature = "1792x1024",
|
||
|
|
},
|
||
|
|
|
||
|
|
styles = {
|
||
|
|
blog = "Dark terminal/editor aesthetic. Rust-orange (#CE422B) accent on deep charcoal. Code or circuit motifs. No humans. High contrast. 16:9 composition.",
|
||
|
|
recipes = "Clean technical blueprint/schematic. Dark navy, crisp white line-art, cyan accent. Engineering diagram feel. No humans. 16:9.",
|
||
|
|
activities = "Professional conference keynote. Dark stage, single bold centered composition. Abstract geometric. No stock photos. No humans. 16:9.",
|
||
|
|
projects = "Product showcase and brand reveal. Dark background, Rust-orange and slate-blue palette. Technical, premium, minimal. No humans. 16:9.",
|
||
|
|
},
|
||
|
|
} | ImageGenerationConfig,
|
||
|
|
}
|