Архитектура
Система памяти
Как GrandHub тебя запоминает
3-уровневая система памяти: от мгновенных regex-фактов до семантических векторов и проактивных напоминаний. Бот помнит тебя навсегда.
Пирамида памяти
УРОВЕНЬ 3 — ГЛУБОКИЙ
Open Loops
незавершённые темы · проактивные напоминания
↓
УРОВЕНЬ 2 — СЕМАНТИКА
RAG-векторы
embeddings · semantic search · FTS fallback
↓
УРОВЕНЬ 1 — БЫСТРЫЙ (БАЗА)
Regex-факты
10 паттернов · <1 мс · 0 токенов
Уровень 1Мгновенно · Бесплатно
Regex-факты
10 регулярных паттернов извлекают ключевые факты прямо из сообщения — без вызова AI.
Имя: «Меня зовут...»
Возраст: «мне 28 лет»
Город: «живу в Москве»
Работа: «работаю в...»
Семья: «моя жена»
Предпочтения: «люблю...»
Режим: «я жаворонок»
Цели: «хочу похудеть»
Животные: «у меня собака»
Хобби: «играю в...»
Задержка: < 1 мс
Стоимость: 0 токенов
Уровень 2Векторный движок · Семантический поиск
RAG-векторы
LLM извлекает факты из разговора → векторные эмбеддинги → семантический поиск + FTS fallback.
LLM-экстракция фактов
Векторные embeddings
Семантический поиск
FTS-fallback (полнотекстовый)
Дедупликация фактов
Временное взвешивание
Задержка: ~200 мс
Стоимость: ~50 токенов
Уровень 3Проактивные напоминания
Open Loops
Незавершённые темы и задачи. Бот сам возвращается к ним при следующем контакте.
Незавершённые задачи
Ожидание результата
Напоминания по времени
Контекстуальные триггеры
Цепочки диалога
Follow-up вопросы
Задержка: async
Стоимость: проактивно
Пример: «Меня зовут Роман, живу в Питере»
⚡
Шаг 1
Regex L1 находит: имя=Роман, город=Санкт-Петербург — мгновенно, <1мс
🔍
Шаг 2
LLM извлекает: {«имя»: «Роман», «город»: «Санкт-Петербург»} → векторизация
💾
Шаг 3
Факты сохранены в векторной БД. buildContext() добавит их в любой будущий промпт
✅
Шаг 4
Следующий запрос: бот уже знает «Роман из Питера» — без повторных вопросов
buildContext() — сборка промпта
async function buildContext(userId, message) {
// L1: Regex-факты (синхронно, <1мс)
const regexFacts = extractRegexFacts(message);
// L2: RAG-поиск (async, ~200мс)
const embedding = await voyage.embed(message);
const ragFacts = await vectorDB.search(userId, embedding, topK=5);
// L3: Open Loops (незавершённые темы)
const openLoops = await getOpenLoops(userId);
// Сборка системного промпта
return `
Пользователь: ${regexFacts.name ?? ragFacts.name}
Город: ${ragFacts.city}
Известные факты: ${ragFacts.join(', ')}
Незакрытые темы: ${openLoops.join(', ')}
Запрос: ${message}
`;
}