# Architecture — grafeo-langchain

## Components

### GrafeoGraphStore (`graph_store.py`)

Knowledge graph storage for LLM-extracted triples (via `LLMGraphTransformer`).

- Stores `GraphDocument` nodes/relationships as native Grafeo nodes and edges
- Supports GQL/Cypher queries via `store.query()`
- Schema introspection for LLM prompts (`get_schema`, `get_structured_schema`)
- Upserts nodes by `node_id` property (idempotent)
- Optionally links extracted entities back to their source document

### GrafeoGraphVectorStore (`graph_vector_store.py`)

Combined vector + graph retrieval store. Subclasses LangChain's `VectorStore`.

- Documents stored as `(:Document)` nodes with `embedding` vector property
- Explicit graph links between documents via `__graph_links__` metadata key
- Three retrieval modes:
  1. **similarity_search** — pure vector similarity (cosine via HNSW index)
  2. **traversal_search** — vector seeds + multi-hop graph traversal
  3. **mmr_traversal_search** — MMR-diversified traversal results
- Compatible with `langchain-graph-retriever` for BFS/Eager strategies

### GraphDocument helpers (`graph_document.py`)

Conversion utilities between LangChain's `GraphDocument` / `Node` / `Relationship` types and Grafeo's native node/edge representations.

## Data Model

```
LangChain GraphDocument          Grafeo
─────────────────────           ─────────────────────
Node(id, type, props)     →     (:Type {node_id: id, ...props})
Relationship(src, tgt, type) →  (src)-[:TYPE {..props}]->(tgt)
GraphDocument.source      →     (:SourceDocument {text, node_id: "source_..."})
  + MENTIONED_IN edges          (entity)-[:MENTIONED_IN]->(source)

Document (vector store)   →     (:Document {doc_id, text, embedding: [...]})
  + __graph_links__       →     (doc)-[:LINKS_TO]->(other_doc)
```

## Index Strategy

| Index | Property | Purpose |
|-------|----------|---------|
| Property index | `node_id` | Fast node upsert lookups in GraphStore |
| Property index | `doc_id` | Fast document lookups in GraphVectorStore |
| Vector index (HNSW) | `embedding` on `:Document` | Cosine similarity search |

## Query Flow — traversal_search

```
1. User query string
   ↓
2. Embed query → vector
   ↓
3. HNSW vector search → seed Document nodes (top-k)
   ↓
4. For each seed: GQL variable-length path traversal
   MATCH (src {doc_id: "..."})-[*1..depth]->(neighbor:Document)
   ↓
5. Deduplicate by doc_id, merge seeds + traversed
   ↓
6. Return results (up to 2*k documents)
```

## Design Decisions

- **src layout**: Prevents accidental imports of uninstalled package during testing.
- **langchain-core only**: `GrafeoGraphStore` duck-types the `GraphStore` interface (no `langchain-community` dep). `GrafeoGraphVectorStore` subclasses `VectorStore` from `langchain-core`.
- **Upsert semantics**: Nodes are matched by `node_id`/`doc_id` to support idempotent ingestion.
- **MMR via native Grafeo**: MMR uses `grafeo.GrafeoDB.mmr_search()` (SIMD-accelerated Rust) instead of numpy. This keeps grafeo-langchain dependency-free beyond grafeo + langchain-core. The MMR feature is being added to Grafeo upstream — see `grafeo/.claude/todo/4_language_bindings/mmr-search.md`.
