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.
Let's create a simple conversation between a user and model and place a button that will call continueConversation
.
'use client';
import { useState } from 'react';import { Message, continueConversation } from './actions';
// Allow streaming responses up to 30 secondsexport const maxDuration = 30;
export default function Home() { const [conversation, setConversation] = useState<Message[]>([]); const [input, setInput] = useState<string>('');
return ( <div> <div> {conversation.map((message, index) => ( <div key={index}> {message.role}: {message.content} </div> ))} </div>
<div> <input type="text" value={input} onChange={event => { setInput(event.target.value); }} /> <button onClick={async () => { const { messages } = await continueConversation([ ...conversation, { role: 'user', content: input }, ]);
setConversation(messages); }} > Send Message </button> </div> </div> );}
Now, let's implement the continueConversation
action that uses generateText
to generate a response to the user's question. We will use the tools
parameter to specify our own function called celsiusToFahrenheit
that will convert a user given value in celsius to fahrenheit.
We will use zod to specify the schema for the celsiusToFahrenheit
function's parameters.
'use server';
import { generateText } from 'ai';import { openai } from '@ai-sdk/openai';import { z } from 'zod';
export interface Message { role: 'user' | 'assistant'; content: string;}
export async function continueConversation(history: Message[]) { 'use server';
const { text, toolResults } = await generateText({ model: openai('gpt-3.5-turbo'), system: 'You are a friendly assistant!', messages: history, tools: { celsiusToFahrenheit: { description: 'Converts celsius to fahrenheit', parameters: z.object({ value: z.string().describe('The value in celsius'), }), execute: async ({ value }) => { const celsius = parseFloat(value); const fahrenheit = celsius * (9 / 5) + 32; return `${celsius}°C is ${fahrenheit.toFixed(2)}°F`; }, }, }, });
return { messages: [ ...history, { role: 'assistant' as const, content: text || toolResults.map(toolResult => toolResult.result).join('\n'), }, ], };}