5 из 102 мин

Как я сделал систему, которая не даёт контенту исчезать

Одна из главных задач этого проекта не только отвечать людям, но и возвращать материал обратно в жизнь.

Для этого у бота есть отдельная база контента. В ней хранятся не только сами материалы, но и их описания. Именно по этим описаниям система понимает, что и когда может снова появиться в разговоре.

Один из ключевых фрагментов выглядит так:

def load_content_index(path: str = CONTENT_JSON_PATH):
    global _content_loaded, content_index, content_embeddings
    if _content_loaded:
        return

    with open(path, "r", encoding="utf-8") as f:
        raw = json.load(f)

    content_index = raw.get("items", []) or []
    content_embeddings = [_extract_embedding(item) for item in content_index]
    _content_loaded = True

Что здесь важно:

• load_content_index(…)
Функция загружает контентную базу из content.json.

• global _content_loaded, content_index, content_embeddings
Здесь объявляются общие переменные, в которых потом живёт загруженный контент.

• if _content_loaded: return
Если база уже загружена, повторно читать файл не нужно.
Это экономит время и не делает лишнюю работу.

• json.load(f)
Читает JSON-файл целиком.

• content_index = raw.get(“items”, []) or []
Достаёт список материалов. То есть бот работает с отдельным индексом контента.
Если ключа items нет, подставляется пустой список.

• content_embeddings = [_extract_embedding(item) for item in content_index]
Для каждого элемента отдельно вытаскивается embedding.
То есть контент хранится не только как текст или ссылка, но и как вектор для смыслового поиска.

• _content_loaded = True
Пометка, что база уже в памяти.

Дальше проект может выбрать подходящий материал не случайно, а по смысловой близости к текущему разговору.

Ещё один важный узел:

picked = pick_relevant_content(query_text, top_k=CONTENT_TOP_K)
if picked:
    send_content_to_chat(chat_id, picked)

Что происходит здесь:

• pick_relevant_content(query_text, top_k=CONTENT_TOP_K)
Система получает текущий текст или тему разговора и ищет среди контента наиболее подходящие элементы.

• query_text
Это то, от чего идёт поиск: сообщение, тема или собранный контекст.

• top_k=CONTENT_TOP_K
Ограничивает количество кандидатов.
Бот не тащит всё подряд, а выбирает только верхние совпадения.

• if picked:
Если подходящий материал найден, бот идёт дальше.

• send_content_to_chat(chat_id, picked)
Отправляет найденный материал обратно в чат.

Именно здесь начинается рециркуляция.
Материал не лежит мёртвым архивом. Он может снова появиться в разговоре, если система понимает, что сейчас для него есть место.

То есть логика здесь такая:

  1. контент хранится отдельно
  2. для него есть embeddings
  3. бот умеет искать по смыслу
  4. найденный материал возвращается в чат
  5. старые вещи не исчезают, а получают новую точку входа

Поэтому этот проект для меня не просто бот.
Это система, в которой память работает не только на ответы, но и на возвращение материала в жизнь.

Как я сделал систему, которая не даёт контенту исчезать: иллюстрация 1Как я сделал систему, которая не даёт контенту исчезать: иллюстрация 2Как я сделал систему, которая не даёт контенту исчезать: иллюстрация 3Как я сделал систему, которая не даёт контенту исчезать: иллюстрация 4
Оглавление серии
  1. Как из идеи книги родилось пространство для памяти, разговора и рециркуляции
  2. Из чего на самом деле состоит этот проект
  3. Память, профиль и контекст: на чем держится бот
  4. По какой логике бот отвечает людям
  5. Как я сделал систему, которая не даёт контенту исчезать
  6. Как философия проекта вшита в код
  7. Почему этот проект живёт не только в тексте
  8. Как бот собирает и обновляет профили людей
  9. Как я защищаю проект от хаоса, дублей и случайности
  10. Почему я писал этот код не ради автоматизации