From 5d0e7555da845180461f92c025b731d0ade12a2a Mon Sep 17 00:00:00 2001 From: Fovway Date: Sat, 8 Nov 2025 00:58:00 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20API=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D1=82=D0=B5=D0=B3=D0=BE=D0=B2:=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D1=8B=20=D0=B8=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BA=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D1=82=D0=B5?= =?UTF-8?q?=D0=B3=D0=BE=D0=B2,=20=D1=83=D0=B2=D0=B5=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BB=D0=B8=D0=BC=D0=B8=D1=82=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BA=D0=B5=D0=BD=D0=BE=D0=B2=20=D0=B4=D0=BE=20500,=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BB=D0=BE?= =?UTF-8?q?=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=B8=D0=B7=D0=B2=D0=BB=D0=B5=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=82=D0=B5=D0=B3=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B8=D0=B7=20reasoning,=20=D0=B0=20=D1=82=D0=B0=D0=BA=D0=B6?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=BE=D1=80=D0=BC=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D1=82=D0=B5=D0=B3=D0=BE=D0=B2=20=D0=B2=20camelC?= =?UTF-8?q?ase.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B2=D0=B8=D0=B7=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20=D0=B2=20=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=B8=D1=81=D0=BD=D0=BE=D0=BC=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BD=D0=B8=D0=BA=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/server.js | 69 +++++++++++++++++++++++++++++++++++++++-------- dev-dist/sw.js | 2 +- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/backend/server.js b/backend/server.js index 66ceae2..dab203c 100644 --- a/backend/server.js +++ b/backend/server.js @@ -2617,7 +2617,7 @@ app.post("/api/ai/generate-tags", requireApiAuth, async (req, res) => { { role: "system", content: - "Ты помощник для генерации тегов. Проанализируй текст и предложи 3-8 релевантных тегов на русском языке через запятую. Теги должны быть краткими (1-3 слова). Избегай общих слов типа 'текст', 'заметка', 'информация'. Верни ТОЛЬКО теги через запятую, без знаков #, без нумерации, без точек. Пример: работа, проект, задачи, дедлайн", + "Ты помощник для генерации тегов. Проанализируй текст и предложи 3-8 релевантных тегов на русском языке через запятую. Теги должны быть краткими (1-3 слова) и написаны БЕЗ ПРОБЕЛОВ - слова объединяются в одно (например: списокПокупок, работаНадПроектом, важныеЗадачи). Избегай общих слов типа 'текст', 'заметка', 'информация'. Верни ТОЛЬКО теги через запятую, без знаков #, без нумерации, без точек. Пример: работа, проект, задачи, дедлайн, списокПокупок", }, { role: "user", @@ -2625,7 +2625,7 @@ app.post("/api/ai/generate-tags", requireApiAuth, async (req, res) => { }, ], temperature: 0.7, - max_tokens: 200, + max_tokens: 500, // Увеличено для моделей с reasoning tokens }; const requestData = JSON.stringify(requestBody); @@ -2693,6 +2693,26 @@ app.post("/api/ai/generate-tags", requireApiAuth, async (req, res) => { responseData.choices[0].message ) { tagsText = responseData.choices[0].message.content || ""; + // Если content пустой, пробуем извлечь из reasoning (для моделей с reasoning tokens) + if (!tagsText && responseData.choices[0].message.reasoning) { + const reasoning = responseData.choices[0].message.reasoning; + // Пытаемся найти теги в reasoning тексте + // Ищем паттерны типа "теги: ..." или просто список тегов через запятую + const tagsMatch = reasoning.match(/(?:теги?|tags?)[:\s]+([^.\n]+)/i); + if (tagsMatch && tagsMatch[1]) { + tagsText = tagsMatch[1].trim(); + } else { + // Если не нашли паттерн, пробуем взять последнюю строку reasoning + const lines = reasoning.split('\n').filter(l => l.trim()); + if (lines.length > 0) { + const lastLine = lines[lines.length - 1]; + // Проверяем, похоже ли на список тегов (содержит запятые и короткие слова) + if (lastLine.includes(',') && lastLine.length < 200) { + tagsText = lastLine.trim(); + } + } + } + } } // Альтернативный формат (некоторые API) else if ( @@ -2729,6 +2749,14 @@ app.post("/api/ai/generate-tags", requireApiAuth, async (req, res) => { firstChoice.content || firstChoice.message?.text || ""; + // Fallback на reasoning + if (!tagsText && firstChoice.message?.reasoning) { + const reasoning = firstChoice.message.reasoning; + const tagsMatch = reasoning.match(/(?:теги?|tags?)[:\s]+([^.\n]+)/i); + if (tagsMatch && tagsMatch[1]) { + tagsText = tagsMatch[1].trim(); + } + } } } @@ -2830,19 +2858,38 @@ app.post("/api/ai/generate-tags", requireApiAuth, async (req, res) => { console.log("Теги до обработки:", tags); + // Функция для объединения слов в теге (убирает пробелы и делает camelCase) + const normalizeTag = (tag) => { + // Убираем # в начале и конце + tag = tag.replace(/^#+\s*/, "").replace(/\s*#+$/, ""); + // Убираем точки, дефисы в начале/конце если они есть + tag = tag.replace(/^[.\-\s]+|[.\-\s]+$/g, ""); + // Убираем кавычки если есть + tag = tag.replace(/^["']+|["']+$/g, ""); + tag = tag.trim(); + + // Если есть пробелы, объединяем слова в camelCase + if (tag.includes(" ")) { + const words = tag.split(/\s+/).filter(w => w.length > 0); + if (words.length > 0) { + // Первое слово в нижнем регистре, остальные с заглавной первой буквой + const firstWord = words[0].toLowerCase(); + const restWords = words.slice(1).map(word => { + if (word.length === 0) return ""; + return word[0].toUpperCase() + word.slice(1).toLowerCase(); + }); + tag = firstWord + restWords.join(""); + } + } + + return tag; + }; + // Обрабатываем теги tags = tags .map((tag) => tag.trim()) .filter((tag) => tag.length > 0) - .map((tag) => { - // Убираем # в начале и конце - tag = tag.replace(/^#+\s*/, "").replace(/\s*#+$/, ""); - // Убираем точки, дефисы в начале/конце если они есть - tag = tag.replace(/^[.\-\s]+|[.\-\s]+$/g, ""); - // Убираем кавычки если есть - tag = tag.replace(/^["']+|["']+$/g, ""); - return tag.trim(); - }) + .map((tag) => normalizeTag(tag)) .filter((tag) => { // Фильтруем слишком короткие и слишком длинные теги return tag.length > 0 && tag.length <= 50; diff --git a/dev-dist/sw.js b/dev-dist/sw.js index f89a5dd..ad0c1a7 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-47da91e0'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "/index.html", - "revision": "0.q2r0i2lj5ro" + "revision": "0.5s0rolua70o" }], { "ignoreURLParametersMatching": [/^utm_/, /^fbclid$/] });