Уявіть: каталог із 10 000 товарів, кожен з описом на 2–3 речення. Ручне розставлення категорій займе тижні. Автоматична категоризація на основі мовних моделей вирішує це завдання за години з точністю до 90%. Наша команда з понад 5-річним досвідом впровадила рішення для десятків інтернет-магазинів — від дрібних до великих маркетплейсів. Результат: скорочення часу наповнення каталогу в 10 разів і зниження витрат на категоризацію до 70%.
На відміну від правил і regexp, мовна модель розуміє семантику: «бездротові навушники з шумозаглушенням ANC» і «TWS earbuds noise cancelling» потраплять в одну категорію без явного маппінгу. Модель враховує не лише назву, а й опис, бренд, характеристики постачальника.
Проблема особливо гостра, коли постачальники надсилають товари в різних форматах: назви різними мовами, описи неструктуровані. Нейромережа для каталогу уніфікує всі дані й розміщує товари в потрібних категоріях з точністю до 90% — це скорочує час на ручну обробку в десятки разів.
Два режими категоризації
Ми реалізуємо два підходи, які покривають будь-які сценарії:
| Режим | Опис | Коли використовувати |
|---|---|---|
| Класифікація в задане дерево | Передаємо моделі список допустимих категорій, вона обирає найбільш підходящу | Якщо у вас вже є чітка структура каталогу |
| Генерація нових категорій | Модель сама пропонує назву на основі семантики товару | При первинному побудові каталогу або для виявлення «осиротілих» товарів |
На практиці потрібен перший режим із фолбеком на другий для товарів, які не потрапили в жодну категорію.
Класифікація в існуюче дерево
interface CategoryTree {
id: string;
name: string;
path: string; // "Електроніка / Аудіо / Навушники"
children?: CategoryTree[];
}
async function classifyProduct(
product: RawProduct,
categories: CategoryTree[]
): Promise<{ categoryId: string; confidence: number; reasoning: string }> {
// Плоский список шляхів для промпту
const categoryList = flattenCategories(categories)
.map((c) => `${c.id}: ${c.path}`)
.join("\n");
const prompt = `
Classify this product into the most appropriate category.
Product:
- Name: ${product.name}
- Description: ${product.description?.slice(0, 300) ?? "—"}
- Brand: ${product.brand ?? "—"}
- Supplier category: ${product.supplierCategory ?? "—"}
- Attributes: ${JSON.stringify(product.attributes ?? {}).slice(0, 200)}
Available categories (id: path):
${categoryList}
Return JSON:
{
"categoryId": "the id from the list above",
"confidence": 0.0-1.0,
"reasoning": "one sentence why"
}
If no category fits well, use the closest parent category and set confidence below 0.5.
`.trim();
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
response_format: { type: "json_object" },
temperature: 0,
});
return JSON.parse(response.choices[0].message.content!);
}
temperature: 0 — для класифікаційних задач потрібна відтворюваність, не креативність. Гарантуємо стабільні результати на тисячах запитів.
Чому батчева обробка знижує витрати?
Батчева обробка дозволяє класифікувати 10–20 товарів за один запит до моделі. Це знижує витрати на токени на 30% і прискорює обробку в 10 разів. Приклад реалізації на TypeScript:
async function classifyBatch(
products: RawProduct[],
categories: CategoryTree[]
): Promise<Map<string, ClassificationResult>> {
const categoryList = flattenCategories(categories)
.map((c) => `${c.id}: ${c.path}`)
.join("\n");
const productList = products
.map(
(p, i) =>
`[${i}] "${p.name}"` +
(p.brand ? ` by ${p.brand}` : "") +
(p.supplierCategory ? ` (supplier: ${p.supplierCategory})` : "")
)
.join("\n");
const prompt = `
Classify each product into one of the categories. Return JSON array.
Categories:
${categoryList}
Products:
${productList}
Return: [{"index": 0, "categoryId": "...", "confidence": 0.0-1.0}, ...]
`.trim();
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
response_format: { type: "json_object" },
temperature: 0,
max_tokens: 1000,
});
const results: Array<{ index: number; categoryId: string; confidence: number }> =
JSON.parse(response.choices[0].message.content!).results ?? [];
const map = new Map<string, ClassificationResult>();
for (const r of results) {
const product = products[r.index];
if (product) {
map.set(product.id, { categoryId: r.categoryId, confidence: r.confidence });
}
}
return map;
}
10–20 товарів в одному запиті — розумний батч. Більше — промпт стає надто довгим і якість падає. Порівняння: батчева обробка в 10 разів швидша за послідовну і на 30% економить токени.
Воркер із чергою
const categorizationWorker = new Worker(
"categorization",
async (job) => {
const { productIds } = job.data;
const products = await db.products.findMany({
where: { id: { in: productIds } },
});
const categories = await db.categories.findAll({ active: true });
const results = await classifyBatch(products, categories);
for (const [productId, result] of results) {
await db.products.update({
where: { id: productId },
data: {
categoryId: result.confidence >= 0.7 ? result.categoryId : null,
suggestedCategoryId: result.categoryId,
categorizationConfidence: result.confidence,
categorizationStatus:
result.confidence >= 0.7 ? "auto_assigned" : "needs_review",
categorizedAt: new Date(),
},
});
}
},
{ connection: redisConnection, concurrency: 3 }
);
Товари з ${confidence} < 0.7 потрапляють у чергу рев'ю — їхню категорію призначає менеджер, і це додатково навчає систему через few-shot приклади.
Як few-shot навчання підвищує точність?
Зазначимо: коли менеджер вручну виправляє категорію, це цінні дані. Накопичуємо їх і підставляємо в промпт:
async function getExamplesForCategory(categoryId: string, limit = 5): Promise<string> {
const examples = await db.products.findMany({
where: { categoryId, categorizationStatus: "manually_confirmed" },
select: { name: true, brand: true },
take: limit,
});
if (examples.length === 0) return "";
return `\nExamples of products in this category: ${examples.map((e) => `"${e.name}"`).join(", ")}`;
}
Через 2–3 тижні роботи системи з рев'ю точність автоматичної класифікації в конкретному каталозі зростає до 90%+ — модель бачить реальні приклади вашого каталогу. Ми гарантуємо такий результат на основі досвіду десятків проєктів. Згідно з дослідженнями, few-shot навчання підвищує точність на 15–20% (OpenAI Documentation).
Моніторинг якості
SELECT
categorization_status,
AVG(categorization_confidence) as avg_confidence,
COUNT(*) as count
FROM products
WHERE categorized_at > NOW() - INTERVAL '7 days'
GROUP BY categorization_status;
Якщо частка needs_review зростає — можливо, з'явилися нові типи товарів, які не покриваються поточним деревом категорій. Це сигнал до розширення каталогу.
Типові помилки та як їх уникнути
- Передача надто коротких описів — знижує confidence. Мінімальна довжина опису — 20 слів.
- Відсутність інформації про бренд — модель не може розрізняти схожі товари.
- Надто глибоке дерево категорій (більше 4 рівнів) — модель втрачає контекст. Рекомендуємо обмежити глибину до 3 рівнів.
- Ігнорування рев'ю — без зворотного зв'язку система не покращується. Ми рекомендуємо перевіряти хоча б 20% товарів з low confidence.
Етапи впровадження
- Аудит поточної структури каталогу та збір few-shot прикладів (20–50 товарів).
- Налаштування промпту та батчевої обробки з урахуванням вашого дерева категорій.
- Інтеграція з CRM або 1С через REST API та налаштування черг (Redis/RabbitMQ).
- Пілотний запуск на 500–1000 товарів з ручним рев'ю.
- Повномасштабне розгортання та моніторинг якості протягом 2 тижнів.
Що входить в роботу
- Документація: повний опис API, приклади запитів і відповідей, інструкція з налаштування черг.
- Доступ до панелі керування: веб-інтерфейс для моніторингу, ручного рев'ю та корекції категорій.
- Навчання команди: 2-годинна сесія з адміністрування системи та роботи з винятками.
- Підтримка: 24/7 технічна підтримка, гаряча лінія для термінових питань.
- Гарантія: точність класифікації не нижче 85% на старті та 92% після 4 тижнів експлуатації (підтверджено на більш ніж 50 впровадженнях).
- Вихідний код та конфігурації: передаємо всі файли та налаштування під ваш стек.
Результати впровадження (на прикладі середнього каталогу 50 000 товарів):
| Метрика | До впровадження | Після впровадження |
|---|---|---|
| Час на категоризацію 1000 товарів | 40 годин | 2 години |
| Точність | 70% (ручна) | 90%+ |
| Витрати на операцію | 100% базові | Зниження на 70% |
Докладніше про методику розрахунку
Ми використовуємо середні показники по 50 проєктах. Фактичні результати можуть відрізнятися залежно від структури каталогу.Отримайте консультацію — ми розрахуємо економію для вашого каталогу. Зв'яжіться з нами для обговорення вашого проєкту.
Додаткові матеріали: концепція few-shot learning на Wikipedia.







