vercel / ai

Build AI-powered applications with React, Svelte, Vue, and Solid
https://sdk.vercel.ai/docs
Other
8.82k stars 1.26k forks source link

Fix multiple parallel tool call support in streamUI #1894

Open mfclarke-cnx opened 1 month ago

mfclarke-cnx commented 1 month ago

Bug Description

streamUI doesn't gracefully handle multiple parallel tool calls. Currently when the model makes multiple tool calls, the tool handler gets called multiple times, but the first call to resolve closes the UI steam and the rest throw:

⨯ node_modules/.pnpm/ai@3.1.26_openai@4.48.1_react@18.3.1_solid-js@1.8.17_svelte@4.2.17_vue@3.4.27_zod@3.23.8/node_modules/ai/rsc/dist/rsc-server.mjs (1231:12) @ assertStream
 ⨯ unhandledRejection: Error: .update(): UI stream is already closed.
camwest commented 1 month ago

It looks like this hardcoded "true" is where the error is happening.

https://github.com/vercel/ai/blob/f7002ad2c5aa58ce6ed83e8d31fe22f71ebdb7d7/packages/core/rsc/stream-ui/stream-ui.tsx#L303

It's a bad assumption. The tool-call event doesn't immediately mean it's the last render call because there may be multiple tool-call events.

camwest commented 1 month ago

A potential fix would be to add a 'all-tool-calls-done' event which gets pushed to stream after the loop right around here:

https://github.com/vercel/ai/blob/f7002ad2c5aa58ce6ed83e8d31fe22f71ebdb7d7/packages/openai/src/openai-chat-language-model.ts#L343

Then we handle that in stream-ui and finalize the stream there.

The challenge is we'd have to update anything that implements LanguageModelV1 to trigger this event, or version to V2.

camwest commented 1 month ago

Another option is to close the stream on finish:

https://github.com/vercel/ai/blob/f7002ad2c5aa58ce6ed83e8d31fe22f71ebdb7d7/packages/openai/src/openai-chat-language-model.ts#L382-L388

Currently not implemented in streamUI:

https://github.com/vercel/ai/blob/f7002ad2c5aa58ce6ed83e8d31fe22f71ebdb7d7/packages/core/rsc/stream-ui/stream-ui.tsx#L314

bneigher commented 1 month ago

ah this is the culprit of my issue! been doing this since v3.1.25

camwest commented 1 month ago

@mfclarke-cnx can you change this to a bug instead of enhancement?

mfclarke-cnx commented 1 month ago

@camwest unfortunately I don't have permissions to change the labels. @lgrammel would you be able to update labels please?

miguelvictor commented 1 month ago

I also have this issue but the weird thing about mine is the same tool is being called twice.

gclark-eightfold commented 1 month ago

As tagged by @bneigher, I have an approach I'm working on in #1904, but it's still a WIP.

Main issue I have right now is that because we don't know how many tool calls will be made ahead of time, the parent "streamableUI" doesn't call .done until all tool calls complete.

I think my expectation is that the UI will be added to as the final tool calls stream in.

camwest commented 1 month ago

Main issue I have right now is that because we don't know how many tool calls will be made ahead of time, the parent "streamableUI" doesn't call .done until all tool calls complete.

I think you can get this information at the provider level.

For example the OpenAI provider passes an array of tool_calls so you know when you're finished iterating that it's 'done'

HECHONG999 commented 1 month ago

"Parallel support, how to resolve the 'done' error bug now."

dutsik-p commented 3 weeks ago

Maybe anybody knows how to tune the prompt so the model doesnot put number of tools to call at the same time?