Skip to content

Commit 79b69bd

Browse files
authored
feat: add deprecated replicate.stream() for v1 compatibility (#79)
* feat: add deprecated replicate.stream() for v1 compatibility Add deprecated replicate.stream() method as a wrapper around replicate.use() with streaming=True to provide backwards compatibility with the v1 SDK. - Add stream() methods to Replicate and AsyncReplicate classes - Add module-level stream() function - Use @deprecated decorator with clear migration message - Add detailed deprecation warning with example code - Add comprehensive tests for sync, async, and deprecation warnings - Update README to recommend replicate.use() with streaming=True - Use anthropic/claude-4.5-sonnet in all examples Resolves: DP-671 * fix: add pyright ignores for deprecated function usage in tests and internal calls * fix: correct test assertions and add missing pyright ignore * fix: add pyright ignores for deprecated imports and unknown types * fix: add mypy type ignore for var-annotated * docs: remove incorrect Raises section from stream() docstring The stream() function issues a deprecation warning via warnings.warn() but doesn't raise an exception, so the Raises section was incorrect.
1 parent f85db05 commit 79b69bd

File tree

6 files changed

+431
-31
lines changed

6 files changed

+431
-31
lines changed

README.md

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,24 @@ output = replicate.run("...", input={...}, wait=False)
110110

111111
When `wait=False`, the method returns immediately after creating the prediction, and you'll need to poll for the result manually.
112112

113+
## Streaming output
114+
115+
For models that support streaming (particularly language models), use `replicate.use()` with `streaming=True` to stream the output response as it's generated:
116+
117+
```python
118+
import replicate
119+
120+
claude = replicate.use("anthropic/claude-4.5-sonnet", streaming=True)
121+
122+
for event in claude(input={"prompt": "Please write a haiku about streaming Python."}):
123+
print(str(event), end="")
124+
```
125+
126+
> **Note:** The [legacy `replicate.stream()` method](https://github.com/replicate/replicate-python/blob/d2956ff9c3e26ef434bc839cc5c87a50c49dfe20/README.md#run-a-model-and-stream-its-output) is also available for backwards compatibility with the v1 SDK, but is deprecated and will be removed in a future version.
127+
113128
## Async usage
114129

115-
Simply import `AsyncReplicate` instead of `Replicate` and use `await` with each API call:
130+
To use the Replicate client asynchronously, import `AsyncReplicate` instead of `Replicate` and use `await` with each API call:
116131

117132
```python
118133
import os
@@ -136,34 +151,6 @@ asyncio.run(main())
136151

137152
Functionality between the synchronous and asynchronous clients is otherwise identical.
138153

139-
### Async run() and stream()
140-
141-
The async client also supports `run()` and `stream()` methods:
142-
143-
```python
144-
import asyncio
145-
from replicate import AsyncReplicate
146-
147-
replicate = AsyncReplicate()
148-
149-
150-
async def main():
151-
# Run a model
152-
output = await replicate.run(
153-
"black-forest-labs/flux-schnell", input={"prompt": "astronaut riding a rocket like a horse"}
154-
)
155-
print(output)
156-
157-
# Stream a model's output
158-
async for event in replicate.stream(
159-
"meta/meta-llama-3-70b-instruct", input={"prompt": "Write a haiku about coding"}
160-
):
161-
print(str(event), end="")
162-
163-
164-
asyncio.run(main())
165-
```
166-
167154
### With aiohttp
168155

169156
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.

src/replicate/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
if not __name.startswith("__"):
110110
try:
111111
# Skip symbols that are imported later from _module_client
112-
if __name in ("run", "use"):
112+
if __name in ("run", "use", "stream"):
113113
continue
114114
__locals[__name].__module__ = "replicate"
115115
except (TypeError, AttributeError):
@@ -253,6 +253,7 @@ def _reset_client() -> None: # type: ignore[reportUnusedFunction]
253253
use as use,
254254
files as files,
255255
models as models,
256+
stream as stream, # pyright: ignore[reportDeprecated]
256257
account as account,
257258
hardware as hardware,
258259
webhooks as webhooks,

src/replicate/_client.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
AsyncIterator,
1717
overload,
1818
)
19-
from typing_extensions import Self, Unpack, ParamSpec, override
19+
from typing_extensions import Self, Unpack, ParamSpec, override, deprecated
2020

2121
import httpx
2222

@@ -321,6 +321,38 @@ def use(
321321
# TODO: Fix mypy overload matching for streaming parameter
322322
return _use(self, ref, hint=hint, streaming=streaming) # type: ignore[call-overload, no-any-return]
323323

324+
@deprecated("replicate.stream() is deprecated. Use replicate.use() with streaming=True instead")
325+
def stream(
326+
self,
327+
ref: str,
328+
*,
329+
input: dict[str, Any],
330+
) -> Iterator[str]:
331+
"""
332+
Run a model and stream its output (deprecated).
333+
334+
.. deprecated::
335+
Use :meth:`use` with ``streaming=True`` instead:
336+
337+
.. code-block:: python
338+
339+
model = replicate.use("anthropic/claude-4.5-sonnet", streaming=True)
340+
for event in model(input={"prompt": "Hello"}):
341+
print(str(event), end="")
342+
343+
Args:
344+
ref: Reference to the model to run. Can be a string with owner/name format
345+
(e.g., "anthropic/claude-4.5-sonnet") or owner/name:version format.
346+
input: Dictionary of input parameters for the model. The required keys depend
347+
on the specific model being run.
348+
349+
Returns:
350+
An iterator that yields output strings as they are generated by the model
351+
"""
352+
from .lib._stream import stream as _stream # pyright: ignore[reportDeprecated]
353+
354+
return _stream(type(self), ref, input=input) # type: ignore[return-value, arg-type]
355+
324356
def copy(
325357
self,
326358
*,
@@ -696,6 +728,38 @@ def use(
696728
# TODO: Fix mypy overload matching for streaming parameter
697729
return _use(self, ref, hint=hint, streaming=streaming) # type: ignore[call-overload, no-any-return]
698730

731+
@deprecated("replicate.stream() is deprecated. Use replicate.use() with streaming=True instead")
732+
async def stream(
733+
self,
734+
ref: str,
735+
*,
736+
input: dict[str, Any],
737+
) -> AsyncIterator[str]:
738+
"""
739+
Run a model and stream its output asynchronously (deprecated).
740+
741+
.. deprecated::
742+
Use :meth:`use` with ``streaming=True`` instead:
743+
744+
.. code-block:: python
745+
746+
model = replicate.use("anthropic/claude-4.5-sonnet", streaming=True)
747+
async for event in model(input={"prompt": "Hello"}):
748+
print(str(event), end="")
749+
750+
Args:
751+
ref: Reference to the model to run. Can be a string with owner/name format
752+
(e.g., "anthropic/claude-4.5-sonnet") or owner/name:version format.
753+
input: Dictionary of input parameters for the model. The required keys depend
754+
on the specific model being run.
755+
756+
Returns:
757+
An async iterator that yields output strings as they are generated by the model
758+
"""
759+
from .lib._stream import stream as _stream # pyright: ignore[reportDeprecated]
760+
761+
return _stream(type(self), ref, input=input) # type: ignore[return-value, arg-type]
762+
699763
def copy(
700764
self,
701765
*,

src/replicate/_module_client.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def __load__(self) -> PredictionsResource:
8282
__client: Replicate = cast(Replicate, {})
8383
run = __client.run
8484
use = __client.use
85+
stream = __client.stream # pyright: ignore[reportDeprecated]
8586
else:
8687

8788
def _run(*args, **kwargs):
@@ -100,8 +101,21 @@ def _use(ref, *, hint=None, streaming=False, use_async=False, **kwargs):
100101

101102
return use(Replicate, ref, hint=hint, streaming=streaming, **kwargs)
102103

104+
def _stream(ref, *, input, use_async=False):
105+
from .lib._stream import stream
106+
107+
if use_async:
108+
from ._client import AsyncReplicate
109+
110+
return stream(AsyncReplicate, ref, input=input)
111+
112+
from ._client import Replicate
113+
114+
return stream(Replicate, ref, input=input)
115+
103116
run = _run
104117
use = _use
118+
stream = _stream
105119

106120
files: FilesResource = FilesResourceProxy().__as_proxied__()
107121
models: ModelsResource = ModelsResourceProxy().__as_proxied__()

src/replicate/lib/_stream.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""
2+
Deprecated streaming functionality for backwards compatibility with v1 SDK.
3+
4+
This module provides the stream() function which wraps replicate.use() with streaming=True.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
import warnings
10+
from typing import Any, Dict, Type, Union, Iterator, AsyncIterator, overload
11+
from typing_extensions import deprecated
12+
13+
from .._client import Client, AsyncClient
14+
from ._predictions_use import use
15+
16+
__all__ = ["stream"]
17+
18+
19+
def _format_deprecation_message(ref: str, input: Dict[str, Any]) -> str:
20+
"""Format the deprecation message with a working example."""
21+
# Format the input dict for display
22+
input_str = "{\n"
23+
for key, value in input.items():
24+
if isinstance(value, str):
25+
input_str += f' "{key}": "{value}",\n'
26+
else:
27+
input_str += f' "{key}": {value},\n'
28+
input_str += " }"
29+
30+
return (
31+
f"replicate.stream() is deprecated and will be removed in a future version. "
32+
f"Use replicate.use() with streaming=True instead:\n\n"
33+
f' model = replicate.use("{ref}", streaming=True)\n'
34+
f" for event in model(input={input_str}):\n"
35+
f' print(str(event), end="")\n'
36+
)
37+
38+
39+
@overload
40+
def stream(
41+
client: Type[Client],
42+
ref: str,
43+
*,
44+
input: Dict[str, Any],
45+
) -> Iterator[str]: ...
46+
47+
48+
@overload
49+
def stream(
50+
client: Type[AsyncClient],
51+
ref: str,
52+
*,
53+
input: Dict[str, Any],
54+
) -> AsyncIterator[str]: ...
55+
56+
57+
@deprecated("replicate.stream() is deprecated. Use replicate.use() with streaming=True instead")
58+
def stream(
59+
client: Union[Type[Client], Type[AsyncClient]],
60+
ref: str,
61+
*,
62+
input: Dict[str, Any],
63+
) -> Union[Iterator[str], AsyncIterator[str]]:
64+
"""
65+
Run a model and stream its output (deprecated).
66+
67+
This function is deprecated. Use replicate.use() with streaming=True instead:
68+
69+
model = replicate.use("anthropic/claude-4.5-sonnet", streaming=True)
70+
for event in model(input={"prompt": "Hello"}):
71+
print(str(event), end="")
72+
73+
Args:
74+
client: The Replicate client class (Client or AsyncClient)
75+
ref: Reference to the model to run. Can be a string with owner/name format
76+
(e.g., "anthropic/claude-4.5-sonnet") or owner/name:version format.
77+
input: Dictionary of input parameters for the model. The required keys depend
78+
on the specific model being run.
79+
80+
Returns:
81+
An iterator (or async iterator) that yields output strings as they are
82+
generated by the model
83+
"""
84+
# Log deprecation warning with helpful migration example
85+
warnings.warn(
86+
_format_deprecation_message(ref, input),
87+
DeprecationWarning,
88+
stacklevel=2,
89+
)
90+
91+
# Use the existing use() function with streaming=True
92+
model = use(client, ref, streaming=True) # type: ignore[var-annotated] # pyright: ignore[reportUnknownVariableType]
93+
94+
# Call the model with the input
95+
return model(**input) # type: ignore[return-value]

0 commit comments

Comments
 (0)