From 9fb3b4d61b5672a88d82176b7a2994048b881d52 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 6 Jun 2024 20:34:10 +0300 Subject: [PATCH] Add assistant examples to next pages (#1873) --- .../01-next-app/06-assistants/index.mdx | 6 +- .../01-stream-assistant-responses.mdx | 85 +++++++++++ ...-stream-assistant-responses-with-tools.mdx | 142 ++++++++++++++++++ .../02-next-pages/15-assistants/index.mdx | 25 +++ 4 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 content/examples/02-next-pages/15-assistants/01-stream-assistant-responses.mdx create mode 100644 content/examples/02-next-pages/15-assistants/05-stream-assistant-responses-with-tools.mdx create mode 100644 content/examples/02-next-pages/15-assistants/index.mdx diff --git a/content/examples/01-next-app/06-assistants/index.mdx b/content/examples/01-next-app/06-assistants/index.mdx index 6fc85c7b13ae..994e698631c3 100644 --- a/content/examples/01-next-app/06-assistants/index.mdx +++ b/content/examples/01-next-app/06-assistants/index.mdx @@ -1,8 +1,8 @@ --- -title: Assistants -description: Learn to use the assistant API using the Vercel AI SDK in your Next.js application +title: OpenAI Assistants +description: Learn to use the OpenAI Assistant API using the Vercel AI SDK in your Next.js application --- # Assistants -In this section, you will learn to use OpenAI's assistant API along with `ai/rsc` functions. +In this section, you will learn to use OpenAI's Assistant API along with `ai/rsc` functions. diff --git a/content/examples/02-next-pages/15-assistants/01-stream-assistant-responses.mdx b/content/examples/02-next-pages/15-assistants/01-stream-assistant-responses.mdx new file mode 100644 index 000000000000..5c801a2d31b7 --- /dev/null +++ b/content/examples/02-next-pages/15-assistants/01-stream-assistant-responses.mdx @@ -0,0 +1,85 @@ +--- +title: Stream Assistant Responses +description: Learn to stream assistant responses using the Vercel AI SDK in your Next.js Pages Router application +--- + +# Stream Assistant Responses + +## Client + +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. + +```tsx filename='pages/index.tsx' +import { Message, useAssistant } from 'ai/react'; + +export default function Page() { + const { status, messages, input, submitMessage, handleInputChange } = + useAssistant({ api: '/api/assistant' }); + + return ( +
+
status: {status}
+ +
+ {messages.map((message: Message) => ( +
+
{`${message.role}: `}
+
{message.content}
+
+ ))} +
+ +
+ +
+
+ ); +} +``` + +## Server + +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. + +```tsx filename='app/api/assistant/route.ts' +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); + }, + ); +} +``` diff --git a/content/examples/02-next-pages/15-assistants/05-stream-assistant-responses-with-tools.mdx b/content/examples/02-next-pages/15-assistants/05-stream-assistant-responses-with-tools.mdx new file mode 100644 index 000000000000..8bdb5c8fc85d --- /dev/null +++ b/content/examples/02-next-pages/15-assistants/05-stream-assistant-responses-with-tools.mdx @@ -0,0 +1,142 @@ +--- +title: Stream Assistant Responses with Tools +description: Learn to stream assistant responses with tools using the Vercel AI SDK in your Next.js Pages Router application +--- + +# Stream Assistant Responses with Tools + +Let's create a simple chat interface that allows users to send messages to the assistant and receive responses and give it the ability to use tools. You will integrate the `useAssistant` hook from `ai/react` to stream the messages and status. + +You will need to provide the list of tools on the OpenAI [Assistant Dashboard](https://platform.openai.com/assistants). You can use the following schema to create a tool to convert celsius to fahrenheit. + +```json +{ + "name": "celsiusToFahrenheit", + "description": "convert celsius to fahrenheit.", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "number", + "description": "the value in celsius." + } + }, + "required": ["value"] + } +} +``` + +## Client + +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. + +```tsx filename='pages/index.tsx' +import { Message, useAssistant } from 'ai/react'; + +export default function Page() { + const { status, messages, input, submitMessage, handleInputChange } = + useAssistant({ api: '/api/assistant' }); + + return ( +
+
status: {status}
+ +
+ {messages.map((message: Message) => ( +
+
{`${message.role}: `}
+
{message.content}
+
+ ))} +
+ +
+ +
+
+ ); +} +``` + +## Server + +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. + +```tsx filename='app/api/assistant/route.ts' +import { AssistantResponse } from 'ai'; +import OpenAI from 'openai'; + +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 is not set'); + })(), + }); + + let runResult = await forwardStream(runStream); + + while ( + runResult?.status === 'requires_action' && + runResult.required_action?.type === 'submit_tool_outputs' + ) { + const tool_outputs = + runResult.required_action.submit_tool_outputs.tool_calls.map( + (toolCall: any) => { + const parameters = JSON.parse(toolCall.function.arguments); + + switch (toolCall.function.name) { + case 'celsiusToFahrenheit': + const celsius = parseFloat(parameters.value); + const fahrenheit = celsius * (9 / 5) + 32; + + return { + tool_call_id: toolCall.id, + output: `${celsius}°C is ${fahrenheit.toFixed(2)}°F`, + }; + + default: + throw new Error( + `Unknown tool call function: ${toolCall.function.name}`, + ); + } + }, + ); + + runResult = await forwardStream( + openai.beta.threads.runs.submitToolOutputsStream( + threadId, + runResult.id, + { tool_outputs }, + ), + ); + } + }, + ); +} +``` diff --git a/content/examples/02-next-pages/15-assistants/index.mdx b/content/examples/02-next-pages/15-assistants/index.mdx new file mode 100644 index 000000000000..427e6523bd2a --- /dev/null +++ b/content/examples/02-next-pages/15-assistants/index.mdx @@ -0,0 +1,25 @@ +--- +title: OpenAI Assistants +description: Learn to use the OpenAI Assistant API using the Vercel AI SDK in your Next.js Pages Router application +--- + +# Assistants + +In this section, you will learn to use OpenAI's Assistant API along with the `useAssistant` hook from `ai/react`. + +