| name | streaming |
| description | JOB-253 — correct streaming pattern via stream() return value; removing streaming_func side-channel. |
Use llm.stream() or chain.stream() — they return Pin>. Never use
streaming_func in CallOptions; that is a deprecated side-channel that will be removed (JOB-253).
## Correct Streaming Pattern
use futures::StreamExt;
use langchainx::{
chain::{Chain, LLMChainBuilder},
prompt_args,
};
let chain = LLMChainBuilder::new().llm(llm).prompt(prompt).build()?;
let mut stream = chain.stream(prompt_args! { "input" => "Write a poem" }).await?;
while let Some(chunk) = stream.next().await {
match chunk {
Ok(data) => print!("{}", data.content),
Err(e) => eprintln!("error: {e}"),
}
}
println!();
## LLM-Level Streaming
use langchainx::language_models::llm::LLM;
use langchainx::schemas::Message;
let mut stream = llm.stream(&[Message::new_human_message("Hello")]).await?;
while let Some(chunk) = stream.next().await {
let data = chunk?;
if !data.content.is_empty() {
print!("{}", data.content);
}
}
## Anti-Pattern: streaming_func (JOB-253 — DO NOT USE)
let options = CallOptions::new()
.with_streaming_func(|chunk| async move {
print!("{chunk}");
Ok(())
});
let llm = OpenAI::default().with_options(options);
let result = llm.generate(&messages).await?;
Problems with streaming_func:
- Runtime state inside a config struct
Arc<Mutex<FnMut>> contamination
- Result (full string) and display (callback) are completely separate
- Cannot be tested without an async closure mock
## StreamData Fields
pub struct StreamData {
pub value: Value,
pub tokens: Option<TokenUsage>,
pub content: String,
}