История о том, как превратить ИИ-агента из «золотой рыбки» с памятью в 128к токенов в полноценного цифрового сотрудника с долгосрочным хранилищем знаний.

Зачем боту память, если есть контекст?

Современные LLM обладают огромными контекстными окнами (у Claude 4.6 это 1М токенов), но это все еще «оперативка». Как только сессия заканчивается или проект перерастает масштаб одного файла, бот начинает «забывать» важные архитектурные решения, предпочтения автора и факты из прочитанных ранее статей.

Мы с моим агентом Полифемом (работающим на базе фреймворка OpenClaw) решили пойти дальше обычного RAG и построить Graph-RAG на стероидах, используя возможности AlloyDB Omni и концепцию SPO (Subject-Predicate-Object).

==AlloyDB Omni — PostgreSQL сервер, переписанный Google, в котором встроены функции обращения к LLM, векторизации строк. Умеет строить и динамически дообучать высокоскоростные индексы кластеризации эмбеддингов на алгоритмах приблизительных ближайших соседей.==

Обычный RAG режет текст на куски (чанки) и ищет похожие. Это дешево, но часто ведет к потере связей. Наш подход в рамках концепции SDD (Skill-Driven Development) был иным:

  1. Сущности (Entities): Хранятся отдельно на английском языке (чтобы избежать проблем с падежами). Каждая сущность имеет свой векторный отпечаток.

  2. Утверждения (Statements): Бот не просто сохраняет абзац, он формулирует атомарный факт. Например: [Claude 4.6] -> [has] -> [1M context window].

  3. Гибридный поиск: AlloyDB Omni позволяет нам одновременно использовать векторный поиск (pgvector) для поиска по смыслу и классический полнотекстовый поиск для точности.

Реализация за 30 минут

Шаг 1: "Zero Trust" Инфраструктура

Первым делом мы создали изолированный проект OmniMemory. Бот сам подготовил .env с ключами доступа к моему удаленному серверу AlloyDB в облаке и Vertex AI для генерации эмбеддин��ов. Несмотря на то, что сервер довольно скромный (всего 8 ГБ RAM), AlloyDB Omni прекрасно справляется с нашими задачами семантического поиска.
Бот написал себе инструкцию по разработке:

# Omni-Memory Project

Semantic Graph-RAG system for AI agents, built on AlloyDB Omni.

## Project Structure
- `schemas.py`: Pydantic models for SPO (Subject-Predicate-Object) logic.
- `init_db.sql`: SQL schema with `pgvector`, `pg_trgm`, and `ivfflat` indexes.
- `db_setup.py`: Database initialization script.
- `.env`: (Ignored in Git) Environment configuration.

## Setup
1. Ensure the AlloyDB Omni cluster is running.
2. Run `db_setup.py` to create the `omny_brain` database and apply the schema.

Шаг 2: Schema-First

Мы обговорили Pydantic-модели, которые стали контрактом между логикой бота и базами данных.

  • Таблица entitiesсодержит уникальные узлы графа.

  • Таблица facts: связи между узлами, сформулированный факт и оригинальный контекст (на случай, если захочется проверить первоисточник). Бот сделал себе схему:

from pydantic import BaseModel, Field
from typing import Optional, Dict, Any, List
from uuid import UUID, uuid4
from datetime import datetime

class EntitySchema(BaseModel):
    """
    Represents a unique concept or object in English.
    """
    id: UUID = Field(default_factory=uuid4)
    name: str = Field(description="Unique name in English (e.g., 'Claude 4.6')")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="Type, description, etc.")

class FactSchema(BaseModel):
    """
    Represents a structured statement connecting entities.
    """
    id: UUID = Field(default_factory=uuid4)
    subject_id: UUID = Field(description="Reference to the Subject entity")
    predicate: str = Field(description="Relationship (e.g., 'uses', 'outperforms')")
    object_id: UUID = Field(description="Reference to the Object entity")
    content: str = Field(description="The formulated fact statement in Russian or English")
    context: str = Field(description="Original snippet for detailed nuance")
    source_url: Optional[str] = Field(None, description="Source URL")
    metadata: Dict[str, Any] = Field(default_factory=dict)
    created_at: datetime = Field(default_factory=datetime.utcnow)

class FactCreateRequest(BaseModel):
    """
    Helper schema for the agent to prepare data for storage.
    """
    subject_name_en: str
    predicate: str
    object_name_en: str
    fact_text: str
    original_context: str
    source: str

Шаг 3: SQL реализация

Бот написал SQL-скрипт инициализации базы omni_brain с применением схемы данных. Мы использовали расширения:

  • pgvector: для семантической кластеризации сущностей.

  • pg_trgm: для поиска по похожим названиям (если я опечатаюсь в вопросе).

  • ivfflat: для мгновенного поиска среди миллионов фактов.

-- SQL Initialization for Omny-Memory (AlloyDB Omni)

-- Enable extensions

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
 
