ai icon indicating copy to clipboard operation
ai copied to clipboard

streamObject doesn't work with google Gemini 2.5 Pro

Open ruizehung opened this issue 9 months ago • 9 comments

Description

streamObject used to work when I tried gemini 2 pro experimental. But now it doesn't work for either gemini 2 pro or gemini 2.5 pro.

The same code works if I swap the model to be openai("gpt-4o-2024-11-20")

I tested it with "@ai-sdk/google": "1.2.9" "ai": "^4.2.0", node: v22.12.0

Code example

import { streamObject, generateObject } from "ai";
import { openai } from '@ai-sdk/openai';
import { google } from "@ai-sdk/google";

const prompt = "....some prompt ...."

const object_schema = z.object({
    topics: z.array(z.string()).max(20).describe('The topics from the file text.'),
});

const { partialObjectStream } = streamObject({
    model: google('gemini-2.5-pro-preview-03-25'),
    schema: object_schema,
    prompt
});

console.log("Streaming object from Gemini");
    
for await (const partialObject of partialObjectStream) {
    if (partialObject.topics) {
        console.log("Partial object", partialObject);
        yield partialObject.topics;
    }
}

Then nothing get output.

AI provider

@ai-sdk/google 1.2.9

Additional context

No response

ruizehung avatar Apr 08 '25 07:04 ruizehung

This affects generateObject as well, with the error AI_JSONParseError, "No object generated: could not parse the response." It seems that it might be due to how gemini pro 2.0/2.5 generates the json output. This happens with both structuredOutputs set to true and false

Here's an example of the text output: Gemini 2.5 pro:

"ny\n```json\n{\n "sentiment": "Very Positive"\n}\n```"

vs Gemini 2.0 flash:

"{\"sentiment\":\"Very Positive\"}"

Please note that this doesn't always happen. It seems that the model itself isn't consistent with how it uses structured outputs.

Cosmin26 avatar Apr 08 '25 16:04 Cosmin26

i think started happening today

cevr avatar Apr 08 '25 17:04 cevr

Yes facing same issue, tommorrow it was working perfect

imhardikdesai avatar Apr 08 '25 19:04 imhardikdesai

for those this may be useful for - i managed to fix this by creating a little middleware

not productionized by any means - but gets you a start and works for my hobby cases

const jsonFixingMiddleware: LanguageModelV1Middleware = {
  async wrapGenerate(options) {
    const result = await options.doGenerate();
    if (result.text) {
      // right now we see that the text is not valid json, so we need to fix it
      // here's an example of what we see 'ny\n```json...```\n\n'
      // we need to remove the ```json and ``` tags and the newlines and the random 'ny'
      let text = result.text;
      const nyStart = text.indexOf("ny");
      if (nyStart === 0) {
        text = text.slice(nyStart + 2);
        const jsonStart = text.indexOf("```json");
        const jsonEnd = text.lastIndexOf("```");
        if (jsonStart !== -1 && jsonEnd !== -1) {
          const json = text.slice(jsonStart + 7, jsonEnd);
          result.text = json;
        }
      }
    }
    return result;
  },
};```

cevr avatar Apr 08 '25 21:04 cevr

@cevr - this worked as an interim fix, thanks

Xexr avatar Apr 09 '25 08:04 Xexr

Same here, started happening 2 days ago 100% of the time. The output always start as

ny
\`\`\`json
{...}
\`\`\`

For now I am using this in experimental_repairText

export function extractMalformedJSON(text: string) {
  return [...text.matchAll(/```(?:json\n)?([\s\S]*?)```/g)][0]?.[1] ?? text
}
...
   // Remove when this is fixed https://github.com/vercel/ai/issues/5594
    experimental_repairText: async ({ text }) => {
      return Promise.resolve(extractMalformedJSON(text))
    },
...

Yuripetusko avatar Apr 09 '25 10:04 Yuripetusko

I think it is working now, without any changes. google has fixed it

imhardikdesai avatar Apr 12 '25 18:04 imhardikdesai

For me it's still broken in streamText with a bunch of tools. After calling a tool and getting result from it back, Gemini Pro 2.5 replies with just empty content (no chunks streamed after this).

<system message, user message, assistant, and tool message>
{"role":"assistant","content":[{"type":"text","te
xt":""}],"id":"msg-OWB5TlZYgdtVTMQyZBKa3D1s"}]},"isContinued":false}}
Image

Any other OpenAI or Anthropic model works fine here.

RafalWilinski avatar Apr 12 '25 18:04 RafalWilinski

For me it's still broken in streamText with a bunch of tools. After calling a tool and getting result from it back, Gemini Pro 2.5 replies with just empty content (no chunks streamed after this).

<system message, user message, assistant, and tool message> {"role":"assistant","content":[{"type":"text","te xt":""}],"id":"msg-OWB5TlZYgdtVTMQyZBKa3D1s"}]},"isContinued":false}} Image Any other OpenAI or Anthropic model works fine here.

can you try with gemini-2.5-pro-exp-03-25

imhardikdesai avatar Apr 12 '25 18:04 imhardikdesai

Same here, started happening 2 days ago 100% of the time. The output always start as这里也一样,两天前开始总是发生。输出总是开始为

ny
\`\`\`json
{...}
\`\`\`

For now I am using this in experimental_repairText目前我正在使用这个在 experimental_repairText

export function extractMalformedJSON(text: string) {
  return [...text.matchAll(/```(?:json\n)?([\s\S]*?)```/g)][0]?.[1] ?? text
}
...
   // Remove when this is fixed https://github.com/vercel/ai/issues/5594
    experimental_repairText: async ({ text }) => {
      return Promise.resolve(extractMalformedJSON(text))
    },
...

streamObject not support

tianshangwuyun avatar May 23 '25 10:05 tianshangwuyun