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

ai/core: support full array element streaming in streamObject #1486

Open
bernaferrari opened this issue May 3, 2024 · 3 comments
Open

ai/core: support full array element streaming in streamObject #1486

bernaferrari opened this issue May 3, 2024 · 3 comments
Assignees
Labels

Comments

@bernaferrari
Copy link

bernaferrari commented May 3, 2024

Feature Description

I have a very very very specific use case. I ask for alt images, and when they are done, I retrieve data from unsplash and cache them. The issue is, with the great auto-closing JSON behavior from streamObject, I don't know if alt has completed (received closing ") or not. I wish I had access to the raw (unparsed) text response from GPT, before Vercel AI SDK auto-complete and types it, so I can check if alt has finished processing or not.

Proposal: would be nice to the behaviour where only "finished strings are appended to the object" feels like a good solid alternative too. I think people would love to have the choice between criticalness and speed. Could even be a gzip 1-9 thing: "letter" | "word" | "object". Default is "letter", I want "word" (property), some people might prefer object (after current object has finished). I think it makes sense to implement these variations.

@bernaferrari bernaferrari changed the title I miss rawText in streamObject I miss rawText in streamObject May 3, 2024
@bernaferrari
Copy link
Author

bernaferrari commented May 3, 2024

Is there a way to know the stream is done?

This is my script for parsing everything except the last children, so it streams but avoids the bug I described. It is not optimized, but does the job. I welcome improvements, so I don't need to call statusStream.update() outside of the loop:

const stream = await streamObject({
  model: openai.chat("gpt-4-turbo"),
  schema: z.object({
    children: z.array(z.object({})),
  }),
  system: `You should do this. Follow the API schema here: ...`,
});

let fullJson;
let partialJson = {};
for await (const partialObject of stream.partialObjectStream) {
  fullJson = partialObject;

  const pJson = modifyJsonByRemovingLastNode(fullJson as any);

  if (JSON.stringify(pJson) === JSON.stringify(partialJson)) {
    continue;
  }
  partialJson = pJson as any;

  const debug = await prettier.format(JSON.stringify(fullJson), {
    parser: "json-stringify",
  });
  console.log('debug info', debug);

 const content = await executeMethod(partialJson);

  statusStream.update({
    type: "loading",
    content,
  });
}

const content = await executeMethod(fullJson);
statusStream.update({
  type: "loading",
  data: content
});

statusStream.done();

@lgrammel
Copy link
Collaborator

lgrammel commented May 7, 2024

A possible solution could be to introduce a "fixMode" property on streamObject (or something like it) with the following settings:

  • always: always try to fix the JSON. Will lead to incomplete strings etc
  • finished-primitive: only fix when primitive attribute values are finished
  • finished-objects: only fix when objects are complete. this might need refinement, e.g. for array streaming

I want to think more about all possible cases before adding this, since it can become more complex.

Is my understanding of your use case correct?

Use case:

You want to stream an array of objects that contains an alt attribute (or event an array of strings). 
For each finish array object, partialObjectStream should contain a new result, 
but not for any intermediates (that may have partial urls etc).

@lgrammel lgrammel changed the title I miss rawText in streamObject ai/core: support full array element streaming in streamObject May 7, 2024
@lgrammel lgrammel self-assigned this May 7, 2024
@bernaferrari
Copy link
Author

bernaferrari commented May 7, 2024

Yes. Right now I went lazy and I am with the "I just want to stream the objects that are complete" so there are no surprises anywhere. Like, it might do style="out" instead of style="outlined". Waiting for the whole object to complete is fine for me, while still streaming. The algorithm I did above could be optimized here and there, but it is what I'm doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants