fix
This commit is contained in:
@@ -14,7 +14,10 @@ import (
|
||||
// <metaDescription> from the HTML reply. v2 must recreate that GPT-predloga
|
||||
// dominance while keeping JSON {"name","description","meta_*","attrs"}.
|
||||
|
||||
const a1StyleEnhanceSystemTemplate = `Si tekstopisec, ki piše opise izdelkov v {{language}}.
|
||||
// {{language}} renders an English label ("Slovenian"), so both templates name the
|
||||
// language after a colon instead of inflecting it — legacy "v Slovenščini" read as
|
||||
// "v Slovenian" and put a grammatical error in front of every A1 prompt.
|
||||
const a1StyleEnhanceSystemTemplateSL = `Si tekstopisec, ki piše opise izdelkov v tem jeziku: {{language}}.
|
||||
Rules:
|
||||
- Reply with ONLY JSON (no markdown)
|
||||
- Schema: {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}}
|
||||
@@ -25,6 +28,20 @@ Rules:
|
||||
- attrs: only Allowed attribute keys when listed; fill from evidence only; omit unknowns
|
||||
{{brand_voice}}`
|
||||
|
||||
// a1StyleEnhanceSystemTemplateEN is the same contract for the English
|
||||
// platform-default formulas, matching the English scaffolding in a1StyleLabelsEN.
|
||||
const a1StyleEnhanceSystemTemplateEN = `You are a copywriter who writes product descriptions in this language: {{language}}.
|
||||
Rules:
|
||||
- Reply with ONLY JSON (no markdown)
|
||||
- Schema: {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}}
|
||||
- Obey the product template in the user message step by step
|
||||
- "name" follows the <name> formula — never copy Old_product_name unchanged when the formula asks for a new name
|
||||
- "description" is ONE HTML string covering each product template body section in order (tags matching type: h1/h2/h3/h4, p, ul) — do NOT wrap the reply in <name> or <metaDescription> tags
|
||||
- "meta_title" and "meta_description" are plain SEO text from the meta / <metaDescription> formula (never HTML body)
|
||||
- Use only the supplied Old_product_name, Old_product_description, Category and Attrs as facts; never invent specifications
|
||||
- attrs: only Allowed attribute keys when listed; fill from evidence only; omit unknowns
|
||||
{{brand_voice}}`
|
||||
|
||||
var (
|
||||
reLegacyNameCapture = regexp.MustCompile(`(?is)<\s*name\s*>\s*(.*?)\s*<\s*/\s*name\s*>`)
|
||||
reLegacyMetaCapture = regexp.MustCompile(`(?is)<\s*metaDescription\s*>\s*(.*?)\s*<\s*/\s*metaDescription\s*>`)
|
||||
@@ -60,7 +77,7 @@ func categoryUsesA1StyleFormula(catPrompt string, titleTemplate, descriptionTemp
|
||||
// buildA1StyleEnhanceUserTemplate rebuilds the legacy GPT-predloga user message
|
||||
// (Title → <name>, Meta → <metaDescription>, Description HTML blocks) plus product
|
||||
// evidence placeholders, asking for JSON field mapping.
|
||||
func buildA1StyleEnhanceUserTemplate(catPrompt string, titleTemplate, descriptionTemplate any, omitSEOMeta bool) string {
|
||||
func buildA1StyleEnhanceUserTemplate(catPrompt string, titleTemplate, descriptionTemplate any, omitSEOMeta bool) (string, bool) {
|
||||
titleInstr := strings.TrimSpace(aiprompts.TitleSectionInstructions(catPrompt))
|
||||
if titleInstr == "" || isBuiltInTitleRoleBoilerplate(titleInstr) {
|
||||
titleInstr = ""
|
||||
@@ -105,37 +122,100 @@ func buildA1StyleEnhanceUserTemplate(catPrompt string, titleTemplate, descriptio
|
||||
predloga.WriteByte('\n')
|
||||
}
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString("Ustvari nov opis izdelka v {{language}} z naslednjimi spremenljivkami:\n\n")
|
||||
b.WriteString("Staro_ime_izdelka: {{name}}\n")
|
||||
b.WriteString("Star_opis_izdelka: {{description}}\n")
|
||||
b.WriteString("Kategorija: {{category}}\n")
|
||||
b.WriteString("Attrs: {{attrs}}\n\n")
|
||||
b.WriteString("Uporabi spodnjo GPT predlogo.\n")
|
||||
b.WriteString("Sledi tej GPT predlogi stavek po stavek in sestavi nov opis izdelka.\n\n")
|
||||
b.WriteString("GPT predloga:\n\n")
|
||||
b.WriteString(strings.TrimSpace(predloga.String()))
|
||||
b.WriteString("\n\n")
|
||||
b.WriteString("Odgovori SAMO z enim JSON objektom:\n")
|
||||
b.WriteString(`- "name" = rezultat <name> formule (novo ime; ne kopiraj Staro_ime_izdelka, če formula zahteva novo ime)` + "\n")
|
||||
b.WriteString(`- "description" = HTML telo po GPT predlogi (vsi razdelki po vrsti), BREZ <name>/<metaDescription> tagov` + "\n")
|
||||
if !omitSEOMeta {
|
||||
b.WriteString(`- "meta_title" / "meta_description" = plain SEO po meta / <metaDescription> formuli` + "\n")
|
||||
body := strings.TrimSpace(predloga.String())
|
||||
slovenian := reSlovenianFormulaCue.MatchString(body)
|
||||
l := a1StyleLabelsEN
|
||||
if slovenian {
|
||||
l = a1StyleLabelsSL
|
||||
}
|
||||
b.WriteString(`- "attrs" = atributi (samo Allowed attribute keys, če so navedeni)`)
|
||||
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "%s\n\n", l.intro)
|
||||
fmt.Fprintf(&b, "%s: {{name}}\n", l.oldName)
|
||||
fmt.Fprintf(&b, "%s: {{description}}\n", l.oldDesc)
|
||||
fmt.Fprintf(&b, "%s: {{category}}\n", l.category)
|
||||
b.WriteString("Attrs: {{attrs}}\n\n")
|
||||
fmt.Fprintf(&b, "%s\n%s\n\n", l.useTemplate, l.followTemplate)
|
||||
fmt.Fprintf(&b, "%s\n\n", l.templateHeader)
|
||||
b.WriteString(body)
|
||||
b.WriteString("\n\n")
|
||||
fmt.Fprintf(&b, "%s\n", l.replyHeader)
|
||||
fmt.Fprintf(&b, "%s\n", l.nameRule)
|
||||
fmt.Fprintf(&b, "%s\n", l.descRule)
|
||||
if !omitSEOMeta {
|
||||
fmt.Fprintf(&b, "%s\n", l.metaRule)
|
||||
}
|
||||
b.WriteString(l.attrsRule)
|
||||
|
||||
// Free-form category overlay (no role markers) — keep as extra guidance like
|
||||
// soft "Category guidance" did, without replacing the GPT predloga.
|
||||
// soft "Category guidance" did, without replacing the template.
|
||||
extra := strings.TrimSpace(catPrompt)
|
||||
if extra != "" &&
|
||||
!aiprompts.CategoryEnhanceHasRoleSections(extra) &&
|
||||
!aiprompts.IsLegacyCombinedEnhancePrompt(extra) {
|
||||
b.WriteString("\n\nDodatna kategorijska navodila:\n")
|
||||
fmt.Fprintf(&b, "\n\n%s\n", l.extraHeader)
|
||||
b.WriteString(extra)
|
||||
}
|
||||
return strings.TrimSpace(b.String())
|
||||
return strings.TrimSpace(b.String()), slovenian
|
||||
}
|
||||
|
||||
// a1StyleLabels are the scaffolding strings around a category formula: how the
|
||||
// supplied variables are labelled and how the reply is framed.
|
||||
type a1StyleLabels struct {
|
||||
intro string
|
||||
oldName string
|
||||
oldDesc string
|
||||
category string
|
||||
useTemplate string
|
||||
followTemplate string
|
||||
templateHeader string
|
||||
replyHeader string
|
||||
nameRule string
|
||||
descRule string
|
||||
metaRule string
|
||||
attrsRule string
|
||||
extraHeader string
|
||||
}
|
||||
|
||||
var a1StyleLabelsSL = a1StyleLabels{
|
||||
intro: "Ustvari nov opis izdelka v tem jeziku: {{language}}, z naslednjimi spremenljivkami:",
|
||||
oldName: "Staro_ime_izdelka",
|
||||
oldDesc: "Star_opis_izdelka",
|
||||
category: "Kategorija",
|
||||
useTemplate: "Uporabi spodnjo GPT predlogo.",
|
||||
followTemplate: "Sledi tej GPT predlogi stavek po stavek in sestavi nov opis izdelka.",
|
||||
templateHeader: "GPT predloga:",
|
||||
replyHeader: "Odgovori SAMO z enim JSON objektom:",
|
||||
nameRule: `- "name" = rezultat <name> formule (novo ime; ne kopiraj Staro_ime_izdelka, če formula zahteva novo ime)`,
|
||||
descRule: `- "description" = HTML telo po GPT predlogi (vsi razdelki po vrsti), BREZ <name>/<metaDescription> tagov`,
|
||||
metaRule: `- "meta_title" / "meta_description" = plain SEO po meta / <metaDescription> formuli`,
|
||||
attrsRule: `- "attrs" = atributi (samo Allowed attribute keys, če so navedeni)`,
|
||||
extraHeader: "Dodatna kategorijska navodila:",
|
||||
}
|
||||
|
||||
var a1StyleLabelsEN = a1StyleLabels{
|
||||
intro: "Create a new product description in {{language}} using the following variables:",
|
||||
oldName: "Old_product_name",
|
||||
oldDesc: "Old_product_description",
|
||||
category: "Category",
|
||||
useTemplate: "Use the product template below.",
|
||||
followTemplate: "Follow this product template sentence by sentence and compose a new product description.",
|
||||
templateHeader: "Product template:",
|
||||
replyHeader: "Reply with ONE JSON object only:",
|
||||
nameRule: `- "name" = the result of the <name> formula (a new name; do not copy Old_product_name when the formula asks for a new one)`,
|
||||
descRule: `- "description" = the HTML body per the product template (every section in order), WITHOUT <name>/<metaDescription> tags`,
|
||||
metaRule: `- "meta_title" / "meta_description" = plain SEO text per the meta / <metaDescription> formula`,
|
||||
attrsRule: `- "attrs" = attributes (only Allowed attribute keys when listed)`,
|
||||
extraHeader: "Additional category instructions:",
|
||||
}
|
||||
|
||||
// reSlovenianFormulaCue keeps the scaffolding in the same language the formula
|
||||
// speaks. A1's legacy formulas refer to "Novo ime izdelka" and were written against
|
||||
// the Slovenian variable labels in generator.php, so those keep the Slovenian
|
||||
// frame; the English platform defaults get the English one. Output language is set
|
||||
// by {{language}} in the system prompt either way.
|
||||
var reSlovenianFormulaCue = regexp.MustCompile(`(?i)novo[ _]ime[ _]izdelka|napiši|napisi|izpostavi|izdelka|znamka`)
|
||||
|
||||
func collapseLegacyInstr(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
s = strings.ReplaceAll(s, "\r\n", "\n")
|
||||
|
||||
Reference in New Issue
Block a user