Developing an AI-Powered Chatbot with Vercel AI SDK
Prerequisites
Step 1: Install the Required npm Packages
Run the following commands to install necessary packages:
npm install groq-sdk
npm install ai
npm install react-markdown
Setting Up the Environment Variables
Then, we need to setup environment variable in .env file. You can get GROQ API Key from here
GROQ_API_KEY="GROQ_API_KEY"
Step 2: Create the Chatbot Components
1. ChatHeader Component
Create a chat-header.tsx file with the following code:
import React from "react";
const ChatHeader = () => {
return (
<div className="h-[70px] p-3 border">
<h3>AI ChatBot</h3>
<h4>Basic chatbot example with Vercel AI SDK</h4>
</div>
);
};
export default ChatHeader;
2. ChatInput Component
Create a chat-input.tsx file.
The ChatInput component is used to renders a input from for user text input and handles input changes and form submission through provided handler functions.
import React, { ChangeEvent, FormEvent } from "react";
type ChatInputProps = {
handleInputChange: (e: ChangeEvent<HTMLInputElement>) => void;
input: string;
className?: string;
handleSubmit: (e: FormEvent<HTMLFormElement>) => void;
};
const ChatInput = ({
handleInputChange,
handleSubmit,
input,
}: ChatInputProps) => {
return (
<div className="p-3 flex justify-center items-center border">
<form className="w-full" onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
className="p-2 rounded-md outline-none border-none w-full text-foreground"
placeholder="write here..."
/>
</form>
</div>
);
};
export default ChatInput;
3. ChatMessage Component
Create a chat-message.tsx file.
The ChatMessage component is used to displays a chat message with conditional formatting based on whether the message is from the user or assistant and also using react-markdown for message content rendering.
领英推荐
import React from "react";
import Markdown from "react-markdown";
type ChatMessageProps = {
message: Message;
isUserMessage: boolean;
};
const ChatMessage = ({ message, isUserMessage }: ChatMessageProps) => {
return (
<div className="chat-message" key={`${message.id}-${message.id}`}>
<div className={`flex items-end ${isUserMessage ? "justify-end" : ""}`}>
<div className={`flex flex-col space-y-3 text-sm max-w-xs mx-3 overflow-x-hidden ${isUserMessage ? "order-1 items-end" : "order-2 items-start"}`}>
<div className={`px-4 py-3 rounded-lg ${isUserMessage ? "bg-blue-500 text-white" : "bg-gray-100 text-gray-900"}`}>
<Markdown>{message.content}</Markdown>
</div>
</div>
</div>
</div>
);
};
export default ChatMessage;
4. ChatMessages Component
Create a chat-messages.tsx file.
This component will display a list of chat messages. The Vercel AI SDK will handle user messages by synchronizing with the input component.
"use client";
import React from "react";
import ChatMessage from "@/components/chat-message";
type ChatMessagesProps = {
messages: Message[];
className?: string;
};
const ChatMessages = ({ messages, className }: ChatMessagesProps) => {
const inverseMessages = [...messages].reverse();
return (
<div className={`flex flex-col-reverse gap-3 overflow-y-auto flex-grow py-3 no-scrollbar ${className}`}>
<div className="flex-1 flex-grow" />
{inverseMessages.map((message) => (
<ChatMessage key={message.id} message={message} isUserMessage={message.role === "user"} />
))}
</div>
);
};
export default ChatMessages;
5. ChatWidget Component
Create a chat-widget.tsx file.
This component will integrate all previously defined components and handle the chatbot's logic.
"use client";
import React, { useState } from "react";
import ChatHeader from "@/components/chat-header";
import ChatInput from "@/components/chat-input";
import ChatMessages from "@/components/chat-messages";
import { useChat } from "ai/react";
import Image from "next/image";
const ChatWidget = () => {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: "/api/chat",
});
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);
return (
<div className="fixed bottom-10 right-10">
<div className="flex flex-col items-end">
{isOpen && (
<div className="w-[350px] flex flex-col shadow-md rounded-lg h-[600px] max-h-[70vh]">
<ChatHeader />
<div className="flex-1 border overflow-auto no-scrollbar">
<ChatMessages messages={messages} />
</div>
<ChatInput handleInputChange={handleInputChange} input={input} handleSubmit={handleSubmit} />
</div>
)}
<button onClick={toggle} className="mt-6 flex justify-center items-center cursor-pointer hover:scale-95 animate-in">
<Image src="/chatbot.svg" alt="chatbot icon" height={60} width={60} />
</button>
</div>
</div>
);
};
export default ChatWidget;
6. Add ChatWidget into Layout
After creating the ChatWidget component we need to set it on layout.tsx file in root directory for ensuring it that will appears on every page of your application:. Here is an example of it.
<body className={inter.className}>
<ChatWidget />
<main>
{children}
</main>
</body>
Step 3: Create the Route for the Chat API
Create a route.ts file in the app/api/chat folder:
This file sets up an API route that takes user messages, sends them to a GROQ AI model and returns a stream response.
import { streamText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
const groq = createOpenAI({
baseURL: "<https://api.groq.com/openai/v1>",
apiKey: process.env.GROQ_API_KEY,
});
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: groq("llama3-8b-8192"),
system: "You are a helpful assistant. Give all your responses in markdown format.",
messages,
});
return result.toAIStreamResponse();
}
We can update the system message to modify how the LLM respond.
system: "You are a helpful assistant. Give all your responses in markdown format.",
I hope you've successfully built the simple AI-powered chatbot using the Vercel AI SDK, React Markdown, and GROQ API. Check out my portfolio website at shubhamkashyap.in for more articles and code snippets.