(&self, request: ChatRequest)
| 349 | } |
| 350 | |
| 351 | async fn chat_stream(&self, request: ChatRequest) -> Result<StreamResult, ProviderError> { |
| 352 | let endpoint = self.get_endpoint(); |
| 353 | let model_id = request.model.clone(); |
| 354 | let model_id_encoded = urlencoding::encode(&model_id); |
| 355 | |
| 356 | let bedrock_request = self.convert_request(request); |
| 357 | let body = serde_json::to_vec(&bedrock_request) |
| 358 | .map_err(|e| ProviderError::ApiError(e.to_string()))?; |
| 359 | |
| 360 | let headers = self |
| 361 | .sign_request( |
| 362 | "POST", |
| 363 | &format!("/model/{}/converse-stream", model_id_encoded), |
| 364 | &body, |
| 365 | ) |
| 366 | .await?; |
| 367 | |
| 368 | let url = format!("{}/model/{}/converse-stream", endpoint, model_id_encoded); |
| 369 | |
| 370 | let response = self |
| 371 | .client |
| 372 | .post(&url) |
| 373 | .headers(headers) |
| 374 | .header("Accept", "application/vnd.amazon.eventstream") |
| 375 | .body(body) |
| 376 | .send() |
| 377 | .await |
| 378 | .map_err(|e| ProviderError::NetworkError(e.to_string()))?; |
| 379 | |
| 380 | if !response.status().is_success() { |
| 381 | let status = response.status(); |
| 382 | let body = response.text().await.unwrap_or_default(); |
| 383 | return Err(ProviderError::ApiError(format!("{}: {}", status, body))); |
| 384 | } |
| 385 | |
| 386 | let stream = response |
| 387 | .bytes_stream() |
| 388 | .map(move |chunk_result| match chunk_result { |
| 389 | Ok(bytes) => { |
| 390 | let text = String::from_utf8_lossy(&bytes); |
| 391 | parse_bedrock_stream(&text) |
| 392 | } |
| 393 | Err(e) => Err(ProviderError::StreamError(e.to_string())), |
| 394 | }); |
| 395 | |
| 396 | Ok(Box::pin(stream)) |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | #[derive(Debug, Serialize)] |
nothing calls this directly
no test coverage detected