Skip to content

Commit 76175cd

Browse files
committed
refactor: update RAG chatbot blog post
1 parent b994464 commit 76175cd

4 files changed

Lines changed: 140 additions & 207 deletions

File tree

website/blog/2025-04-24-rag-chatbot/index.md

Lines changed: 67 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Building a RAG Chatbot with VoltAgent
3-
description: Learn how to enhance your chatbot with external knowledge using Retrieval-Augmented Generation (RAG) in VoltAgent.
3+
description: Build RAG chatbots with VoltAgent to use external knowledge.
44
slug: rag-chatbot
55
tags: [rag, tutorial]
66
authors: necatiozmen
@@ -11,27 +11,41 @@ import Tabs from '@theme/Tabs';
1111
import TabItem from '@theme/TabItem';
1212
import RetrieverMethodHelper from '@site/src/components/blog-widgets/RetrieverMethodHelper';
1313

14-
Chatbots have become incredibly useful, haven't they? From customer support to personal assistants, they handle conversations pretty well. But sometimes, standard chatbots hit a wall – their knowledge is limited to what they were trained on. What if you want your chatbot to answer questions based on specific documents, recent data, or a private knowledge base?
14+
## Introduction
15+
16+
Chatbots have become incredibly useful, haven't they? From customer support to personal assistants, they handle conversations pretty well. But sometimes, standard chatbots hit a wall – their knowledge is limited to what they were trained on.
17+
18+
What if you want your chatbot to answer questions based on specific documents, recent data, or a private knowledge base?
1519

1620
That's where **Retrieval-Augmented Generation (RAG)** comes in.
1721

