Skip to content

Repository files navigation

Synaptic

A local-first, multi-agent RAG assistant with memory engineering and observability, built on FastAPI, LangGraph, pgvector, and Redis.

Also a hands-on learning project: an excuse to get industry-depth, hands-on experience with the tools real AI engineering teams use — LangChain, LangGraph, hybrid retrieval, context engineering, evals, and tracing — while shipping something a user could actually query.


What It Does

Synaptic answers questions grounded in an answer-bearing Stack Overflow knowledge base (~134k documents built from Kaggle + StackExchange Data Explorer exports — every chunk is title + question + accepted/best answer, not just a bare question) while maintaining memory across sessions. Each query is condensed against conversation history, optionally expanded via HyDE, retrieved with hybrid dense + BM25 search, reranked with a cross-encoder, and answered by an LLM through a LangGraph multi-agent pipeline before streaming back to the UI.

Everything runs against a local, OpenAI-compatible model endpoint — no data leaves the machine.


Architecture

User Query (Next.js UI)
│
▼
Triage Agent ──► RAG Agent ──► query condensation → HyDE (optional) → hybrid search (dense + BM25/RRF) → rerank → generate
└──► Memory Agent ──► Redis (short-term) + pgvector (long-term summaries)
└──► Orchestrator (multi-intent only)
│
▼
Writer Node
│
▼
Context Engineer + Optimiser (per-agent token budgets, LLMLingua compression on overflow)
│
▼
Streamed response (OpenAI-compatible SSE)
│
▼
Langfuse (per-node trace)

A guardrail classifier (input-side injection/jailbreak/off-topic detection + output-side streaming check) sits ahead of triage as the next planned entry point — see Roadmap.

All agents call the same model through one OpenAI-compatible endpoint (LLM_MODEL / LLM_BASE_URL), differentiated by system prompt and tool access rather than by separate model deployments — swapping models is a config change, not a code change. Embeddings run locally via nomic-embed-text-v1.5 (sentence-transformers).


Tech Stack

LayerTechnology
BackendFastAPI (Python 3.11+), async SSE streaming, OpenAI-compatible /v1/chat/completions
Agent orchestrationLangGraph (stateful graph, Redis checkpointing via AsyncRedisSaver)
LLMAny OpenAI-compatible endpoint (local model server) — one model, prompt-differentiated agents
Embeddingsnomic-embed-text-v1.5 via langchain-huggingface (local)
Vector DBpgvector on PostgreSQL (HNSW index, cosine similarity)
Dense retrievalpgvector cosine search (retrieval/chunks_retriever.py)
Sparse retrievalrank-bm25, in-memory, rebuilt on app startup (retrieval/bm25_retriever.py)
Hybrid fusionReciprocal Rank Fusion, dense + BM25 (retrieval/hybrid.py)
Query expansionHyDE — hypothetical document embedding (retrieval/hyde.py), gated by use_hyde
Rerankercross-encoder/ms-marco-MiniLM-L-6-v2 (sentence-transformers)
Context engineeringPer-agent token budgets + LLMLingua compression on overflow (context/engineer.py, context/optimiser.py)
Short-term memoryRedis (sliding window, ~10 turns, 24h TTL)
Long-term memorypgvector (session summaries, linear relevance decay)
EvalsRAGAS — faithfulness, answer relevancy, context precision (reference-based recall/correctness in progress)
ObservabilityLangfuse (LangChain CallbackHandler, per-node @observe spans)
FrontendNext.js + TypeScript + shadcn/radix (SSE streaming via the OpenAI SDK)

Prerequisites

  • Python 3.11+
  • Docker + Docker Compose
  • An OpenAI-compatible local LLM server (e.g. Unsloth Studio, Ollama, LM Studio, vLLM) reachable at LLM_BASE_URL

Setup

1. Clone and install

git clone https://github.com/gh0sty02/synaptic.git
cd synaptic
python -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txt

2. Configure environment

cp .env.example .env
# LLM Provider (OpenAI-compatible)LLM_MODEL=your-model-nameLLM_BASE_URL=http://localhost:8000LLM_API_KEY=your-api-key# DatabaseCONN_STR=postgresql://user:password@localhost:5432/dbname# Vector StoreCHUNK_COLLECTION_NAME=your-collection-nameEMBEDDING_MODEL=your-embedding-modelEMBEDDING_VERSION=your-embedding-versionREBUILD_INDEX_THRESHOLD=1000# RetrievalRETRIEVAL_CANDIDATE_K=100RETRIEVAL_TOP_K=10RETRIEVAL_SCORE_CUTOFF=0.35RERANKER_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2# Observability (Langfuse)LANGFUSE_SECRET_KEY=your-langfuse-secret-keyLANGFUSE_PUBLIC_KEY=your-langfuse-public-keyLANGFUSE_BASE_URL=https://cloud.langfuse.com

3. Start infrastructure

docker-compose up -d

Starts: PostgreSQL + pgvector, Redis.

4. Run database migrations

psql "$CONN_STR" -f backend/db/schema.sql

5. Ingest data

Place the source CSVs under dataset/kaggle/ and dataset/stackexchange/, then:

curl -X POST http://localhost:8000/ingest \
-H "Content-Type: application/json" \
-d '{}'

Builds the combined Kaggle + StackExchange corpus (~134,000 answer-grounded documents), embeds, and bulk-loads into pgvector.

6. Start the backend

uvicorn backend.main:app --reload --port 8000

7. Start the frontend

cd frontend
npm install
npm run dev
# → http://localhost:3000

API

MethodEndpointDescription
POST/v1/chat/completionsStream a response (OpenAI-compatible SSE)
POST/ingestTrigger dataset ingestion
GET/healthService health check
GET/sessions/{id}Get session history
DELETE/sessions/{id}End session (archive → summarise long-term memory)
GET/metricsQuery count, error count, average latency

POST /v1/chat/completions

{
"session_id": "optional-uuid",
"model": "your-model-name",
"messages": [{ "role": "user", "content": "What is the difference between useEffect and useLayoutEffect?" }],
"use_hyde": false
}

Streams standard OpenAI chat-completion chunks.


Project Structure

synaptic/
├── docker-compose.yml
├── .env.example
├── backend/
│ ├── main.py # FastAPI app, OpenAI-compatible SSE endpoint
│ ├── requirements.txt
│ ├── agents/ # LangGraph graph + agent nodes (triage, rag_agent,
│ │ # memory_node, orchestrator, writer_node)
│ ├── chain/ # RAG chain (condensation → HyDE → retrieve → generate)
│ ├── context/ # Per-agent token budgets + LLMLingua compression
│ ├── memory/ # Short-term (Redis) + long-term (pgvector)
│ ├── retrieval/ # Dense, BM25, hybrid (RRF), reranker, HyDE
│ ├── ingestion/ # Kaggle + StackExchange adapters, shared dataset builder
│ ├── evals/ # RAGAS eval runner
│ └── db/ # schema.sql
├── frontend/
│ ├── app/ # Next.js app router
│ └── components/ # Chat UI (shadcn/radix)
├── dataset/ # Source CSVs (not committed)
└── experiments/ # Retrieval experiment results

Roadmap

PhaseFocusStatus
1RAG pipeline end-to-end (ingestion → retrieval → streaming)Done (Next.js UI, /v1/chat/completions instead of the originally specced /chat)
1.2Retrieval quality — over-fetch + cross-encoder rerankingDone
2LangGraph multi-agent graph + memory engineeringDone
3Context engineering, hybrid search (BM25 + RRF), HyDE, RAGAS evalsCore done — Langfuse budget-decision logging and reference-based RAGAS metrics remain
3.1Answer-grounded Stack Overflow dataset (Kaggle + StackExchange)Mostly done — ragas_runner.py reference metrics remain
3.2Conversation history — listable, resumable past sessionsNot started
4Guardrail classifier — input injection/jailbreak/off-topic + output streaming checkPlanned, implementation-ready
4.5Metadata filters, tool use, KV/prompt cache, API fixesDeferred until Phase 4 ships
5Full Langfuse observability, memory depth, UI polish (citations, latency)Partially done
6OAuth authentication (Google + GitHub)Not started
7Tests, RAGAS eval harness, CINot started
8Multimodal image inputNot started
9Infra and VPS deploymentNot started

Eval Results

ConfigurationContext PrecisionContext RecallFaithfulnessAnswer Relevancy
Dense-only baseline
+ Hybrid search (BM25 + RRF)
+ HyDE

The RAGAS runner exists (backend/evals/ragas_runner.py); results are populated once the reference-based metrics (Phase 3.1) and a committed baseline (Phase 7) land.


Swapping Models

All agents read the model from LLM_MODEL/LLM_BASE_URL at startup — pointing these at a different OpenAI-compatible endpoint (a larger local model, or a hosted API) requires no code changes.

About

Local-first, multi-agent RAG assistant over a Stack Overflow knowledge base - FastAPI + LangGraph agents, hybrid (dense + BM25/RRF) retrieval with reranking and HyDE, Redis/pgvector memory, RAGAS evals, and Langfuse tracing.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages