diff --git a/llama-index-core/llama_index/core/base/response/schema.py b/llama-index-core/llama_index/core/base/response/schema.py index f3239338bbab2c0f8d9134c96c83872eff89b1a4..3689ed2cefa514d14f8da2357c2965cf0e4a7404 100644 --- a/llama-index-core/llama_index/core/base/response/schema.py +++ b/llama-index-core/llama_index/core/base/response/schema.py @@ -159,6 +159,16 @@ class AsyncStreamingResponse: def __post_init__(self) -> None: self._lock = asyncio.Lock() + def __str__(self) -> str: + """Convert to string representation.""" + return asyncio.run(self._async_str) + + async def _async_str(self) -> str: + """Convert to string representation.""" + async for _ in self._yield_response(): + ... + return self.response_txt or "None" + async def _yield_response(self) -> TokenAsyncGen: """Yield the string response.""" async with self._lock: diff --git a/llama-index-core/llama_index/core/instrumentation/events/synthesis.py b/llama-index-core/llama_index/core/instrumentation/events/synthesis.py index 71251eaec63602d7fb68437261502beaae4139c5..27a3a03dd29baf957b1f10806c28d86894fac8df 100644 --- a/llama-index-core/llama_index/core/instrumentation/events/synthesis.py +++ b/llama-index-core/llama_index/core/instrumentation/events/synthesis.py @@ -1,4 +1,3 @@ -from llama_index.core.base.response.schema import RESPONSE_TYPE from llama_index.core.instrumentation.events.base import BaseEvent from llama_index.core.schema import QueryType @@ -14,7 +13,7 @@ class SynthesizeStartEvent(BaseEvent): class SynthesizeEndEvent(BaseEvent): query: QueryType - response: RESPONSE_TYPE + response: str @classmethod def class_name(cls): diff --git a/llama-index-core/llama_index/core/instrumentation/span_handlers/simple.py b/llama-index-core/llama_index/core/instrumentation/span_handlers/simple.py index 4cdee9d67d88f86bca92cfcd7e979e4fc4816e3c..1cea445b77b880599134547c45df87b5bb87ee7a 100644 --- a/llama-index-core/llama_index/core/instrumentation/span_handlers/simple.py +++ b/llama-index-core/llama_index/core/instrumentation/span_handlers/simple.py @@ -3,6 +3,7 @@ from llama_index.core.bridge.pydantic import Field from llama_index.core.instrumentation.span.simple import SimpleSpan from llama_index.core.instrumentation.span_handlers.base import BaseSpanHandler from datetime import datetime +import warnings if TYPE_CHECKING: from treelib import Tree @@ -42,6 +43,7 @@ class SimpleSpanHandler(BaseSpanHandler[SimpleSpan]): """Method for getting trace trees.""" try: from treelib import Tree + from treelib.exceptions import NodeIDAbsentError except ImportError as e: raise ImportError( "`treelib` package is missing. Please install it by using " @@ -59,12 +61,31 @@ class SimpleSpanHandler(BaseSpanHandler[SimpleSpan]): # start new tree tree = Tree() - tree.create_node( - tag=f"{span.id_} ({span.duration})", - identifier=span.id_, - parent=span.parent_id, - data=span.start_time, - ) + try: + tree.create_node( + tag=f"{span.id_} ({span.duration})", + identifier=span.id_, + parent=span.parent_id, + data=span.start_time, + ) + except NodeIDAbsentError: + warnings.warn("Parent with id {span.parent_id} missing from spans") + # create new tree and fake parent node + trees.append(tree) + tree = Tree() + tree.create_node( + tag=f"{span.parent_id} (MISSING)", + identifier=span.parent_id, + parent=None, + data=span.start_time, + ) + tree.create_node( + tag=f"{span.id_} ({span.duration})", + identifier=span.id_, + parent=span.parent_id, + data=span.start_time, + ) + trees.append(tree) return trees diff --git a/llama-index-core/llama_index/core/response_synthesizers/base.py b/llama-index-core/llama_index/core/response_synthesizers/base.py index ebedd93aa6f906b7d8e5a2fef8870c437728cb55..b8440807898a5e1486cdba4be74212f09c5c7f3c 100644 --- a/llama-index-core/llama_index/core/response_synthesizers/base.py +++ b/llama-index-core/llama_index/core/response_synthesizers/base.py @@ -209,13 +209,13 @@ class BaseSynthesizer(ChainableMixin, PromptMixin): response_gen=empty_response_generator() ) dispatcher.event( - SynthesizeEndEvent(query=query, response=empty_response) + SynthesizeEndEvent(query=query, response=str(empty_response)) ) return empty_response else: empty_response = Response("Empty Response") dispatcher.event( - SynthesizeEndEvent(query=query, response=empty_response) + SynthesizeEndEvent(query=query, response=str(empty_response)) ) return empty_response @@ -240,7 +240,7 @@ class BaseSynthesizer(ChainableMixin, PromptMixin): event.on_end(payload={EventPayload.RESPONSE: response}) - dispatcher.event(SynthesizeEndEvent(query=query, response=response)) + dispatcher.event(SynthesizeEndEvent(query=query, response=str(response))) return response @dispatcher.span @@ -258,13 +258,13 @@ class BaseSynthesizer(ChainableMixin, PromptMixin): response_gen=empty_response_agenerator() ) dispatcher.event( - SynthesizeEndEvent(query=query, response=empty_response) + SynthesizeEndEvent(query=query, response=str(empty_response)) ) return empty_response else: empty_response = Response("Empty Response") dispatcher.event( - SynthesizeEndEvent(query=query, response=empty_response) + SynthesizeEndEvent(query=query, response=str(empty_response)) ) return empty_response @@ -289,7 +289,7 @@ class BaseSynthesizer(ChainableMixin, PromptMixin): event.on_end(payload={EventPayload.RESPONSE: response}) - dispatcher.event(SynthesizeEndEvent(query=query, response=response)) + dispatcher.event(SynthesizeEndEvent(query=query, response=str(response))) return response def _as_query_component(self, **kwargs: Any) -> QueryComponent: