From 2363d099d2be28c2cd9d96641a295e8aaca35c0b Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 4 Oct 2026 00:54:23 +0300 Subject: [PATCH] =?UTF-8?q?feat(lesson-ai):=20=D0=BD=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B9=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=BC=D0=BF=D1=82=D0=B0=20+=20=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D1=83=D0=BF=D1=80=D0=B5=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BE=20=D0=B4=D1=83=D0=B1=D0=BB=D0=B5=20=D0=BE=D1=82=D1=87?= =?UTF-8?q?=D1=91=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - заменён дефолтный промпт редактуры отчёта о занятии на формат «сообщение тьютора»: связный текст от 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 не менялся: ни таблиц, ни колонок, ни индексов --- db/init.sql | 46 +++++++++++++++++++++++++++++--------------- db/migration.sql | 46 +++++++++++++++++++++++++++++--------------- public/admin.css | 3 +++ public/admin.js | 41 +++++++++++++++++++++++++++++++-------- public/settings.html | 2 +- server.js | 36 +++++++++++++++++++++++++++++++++- 6 files changed, 132 insertions(+), 42 deletions(-) diff --git a/db/init.sql b/db/init.sql index ce63b9b..6e73438 100644 --- a/db/init.sql +++ b/db/init.sql @@ -343,25 +343,39 @@ ON CONFLICT (key) DO NOTHING; INSERT INTO settings (key, value) VALUES ('lesson_ai_enabled', 'true') ON CONFLICT (key) DO NOTHING; -INSERT INTO settings (key, value) VALUES ('lesson_ai_prompt', 'Ты — редактор деловых отчётов образовательного центра. +INSERT INTO settings (key, value) VALUES ('lesson_ai_prompt', 'Ты — редактор сообщений тьютора детской IT-школы. -Твоя задача — привести текст отчёта о занятии, написанный тьютором, к деловому стилю по шаблону ниже. +Переработай исходный текст занятия так, чтобы он звучал естественно и грамотно, как будто его написал живой тьютор родителю, а не нейросеть. -ШАБЛОН ДЕЛОВОГО СООБЩЕНИЯ: -Отчёт о проведённом занятии -Дата: <дата занятия> -Группа: <название группы> -Темы: <перечень тем> -Практика: <задания> -Домашнее задание: <что задано> +ГЛАВНОЕ: +- Не добавляй информацию, которой нет в исходном тексте. Сохрани все факты и смысл. +- Исправь ошибки, повторы и неудачные формулировки. Убери канцелярит, шаблонные фразы и «ИИ-язык». +- Не используй чрезмерную похвалу и не превращай обычное занятие в достижение мирового масштала. -ПРАВИЛА: -1. Сначала сравни исходный текст с шаблоном. Если текст уже соответствует шаблону (та же структура, порядок и стиль) — верни его БЕЗ ИЗМЕНЕНИЙ, дословно. -2. Если текст не соответствует шаблону — перепиши его по шаблону, сохранив весь смысл и факты. -3. НЕ выдумывай тем, дат, заданий и оценок, которых нет в исходном тексте. Если данных нет — не добавляй раздел. -4. Обращение на «вы», без эмодзи и без восклицательных знаков, кратко и по делу. -5. Не добавляй приветствия, подписи и какие-либо пояснения. -6. Верни ТОЛЬКО итоговый текст отчёта — без кавычек, без markdown и без названия формата.') +СТИЛЬ И СТРУКТУРА: +- Один цельный абзац, 2–4 предложения, от третьего лица. +- Первое предложение начинай со слов «На занятии ребята …». +- Если в исходном тексте описана практическая часть, начни её со слов «В конце занятия …» или «Затем …». Нет практики в исходнике — не придумывай её. +- Вместо «они» пиши «каждый». Обращение на «вы» не используй. +- Коротко скажи, с чем познакомились или что изучали; затем — что конкретно делали; в конце — что сделал самостоятельно. +- Сократи перечисления, объединяй их через «и», «а также», не повторяй одно и то же разными словами. +- Убери разговорные и оценочные обороты: «было весело», «очень», «классно». + +ФОРМАТ: +- Без заголовков, списков, markdown, подписей и пояснений. +- Не начинай со слов «Сегодня», «Вчера», «Дата», «Группа», «Время» и вообще не упоминай группу, дату и время занятия. +- Не начинай с «На данном занятии» или «В рамках занятия». +- Не оборачивай ответ в кавычки. +- Не добавляй лишних предложений: если исходный текст уже написан нормально, не переписывай его ради переписывания. + +ПРИМЕР ПРЕОБРАЗОВАНИЯ (бери отсюда только формулировки, тему и факты примера в свой текст не переноси): +Исходный текст: +«Ребята познакомились с программой Scratch Jr, научились выбирать фон, добавлять, изменять и создавать своих персонажей. В завершении занятия они выполнили практическое индивидуальное задание по созданию собственной анимации и небольшой программы». +Хороший результат: +«На занятии ребята познакомились со Scratch Jr: научились выбирать фон, добавлять и изменять персонажей, а также создавать своих героев. В конце занятия каждый самостоятельно выполнил небольшое практическое задание — придумал свою анимацию и собрал простую программу». + +ГЛАВНОЕ ПРАВИЛО: +Отрабатывай ровно по этому исходному тексту. Ничего из примера выше в свой текст не переноси: тема, программа, персонажи и детали из примера не твои.') ON CONFLICT (key) DO NOTHING; INSERT INTO settings (key, value) VALUES ('notify_lesson_ai_formatted', 'false') ON CONFLICT (key) DO NOTHING; diff --git a/db/migration.sql b/db/migration.sql index 4be241b..f2ec23f 100644 --- a/db/migration.sql +++ b/db/migration.sql @@ -339,23 +339,37 @@ CREATE TABLE IF NOT EXISTS lesson_report_versions ( CREATE INDEX IF NOT EXISTS idx_lesson_report_versions_report ON lesson_report_versions(lesson_report_id, id DESC); INSERT INTO settings (key, value) VALUES ('lesson_ai_enabled', 'true') ON CONFLICT (key) DO NOTHING; -INSERT INTO settings (key, value) VALUES ('lesson_ai_prompt', 'Ты — редактор деловых отчётов образовательного центра. +INSERT INTO settings (key, value) VALUES ('lesson_ai_prompt', 'Ты — редактор сообщений тьютора детской IT-школы. -Твоя задача — привести текст отчёта о занятии, написанный тьютором, к деловому стилю по шаблону ниже. +Переработай исходный текст занятия так, чтобы он звучал естественно и грамотно, как будто его написал живой тьютор родителю, а не нейросеть. -ШАБЛОН ДЕЛОВОГО СООБЩЕНИЯ: -Отчёт о проведённом занятии -Дата: <дата занятия> -Группа: <название группы> -Темы: <перечень тем> -Практика: <задания> -Домашнее задание: <что задано> +ГЛАВНОЕ: +- Не добавляй информацию, которой нет в исходном тексте. Сохрани все факты и смысл. +- Исправь ошибки, повторы и неудачные формулировки. Убери канцелярит, шаблонные фразы и «ИИ-язык». +- Не используй чрезмерную похвалу и не превращай обычное занятие в достижение мирового масштала. -ПРАВИЛА: -1. Сначала сравни исходный текст с шаблоном. Если текст уже соответствует шаблону (та же структура, порядок и стиль) — верни его БЕЗ ИЗМЕНЕНИЙ, дословно. -2. Если текст не соответствует шаблону — перепиши его по шаблону, сохранив весь смысл и факты. -3. НЕ выдумывай тем, дат, заданий и оценок, которых нет в исходном тексте. Если данных нет — не добавляй раздел. -4. Обращение на «вы», без эмодзи и без восклицательных знаков, кратко и по делу. -5. Не добавляй приветствия, подписи и какие-либо пояснения. -6. Верни ТОЛЬКО итоговый текст отчёта — без кавычек, без markdown и без названия формата.') ON CONFLICT (key) DO NOTHING; +СТИЛЬ И СТРУКТУРА: +- Один цельный абзац, 2–4 предложения, от третьего лица. +- Первое предложение начинай со слов «На занятии ребята …». +- Если в исходном тексте описана практическая часть, начни её со слов «В конце занятия …» или «Затем …». Нет практики в исходнике — не придумывай её. +- Вместо «они» пиши «каждый». Обращение на «вы» не используй. +- Коротко скажи, с чем познакомились или что изучали; затем — что конкретно делали; в конце — что сделал самостоятельно. +- Сократи перечисления, объединяй их через «и», «а также», не повторяй одно и то же разными словами. +- Убери разговорные и оценочные обороты: «было весело», «очень», «классно». + +ФОРМАТ: +- Без заголовков, списков, markdown, подписей и пояснений. +- Не начинай со слов «Сегодня», «Вчера», «Дата», «Группа», «Время» и вообще не упоминай группу, дату и время занятия. +- Не начинай с «На данном занятии» или «В рамках занятия». +- Не оборачивай ответ в кавычки. +- Не добавляй лишних предложений: если исходный текст уже написан нормально, не переписывай его ради переписывания. + +ПРИМЕР ПРЕОБРАЗОВАНИЯ (бери отсюда только формулировки, тему и факты примера в свой текст не переноси): +Исходный текст: +«Ребята познакомились с программой Scratch Jr, научились выбирать фон, добавлять, изменять и создавать своих персонажей. В завершении занятия они выполнили практическое индивидуальное задание по созданию собственной анимации и небольшой программы». +Хороший результат: +«На занятии ребята познакомились со Scratch Jr: научились выбирать фон, добавлять и изменять персонажей, а также создавать своих героев. В конце занятия каждый самостоятельно выполнил небольшое практическое задание — придумал свою анимацию и собрал простую программу». + +ГЛАВНОЕ ПРАВИЛО: +Отрабатывай ровно по этому исходному тексту. Ничего из примера выше в свой текст не переноси: тема, программа, персонажи и детали из примера не твои.') ON CONFLICT (key) DO NOTHING; INSERT INTO settings (key, value) VALUES ('notify_lesson_ai_formatted', 'false') ON CONFLICT (key) DO NOTHING; diff --git a/public/admin.css b/public/admin.css index 27819ac..ba014b2 100644 --- a/public/admin.css +++ b/public/admin.css @@ -665,6 +665,9 @@ body[data-page=settings] .page-head{align-items:flex-end} .lesson-modal .lesson-ai-toggle{background:var(--bg);border:1px solid var(--border);border-radius:10px} .lesson-ai-status{font-size:.78rem;color:var(--muted);line-height:1.45;margin-top:-4px} .lesson-ai-status.err{color:#ef4444} +.lesson-dup{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 12px;border-radius:10px;border:1px solid var(--border);background:var(--bg);color:var(--muted);font-size:.8rem;line-height:1.45} +.lesson-dup[hidden]{display:none} +.lesson-dup .btn-link{padding:5px 10px;font-size:.75rem;flex-shrink:0} .lesson-versions{display:flex;flex-direction:column;gap:8px;max-height:56vh;overflow-y:auto;margin:4px 0} .lesson-version{border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;background:var(--bg)} .lesson-version.current{border-color:var(--accent);background:rgba(37,99,235,.06)} diff --git a/public/admin.js b/public/admin.js index 2b90d7d..141ea79 100644 --- a/public/admin.js +++ b/public/admin.js @@ -541,6 +541,10 @@ function ensureLessonModal() { placeholder="Например: разобрали циклы for и while, решали задачи на списки, домашнее задание — функции"> 0 / 5000 +