37.5 KB · updated 2026-07-06 · md

v0.2.0.ru.md

docs/i18n/release-notes/v0.2.0.ru.md

Tesserae v0.2.0 — типизированный поиск, граф кода, эволюция онтологии

<!-- translations:start -->

English · 한국어 · 中文 · 日本語 · Español · Français · Deutsch

<!-- translations:end -->

Выпущено 2026-05-21 · PyPI · GitHub release · pip install --upgrade tesserae

Tesserae 0.2.0 — это первый функциональный релиз поверх линейки v0.1.0, который приносит шесть аддитивных возможностей без ломающих изменений. Релиз продвигает поисковую поверхность Tesserae от «BM25 поверх типизированного графа» к гибридному ретриверу в стиле HippoRAG-2 с расширением затравок через Personalized PageRank (персонализированный PageRank), закладывает фундамент «код как граф», связывающий текстовые инсайты с исходными символами, и добавляет два прохода эволюции онтологии (сводки сообществ и затухание памяти) плюс отчёт о дрейфе схемы. Эти возможности отображаются на три точки рабочего процесса пользователя: лучший recall на этапе запроса (graph_ppr, гибридный search_nodes), более насыщенные узлы на этапе компиляции (ingest-code, сводки сообществ, decay/supersedes) и более быстрый цикл итераций над самой онтологией (schema-drift).

Содержание:

  1. MD0 — Personalized PageRank поверх типизированного графа
  2. Гибридный MD0 — BM25 + лексический + эмбеддинги через RRF
  3. MD0 — Python AST → типизированный граф кода
  4. Сводки сообществ — Louvain + LLM (опционально)
  5. Оценка затухания + MD0 + MD1
  6. MD0 — EDC-предложения для enum-ов
  7. Обновление с v0.1.0
  8. Стратегический контекст

1. graph_ppr — Personalized PageRank поверх типизированного графа

Что это

Новый MCP-инструмент, который запускает Personalized PageRank (PPR) с затравкой в одном или нескольких идентификаторах узлов и возвращает top-k наиболее релевантных узлов по массе стационарного распределения. Обход учитывает типы: рёбра взвешиваются по типу отношения, причём профиль по умолчанию повышает вес четырёх типов рёбер, несущих наибольший «реальный» сигнал в графе Tesserae — derived_from_session, discussed_in, references и supersedes. Это тот же примитив многошагового расширения затравок, который используется в HippoRAG 2, но адаптированный к типизированным рёбрам Tesserae, а не к графу со-встречаемости на уровне пассажей.

Конкретно, graph_ppr отвечает на вопрос «какова окрестность этого узла, взвешенная по отношениям, которые меня действительно интересуют?» способом, недоступным простому BFS или BM25. Затравка-Decision подтянет сессии, в которых она была принята, вопросы, на которые она отвечала, документы, которые она вытеснила, и концепции, обсуждавшиеся в этих документах — даже если ни один из этих узлов не содержит одинаковых ключевых слов.

Как использовать

Инструмент регистрируется автоматически при запуске MCP-сервера Tesserae. Из любого MCP-клиента:

// Затравка в одном узле, по умолчанию α=0.15, top-10 результатов
{
  "tool": "graph_ppr",
  "arguments": {
    "seed_node_id": "decision-2026-05-12-switch-to-hybrid-retrieval",
    "top_k": 10
  }
}

// Затравка в нескольких узлах («концептуальный кластер»), кастомные α + веса рёбер
{
  "tool": "graph_ppr",
  "arguments": {
    "seed_node_ids": ["concept-rrf", "concept-bm25", "concept-embedding-fusion"],
    "top_k": 25,
    "alpha": 0.2,
    "edge_type_weights": {
      "derived_from_session": 3.0,
      "discussed_in": 2.0,
      "references": 1.5,
      "supersedes": 1.5
    }
  }
}

Инструмент возвращает массив записей {node_id, score, kind, title}, упорядоченных по стационарной массе. Из сессии Claude Code просто попросите агента «use graph_ppr seeded at <node> with top-k 15», и навык using-tesserae сам направит вызов.

Когда использовать

Обращайтесь к graph_ppr, когда:

  • У вас есть один хорошо идентифицируемый узел (решение, статья, инсайт сессии), и вам нужна его окрестность в терминах графового расстояния, а не его «братья» по совпадению ключевых слов.
  • Вы хотите многошагового recall — например, «всё, что находится в двух-трёх отношениях от этой концепции, со смещением в сторону инсайтов, полученных из сессий».
  • Обычный search_nodes возвращает нужный узел, но его контекст, связанный через references, оказывается слишком узким.

Для свободного текстового запроса, начинающегося с фразы, предпочтительнее гибридный search_nodes (возможность 2); для получения текстового контекста известного узла предпочтительнее node_context.

Где находится

Основная реализация: MD0. Регистрация инструмента: tesserae/mcp_server.py.

Оговорки

  • Значения по умолчанию α=0.15 (вероятность перезапуска) и лимит в 50 итераций подобраны для графов в диапазоне 5k–50k узлов, типичных для проектной памяти. Очень крупным графам (>250k узлов) может потребоваться меньшее α и инициализация с учётом степени вершин; это запланировано на следующие итерации.
  • Веса рёбер применяются симметрично; асимметричный профиль (например, иной вес для references, чем для его обратного отношения) пока не вынесен наружу.
  • Реализация полностью на Python и не добавляет новых runtime-зависимостей; если у вас «горячий» цикл, вызывающий graph_ppr тысячи раз за сессию, рассмотрите кэширование стохастической по столбцам матрицы между вызовами.

2. Гибридный search_nodes — BM25 + лексический + эмбеддинги через RRF

Что это

Существующий MCP-инструмент search_nodes получил параметр mode и слитный ретривер под капотом. Новое значение по умолчанию, mode="hybrid", параллельно запускает три ретривера — BM25 (baseline из v0.1.0), лексический (пересечение токенов / подстрока) и эмбеддинговый (семантическая близость) — и сливает их через Reciprocal Rank Fusion (RRF(d) = Σ 1/(k + rank_i(d)), k=60 — константа из работы Cormack et al. 2009). Это тот же рецепт слияния, который применяется в локальном поиске Microsoft GraphRAG и в гибридном режиме LightRAG.

Параметр mode принимает значения:

РежимИспользуемые ретриверы
hybrid (по умолчанию)BM25 + лексический + эмбеддинги, слитые через RRF
lexicalТолько лексический
bm25Только BM25
embeddingТолько эмбеддинги
legacyТочное ранжирование v0.1.0 — сохранено бит в бит

Эмбеддинговый бэкенд автоопределяется в следующем порядке: если sentence-transformers импортируется, загружается sentence-transformers/all-MiniLM-L6-v2 (384 измерения, ~80 МБ, лицензия MIT, без сетевых вызовов после первого скачивания). Если нет — выполняется откат на детерминированную hash-bucket-проекцию: рабочую, без зависимостей и воспроизводимую, но с более слабым семантическим recall.

Новый сопутствующий MCP-инструмент embedding_status сообщает, какой бэкенд активен, чтобы вы могли подтвердить, выигрывают ли ваши гибридные оценки от реальных эмбеддингов или работают на hash-bucket-откате.

Как использовать

// Новое значение по умолчанию — слитный режим, возвращает top 10
{
  "tool": "search_nodes",
  "arguments": { "query": "RRF fusion constant choice", "top_k": 10 }
}

// Принудительно одиночный ретривер для ablation-исследования
{ "tool": "search_nodes", "arguments": { "query": "RRF fusion", "mode": "bm25" } }

// Откатиться к поведению v0.1.0 бит в бит
{ "tool": "search_nodes", "arguments": { "query": "RRF fusion", "mode": "legacy" } }

// Проверить, какой эмбеддинговый бэкенд активен
{ "tool": "embedding_status", "arguments": {} }

Чтобы получить реальный бэкенд sentence-transformers вместо hash-bucket-отката:

pip install 'sentence-transformers>=2.7'
# Первый вызов скачивает веса MiniLM (~80MB) в кэш HF; последующие вызовы офлайновые.

Какой режим когда использовать

  • hybrid — для всего и по умолчанию. RRF устойчив к ситуации, когда один из ретриверов возвращает мусор, потому что обратно-ранговое затухание ограничивает вклад любого отдельного ретривера.
  • bm25 — когда запрос по сути является тегом или структурным slug-ом (concept-rrf, decision-2026-05-12-…): доминирует точное совпадение, а эмбеддинги добавляют шум.
  • embedding — когда запрос является парафразом или вопросом, а подходящие узлы используют существенно другую лексику.
  • legacy — для ablation-исследований против baseline v0.1.0 или как запасной люк, если выявится единичная регрессия.

Где находится

Основная реализация: MD0.

Оговорки

  • Hash-bucket-откат воспроизводим, но имеет ограниченный семантический recall на парафразах — embedding_status делает выбор бэкенда видимым.
  • Текущая константа RRF зафиксирована на 60; сделать её конфигурируемой на каждый вызов — небольшая доработка, если вы захотите протестировать другие значения.
  • Кэширование эмбеддингов работает в пределах процесса; постоянное хранилище эмбеддингов (Lance/SQLite-vec) — кандидат на будущую v0.3.

