Skip to content

AI SDK Integration

AI SDK is a free open-source library for building AI-powered products. You can seamlessly integrate it with oRPC without any extra overhead.

WARNING

This documentation requires AI SDK v5.0.0 or later. For a refresher, review the AI SDK documentation.

Server

Use streamToEventIterator to convert AI SDK streams to oRPC Event Iterators.

ts
import { 
os
,
streamToEventIterator
,
type
} from '@orpc/server'
import {
convertToModelMessages
,
streamText
,
UIMessage
} from 'ai'
import {
google
} from '@ai-sdk/google'
export const
chat
=
os
.
input
(
type
<{
chatId
: string,
messages
:
UIMessage
[] }>())
.
handler
(({
input
}) => {
const
result
=
streamText
({
model
:
google
('gemini-1.5-flash'),
system
: 'You are a helpful assistant.',
messages
:
convertToModelMessages
(
input
.
messages
),
}) return
streamToEventIterator
(
result
.
toUIMessageStream
())
})

Client

On the client side, convert the event iterator back to a stream using eventIteratorToStream.

tsx
import { 
useChat
} from '@ai-sdk/react'
import {
eventIteratorToStream
} from '@orpc/client'
export function
Example
() {
const {
messages
,
sendMessage
,
status
} =
useChat
({
transport
: {
async
sendMessages
(
options
) {
return
eventIteratorToStream
(await
client
.
chat
({
chatId
:
options
.
chatId
,
messages
:
options
.
messages
,
}, {
signal
:
options
.
abortSignal
}))
},
reconnectToStream
(
options
) {
throw new
Error
('Unsupported')
}, }, }) const [
input
,
setInput
] =
useState
('')
return ( <> {
messages
.
map
(
message
=> (
<
div
key
={
message
.
id
}>
{
message
.
role
=== 'user' ? 'User: ' : 'AI: '}
{
message
.
parts
.
map
((
part
,
index
) =>
part
.
type
=== 'text' ? <
span
key
={
index
}>{
part
.
text
}</
span
> : null,
)} </
div
>
))} <
form
onSubmit
={(
e
) => {
e
.
preventDefault
()
if (
input
.
trim
()) {
sendMessage
({
text
:
input
})
setInput
('')
} }} > <
input
value
={
input
}
onChange
={
e
=>
setInput
(
e
.
target
.
value
)}
disabled
={
status
!== 'ready'}
placeholder
="Say something..."
/> <
button
type
="submit"
disabled
={
status
!== 'ready'}>
Submit </
button
>
</
form
>
</> ) }

INFO

The reconnectToStream function is not supported by default, which is fine for most use cases. If you need reconnection support, implement it similar to sendMessages with custom reconnection logic. See this reconnect example.

Released under the MIT License.