אנו הופכים את יצירת תיאורי ה-SEO לאוטומטית עבור חנויות מסחר אלקטרוני שבהן הקטלוג כולל אלפי פריטים. כתיבה ידנית של טקסטים ייחודיים לכל מוצר הייתה אורכת חודשים ועולה מיליונים — המערכת שלנו מבצעת זאת תוך שעות. אך קריאה פשוטה ל-API של רשת נוירונים אינה מספיקה: נדרשת ארכיטקטורה מחושבת היטב, הכוללת הכנת נתונים, הנדסת פרומפטים, עיבוד אצווה, ולידציה וממשק סקירה. עם ניסיון של למעלה מ-10 שנים בפיתוח מערכות בעומס גבוה, אנו מבטיחים יציבות ואיכות הפקה.
למה זה עובד?
מודלי שפה מודרניים — כגון ChatGPT (GPT-4o) ו-Claude — מייצרים טקסטים משמעותיים אם מספקים להם נתונים מובנים: שם, קטגוריה, מאפיינים. לפי תיעוד OpenAI, למידה קונטקסטואלית מאפשרת התאמת הפלט למשימה. הנדסת פרומפטים קובעת את הטון, האורך, המבנה ודרישות מילות המפתח, כך שהתוצאה רלוונטית ומותאמת ל-SEO. דוגמה לנעלי סניקרס Nike Air Max 270:
{
"id": "SKU-4821",
"name": "Кроссовки Nike Air Max 270",
"category": "Мужская обувь / Кроссовки",
"brand": "Nike",
"attributes": {
"material": "mesh + synthetic",
"sole": "Air Max unit",
"colors": ["black/white", "navy/grey"],
"sizes": "40–46",
"weight": "310g"
},
"tags": ["беговые", "повседневные", "амортизация"],
"targetKeywords": ["nike air max 270 купить", "кроссовки найк аир макс 270"]
} כיצד מובטחת ייחודיות?
המודל עם טמפרטורה >0 תמיד מייצר תוצאה שונה. בנוסף, אנו בודקים כל הפקה לכפילויות באמצעות Elasticsearch — אם הטקסט תואם לטקסט קיים, אנו מפעילים הפקה חדשה עם seed שונה. זה מבטל כפילויות בקטלוג. גישה זו שומרת על ייחודיות גם בהפקה המונית.
כיצד אנו מעצבים פרומפטים לטקסטים של מוצרים?
פרומפט אינו רק "כתוב תיאור מוצר." פרומפט טוב מגדיר מבנה, טון, אורך, דרישות מילות מפתח ואיסורים. דוגמה ב-TypeScript:
function buildProductSeoPrompt(product: Product, keywords: string[]): string {
return ` Write a product description for an e-commerce catalog in Russian.
Product: ${product.name}
Category: ${product.category}
Brand: ${product.brand}
Key attributes: ${JSON.stringify(product.attributes)}
Tags: ${product.tags.join(", ")}
Requirements:
- Length: 200–400 words
- Include these keywords naturally: ${keywords.join(", ")}
- Structure: opening benefit statement → key features (3–5 points) → use cases → closing
- Tone: informative, no hype, no superlatives like "лучший" or "уникальный"
- Do NOT use: "данный товар", "представляем вашему вниманию", bullet points
- Do NOT start with the product name
- Write for a person who is comparing options
Output: plain text, no markdown, no headings.
`.trim();
} מדוע עיבוד אצווה עם תורים חשוב?
הפקת טקסטים באופן סינכרוני אינה מעשית — בקשה ל-LLM אורכת 3–10 שניות, וייתכנו אלפי פריטים. אנו משתמשים בתור משימות מבוסס BullMQ עם מקביליות וניסיונות חוזרים.
import { Queue, Worker } from "bullmq";
import { openai } from "../lib/openai";
import { db } from "../lib/db";
const seoQueue = new Queue("seo-generation", {
connection: {
host: "localhost",
port: 6379,
},
});
export async function queueProductsForGeneration(productIds: string[]) {
const jobs = productIds.map((id) => ({
name: "generate",
data: { productId: id },
opts: {
attempts: 3,
backoff: { type: "exponential", delay: 5000 },
removeOnComplete: 100,
},
}));
await seoQueue.addBulk(jobs);
}
const worker = new Worker(
"seo-generation",
async (job) => {
const product = await db.products.findById(job.data.productId);
if (!product) return;
const keywords = await getTargetKeywords(product);
const prompt = buildProductSeoPrompt(product, keywords);
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
temperature: 0.7,
max_tokens: 600,
});
const text = completion.choices[0].message.content?.trim();
if (!text) throw new Error("Empty response");
await db.productSeoTexts.upsert({
productId: product.id,
text,
status: "draft",
model: "gpt-4o-mini",
generatedAt: new Date(),
});
},
{
connection: {
host: "localhost",
port: 6379,
},
concurrency: 5,
}
);
כיצד מטפלים בשגיאות במהלך ההפקה?
אם בקשה נכשלת או מחזירה תגובה ריקה, המשימה נכנסת אוטומטית מחדש לתור עם השהיה אקספוננציאלית. לאחר שלושה ניסיונות כושלים, המוצר מסומן כ-{ "id": "SKU-4821", "name": "Кроссовки Nike Air Max 270", "category": "Мужская обувь / Кроссовки", "brand": "Nike", "attributes": { "material": "mesh + synthetic", "sole": "Air Max unit", "colors": ["black/white", "navy/grey"], "sizes": "40–46", "weight": "310g" }, "tags": ["беговые", "повседневные", "амортизация"], "targetKeywords": ["nike air max 270 купить", "кроссовки найк аир макс 270"] } ונשלח לסקירה ידנית. זה מבטיח סובלנות לתקלות וממזער אובדן נתונים.
בקרת איכות באמצעות ולידציה
הטקסט המופק נבדק אוטומטית: אורך, נוכחות כל מילות המפתח, היעדר ביטויי עצירה, צפיפות מילות מפתח. אם הוולידציה נכשלת, המוצר מסומן ב-function buildProductSeoPrompt(product: Product, keywords: string[]): string { return ` Write a product description for an e-commerce catalog in Russian. Product: ${product.name} Category: ${product.category} Brand: ${product.brand} Key attributes: ${JSON.stringify(product.attributes)} Tags: ${product.tags.join(", ")} Requirements: - Length: 200–400 words - Include these keywords naturally: ${keywords.join(", ")} - Structure: opening benefit statement → key features (3–5 points) → use cases → closing - Tone: informative, no hype, no superlatives like "лучший" or "уникальный" - Do NOT use: "данный товар", "представляем вашему вниманию", bullet points - Do NOT start with the product name - Write for a person who is comparing options Output: plain text, no markdown, no headings. `.trim(); } ונשלח להפקה מחודשת עם פרומפט מותאם.
interface ValidationResult {
passed: boolean;
issues: string[];
}
function validateSeoText(text: string, product: Product): ValidationResult {
const issues: string[] = [];
if (text.length < 500) issues.push(`Too short: ${text.length} chars`);
const missingKeywords = product.targetKeywords.filter(kw => !text.toLowerCase().includes(kw.toLowerCase()));
if (missingKeywords.length > 0) issues.push(`Missing keywords: ${missingKeywords.join(", ")}`);
const stopPhrases = ["данный товар", "представляем вашему вниманию", "уникальный", "лучший в своём классе"];
for (const phrase of stopPhrases) {
if (text.toLowerCase().includes(phrase)) issues.push(`Contains stop phrase: "${phrase}"`);
}
const wordCount = text.split(/\s+/).length;
for (const kw of product.targetKeywords) {
const kwCount = (text.toLowerCase().match(new RegExp(kw.toLowerCase(), "g")) || []).length;
if (kwCount / wordCount > 0.03) issues.push(`Keyword density too high for "${kw}": ${(kwCount / wordCount * 100).toFixed(1)}%`);
}
return { passed: issues.length === 0, issues };
} ממשק סקירה
עורכים רואים רשימת טיוטות עם כפתורי "פרסום", "הפקה מחדש", "עריכה". הפקה מחדש מתחשבת בסיבת הדחייה הקודמת — העובד מוסיף אותה לפרומפט. כל הטיוטות נשמרות בסטטוס import { Queue, Worker } from "bullmq"; import { openai } from "../lib/openai"; import { db } from "../lib/db"; const seoQueue = new Queue("seo-generation", { connection: { host: "localhost", port: 6379 }, }); export async function queueProductsForGeneration(productIds: string[]) { const jobs = productIds.map((id) => ({ name: "generate", data: { productId: id }, opts: { attempts: 3, backoff: { type: "exponential", delay: 5000 }, removeOnComplete: 100 }, })); await seoQueue.addBulk(jobs); } const worker = new Worker("seo-generation", async (job) => { const product = await db.products.findById(job.data.productId); if (!product) return; const keywords = await getTargetKeywords(product); const prompt = buildProductSeoPrompt(product, keywords); const completion = await openai.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: prompt }], temperature: 0.7, max_tokens: 600, }); const text = completion.choices[0].message.content?.trim(); if (!text) throw new Error("Empty response"); await db.productSeoTexts.upsert({ productId: product.id, text, status: "draft", model: "gpt-4o-mini", generatedAt: new Date(), }); }, { connection: { host: "localhost", port: 6379 }, concurrency: 5 }); ; פרסום מתרחש רק לאחר אישור.
השוואה: כתיבה ידנית מול הפקת AI
| פרמטר | כתיבת תוכן ידנית | הפקת AI |
|---|---|---|
| מהירות לטקסט | 15–30 דקות | 5–15 שניות |
| עלות עבור 10,000 טקסטים | גבוהה (תלויה בכותבים) | נמוכה משמעותית |
| מדרגיות | לינארית עם מספר הכותבים | תור מקבילי |
| בקרת איכות | תלויה במבצע | ולידציה אוטומטית |
| עדכניות | עדכונים ידניים | טריגר בשינוי נתונים |
דוגמה: עבור לקוח גדול בתחום ההלבשה, הפקנו 12,000 תיאורים ב-4 שעות. הפרומפטים כללו עונתיות, מגדר, טבלת מידות. לאחר ההפקה הראשונית, 8% מהטקסטים נכנסו ל-needs_review עקב צפיפות מילות מפתח גבוהה — לאחר התאמת הפרומפט, האחוז ירד ל-2%. ההשקה הסופית ארכה יום אחד.
שלבי הטמעה
| שלב | תיאור | משך |
|---|---|---|
| ניתוח | איסוף מבנה נתונים, בדיקת פרומפטים על מדגם | שבוע |
| פיתוח | שילוב LLM, תור, ולידטורים, ממשק סקירה | 2–3 שבועות |
| בדיקות | הרצה על 500 מוצרים, שיפור איטרטיבי של פרומפטים | שבוע |
| השקה | הפקת כל הקטלוג, הדרכת הצוות | שבוע |
מה כלול בהטמעה?
- שילוב עם LLM (OpenAI, Claude) דרך API
- מערכת תורים על BullMQ עם ניסיונות חוזרים והשהיה
- הנדסת פרומפטים לספציפיות שלך (קטגוריות, טון, מילות מפתח)
- ממשק סקירה ומודרציה (React + TypeScript)
- ולידטורים: אורך, מילות מפתח, מילות עצירה, צפיפות
- תיעוד והדרכת צוות
- תמיכה לחודש לאחר ההשקה
לוח זמנים ועלות
זמן הטמעה — בין 2 ל-6 שבועות בהתאם לגודל הקטלוג ומורכבות השילוב. העלות מחושבת באופן אישי — ככל שיש יותר מוצרים, כך כל טקסט בודד זול יותר. בואו נבחן את הפרויקט שלכם? צרו קשר — נספר לכם כיצד להפחית את תקציב תוכן ה-SEO פי כמה.
בקשו ייעוץ — ננתח את הקטלוג שלכם ונבחר את מודל ההפקה האופטימלי. קבלו אב-טיפוס על הנתונים שלכם ותראו את האפקט.







