-
Notifications
You must be signed in to change notification settings - Fork 16
Documentation Updates for RTVI version 1.0.0 and corresponding client-js and client-react libraries. #265
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
base: main
Are you sure you want to change the base?
Conversation
4960756
to
7fee2fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates the client-side documentation to reflect the migration from RTVIClient to the new PipecatClient, updating import names, code examples, and documentation files across the JS and React SDKs. Key changes include:
- Renaming of client classes, hooks, and components from RTVI* to Pipecat*.
- Updates to code examples and configuration details in multiple transport and API reference documentations.
- Removal of outdated documentation pages and streamlining of migration guides.
Reviewed Changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
mint.json | Updated navigation pages to include new client documentation and migration guides. |
client/react/*.md | Updated migration guides, introductions, hooks, and components to replace RTVI references with Pipecat references. |
client/js/*.md | Revised API references, transport guides, and examples to use the new PipecatClient naming. |
Comments suppressed due to low confidence (1)
client/js/api-reference/client-constructor.mdx:68
- [nitpick] Consider renaming the instance variable (e.g., to 'pcClient') rather than reusing the class name 'PipecatClient' to improve code clarity and avoid confusion.
const PipecatClient = new PipecatClient({
client/introduction.mdx
Outdated
@@ -3,6 +3,10 @@ title: "Client SDKs" | |||
description: "Client libraries for building real-time AI applications with Pipecat" | |||
--- | |||
|
|||
<Warning> | |||
The Client SDKs are currently in transition to a new, simpler API design. The js and react libraries have already been deployed with these changes. Their corresponding documentation along with this top-level documentation has been updated to reflect the latest changes, but some specific API references may still be in the old format. For transitioning to the new API, please refer to the [migration guide](/client/migration-guide). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which API references would still be in the old format?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, do you mean the API references for the other libraries (iOS, Android, React Native)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, i think this was the first paragraph i wrote and figured i'd miss something, so betting on failure, but i feel pretty confident in my updates now 😂 -- i'll remove that language. maybe also specifically point out that iOS, Android, ReactNative have not been ported and therefore their documentation has also not been updated.
client/introduction.mdx
Outdated
} catch (e) { | ||
console.error(e.message); | ||
} | ||
|
||
// Events | ||
rtviClient.on(RTVIEvent.Connected, () => { | ||
// Alternative Event Handling Setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this pattern an alternative to? Specifying handlers in the callbacks
constructor arg?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like i just updated what was here in this case and noticed that it was setting up callbacks two different ways, so added the "alternative" language. not sure what's best here really...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable to show both patterns, as you do here! Maybe a comment tweak would've made it clearer to me, like // Events (alternative to constructor-provided callbacks)
client/introduction.mdx
Outdated
@@ -111,66 +118,71 @@ All Pipecat client SDKs provide: | |||
}); | |||
|
|||
try { | |||
await rtviClient.connect(); | |||
// you can provide your Daily connection credentials directly as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah took me a moment to remember that the connect endpoint (shown below) is the way to get the connection credentials. This comment didn't quite get me there quickly—wondering if it could be clearer, like:
Below, we use a REST endpoint to fetch connection credentials for our Daily Transport.
Alternatively, you could provide those credentials directly to `connect()`.
console.log("[EVENT] User disconnected"); | ||
}); | ||
``` | ||
|
||
```react react | ||
// Example: Using PipecatClient in a React component |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops
client/introduction.mdx
Outdated
``` | ||
|
||
```react react | ||
// Example: Using PipecatClient in a React component |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup.
console.error(e.message); | ||
} | ||
``` | ||
await pcClient.connect({url: "https://your-daily-room-url", token: "your-daily-token"}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like that you found a way to also illustrate the alternative method of connecting 👍
content: "tell me a joke", | ||
}, | ||
], | ||
<Tab title="Custom Messaging"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Philosophical question: if we're no longer selling Pipecat Client as a tool for sending "non-custom" bot configuration messages (we're recommending folks do their bot configuration server-side), then can we just call this "messaging" as opposed to "custom messaging"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think i was considering anything about configuration when i labeled this. I believe i was thinking that RTVI is a bunch of messages, this looks at sending custom ones. But also, that seems nuanced and agree it could just be "messaging" 🤷♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think i had also planned on maybe adding more tabs for any other most-common patterns, but only did messaging for now as a replacement for what was here, which was an "actions" example.
`@pipecat-ai/daily-transport`) exports multiple transports classes, you can | ||
specify which to use here. | ||
<Note> | ||
For best practice, we recommend you pass in a transport using its factory function as access to the transport is typically unnecessary. For advanced use cases that do require access to the transport, we recommend doing so via the `PipecatClient.transport` property. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow—how is creating a transport via a factory function v a constructor related to whether or not you then hold a reference to the transport?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
um... uh... good point. you know, i think i initially introduced factory functions thinking we would pass the function to the constructor for the constructor to call, but ended up realizing you need to provide constructor opts to the transport, so backed into using the factory function but calling it to get the transport when just doing a new myTransport(opts)
would work just the same.
The real note here is that the best practice is to construct the transport inline in the client constructor so that you are forced to get the transport (if needed) from the client, and not tempted to just hold on to the one you made and passed in, since client.transport !== rawTransport (remember that client.transport returns a wrapped version of the transport with a safety harness).
i.e.
const pcClient = new PipecatClient({transport: new DailyTransport(dailyOpts)});
// forces me to do
(pcClient.transport as DailyClient).preAuth({url});
vs.
const transport = new DailyTransport(dailyOpts);
const pcClient = new PipecatClient({transport});
// this works but now i'm more likely to do:
transport.preAuth({url});
GIVEN THAT BREATHY RESPONSE, should i get rid of the create()
factory methods? you're right, they don't really accomplish anything. it's more about documenting best practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should i get rid of the create() factory methods
Maybe! I suppose they don't really seem necessary.
The real note here is that the best practice is to construct the transport inline in the client constructor so that you are forced to get the transport (if needed) from the client, and not tempted to just hold on to the one you made and passed in
👍 . Maybe the action item is to simplify this note to just focus on this recommendation, then? Like:
"As a best practice, we recommend you construct the transport inline in the client constructor, as opposed to holding a reference to it. Access to the transport is typically unnecessary. For advanced use cases that do require access to the transport, we recommend doing so via the PipecatClient.transport
property, which provides some additional safeguards."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done and factory functions are now removed from code and docs :)
@@ -1,45 +1,288 @@ | |||
--- | |||
title: "Messages" | |||
title: "Custom Messaging" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See earlier note about the need for "custom"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same response. I'm happy either way, but let me know your thoughts after reading why I used "Custom messaging" here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No strong feelings about this! Keeping it as "custom messaging" sounds fine to me.
client/js/api-reference/messages.mdx
Outdated
|
||
Messages are used by a client for passing an instruction to a bot that typically results in a [callback or event](./callbacks). | ||
Oftentimes clients need to provide configuration data to the server when connecting. This can include things like preferred language, user preferences, initial messages, or any other data that the server needs to know about the client. This must occur before the bot is started and therefore not part of the RTVI standard, but rather a custom implementation. That said, the PipecatClient makes it easy to send this data as part of the `connect()` method, by passing an object with the `requestData` property. Your server endpoint can then handle this data as needed. In the example below, we demonstrate sending an initial prompt and preferred language to the server when connecting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'm noticing that sometimes we say PipecatClient and sometimes PipecatClient
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah... that's probably laziness or copilot'ing (or i guess those are one and the same 😂 ) -- What should I try to be consistent towards? i'm guessing PipecatClient
?
|
||
Examples of messages include: | ||
<CodeGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great example!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
# Kick off the conversation | ||
await task.queue_frames([context_aggregator.user().get_context_frame()]) | ||
|
||
@daily_transport.event_handler("on_participant_left") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stepping back: would it be better if this were an rtvi event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe. other than supporting the new behaviors and deprecating the ones going away, though, i didn't do a ton of work on the pipecat side of all this. maybe we do a better sweep of things like this in post?
|
||
```python bot | ||
# Listen for a RTVIClientMessageFrame and push a STTUpdateSettingsFrame | ||
class CustomFrameProcessor(FrameProcessor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure we talked about this on a call and I don't remember, but: this is the recommended way for a bot to handle a message? Creating a custom frame processor feels like rather a lot of verbose boilerplate for a customer.
It also feels a bit unintuitive to me...a client message feels conceptually like something that is coming from outside the pipeline and controlling it, not like something that automatically originates within it. I would've expected something more like an event handler in the bot's code file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, I also see an example below of using an "on_client_message" event handler. That feels much more natural to me.
When are we recommending using one approach v the other? Why are we only showing the custom processor approach in this example, and showing both approaches in the other example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question re rtvi.send_server_response
v pushing a RTVIServerResponseFrame
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah! GREAT question. walking away from that discussion, my understanding was that handlers are definitely the preferred and simpler approach, so long as you do not need to mess with the pipeline. In this example, I'm updating the STT language and thought that action required a FrameProcessor, but I could be wrong.
...
I just checked with mark and he agrees, this sort of action is best done as a frame processor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so long as you do not need to mess with the pipeline
Not sure I understand—what's the downside to calling task.queue_frame(frame)
inside an event handler, if event handlers are otherwise the preferred and simpler approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
um. uh. @aconchillo ? @markbackman ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also, just realized that using the event handler makes it so you don't have to be so careful about where in your pipeline you put your custom frame processor for it to have the desired effect—in the event handler you'll just shove frames into the top of the pipeline)
client/js/api-reference/messages.mdx
Outdated
class CustomFrameProcessor(FrameProcessor): | ||
async def process_frame(self, frame: Frame, direction: FrameDirection): | ||
await super().process_frame(frame, direction) | ||
if isinstance(frame, STTUpdateSettingsFrame): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The presence of this frame tells us that the language has been updated only if this CustomFrameProcessor
is downstream from the STT service, right?
Is it worth showing how the CustomFrameProcessor
is inserted into the pipeline? (And maybe also showing how the CustomObserver
is wired up, for that matter?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe? though, that feels more a documentation on how observers and processors work and therefore the job of the documentation on those, rather than client-side documentation on sending rtvi messages. you have to draw the line somewhere.
client/js/migration-guide.mdx
Outdated
}); | ||
``` | ||
|
||
5. Pipeline Configuration Initialization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doh. yes, i forgot to come back to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
client/js/transports/transport.mdx
Outdated
@@ -3,23 +3,27 @@ title: "Transport Overview" | |||
sidebarTitle: "Overview" | |||
--- | |||
|
|||
Transports are the means by which Pipecat clients communicate with their bot services. They handle both message exchange between client and server and real-time media transport. Pipecat implements the RTVI standard for these communications. | |||
Transports are the means by which Pipecat clients communicate with their bot services. They handle both message exchange between client and server and real-time media transport. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was list of additional transport functionality (like device management) somewhere else in these docs. Should it go here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea.
description: "A Guide to migrating from RTVIClient to PipecatClient" | ||
--- | ||
|
||
This guide will cover the high-level changes between the old `RTVIClient` and the new `PipecatClient`. For specific code updates, refer to the platform-specific migration guides. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also have a warning somewhere in this guide—like we have in the introduction page—that not all client libraries have yet been updated to the new patterns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea.
client/rtvi-standard.mdx
Outdated
|
||
#### client-ready | ||
|
||
Indicates that the client is ready to receive messages and interact with the server. Typically send after the transport media channels have connected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
Indicates that the client is ready to receive messages and interact with the server. Typically send after the transport media channels have connected. | |
Indicates that the client is ready to receive messages and interact with the server. Typically sent after the transport media channels have connected. |
client/rtvi-standard.mdx
Outdated
|
||
#### bot-transcription | ||
|
||
Transcription of the bot's speech. Note: This protocol currently does not the user transcription format to support real-time timestamping for bot transcriptions. The event is typically sent for each sentence of the bot's response. In the future, this may be updated to include the user with real-time transcription capabilities. Currently, most TTS services do not support (or support well), accurate timing information to make this possible. For now, if you want to attempt real-time transcription to match your bot's speaking, you can try using the `bot-tts-text` message type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a word here? This protocol currently does not the user transcription
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was i drunk? pushing an update that's hopefully much better...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was i drunk?
that would've made writing this huge amount of documentation more fun! (i'm trying to give a compliment: very impressive overhaul of the docs)
The payload of the message, which can be any data structure relevant to the message type. | ||
</ParamField> | ||
|
||
## RTVI Message Types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder if there should be a structured way of denoting who (the bot or client) is expected to send each of the messages. Having them mixed together with no labels could be a bit confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea... 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) emojis :)
🤖 🏄
client/rtvi-standard.mdx
Outdated
|
||
### Client-Server Messaging | ||
|
||
#### server-message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apparently 🤦♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pre-approving, as all comments (except one new question) have been acknowledged. Nice work!
I have made all the suggested updates and filled in the missing sections! |
client/js/api-reference/messages.mdx
Outdated
), | ||
) | ||
return | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like something weird's happened with the indentation here -- I think this is using tabs for the else
and spaces for the if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch. not sure where those tabs came from 🤔
## From inside an Observer, call `send_server_message` directly on your rtvi instance | ||
class CustomObserver(BaseObserver): | ||
async def on_push_frame(self, data: FramePushed): | ||
if isinstance(frame, STTUpdateSettingsFrame): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again it looks like the indentation is weird here (tabs vs spaces mixed)
**New** | ||
```javascript | ||
const client = new PipecatClient({ | ||
transport: new DailyTransport(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the discussions I thought we were going to pass in a factory rather than the transport directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the topic of an earlier comment discussion, in which @mattieruth explains:
"i think i initially introduced factory functions thinking we would pass the function to the constructor for the constructor to call, but ended up realizing you need to provide constructor opts to the transport"
So she made the call to just ditch the factory pattern since it wasn't adding anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exactly what kompfner said i said. I had to back away because you need to be able to pass args to the transport constructor/factory function. If you know of a way around this, i'm all ears. The only thing i came up with was to pass the args as a separate param, but that felt ugly. So i'm just trying to document best practice and update all the examples to show inline construction.
a914407
to
3c8e116
Compare
This PR updates the client-side documentation to match the new PipecatClient and the underlying, simplified RTVI Message protocol. Corresponding code PRs:
This should be merged after the above PRs have been merged and released.