Natural language conversation and retrieval-augmented generation over a Neo4j knowledge graph and PostgreSQL (pgvector) database — eliminating lossy Text2SQL models.
- Docker & Docker Compose
- Python 3.10+ (if running scripts locally)
- Ollama running locally or accessible via network (default model:
gemma4:31b-cloud)
To build and start all containers (PostgreSQL + pgvector, Neo4j + APOC, and the Streamlit App):
docker compose up --build -dCheck the status of running services:
docker compose psTo migrate relational data from your source database into the containerized PostgreSQL database and build the Neo4j graph:
# Run from outside Docker:
python .\scripts\migrate_db.py
# Or execute inside the app container:
docker exec -it kg_app python scripts/migrate_db.pyOnce the containers are running:
- Streamlit Web Application: http://localhost:8501
- Neo4j Browser Dashboard: http://localhost:7474 (Default user:
neo4j/ password in.env)
The platform implements a Hybrid Two-Tier GraphRAG Retrieval Architecture.
graph TD
User["User Question"] --> UI["Streamlit Web Interface (ui/app.py)"]
subgraph Core Engine ["GraphRAG Core Engine"]
Retriever["GraphRetriever (kg/retrieval/retriever.py)"]
T2C["Text2Cypher Engine (kg/retrieval/text2cypher.py)"]
VectorSearch["Semantic Vector Search (kg/retrieval/vector_search.py)"]
GraphEngine["Neo4j Engine (kg/graph/neo4j_engine.py)"]
OntologyStore["Ontology Store (kg/ontology/store.py)"]
end
subgraph Data Stores ["Storage Layer (Docker Containerized)"]
Postgres[("PostgreSQL + pgvector (kg_db:5432)")]
Neo4jDB[("Neo4j Knowledge Graph (bolt:7687)")]
end
subgraph Inference ["LLM Provider"]
Ollama["Ollama API / LLM Server (gemma4:31b-cloud)"]
end
UI -->|1. Submit Question| Retriever
Retriever -->|Check Active Schema| OntologyStore
Retriever -->|Tier 1: Translate Query| T2C
T2C -->|Schema Prompt| Ollama
Ollama -->|JSON Cypher| T2C
T2C -->|Execute Query| GraphEngine
GraphEngine <-->|Bolt Protocol| Neo4jDB
Retriever -->|Tier 2: Fallback Vector Search| VectorSearch
VectorSearch <-->|Cosine Similarity| Postgres
VectorSearch -->|Seed Node IDs| GraphEngine
GraphEngine -->|Expand Subgraph| Neo4jDB
Retriever -->|Context Text| UI
UI -->|Stream Context + Question| Ollama
Ollama -->|Token Stream| UI
sequenceDiagram
autonumber
actor User as User
participant UI as Streamlit UI
participant GR as GraphRetriever
participant T2C as Text2Cypher
participant Neo4j as Neo4j Engine
participant Vec as VectorSearch
participant LLM as Ollama LLM
User->>UI: Submit Question
UI->>GR: retrieve(question)
rect rgb(240, 245, 255)
note over GR,T2C: Tier 1: Text2Cypher Query Translation
GR->>T2C: text2cypher_query
T2C->>LLM: Schema Prompt + Rules
LLM-->>T2C: Return JSON Cypher
alt Query Validated and Executed
T2C->>Neo4j: run_cypher
Neo4j-->>T2C: Return Records
T2C-->>GR: Return cypher_records
else Query Error
T2C->>T2C: Retry Loop with Error Trace
end
end
rect rgb(254, 242, 242)
note over GR,Vec: Tier 2: Hybrid Fallback
opt If cypher_records is Empty
GR->>Vec: semantic_search
Vec->>Vec: Compute Embeddings
Vec-->>GR: Return Seed Node Hits
GR->>Neo4j: expand_from_seeds
Neo4j-->>GR: Return SubgraphResult
end
end
GR-->>UI: Return RetrievalResult
UI->>UI: Format Context Text
UI->>LLM: Stream Prompt
LLM-->>UI: Stream Tokens
UI-->>User: Render Final Answer
flowchart TD
Start["User Question"] --> BuildPrompt["1. Build Schema-Aware System Prompt"]
BuildPrompt --> CallLLM["2. Call LLM for JSON Cypher Output"]
CallLLM --> ParseJSON{"3. Valid JSON Output?"}
ParseJSON -- No --> Fallback["Transition to Tier 2: Vector Search"]
ParseJSON -- Yes --> RegexCheck{"4. Security Check: Forbidden Keywords?"}
RegexCheck -- Invalid Mutation --> FailSecurity["Reject Cypher (Security Violation)"] --> Fallback
RegexCheck -- Safe Query --> ExecCypher["5. Execute Cypher against Neo4j Engine"]
ExecCypher --> ExecCheck{"6. Neo4j Execution Result"}
ExecCheck -- Success with Records --> SuccessReturn["Return Records to Retriever"]
ExecCheck -- Error / Exception --> CheckAttempts{"7. Attempt Count < Max Retries?"}
CheckAttempts -- Yes --> Retrify["Feedback Loop: Append Error Trace"] --> CallLLM
CheckAttempts -- No --> Fallback
- Chat (
app.py): Interactive GraphRAG chat interface with full retrieval transparency (preview generated Cypher, fallback mode, raw context, and RTL support). - Ontology (
pages/1_ontology.py): Define, edit, and discover graph schemas and relationships from PostgreSQL tables. - Graph Management (
pages/2_graph_admin.py): Rebuild the Neo4j graph and updatepgvectorsemantic embeddings.
kg_project/
├── kg/
│ ├── graph/ # Neo4j engine & graph builder (maps PG to Neo4j)
│ ├── ontology/ # Ontology config, schema models & DB auto-discovery
│ ├── retrieval/ # Text2Cypher + Vector Search + Hybrid Graph Retriever
│ ├── embeddings.py # pgvector embedding creation via sentence-transformers
│ ├── db.py # PostgreSQL connection pool
│ └── llm.py # Ollama chat & JSON parsing interface
├── ui/
│ ├── app.py # Main Streamlit Chat Interface
│ └── pages/ # Ontology Manager & Graph Admin UI
├── scripts/
│ ├── migrate_db.py # Database migration script from source DB
│ └── mock_data.py # Mock data generator
├── docker-compose.yml # PostgreSQL + Neo4j + App containerization
└── requirements.txt # Python dependencies