title |
---|
Next.js |
Create a new Next.js application and install @upstash/rag-chat
package.
npx create-next-app@latest
cd my-app
npm install @upstash/rag-chat
Create a Redis database using Upstash Console or Upstash CLI and copy the UPSTASH_REDIS_REST_URL
and UPSTASH_REDIS_REST_TOKEN
into your .env
file.
UPSTASH_REDIS_REST_URL=<YOUR_URL>
UPSTASH_REDIS_REST_TOKEN=<YOUR_TOKEN>
Create a Vector index using Upstash Console or Upstash CLI and copy the UPSTASH_VECTOR_REST_URL
and UPSTASH_VECTOR_REST_TOKEN
into your .env
file.
UPSTASH_VECTOR_REST_URL=<YOUR_URL>
UPSTASH_VECTOR_REST_TOKEN=<YOUR_TOKEN>
Navigate to QStash Console and copy the QSTASH_TOKEN
into your .env
file.
QSTASH_TOKEN=<YOUR_TOKEN>
Create a middleware in /app/middleware.ts
to generate a session ID cookie. This cookie will be used to track the user's chat session.
import { NextRequest, NextResponse } from "next/server";
export function middleware(req: NextRequest) {
const res = NextResponse.next();
const cookie = req.cookies.get("sessionId");
if (!cookie) {
res.cookies.set("sessionId", crypto.randomUUID());
}
return res;
}
We will create a RAG Chat instance in /app/lib/rag-chat.ts
to later use in our API route and Home page.
import { RAGChat, upstash } from "@upstash/rag-chat";
import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
export const ragChat = new RAGChat({
model: upstash("meta-llama/Meta-Llama-3-8B-Instruct"),
redis: redis,
});
Using the RAG Chat instance we created, we can now create a chat streaming API route in /app/api/chat-stream/route.ts
.
import { ragChat } from "@/app/lib/rag-chat";
import { aiUseChatAdapter } from "@upstash/rag-chat/nextjs";
import { NextRequest } from "next/server";
export const POST = async (req: NextRequest) => {
const { messages, sessionId } = await req.json();
const lastMessage = messages[messages.length - 1].content;
const response = await ragChat.chat(lastMessage, {
streaming: true,
sessionId,
});
return aiUseChatAdapter(response);
};
We can now create a chat component in /app/components/chat.tsx
using the chat streaming API route we created.
"use client";
import { useChat, Message } from "ai/react";
export const Chat = ({
sessionId,
initialMessages,
}: {
sessionId: string;
initialMessages: Message[];
}) => {
const { messages, handleInputChange, handleSubmit, input, setInput } =
useChat({
api: "/api/chat-stream",
body: { sessionId },
initialMessages,
});
return (
<div>
<div className="flex h-[calc(100vh-64px)] flex-col overflow-y-auto items-center">
{messages.length ? (
messages.map((message, i) => (
<div className="w-[60vw] flex flex-row gap-3 p-6" key={i}>
<div className="min-w-12">
{message.role === "user" ? "User" : "Bot"}
</div>
<p className="text-sm font-normal text-gray-900">
{message.content}
</p>
</div>
))
) : (
<div className="text-zinc-500 text-sm pt-6">
Ask your first question to get started.
</div>
)}
</div>
<form onSubmit={handleSubmit} className="relative">
<div className="flex flex-row gap-2 p-3 h-16 items-center">
<input
onChange={handleInputChange}
value={input}
onKeyDown={(e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSubmit();
setInput("");
}
}}
placeholder="Enter your question..."
className="border rounded-xl w-full py-1 px-3"
/>
<button type="submit" className="border rounded-xl py-1 px-3">
Send
</button>
</div>
</form>
</div>
);
};
Update /app/page.tsx
using the Chat component we created.
import { Chat } from "./components/chat";
import { cookies } from "next/headers";
import { ragChat } from "@/app/lib/rag-chat";
export default async function Home() {
const sessionId = cookies().get("sessionId")?.value;
const initialMessages = await ragChat.history.getMessages({
amount: 10,
sessionId,
});
return <Chat sessionId={sessionId!} initialMessages={initialMessages} />;
}
Run the app locally with npm run dev
, check http://localhost:3000/
Deploy your app with vercel