-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat (ui/react): add experimental_useObject hook (#2019)
- Loading branch information
Showing
37 changed files
with
1,070 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'ai': patch | ||
--- | ||
|
||
feat (ai): add textStream, toTextStreamResponse(), and pipeTextStreamToResponse() to streamObject |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@ai-sdk/react': patch | ||
--- | ||
|
||
feat (@ai-sdk/react): add experimental_useObject to @ai-sdk/react |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@ai-sdk/ui-utils': patch | ||
--- | ||
|
||
chore (@ai-sdk/ui-utils): move functions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
--- | ||
title: Object Generation | ||
description: Learn how to use the useObject hook. | ||
--- | ||
|
||
# Object Generation | ||
|
||
<Note>`useObject` is an experimental feature and only available in React.</Note> | ||
|
||
The [`useObject`](/docs/reference/ai-sdk-ui/use-object) hook allows you to create interfaces that represent a structured JSON object that is being streamed. | ||
|
||
In this guide, you will learn how to use the `useObject` hook in your application to generate UIs for structured data on the fly. | ||
|
||
## Example | ||
|
||
The example shows a small notfications demo app that generates fake notifications in real-time. | ||
|
||
### Schema | ||
|
||
It is helpful to set up the schema in a separate file that is imported on both the client and server. | ||
|
||
```ts filename='app/api/use-object/schema.ts' | ||
import { DeepPartial } from 'ai'; | ||
import { z } from 'zod'; | ||
|
||
// define a schema for the notifications | ||
export const notificationSchema = z.object({ | ||
notifications: z.array( | ||
z.object({ | ||
name: z.string().describe('Name of a fictional person.'), | ||
message: z.string().describe('Message. Do not use emojis or links.'), | ||
minutesAgo: z.number(), | ||
}), | ||
), | ||
}); | ||
|
||
// define a type for the partial notifications during generation | ||
export type PartialNotification = DeepPartial<typeof notificationSchema>; | ||
``` | ||
|
||
### Client | ||
|
||
The client uses [`useObject`](/docs/reference/ai-sdk-ui/use-object) to stream the object generation process. | ||
|
||
The results are partial and are displayed as they are received. | ||
Please note the code for handling `undefined` values in the JSX. | ||
|
||
```tsx filename='app/page.tsx' | ||
'use client'; | ||
|
||
import { experimental_useObject as useObject } from '@ai-sdk/react'; | ||
import { notificationSchema } from './api/use-object/schema'; | ||
|
||
export default function Page() { | ||
const { setInput, object } = useObject({ | ||
api: '/api/use-object', | ||
schema: notificationSchema, | ||
}); | ||
|
||
return ( | ||
<div> | ||
<button | ||
onClick={async () => { | ||
setInput('Messages during finals week.'); | ||
}} | ||
> | ||
Generate notifications | ||
</button> | ||
|
||
<div> | ||
{object?.notifications?.map((notification, index) => ( | ||
<div key={index}> | ||
<div> | ||
<div> | ||
<p>{notification?.name}</p> | ||
<p> | ||
{notification?.minutesAgo} | ||
{notification?.minutesAgo != null ? ' minutes ago' : ''} | ||
</p> | ||
</div> | ||
<p>{notification?.message}</p> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Server | ||
|
||
On the server, we use [`streamObject`](/docs/reference/ai-sdk-core/stream-object) to stream the object generation process. | ||
|
||
```typescript filename='app/api/use-object/route.ts' | ||
import { openai } from '@ai-sdk/openai' | ||
import { streamObject } from 'ai' | ||
import { notificationSchema } from './schema' | ||
|
||
// Allow streaming responses up to 30 seconds | ||
export const maxDuration = 30 | ||
|
||
export async function POST(req: Request) { | ||
const context = await req.json() | ||
|
||
const result = await streamObject({ | ||
model: openai('gpt-4-turbo'), | ||
schema: notificationSchema | ||
prompt: | ||
`Generate 3 notifications for a messages app in this context:` + context, | ||
}) | ||
|
||
return result.toTextStreamResponse() | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
--- | ||
title: useObject | ||
description: API reference for the useObject hook. | ||
--- | ||
|
||
# `experimental_useObject()` | ||
|
||
<Note>`useObject` is an experimental feature and only available in React.</Note> | ||
|
||
Allows you to consume text streams that represent a JSON object and parse them into a complete object based on a Zod schema. | ||
You can use it together with [`streamObject`](/docs/reference/ai-sdk-core/stream-object) in the backend. | ||
|
||
```tsx | ||
'use client'; | ||
|
||
import { experimental_useObject as useObject } from '@ai-sdk/react'; | ||
|
||
export default function Page() { | ||
const { setInput, object } = useObject({ | ||
api: '/api/use-object', | ||
schema: z.object({ content: z.string() }), | ||
}); | ||
|
||
return ( | ||
<div> | ||
<button onClick={() => setInput('example input')}>Generate</button> | ||
{object?.content && <p>{object.content}</p>} | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
## Import | ||
|
||
<Snippet | ||
text="import { experimental_useObject as useObject } from '@ai-sdk/react'" | ||
dark | ||
prompt={false} | ||
/> | ||
|
||
## API Signature | ||
|
||
### Parameters | ||
|
||
<PropertiesTable | ||
content={[ | ||
{ | ||
name: 'api', | ||
type: 'string', | ||
description: | ||
'The API endpoint. It should stream JSON that matches the schema as chunked text.', | ||
}, | ||
{ | ||
name: 'schema', | ||
type: 'ZodSchema<RESULT>', | ||
description: | ||
'A Zod schema that defines the shape of the complete object.', | ||
}, | ||
{ | ||
name: 'id?', | ||
type: 'string', | ||
description: | ||
'Allows you to consume text streams that represent a JSON object and parse them into a complete object based on a Zod schema.', | ||
}, | ||
{ | ||
name: 'initialValue?', | ||
type: 'DeepPartial<RESULT> | undefined', | ||
description: 'An optional value for the initial object.', | ||
}, | ||
]} | ||
/> | ||
|
||
### Returns | ||
|
||
<PropertiesTable | ||
content={[ | ||
{ | ||
name: 'setInput', | ||
type: '(input: INPUT) => void', | ||
description: 'Calls the API with the provided input as JSON body.', | ||
}, | ||
{ | ||
name: 'object', | ||
type: 'DeepPartial<RESULT> | undefined', | ||
description: | ||
'The current value for the generated object. Updated as the API streams JSON chunks.', | ||
}, | ||
{ | ||
name: 'error', | ||
type: 'undefined | unknown', | ||
description: 'The error object if the API call fails.', | ||
|
||
} | ||
|
||
]} | ||
/> | ||
|
||
## Examples | ||
|
||
<ExampleLinks | ||
examples={[ | ||
{ | ||
title: 'Streaming Object Generation with useObject', | ||
link: '/examples/next-pages/basics/streaming-object-generation', | ||
}, | ||
]} | ||
/> |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.