feat(assistant): RAG по учебникам, кэш+счётчик, режим учителя
- RAG: индексатор scripts/index-textbooks.js → textbook_chunks (миграция 063); ask() подмешивает релевантные куски учебников (LIKE-скоринг). Покрывает учебники со статическим текстом; JS-рендеримые — через контекст страницы. Админка: тумблер RAG + кнопка «Переиндексировать» + число фрагментов. - Кэш ответов (assistant_cache, 7 дней, только «чистые» вопросы без контекста/ истории) + суточный счётчик (assistant_usage: ИИ/кэш/FAQ) в админке. - Режим учителя: роль в /context, системный промпт для учителей (задания, план урока, учительские инструменты), подсказки-чипы для учителей. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -424,6 +424,7 @@
|
||||
|
||||
/* ── контекст: выделенный текст / текущий параграф ───────────────────── */
|
||||
var _lastSel = '';
|
||||
var _role = 'student';
|
||||
function getPageContext() {
|
||||
try {
|
||||
if (PAGE === 'textbook') {
|
||||
@@ -441,6 +442,7 @@
|
||||
|
||||
/* ── «Спроси Квантика» ───────────────────────────────────────────────── */
|
||||
var SUGGESTIONS = ['Как вырезать кусок учебника?', 'Как создать карточки?', 'Как начать тест?', 'Объясни теорему Пифагора', 'Где мои домашние задания?', 'Как включить тёмную тему?'];
|
||||
var TEACHER_SUGGESTIONS = ['Как создать класс и выдать задание?', 'Идеи заданий по теме…', 'Составь план урока по теме…', 'Как работает журнал и аналитика?', 'Как провести онлайн-урок?'];
|
||||
var _chat = []; // многоходовой диалог: [{role:'user'|'assistant', content}]
|
||||
function msgEl(role) { var d = document.createElement('div'); d.className = 'asst-msg asst-msg-' + role; return d; }
|
||||
function renderChat(chatEl) {
|
||||
@@ -460,8 +462,9 @@
|
||||
if (pc) ctxBtns += '<button class="asst-chip asst-chip-ctx" data-ctx="sec" type="button">Объяснить этот параграф</button>' +
|
||||
'<button class="asst-chip asst-chip-ctx" data-ctx="sum" type="button">Конспект параграфа</button>' +
|
||||
'<button class="asst-chip asst-chip-ctx" data-ctx="cards" type="button">Флешкарты из параграфа</button>';
|
||||
var sug = (_role === 'teacher' || _role === 'admin') ? TEACHER_SUGGESTIONS : SUGGESTIONS;
|
||||
var chips = '<div class="asst-chips">' + ctxBtns +
|
||||
SUGGESTIONS.map(function (q) { return '<button class="asst-chip" type="button">' + esc(q) + '</button>'; }).join('') + '</div>';
|
||||
sug.map(function (q) { return '<button class="asst-chip" type="button">' + esc(q) + '</button>'; }).join('') + '</div>';
|
||||
openBubble(
|
||||
'<div class="asst-name">Спроси Квантика' + (_chat.length ? '<button class="asst-link" data-a="clear" style="float:right;font-weight:600;margin-right:24px">Очистить</button>' : '') + '</div>' +
|
||||
'<div class="asst-chat"></div>' + chips +
|
||||
@@ -697,6 +700,7 @@
|
||||
if (!document.body) { return setTimeout(boot, 200); }
|
||||
LS.assistantContext().then(function (ctx) {
|
||||
SRV = ctx || {};
|
||||
_role = (SRV && SRV.role) || 'student';
|
||||
if (SRV.enabled === false) return; // выключено пользователем
|
||||
return (LS.api ? LS.api('/api/pet') : Promise.resolve(null)).then(function (pet) {
|
||||
PET = pet || null;
|
||||
|
||||
Reference in New Issue
Block a user