Skip to main content
Glama
masaki-kato-119

hybrid-rag-memory

English | 日本語

Hybrid RAG — Agent Long-Term Memory System

Ein hybrides RAG-System, das dichte und sparse Retrieval kombiniert, mit einem tag-basierten Speichermechanismus (Wichtigkeit, Veraltungsrate pro knowledge_type und Zugriffshäufigkeit), der in das Re-Ranking integriert ist. Zur Design-Begründung siehe hybrid_rag_agent_spec.en.md.

Betreiben Sie es als MCP-Server, und Agenten wie Claude Code können es direkt als „Langzeitgedächtnis" nutzen.

So funktioniert dieser Mechanismus

Gemäß der Spezifikation wird die Verarbeitung in zwei Arten aufgeteilt.

Klasse

Inhalt

Implementierung

① Modellabhängig (Reasoning)

Wichtigkeitstaggung, Query-Expansion / Suffizienz-Urteil, Orchestrierung

Agentenseite (LLM-Urteil)

② Strukturabhängig (deterministische Verarbeitung)

Chunking, Embedding-Erzeugung, hybride Suche, gestuftes Re-Ranking, Vergessen/Archivierung

RAG-Seite (diese Bibliothek / MCP-Server)

„Wichtigkeit" und „Veraltungsrate pro knowledge_type" werden als getrennte Achsen behandelt; statt einer einfachen linearen Kombination werden sie stufenweise angewendet: ① Cutoff nach Wichtigkeit → ② Zeitabklingung nach knowledge_type → ③ Boost nach Zugriffshäufigkeit (Details siehe Spezifikationsabschnitt 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 ist so konzipiert, dass es deterministisch aus der Aufnahmequelle bestimmt wird und nicht von einem LLM anhand des Chunk-Inhalts beurteilt wird (z. B. ein von einem Menschen explizit registriertes Designdokument → principle; ein arXiv-Paper/technischer Artikel → paper; Nachrichten/Web-Suchergebnisse → news; ein Ausführungsprotokoll → experiment).

Hinweis: principle (keine Abklingung) garantiert nicht, dass ein Chunk „nie von run_forgetting_batch vergessen wird". Da das gestufte Re-Ranking zuerst den ① Wichtigkeits-Cutoff anwendet, kann ein Chunk mit knowledge_type=principle dennoch ein Archivierungsziel werden, wenn seine importance niedrig gesetzt ist und unter importance_threshold fällt (bestätigt durch tests/test_archival.py). „Keine Abklingung" gilt nur für die ② Zeitabklingungs-Stufe — es ist keine „nie vergessen"-Garantie über die gesamte ①②③-Pipeline.

Hinweis: Der Speichermechanismus (knowledge_type/importance/gestuftes Re-Ranking/Forgetting-Batch/MCP-Server) ist nur für das FAISS-Backend (HybridRAGSystem) implementiert. Die Qdrant/Chroma/PostgreSQL-Versionen sind nur als reine Hybrid-Suchbibliothek verfügbar.

Related MCP server: mnemostack

Installation

pip install -r requirements.txt

Für Entwicklung/Tests:

pip install -r requirements-dev.txt

Verwendung ① Als MCP-Server (empfohlen)

Server starten

python mcp_server/server.py

Die Speicherorte können über Umgebungsvariablen festgelegt werden (Standardwerte: hybrid_rag.db / indices).

HYBRID_RAG_DB_PATH=my_memory.db HYBRID_RAG_INDEX_PATH=my_indices python mcp_server/server.py

Bei Claude Code registrieren

.mcp.json im Projektstamm ist bereits wie folgt eingerichtet. Claude Code erkennt es automatisch, wenn es dieses Repository öffnet.

{
  "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"
      }
    }
  }
}

Wenn Sie eine virtuelle Umgebung verwenden, schreiben Sie command auf den absoluten Pfad des Python-Interpreters in Ihrer venv um (z. B. "command": "./.venv/Scripts/python.exe").

Bereitgestellte Tools

Zusätzlich zu den minimalen 3 Tools (①–③), die in Spezifikationsabschnitt 5 gefordert sind, bietet dieser Server 10 weitere Tools (④–⑬, Spezifikationserweiterungen) für Datenaufnahme, Tagging, Duplikatvermeidung, Forgetting-Batches und Health-Checks.

