feat(lesson-ai): новый шаблон промпта + предупреждение о дубле отчёта

- заменён дефолтный промпт редактуры отчёта о занятии на формат
  «сообщение тьютора»: связный текст от 3-го лица, 1 абзац 2–4
  предложения, начало «На занятии ребята …», практика «В конце занятия …»,
  без группы/даты/времени и markdown, обращение на «вы» убрано, «они» → «каждый»
- синхронизированы три копии промпта: LESSON_AI_DEFAULT_PROMPT в server.js
  и сид lesson_ai_prompt в db/init.sql и db/migration.sql; добавлен пример
  «плохо → хорошо» с запретом переносить факты примера
- дубль отчёта в модалке создания больше не автозаполняет форму: показывается
  баннер #lessonDup с кнопкой перехода к существующему отчёту
- проверка на дубль срабатывает и при смене даты (#lessonDate), защищена
  счётчиком поколений lessonDupSeq от гонки при быстрой смене группы/даты
- стили .lesson-dup в public/admin.css, уточнена подсказка в карточке
  шаблона отчёта на public/settings.html
- DDL не менялся: ни таблиц, ни колонок, ни индексов
This commit is contained in:
dev
2026-10-04 00:54:23 +03:00
parent b931c0a760
commit 2363d099d2
6 changed files with 132 additions and 42 deletions
+35 -1
View File
@@ -3755,7 +3755,41 @@ app.delete('/api/modules/:id/photo', requireAdmin, async (req, res) => {
const LESSON_REPORT_TEXT_MAX = 5000;
const LESSON_REPORT_LIST_TTL_MS = 30 * 1000;
const LESSON_AI_VERSION_LIMIT = 50;
const LESSON_AI_DEFAULT_PROMPT = 'Ты — редактор деловых отчётов образовательного центра.\n\nТвоя задача — привести текст отчёта о занятии, написанный тьютором, к деловому стилю по шаблону ниже.\n\nШАБЛОН ДЕЛОВОГО СООБЩЕНИЯ:\nОтчёт о проведённом занятии\nДата: <дата занятия>\nГруппа: <название группы>\nТемы: <перечень тем>\nПрактика: <задания>\nДомашнее задание: <что задано>\n\nПРАВИЛА:\n1. Сначала сравни исходный текст с шаблоном. Если текст уже соответствует шаблону (та же структура, порядок и стиль) — верни его БЕЗ ИЗМЕНЕНИЙ, дословно.\n2. Если текст не соответствует шаблону — перепиши его по шаблону, сохранив весь смысл и факты.\n3. НЕ выдумывай тем, дат, заданий и оценок, которых нет в исходном тексте. Если данных нет — не добавляй раздел.\n4. Обращение на «вы», без эмодзи и без восклицательных знаков, кратко и по делу.\n5. Не добавляй приветствия, подписи и какие-либо пояснения.\n6. Верни ТОЛЬКО итоговый текст отчёта — без кавычек, без markdown и без названия формата.';
const LESSON_AI_DEFAULT_PROMPT = [
'Ты — редактор сообщений тьютора детской IT-школы.',
'',
'Переработай исходный текст занятия так, чтобы он звучал естественно и грамотно, как будто его написал живой тьютор родителю, а не нейросеть.',
'',
'ГЛАВНОЕ:',
'- Не добавляй информацию, которой нет в исходном тексте. Сохрани все факты и смысл.',
'- Исправь ошибки, повторы и неудачные формулировки. Убери канцелярит, шаблонные фразы и «ИИ-язык».',
'- Не используй чрезмерную похвалу и не превращай обычное занятие в достижение мирового масштала.',
'',
'СТИЛЬ И СТРУКТУРА:',
'- Один цельный абзац, 2–4 предложения, от третьего лица.',
'- Первое предложение начинай со слов «На занятии ребята …».',
'- Если в исходном тексте описана практическая часть, начни её со слов «В конце занятия …» или «Затем …». Нет практики в исходнике — не придумывай её.',
'- Вместо «они» пиши «каждый». Обращение на «вы» не используй.',
'- Коротко скажи, с чем познакомились или что изучали; затем — что конкретно делали; в конце — что сделал самостоятельно.',
'- Сократи перечисления, объединяй их через «и», «а также», не повторяй одно и то же разными словами.',
'- Убери разговорные и оценочные обороты: «было весело», «очень», «классно».',
'',
'ФОРМАТ:',
'- Без заголовков, списков, markdown, подписей и пояснений.',
'- Не начинай со слов «Сегодня», «Вчера», «Дата», «Группа», «Время» и вообще не упоминай группу, дату и время занятия.',
'- Не начинай с «На данном занятии» или «В рамках занятия».',
'- Не оборачивай ответ в кавычки.',
'- Не добавляй лишних предложений: если исходный текст уже написан нормально, не переписывай его ради переписывания.',
'',
'ПРИМЕР ПРЕОБРАЗОВАНИЯ (бери отсюда только формулировки, тему и факты примера в свой текст не переноси):',
'Исходный текст:',
'«Ребята познакомились с программой Scratch Jr, научились выбирать фон, добавлять, изменять и создавать своих персонажей. В завершении занятия они выполнили практическое индивидуальное задание по созданию собственной анимации и небольшой программы».',
'Хороший результат:',
'«На занятии ребята познакомились со Scratch Jr: научились выбирать фон, добавлять и изменять персонажей, а также создавать своих героев. В конце занятия каждый самостоятельно выполнил небольшое практическое задание — придумал свою анимацию и собрал простую программу».',
'',
'ГЛАВНОЕ ПРАВИЛО:',
'Отрабатывай ровно по этому исходному тексту. Ничего из примера выше в свой текст не переноси: тема, программа, персонажи и детали из примера не твои.',
].join('\n');
async function lessonReportGroup(user, groupId) {
const gid = Number(groupId);