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

Client side tool calling not working #4283

Open
focux opened this issue Jan 5, 2025 · 2 comments
Open

Client side tool calling not working #4283

focux opened this issue Jan 5, 2025 · 2 comments
Labels
ai/provider ai/ui bug Something isn't working

Comments

@focux
Copy link

focux commented Jan 5, 2025

Description

When using anthropic provider with Haiku 3.5, and calling addToolResult from the client, I'm getting the following error:

APICallError [AI_APICallError]: Your API request included an `assistant` message in the final position, which would pre-fill the `assistant` response. When using tools, pre-filling the `assistant` response is not supported.

Code example

'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,

      // run client-side tools that are automatically executed:
      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 (
    <>
      {messages?.map((m: Message) => (
        <div key={m.id}>
          <strong>{m.role}:</strong>
          {m.content}
          {m.toolInvocations?.map((toolInvocation: ToolInvocation) => {
            const toolCallId = toolInvocation.toolCallId;
            const addResult = (result: string) =>
              addToolResult({ toolCallId, result });

            // render confirmation tool (client-side tool with user interaction)
            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>
              );
            }

            // other tools:
            return 'result' in toolInvocation ? (
              <div key={toolCallId}>
                Tool call {`${toolInvocation.toolName}: `}
                {toolInvocation.result}
              </div>
            ) : (
              <div key={toolCallId}>Calling {toolInvocation.toolName}...</div>
            );
          })}
          <br />
        </div>
      ))}

      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
      </form>
    </>
  );
}

AI provider

@ai-sdk/anthropic v1.0.6

Additional context

ai v4.0.26

@focux focux added the bug Something isn't working label Jan 5, 2025
@nicoalbanese
Copy link
Contributor

Hey! Can you share your API route too?

@focux
Copy link
Author

focux commented Jan 6, 2025

Sure, this is how the route looks. I'm using Hono btw.

routes.openapi("...", async (c) => {
  const { messages, chatId } = c.req.valid("json");

  const anthropic = createAnthropic({
    apiKey: c.env.ANTHROPIC_API_KEY,
    baseURL:
      "https://gateway.ai.cloudflare.com/v1/[redacted]/[redacted]/anthropic",
  });
  const model = anthropic("claude-3-5-haiku-latest");

  const dataStream = createDataStream({
    execute: async (dataStreamWriter) => {
      const result = streamText({
        model,
        messages,
        tools: {
          askUserToMakeAChoice: tool({
            description:
              "Ask the user to choose an option from a list of options",
            parameters: z.object({
              options: z
                .string()
                .array()
                .describe("The options to present to the user"),
            }),
          }),
        },
        maxSteps: 5,
        maxRetries: 10,
        experimental_transform: smoothStream(),
        system: chatPrompt(),
        onFinish: () => {
          dataStreamWriter.writeData("done");
        },
      });

      result.mergeIntoDataStream(dataStreamWriter);
    },
  });

  c.header("X-Vercel-AI-Data-Stream", "v1");
  c.header("Content-Type", "text/plain; charset=utf-8");
  c.header("Content-Encoding", "Identity");
  return stream(c, (stream) =>
    stream.pipe(dataStream.pipeThrough(new TextEncoderStream()))
  );
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ai/provider ai/ui bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants