Overview
With expressive conversation on, the LLM writes expression tags into its reply and the TTS service performs them, and a perception producer, such asPipecatToneReader, tells the LLM how the user sounded. Tags and readings follow the Real-time Context Standard, which defines their syntax.
For a walkthrough, see Expressive Conversation.
Expressive TTS Services
The TTS services and models that perform tags, and what each performs
Pipecat Tone
The reader, which hears how the user sounded, and the tagger, which writes
tags for the LLM
Configuration
PipelineParams
bool
default:"False"
Whether the agent takes part in expressive conversation. The LLM is taught the
tags the TTS service performs and how to read the user’s perception, and the
TTS service performs the tags instead of speaking them.
ExpressionPolicy | None
default:"None"
Which tags the LLM is offered, and when to use them.
None offers the core
names the TTS service performs, with no guidance. Has no effect,
with a warning, unless enable_expressive_conversation is True.ExpressionPolicy
list[ExpressionGuidance | str]
default:"[]"
Lines on when and how much to express: presets or your
own, joined in order, so a later line can refine an earlier one. Your own
lines reach the LLM whenever it has tags to write or a reading to act on. The
presets go to whoever writes the tags: the LLM, or
PipecatToneTagger
in its place.list[ExpressionDelivery | str] | None
default:"None"
The deliveries to offer, by their universal names.
None offers the core
deliveries. A name that isn’t universal, such as an accent, is offered as
written. Names the TTS service can’t perform are left out, with a warning.list[ExpressionSound | str] | None
default:"None"
The sounds to offer, as
delivery offers deliveries. None offers the core
sounds, and breath only with ExpressionGuidance.BREATHE.ExpressionGuidance
Presets forExpressionPolicy.guidance. Each is a short paragraph on one aspect of delivery, written to combine with the others and with your own lines. A preset is about writing tags, so an LLM taught no tags isn’t given it.
Universal Names
ExpressionDelivery and ExpressionSound name every delivery and sound the expressive TTS services perform, the same on each. A TTS service translates a universal name into its own, such as warm into ElevenLabs’ warmly, while transcripts, frames and RTVI messages keep the universal name. The members are strings: ExpressionDelivery.WARM is "warm", and ExpressionSound.CLEAR_THROAT is "clear throat". The Real-time Context Standard lists every name.
Core Names
The core names are what the LLM is offered when the policy names none, and whatPipecatToneTagger writes:
A breath is offered only with
ExpressionGuidance.BREATHE.
Perception
A perception producer reads how the user spoke each turn and sets it as the transcription’sperception. The LLM reads it at the head of the user’s message, formatted by format_perception().
PerceptionSignal
One signal of a reading, read either as labels or as a value.PerceptionTerm
One signal a perception producer reports, as it declares it at start.PerceptionCapabilities
format_perception
([emotion angry=0.81, neutral=0.12],[sarcasm value=0.04]).
Frames
Events
The user aggregator’son_user_turn_stopped message carries perception, the turn’s final reading, or None without a perception producer.
Notes
- Context keeps the tags: the reply is stored in the context as the LLM wrote it, so the LLM sees the tags it used. With
PipecatToneTagger, the context keeps the reply plain. - Tags never reach text: transcripts,
LLMContextAssistantTurnFrameand RTVIbot-outputtext carry the words alone. - Tags the TTS service can’t perform: they are left out of the speech and kept in the context.
- Unfinished tags: a tag cut off at the end of a reply or by an interruption is removed.
- A TTS service after the LLM: the LLM is taught the tags of the TTS service that speaks its replies. When a settings change, such as a new model or voice, changes what it performs, the LLM is taught the new tags.