Skip to content

Commit 621162a

Browse files
committed
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
1 parent 2804bd6 commit 621162a

File tree

6 files changed

+430
-39
lines changed

6 files changed

+430
-39
lines changed

README.md

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +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-
## Run a model and stream its output
113+
## Streaming output
114114

115-
For models that support streaming (particularly language models), you can use `replicate.stream()`:
115+
For models that support streaming (particularly language models), use `replicate.use()` with `streaming=True` to stream the output response as it's generated:
116116

117117
```python
118118
import replicate
119119

120-
for event in replicate.stream(
121-
"meta/meta-llama-3-70b-instruct",
122-
input={
123-
"prompt": "Please write a haiku about llamas.",
124-
},
125-
):
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."}):
126123
print(str(event), end="")
127124
```
128125

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+
129128
## Async usage
130129

131-
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:
132131

133132
```python
134133
import os
@@ -152,34 +151,6 @@ asyncio.run(main())
152151

153152
Functionality between the synchronous and asynchronous clients is otherwise identical.
154153

155-
### Async run() and stream()
156-
157-
The async client also supports `run()` and `stream()` methods:
158-
159-
```python
160-
import asyncio
161-
from replicate import AsyncReplicate
162-
163-
replicate = AsyncReplicate()
164-
165-
166-
async def main():
167-
# Run a model
168-
output = await replicate.run(
169-
"black-forest-labs/flux-schnell", input={"prompt": "astronaut riding a rocket like a horse"}
170-
)
171-
print(output)
172-
173-
# Stream a model's output
174-
async for event in replicate.stream(
175-
"meta/meta-llama-3-70b-instruct", input={"prompt": "Write a haiku about coding"}
176-
):
177-
print(str(event), end="")
178-
179-
180-
asyncio.run(main())
181-
```
182-
183154
### With aiohttp
184155

185156
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,
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

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

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

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

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
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: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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+
Raises:
85+
DeprecationWarning: Always raised when this function is called
86+
"""
87+
# Log deprecation warning with helpful migration example
88+
warnings.warn(
89+
_format_deprecation_message(ref, input),
90+
DeprecationWarning,
91+
stacklevel=2,
92+
)
93+
94+
# Use the existing use() function with streaming=True
95+
model = use(client, ref, streaming=True)
96+
97+
# Call the model with the input
98+
return model(**input) # type: ignore[return-value]

0 commit comments

Comments
 (0)