3. tesserae project ingest-code — Python AST → типизированный граф кода

Что это

Новая CLI-подкоманда, которая обходит Python-репозиторий с помощью стандартного модуля ast и порождает пять типов узлов и пять типов рёбер:

УзлыРёбра
CODE_FILE, CODE_MODULE, CODE_CLASS, CODE_FUNCTION, CODE_METHODcontains, calls, imports, inherits_from, declared_in

Результат сохраняется в .tesserae/code-graph.json и подхватывается следующим tesserae project compile, благодаря чему символы кода становятся полноправными узлами графа, на которые можно ссылаться из прозы, искать через search_nodes, расширять через graph_ppr и визуализировать рядом с концепциями и статьями. Это закладывает основу для связывания решений с символами, которые их реализуют — ниша, которую сегодня не закрывает ни один другой PKM-AI-инструмент.

Как использовать

# Из активированного проекта Tesserae
tesserae project ingest-code

# Или для произвольного корня
tesserae project ingest-code --root ./my-package

# Затем обычная компиляция подхватит новый code-graph.json
tesserae project compile

После следующей компиляции узлы кода становятся доступны для поиска:

tesserae ask "Where is the RRF fusion implemented?"

…и агент может перейти от текстового узла Decision к CODE_FUNCTION, который его реализует, через рёбра references / declared_in.

Когда использовать

  • Вы хотите, чтобы решения и инсайты ссылались на реальные символы, которые они обсуждают, а не только на README, упоминающий эти символы.
  • Вы хотите код-осведомлённый поиск без настройки отдельного индекса поиска по коду — те же инструменты search_nodes + graph_ppr теперь покрывают и прозу, и код.
  • Вы используете интеграцию Understand-Anything, но хотите более лёгкий, без-зависимостный граф кода, живущий внутри основного графа Tesserae, а не в sidecar-JSON.

Где находится

Основная реализация: MD0.

Оговорки

  • В v0.2.0 поддерживается только Python. Экстрактор структурирован так, чтобы позже добавить обходчики для других языков; TypeScript / Rust / Go — в roadmap v0.3.
  • Рёбра calls разрешаются по поиску имени в области видимости того же модуля; межмодульное разрешение вызовов использует псевдонимы импортов, но не выполняет полного вывода типов. Ожидайте умеренной доли ложноположительных срабатываний на сильно перегруженных именах — для поиска приемлемо, для рефакторинга — нет.
  • Декораторы фиксируются в атрибутах декорируемого узла, но (пока) не порождают собственного типа рёбер.

4. Сводки сообществ — Louvain + LLM (опционально)

Что это

Опциональный пост-компиляционный проход, который запускает обнаружение сообществ методом Louvain на типизированном графе, а затем просит LLM составить однопараграфную сводку для каждого сообщества размером ≥ 4. Каждая сводка материализуется как узел COMMUNITY_SUMMARY, связанный со своими участниками рёбрами summarizes, и кэшируется по SHA списка id участников, так что повторная компиляция пересуммаризует только те сообщества, чей состав действительно изменился. Это тот же паттерн, который Microsoft GraphRAG использует, чтобы на этапе запроса всплывало «о чём этот кластер?».

Новый MCP-инструмент list_communities(min_size, limit) возвращает узлы сводок сообществ, упорядоченные по количеству участников, чтобы вы могли просматривать макроструктуру графа, не загружая его целиком.

Как использовать

Включите через переменную окружения, затем выполните компиляцию:

export TESSERAE_COMMUNITY_SUMMARIES=true
tesserae project compile

Затем запрашивайте полученные сводки:

{ "tool": "list_communities", "arguments": { "min_size": 5, "limit": 20 } }

Либо переходите от узла сводки сообщества по рёбрам summarizes обратно к его участникам через node_context.

Когда включать

  • У вас граф среднего или большого размера (как правило, >500 узлов), и вы хотите оглавление на уровне кластеров.
  • Вы хотите, чтобы написанные LLM метки кластеров прикреплялись к цветовым группам в графовом представлении статичного сайта.
  • Вы выпускаете периодические дайджесты (еженедельные / ежемесячные) и хотите раздел «макроструктура», обновляющийся только тогда, когда состав действительно изменился.

Если ваш граф мал (один README-проект + горсть документов), структурные узлы Synthesis уже это покрывают — сводки сообществ добавят шум, а не сигнал.

Где находится

Основная реализация: MD0.

