Documentation•Reference
Build a TypeScript RAG API with HazelJS
Ship a production-shaped RAG HTTP API in TypeScript: ingest documents, retrieve context, generate answers — all in one HazelJS app with @hazeljs/rag and @hazeljs/ai.
Quick Reference
- Purpose: End-to-end tutorial for a Node.js / TypeScript RAG API without assembling Express + LangChain glue.
- When to use: You searched for “build RAG API TypeScript”, “Node.js RAG backend”, or are comparing stacks for a retrieval service.
- Key concepts: embeddings, vector store,
RAGPipeline, controller endpoints, HCEL.rag(), optional Agentic RAG. - Dependencies:
@hazeljs/core,@hazeljs/ai,@hazeljs/rag. - Related: RAG patterns, RAG vs Agentic RAG, Vector stores, vs LangChain.
What you will build
- A HazelJS module with DI
- Ingest (index) text or docs into a vector store
POST /rag/querythat retrieves + generates an answer- Optional upgrade path to Agentic RAG
Install
npm install @hazeljs/core @hazeljs/ai @hazeljs/rag
Set OPENAI_API_KEY (or configure another supported provider in @hazeljs/ai).
Step 1 — Bootstrap the app
import { HazelApp, HazelModule } from '@hazeljs/core';
import { RagController } from './rag.controller';
import { RagService } from './rag.service';
@HazelModule({
controllers: [RagController],
providers: [RagService],
})
class AppModule {}
async function bootstrap() {
const app = new HazelApp(AppModule);
await app.listen(3000);
console.log('RAG API on :3000');
}
bootstrap();
Step 2 — RAG service (index + query)
import { Injectable } from '@hazeljs/core';
import { RAGPipeline, MemoryVectorStore, OpenAIEmbeddings } from '@hazeljs/rag';
import { AIService } from '@hazeljs/ai';
@Injectable()
export class RagService {
private pipeline: RAGPipeline;
private ready = false;
constructor(private ai: AIService) {
const embeddings = new OpenAIEmbeddings({
apiKey: process.env.OPENAI_API_KEY,
});
const vectorStore = new MemoryVectorStore(embeddings);
this.pipeline = new RAGPipeline({
vectorStore,
embeddingProvider: embeddings,
topK: 4,
});
}
async init() {
if (this.ready) return;
await this.pipeline.vectorStore.initialize?.();
this.ready = true;
}
async ingest(docs: { id: string; text: string }[]) {
await this.init();
// Adapt to your package’s ingest API — see RAG package docs for loaders
for (const doc of docs) {
await this.pipeline.addDocuments?.([
{ id: doc.id, content: doc.text, metadata: { source: doc.id } },
]);
}
return { indexed: docs.length };
}
async answer(question: string) {
await this.init();
const results = await this.pipeline.query(question);
const context = (results.sources ?? [])
.map((s: { content: string }) => s.content)
.join('\n\n');
return this.ai.hazel
.prompt(
`Answer using only the context.\n\nContext:\n${context}\n\nQuestion: {{input}}`
)
.execute(question);
}
}
Exact ingest helpers vary by vector store. Prefer document loaders from the Document loaders guide and Vector stores for Pinecone, Qdrant, Weaviate, or Chroma in production.
Step 3 — HTTP controllers
import { Controller, Post, Body, Get } from '@hazeljs/core';
import { RagService } from './rag.service';
@Controller({ path: '/rag' })
export class RagController {
constructor(private rag: RagService) {}
@Get('health')
health() {
return { ok: true };
}
@Post('ingest')
ingest(@Body() body: { docs: { id: string; text: string }[] }) {
return this.rag.ingest(body.docs ?? []);
}
@Post('query')
query(@Body() body: { question: string }) {
return this.rag.answer(body.question);
}
}
Step 4 — Try it
curl -s localhost:3000/rag/ingest -H 'content-type: application/json' \
-d '{"docs":[{"id":"1","text":"HazelJS is an AI-native TypeScript backend framework."}]}'
curl -s localhost:3000/rag/query -H 'content-type: application/json' \
-d '{"question":"What is HazelJS?"}'
HCEL one-liner (when the collection already exists)
If documents are already indexed under a named collection:
return this.ai.hazel
.prompt('Answer with citations from context: {{input}}')
.rag('product-docs')
.execute(question);
See HCEL guide.
When to upgrade to Agentic RAG
Use standard RAG for simple Q&A over a curated corpus. Move to Agentic RAG when queries need planning, reflection, or multi-hop retrieval:
Production checklist
- Swap
MemoryVectorStorefor a durable store (vector stores) - Add auth / rate limits (security,
@hazeljs/auth) - Chunking + metadata strategy (RAG patterns)
- Eval retrieval quality separately from generation (
@hazeljs/eval) - Observability for LLM cost and latency
Related comparisons
- HazelJS vs LangChain — library vs full backend
- NestJS + LangChain vs HazelJS — common glue stack
Next steps
- RAG package docs
- AI package
- Support agent example — RAG + tools together
- Installation