#

Tool

Beschreibung

embed(text)

Vektorisiert Text mit einem festen Embedding-Modell (deterministische Verarbeitung)

hybrid_search(query, tags?, filters?, top_k?, include_stats?)

Hybride Vektor+BM25-Suche. Gibt Chunks zurück, die bereits ein Relevanz-Re-Ranking (Cross-Encoder) durchlaufen haben. Mit include_stats=True wird die Rückgabeform zu {"chunks": [...], "stats": {...}}, wobei orphan_index_entries (Einträge, die als Index-Schutt verworfen wurden) und duplicate_contents (Einträge, die wegen identischem Text zusammengelegt wurden) zusammen mit Zeitinformationen hinzugefügt werden [include_stats ist eine Spezifikationserweiterung, hinzugefügt 2026-08-08]

rerank(chunks, time_weight?, freq_weight?, importance_threshold?)

Gestuftes Re-Ranking: Wichtigkeits-Cutoff → Zeitabklingung pro knowledge_type → Zugriffshäufigkeits-Boost

ingest(file_paths, metadata?, rebuild_index?)

Nimmt Dokumente auf. rebuild_index=True (Standard) führt intern ein leichtgewichtiges inkrementelles Update (update_index) aus [Spezifikationserweiterung]

set_chunk_tags(doc_id, chunk_index, importance?, knowledge_type?, tags?)

Weist Wichtigkeitstags zu / taggt knowledge_type neu (für ein menschliches Gate gedacht) [Spezifikationserweiterung]

find_by_tag(tag)

Exakte Tag-Suche (umgeht die semantische Suche). Wird verwendet, um zu prüfen, ob ein Dokument aus derselben Quelle bereits aufgenommen wurde [Spezifikationserweiterung]

get_document_chunks(doc_id, chunk_index?, window?)

Ruft benachbarte Chunks innerhalb desselben Dokuments ab (eine direkte Suche, die die semantische Suche umgeht). Kompensiert Kontextverlust an Chunk-Grenzen [Spezifikationserweiterung]

delete_document(doc_id, rebuild_index?)

Löscht ein Dokument und alle seine Chunks. Wird im „Ersetzen"-Ablauf beim erneuten Aufnehmen verwendet [Spezifikationserweiterung]

update_index()

Ein leichtgewichtiges Index-Update, das inkrementell nur die Chunks einbezieht, die seit dem letzten Index-Update hinzugefügt wurden [Spezifikationserweiterung, hinzugefügt 2026-07-30]

rebuild_index()

Führt einen vollständigen Neuaufbau der FAISS/BM25-Indizes aus jedem Chunk in der DB durch. Erforderlich nach Löschungen (⑧ oder run_forgetting_batch), da inkrementelle Updates diese nicht verarbeiten können [Spezifikationserweiterung]

run_forgetting_batch(time_weight?, freq_weight?, importance_threshold?, score_threshold?, dry_run?)

Der Vergessens-/Archivierungs-Batch-Job. Nur für seltene Ausführung gedacht [Spezifikationserweiterung]

index_health()

Prüft die Konsistenz zwischen Index und DB und meldet sie (nimmt keine Änderungen vor). Erkennt „im Index, aber nicht in der DB"-Schutt (durch Vergessen, rebuild_index nach einer Löschung aufzurufen) und „in der DB, aber nicht im Index"-Lücken (durch Vergessen, update_index nach ingest(rebuild_index=False) aufzurufen) [Spezifikationserweiterung, hinzugefügt 2026-08-08]

get_system_stats()

Meldet die Tagging-Abdeckung des Speichermechanismus der DB (nimmt keine Änderungen vor). Während index_health die strukturelle Konsistenz zwischen Index und DB betrachtet, betrachtet dieses Tool „wie gut die Speicherachse tatsächlich funktionieren kann" — Zählungen pro knowledge_type, die Importance-Setzungsrate, die Tag-Abdeckungsrate usw. [Spezifikationserweiterung, hinzugefügt 2026-08]

Ohne ④–⑬ können die ①–③-Tools allein weder Daten aufnehmen, Importance-Tags finalisieren noch Doppelregistrierungen aus derselben Quelle vermeiden — was das System unpraktikabel macht, weshalb sie hinzugefügt wurden.

Ein Hinweis zum Aufnehmen vieler Dateien hintereinander (wichtig)

Hintergrund (ein früheres Problem, behoben am 2026-07-30): ingest standardmäßig auf „jeden Chunk in der DB neu einbetten und den Index bei jedem Aufruf neu aufbauen“ eingestellt, sodass die Kosten eines einzelnen Aufrufs linear mit der Korpusgröße wuchsen und das Ingestieren von Dateien einzeln nacheinander zu Timeouts führte. ingest(rebuild_index=True) (die Standardeinstellung) ruft jetzt intern update_index() auf – einen inkrementellen Ansatz, der nur die neu hinzugefügten Chunks seit dem letzten Update einbettet und sie per .add() zum FAISS-Index hinzufügt –, sodass es jetzt unabhängig von der Gesamtkorpusgröße schnell ist (die BM25-Seite macht weiterhin bei jedem Mal einen leichten vollständigen Neuaufbau, da ihre IDF-Statistiken vom gesamten Korpus abhängen, aber das ist günstig, da keine neuronale Einbettung involviert ist).

Das heißt, ein inkrementelles Update für jede einzelne Datei auszuführen ist immer noch verschwendeter Overhead. Wenn man also viele Dateien hintereinander ingestiert, ist es besser, bei jedem ingest-Aufruf rebuild_index=False zu übergeben und am Ende des Batches einmal update_index() aufzurufen, um alles auf einmal abzugleichen. .claude/agents/doc-to-memory.md und .claude/agents/session-to-memory.md sind bereits mit diesem Muster implementiert. Das Überprüfen der DB über find_by_tag (zur Duplikatvermeidung / Fortschrittsprüfung) fragt SQLite direkt ab, funktioniert also, ohne auf den Index warten zu müssen.

Wann ein vollständiges rebuild_index() erforderlich ist: immer dann, wenn der Batch auch nur einen einzigen delete_document-Aufruf oder einen Archivierungsdurchlauf von run_forgetting_batch enthält (d. h. jede Vektorlöschung). Inkrementelles Hinzufügen (update_index) unterstützt nur das Hinzufügen zu FAISS, nicht das Entfernen daraus. Jeder Batch, der Löschungen enthält, muss daher mit einem vollständigen rebuild_index() enden. Ein Batch, der ausschließlich aus neuen Hinzufügungen besteht, ist mit update_index() in Ordnung.

Duplikate beim erneuten Registrieren derselben Quelle verhindern

Da ingest die doc_id aus einem Hash des Dateiinhalts ableitet, wird das erneute Ingestieren byte-identischer Inhalte automatisch übersprungen (ein diff-basiertes Update). In Fällen jedoch, in denen dieselbe Quelle (z. B. dieselbe Sitzung) jedes Mal von einem LLM neu zusammengefasst und erneut ingestiert wird, führen geringfügige Abweichungen im Zusammenfassungstext dazu, dass sie als anderes Dokument behandelt wird – was Duplikate erzeugt.

Um dies zu vermeiden, ingestiere mit einem eindeutigen Identifikator-Tag (z. B. session_id:xxx) und einem Aktualisiert-am-Tag (z. B. session_last_activity:2026-07-28T15:59:49Z), und bei späteren Ausführungen:

  1. Prüfe, ob das Dokument bereits über find_by_tag("session_id:xxx") existiert.

  2. Wenn das vorhandene Aktualisiert-am-Tag mit dem aktuellen Wert übereinstimmt, überspringe – tue nichts.

  3. Nur wenn es sich unterscheidet (die Quelle hat sich geändert), entferne das alte mit delete_document(doc_id, rebuild_index=False), bevor du den neuen Inhalt per ingest einfügst.

Die Implementierung dieses Musters „überspringen, wenn unverändert, ersetzen, wenn geändert“ wird empfohlen. .claude/agents/session-to-memory.md ist eine Referenzimplementierung dieses Musters.

Verwendungsbeispiel (konzeptionell)

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)

Verwendung ② Als Claude-Code-Agent

.claude/agents/rag-memory.md enthält eine Sub-Agent-Definition, die für die „Agent-Seite (Klasse ①)“ dieses Speichermechanismus verantwortlich ist. Sobald .mcp.json registriert ist, kannst du ihn aus Claude Code wie folgt aufrufen:

Use the rag-memory agent to look into past design decisions

Die Betriebsregeln für Aktionen, die eine Bestätigung durch menschliche Absicht erfordern – Wichtigkeit-Tagging, knowledge_type-Neutagging, Entscheidung, wann der Vergessens-Batch ausgeführt wird – sind ebenfalls in dieser Agent-Definition festgehalten.

Zusätzlich ist .claude/agents/session-to-memory.md ein dedizierter Agent, der vergangene Claude-Code-Sitzungen (Chat-Transkripte) zusammenfasst und sie als knowledge_type="experiment" in das Langzeitgedächtnis ingestiert. Er läuft auf einem Haiku-Modell, um die Kosten niedrig zu halten, und vergleicht bei der erneuten Verarbeitung derselben Sitzung den bestehenden Eintrag über die session_id/Aktualisiert-am-Tags – überspringt, wenn unverändert, ersetzt, wenn geändert (siehe vorheriger Abschnitt). Der Aufrufer muss explizit angeben, welche Sitzungen Ziel sein sollen; er zielt niemals ohne Begrenzung auf alle Sitzungen.

Verwendung ③ Direkt als Python-Bibliothek

Du kannst es auch direkt aus Python-Code aufrufen, ohne den MCP-Server zu durchlaufen.

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)

Ausführen des Vergessens-Batches über die CLI

Ein Skript, das für seltene Batch-Ausführungen gedacht ist – z. B. in einem 3-Monats-Zyklus oder wenn ein neues Modell veröffentlicht wird (es wird niemals automatisch innerhalb des Servers ausgeführt).

python scripts/run_forgetting_batch.py --dry-run
python scripts/run_forgetting_batch.py --score-threshold 0.1 --time-weight 0.8

Hauptoptionen: --db-path --index-path --archive-path --time-weight --freq-weight --importance-threshold --score-threshold --dry-run

Archivierte Chunks werden nach archive/chunks_archive.jsonl evakuiert (Rohtext + Metadaten + Score + Löschgrund + Löschzeitstempel), und ihre Vektorrepräsentationen werden verworfen.

Automatisches Bewerten der Retrieval-Genauigkeit über die CLI

Ein Skript, das die Retrieval-Genauigkeit gegen einen goldenen Query-Satz misst (Precision@k/Recall@k/MRR/NDCG@k/Hit Rate@k, Rang des Autoritätsdokuments, Rauschrate) auf reproduzierbare Weise, anstatt sich auf manuelle Abfragen und das Überprüfen von Ergebnissen über Cursor/Claude Code zu verlassen.

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

Hauptoptionen: --db-path --index-path --golden-set (Standard eval/golden_queries.yaml) --k-values (Standard 1,3,5,10) --authority-window (Standard 20) --output

Prüfen auf nahezu doppelte Ingeste

Die Duplikaterkennung von ingest kann Fälle nicht abfangen, in denen identischer Inhalt über eine andere Datei (einen anderen Pfad/Dateinamen – siehe „Duplikate beim erneuten Registrieren derselben Quelle verhindern“ oben) eingeht. Dieses Skript listet lediglich nahezu doppelte Einträge auf, die bereits in einem bestehenden Korpus gelandet sind. Es löscht niemals etwas.

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

Es gruppiert Dokumente, deren normalisierter Inhalts-Hash (documents.content_hash) übereinstimmt. Die Entscheidung, welches behalten werden soll – und ob überhaupt etwas gelöscht wird – bleibt dem Benutzer überlassen; rufe delete_document(doc_id, rebuild_index=False) manuell auf (und stelle sicher, dass du am Ende des Batches rebuild_index aufrufst).

eval/golden_queries.yaml ist .gitignored, da es persönliche Daten mit doc_ids enthält, die für deinen tatsächlichen Korpus spezifisch sind. Berichte werden nach eval/eval_report_<date>.md geschrieben (plus eine gleichnamige .json), die ebenfalls .gitignored sind (sie bleiben für laufende Verfolgung auf deinem Rechner).

Speichermechanismus-Felder

Felder, die in den metadata von ingest/der Python-API oder pro Chunk getragen werden:

Feld

Typ

Beschreibung

knowledge_type

str

principle / paper / news / experiment. Deterministisch aus der Ingestionsquelle bestimmt