-- Entities Table (Canonical English names)
CREATE TABLE IF NOT EXISTS entities (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name TEXT UNIQUE NOT NULL,
    embedding VECTOR(768),
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Index for entity name similarity
CREATE INDEX IF NOT EXISTS idx_entities_name_trgm ON entities USING gin (name gin_trgm_ops);

-- Vector index for entity clustering
CREATE INDEX IF NOT EXISTS idx_entities_embedding ON entities USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

-- Facts Table (SPO structure + Content)
CREATE TABLE IF NOT EXISTS facts (

    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    subject_id UUID REFERENCES entities(id),
    predicate TEXT NOT NULL,
    object_id UUID REFERENCES entities(id),
    content TEXT NOT NULL,
    context TEXT NOT NULL,
    embedding VECTOR(768),
    source_url TEXT,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Full-text search index for facts
CREATE INDEX IF NOT EXISTS idx_facts_content_fts ON facts USING gin (to_tsvector('english', content));
-- Vector index for semantic RAG
CREATE INDEX IF NOT EXISTS idx_facts_embedding ON facts USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

Затем он написал всю Python-обвязку, запустил скрипты и создал в базе нужные функции записи и извлечения. Весь код на гитхабе

Первые тесты

Мы скормили боту статью про новую модель Claude 4.6. Полифем сам:

  1. Выделил ключевые сущности.

  2. Перевел их на английский для нормализации.

  3. Сгенерировал векторы через text-embedding-005.

  4. Сохранил всё в облачной базе.

Когда я спросил: «Что там с контекстом у новой модели Клод?», бот нашел семантически близкие сущности и выдал структурированный ответ из базы с точностью совпадения 0.83.

Итог

За полчаса мы перевели модель «вопрос-ответ» к модели «накопление-анализ». Теперь мой бот — это развивающаяся база знаний, которая помнит всё: от параметров новых моделей до архитектурных особенностей удаленного облака.

Что дальше? Теперь мы планируем научить бота строить визуальные графы связей прямо в Obsidian, чтобы я мог буквально «видеть», как связаны технологии в его голове.


Статья подготовлена в соавторстве с агентом Полифемом в рамках проекта OpenClaw. Он накидывает драфт по своим логам, я пишу читаемый текст.

Дневник Полифема можно читать в канале t.me/veriga_pro_AI

Комментарии (13)


  1. constXife
    13.02.2026 09:51

    Тоже к такой схеме пришел, правда я использую https://memgraph.com/.


    1. veriga Автор
      13.02.2026 09:51

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


  1. sickfar
    13.02.2026 09:51

    А какова схема взаимодействия с ботом? MCP? Shell скрипты? Как именно он ходит в эту базу?


    1. veriga Автор
      13.02.2026 09:51

      Бот написал себе скилл, в котором прописана строка подключения к AlloyDB, скрипт на Python и инструкция по запуску в markdown. Когда я ему говорю что-то типа "занеси ключевые факты из такой-то статьи в omni-memory", он другим скиллом читает статью, выделяет там то, что посчитал интересным и отправляет в этот скилл, в котором абзац разбивается на subject->predicat->object и уже в виде json отправляется в базу.

      Чтение статьи и выявление фактов не отлажено и пока больше похоже на аттракцион, потому что факты из статьи он выбирает довольно своеобразно. Но это всё допиливается. Сам скилл, если ему передать конкретный факт, отрабатывает хорошо.


      1. sickfar
        13.02.2026 09:51

        А во внутренности скилла вы не заглядывали? Что там конкретно? Sh? Js?

        Upd. Затупил, простите. У вас же питон обвязка в репозитории, она и вызывается скилом.


  1. Per_Ardua
    13.02.2026 09:51

    Выглядит очень здорово. А может на github это всё вместе со скиллом оформить? Сразу готовый вариант и можно на clawhub выложить.


    1. veriga Автор
      13.02.2026 09:51

      В скилле сидят строки подключения к SQL, и он подключается к уже созданной базе, так что выложить в таком виде я его не могу. А на github лежит весь проект со скриптами создания базы, правда, для AlloyDB Omni. это PostgreSQL от Гугла. Он opensource, я его на слабую виртуалку поставил в докере, его можно локально ставить себе на linux


      1. Per_Ardua
        13.02.2026 09:51

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

        Или я что-то не так понял? Я могу и ошибаться)


        1. veriga Автор
          13.02.2026 09:51

          Все правильно, на гитхабе есть скрипт на SQL для создания базы. Но я не пробовал его на стандартном postgres, а в AlloyDB уже встроены нужные расширения, там есть индексы для поиска приблизительным ближайшим соседям, которых не будет в postgres. AlloyDB Omni опенсорс, ставится на локальную машину, никаких проблем с ним нет, но его надо сначала ставить. А в скилл добавлять установку СУБД так себе идея)


  1. ENick
    13.02.2026 09:51

    "семантически близкие сущности и выдал структурированный ответ из базы с точностью совпадения 0.83. " если это не косинус, то поясните как определили эту цифирку?


    1. veriga Автор
      13.02.2026 09:51

      почему не косинус, это косинус. косинусное расстояние вычисляется по формуле (1-\cos(\Theta). Значок `<=>` -- это косинусное расстояние -- чем меньше угол, тем больше расстояние между точками в семантическом пространстве, тем они меньше похожи.
      Там в скриптах на гитхабе прописано (1 - (f.embedding <=> query_embedding)), это более привычный подход: чем больше число, тем больше сходство. Поэтому 0.84 -- это большое сходство.


      1. veriga Автор
        13.02.2026 09:51

        Ой, только заметил, у меня опечатка: " чем меньше угол, тем больше расстояние между точками в семантическом пространстве". Правильно будет , чем меньше значение косинуса, тем больше косинусное расстояние, тем меньше они похожи.


  1. FSmile
    13.02.2026 09:51

    Что-то долго. Я за 25 справился