Data model and storage
What PostgreSQL and Neo4j store and how source provenance reaches citations.
PostgreSQL holds source text, embeddings, and conversation state. Neo4j holds extracted entities and relationships linked back to source chunks.
PostgreSQL
Search corpus
The document_chunks table stores an integer row ID, document name, chunk index, content, 768-dimensional embedding, and creation time. Dense retrieval compares query embeddings with the stored pgvector column. Ingestion bulk-loads rows; document deletion removes the corresponding corpus rows.
Conversation state
The application store manages four tables:
| Table | Purpose |
|---|---|
conversations | Conversation identity and optional user association |
messages | User and assistant turns, confidence, citations, and tool attribution |
feedback | Up/down rating and optional comment for an assistant message |
memories | User-scoped key/value memory |
The store initializes its tables on demand. Chat loads a bounded recent history window for planning and generation.
Neo4j
Entities are represented as Entity nodes. Their category is the label property, and relationships use RELATES edges with a type property. MENTIONS connects entities to chunks. Entity provenance also stores source chunk IDs.
The entity category is a property, not a Neo4j node label. Queries must filter on the property to match the current schema.
Provenance path
Vector hits already identify their source chunk. Graph hits collect chunk IDs, then resolve_chunks loads the corresponding text and document metadata from PostgreSQL. The answer generator receives these passages and their citations rather than treating an entity description as a source.
An entity without source chunk IDs cannot support a document-grounded graph claim. See Operations and limitations for the known provenance gap.