Let's create a simple chat interface that allows users to send messages to the assistant and receive responses. You will integrate the useAssistant
hook from ai/react
to stream the messages and status.
'use chat';
import { Message, useAssistant } from 'ai/react';
export default function Page() { const { status, messages, input, submitMessage, handleInputChange } = useAssistant({ api: '/api/assistant' });
return ( <div className="flex flex-col gap-2"> <div className="p-2">status: {status}</div>
<div className="flex flex-col p-2 gap-2"> {messages.map((message: Message) => ( <div key={message.id} className="flex flex-row gap-2"> <div className="w-24 text-zinc-500">{`${message.role}: `}</div> <div className="w-full">{message.content}</div> </div> ))} </div>
<form onSubmit={submitMessage} className="fixed bottom-0 p-2 w-full"> <input disabled={status !== 'awaiting_message'} value={input} onChange={handleInputChange} className="bg-zinc-100 w-full p-2" /> </form> </div> );}
Next, you will create an API route for api/assistant
to handle the assistant's messages and responses. You will use the AssistantResponse
function from ai
to stream the assistant's responses back to the useAssistant
hook on the client.
import OpenAI from 'openai';import { AssistantResponse } from 'ai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY || '',});
export async function POST(req: Request) { const input: { threadId: string | null; message: string; } = await req.json();
const threadId = input.threadId ?? (await openai.beta.threads.create({})).id;
const createdMessage = await openai.beta.threads.messages.create(threadId, { role: 'user', content: input.message, });
return AssistantResponse( { threadId, messageId: createdMessage.id }, async ({ forwardStream }) => { const runStream = openai.beta.threads.runs.stream(threadId, { assistant_id: process.env.ASSISTANT_ID ?? (() => { throw new Error('ASSISTANT_ID environment is not set'); })(), });
await forwardStream(runStream); }, );}