Wrap OpenAI SSE stream and persist completion metadata.
(
stream: AsyncGenerator[str, None],
*,
provider: str,
model: str,
source_info: RequestSourceInfo,
started_at: float,
)
| 185 | |
| 186 | |
| 187 | async def wrap_openai_stream_with_logging( |
| 188 | stream: AsyncGenerator[str, None], |
| 189 | *, |
| 190 | provider: str, |
| 191 | model: str, |
| 192 | source_info: RequestSourceInfo, |
| 193 | started_at: float, |
| 194 | ) -> AsyncGenerator[str, None]: |
| 195 | """Wrap OpenAI SSE stream and persist completion metadata.""" |
| 196 | success = True |
| 197 | status_code = 200 |
| 198 | error_message: Optional[str] = None |
| 199 | first_token_time = 0.0 |
| 200 | usage = { |
| 201 | "input_tokens": 0, |
| 202 | "output_tokens": 0, |
| 203 | "cache_creation_tokens": 0, |
| 204 | "cache_read_tokens": 0, |
| 205 | "total_tokens": 0, |
| 206 | } |
| 207 | |
| 208 | try: |
| 209 | async for chunk in stream: |
| 210 | if chunk.startswith("data: "): |
| 211 | payload_text = chunk[6:].strip() |
| 212 | if payload_text and payload_text != "[DONE]": |
| 213 | try: |
| 214 | payload = json.loads(payload_text) |
| 215 | except json.JSONDecodeError: |
| 216 | payload = None |
| 217 | |
| 218 | if isinstance(payload, dict): |
| 219 | if "error" in payload: |
| 220 | success = False |
| 221 | error = payload.get("error") or {} |
| 222 | error_message = ( |
| 223 | error.get("message") |
| 224 | or "Unknown stream error" |
| 225 | ) |
| 226 | status_code = int(error.get("code") or 500) |
| 227 | else: |
| 228 | if ( |
| 229 | not first_token_time |
| 230 | and _openai_payload_has_output(payload) |
| 231 | ): |
| 232 | first_token_time = max( |
| 233 | 0.0, |
| 234 | time.perf_counter() - started_at, |
| 235 | ) |
| 236 | if payload.get("usage"): |
| 237 | usage = _merge_usage( |
| 238 | usage, |
| 239 | extract_openai_usage(payload), |
| 240 | include_cache_in_total=False, |
| 241 | ) |
| 242 | |
| 243 | yield chunk |
| 244 | except Exception as exc: |
no test coverage detected