Generative UI without generating text

I am currently trying to follow the example from the documents regarding tool-calling and generative UI
I would like to call the UI only without any additional text generated by the AI. The image shows a red square of the AI response which I don’t want (which happens after the UI was rendered)

My page.tsx

"use client";

import { useChat } from "@ai-sdk/react";
import AskForConfirmation from "./components/AskForConfirmation";
import GetLocation from "./components/GetLocation";
import GetWeatherInformation from "./components/GetWeatherInformation";

export default function Page() {
  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 (
    <div>
      {messages.map((message) => (
        <div key={message.id}>
          <div>
            {message.parts.map((part, index) => {
              switch (part.type) {
                case "text":
                  return <div key={index}>{part.text}</div>;

                case "tool-invocation":
                  const callId = part.toolInvocation.toolCallId;
                  const { toolName, state, args } = part.toolInvocation;
                  switch (toolName) {
                    case "askForConfirmation":
                      return (
                        <AskForConfirmation
                          key={callId}
                          callId={callId}
                          message={args?.message ?? ""}
                          result={
                            part.toolInvocation.state === "result"
                              ? part.toolInvocation.result
                              : undefined
                          }
                          state={state}
                          addToolResult={addToolResult}
                        />
                      );
                    case "getLocation":
                      return (
                        <GetLocation
                          key={callId}
                          callId={callId}
                          result={
                            part.toolInvocation.state === "result"
                              ? part.toolInvocation.result
                              : undefined
                          }
                          state={state}
                        />
                      );
                    case "getWeatherInformation":
                      return (
                        <GetWeatherInformation
                          key={callId}
                          callId={callId}
                          city={args?.city ?? ""}
                          result={
                            part.toolInvocation.state === "result"
                              ? part.toolInvocation.result
                              : undefined
                          }
                          state={state}
                        />
                      );
                  }
                  break;
              }
            })}
          </div>
        </div>
      ))}

      <form onSubmit={handleSubmit}>
        <div className="flex gap-2">
          <input
            className="w-full border-2 border-gray-300 rounded-md p-2"
            value={input}
            onChange={handleInputChange}
            placeholder="Type a message..."
          />
          <button
            type="submit"
            className="bg-blue-500 text-white p-2 rounded-md"
          >
            Send
          </button>
        </div>
      </form>
    </div>
  );
}

This is my route.ts

import { openai } from "@ai-sdk/openai";
import { streamText } from "ai";
import { z } from "zod";

export async function POST(request: Request) {
  const { messages } = await request.json();

  const result = streamText({
    model: openai("gpt-4o"),
    system: "You are a friendly assistant!",
    toolCallStreaming: true,
    messages,
    maxSteps: 5,
    tools: {
      // server-side tool with execute function:
      getWeatherInformation: {
        description: "show the weather in a given city to the user",
        parameters: z.object({ city: z.string() }),
        execute: async ({}: { city: string }) => {
          const weatherOptions = ["sunny", "cloudy", "rainy", "snowy", "windy"];
          return weatherOptions[
            Math.floor(Math.random() * weatherOptions.length)
          ];
        },
      },
      // client-side tool that starts user interaction:
      askForConfirmation: {
        description: "Ask the user for confirmation.",
        parameters: z.object({
          message: z.string().describe("The message to ask for confirmation."),
        }),
      },
      // client-side tool that is automatically executed on the client:
      getLocation: {
        description:
          "Get the user location. Always ask for confirmation before using this tool.",
        parameters: z.object({}),
      },
    },
  });

  return result.toDataStreamResponse();
}

I tried using the stop() function from the useChat hook, but this sets the error prop in the useChat hook.
Any insight is greatly appreciated.
Camilo

Hey! If you don’t want follow on text, you have to either omit maxSteps, or set it to 1.

2 Likes

Great, this solved it thank you!
Do you happen to know if there is a good way to modify the maxSteps for certain tools, but not for others if we have multiple tools?

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.