MCPcopy Index your code
hub / github.com/InfinitiBit/graphbit / streaming_response

Method streaming_response

python/src/llm/client.rs:1245–1310  ·  view source on GitHub ↗

Stream and print the response in real-time Returns the complete response as a string after streaming Usage in Python: response = await chunks.streaming_response() # Chunks are printed in real-time, then full response is returned

(&'a self, py: Python<'a>)

Source from the content-addressed store, hash-verified

1243 /// response = await chunks.streaming_response()
1244 /// # Chunks are printed in real-time, then full response is returned
1245 fn streaming_response<'a>(&'a self, py: Python<'a>) -> PyResult<Bound<'a, PyAny>> {
1246 let provider = Arc::clone(&self.provider);
1247 let prompt = self.prompt.clone();
1248 let max_tokens = self.max_tokens;
1249 let temperature = self.temperature;
1250 let stream = Arc::clone(&self.stream);
1251 let initialized = Arc::clone(&self.initialized);
1252
1253 pyo3_async_runtimes::tokio::future_into_py(py, async move {
1254 // Phase 1: Initialize stream if needed (using OnceCell - no lock held during init)
1255 let init_result = initialized
1256 .get_or_try_init(|| async {
1257 // Build request
1258 let mut request = LlmRequest::new(prompt.clone());
1259 if let Some(tokens) = max_tokens {
1260 request = request.with_max_tokens(tokens);
1261 }
1262 if let Some(temp) = temperature {
1263 request = request.with_temperature(temp);
1264 }
1265
1266 // Get stream from provider (NO MUTEX HELD during this await!)
1267 let guard = provider.read().await;
1268 let provider_stream = guard.stream(request).await.map_err(to_py_error)?;
1269 drop(guard); // Explicitly drop read lock before acquiring mutex
1270
1271 // Now briefly hold mutex just to store the stream
1272 let mut stream_guard = stream.lock().await;
1273 *stream_guard = Some(Box::pin(provider_stream));
1274 drop(stream_guard); // Explicitly release mutex
1275
1276 Ok::<(), PyErr>(())
1277 })
1278 .await;
1279
1280 // Check if initialization failed
1281 init_result?;
1282
1283 // Phase 2: Collect and print chunks in real-time
1284 let mut full_response = String::new();
1285
1286 // Hold mutex for streaming - but now we're just polling, not doing heavy I/O
1287 let mut stream_guard = stream.lock().await;
1288 if let Some(ref mut s) = *stream_guard {
1289 while let Some(result) = s.next().await {
1290 match result {
1291 Ok(response) => {
1292 // Print chunk immediately (to stdout) - handle errors gracefully
1293 print!("{}", response.content);
1294 use std::io::Write;
1295 let _ = std::io::stdout().flush(); // Don't panic if flush fails
1296
1297 // Accumulate for final response
1298 full_response.push_str(&response.content);
1299 }
1300 Err(e) => {
1301 // Always propagate errors
1302 return Err(to_py_error(e));

Callers

nothing calls this directly

Calls 5

to_py_errorFunction · 0.85
cloneMethod · 0.80
with_max_tokensMethod · 0.45
with_temperatureMethod · 0.45
streamMethod · 0.45

Tested by

no test coverage detected