Оговорки

  • Отключено по умолчанию — Louvain + LLM-суммаризация добавляют wall time, а стоимость LLM нетривиальна для графов с большим числом сообществ. Кэш амортизирует это между повторными компиляциями.
  • Состав сообществ недетерминирован между разными seed-ами Louvain; проход фиксирует seed для воспроизводимости в рамках одного проекта, но сравнивать id сообществ между проектами не имеет смысла.
  • Промпт для сводки общий; переопределения промпта на конкретный домен запланированы как доработка.

5. Оценка затухания + supersedes + fresh_insights

Что это

Два взаимодополняющих примитива, оба вдохновлённые моделью памяти с забыванием по Эббингаузу из A-MEM:

Оценка затухания присваивает каждому узлу-инсайту сессии (Insight / Decision / Question / TODO / Hypothesis / Takeaway) непрерывный decay_score ∈ (0, 1] по классической кривой забывания:

decay_score = exp(-ln(2) · age_days / half_life)

Период полураспада по умолчанию — 14 дней, а инкремент access_count (каждый раз, когда узел всплывает через ask или fresh_insights) дополнительно замедляет затухание. Метки времени структурных решений выводятся из родительской сессии, чтобы постфактум-инсайты получали разумный возраст.

Проход supersedes — это опциональный пост-компиляционный шаг, который находит почти-дубликаты инсайтов сессий через меру Jaccard на шинглах заголовка + содержимого, а затем просит LLM рассудить, действительно ли новый узел вытесняет старый. Подтверждённая пара получает ребро supersedes, а эффективный decay_score старого узла подавляется.

Новый MCP-инструмент fresh_insights(limit, kind) возвращает топ инсайтов по текущему decay_score, исключая вытесненные узлы. Это канонический запрос «что агенту следует приоритизировать из прошлых сессий?».

Как использовать

Оценка затухания выполняется автоматически при каждой компиляции. Чтобы включить проход supersedes:

export TESSERAE_SUPERSEDE_PASS=true
tesserae project compile

Затем запрашивайте самые свежие невытесненные инсайты:

{
  "tool": "fresh_insights",
  "arguments": { "limit": 15, "kind": "Decision" }
}

Либо опустите kind, чтобы получить смешанную ленту по всем типам инсайтов сессий.

Когда включать проход supersedes

  • Вы еженедельно накапливаете сессии, и ваши запросы по Decision / Hypothesis начинают возвращать противоречивые устаревшие записи.
  • Вы хотите, чтобы поток recall у агента в using-tesserae смещался в сторону «это текущая точка зрения на X», а не «всё, что мы когда-либо думали про X».
  • Стоимость приемлема: каждая компиляция оплачивает один Jaccard-проход (дёшево) плюс N LLM-судейских вызовов на пары-кандидаты выше порога Jaccard (с кэшем по хэшу содержимого).

Если у вас всего несколько недель сессий, обычно достаточно одного затухания — ребро supersedes — это оптимизация для более старых и плотных графов.

Где находится

  • Оценка затухания: MD0
  • Проход supersedes: MD0

Оговорки

  • Период полураспада в 14 дней — разумное значение по умолчанию для активных исследовательских проектов; для долгосрочных архивных графов уместны 60–90 дней. Таблица периодов полураспада по типам — запланированная фича v0.3.
  • Генерация кандидатов Jaccard использует фиксированный размер шингла 5; очень короткие инсайты (одно-предложение Takeaways) могут недостаточно кластеризоваться.
  • LLM-судья для supersedes намеренно консервативен — ложноотрицательные срабатывания (пропущенные дубликаты) перевешивают ложноположительные (некорректные рёбра supersedes).

6. tesserae project schema-drift — EDC-предложения для enum-ов

Что это

