feat(flashcards): ИИ-генерация карточек по теме/тексту с предпросмотром в текущую колоду

This commit is contained in:
Maxim Dolgolyov
2026-06-12 23:06:08 +03:00
parent 21cea72874
commit 9dd3522869
3 changed files with 69 additions and 7 deletions
@@ -588,12 +588,15 @@ async function flashcardsFromText(req, res) {
if (!providersOrdered().length) return res.status(503).json({ error: 'LLM не настроена' });
const text = String((req.body && req.body.text) || '').trim().slice(0, 6000);
const title = String((req.body && req.body.title) || 'Карточки').trim().slice(0, 80) || 'Карточки';
if (text.length < 20) return res.status(400).json({ error: 'Слишком мало текста' });
const sys = 'Ты составляешь учебные флешкарты по тексту. Верни СТРОГО JSON-массив из 5–6 объектов ' +
'вида {"front":"...","back":"..."} без markdown и пояснений. front — короткий вопрос, back — краткий ответ (1–2 предложения). ' +
'По-русски. Формулы в LaTeX между $...$. Никакого текста вне JSON.';
let count = Number(req.body && req.body.count);
count = Number.isFinite(count) ? Math.max(3, Math.min(10, Math.round(count))) : 6;
if (text.length < 3) return res.status(400).json({ error: 'Введите тему или текст' });
const sys = 'Ты составляешь учебные флешкарты. Если на вход дан учебный текст или параграф — делай карточки СТРОГО по нему. ' +
'Если дана короткая тема (несколько слов) — раскрой её сам по школьной программе. ' +
'Верни СТРОГО JSON-массив из ' + count + ' объектов вида {"front":"...","back":"..."} без markdown и пояснений. ' +
'front — короткий вопрос, back — краткий ответ (1–2 предложения). По-русски. Формулы в LaTeX между $...$. Никакого текста вне JSON.';
let rr;
try { rr = await callLLMFailover([{ role: 'system', content: sys }, { role: 'user', content: text }], 1400); }
try { rr = await callLLMFailover([{ role: 'system', content: sys }, { role: 'user', content: text }], 1600); }
catch (e) { return res.status(502).json({ error: 'Не удалось обратиться к ИИ' }); }
const raw = rr && rr.text;
let cards = [];
@@ -609,7 +612,7 @@ async function flashcardsFromText(req, res) {
const arr = JSON.parse(s);
if (Array.isArray(arr)) {
cards = arr.filter(c => c && c.front && c.back)
.slice(0, 8)
.slice(0, count + 2)
.map(c => ({ front: String(c.front).slice(0, 500), back: String(c.back).slice(0, 1000) }));
}
} catch (e) { /* модель вернула не-JSON */ }