Open
Description
Description
- npx create-next-app
- npm i zod ai @ai-sdk/openai
- copy from docs, /app/page.tsx and /api/chat/route.ts
- npm run dev
copy in code from docs here: https://sdk.vercel.ai/cookbook/next/call-tools
The source files are pasted below (and are identical in the GitHub repo)
This is the broken branch with the issue: https://github.com/pkellner/ai-sdk-chat-issue1/tree/bug-broken-directly-from-ai-sdk-docs
This is the fixed branch with the chat app working as expected: https://github.com/pkellner/ai-sdk-chat-issue1/tree/bug-fixed-by-minor-div-changes
into /src/app/page.tsx:
'use client';
import { useChat } from 'ai/react';
export default function Page() {
const { messages, input, setInput, append } = useChat({
api: '/api/chat',
maxSteps: 2,
});
return (
<div>
<input
value={input}
onChange={event => {
setInput(event.target.value);
}}
onKeyDown={async event => {
if (event.key === 'Enter') {
append({ content: input, role: 'user' });
}
}}
/>
{messages.map((message, index) => (
<div key={index}>{message.content}</div>
))}
</div>
);
}
and /src/app/api/chat/route.ts
import { ToolInvocation, streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
interface Message {
role: 'user' | 'assistant';
content: string;
toolInvocations?: ToolInvocation[];
}
export async function POST(req: Request) {
const { messages }: { messages: Message[] } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant.',
messages,
tools: {
getWeather: {
description: 'Get the weather for a location',
parameters: 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}!`;
},
},
},
});
return result.toDataStreamResponse();
}
Get blank page when running npm run dev
To Fix, I can give page.tsx to ChatGPT and say fix for blank render, and it gives me this:
'use client';
import { ToolInvocation } from 'ai';
import { Message, useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, addToolResult } =
useChat({
maxSteps: 5,
async onToolCall({ toolCall }) {
if (toolCall.toolName === 'getLocation') {
const cities = ['New York', 'Los Angeles', 'Chicago', 'San Francisco'];
return cities[Math.floor(Math.random() * cities.length)];
}
},
});
return (
<div style={{ padding: '1rem' }}>
{messages.length === 0 ? (
<p>No messages yet. Type something below!</p>
) : (
messages.map((m: Message) => (
<div key={m.id} style={{ marginBottom: '1rem' }}>
<strong>{m.role}:</strong> {m.content}
{m.toolInvocations?.map((toolInvocation: ToolInvocation) => {
const toolCallId = toolInvocation.toolCallId;
const addResult = (result: string) =>
addToolResult({ toolCallId, result });
if (toolInvocation.toolName === 'askForConfirmation') {
return (
<div key={toolCallId}>
{toolInvocation.args.message}
<div>
{'result' in toolInvocation ? (
<b>{toolInvocation.result}</b>
) : (
<>
<button onClick={() => addResult('Yes')}>Yes</button>
<button onClick={() => addResult('No')}>No</button>
</>
)}
</div>
</div>
);
}
return 'result' in toolInvocation ? (
<div key={toolCallId}>
Tool call {toolInvocation.toolName}: {toolInvocation.result}
</div>
) : (
<div key={toolCallId}>Calling {toolInvocation.toolName}...</div>
);
})}
</div>
))
)}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
</div>
);
}