Урок 1: первая память — хранилище и поиск по смыслу¶
В этом уроке бот-географ получит базу знаний и научится отвечать на вопросы, даже если формулировки вопроса и ответа не совпадают дословно.
Концепция: что такое память в LLM-приложении¶
Модель (ChatGPT, Llama, что угодно) не помнит ничего за пределами тех
слов, которые вы прислали прямо сейчас. Память в protoprompt — это
отдельное хранилище, куда приложение складывает факты, а потом
подкладывает нужные в промпт.
Чтобы найти нужный факт, хранилище использует векторы:
- Каждый текст переводится в эмбеддинг — список чисел, «отпечаток смысла» текста.
- Похожие по смыслу тексты получают похожие отпечатки.
- Поиск — это сравнение: чем ближе векторы, тем ближе смысл.
Сравнение считается как косинусная близость: результат от 0 (совсем не похоже) до 1 (почти одно и то же). Бот не ищет по точному совпадению слов — он ищет по совпадению смысла.
Практика: читаем проект¶
Откройте examples/tutorials/01_first_bot/main.py. Он состоит из трёх
частей.
Шаг 1. Заглушка LLM¶
В настоящем проекте здесь был бы Ollama или OpenAI. Заглушка просто собирает эмбеддинг из слов: каждое слово красит свою «точку» в векторе. Примитивно, но работает офлайн и позволяет почувствовать механику.
Шаг 2. Кладём факты в память¶
store = InMemStore()
for i, (text, meta) in enumerate(FACTS):
store.add(f"fact-{i}", [text], await llm.embed([text]), meta)
Что здесь происходит:
InMemStore()— хранилище в оперативке. Всё пропадёт при перезапуске — для урока это нормально.store.add(doc_id, chunks, embeddings, metadata)— кладёт документ. Три аргумента понятны из имени:"fact-0"— имя документа;[text]— список кусков текста;await llm.embed([text])— эмбеддинги этих кусков.
meta— ярлык-метаданные (например, тема факта).
Повторное добавление
Если добавить документ с тем же doc_id ещё раз, старые чанки этого
документа заменятся, а не продублируются.
Шаг 3. Ищем ответ¶
store.query — сердце поиска:
- первый аргумент — эмбеддинг вопроса;
top_k=1— вернуть самый похожий чанк;score_threshold=0.2— не считать ответом то, что похоже слишком слабо.
Похожесть хранится в поле score каждого результата:
Что увидите при запуске¶
Вопрос: Какая столица у Франции?
Похожесть: 0.38
Ответ: Париж — столица Франции, стоит на реке Сена.
Вопрос: Кто придумал Python?
Похожесть: 0.65
Ответ: Python — язык программирования...
Вопрос: Сколько будет 2+2?
(в памяти ничего похожего нет)
Обратите внимание на «Сколько будет 2+2?»: в базе что-то есть, но ничего
не похоже по смыслу — поэтому score ниже порога и ответа нет.
Задание¶
- Добавьте в
FACTSтри своих факта (любая тема) и перезапустите. - Найдите факт, который не найдет бот, хотя факт в базе есть. Почему так? (Подсказка: заглушка ловит только совпавшие слова.)
- Попробуйте фильтр по теме. Замените вызов
queryна:
Вопрос про Python теперь не должен находить ничего.
- Замените
InMemStore()наSqliteStore("geo.db")и запустите дважды. Первый раз бот добавит факты, второй раз — заменит теми же. База сохраняется между запусками.
Дальше¶
Вы умеете хранить и находить факты. Но живой диалог — это не база фактов, а переписка, которая растёт с каждым сообщением. Что с ней делать, когда она перестаёт влезать в окно модели? Урок 2 — про сжатие сессии.