diff --git a/backend/src/controllers/assistantController.js b/backend/src/controllers/assistantController.js index 2553bce..705f0b7 100644 --- a/backend/src/controllers/assistantController.js +++ b/backend/src/controllers/assistantController.js @@ -616,4 +616,4 @@ async function flashcardsFromText(req, res) { res.json({ title, cards }); } -module.exports = { getContext, markSeen, dismiss, setSettings, ask, flashcardsFromText, feedback, getMemory, clearMemory, getStudentProfile, llmConfig, pingLLM, clearFailover: _clearFailover }; +module.exports = { getContext, markSeen, dismiss, setSettings, ask, flashcardsFromText, feedback, getMemory, clearMemory, getStudentProfile, llmConfig, pingLLM, clearFailover: _clearFailover, callLLMFailover }; diff --git a/backend/src/controllers/imggenController.js b/backend/src/controllers/imggenController.js index 642ef7e..8fc3916 100644 --- a/backend/src/controllers/imggenController.js +++ b/backend/src/controllers/imggenController.js @@ -17,6 +17,23 @@ function _cfg() { } function _enabled() { const c = _cfg(); return !!(c && c.provider === 'cloudflare' && c.accountId && c.token); } +/* FLUX лучше понимает английский. Если в промпте есть кириллица — переводим + * через тот же LLM-провайдер, что и ассистент (с failover). При сбое — исходный текст. */ +async function _toEnglish(prompt) { + if (!/[Ѐ-ӿ]/.test(prompt)) return prompt; + try { + const { callLLMFailover } = require('./assistantController'); + const sys = 'You translate image-generation prompts into concise, vivid English. ' + + 'Output ONLY the English prompt — no quotes, no notes, no preamble. Keep it short and descriptive.'; + const r = await callLLMFailover([{ role: 'system', content: sys }, { role: 'user', content: prompt }], 120); + if (r && r.text) { + const en = String(r.text).replace(/^["'«»\s]+|["'«»\s]+$/g, '').replace(/\s+/g, ' ').trim(); + if (en && !/[Ѐ-ӿ]/.test(en)) return en.slice(0, 500); + } + } catch (e) {} + return prompt; // перевод не удался — отправим как есть +} + /* GET /api/imggen/status — для UI (показывать кнопки или нет) */ function status(req, res) { res.json({ enabled: _enabled() }); } @@ -35,13 +52,15 @@ async function generate(req, res) { if (d && d.day === today && d.count >= DAILY_CAP) return res.status(429).json({ error: 'Дневной лимит генераций исчерпан, попробуй завтра' }); _cooldown.set(uid, now); + const enPrompt = await _toEnglish(prompt); + const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), 30000); try { const r = await fetch(`https://api.cloudflare.com/client/v4/accounts/${cfg.accountId}/ai/run/${cfg.model}`, { method: 'POST', headers: { Authorization: 'Bearer ' + cfg.token, 'Content-Type': 'application/json' }, - body: JSON.stringify({ prompt, steps: 4 }), + body: JSON.stringify({ prompt: enPrompt, steps: 4 }), signal: ctrl.signal, }); if (!r.ok) { const t = await r.text(); return res.status(502).json({ error: 'Сервис картинок ответил ошибкой (' + r.status + ')', detail: t.slice(0, 120) }); }