Call Tools
Some models allow developers to provide a list of tools that can be called at any time during a generation. This is useful for extending the capabilites of a language model to either use logic or data to interact with systems external to the model.
Client
Let's create a React component that imports the useChat
hook from the @ai-sdk/react
module. The useChat
hook will call the /api/chat
endpoint when the user sends a message. The endpoint will generate the assistant's response based on the conversation history and stream it to the client. If the assistant responds with a tool call, the hook will automatically display them as well.
'use client';
import { useChat } from '@ai-sdk/react';import { DefaultChatTransport } from 'ai';import { useState } from 'react';import type { ChatMessage } from './api/chat/route';
export default function Page() { const [input, setInput] = useState('');
const { messages, sendMessage } = useChat<ChatMessage>({ transport: new DefaultChatTransport({ api: '/api/chat', }), });
return ( <div> <input className="border" value={input} onChange={event => { setInput(event.target.value); }} onKeyDown={async event => { if (event.key === 'Enter') { sendMessage({ text: input, }); setInput(''); } }} />
{messages.map((message, index) => ( <div key={index}> {message.parts.map(part => { switch (part.type) { case 'text': return <div key={`${message.id}-text`}>{part.text}</div>; case 'tool-getWeather': return ( <div key={`${message.id}-weather`}> {JSON.stringify(part, null, 2)} </div> ); } })} </div> ))} </div> );}
Server
You will create a new route at /api/chat
that will use the streamText
function from the ai
module to generate the assistant's response based on the conversation history.
You will use the tools
parameter to specify a tool called celsiusToFahrenheit
that will convert a user given value in celsius to fahrenheit.
You will also use zod to specify the schema for the celsiusToFahrenheit
function's parameters.
import { openai } from '@ai-sdk/openai';import { type InferUITools, type ToolSet, type UIDataTypes, type UIMessage, convertToModelMessages, stepCountIs, streamText, tool,} from 'ai';import { z } from 'zod';
const tools: ToolSet = { getWeather: tool({ description: 'Get the weather for a location', inputSchema: z.object({ city: z.string().describe('The city to get the weather for'), unit: z .enum(['C', 'F']) .describe('The unit to display the temperature in'), }), execute: async ({ city, unit }) => { const weather = { value: 24, description: 'Sunny', };
return `It is currently ${weather.value}°${unit} and ${weather.description} in ${city}!`; }, }),};
export type ChatTools = InferUITools<typeof tools>;
export type ChatMessage = UIMessage<never, UIDataTypes, ChatTools>;
export async function POST(req: Request) { const { messages }: { messages: ChatMessage[] } = await req.json();
const result = streamText({ model: openai('gpt-4o'), system: 'You are a helpful assistant.', messages: convertToModelMessages(messages), stopWhen: stepCountIs(5), tools, });
return result.toUIMessageStreamResponse();}