fix: avoid repeating last 3 rubrics in cover selection (no more similar covers)

This commit is contained in:
Nik (Claude)
2026-06-19 01:09:52 +03:00
parent eca072a172
commit 5b5f703078
+41 -7
View File
@@ -466,13 +466,34 @@ async function generateCoverViaPollinations({ prompt }) {
* Выбирает наиболее подходящую рубрику для обложки статьи. * Выбирает наиболее подходящую рубрику для обложки статьи.
* Дешёвый haiku-вызов: ~50 токенов. При ошибке — случайная рубрика. * Дешёвый haiku-вызов: ~50 токенов. При ошибке — случайная рубрика.
*/ */
async function selectRubric({ title, tags = [], rubrics }) { async function selectRubric({ title, tags = [], rubrics, channelId = null }) {
if (!rubrics || rubrics.length === 0) return null; if (!rubrics || rubrics.length === 0) return null;
if (rubrics.length === 1) return rubrics[0]; if (rubrics.length === 1) return rubrics[0];
const rubricList = rubrics.map((r, i) => `${i}. ${r.id}: ${r.desc}`).join('\n'); // Получаем последние использованные рубрики из БД (анти-повтор)
const userMsg = `Article title: "${title}"\nTags: ${tags.join(', ') || 'none'}\n\nRubrics:\n${rubricList}\n\nRespond with ONLY the index number (0-${rubrics.length - 1}) of the best matching rubric.`; let recentlyUsed = [];
if (channelId) {
try {
const r = await query(
'SELECT last_rubrics_used FROM channel_style WHERE channel_id = $1',
[channelId]
);
recentlyUsed = Array.isArray(r.rows[0]?.last_rubrics_used)
? r.rows[0].last_rubrics_used
: [];
} catch (_) {}
}
// Доступные рубрики = все минус последние 3 использованные
// (если осталось < 2 — берём все, иначе AI выбирает только из свежих)
const recent = recentlyUsed.slice(-3);
let available = rubrics.filter(r => !recent.includes(r.id));
if (available.length < 2) available = rubrics;
const rubricList = available.map((r, i) => `${i}. ${r.id}: ${r.desc}`).join('\n');
const userMsg = `Article title: "${title}"\nTags: ${tags.join(', ') || 'none'}\n\nRubrics:\n${rubricList}\n\nRespond with ONLY the index number (0-${available.length - 1}) of the best matching rubric.`;
let selected = null;
try { try {
const res = await axios.post( const res = await axios.post(
`${config.ai.baseUrl}/chat/completions`, `${config.ai.baseUrl}/chat/completions`,
@@ -489,12 +510,25 @@ async function selectRubric({ title, tags = [], rubrics }) {
); );
const raw = res.data?.choices?.[0]?.message?.content?.trim() || '0'; const raw = res.data?.choices?.[0]?.message?.content?.trim() || '0';
const idx = parseInt(raw.replace(/\D/g, '')) || 0; const idx = parseInt(raw.replace(/\D/g, '')) || 0;
const safeIdx = Math.min(Math.max(idx, 0), rubrics.length - 1); const safeIdx = Math.min(Math.max(idx, 0), available.length - 1);
return rubrics[safeIdx]; selected = available[safeIdx];
} catch (err) { } catch (err) {
console.warn('[Cover] selectRubric failed, using random:', err.message.slice(0, 80)); console.warn('[Cover] selectRubric failed, using random:', err.message.slice(0, 80));
return rubrics[Math.floor(Math.random() * rubrics.length)]; selected = available[Math.floor(Math.random() * available.length)];
} }
// Записываем в last_rubrics_used (храним последние 5)
if (channelId && selected) {
try {
const newList = [...recentlyUsed, selected.id].slice(-5);
await query(
'UPDATE channel_style SET last_rubrics_used = $1 WHERE channel_id = $2',
[JSON.stringify(newList), channelId]
);
} catch (_) {}
}
return selected;
} }
async function generateCover({ articleId, title, tags = [], channelId = null }) { async function generateCover({ articleId, title, tags = [], channelId = null }) {
@@ -514,7 +548,7 @@ async function generateCover({ articleId, title, tags = [], channelId = null })
let styleName; let styleName;
const rubrics = channelStyle?.image_rubrics; const rubrics = channelStyle?.image_rubrics;
if (Array.isArray(rubrics) && rubrics.length > 0) { if (Array.isArray(rubrics) && rubrics.length > 0) {
selectedRubric = await selectRubric({ title, tags, rubrics }); selectedRubric = await selectRubric({ title, tags, rubrics, channelId });
styleName = selectedRubric?.id || 'rubric'; styleName = selectedRubric?.id || 'rubric';
console.log(`[Cover] article=${articleId} channel=${channelId} rubric=${styleName}`); console.log(`[Cover] article=${articleId} channel=${channelId} rubric=${styleName}`);
} else { } else {