swiftide/examples/streaming_agents.rs

59 lines
2.1 KiB
Rust

//! This example demonstrates how to stream responses from an agent
//!
//! By default, for convenience the accumulated response is streamed. You can opt-out of this
//! behaviour and only receive the delta as well (only with OpenAI-like providers).
use anyhow::Result;
use swiftide::agents;
#[tokio::main]
async fn main() -> Result<()> {
let openai = swiftide::integrations::openai::OpenAI::builder()
.default_embed_model("text-embeddings-3-small")
.default_prompt_model("gpt-4o-mini")
// Only streams the delta, leave this out to stream the full response
.stream_full(false)
.build()?;
// let anthropic = swiftide::integrations::anthropic::Anthropic::builder()
// .default_prompt_model("claude-3-7-sonnet-latest")
// .build()?;
agents::Agent::builder()
.llm(&openai)
.on_stream(|_agent, response| {
// We print the message chunk if it exists. Streamed responses also include
// the full response (without tool calls) in `message` and an `id` to map them to
// previous chunks for convenience.
//
// The agent uses the full assembled response at the end of the stream.
if let Some(delta) = &response.delta {
print!(
"{}",
delta
.message_chunk
.as_deref()
.map(str::to_string)
.unwrap_or_default()
);
};
// If `stream_full` is disabled, response.message() will be the accumulated response
// response.message()
Box::pin(async move { Ok(()) })
})
// Every message added by the agent will be printed to stdout
.on_new_message(move |_, msg| {
let msg = msg.to_string();
Box::pin(async move {
println!("\n---\nFinal message:\n {msg}");
Ok(())
})
})
.limit(5)
.build()?
.query("Why is the rust programming language so good?")
.await?;
Ok(())
}