feat: customPrompt piped through full generation chain

- generatePost: customPrompt или channel.ai_style_prompt → добавляется к userPrompt
- routes/generate.js: принимает customPrompt, передаёт в очередь
- workers/generation.js: передаёт customPrompt в generatePost и generateArticle
This commit is contained in:
Ник (Claude)
2026-06-11 15:15:22 +03:00
parent 1ef770b5fc
commit 08086650fc
3 changed files with 11 additions and 7 deletions
+2 -2
View File
@@ -7,7 +7,7 @@ const generationQueue = require('../workers/generation');
// POST /api/generate — создать задачу генерации // POST /api/generate — создать задачу генерации
router.post('/', async (req, res) => { router.post('/', async (req, res) => {
try { 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; const userId = req.headers['x-user-id'] || null;
if (!type) return res.status(400).json({ error: 'type is required' }); 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; 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' }); res.json({ jobId, status: 'pending' });
} catch (err) { } catch (err) {
+6 -2
View File
@@ -119,11 +119,15 @@ async function image(prompt, options = {}) {
* @returns {object} {content, prompt, usage} * @returns {object} {content, prompt, usage}
*/ */
async function generatePost(channel, opts = {}) { 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'); if (!topic) throw new Error('topic is required');
const systemPrompt = pb.buildPostSystemPrompt(channel, rubric); 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: первичная генерация (с повышенной температурой для разнообразия) // Шаг 1: первичная генерация (с повышенной температурой для разнообразия)
const first = await chat( const first = await chat(
+3 -3
View File
@@ -15,7 +15,7 @@ const generationQueue = new Queue('generation', {
}); });
generationQueue.process(async (job) => { 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]); 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 (type === 'post') {
if (!channel) throw new Error('Channel not found for post generation'); 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; resultText = r.content;
usage = r.usage; usage = r.usage;
} else if (type === 'article') { } 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; resultText = r.content;
usage = r.usage; usage = r.usage;