From 08086650fc9925d90f6f5ced62ebb06dc06070af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=20=28Claude=29?= Date: Thu, 11 Jun 2026 15:15:22 +0300 Subject: [PATCH] feat: customPrompt piped through full generation chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - generatePost: customPrompt или channel.ai_style_prompt → добавляется к userPrompt - routes/generate.js: принимает customPrompt, передаёт в очередь - workers/generation.js: передаёт customPrompt в generatePost и generateArticle --- src/routes/generate.js | 4 ++-- src/services/ai.js | 8 ++++++-- src/workers/generation.js | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/routes/generate.js b/src/routes/generate.js index a3b9311..0fb1e11 100644 --- a/src/routes/generate.js +++ b/src/routes/generate.js @@ -7,7 +7,7 @@ const generationQueue = require('../workers/generation'); // POST /api/generate — создать задачу генерации router.post('/', async (req, res) => { try { - const { type, topic, channelId, rubric, keywords = [], useCritique = true } = req.body; + const { type, topic, channelId, rubric, keywords = [], useCritique = true, customPrompt } = req.body; const userId = req.headers['x-user-id'] || null; if (!type) return res.status(400).json({ error: 'type is required' }); @@ -22,7 +22,7 @@ router.post('/', async (req, res) => { ); const jobId = rows[0].id; - await generationQueue.add({ jobId, type, topic, channelId, rubric, keywords, useCritique }); + await generationQueue.add({ jobId, type, topic, channelId, rubric, keywords, useCritique, customPrompt }); res.json({ jobId, status: 'pending' }); } catch (err) { diff --git a/src/services/ai.js b/src/services/ai.js index 2bc111e..06921fc 100644 --- a/src/services/ai.js +++ b/src/services/ai.js @@ -119,11 +119,15 @@ async function image(prompt, options = {}) { * @returns {object} {content, prompt, usage} */ async function generatePost(channel, opts = {}) { - const { topic, rubric = '', useCritique = true, returnPrompt = false } = opts; + const { topic, rubric = '', useCritique = true, returnPrompt = false, customPrompt } = opts; if (!topic) throw new Error('topic is required'); const systemPrompt = pb.buildPostSystemPrompt(channel, rubric); - const userPrompt = `Напиши пост на тему: "${topic}"`; + const stylePrompt = customPrompt || channel?.ai_style_prompt || null; + let userPrompt = `Напиши пост на тему: "${topic}"`; + if (stylePrompt) { + userPrompt += `\n\n---\nДОПОЛНИТЕЛЬНЫЕ ИНСТРУКЦИИ (выполнить обязательно):\n${stylePrompt.trim()}`; + } // Шаг 1: первичная генерация (с повышенной температурой для разнообразия) const first = await chat( diff --git a/src/workers/generation.js b/src/workers/generation.js index ac2b641..3d876d5 100644 --- a/src/workers/generation.js +++ b/src/workers/generation.js @@ -15,7 +15,7 @@ const generationQueue = new Queue('generation', { }); generationQueue.process(async (job) => { - const { jobId, type, topic, channelId, rubric, keywords, useCritique } = job.data; + const { jobId, type, topic, channelId, rubric, keywords, useCritique, customPrompt } = job.data; await query(`UPDATE generation_jobs SET status='processing', updated_at=NOW() WHERE id=$1`, [jobId]); @@ -28,12 +28,12 @@ generationQueue.process(async (job) => { if (type === 'post') { if (!channel) throw new Error('Channel not found for post generation'); - const r = await ai.generatePost(channel, { topic, rubric, useCritique }); + const r = await ai.generatePost(channel, { topic, rubric, useCritique, customPrompt }); resultText = r.content; usage = r.usage; } else if (type === 'article') { - const r = await ai.generateArticle(channel || { language: 'ru' }, { topic, keywords }); + const r = await ai.generateArticle(channel || { language: 'ru' }, { topic, keywords, customPrompt }); resultText = r.content; usage = r.usage;