1822
![VoltAgent Console Chat Example](https://cdn.voltagent.dev/2025-04-24-rag-chatbot/rag-chatbot-voltagent-console.gif)
1923

24+
Steps we'll cover:
25+
26+
- [What RAG (Retrieval-Augmented Generation) is and why it's useful.](#what-is-rag-and-why-use-it)
27+
- [How VoltAgent's Retriever system facilitates RAG.](#voltagents-retriever-system)
28+
- [Setting up a VoltAgent project.](#setting-up-the-project)
29+
- [Implementing a custom `BaseRetriever` with a simple knowledge base.](#implementing-the-retriever-and-agent)
30+
- [Creating a VoltAgent `Agent` that uses the retriever directly.](#implementing-the-retriever-and-agent)
31+
- [Running and testing the RAG chatbot using the VoltAgent Console.](#running-the-agent)
32+
2033
## What is RAG, and Why Use It?
2134

2235
At its core, RAG is a technique that helps Large Language Models (LLMs) like the ones powering chatbots become smarter by giving them access to external information _before_ they generate a response.
2336

24-
Think of it like this:
37+
:::info Think of it like this:
2538

26-
1. **Retrieval:** When you ask a RAG-enabled chatbot a question, it first _retrieves_ relevant snippets of information from a predefined data source (like documents, databases, or websites).
27-
2. **Augmentation:** This retrieved information (the "context") is then _added_ to your original question.
28-
3. **Generation:** Finally, the LLM receives the combined prompt (your question + the retrieved context) and _generates_ an answer that's grounded in that specific information.
39+
- **Retrieval:** When you ask a RAG-enabled chatbot a question, it first _retrieves_ relevant snippets of information from a predefined data source (like documents, databases, or websites).
40+
- **Augmentation:** This retrieved information (the "context") is then _added_ to your original question.
41+
- **Generation:** Finally, the LLM receives the combined prompt (your question + the retrieved context) and _generates_ an answer that's grounded in that specific information.
42+
:::
2943

3044
The result? Chatbots that can provide more accurate, up-to-date, and contextually relevant answers, going beyond their built-in knowledge. I find this incredibly powerful for building bots that need to know about specific product documentation, internal company policies, or recent news.
3145

3246
## Introducing VoltAgent
3347

34-
Before we dive into building, let me briefly mention **VoltAgent**. It's a TypeScript framework I've been working with that makes building sophisticated AI agents (like our RAG chatbot) much simpler. It handles a lot of the boilerplate, letting me focus on the core logic of my agents, including how they retrieve and use information.
48+
Before we dive into building, let me briefly mention [**VoltAgent**](https://github.com/VoltAgent/voltagent). It's a TypeScript framework I've been working with that makes building sophisticated AI agents (like our RAG chatbot) much simpler. It handles a lot of the boilerplate, letting me focus on the core logic of my agents, including how they retrieve and use information.
3549

3650
## VoltAgent's Retriever System
3751

@@ -44,11 +58,13 @@ To add RAG capabilities to your agent, you essentially need to:
4458
- **Direct Attachment (`agent.retriever`):** The retriever runs automatically _before every_ LLM call for that agent. Simple, ensures context is always fetched.
4559
- **As a Tool (`agent.tools`):** The LLM decides _when_ to call the retriever tool based on the conversation. More efficient and flexible, especially if retrieval isn't always needed.
4660

61+
<br/>
62+
4763
<RetrieverMethodHelper />
4864

4965
For this tutorial, we'll use the **direct attachment** method for simplicity. Our agent will always try to fetch context from its small knowledge base before answering.
5066

51-
## Let's Build a Simple RAG Chatbot!
67+
## Let's Build a Simple RAG Chatbot
5268

5369
Okay, theory's great, but let's get hands-on. I'll show you how I built a basic RAG chatbot using VoltAgent that answers questions based on a small, hardcoded set of facts about VoltAgent itself.
5470

@@ -73,7 +89,7 @@ The CLI sets up a standard project structure for you:
7389
```
7490
with-rag-chatbot/
7591
├── src/
76-
│ └── index.ts # Our main agent logic will go here
92+
│ └── index.ts # Our main agent logic will go here
7793
├── package.json # Project dependencies
7894
├── tsconfig.json # TypeScript config
7995
├── .gitignore # Git ignore rules
@@ -187,63 +203,63 @@ new VoltAgent({
187203

188204
Before running, you need an API key for your chosen LLM provider (like OpenAI).
189205

190-
**Create `.env` file:** In the root of your `with-rag-chatbot` project folder, create a file named `.env`.
206+
1. **Create `.env` file:** In the root of your `with-rag-chatbot` project folder, create a file named `.env`.
191207

192-
**Add API Key:** Add your key like this:
193-
`bash title=".env"
194-
OPENAI_API_KEY=your_openai_api_key_here
195-
`
196-
(Replace `your_openai_api_key_here` with your actual key).
208+
2. **Add API Key:** Add your key like this:
209+
`bash title=".env"
210+
OPENAI_API_KEY=your_openai_api_key_here
211+
`
212+
(Replace `your_openai_api_key_here` with your actual key).
197213

198-
**Install Dependencies:** Open your terminal _inside_ the `with-rag-chatbot` directory and run:
199-
<Tabs>
200-
<TabItem value="npm" label="npm" default>
214+
3. **Install Dependencies:** Open your terminal _inside_ the `with-rag-chatbot` directory and run:
215+
<Tabs>
216+
<TabItem value="npm" label="npm" default>
201217

202-
```bash
203-
npm install
204-
```
218+
```bash
219+
npm install
220+
```
205221

206-
</TabItem>
207-
<TabItem value="yarn" label="yarn">
222+
</TabItem>
223+
<TabItem value="yarn" label="yarn">
208224

209-
```bash
210-
yarn install
211-
```
225+
```bash
226+
yarn install
227+
```
212228

213-
</TabItem>
214-
<TabItem value="pnpm" label="pnpm">
229+
</TabItem>
230+
<TabItem value="pnpm" label="pnpm">
215231

216-
```bash
217-
pnpm install
218-
```
232+
```bash
233+
pnpm install
234+
```
219235

220-
</TabItem>
221-
</Tabs>
236+
</TabItem>
237+
</Tabs>
222238

223-
**Start the Agent:** Run the development server:
224-
<Tabs>
225-
<TabItem value="npm" label="npm" default>
239+
4. **Start the Agent:** Run the development server:
240+
<Tabs>
241+
<TabItem value="npm" label="npm" default>
226242

227-
```bash
228-
npm run dev
229-
```
243+
```bash
244+
npm run dev
245+
```
230246

231-
</TabItem>
232-
<TabItem value="yarn" label="yarn">
247+
</TabItem>
248+
<TabItem value="yarn" label="yarn">
233249

234-
```bash
235-
yarn dev
236-
```
250+
```bash
251+
yarn dev
252+
```
237253

238-
</TabItem>
239-
<TabItem value="pnpm" label="pnpm">
254+
</TabItem>
255+
<TabItem value="pnpm" label="pnpm">
240256

241-
```bash
242-
pnpm dev
243-
```
257+
```bash
258+
pnpm dev
259+
```
244260

245-
</TabItem>
246-
</Tabs>
261+
</TabItem>
262+
</Tabs>
247263

248264
You should see the VoltAgent server startup message, including a link to the Developer Console:
249265

@@ -279,5 +295,3 @@ Observe the responses. They should be directly based on the content from the `do
279295
As you can see, implementing a basic RAG system with VoltAgent is quite straightforward. By creating a custom `BaseRetriever` and attaching it to an `Agent`, I could quickly build a chatbot grounded in specific external knowledge.
280296

281297
This simple example uses hardcoded data, but you could easily adapt the `KnowledgeBaseRetriever` to fetch data from a real database, API, or vector store for much more powerful applications. RAG opens up a lot of possibilities for creating smarter, more knowledgeable AI agents, and I think VoltAgent makes it significantly easier to get started.
282-
283-
Happy building!

website/src/components/blog-widgets/RetrieverMethodHelper/index.tsx

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type React from "react";
22
import { useState } from "react";
3-
import styles from "./styles.module.css"; // Assuming shared styles or create new ones
3+
import clsx from "clsx"; // Import clsx for conditional classes
44

55
type Recommendation = {
66
method: "Direct Attachment" | "Tool" | "Unsure";
@@ -91,48 +91,76 @@ const RetrieverMethodHelper: React.FC = () => {
9191
};
9292

9393
return (
94-
<div className={styles.widgetContainer}>
95-
<h4>Help Me Choose: Retriever Method</h4>
94+
<div className="border border-solid border-emerald-500 rounded-lg p-5 mb-6 bg-gray-800 shadow-lg">
95+
<h4 className="mt-0 mb-6 text-lg font-semibold text-emerald-400 text-center">
96+
Help Me Choose: Retriever Method
97+
</h4>
9698

9799
{/* Frequency Question */}
98-
<div className={styles.questionBlock}>
99-
<p className={styles.questionLabel}>
100+
<div className="mb-6">
101+
<p className="block mb-2 font-medium text-white text-sm">
100102
How often will your agent need the retrieved information?
101103
</p>
102-
<div className={styles.radioGroup}>
104+
<div className="flex flex-col gap-3">
103105
{frequencyOptions.map((option) => (
104-
<label key={option.value} className={styles.radioOption}>
106+
<label
107+
key={option.value}
108+
className={clsx(
109+
"flex items-center cursor-pointer p-3 rounded-md border-solid border bg-gray-800 transition-colors duration-200 text-white",
110+
"hover:border-emerald-400/50 hover:bg-gray-700", // Hover state
111+
frequency === option.value
112+
? "border-emerald-500 bg-emerald-900/30" // Checked state
113+
: "border-gray-700", // Default state
114+
)}
115+
>
105116
<input
106117
type="radio"
107118
name="frequency"
108119
value={option.value}
109120
checked={frequency === option.value}
110121
onChange={() => handleFrequencyChange(option.value)}
111-
className={styles.radioInput}
122+
className="mr-3 accent-emerald-500" // Input specific styles
112123
/>
113-
<span className={styles.radioLabel}>{option.label}</span>
124+
<span className="flex-grow text-sm">
125+
{" "}
126+
{/* Label text */}
127+
{option.label}
128+
</span>
114129
</label>
115130
))}
116131
</div>
117132
</div>
118133

119134
{/* Agent Decision Question */}
120-
<div className={styles.questionBlock}>
121-
<p className={styles.questionLabel}>
135+
<div className="mb-6">
136+
<p className="block mb-2 font-medium text-white text-sm">
122137
How important is it for the agent (LLM) to *decide* when to retrieve?
123138
</p>
124-
<div className={styles.radioGroup}>
139+
<div className="flex flex-col gap-3">
125140
{agentDecisionOptions.map((option) => (
126-
<label key={option.value} className={styles.radioOption}>
141+
<label
142+
key={option.value}
143+
className={clsx(
144+
"flex items-center cursor-pointer p-3 rounded-md border-solid border bg-gray-800 transition-colors duration-200 text-white",
145+
"hover:border-emerald-400/50 hover:bg-gray-700", // Hover state
146+
agentDecision === option.value
147+
? "border-emerald-500 bg-emerald-900/30" // Checked state
148+
: "border-gray-700", // Default state
149+
)}
150+
>
127151
<input
128152
type="radio"
129153
name="agentDecision"
130154
value={option.value}
131155
checked={agentDecision === option.value}
132156
onChange={() => handleAgentDecisionChange(option.value)}
133-
className={styles.radioInput}
157+
className="mr-3 accent-emerald-500" // Input specific styles
134158
/>
135-
<span className={styles.radioLabel}>{option.label}</span>
159+
<span className="flex-grow text-sm">
160+
{" "}
161+
{/* Label text */}
162+
{option.label}
163+
</span>
136164
</label>
137165
))}
138166
</div>
@@ -141,18 +169,43 @@ const RetrieverMethodHelper: React.FC = () => {
141169
{/* Recommendation Box */}
142170
{recommendation && (
143171
<div
144-
className={styles.recommendationBox}
145-
data-recommendation-type={recommendation.method.toLowerCase()}
172+
// Using similar styling as LlmChoiceHelper recommendation box
173+
// Added a dynamic border color based on the recommendation type for subtle distinction
174+
className={clsx(
175+
"mt-6 p-4 rounded-md shadow-sm border",
176+
recommendation.method === "Unsure"
177+
? "bg-yellow-900/60 border-yellow-500/50" // Yellow theme for unsure
178+
: "bg-emerald-900/60 border-emerald-500/50", // Emerald theme for others
179+
)}
146180
>
147-
<h5>Recommendation: {recommendation.method}</h5>
148-
<p>{recommendation.reasoning}</p>
181+
<h5
182+
className={clsx(
183+
"mt-0 mb-2 text-base font-medium",
184+
recommendation.method === "Unsure"
185+
? "text-yellow-400" // Yellow title for unsure
186+
: "text-emerald-400", // Emerald title for others
187+
)}
188+
>
189+
Recommendation: {recommendation.method}
190+
</h5>
191+
<p
192+
className={clsx(
193+
"mb-2 text-sm", // Slightly smaller text for reasoning
194+
recommendation.method === "Unsure"
195+
? "text-yellow-100" // Lighter yellow text for unsure
196+
: "text-emerald-100", // Lighter emerald text for others
197+
)}
198+
>
199+
{recommendation.reasoning}
200+
</p>
149201
{recommendation.method !== "Unsure" && (
150-
<p>
202+
<p className="text-sm text-emerald-100">
151203
Learn more in the{" "}
152204
<a
153205
href="/docs/agents/retriever"
154206
target="_blank"
155207
rel="noopener noreferrer"
208+
className="text-emerald-400 hover:underline" // Link styling
156209
>
157210
Retriever Documentation
158211
</a>

0 commit comments

Comments
 (0)