This commit is contained in:
2026-08-16 23:42:00 +02:00
parent 6e77154228
commit 92f046b542
32 changed files with 1443 additions and 105 deletions
+50 -24
View File
@@ -26,7 +26,9 @@ type Variable struct {
// Catalog of supported {{variables}} (only these are substituted; unknown tokens stay literal).
var VariableCatalog = []Variable{
{Name: "name", Label: "Product name", Description: "Current product title", Keys: []string{KeyProductEnhance, KeySEOMeta}},
{Name: "description", Label: "Description", Description: "Current product description", Keys: []string{KeyProductEnhance, KeySEOMeta}},
// description = product HTML body input (not SEO meta_description). Template key
// stays "description" so stored tenant prompts keep working (renaming would be BREAKING).
{Name: "description", Label: "Product description", Description: "Current product description (HTML body). Not SEO meta_description.", Keys: []string{KeyProductEnhance, KeySEOMeta}},
{Name: "category", Label: "Category", Description: "Resolved category name", Keys: []string{KeyProductEnhance, KeySEOMeta}},
{Name: "attrs", Label: "Attributes", Description: "Compact JSON of product attributes", Keys: []string{KeyProductEnhance}},
{Name: "gtin", Label: "GTIN", Description: "Product GTIN / barcode when present", Keys: []string{KeyProductEnhance}},
@@ -48,20 +50,38 @@ type DefaultTemplate struct {
}
// CategoryEnhanceUserTemplate is the shared per-category (and built-in) enhance USER
// message. Includes {{name}} {{description}} {{attrs}} {{category}} {{language}}.
// Compatible with the enhance system JSON schema {"name","description"} — not a
// competing HTML marketing document. Title/description formulas stay in
// title_template / description_template and are appended at render time as plain
// text instructions (see processing.AppendFormulaConstraints).
// Used by local A1/Demo prompt repair and seed-a1 overlays.
const CategoryEnhanceUserTemplate = `Your reply is parsed as JSON {"name":"string","description":"string"} only (system schema). Write name and description in {{language}} (do not hardcode a language).
- name: short retail title; follow any Title formula constraints that follow; use Attrs
- description: when a Description formula follows, emit ONE HTML string covering each section in order (tags matching type: h1/h2/h3/h4, p, ul); otherwise prefer 1-3 factual paragraphs as ONE string with limited HTML (<h2><p><ul><li>) — do NOT emit a competing full HTML document, <name>/<metaDescription> blocks, or separate schema
// message, sectioned by role (title / description / meta / attributes) using the
// same "--- Section ---" markers as legacy enhance-product. Includes {{name}}
// {{description}} {{attrs}} {{category}} {{language}}. Compatible with enhance
// JSON {"name","description","meta_title","meta_description","attrs"} —
// description is formula HTML product body; meta_* are plain SEO fields (legacy
// A1 <metaDescription> / cats.json metaTitle+metaDescription); attrs is the
// category-allowlisted attribute map. Title/description/meta formulas stay in
// title_template / description_template and are appended at render time (see
// processing.AppendFormulaConstraints / AppendAttributeConstraints). Categorize
// (unique_id) is RoleCategorize / ProductCategorize* — not this overlay. Used by
// local A1/Demo prompt repair and seed-a1 overlays.
const CategoryEnhanceUserTemplate = `Your reply is parsed as JSON {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}} only (system schema). Write all string fields in {{language}} (do not hardcode a language).
Category: {{category}}
--- Title ---
Role: title. Build JSON "name": short retail title; follow any Title formula constraints that follow; use Attrs.
Name: {{name}}
Desc: {{description}}
Attrs: {{attrs}}`
--- End Title ---
--- Description ---
Role: description. Build JSON "description": product body HTML only (not SEO meta). When a Description formula follows, emit ONE HTML string covering each section in order (tags matching type: h1/h2/h3/h4, p, ul); otherwise prefer 1-3 factual paragraphs as ONE string with limited HTML (<h2><p><ul><li>) — do NOT emit a competing full HTML document or wrap the whole reply in <name>/<metaDescription> tags.
Description: {{description}}
--- End Description ---
--- Meta ---
Role: meta. Build JSON "meta_title" and "meta_description" as plain SEO text (never HTML). meta_title: 50-60 chars; meta_description: 120-155 chars; follow any SEO meta formula that follows; never copy the full description HTML into meta_description.
--- End Meta ---
--- Attributes ---
Role: attributes. Build JSON "attrs" as an object of attribute_key → value strings. Prefer Allowed attribute keys / Title formula attr slots that follow; remap near-miss labels onto those keys; fill missing keys only from Name/Description/Category/Attrs evidence; never invent specs; omit unknown keys; never invent dimensions.
Category: {{category}}
Attrs: {{attrs}}
--- End Attributes ---`
// CategoryEnhancePromptNeedsRepair reports whether a stored categories.prompt value
// should be replaced by CategoryEnhanceUserTemplate (idempotent equality check).
@@ -77,38 +97,44 @@ func CategoryEnhancePromptNeedsRepair(prompt string) bool {
var BuiltInDefaults = []DefaultTemplate{
{
Key: KeyProductEnhance,
Label: "Product title & description",
Description: "Used when processing products (AI enhance step). Categorize (taxonomy pick when category is empty) is a separate pipeline step before this.",
Label: "Product title, description, SEO meta & attributes",
Description: "Used when processing products (AI enhance step). Produces title, HTML description, meta_*, and attrs. Categorize (taxonomy pick when category is empty) is a separate pipeline step before this.",
SystemTemplate: `Retail product copywriter.
Rules:
- Reply with ONLY JSON (no markdown)
- Schema: {"name":"string","description":"string"}
- Schema: {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}}
- name: short retail title
- description: follow any Description formula in the user message (structured HTML sections); otherwise 1-3 factual paragraphs; never copy name as description
- When Desc is empty or the same as Name, write from Category and Attrs only (do not invent specs); still obey a Description formula when present
- Write name and description in {{language}}
- description: product body HTML only — follow any Description formula in the user message (structured HTML sections); otherwise 1-3 factual paragraphs; never copy name as description; never put SEO meta here
- meta_title: plain SEO title 50-60 chars (follow any SEO meta formula)
- meta_description: plain SEO snippet 120-155 chars (follow any SEO meta formula); never HTML
- attrs: object of attribute_key → value; only Allowed attribute keys / formula attr slots from the user message; remap near-miss labels; fill gaps from evidence only; omit unknowns; do not invent specs
- When Description is empty or the same as Name, write description from Category and Attrs only (do not invent specs); still obey a Description formula when present
- Write name, description, meta_title, and meta_description in {{language}}
Example:
{"name":"Acme Widget Pro","description":"Durable widget for everyday use. Clear specs, ready to ship."}
{"name":"Acme Widget Pro","description":"<p>Durable widget for everyday use. Clear specs, ready to ship.</p>","meta_title":"Acme Widget Pro | Durable Daily Use","meta_description":"Shop Acme Widget Pro for reliable everyday performance. Clear specs and fast delivery.","attrs":{"brand":"Acme","product_model":"Widget Pro"}}
{{brand_voice}}`,
UserTemplate: CategoryEnhanceUserTemplate,
},
{
Key: KeySEOMeta,
Label: "SEO meta title & description",
Description: "Used when applying AI SEO meta to a product.",
Description: "Used when applying AI SEO meta to a product (standalone path). Product enhance already emits meta_* when run.",
SystemTemplate: `SEO meta writer for ecommerce.
Rules:
- Reply with ONLY JSON (no markdown)
- Schema: {"meta_title":"string","meta_description":"string"}
- meta_title: 50-60 chars, product + benefit
- meta_description: 120-155 chars, factual
- meta_description: 120-155 chars, factual plain text (not HTML product description)
- Write meta_title and meta_description in {{language}}
Example:
{"meta_title":"Acme Widget Pro | Durable Daily Use","meta_description":"Shop Acme Widget Pro for reliable everyday performance. Clear specs and fast delivery."}
{{brand_voice}}`,
UserTemplate: `Name: {{name}}
UserTemplate: `--- Meta ---
Role: meta. Reply with JSON meta_title and meta_description only (standalone seo_meta path).
Name: {{name}}
Category: {{category}}
Desc: {{description}}`,
Description: {{description}}
--- End Meta ---`,
},
{
Key: KeyCampaignEmail,