Treat AI create input as a research brief and localize FA prompts.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
d37b920c01
commit
57800634ca
@@ -105,7 +105,7 @@ Rules:
|
||||
- Use 2-6 top-level categories when appropriate.
|
||||
- Add subcategories only where they help shoppers browse (max depth ${MAX_DEPTH}).
|
||||
- Every node needs nameEn and nameFa (Farsi in Persian script).
|
||||
- Descriptions are optional, max 120 characters, English only.
|
||||
- Descriptions are optional, max 120 characters. Match the user prompt language (Persian if the prompt is Persian, otherwise English).
|
||||
- Do not duplicate category names at the same level.
|
||||
- Total nodes must not exceed ${MAX_TOTAL}.`;
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ Return ONLY valid JSON with this shape:
|
||||
{
|
||||
"fields": [
|
||||
{
|
||||
"label": "Field label in English",
|
||||
"label": "Field label",
|
||||
"type": "text | textarea | select | multi_select",
|
||||
"isRequired": true,
|
||||
"options": ["Option A", "Option B"]
|
||||
@@ -108,6 +108,7 @@ Rules:
|
||||
- textarea fields are for longer specs (features, care instructions).
|
||||
- Mark important buyer-facing specs as required.
|
||||
- Labels must be unique and human-readable.
|
||||
- Write labels and option text in the same language as the user hint. If the hint is Persian (Farsi), use Persian labels and options; otherwise use English.
|
||||
- Do not include price, stock, SKU, or warranty period fields.
|
||||
- Prefer metric units common in Iran when relevant.`;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsEnum, IsOptional, IsString, MinLength, ValidateIf } from 'class-validator';
|
||||
import { IsEnum, IsOptional, IsString, MaxLength, MinLength, ValidateIf } from 'class-validator';
|
||||
|
||||
export enum ProductAiLanguage {
|
||||
en = 'en',
|
||||
@@ -16,8 +16,10 @@ export class CreateProductByAiDto {
|
||||
@MinLength(1)
|
||||
categoryId!: string;
|
||||
|
||||
/** Product brief for AI: model name, optional URL, and notes. */
|
||||
@IsString()
|
||||
@MinLength(2)
|
||||
@MaxLength(4000)
|
||||
name!: string;
|
||||
|
||||
@IsEnum(ProductAiLanguage)
|
||||
|
||||
@@ -285,18 +285,21 @@ Return ONLY valid JSON with this shape:
|
||||
}
|
||||
|
||||
Rules:
|
||||
- Be factual and realistic for the named product in the given category.
|
||||
- The user input is a research brief in ${inputLanguage}. It may include a model/product name, a product page URL, and extra notes — not a final storefront title.
|
||||
- Infer the real product from the brief (and any URL/model clues). Do not copy URLs, markdown, or raw notes into title/nameFa.
|
||||
- Write clean storefront titles: "title" in English, "nameFa" in Persian. Keep brand/model accurate.
|
||||
- Be factual and realistic for the identified product in the given category.
|
||||
- If technical form fields are provided, fill technicalValues using exact field keys.
|
||||
- For select fields use one allowed option value exactly.
|
||||
- For multi_select fields use an array of allowed option values.
|
||||
- For text/textarea fields use plain strings.
|
||||
- The user input name is in ${inputLanguage}; keep that spelling in the matching field and translate/generate the other language field.
|
||||
- Prefer the input language for summary/description tone, but always return both title and nameFa.
|
||||
- descriptionHtml should be 2-4 paragraphs with key specs.
|
||||
- tags: 3-8 relevant lowercase tags.`;
|
||||
|
||||
const userPrompt = JSON.stringify({
|
||||
category: input.categoryName,
|
||||
inputName: input.productName,
|
||||
researchBrief: input.productName,
|
||||
inputLanguage: input.language,
|
||||
technicalFields: technicalSchema,
|
||||
});
|
||||
@@ -327,15 +330,9 @@ Rules:
|
||||
fields: TechnicalFormField[];
|
||||
},
|
||||
): AiProductDraft {
|
||||
const title =
|
||||
input.language === ProductAiLanguage.en
|
||||
? input.productName
|
||||
: String(draft.title ?? input.productName).trim();
|
||||
|
||||
const nameFa =
|
||||
input.language === ProductAiLanguage.fa
|
||||
? input.productName
|
||||
: String(draft.nameFa ?? '').trim();
|
||||
const fallbackName = this.shortProductLabel(input.productName);
|
||||
const title = String(draft.title ?? '').trim() || fallbackName;
|
||||
const nameFa = String(draft.nameFa ?? '').trim() || fallbackName;
|
||||
|
||||
const summary = String(draft.summary ?? '').trim();
|
||||
const descriptionHtml = normalizeAiDescriptionHtml(
|
||||
@@ -395,4 +392,14 @@ Rules:
|
||||
technicalValues,
|
||||
};
|
||||
}
|
||||
|
||||
/** First non-URL line of the research brief, truncated for fallback titles. */
|
||||
private shortProductLabel(brief: string): string {
|
||||
const line =
|
||||
brief
|
||||
.split(/\r?\n/)
|
||||
.map((part) => part.trim())
|
||||
.find((part) => part && !/^https?:\/\//i.test(part)) ?? brief.trim();
|
||||
return line.slice(0, 120).trim();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user