RAG (Retrieval-Augmented Generation) lets your chatbot answer questions based on your specific documents — not just what Claude already knows. Day 4 builds a simple but functional RAG system.
RAG works in two steps: first, find the relevant parts of your documents that match the user's question (retrieval). Second, include those parts in the prompt and ask Claude to answer based on them (generation). The simplest implementation uses text search rather than vector embeddings — good enough for most use cases.
npm install natural// Simple keyword-based retrieval
class DocumentStore {
constructor() {
this.chunks = [];
}
addDocument(text, metadata = {}) {
// Split into ~500 character chunks with overlap
const words = text.split(/\s+/);
const chunkSize = 80; // words
const overlap = 20;
for (let i = 0; i < words.length; i += (chunkSize - overlap)) {
const chunk = words.slice(i, i + chunkSize).join(' ');
if (chunk.trim()) {
this.chunks.push({ text: chunk, metadata });
}
}
}
retrieve(query, topK = 3) {
const queryWords = new Set(
query.toLowerCase().split(/\W+/).filter(w => w.length > 3)
);
const scored = this.chunks.map(chunk => {
const chunkWords = new Set(
chunk.text.toLowerCase().split(/\W+/).filter(w => w.length > 3)
);
let score = 0;
for (const word of queryWords) {
if (chunkWords.has(word)) score++;
}
return { ...chunk, score };
});
return scored
.sort((a, b) => b.score - a.score)
.slice(0, topK)
.filter(c => c.score > 0);
}
}
module.exports = DocumentStore;const DocumentStore = require('./rag');
const docStore = new DocumentStore();
// Load your documents at startup
docStore.addDocument(`
Your company knowledge base text goes here.
This can be product documentation, FAQs,
policies, or any text you want the bot to
know about. Add as much as you need.
`, { source: 'knowledge-base' });
// Update the /chat route to use RAG
app.post('/chat', async (req, res) => {
const { message, sessionId } = req.body;
if (!conversations[sessionId]) {
conversations[sessionId] = [];
}
// Retrieve relevant chunks
const chunks = docStore.retrieve(message, 3);
const context = chunks.length > 0
? 'Relevant information:
' + chunks.map(c => c.text).join('
')
: '';
conversations[sessionId].push({
role: 'user',
content: message
});
const systemPrompt = `You are a helpful assistant.
${context ? context + '
Use the above information to answer if relevant.' : ''}
If you don't know something, say so honestly.`;
const response = await client.messages.create({
model: 'claude-opus-4-5',
max_tokens: 1024,
system: systemPrompt,
messages: conversations[sessionId]
});
const reply = response.content[0].text;
conversations[sessionId].push({ role: 'assistant', content: reply });
res.json({ reply, sourcesFound: chunks.length });
});