@dooor-ai/toolkit
Version:
Guards, Evals & Observability for AI applications - works seamlessly with LangChain/LangGraph
233 lines (190 loc) • 6.17 kB
Markdown
# RAG (Retrieval-Augmented Generation) - Usage Examples
## Basic Usage
```typescript
import {
dooorChatGuard,
RAGContext,
RAGStrategy,
buildRAGPrompt,
PromptInjectionGuard,
ToxicityGuard,
LatencyEval,
} from "@dooor-ai/toolkit";
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
import fs from "fs/promises";
// Setup LLM with guards and evals
const baseProvider = new ChatGoogleGenerativeAI({
model: "gemini-2.0-flash-exp",
apiKey: process.env.GEMINI_API_KEY,
temperature: 0,
});
const llm = dooorChatGuard(baseProvider, {
apiKey: "cortexdb://cortexdb_admin_...@35.223.201.25:8000/ai",
providerName: "gemini",
project: "my-project",
guards: [
new PromptInjectionGuard({ threshold: 0.8 }),
new ToxicityGuard({ threshold: 0.7 }),
],
evals: [new LatencyEval({ threshold: 3000 })],
observability: true,
});
// Create RAG context with PDF files
const manualPdf = await fs.readFile("./docs/manual.pdf");
const apiDocsPdf = await fs.readFile("./docs/api-reference.pdf");
const ragContext = new RAGContext({
files: [
{ name: "manual.pdf", data: manualPdf, type: "application/pdf" },
{ name: "api-reference.pdf", data: apiDocsPdf, type: "application/pdf" },
],
embeddingProvider: "prod-gemini", // Internal name configured in /settings/embeddings
strategy: RAGStrategy.HYDE,
topK: 5,
chunkSize: 1000,
chunkOverlap: 200,
});
// Use buildRAGPrompt to automatically inject context
const userQuery = "How do I authenticate users in the system?";
const promptWithContext = await buildRAGPrompt(userQuery, ragContext);
const result = await llm.invoke([
{ role: "user", content: promptWithContext }
]);
console.log("Answer:", result.content);
```
## Mixing Different Sources
```typescript
const ragContext = new RAGContext({
// PDF files
files: [
{ name: "manual.pdf", data: pdfBuffer, type: "application/pdf" },
{ name: "api-docs.md", data: mdBuffer, type: "text/markdown" },
],
// Plain text documents
documents: [
{
content: "Authentication uses JWT tokens. Tokens expire after 24h.",
metadata: { source: "internal-notes" }
},
{
content: "Users can reset passwords via /auth/reset endpoint.",
metadata: { source: "support-docs" }
},
],
// Pre-computed embeddings (if you already have them)
embeddings: [
{
text: "OAuth 2.0 is supported for third-party integrations.",
vector: [0.1, 0.2, 0.3, ...], // Your pre-computed embedding
metadata: { source: "oauth-spec" }
},
],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.RERANK,
topK: 10,
});
```
## Different RAG Strategies
```typescript
// 1. SIMPLE - Basic semantic search
const simpleRAG = new RAGContext({
files: [pdfFile],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.SIMPLE,
topK: 5,
});
// 2. HYDE - Hypothetical Document Embeddings (best for complex queries)
const hydeRAG = new RAGContext({
files: [pdfFile],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.HYDE,
topK: 5,
});
// 3. RERANK - Retrieve more candidates, rerank with LLM
const rerankRAG = new RAGContext({
files: [pdfFile],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.RERANK,
topK: 10,
});
// 4. FUSION - Combine multiple retrieval methods
const fusionRAG = new RAGContext({
files: [pdfFile],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.FUSION,
topK: 5,
});
// 5. MULTI_QUERY - Generate multiple queries for better coverage
const multiQueryRAG = new RAGContext({
files: [pdfFile],
embeddingProvider: "prod-gemini",
strategy: RAGStrategy.MULTI_QUERY,
topK: 5,
});
```
## Manual Context Retrieval
```typescript
import { retrieveContext } from "@dooor-ai/toolkit";
// Get context without building prompt
const { context, results, metadata } = await retrieveContext(
"How to authenticate?",
ragContext
);
console.log("Retrieved context:", context);
console.log("Chunks used:", metadata.chunks_retrieved);
console.log("Latency:", metadata.took_ms, "ms");
console.log("Strategy:", metadata.strategy_used);
console.log("Similarity scores:", metadata.similarity_scores);
// Build custom prompt
const customPrompt = `
Here is relevant documentation:
${context}
Based ONLY on the documentation above, answer this question:
${userQuery}
If the documentation doesn't contain the answer, say "I don't know based on the provided documentation."
`;
const result = await llm.invoke([{ role: "user", content: customPrompt }]);
```
## With LangGraph Agents
```typescript
import { createReactAgent } from "@langchain/langgraph/prebuilt";
const agent = createReactAgent({
llm: llm,
tools: [],
prompt: `You are a helpful assistant. Use the provided context to answer questions.`,
});
// Build RAG prompt before calling agent
const promptWithContext = await buildRAGPrompt(userQuery, ragContext);
const result = await agent.invoke({
messages: [{ role: "user", content: promptWithContext }]
});
console.log(result);
```
## Error Handling
```typescript
try {
const ragContext = new RAGContext({
files: [pdfFile],
embeddingProvider: "my-embedding-provider",
strategy: RAGStrategy.HYDE,
});
const prompt = await buildRAGPrompt(userQuery, ragContext);
const result = await llm.invoke([{ role: "user", content: prompt }]);
console.log(result.content);
} catch (error) {
if (error.message.includes("Embedding provider")) {
console.error("Configure embedding provider at /settings/embeddings");
} else if (error.message.includes("not found")) {
console.error("Embedding provider 'my-embedding-provider' not found");
} else {
console.error("RAG failed:", error.message);
}
}
```
## Observability
RAG metrics are automatically tracked in observability:
- **Retrieval latency** - Time to retrieve and process documents
- **Chunks retrieved** - Number of document chunks used
- **Similarity scores** - Relevance scores for retrieved chunks
- **Strategy used** - Which RAG strategy was applied
- **Embedding provider** - Which provider generated embeddings
All metrics are visible in the CortexDB Studio observability dashboard.