fix: avoid repeating last 3 rubrics in cover selection (no more similar covers)
This commit is contained in:
+41
-7
@@ -466,13 +466,34 @@ async function generateCoverViaPollinations({ prompt }) {
|
||||
* Выбирает наиболее подходящую рубрику для обложки статьи.
|
||||
* Дешёвый 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.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 {
|
||||
const res = await axios.post(
|
||||
`${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 idx = parseInt(raw.replace(/\D/g, '')) || 0;
|
||||
const safeIdx = Math.min(Math.max(idx, 0), rubrics.length - 1);
|
||||
return rubrics[safeIdx];
|
||||
const safeIdx = Math.min(Math.max(idx, 0), available.length - 1);
|
||||
selected = available[safeIdx];
|
||||
} catch (err) {
|
||||
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 }) {
|
||||
@@ -514,7 +548,7 @@ async function generateCover({ articleId, title, tags = [], channelId = null })
|
||||
let styleName;
|
||||
const rubrics = channelStyle?.image_rubrics;
|
||||
if (Array.isArray(rubrics) && rubrics.length > 0) {
|
||||
selectedRubric = await selectRubric({ title, tags, rubrics });
|
||||
selectedRubric = await selectRubric({ title, tags, rubrics, channelId });
|
||||
styleName = selectedRubric?.id || 'rubric';
|
||||
console.log(`[Cover] article=${articleId} channel=${channelId} rubric=${styleName}`);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user