importance

float (0.0–1.0)

Wichtigkeit, die nachträglich vom Agenten zugewiesen wird. Nicht gesetzt (None) besteht immer den Cutoff

tags

list[str]

Beliebige Tags. Werden verwendet, um Ergebnisse über das tags-Argument von hybrid_search einzugrenzen

access_count

int

Zugriffshäufigkeit. Wird jedes Mal automatisch erhöht, wenn ein Chunk tatsächlich von einer Abfrage zurückgegeben wird

last_accessed_at / created_at

str

Zeitstempel des letzten Zugriffs / der Erstellung. Dienen als Grundlage für den Zeitabfall

Tests

pytest tests/ -v
  • test_metadata_pipeline.py: ein Regressionstest, dass knowledge_type/importance/tags die ingest → build_index → query-Pipeline überleben

  • test_memory_scoring.py: Unit-Tests für das gestufte Re-Ranking (Cutoff, Abfall, Häufigkeits-Boost)

  • test_archival.py: Unit-Tests für den Vergessens-/Archivierungs-Batch

  • test_index_health.py: Unit-Tests für index_health (Index/DB-Konsistenzprüfung)

Siehe Dateilayout für die vollständige Liste und Rolle der anderen Testdateien.

Basisbibliotheks-Funktionalität (gemeinsam über Backends)

Die Basis-RAG-Funktionalität – dichte/spärliche Hybridsuche, RRF, Cross-Encoder-Re-Ranking, MMR-Diversitätsauswahl, Query-Expansion, Caching usw. – ist für jedes Backend (FAISS/Qdrant/Chroma/PostgreSQL) gemeinsam.

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)

Aspekt

FAISS

Qdrant

ChromaDB

PostgreSQL

Gefilterte Suche

Nachbearbeitung

schnell (einstufig)

Nachbearbeitung

Nachbearbeitung

Server erforderlich

nein

nein

nein

ja

Skalierung

bis zu ~20M

bis zu ~50M

mittelgroß

großskalig

Speichermechanismus (diese README)

Optionale Installationen: Dieses Repository hat keine pyproject.toml/setup.py, daher wird es nicht in der Form pip install hybrid-rag[...] verteilt. Um die Qdrant/Chroma/PostgreSQL-Versionen zu verwenden, installiere die entsprechende Client-Bibliothek direkt (pip install qdrant-client / pip install chromadb / pip install "psycopg[binary]" pgvector – alle sind bereits in requirements.txt aufgeführt, sodass pip install -r requirements.txt allein sie abdeckt).

Wichtige zusätzliche Einstellungen (eine Teilmenge der Konstruktorargumente der FAISS-Version von HybridRAGSystem):

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 (Standard True) adressiert ein Problem, bei dem knowledge_type=principle-Chunks (oder Chunks mit importance>=0.7) nie in den Kandidatenpool der Suche gelangten und das gestufte Re-Ranking sie nicht retten konnte (das in RAG_EVALUATION_REPORT_2026-07-30.md/RAG_精度テスト_2026-07-31.md gemeldete Problem „Prinzip-Dokumente werden vergraben“). Es funktioniert, indem es passende Chunks direkt nach der Abfrage immer zum Kandidatenpool hinzufügt und den Cross-Encoder ihre Relevanz bewerten lässt – es erzwingt nicht, dass sie nach oben kommen. Aufrufe von query()/hybrid_search, die metadata_filters (filters) übergeben, überspringen diese Zusammenführung.

Dokumentation (Sphinx) / Diagramme (PlantUML)

pip install sphinx sphinx-rtd-theme
python -m sphinx -b html docs/source docs/build

docs/uml/ ist dafür gedacht, PlantUML-Quellen für Klassendiagramme, Sequenzdiagramme und Zustandsdiagramme zu enthalten (zum Zeitpunkt dieses Schreibens noch nicht befüllt).

Dateilayout

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

Lizenz

MIT-Lizenz

Maintenance

ActivityMaintained
ResponsivenessSyncing

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

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Durable 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.
    7
    7
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides 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.
    32
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Local-first AI memory layer with hybrid retrieval and brain-inspired namespaces. Enables agents to save, search, and manage memories directly via MCP tools.
    5
    MIT

Latest Blog Posts

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