Skip to content

Commit fb3cbbb

Browse files
refactor: add Chunk type parameter to Stream class for type-safe streaming (#42)
Make Stream generic over Chunk type to enable capability-specific chunk types, improving type safety and IDE support across all streaming implementations. Changes: - Add Chunk type parameter to Stream[Out, Params, Chunk] base class - Update all provider streaming implementations to use specific chunk types (TextGenerationChunk, ImageGenerationChunk) instead of generic Chunk - Update Client.stream() and _stream_class() return types to include Chunk - Remove generic Chunk imports from provider implementations - Update all tests to use new Stream signature - Remove streaming modules from mypy ignore lists (now properly typed) - Use ApplicationMimeType.JSON constant in HTTP tests Benefits: - Type-safe chunk parsing per capability - Better IDE autocomplete and type checking - Cleaner provider code without generic Chunk imports - Improved mypy compliance
1 parent 8852c07 commit fb3cbbb

15 files changed

Lines changed: 28 additions & 32 deletions

File tree

packages/image-generation/src/celeste_image_generation/providers/bytedance/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from typing import Any
66

77
from celeste.artifacts import ImageArtifact
8-
from celeste.io import Chunk
98
from celeste.mime_types import ImageMimeType
109
from celeste_image_generation.io import ImageGenerationChunk, ImageGenerationUsage
1110
from celeste_image_generation.streaming import ImageGenerationStream
@@ -21,7 +20,7 @@ def __init__(self, sse_iterator: AsyncIterator[dict[str, Any]]) -> None:
2120
super().__init__(sse_iterator)
2221
self._completed_usage: ImageGenerationUsage | None = None
2322

24-
def _parse_chunk(self, chunk_data: dict[str, Any]) -> Chunk | None:
23+
def _parse_chunk(self, chunk_data: dict[str, Any]) -> ImageGenerationChunk | None:
2524
"""Parse chunk from SSE event."""
2625
event_type = chunk_data.get("type")
2726

packages/image-generation/src/celeste_image_generation/providers/openai/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from typing import Any
66

77
from celeste.artifacts import ImageArtifact
8-
from celeste.io import Chunk
98
from celeste_image_generation.io import ImageGenerationChunk, ImageGenerationUsage
109
from celeste_image_generation.streaming import ImageGenerationStream
1110

@@ -15,7 +14,7 @@
1514
class OpenAIImageGenerationStream(ImageGenerationStream):
1615
"""OpenAI streaming for image generation."""
1716

18-
def _parse_chunk(self, chunk_data: dict[str, Any]) -> Chunk | None:
17+
def _parse_chunk(self, chunk_data: dict[str, Any]) -> ImageGenerationChunk | None:
1918
"""Parse chunk from SSE event.
2019
2120
OpenAI returns two event types:

packages/image-generation/src/celeste_image_generation/streaming.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
from celeste_image_generation.parameters import ImageGenerationParameters
1313

1414

15-
class ImageGenerationStream(Stream[ImageGenerationOutput, ImageGenerationParameters]):
15+
class ImageGenerationStream(
16+
Stream[ImageGenerationOutput, ImageGenerationParameters, ImageGenerationChunk]
17+
):
1618
"""Streaming for image generation."""
1719

1820
def _parse_output(

packages/text-generation/src/celeste_text_generation/providers/anthropic/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from collections.abc import Callable
44
from typing import Any, Unpack
55

6-
from celeste.io import Chunk
76
from celeste_text_generation.io import (
87
TextGenerationChunk,
98
TextGenerationFinishReason,
@@ -34,7 +33,7 @@ def __init__(
3433
self._transform_output = transform_output
3534
self._last_finish_reason: TextGenerationFinishReason | None = None
3635

37-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
36+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
3837
"""Parse SSE event into Chunk."""
3938
event_type = event.get("type")
4039
if not event_type:

packages/text-generation/src/celeste_text_generation/providers/cohere/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from collections.abc import Callable
55
from typing import Any, Unpack
66

7-
from celeste.io import Chunk
87
from celeste_text_generation.io import (
98
TextGenerationChunk,
109
TextGenerationFinishReason,
@@ -36,7 +35,7 @@ def __init__(
3635
super().__init__(sse_iterator, **parameters)
3736
self._transform_output = transform_output
3837

39-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
38+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
4039
"""Parse SSE event into Chunk, extracting text deltas and metadata."""
4140
event_type = event.get("type")
4241

packages/text-generation/src/celeste_text_generation/providers/google/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from collections.abc import Callable
44
from typing import Any, Unpack
55

6-
from celeste.io import Chunk
76
from celeste_text_generation.io import (
87
TextGenerationChunk,
98
TextGenerationFinishReason,
@@ -33,7 +32,7 @@ def __init__(
3332
super().__init__(sse_iterator, **parameters)
3433
self._transform_output = transform_output
3534

36-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
35+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
3736
"""Parse SSE event into Chunk.
3837
3938
Extract text delta from candidates[0].content.parts[0].text.

packages/text-generation/src/celeste_text_generation/providers/mistral/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from collections.abc import Callable
55
from typing import Any, Unpack
66

7-
from celeste.io import Chunk
87
from celeste_text_generation.io import (
98
TextGenerationChunk,
109
TextGenerationFinishReason,
@@ -36,7 +35,7 @@ def __init__(
3635
super().__init__(sse_iterator, **parameters)
3736
self._transform_output = transform_output
3837

39-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
38+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
4039
"""Parse chunk from SSE event.
4140
4241
Extract from choices[0].delta.content (content delta events).

packages/text-generation/src/celeste_text_generation/providers/openai/streaming.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from collections.abc import Callable
44
from typing import Any, Unpack
55

6-
from celeste.io import Chunk
76
from celeste_text_generation.io import (
87
TextGenerationChunk,
98
TextGenerationFinishReason,
@@ -27,7 +26,7 @@ def __init__(
2726
super().__init__(sse_iterator, **parameters)
2827
self._transform_output = transform_output
2928

30-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
29+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
3130
"""Parse SSE event into Chunk."""
3231
event_type = event.get("type")
3332
if not event_type:

packages/text-generation/src/celeste_text_generation/streaming.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from abc import abstractmethod
44
from typing import Any, Unpack
55

6-
from celeste.io import Chunk
76
from celeste.streaming import Stream
87
from celeste_text_generation.io import (
98
TextGenerationChunk,
@@ -13,11 +12,13 @@
1312
from celeste_text_generation.parameters import TextGenerationParameters
1413

1514

16-
class TextGenerationStream(Stream[TextGenerationOutput, TextGenerationParameters]):
15+
class TextGenerationStream(
16+
Stream[TextGenerationOutput, TextGenerationParameters, TextGenerationChunk]
17+
):
1718
"""Streaming for text generation."""
1819

1920
@abstractmethod
20-
def _parse_chunk(self, event: dict[str, Any]) -> Chunk | None:
21+
def _parse_chunk(self, event: dict[str, Any]) -> TextGenerationChunk | None:
2122
"""Parse SSE event into Chunk (provider-specific)."""
2223

2324
def _parse_output(

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ ignore_missing_imports = true
165165
module = [
166166
"celeste_text_generation.*",
167167
"celeste_text_generation.client",
168-
"celeste_text_generation.streaming",
169168
"celeste_text_generation.providers.*",
170169
]
171170
disable_error_code = ["override", "return-value", "arg-type", "call-arg", "assignment", "no-any-return"]
@@ -174,7 +173,6 @@ disable_error_code = ["override", "return-value", "arg-type", "call-arg", "assig
174173
module = [
175174
"celeste_image_generation.*",
176175
"celeste_image_generation.client",
177-
"celeste_image_generation.streaming",
178176
"celeste_image_generation.providers.*",
179177
]
180178
disable_error_code = ["override", "return-value", "arg-type", "call-arg", "assignment", "no-any-return"]

0 commit comments

Comments
 (0)