genblaze-replicate 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/PKG-INFO +3 -1
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/genblaze_replicate/provider.py +32 -7
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/pyproject.toml +3 -1
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/tests/test_replicate_provider.py +48 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/.gitignore +0 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/README.md +0 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/genblaze_replicate/__init__.py +0 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/genblaze_replicate/_errors.py +0 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/genblaze_replicate/py.typed +0 -0
- {genblaze_replicate-0.2.0 → genblaze_replicate-0.2.2}/tests/__init__.py +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: genblaze-replicate
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Replicate provider adapter for genblaze
|
|
5
|
+
Project-URL: Homepage, https://github.com/backblaze-labs/genblaze
|
|
5
6
|
Project-URL: Documentation, https://github.com/backblaze-labs/genblaze
|
|
6
7
|
Project-URL: Repository, https://github.com/backblaze-labs/genblaze
|
|
7
8
|
Project-URL: Issues, https://github.com/backblaze-labs/genblaze/issues
|
|
9
|
+
Author-email: Jeronimo De Leon <jdeleon@backblaze.com>
|
|
8
10
|
License-Expression: MIT
|
|
9
11
|
Classifier: Development Status :: 3 - Alpha
|
|
10
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -29,6 +29,7 @@ from genblaze_core.providers import (
|
|
|
29
29
|
route_by_media_type,
|
|
30
30
|
validate_asset_url,
|
|
31
31
|
)
|
|
32
|
+
from genblaze_core.providers.retry import retry_after_from_response
|
|
32
33
|
from genblaze_core.runnable.config import RunnableConfig
|
|
33
34
|
|
|
34
35
|
from ._errors import map_replicate_error
|
|
@@ -123,6 +124,7 @@ class ReplicateProvider(BaseProvider):
|
|
|
123
124
|
raise ProviderError(
|
|
124
125
|
f"Replicate submit failed: {exc}",
|
|
125
126
|
error_code=map_replicate_error(exc),
|
|
127
|
+
retry_after=retry_after_from_response(exc),
|
|
126
128
|
) from exc
|
|
127
129
|
|
|
128
130
|
def poll(self, prediction_id: Any, config: RunnableConfig | None = None) -> bool:
|
|
@@ -137,6 +139,7 @@ class ReplicateProvider(BaseProvider):
|
|
|
137
139
|
raise ProviderError(
|
|
138
140
|
f"Replicate poll failed: {exc}",
|
|
139
141
|
error_code=map_replicate_error(exc),
|
|
142
|
+
retry_after=retry_after_from_response(exc),
|
|
140
143
|
) from exc
|
|
141
144
|
|
|
142
145
|
def fetch_output(self, prediction_id: Any, step: Step) -> Step:
|
|
@@ -176,14 +179,35 @@ class ReplicateProvider(BaseProvider):
|
|
|
176
179
|
error_code=ProviderErrorCode.UNKNOWN,
|
|
177
180
|
)
|
|
178
181
|
|
|
179
|
-
output
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
# Replicate output shapes vary by model: str (single URL), list[str]
|
|
183
|
+
# (multi-asset), dict[str, str | list] (e.g. {"video": url,
|
|
184
|
+
# "subtitles": url} from text-to-video models with side-channels),
|
|
185
|
+
# or None (no output). Normalize to list[str].
|
|
186
|
+
raw_output = prediction.output
|
|
187
|
+
urls: list[str]
|
|
188
|
+
if raw_output is None:
|
|
189
|
+
urls = []
|
|
190
|
+
elif isinstance(raw_output, str):
|
|
191
|
+
urls = [raw_output]
|
|
192
|
+
elif isinstance(raw_output, list):
|
|
193
|
+
# Nested lists happen on batch-output models; flatten one level.
|
|
194
|
+
urls = []
|
|
195
|
+
for item in raw_output:
|
|
196
|
+
if isinstance(item, str):
|
|
197
|
+
urls.append(item)
|
|
198
|
+
elif isinstance(item, list):
|
|
199
|
+
urls.extend(str(u) for u in item if isinstance(u, (str, bytes)))
|
|
200
|
+
elif isinstance(raw_output, dict):
|
|
201
|
+
# Multi-channel outputs: keep only URL-shaped string values.
|
|
202
|
+
urls = [str(v) for v in raw_output.values() if isinstance(v, str)]
|
|
203
|
+
else:
|
|
204
|
+
raise ProviderError(
|
|
205
|
+
f"Unexpected Replicate output shape "
|
|
206
|
+
f"({type(raw_output).__name__}): {raw_output!r}",
|
|
207
|
+
error_code=ProviderErrorCode.SERVER_ERROR,
|
|
208
|
+
)
|
|
184
209
|
|
|
185
|
-
for
|
|
186
|
-
url_str = str(url)
|
|
210
|
+
for url_str in urls:
|
|
187
211
|
validate_asset_url(url_str)
|
|
188
212
|
path = urlparse(url_str).path
|
|
189
213
|
mime, _ = mimetypes.guess_type(path)
|
|
@@ -199,4 +223,5 @@ class ReplicateProvider(BaseProvider):
|
|
|
199
223
|
raise ProviderError(
|
|
200
224
|
f"Replicate fetch_output failed: {exc}",
|
|
201
225
|
error_code=map_replicate_error(exc),
|
|
226
|
+
retry_after=retry_after_from_response(exc),
|
|
202
227
|
) from exc
|
|
@@ -4,8 +4,9 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "genblaze-replicate"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Replicate provider adapter for genblaze"
|
|
9
|
+
authors = [{name = "Jeronimo De Leon", email = "jdeleon@backblaze.com"}]
|
|
9
10
|
readme = "README.md"
|
|
10
11
|
requires-python = ">=3.11"
|
|
11
12
|
license = "MIT"
|
|
@@ -20,6 +21,7 @@ dependencies = [
|
|
|
20
21
|
]
|
|
21
22
|
|
|
22
23
|
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/backblaze-labs/genblaze"
|
|
23
25
|
Documentation = "https://github.com/backblaze-labs/genblaze"
|
|
24
26
|
Repository = "https://github.com/backblaze-labs/genblaze"
|
|
25
27
|
Issues = "https://github.com/backblaze-labs/genblaze/issues"
|
|
@@ -185,6 +185,54 @@ def test_fetch_output_success_with_none():
|
|
|
185
185
|
assert len(result.assets) == 0
|
|
186
186
|
|
|
187
187
|
|
|
188
|
+
def test_fetch_output_success_with_dict():
|
|
189
|
+
"""Some Replicate models return dict outputs like {'video': url, 'audio': url}."""
|
|
190
|
+
provider = ReplicateProvider(api_token="test-token")
|
|
191
|
+
mock_client = MagicMock()
|
|
192
|
+
mock_client.predictions.get.return_value = FakePrediction(
|
|
193
|
+
output={
|
|
194
|
+
"video": "https://example.com/video.mp4",
|
|
195
|
+
"subtitles": "https://example.com/subs.vtt",
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
provider._client = mock_client
|
|
199
|
+
|
|
200
|
+
step = _make_step()
|
|
201
|
+
result = provider.fetch_output("pred-abc123", step)
|
|
202
|
+
|
|
203
|
+
urls = {a.url for a in result.assets}
|
|
204
|
+
assert urls == {"https://example.com/video.mp4", "https://example.com/subs.vtt"}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def test_fetch_output_success_with_nested_list():
|
|
208
|
+
"""Batch-output models return list[list[str]]; flatten one level."""
|
|
209
|
+
provider = ReplicateProvider(api_token="test-token")
|
|
210
|
+
mock_client = MagicMock()
|
|
211
|
+
mock_client.predictions.get.return_value = FakePrediction(
|
|
212
|
+
output=[["https://example.com/a.png", "https://example.com/b.png"]]
|
|
213
|
+
)
|
|
214
|
+
provider._client = mock_client
|
|
215
|
+
|
|
216
|
+
step = _make_step()
|
|
217
|
+
result = provider.fetch_output("pred-abc123", step)
|
|
218
|
+
|
|
219
|
+
assert len(result.assets) == 2
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def test_fetch_output_unknown_shape_raises_clear_error():
|
|
223
|
+
"""Unknown output shapes raise ProviderError with a specific message."""
|
|
224
|
+
from genblaze_core.exceptions import ProviderError
|
|
225
|
+
|
|
226
|
+
provider = ReplicateProvider(api_token="test-token")
|
|
227
|
+
mock_client = MagicMock()
|
|
228
|
+
mock_client.predictions.get.return_value = FakePrediction(output=42)
|
|
229
|
+
provider._client = mock_client
|
|
230
|
+
|
|
231
|
+
step = _make_step()
|
|
232
|
+
with pytest.raises(ProviderError, match="Unexpected Replicate output shape"):
|
|
233
|
+
provider.fetch_output("pred-abc123", step)
|
|
234
|
+
|
|
235
|
+
|
|
188
236
|
def test_fetch_output_failed():
|
|
189
237
|
from genblaze_core.exceptions import ProviderError
|
|
190
238
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|