Новая CLI-подкоманда, помогающая онтологии эволюционировать вместе с корпусом. Она реализует паттерн EDC (Extract-Define-Canonicalize, EMNLP'24): для каждого узла-типа с большим объёмом она кластеризует участников по Jaccard на основе шинглов заголовка+содержимого, затем просит LLM предложить подтипы в PascalCase с кратким обоснованием и тремя репрезентативными превью участников на кластер. Вывод записывается в .tesserae/schema-drift.md как чек-лист готовых к копированию дополнений к enum-ам для файлов онтологии в ontology/.

LLM-предложения кэшируются атомарно (write-temp-then-rename) с ключом по SHA id-ов участников кластера, так что повторный запуск прохода дёшев и сходится к одним и тем же предложениям, пока корпус не изменился.

Как использовать

tesserae project schema-drift
# → пишет .tesserae/schema-drift.md

Затем откройте отчёт, просмотрите предложенные enum-ы (каждый блок — готовый к копированию литерал Python) и вставьте принятые в соответствующий файл в ontology/. Следующий tesserae project compile выполнит валидацию по обновлённой схеме.

Когда использовать

  • После большой партии новых документов / сессий, прежде чем повысить новое значение типа узла до полноправного enum-а.
  • Периодически (ежемесячно) на долгосрочных проектах, чтобы выявлять дрейф онтологии — отчёт быстрый и доступен только для чтения.
  • Как артефакт для передачи: markdown самодостаточен, так что его можно отдать рецензенту (или другому агенту) без поднятия полного Tesserae CLI.

Где находится

Основная реализация: MD0.

Оговорки

  • Предложения являются рекомендациями — человек (или агент далее по конвейеру) всё равно решает, какие кластеры станут реальными значениями enum-а. Проход намеренно не модифицирует ontology/ самостоятельно.
  • Кластеризация Jaccard использует то же предположение о размере шингла, что и проход supersedes; очень короткие участники могут кластеризоваться менее чётко.
  • Проход сосредоточен на типах с большим объёмом; редкие типы (≤ 3 участников) пропускаются, чтобы не плодить умозрительные enum-ы.

Обновление с v0.1.0

pip install --upgrade tesserae

Это всё, что нужно для обновления — v0.2.0 является аддитивным и без ломающих изменений. Несколько опциональных «крутилок» стоит держать в голове:

Переменные окружения для опциональных проходов:

# Включить пост-компиляционный проход сводок сообществ (возможность 4)
export TESSERAE_COMMUNITY_SUMMARIES=true

# Включить проход supersedes по почти-дубликатам (возможность 5)
export TESSERAE_SUPERSEDE_PASS=true

Одно изменение поверхности MCP, о котором стоит знать: search_nodes теперь по умолчанию использует mode="hybrid". Если у вас есть автоматизация, зависевшая от точного ранжирования v0.1.0, передавайте mode="legacy" — legacy-путь сохранён бит в бит.

Новая опциональная Python-зависимость для реального бэкенда эмбеддингов:

pip install 'sentence-transformers>=2.7'

Если вы её пропустите, search_nodes mode="hybrid" всё равно работает (hash-bucket-откат); embedding_status сообщит hash-bucket вместо minilm-l6-v2, так что выбор будет наблюдаемым.

Новые CLI-подкоманды, которые стоит добавить в мышечную память:

tesserae project ingest-code      # породить узлы кода (возможность 3)
tesserae project schema-drift     # предложить enum-ы онтологии (возможность 6)

Новые MCP-инструменты, теперь доступные агенту:

  • graph_ppr (возможность 1)
  • embedding_status (возможность 2)
  • list_communities (возможность 4)
  • fresh_insights (возможность 5)

Всё остальное — slash-команды, хуки, ask, проекция wiki / Obsidian — без изменений.


Стратегический контекст

v0.2.0 структурно приводит Tesserae в соответствие с состоянием искусства GraphRAG / агентской памяти 2026 года:

  • Гибридный поиск (BM25 + лексический + эмбеддинги через RRF) — это тот же рецепт слияния, который использует локальный поиск Microsoft GraphRAG и гибридный режим LightRAG.
  • Расширение затравок Personalized PageRank — это многошаговый примитив, лежащий в основе HippoRAG 2, здесь адаптированный к типизированным рёбрам, а не к со-встречаемости пассажей.
  • Сводки сообществ зеркалят уровень сводок кластеров Microsoft GraphRAG — слой, который даёт быстрый структурный ответ на запросы «о чём этот корпус в общих чертах?».
  • Оценка затухания + supersedes — это модель Эббингауза A-MEM, применённая к проектной памяти; проход supersedes по духу ближе к операциям памяти «ADD / UPDATE / DELETE» из Mem0, но выражен как чистое ребро, а не как переписывание на месте.
  • Schema-drift через EDC — это та же идея Extract-Define-Canonicalize из EMNLP'24, применённая к эволюции онтологии, а не к извлечению отношений.

Что остаётся специфичным для Tesserae и защитимой нишей: типизированные рёбра повсюду, инсайты сессий как полноправные узлы графа и (теперь) символы кода внутри того же графа. Большинство конкурентов в ландшафте 2026 года вообще не имеют типизированных рёбер; среди тех, у кого они есть, никто не связывает текстовые решения с символами кода — фундамент feat/code-graph, заложенный в v0.2.0, — это точка, в которой эта ниша начинает накапливать преимущество.

См. также: