@@ -335,6 +335,8 @@ async def wrapper(
335335class StreamingWrapper (ObjectProxy ): # type: ignore[misc]
336336 """Wrapper for streaming responses"""
337337
338+ _netra_stream_wrapper = True
339+
338340 def __init__ (self , span : Span , response : Iterator [Any ], request_kwargs : Dict [str , Any ]) -> None :
339341 super ().__init__ (response )
340342 self ._span = span
@@ -354,6 +356,15 @@ def _ensure_choice(self, index: int) -> None:
354356 else :
355357 self ._complete_response ["choices" ].append ({"text" : "" })
356358
359+ def _extract_content_text (self ) -> str :
360+ """Extract the plain text content from the accumulated response."""
361+ parts = []
362+ for choice in self ._complete_response .get ("choices" , []):
363+ msg = choice .get ("message" , {})
364+ if content := msg .get ("content" ):
365+ parts .append (content )
366+ return "" .join (parts )
367+
357368 def __enter__ (self ) -> "StreamingWrapper" :
358369 if hasattr (self .__wrapped__ , "__enter__" ):
359370 self .__wrapped__ .__enter__ ()
@@ -444,13 +455,16 @@ def _finalize_span(self) -> None:
444455 """Finalize span when streaming is complete"""
445456 record_span_timing (self ._span , LLM_RESPONSE_DURATION )
446457 set_response_attributes (self ._span , self ._complete_response )
458+ self ._netra_output = self ._extract_content_text ()
447459 self ._span .set_status (Status (StatusCode .OK ))
448460 self ._span .end ()
449461
450462
451463class AsyncStreamingWrapper (ObjectProxy ): # type: ignore[misc]
452464 """Async wrapper for streaming responses"""
453465
466+ _netra_stream_wrapper = True
467+
454468 def __init__ (self , span : Span , response : AsyncIterator [Any ], request_kwargs : Dict [str , Any ]) -> None :
455469 super ().__init__ (response )
456470 self ._span = span
@@ -470,6 +484,15 @@ def _ensure_choice(self, index: int) -> None:
470484 else :
471485 self ._complete_response ["choices" ].append ({"text" : "" })
472486
487+ def _extract_content_text (self ) -> str :
488+ """Extract the plain text content from the accumulated response."""
489+ parts = []
490+ for choice in self ._complete_response .get ("choices" , []):
491+ msg = choice .get ("message" , {})
492+ if content := msg .get ("content" ):
493+ parts .append (content )
494+ return "" .join (parts )
495+
473496 async def __aenter__ (self ) -> "AsyncStreamingWrapper" :
474497 if hasattr (self .__wrapped__ , "__aenter__" ):
475498 await self .__wrapped__ .__aenter__ ()
@@ -560,5 +583,6 @@ def _finalize_span(self) -> None:
560583 """Finalize span when streaming is complete"""
561584 record_span_timing (self ._span , LLM_RESPONSE_DURATION )
562585 set_response_attributes (self ._span , self ._complete_response )
586+ self ._netra_output = self ._extract_content_text ()
563587 self ._span .set_status (Status (StatusCode .OK ))
564588 self ._span .end ()
0 commit comments