From 4e8c0841db05969fc230dcd336e72a6f8ec7b2bc Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 12 Jun 2026 11:20:05 +0300 Subject: [PATCH] =?UTF-8?q?feat(imggen):=20=D0=B0=D0=B2=D1=82=D0=BE-=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=D0=BF=D1=82=D0=B0=20=D0=BD=D0=B0=20=D0=B0=D0=BD=D0=B3=D0=BB?= =?UTF-8?q?=D0=B8=D0=B9=D1=81=D0=BA=D0=B8=D0=B9=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=20FLUX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FLUX лучше понимает английский. Если в промпте есть кириллица — прогоняем через тот же LLM-провайдер ассистента (callLLMFailover, с failover) и отправляем перевод. При сбое перевода — исходный текст. callLLMFailover теперь экспортируется из assistantController. Co-Authored-By: Claude Opus 4.8 --- .../src/controllers/assistantController.js | 2 +- backend/src/controllers/imggenController.js | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) 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) }); }