Expand description
Provider-native interactive values and the unique session handle.
SessionConfig carries no model selector: open it through one exact
crate::ModelBackend. Drive SessionBackend::send and SessionBackend::recv
through a unique mutable Session, then consume it with SessionBackend::close.
Provider shutdown remains shared. Ordinary multi-turn generation uses messages
and opaque continuation; it does not require a native Session.
§Supplied support and a complete text turn
The supplied Session implementation is OpenAI-only. Supplied Gemini,
Anthropic and Ollama Models return Unsupported; their stateless operations remain
separate. The portable trait also supports independently implemented caller
Sessions, as illustrated on crate::ProviderBackend. Stateless OpenAI audio
input is unsupported; OpenAI Realtime audio is a Session operation.
This example requires OpenAI credentials and access to gpt-realtime-2.1.
A text turn may produce several audio and transcription events before completion.
Advisory usage/output is not a terminal signal; cancellation is not completion.
The caller applies a single turn deadline and consumes close even after a turn
error. Function requests would need a configured application handler and exact
FunctionResult correlation; this text-only example configures no functions.
use std::time::Duration;
use providers_kit::{Provider, ProviderBackend, ProviderConfig, ModelBackend, ModelId, SessionBackend};
use providers_kit::config::{ApiKey, OpenAiConfig, ProviderKind, TransportConfig};
use providers_kit::session::{SessionConfig, SessionEvent, SessionInput};
let provider = Provider::from_config(ProviderConfig::new(
ProviderKind::OpenAi(OpenAiConfig::new(ApiKey::new("replace-with-your-key")?)),
TransportConfig::default(),
))?;
let work = async {
let model = provider.model(ModelId::new("gpt-realtime-2.1")?)?;
let config = SessionConfig::default().with_output_audio("audio/pcm;rate=24000", true)?;
let mut session = model.open_session(config).await?;
let turn = tokio::time::timeout(Duration::from_secs(90), async {
session.send(SessionInput::Text { text: "Describe one use of a bicycle.".into() }).await?;
let mut audio_bytes = 0usize;
let mut transcript_bytes = 0usize;
let mut substantive_transcript = false;
loop {
match session.recv().await? {
SessionEvent::Audio { data, .. } => audio_bytes += data.len(),
SessionEvent::OutputTranscriptionDelta { delta } => {
transcript_bytes += delta.len();
substantive_transcript |= !delta.trim().is_empty();
}
SessionEvent::Completed => break,
SessionEvent::TurnCancelled | SessionEvent::FunctionCall(_)
| SessionEvent::FunctionCallsCancelled { .. } => return Err("unexpected control event".into()),
SessionEvent::TextDelta { .. } | SessionEvent::InputTranscriptionDelta { .. }
| SessionEvent::Usage(_) => {}
}
if audio_bytes > 8 * 1024 * 1024 || transcript_bytes > 1024 * 1024 {
return Err("example output bound exceeded".into());
}
}
if audio_bytes == 0 || !substantive_transcript { return Err("missing output".into()); }
Ok::<(), Box<dyn std::error::Error>>(())
}).await;
let closed = session.close().await;
turn??;
closed?;
Ok::<(), Box<dyn std::error::Error>>(())
}.await;
let shutdown = provider.shutdown().await;
work?;
shutdown?;For manual audio, send TurnStart, one or more raw Audio chunks in the exact
configured format, then TurnEnd; receive until a native terminal event. A raw
chunk is not a whole-turn or automatic flush operation. Output wording is
model-authored, not a Kit exact-copy guarantee.
Structs§
- Session
- Unique opaque provider-native interactive session supplied for OpenAI models.
- Session
Config - Defaults applied to one provider-native interactive session.
Enums§
- Session
Event - Event received from an interactive session.
- Session
Input - Input sent to an interactive session.
- Session
Turn Detection - Portable interactive audio turn detection.
Traits§
- Session
Backend - Public implementation contract for one unique provider-native session.