hybrid-rag-memory
English | 日本語
Hybrid RAG — система долговременной памяти агента
Гибридная RAG-система, сочетающая плотный и разреженный поиск, с механизмом памяти на основе тегов (важность, скорость устаревания для каждого knowledge_type и частота доступа), встроенным в её реранкинг. Обоснование дизайна см. в hybrid_rag_agent_spec.en.md.
Запускается как MCP-сервер, и агенты, такие как Claude Code, могут использовать его напрямую как «долговременную память».
Как работает этот механизм
Согласно спецификации, обработка разделена на два вида.
Класс | Содержание | Реализация |
① Зависящий от модели (рассуждение) | Присвоение важности, расширение запроса / оценка достаточности, оркестрация | Сторона агента (суждение LLM) |
② Зависящий от структуры (детерминированная обработка) | Разбиение на чанки, генерация эмбеддингов, гибридный поиск, ступенчатый реранкинг, забывание/архивирование | Сторона RAG (эта библиотека / MCP-сервер) |
«Важность» и «скорость устаревания для каждого knowledge_type» рассматриваются как отдельные оси; вместо простой линейной комбинации они применяются поэтапно: ① отсечение по важности → ② временное затухание по knowledge_type → ③ усиление по частоте доступа (подробности см. в разделе 2.3 спецификации).
principle : no decay (MBSE design principles, math/algorithms)
paper : re-evaluated roughly every half year (papers, technical articles)
news : decays significantly over weeks to months (news, model-release info)
experiment : decays according to project duration (experiment logs, run records)knowledge_type задуман так, чтобы определяться детерминированно из источника приёма данных, а не оцениваться LLM по содержимому чанка (например, проектный документ, явно зарегистрированный человеком → principle; статья arXiv/техническая статья → paper; новости/результаты веб-поиска → news; журнал выполнения → experiment).
Примечание:
principle(без затухания) не гарантирует, что чанк «никогда не будет забытrun_forgetting_batch». Поскольку ступенчатый реранкинг сначала применяет отсечение ① по важности, чанк сknowledge_type=principleвсё равно может стать целью архивирования, если егоimportanceустановлена низко и опускается нижеimportance_threshold(подтверждено вtests/test_archival.py). «Без затухания» относится только к этапу ② временного затухания — это не гарантия «никогда не будет забыт» для всего конвейера ①②③.
Примечание: Механизм памяти (knowledge_type/importance/ступенчатый реранкинг/пакетное забывание/MCP-сервер) реализован только для бэкенда FAISS (
HybridRAGSystem). Версии для Qdrant/Chroma/PostgreSQL доступны только как обычная библиотека гибридного поиска.
Related MCP server: mnemostack
Установка
pip install -r requirements.txtДля разработки/тестирования:
pip install -r requirements-dev.txtИспользование ① В качестве MCP-сервера (рекомендуется)
Запуск сервера
python mcp_server/server.pyМеста хранения можно задать через переменные окружения (по умолчанию: hybrid_rag.db / indices).
HYBRID_RAG_DB_PATH=my_memory.db HYBRID_RAG_INDEX_PATH=my_indices python mcp_server/server.pyРегистрация в Claude Code
.mcp.json в корне проекта уже настроен следующим образом. Claude Code подхватывает его автоматически при открытии этого репозитория.
{
"mcpServers": {
"hybrid-rag-memory": {
"type": "stdio",
"command": "python",
"args": ["mcp_server/server.py"],
"env": {
"HYBRID_RAG_DB_PATH": "hybrid_rag.db",
"HYBRID_RAG_INDEX_PATH": "indices"
}
}
}
}Если вы используете виртуальное окружение, перепишите command на абсолютный путь к интерпретатору Python внутри вашего venv (например, "command": "./.venv/Scripts/python.exe").
Предоставляемые инструменты
В дополнение к минимальным 3 инструментам (①–③), предусмотренным в разделе 5 спецификации, этот сервер предоставляет ещё 10 инструментов (④–⑬, расширения спецификации) для приёма данных, тегирования, предотвращения дубликатов, пакетного забывания и проверки работоспособности.
# | Инструмент | Описание |
① |
| Векторизует текст фиксированной моделью эмбеддингов (детерминированная обработка) |
② |
| Гибридный поиск вектор+BM25. Возвращает чанки, уже прошедшие реранкинг по релевантности (Cross-encoder). При |
③ |
| Ступенчатый реранкинг: отсечение по важности → временное затухание по |
④ |
| Принимает документы. |
⑤ |
| Назначает теги важности / переназначает |
⑥ |
| Поиск по тегу с точным совпадением (в обход семантического поиска). Используется для проверки, был ли уже принят документ из того же источника [расширение спецификации] |
⑦ |
| Извлекает соседние чанки в пределах того же документа (прямое обращение в обход семантического поиска). Компенсирует потерю контекста на границах чанков [расширение спецификации] |
⑧ |
| Удаляет документ и все его чанки. Используется в процессе «замены» при повторном приёме [расширение спецификации] |
⑨ |
| Лёгкое обновление индекса, инкрементально включающее только чанки, добавленные с момента последнего обновления индекса [расширение спецификации, добавлено 2026-07-30] |
⑩ |
| Выполняет полную пересборку индексов FAISS/BM25 из всех чанков в БД. Требуется после удалений (⑧ или |
⑪ |
| Пакетное задание забывания/архивирования. Предназначено только для нечастого выполнения [расширение спецификации] |
⑫ |
| Проверяет согласованность между индексом и БД и сообщает о ней (без изменений). Обнаруживает «в индексе, но не в БД» мусор (из-за забытого |
⑬ |
| Сообщает о покрытии тегированием механизма памяти в БД (без изменений). Если |
Без ④–⑬ одни только инструменты ①–③ не могут ни принимать данные, ни финализировать теги важности, ни избегать дублирующей регистрации из одного источника — что делает систему непрактичной, поэтому они и были добавлены.
Замечание о приёме множества файлов подряд (важно)
Предыстория (проблема, исправленная 2026-07-30): раньше ingest по умолчанию выполнял «пере-эмбеддинг каждого чанка в БД и пересборку индекса при каждом вызове», поэтому стоимость одного вызова росла линейно с размером корпуса, а пакетная загрузка файлов по одному приводила к тайм-аутам. Теперь ingest(rebuild_index=True) (по умолчанию) внутри вызывает update_index() — инкрементальный подход, который эмбеддит только новые добавленные чанки с момента последнего обновления и добавляет их (.add()) в индекс FAISS — поэтому теперь он быстр независимо от общего размера корпуса (сторона BM25 по-прежнему выполняет лёгкую полную пересборку каждый раз, потому что её статистика IDF зависит от всего корпуса, но это дёшево, так как не требует нейронного эмбеддинга).
Тем не менее, выполнение инкрементального обновления для каждого отдельного файла — всё ещё лишние накладные расходы, поэтому при пакетной загрузке множества файлов подряд лучше передавать rebuild_index=False в каждый вызов ingest и вызывать update_index() один раз в конце пакета, чтобы согласовать всё разом. .claude/agents/doc-to-memory.md и .claude/agents/session-to-memory.md уже реализованы с этим паттерном. Проверка БД через find_by_tag (для предотвращения дубликатов / проверки прогресса) обращается напрямую к SQLite, поэтому работает без ожидания, пока индекс догонит.
Когда требуется полный rebuild_index(): когда в пакете есть хотя бы один вызов delete_document или проход архивации из run_forgetting_batch (т.е. любое удаление векторов). Инкрементальное добавление (update_index) поддерживает только добавление в FAISS, но не удаление из него, поэтому любой пакет, содержащий удаления, должен заканчиваться полным rebuild_index(). Пакет, состоящий только из новых добавлений, вполне обходится update_index().
Предотвращение дубликатов при повторной регистрации одного и того же источника
Поскольку ingest вычисляет doc_id как хэш содержимого файла, повторная загрузка байт-идентичного содержимого автоматически пропускается (дифф-обновление). Однако в случаях, когда один и тот же источник (например, одна и та же сессия) каждый раз заново резюмируется LLM и загружается заново, небольшие вариации в тексте резюме каждый раз приводят к тому, что он рассматривается как другой документ — создавая дубликаты.
Чтобы этого избежать, загружайте с уникальным идентификационным тегом (например, session_id:xxx) и тегом обновления (например, session_last_activity:2026-07-28T15:59:49Z), а при последующих запусках:
Проверьте, существует ли документ, через
find_by_tag("session_id:xxx")Если существующий тег обновления совпадает с текущим значением, пропустите — ничего не делайте
Только если он отличается (источник изменился), удалите старый с помощью
delete_document(doc_id, rebuild_index=False)передingest-ом нового содержимого
Рекомендуется реализовать этот паттерн «пропустить, если не изменилось, заменить, если изменилось». .claude/agents/session-to-memory.md — эталонная реализация этого паттерна.
Пример использования (концептуально)
1. ingest(["design_doc.md"], metadata={"knowledge_type": "principle", "tags": ["mbse"]})
2. hybrid_search("about consistency between requirements and architecture", top_k=5)
-> [{"doc_id": ..., "chunk_index": ..., "content": ..., "knowledge_type": "principle",
"importance": null, "access_count": 0, "score": 0.87}, ...]
3. set_chunk_tags(doc_id, chunk_index, importance=0.9)
4. rerank(chunks, time_weight=0.5, freq_weight=0.1, importance_threshold=0.3)
-> chunks reordered along the memory axis (staleness, frequency, importance)Использование ② В качестве агента Claude Code
.claude/agents/rag-memory.md содержит определение субагента, отвечающего за «сторону агента (класс ①)» этого механизма памяти. После регистрации .mcp.json вы можете вызывать его из Claude Code так:
Use the rag-memory agent to look into past design decisionsПравила работы для действий, требующих подтверждения намерения человека — простановка важности, пере-тегирование knowledge_type, решение о запуске пакета забывания — также записаны в это определение агента.
Кроме того, .claude/agents/session-to-memory.md — это специализированный агент, который резюмирует прошлые сессии Claude Code (транскрипты чатов) и загружает их в долговременную память как knowledge_type="experiment". Он работает на модели Haiku для снижения затрат, а при повторной обработке той же сессии сравнивает с существующей записью через теги session_id/updated-at — пропуская, если не изменилось, заменяя, если изменилось (см. предыдущий раздел). Вызывающий должен явно указать, какие сессии обрабатывать; он никогда не обрабатывает все сессии без ограничений.
Использование ③ Напрямую как Python-библиотека
Вы также можете вызывать его напрямую из Python-кода, не проходя через MCP-сервер.
from hybrid_rag import HybridRAGSystem
rag = HybridRAGSystem(db_path="hybrid_rag.db", index_path="indices")
rag.ingest_documents(
["design_doc.md"],
metadata={"knowledge_type": "principle", "importance": 0.9, "tags": ["mbse"]},
)
result = rag.query(
"about consistency between requirements and architecture",
top_k=5,
enable_memory_rerank=True, # enable the memory mechanism's staged reranking
memory_time_weight=0.5,
memory_freq_weight=0.1,
memory_importance_threshold=0.3,
)
print(result["context"])
# assign an importance tag after the fact (no vector rebuild needed)
rag.set_chunk_tags(doc_id="design_doc_xxxx", chunk_index=0, importance=0.9)
# forgetting/archival batch (normally run infrequently)
report = rag.run_forgetting_batch(score_threshold=0.05, dry_run=True)Запуск пакета забывания из CLI
Скрипт, предназначенный для редкого пакетного выполнения — например, с циклом в 3 месяца или при выходе новой модели (он никогда не запускается автоматически внутри сервера).
python scripts/run_forgetting_batch.py --dry-run
python scripts/run_forgetting_batch.py --score-threshold 0.1 --time-weight 0.8Основные опции: --db-path --index-path --archive-path --time-weight --freq-weight --importance-threshold --score-threshold --dry-run
Архивированные чанки эвакуируются в archive/chunks_archive.jsonl (сырой текст + метаданные + оценка + причина удаления + временная метка удаления), а их векторные представления отбрасываются.
Автоматическая оценка точности поиска из CLI
Скрипт, который измеряет точность поиска по золотому набору запросов (Precision@k/Recall@k/MRR/NDCG@k/Hit Rate@k, ранг авторитетного документа, уровень шума) воспроизводимым образом, вместо ручных запросов и визуальной оценки результатов через Cursor/Claude Code.
cp eval/golden_queries.example.yaml eval/golden_queries.yaml # once, at first use — rewrite the doc_ids for your own corpus
python scripts/run_evaluation.py --db-path mcp_server/hybrid_rag.db --index-path mcp_server/hybrid_rag_indicesОсновные опции: --db-path --index-path --golden-set (по умолчанию eval/golden_queries.yaml) --k-values (по умолчанию 1,3,5,10) --authority-window (по умолчанию 20) --output
Аудит почти дублирующихся загрузок
Детекция дубликатов в ingest не может поймать случаи, когда идентичное содержимое попадает через другой файл (другой путь/имя файла — см. «Предотвращение дубликатов при повторной регистрации одного и того же источника» выше). Этот скрипт просто перечисляет почти дубликаты, которые уже попали в существующий корпус. Он никогда ничего не удаляет.
python scripts/find_near_duplicates.py --db-path mcp_server/hybrid_rag.db
python scripts/find_near_duplicates.py --db-path mcp_server/hybrid_rag.db --output eval/duplicates_report.jsonОн группирует документы, у которых совпадает хэш нормализованного содержимого (documents.content_hash). Решение о том, какой оставить — и удалять ли что-либо — остаётся за пользователем; вызовите delete_document(doc_id, rebuild_index=False) вручную (и обязательно вызовите rebuild_index в конце пакета).
eval/golden_queries.yaml находится в .gitignore, так как это личные данные, содержащие doc_id, специфичные для вашего реального корпуса. Отчёты записываются в eval/eval_report_<date>.md (плюс одноимённый .json), которые также в .gitignore (они остаются на вашей машине для постоянного отслеживания).
Поля механизма памяти
Поля, переносимые в metadata в ingest/Python API, или на каждый чанк:
Поле | Тип | Описание |
|
|
|
|
| Важность, назначаемая агентом постфактум. Если не задано ( |
|
| Произвольные теги. Используются для сужения результатов через аргумент |
|
| Частота обращений. Автоматически увеличивается каждый раз, когда чанк реально возвращается запросом |
|
| Временные метки последнего обращения / создания. Служат основой для временного затухания |
Тесты
pytest tests/ -vtest_metadata_pipeline.py: регрессионный тест, чтоknowledge_type/importance/tagsпереживают конвейер ingest → build_index → querytest_memory_scoring.py: модульные тесты для многоэтапного реранжирования (отсечение, затухание, частотный буст)test_archival.py: модульные тесты для пакета забывания/архивацииtest_index_health.py: модульные тесты дляindex_health(проверка согласованности индекса/БД)
Полный список и роль остальных тестовых файлов см. в File layout.
Функциональность базовой библиотеки (общая для всех бэкендов)
Базовая RAG-функциональность — гибридный поиск по плотным/разреженным векторам, RRF, реранжирование Cross-encoder, MMR-разнообразие, расширение запросов, кэширование и т.д. — общая для всех бэкендов (FAISS/Qdrant/Chroma/PostgreSQL).
from hybrid_rag import create_rag_system
rag = create_rag_system(backend="faiss") # "qdrant" / "chroma" / "postgres" are also available
rag.ingest_documents(["document1.pdf", "document2.md"])
result = rag.query("What is machine learning?", top_k=5)Аспект | FAISS | Qdrant | ChromaDB | PostgreSQL |
Фильтрованный поиск | пост-обработка | быстрый (один этап) | пост-обработка | пост-обработка |
Требуется сервер | нет | нет | нет | да |
Масштаб | до ~20M | до ~50M | средний | крупномасштабный |
Механизм памяти (этот README) | ✓ | ✗ | ✗ | ✗ |
Опциональные установки: в этом репозитории нет pyproject.toml/setup.py, поэтому он не распространяется в форме pip install hybrid-rag[...]. Для использования версий Qdrant/Chroma/PostgreSQL установите соответствующий клиентский пакет напрямую (pip install qdrant-client / pip install chromadb / pip install "psycopg[binary]" pgvector — все они уже перечислены в requirements.txt, так что одного pip install -r requirements.txt достаточно).
Ключевые дополнительные настройки (подмножество аргументов конструктора HybridRAGSystem версии FAISS):
rag = HybridRAGSystem(
dense_model="paraphrase-multilingual-MiniLM-L12-v2",
rerank_model="BAAI/bge-reranker-v2-m3",
max_chunk_size=512,
index_type="hnsw", # "flat" / "ivf" / "hnsw"
enable_mmr=True, mmr_lambda=0.6,
enable_cache=True, cache_ttl_seconds=3600,
query_expander=None, # pass a QueryExpander instance for LLM-based query expansion
memory_half_life_overrides=None, # override the half-life (days) per knowledge_type
enable_guaranteed_candidates=True, # always add principle/high-importance chunks to the candidate pool (default True)
guaranteed_knowledge_types=None, # defaults to ["principle"]
guaranteed_importance_threshold=0.7,
guaranteed_candidates_limit=50,
)enable_guaranteed_candidates (по умолчанию True) решает проблему, когда чанки с knowledge_type=principle (или чанки с importance>=0.7) вообще не попадали в пул кандидатов поиска, и многоэтапное реранжирование не могло их спасти (проблема «принципиальные документы оказываются погребёнными», о которой сообщалось в RAG_EVALUATION_REPORT_2026-07-30.md/RAG_精度テスト_2026-07-31.md). Он работает, всегда добавляя подходящие чанки в пул кандидатов сразу после поиска и позволяя Cross-encoder оценить их релевантность — он не принудительно поднимает их наверх. Вызовы query()/hybrid_search, передающие metadata_filters (filters), пропускают это слияние.
Документация (Sphinx) / диаграммы (PlantUML)
pip install sphinx sphinx-rtd-theme
python -m sphinx -b html docs/source docs/builddocs/uml/ предназначен для хранения исходников PlantUML для диаграмм классов, последовательностей и конечных автоматов (на момент написания ещё не заполнен).
Структура файлов
hybrid_rag_agent_spec.md # design spec for the memory mechanism
.mcp.json # MCP server registration for Claude Code
.claude/agents/rag-memory.md # sub-agent definition for Claude Code
mcp_server/
└── server.py # the MCP server itself (13 tools, see the table above)
scripts/
├── run_forgetting_batch.py # CLI for the forgetting/archival batch
├── run_evaluation.py # CLI that automatically evaluates retrieval accuracy against a golden query set
├── find_near_duplicates.py # CLI that audits near-duplicate ingests in the existing corpus (report-only, never deletes)
├── backfill_source_date.py # bulk-backfills source_date on existing chunks
├── list_md_files.py # lists candidate Markdown files for ingestion
├── manage_ingest_status.py # tracks ingest progress against list_md_files.py's listing
├── manage_conv_ingest_status.py # tracks ingest progress against convert_conversations.py's output
└── convert_conversations.py # converts a Claude.ai export (JSON) into Markdown
hybrid_rag/
├── __init__.py
├── ingestion.py # document processing
├── chunking.py # semantic chunking
├── indexing.py # dense & sparse index (FAISS)
├── indexing_bm25.py # BM25 index
├── indexing_sparse_tfidf.py # TF-IDF sparse index (shared by the Chroma/Postgres/Qdrant backends)
├── indexing_qdrant.py / indexing_chroma.py / indexing_postgres.py
├── retrieval.py # RRF search
├── reranking.py # Cross-encoder reranking (relevance axis)
├── memory_scoring.py # staged reranking (memory axis: importance/decay/frequency)
├── archival.py # forgetting/archival batch processing
├── index_health.py # index/DB consistency checking (backs the ⑫ index_health tool)
├── caching.py / embedding_cache.py
├── context.py / diversity.py / evaluation.py
├── storage.py # SQLite database (including memory-mechanism fields)
├── query_expansion.py
├── rag_system.py # main orchestrator (FAISS version, implements the memory mechanism)
├── _rag_system_indexing.py # ^ ingest/build/incremental-update/load (mixin)
├── _rag_system_query.py # ^ query pipeline (mixin)
├── _rag_system_memory.py # ^ tags/neighboring chunks/forgetting batch (mixin)
├── _rag_system_stats.py # ^ stats & cache management (mixin)
├── _rag_system_docops.py # ^ embedding/delete/lightweight search (mixin)
├── rag_system_base.py # base class shared by the Chroma/Postgres/Qdrant backends
├── rag_system_qdrant.py / rag_system_chroma.py / rag_system_postgres.py
└── rag_system_factory.py
tests/
├── test_metadata_pipeline.py # metadata regression test across ingest → build_index → query
├── test_memory_scoring.py # unit tests for staged reranking
├── test_archival.py # unit tests for the forgetting/archival batch
├── test_incremental_index.py # unit/integration tests for update_index (incremental updates)
├── test_index_health.py # unit tests for index_health (index/DB consistency check)
├── test_result_dedup.py # unit tests for RRF fusion-key stability and search-result dedup
├── test_diversity.py # unit tests for MMR diversity selection
├── test_reranking.py # unit tests for Cross-encoder reranking stats
├── test_retriever_shutdown.py # tests for RRFRetriever resource cleanup (thread leaks)
├── test_indexing_bm25.py # unit tests for the BM25 index
├── test_storage_concurrency.py # unit tests for concurrent SQLite writes
├── test_source_date.py # unit tests for source_date derivation (time-decay reference point)
├── test_document_chunks.py # unit tests for get_document_chunks (fetching neighboring chunks)
├── test_evaluation.py # unit tests for RAGEvaluator (Precision@k, etc.)
├── test_database_stats.py # unit tests for get_database_stats / duplicate-ingest detection
├── test_guaranteed_candidates.py # unit tests for guaranteed candidate-pool merging (the fix for principle burial)
├── test_rag_system_factory.py # unit tests for create_rag_system (backend switching)
└── conftest.py # shared pytest configurationЛицензия
Лицензия MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
Shared long-term memory vault for AI agents with 20 MCP tools.
Related MCP Servers
- AlicenseBqualityFmaintenancePersistent memory, teams, and projects for AI agents. 76 MCP tools for storing, recalling, and sharing knowledge across sessions with 4-strategy hybrid search.332301MIT
- AlicenseAqualityAmaintenanceDurable hybrid memory for AI agents. Combines vector search, BM25, temporal retrieval, and optional Memgraph knowledge graph via reciprocal rank fusion. 6 MCP tools: health, search, answer, feedback, graph_query, graph_add_triple. Self-hosted with Qdrant backend.77Apache 2.0
- AlicenseNot gradedqualityAmaintenanceProvides AI agents with persistent knowledge storage, enabling them to store, search, and retrieve text, documents, and files using semantic and keyword search via MCP tools.32Apache 2.0
- AlicenseNot gradedqualityDmaintenanceLocal-first AI memory layer with hybrid retrieval and brain-inspired namespaces. Enables agents to save, search, and manage memories directly via MCP tools.5MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/masaki-kato-119/hybrid-rag-memory'
If you have feedback or need assistance with the MCP directory API, please join our Discord server