streaming - How to Stream Responses to the Frontend Using streamText in Next.js? - Stack Overflow

admin2025-04-18  2

Problem Statement: I am building a chatbot in Next.js using ai and @ai-sdk/google. The chatbot should stream responses from Gemini (gemini-1.5-flash-8b) to the frontend. I confirmed that the response is streamed in the backend by logging the chunks:

for await (const textPart of result.textStream) {
    console.log(textPart);
}

However, when I return the response to the frontend, the streaming effect is lost, and I receive the full response all at once.

What I Have Tried:

Backend (API Route in Next.js):

import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { streamText } from "ai";
import { NextRequest, NextResponse } from "next/server";

const google = createGoogleGenerativeAI({
  apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
});

const model = google("gemini-1.5-flash-8b");

export async function POST(req: NextRequest) {
  try {
    const { messages } = await req.json();
    console.log(messages);

    const result = streamText({
      model: model,
      system: "You are a helpful assistant.",
      prompt: messages[0].content,
    });

    for await (const textPart of result.textStream) {
      console.log(textPart); // Confirms streaming works in backend
    }

    return result.toDataStreamResponse(); // Returns the response
  } catch (error) {
    console.error(error);
    return new NextResponse("Error processing request", { status: 500 });
  }
}

Frontend (useChat Hook from ai/react):

"use client";
import React from "react";
import { Input } from "./ui/input";
import { useChat } from "ai/react";
import { Button } from "./ui/button";
import { Send } from "lucide-react";
import MessageList from "./MessageList";

const ChatComponent = () => {
  const { input, handleInputChange, handleSubmit, messages } = useChat();

  return (
    <div className="relative max-h-screen overflow-scroll" id="message-container">
      <div className="sticky top-0 inset-x-0 p-2 bg-white h-fit">
        <h3 className="text-xl font-bold">Chat</h3>
      </div>
      <MessageList messages={messages} />
      <form onSubmit={handleSubmit} className="sticky bottom-0 inset-x-0 px-2 py-4 bg-white">
        <div className="flex">
          <Input value={input} onChange={handleInputChange} placeholder="Ask any question" className="w-full" />
          <Button className="bg-blue-600 ml-2">
            <Send className="h-4 w-4" />
          </Button>
        </div>
      </form>
    </div>
  );
};

export default ChatComponent; Expected Behavior: I want the frontend to display the response text as it arrives, rather than waiting for the entire response to be received.

Actual Behavior: The backend correctly logs the response as a stream. The frontend receives the response, but only after all of it is processed. The real-time streaming effect is lost. Question: How can I ensure the response is streamed to the frontend in real time using streamText? Do I need to manually handle the stream in the frontend instead of relying on useChat?

Problem Statement: I am building a chatbot in Next.js using ai and @ai-sdk/google. The chatbot should stream responses from Gemini (gemini-1.5-flash-8b) to the frontend. I confirmed that the response is streamed in the backend by logging the chunks:

for await (const textPart of result.textStream) {
    console.log(textPart);
}

However, when I return the response to the frontend, the streaming effect is lost, and I receive the full response all at once.

What I Have Tried:

Backend (API Route in Next.js):

import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { streamText } from "ai";
import { NextRequest, NextResponse } from "next/server";

const google = createGoogleGenerativeAI({
  apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
});

const model = google("gemini-1.5-flash-8b");

export async function POST(req: NextRequest) {
  try {
    const { messages } = await req.json();
    console.log(messages);

    const result = streamText({
      model: model,
      system: "You are a helpful assistant.",
      prompt: messages[0].content,
    });

    for await (const textPart of result.textStream) {
      console.log(textPart); // Confirms streaming works in backend
    }

    return result.toDataStreamResponse(); // Returns the response
  } catch (error) {
    console.error(error);
    return new NextResponse("Error processing request", { status: 500 });
  }
}

Frontend (useChat Hook from ai/react):

"use client";
import React from "react";
import { Input } from "./ui/input";
import { useChat } from "ai/react";
import { Button } from "./ui/button";
import { Send } from "lucide-react";
import MessageList from "./MessageList";

const ChatComponent = () => {
  const { input, handleInputChange, handleSubmit, messages } = useChat();

  return (
    <div className="relative max-h-screen overflow-scroll" id="message-container">
      <div className="sticky top-0 inset-x-0 p-2 bg-white h-fit">
        <h3 className="text-xl font-bold">Chat</h3>
      </div>
      <MessageList messages={messages} />
      <form onSubmit={handleSubmit} className="sticky bottom-0 inset-x-0 px-2 py-4 bg-white">
        <div className="flex">
          <Input value={input} onChange={handleInputChange} placeholder="Ask any question" className="w-full" />
          <Button className="bg-blue-600 ml-2">
            <Send className="h-4 w-4" />
          </Button>
        </div>
      </form>
    </div>
  );
};

export default ChatComponent; Expected Behavior: I want the frontend to display the response text as it arrives, rather than waiting for the entire response to be received.

Actual Behavior: The backend correctly logs the response as a stream. The frontend receives the response, but only after all of it is processed. The real-time streaming effect is lost. Question: How can I ensure the response is streamed to the frontend in real time using streamText? Do I need to manually handle the stream in the frontend instead of relying on useChat?

Share Improve this question asked Jan 29 at 15:14 ninad baruahninad baruah 111 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

It seems you shouldnt be using useChat(), instead use useCompletion(), more info here. Hope it helps, let me know if it worked

转载请注明原文地址:http://anycun.com/QandA/1744957481a90020.html