Real-world document ingestion, semantic search, RAG Q&A, and knowledge-graph retrieval—all in one production-ready REST API
Introduction
Retrieval-augmented generation (RAG) has become the standard way to ground LLMs in your own data. But production RAG is more than “chunk and embed”: you need flexible ingestion (files, web, GitHub, YouTube), semantic search, and—for complex, multi-hop questions—knowledge-graph–backed retrieval (GraphRAG).
The HazelJS RAG Documents Starter demonstrates exactly that. Built on HazelJS and @hazeljs/rag, it ships with every document loader in the package, a full ingest API, semantic vector search, RAG Q&A, and a complete GraphRAG pipeline (entity extraction, community detection, local/global/hybrid search). In this post we walk through what’s in the starter and how to use it.
What’s in the box
| Feature | Component | Source type |
|---|---|---|
| Local text | TextFileLoader |
.txt |
| Markdown (heading splits) | MarkdownFileLoader |
.md, .mdx
|
| JSON | JSONFileLoader |
.json |
| CSV | CSVFileLoader |
.csv |
| HTML | HtmlFileLoader |
.html, .htm
|
| Recursive directory | DirectoryLoader |
any supported type |
| Web scraping | WebLoader |
any URL |
| YouTube transcripts | YouTubeTranscriptLoader |
YouTube URLs |
| GitHub repos | GitHubLoader |
GitHub REST API |
| Word / PDF |
DocxLoader, PdfLoader
|
.docx, .pdf (optional deps) |
| Semantic search |
MemoryVectorStore + OpenAIEmbeddings
|
— |
| RAG Q&A |
RAGPipeline + GPT |
— |
| GraphRAG |
GraphRAGPipeline, CommunityDetector, CommunitySummarizer
|
any Document[]
|
| GraphRAG search | Local (BFS) + global (community reports) + hybrid | entity & thematic queries |
You get a single REST API: ingest from files or URLs, search by meaning, ask questions with citations, and run GraphRAG build + local/global/hybrid search—all with health checks and production-style structure.
Quick start
cd hazeljs-rag-documents-starter
npm install
cp .env.example .env # add OPENAI_API_KEY
npm run dev
Server runs at http://localhost:3000. Ingest the bundled sample docs:
curl -X POST http://localhost:3000/api/ingest/directory \
-H "Content-Type: application/json" \
-d '{"dirPath":"./sample-docs","recursive":true,"tags":["sample"]}'
Then try semantic search or RAG Q&A (see examples below).
Ingest API: one interface, many loaders
The starter exposes one family of endpoints for all supported sources:
| Endpoint | Loader | Typical body |
|---|---|---|
POST /api/ingest/file |
Auto by extension | { filePath, tags? } |
POST /api/ingest/directory |
DirectoryLoader |
{ dirPath, recursive?, include?, exclude?, tags? } |
POST /api/ingest/url |
WebLoader |
{ url, selector?, label?, tags? } |
POST /api/ingest/urls |
WebLoader (batch) |
{ urls[], selector?, tags? } |
POST /api/ingest/youtube |
YouTubeTranscriptLoader |
{ videoUrl, segmentDuration?, tags? } |
POST /api/ingest/github |
GitHubLoader |
{ owner, repo, ref?, directory?, extensions?, maxFiles?, tags? } |
POST /api/ingest/text |
Inline | { content, title?, metadata? } |
Every ingest response includes documentsLoaded, chunksIndexed, loader name, and optional ids. Optional peer deps: pdf-parse, mammoth, cheerio for PDF, Word, and selector-based HTML.
Knowledge API: search and RAG Q&A
After ingestion, the Knowledge API gives you vector search and RAG:
| Endpoint | Description | Body |
|---|---|---|
POST /api/knowledge/search |
Semantic similarity search | { q, topK?, minScore?, filter? } |
POST /api/knowledge/ask |
RAG Q&A (retrieve + GPT, with sources) | { question, topK?, minScore?, filter?, systemPrompt? } |
GET /api/knowledge/stats |
Document counts and sources | — |
DELETE /api/knowledge/clear |
Wipe the knowledge base | — |
Example: semantic search
curl -X POST http://localhost:3000/api/knowledge/search \
-H "Content-Type: application/json" \
-d '{"q":"How does dependency injection work in HazelJS?","topK":4,"minScore":0.35}'
Example: RAG Q&A
curl -X POST http://localhost:3000/api/knowledge/ask \
-H "Content-Type: application/json" \
-d '{"question":"What vector stores does @hazeljs/rag support and how do I swap them?","topK":5}'
Responses include answer, sources, and duration. Out of the box the starter uses MemoryVectorStore; for production you can swap in Qdrant or Pinecone in the RAG pipeline service without changing the rest of the app.
GraphRAG: knowledge graph + community reports
GraphRAG goes beyond flat vector similarity. It:
- Extracts entities and relationships from documents using the LLM (CONCEPT, TECHNOLOGY, PERSON, USES, DEPENDS_ON, etc.).
- Builds a knowledge graph (nodes = entities, edges = typed relationships).
- Detects communities with the Label Propagation Algorithm (no extra config).
- Generates community reports — LLM-written summaries per cluster.
- Retrieves in three modes: local (entity-centric BFS), global (community reports), and hybrid (both merged, recommended default).
| Mode | How it works | Best for |
|---|---|---|
| local | Seed entities → K-hop traversal → entity + relationship context | “What is X?”, “How does Y relate to Z?” |
| global | Rank community reports by query relevance → thematic summaries | “What are the main themes?” |
| hybrid | Run local + global in parallel, merge context, one synthesis call | General default |
Build the graph from the sample docs:
curl -X POST http://localhost:3000/api/graphrag/build \
-H "Content-Type: application/json" \
-d '{"dirPath":"./sample-docs"}'
Hybrid search (default):
curl -X POST http://localhost:3000/api/graphrag/search \
-H "Content-Type: application/json" \
-d '{"query":"How does HazelJS dependency injection work with modules?"}'
Local (entity-centric) and global (thematic):
curl -X POST http://localhost:3000/api/graphrag/search/local \
-H "Content-Type: application/json" \
-d '{"query":"AgentGraph and SupervisorAgent","depth":3}'
curl -X POST http://localhost:3000/api/graphrag/search/global \
-H "Content-Type: application/json" \
-d '{"query":"What are the main architectural layers of HazelJS?"}'
You can also inspect the graph and communities:
-
GET /api/graphrag/graph— full graph (entities, edges, communities) -
GET /api/graphrag/communities— community reports only -
GET /api/graphrag/stats— entity/relationship/community counts
Project structure
hazeljs-rag-documents-starter/
├── src/
│ ├── main.ts
│ ├── app.module.ts
│ ├── rag/ # RAGPipeline, embeddings, vector store
│ ├── ingest/ # All loaders, DTOs, POST /api/ingest/*
│ ├── knowledge/ # Search, ask, stats, clear
│ ├── graphrag/ # Build, search (local/global/hybrid), graph/communities/stats
│ └── health/ # GET /health, /health/ready
├── sample-docs/ # TXT, MD, CSV, JSON, HTML to try immediately
├── .env.example
└── README.md
Health: GET /health (liveness), GET /health/ready (readiness, e.g. API key check).
Environment and production notes
Key env vars: OPENAI_API_KEY (required), EMBEDDING_MODEL, QA_MODEL, CHUNK_SIZE, CHUNK_OVERLAP, SEARCH_TOP_K, SEARCH_MIN_SCORE. GraphRAG: GRAPH_EXTRACTION_CHUNK_SIZE, GRAPH_COMMUNITY_REPORTS, GRAPH_MAX_COMMUNITY_SIZE, GRAPH_LOCAL_DEPTH, GRAPH_LOCAL_TOPK, GRAPH_GLOBAL_TOPK. See the starter README for the full list.
For production, replace MemoryVectorStore in the RAG pipeline service with QdrantStore or PineconeStore; the ingest and knowledge controllers stay unchanged.
Summary
The HazelJS RAG Documents Starter gives you:
- Unified ingest — files, directories, URLs, YouTube, GitHub, and raw text via a single REST surface.
- Semantic search and RAG Q&A — vector store + GPT with configurable chunking and models.
- GraphRAG — entity/relationship extraction, community detection, and local/global/hybrid search for richer answers.
Clone it, set OPENAI_API_KEY, and you have a production-style document RAG + GraphRAG API in minutes. For more on HazelJS and @hazeljs/rag, see hazeljs.com and the HazelJS repository.
Top comments (0)