forked from admin/zeropost-engine
feat: rewrite article prompt for natural Russian, add editor pass (2-stage generation)
This commit is contained in:
+45
-5
@@ -167,20 +167,60 @@ async function generateTopics(channel, count = 5) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сгенерировать статью для блога.
|
* Сгенерировать статью для блога. С двумя проходами для качества:
|
||||||
|
* 1. Первый драфт
|
||||||
|
* 2. Критика + переписывание (если useEditPass=true, по умолчанию включено)
|
||||||
*/
|
*/
|
||||||
async function generateArticle(channel, opts = {}) {
|
async function generateArticle(channel, opts = {}) {
|
||||||
const { topic, keywords = [] } = opts;
|
const { topic, keywords = [], useEditPass = true } = opts;
|
||||||
if (!topic) throw new Error('topic is required');
|
if (!topic) throw new Error('topic is required');
|
||||||
|
|
||||||
const systemPrompt = pb.buildArticleSystemPrompt(channel, keywords);
|
const systemPrompt = pb.buildArticleSystemPrompt(channel, keywords);
|
||||||
const userPrompt = `Напиши статью на тему: "${topic}"`;
|
const userPrompt = `Напиши статью на тему: "${topic}"`;
|
||||||
const res = await chat(
|
|
||||||
|
// === Первый проход — драфт ===
|
||||||
|
const draft = await chat(
|
||||||
config.ai.models.article,
|
config.ai.models.article,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
userPrompt,
|
userPrompt,
|
||||||
{ maxTokens: 4000, temperature: 0.8 }
|
{ maxTokens: 4000, temperature: 0.85 }
|
||||||
);
|
);
|
||||||
return { content: res.text, usage: res.usage };
|
|
||||||
|
if (!useEditPass) {
|
||||||
|
return { content: draft.text, usage: draft.usage };
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Второй проход — редактура ===
|
||||||
|
const editorPrompt = `Ты — опытный редактор. Передо мной черновик статьи. Перепиши его так, чтобы он звучал максимально по-человечески — как будто писал живой думающий автор для русской аудитории.
|
||||||
|
|
||||||
|
ЧТО ИСПРАВИТЬ В ПЕРВУЮ ОЧЕРЕДЬ:
|
||||||
|
|
||||||
|
1. Убери AI-штампы: "В современном мире", "Важно отметить", "Стоит подчеркнуть", "Революционный", "Поистине", "Не секрет, что", "В заключение"
|
||||||
|
2. Убери канцелярит: "осуществить", "произвести", "представляет собой", "позволяет осуществлять"
|
||||||
|
3. Разорви монотонность — варьируй длину предложений. Если 5 предложений подряд одинаковой длины — переписать.
|
||||||
|
4. Добавь связки между абзацами: "Дело в том что", "На практике", "С другой стороны", "Точнее"
|
||||||
|
5. Замени общие фразы на конкретику. "Многие компании" → конкретные названия. "Недавно" → конкретный месяц.
|
||||||
|
6. Убери параллельные конструкции если их слишком много (первое... второе... третье...)
|
||||||
|
7. Сохрани структуру (заголовки H1, H2), длину и тему — но перепиши язык
|
||||||
|
8. Markdown только для заголовков. Никакого **жирного** и *курсива* в тексте.
|
||||||
|
|
||||||
|
ВАЖНО: верни ТОЛЬКО переписанную статью, без комментариев и пояснений. Начинай с заголовка # ...`;
|
||||||
|
|
||||||
|
const edited = await chat(
|
||||||
|
config.ai.models.article,
|
||||||
|
editorPrompt,
|
||||||
|
`Вот черновик для редактуры:\n\n${draft.text}`,
|
||||||
|
{ maxTokens: 4000, temperature: 0.75 }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: edited.text,
|
||||||
|
usage: {
|
||||||
|
prompt_tokens: (draft.usage?.prompt_tokens || 0) + (edited.usage?.prompt_tokens || 0),
|
||||||
|
completion_tokens: (draft.usage?.completion_tokens || 0) + (edited.usage?.completion_tokens || 0),
|
||||||
|
},
|
||||||
|
draft: draft.text, // оставим для дебага
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -196,20 +196,70 @@ ${style.banned_topics?.length ? `НЕ трогай темы: ${style.banned_topi
|
|||||||
*/
|
*/
|
||||||
function buildArticleSystemPrompt(channel, keywords = []) {
|
function buildArticleSystemPrompt(channel, keywords = []) {
|
||||||
const lang = channel?.language === 'en' ? 'английском' : 'русском';
|
const lang = channel?.language === 'en' ? 'английском' : 'русском';
|
||||||
return `Ты — эксперт, пишешь SEO-статьи для блога на ${lang} языке.
|
return `Ты — опытный русскоязычный автор и редактор. Пишешь живые, читаемые статьи для русской аудитории на ${lang} языке.
|
||||||
|
|
||||||
Формат:
|
ГЛАВНОЕ: текст должен звучать так, будто его написал думающий человек, а не ИИ. Если статья звучит "по-нейросетевому" — она провалена.
|
||||||
- Заголовок H1
|
|
||||||
- Лид-абзац (что в статье и почему важно)
|
═══════════════════════════════════════════════════════════
|
||||||
- 3-5 разделов с H2
|
ЯЗЫК И СТИЛЬ — критично, читай внимательно
|
||||||
- Заключение
|
═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
ХОРОШИЙ русский текст:
|
||||||
|
✓ Естественный поток речи, как будто автор объясняет другу
|
||||||
|
✓ Связки между предложениями ("Дело в том что", "Точнее говоря", "На практике это значит")
|
||||||
|
✓ Длина предложений варьируется: короткие, средние, иногда длинные с уточнениями
|
||||||
|
✓ Конкретные примеры, имена, цифры — не общие фразы
|
||||||
|
✓ Логические переходы между абзацами — мысль развивается, а не прыгает
|
||||||
|
✓ Личный взгляд автора заметен — где-то ирония, где-то скепсис, где-то восторг
|
||||||
|
✓ Можно начинать предложение с "И", "Но", "А", "Зато", "Кстати"
|
||||||
|
|
||||||
|
ПЛОХОЙ ИИ-русский (НИКОГДА не пиши так):
|
||||||
|
✗ "Рваные" короткие фразы подряд без связок
|
||||||
|
✗ "В современном мире...", "В эпоху цифровизации...", "Важно отметить..."
|
||||||
|
✗ "Не секрет, что...", "Поистине...", "Революционный/уникальный"
|
||||||
|
✗ Канцелярит: "осуществить разработку", "произвести анализ", "явиться причиной"
|
||||||
|
✗ Англицизмы калькой: "имплементировать", "интегрировать в воркфлоу", "комьюнити"
|
||||||
|
✗ Списки маркированных пунктов из 3 слов каждый
|
||||||
|
✗ Параллельные конструкции в каждом абзаце ("первое... второе... третье...")
|
||||||
|
✗ Двоеточие после каждой второй фразы
|
||||||
|
✗ "В заключение хотелось бы отметить..."
|
||||||
|
✗ Прямой перевод английских структур: "Это позволяет вам..." вместо "Так можно..."
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
ПРИМЕРЫ
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
ПЛОХО (ИИ-стиль):
|
||||||
|
"В современном мире искусственный интеллект играет важную роль. Важно отметить, что компании активно внедряют ИИ-решения. ChatGPT представляет собой революционную технологию. Она позволяет пользователям эффективно решать задачи. В заключение стоит подчеркнуть, что будущее за ИИ."
|
||||||
|
|
||||||
|
ХОРОШО (живой русский):
|
||||||
|
"С ChatGPT случилась странная штука. За полтора года он из игрушки превратился в инструмент, которым серьёзно пользуются юристы, аналитики и редакторы — те, кто раньше посмеивался над "роботом-болтуном". И дело даже не в качестве ответов. Просто оказалось, что для большинства задач хватает и "достаточно хорошо", если это "хорошо" приходит за 5 секунд."
|
||||||
|
|
||||||
|
Чувствуешь разницу? В плохом — текст из штампов, никакой мысли. В хорошем — есть наблюдение, конкретика, голос автора.
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
СТРУКТУРА
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
- Заголовок H1 — конкретный, без воды, без двоеточий-подзаголовков типа "ИИ: будущее уже наступило"
|
||||||
|
- Лид (1-2 абзаца) — сразу к делу, цепляешь читателя, ставишь проблему или интригу
|
||||||
|
- 3-5 разделов с H2 — каждый раздел развивает мысль, не дублирует
|
||||||
|
- Заключение — короткое, без "подведём итоги". Можно вывод, наблюдение или открытый вопрос
|
||||||
- 800-1500 слов
|
- 800-1500 слов
|
||||||
|
- Markdown ТОЛЬКО для заголовков (# и ##). Никакого **жирного**, *курсива* — это уродует текст
|
||||||
|
- Списки используй только когда они реально нужны (этапы, перечисление инструментов). Не превращай статью в bullet points
|
||||||
|
|
||||||
${keywords.length ? `Ключевые слова (вплети органично): ${keywords.join(', ')}` : ''}
|
${keywords.length ? `Ключевые слова для SEO (вплети органично, не криво): ${keywords.join(', ')}\n` : ''}
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
ФИНАЛЬНАЯ ПРОВЕРКА
|
||||||
|
═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
${HUMANITY_RULES}
|
Прежде чем закончить — перечитай текст и спроси себя:
|
||||||
|
1. Если убрать тему — этот текст можно отличить от любого другого ИИ-текста?
|
||||||
|
2. Есть ли в тексте хоть одно наблюдение или мысль, которую ИИ-генератор не сделал бы автоматически?
|
||||||
|
3. Если бы это написал живой автор — он бы оставил эту фразу?
|
||||||
|
|
||||||
Не используй markdown-разметку для жирного/курсива — только заголовки # и ##.`;
|
Если на любой вопрос "нет" — переписывай абзац.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
Reference in New Issue
Block a user