Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat example with tools in Docs broken #4229

Open
pkellner opened this issue Dec 30, 2024 · 0 comments
Open

Chat example with tools in Docs broken #4229

pkellner opened this issue Dec 30, 2024 · 0 comments
Labels
bug Something isn't working docs Improvements or additions to documentation

Comments

@pkellner
Copy link

pkellner commented Dec 30, 2024

Description

  1. npx create-next-app
  2. npm i zod ai @ai-sdk/openai
  3. copy from docs, /app/page.tsx and /api/chat/route.ts
  4. 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>
  );
}
@pkellner pkellner added the bug Something isn't working label Dec 30, 2024
@lgrammel lgrammel added the docs Improvements or additions to documentation label Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working docs Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants