Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion dspy/streaming/streaming_listener.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import re
from collections import defaultdict
from queue import Queue
Expand Down Expand Up @@ -135,7 +136,12 @@ def receive(self, chunk: ModelResponseStream):
return

# Handle custom streamable types
if self._output_type and issubclass(self._output_type, Type) and self._output_type.is_streamable():
if (
self._output_type
and inspect.isclass(self._output_type)
and issubclass(self._output_type, Type)
and self._output_type.is_streamable()
):
if parsed_chunk := self._output_type.parse_stream_chunk(chunk):
return StreamResponse(
self.predict_name,
Expand Down
21 changes: 21 additions & 0 deletions tests/streaming/test_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -1932,3 +1932,24 @@ async def non_reasoning_stream(*args, **kwargs):
assert final_prediction.reasoning.content == "Let's think step by step about this question."
# Verify Reasoning object is str-like
assert str(final_prediction.reasoning) == "Let's think step by step about this question."


@pytest.mark.anyio
async def test_stream_listener_with_generic_type_annotation():
class TestSignature(dspy.Signature):
input_text: str = dspy.InputField()
output_list: list[str] | int = dspy.OutputField()

predict = dspy.Predict(TestSignature)
listener = dspy.streaming.StreamListener(signature_field_name="output_list", predict=predict)

assert listener._output_type == list[str] | int

mock_chunk = ModelResponseStream(
model="gpt-4o-mini",
choices=[StreamingChoices(delta=Delta(content="test"))],
)

with dspy.context(adapter=dspy.JSONAdapter()):
result = listener.receive(mock_chunk)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do get what the test case is testing, but our future maintainers could be confused. Maybe add a few more chunks + flush to make the test easier to follow?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, updated the test case into a full example of streaming

assert result is None