-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix (ai/ui): tool call streaming (#2345)
- Loading branch information
Showing
7 changed files
with
141 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@ai-sdk/ui-utils': patch | ||
'@ai-sdk/react': patch | ||
--- | ||
|
||
fix (ai/ui): tool call streaming |
51 changes: 51 additions & 0 deletions
51
examples/next-openai/app/api/use-chat-streaming-tool-calls/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { openai } from '@ai-sdk/openai'; | ||
import { convertToCoreMessages, streamText } from 'ai'; | ||
import { z } from 'zod'; | ||
|
||
// Allow streaming responses up to 30 seconds | ||
export const maxDuration = 30; | ||
|
||
export async function POST(req: Request) { | ||
const { messages } = await req.json(); | ||
|
||
const result = await streamText({ | ||
model: openai('gpt-4-turbo'), | ||
messages: convertToCoreMessages(messages), | ||
experimental_toolCallStreaming: true, | ||
system: | ||
'You are a helpful assistant that answers questions about the weather in a given city.' + | ||
'You use the showWeatherInformation tool to show the weather information to the user instead of talking about it.', | ||
tools: { | ||
// server-side tool with execute function: | ||
getWeatherInformation: { | ||
description: 'show the weather in a given city to the user', | ||
parameters: z.object({ city: z.string() }), | ||
execute: async ({}: { city: string }) => { | ||
const weatherOptions = ['sunny', 'cloudy', 'rainy', 'snowy', 'windy']; | ||
return { | ||
weather: | ||
weatherOptions[Math.floor(Math.random() * weatherOptions.length)], | ||
temperature: Math.floor(Math.random() * 50 - 10), | ||
}; | ||
}, | ||
}, | ||
// client-side tool that displays whether information to the user: | ||
showWeatherInformation: { | ||
description: | ||
'Show the weather information to the user. Always use this tool to tell weather information to the user.', | ||
parameters: z.object({ | ||
city: z.string(), | ||
weather: z.string(), | ||
temperature: z.number(), | ||
typicalWeather: z | ||
.string() | ||
.describe( | ||
'2-3 sentences about the typical weather in the city during spring.', | ||
), | ||
}), | ||
}, | ||
}, | ||
}); | ||
|
||
return result.toAIStreamResponse(); | ||
} |
69 changes: 69 additions & 0 deletions
69
examples/next-openai/app/use-chat-streaming-tool-calls/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
'use client'; | ||
|
||
import { ToolInvocation } from 'ai'; | ||
import { Message, useChat } from 'ai/react'; | ||
|
||
export default function Chat() { | ||
const { messages, input, handleInputChange, handleSubmit } = useChat({ | ||
api: '/api/use-chat-streaming-tool-calls', | ||
maxToolRoundtrips: 5, | ||
|
||
// run client-side tools that are automatically executed: | ||
async onToolCall({ toolCall }) { | ||
if (toolCall.toolName === 'showWeatherInformation') { | ||
// display tool. add tool result that informs the llm that the tool was executed. | ||
return 'Weather information was shown to the user.'; | ||
} | ||
}, | ||
}); | ||
|
||
// used to only render the role when it changes: | ||
let lastRole: string | undefined = undefined; | ||
|
||
return ( | ||
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch"> | ||
{messages?.map((m: Message) => { | ||
const isNewRole = m.role !== lastRole; | ||
lastRole = m.role; | ||
|
||
return ( | ||
<div key={m.id} className="whitespace-pre-wrap"> | ||
{isNewRole && <strong>{`${m.role}: `}</strong>} | ||
{m.content} | ||
{m.toolInvocations?.map((toolInvocation: ToolInvocation) => { | ||
const { toolCallId, args } = toolInvocation; | ||
|
||
// render display weather tool calls: | ||
if (toolInvocation.toolName === 'showWeatherInformation') { | ||
return ( | ||
<div | ||
key={toolCallId} | ||
className="p-4 my-2 text-gray-500 border border-gray-300 rounded" | ||
> | ||
<h4 className="mb-2">{args?.city ?? ''}</h4> | ||
<div className="flex flex-col gap-2"> | ||
<div className="flex gap-2"> | ||
{args?.weather && <b>{args.weather}</b>} | ||
{args?.temperature && <b>{args.temperature} °C</b>} | ||
</div> | ||
{args?.typicalWeather && <div>{args.typicalWeather}</div>} | ||
</div> | ||
</div> | ||
); | ||
} | ||
})} | ||
</div> | ||
); | ||
})} | ||
|
||
<form onSubmit={handleSubmit}> | ||
<input | ||
className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl" | ||
value={input} | ||
placeholder="Say something..." | ||
onChange={handleInputChange} | ||
/> | ||
</form> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.