runapi-imagen-4 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,24 @@
1
+ """Imagen 4 client for RunAPI."""
2
+
3
+ from runapi.core import (
4
+ AuthenticationError,
5
+ InsufficientCreditsError,
6
+ NotFoundError,
7
+ RateLimitError,
8
+ TaskFailedError,
9
+ TaskTimeoutError,
10
+ ValidationError,
11
+ )
12
+
13
+ from .client import Imagen4Client
14
+
15
+ __all__ = [
16
+ "Imagen4Client",
17
+ "AuthenticationError",
18
+ "RateLimitError",
19
+ "InsufficientCreditsError",
20
+ "NotFoundError",
21
+ "ValidationError",
22
+ "TaskFailedError",
23
+ "TaskTimeoutError",
24
+ ]
@@ -0,0 +1,29 @@
1
+ """Imagen 4 client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import ClientOptions, HttpClient, resolve_api_key
8
+
9
+ from .resources.remix_image import RemixImage
10
+ from .resources.text_to_image import TextToImage
11
+
12
+
13
+ class Imagen4Client:
14
+ """Imagen 4 text-to-image and remix-image client.
15
+
16
+ Example::
17
+
18
+ client = Imagen4Client(api_key="sk-...")
19
+ result = client.text_to_image.run(
20
+ model="imagen-4", prompt="A neon city street"
21
+ )
22
+ """
23
+
24
+ def __init__(self, api_key: Optional[str] = None, **options: Any) -> None:
25
+ resolved_api_key = resolve_api_key(api_key)
26
+ client_options = ClientOptions(api_key=resolved_api_key, **options)
27
+ http = client_options.http_client or HttpClient(client_options)
28
+ self.text_to_image = TextToImage(http)
29
+ self.remix_image = RemixImage(http)
File without changes
@@ -0,0 +1,4 @@
1
+ from .remix_image import RemixImage
2
+ from .text_to_image import TextToImage
3
+
4
+ __all__ = ["TextToImage", "RemixImage"]
@@ -0,0 +1,84 @@
1
+ """Imagen 4 remix-image resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict
6
+
7
+ from runapi.core import Resource, ValidationError
8
+
9
+ from ..types import (
10
+ OUTPUT_FORMATS,
11
+ OUTPUT_RESOLUTIONS,
12
+ PRO_ASPECT_RATIOS,
13
+ REMIX_MODELS,
14
+ CompletedRemixImageResponse,
15
+ RemixImageResponse,
16
+ )
17
+
18
+
19
+ class RemixImage(Resource):
20
+ """Remix a set of source images with an Imagen 4 pro model."""
21
+
22
+ ENDPOINT = "/api/v1/imagen_4/remix_image"
23
+
24
+ RESPONSE_CLASS = RemixImageResponse
25
+ COMPLETED_RESPONSE_CLASS = CompletedRemixImageResponse
26
+
27
+ SOURCE_IMAGE_URLS_MAX = 8
28
+
29
+ def run(self, **params: Any) -> Any:
30
+ """Remix source images and poll until it completes.
31
+
32
+ Args:
33
+ **params: Remix-image parameters (model, prompt, source_image_urls, ...).
34
+
35
+ Returns:
36
+ The completed task with images.
37
+ """
38
+ task = self.create(**params)
39
+ return self._poll_until_complete(lambda: self.get(task.id))
40
+
41
+ def create(self, **params: Any) -> Any:
42
+ """Create a remix-image task and return immediately with an ``id``.
43
+
44
+ Args:
45
+ **params: Remix-image parameters (model, prompt, source_image_urls, ...).
46
+
47
+ Returns:
48
+ The task creation result with an id.
49
+ """
50
+ compacted = self._compact_params(params)
51
+ self._validate_params(compacted)
52
+ return self._request("post", self.ENDPOINT, body=compacted)
53
+
54
+ def get(self, id: str) -> Any:
55
+ """Fetch the current status of a remix-image task.
56
+
57
+ Args:
58
+ id: The task id.
59
+
60
+ Returns:
61
+ The current task status.
62
+ """
63
+ return self._request("get", f"{self.ENDPOINT}/{id}")
64
+
65
+ def _validate_params(self, params: Dict[str, Any]) -> None:
66
+ model = params.get("model")
67
+ if not model:
68
+ raise ValidationError("model is required")
69
+ if model not in REMIX_MODELS:
70
+ raise ValidationError(f"Invalid model: {model}. Must be one of: {', '.join(REMIX_MODELS)}")
71
+ if not params.get("prompt"):
72
+ raise ValidationError("prompt is required")
73
+
74
+ self._validate_source_image_urls(params)
75
+ self._validate_optional(params, "aspect_ratio", PRO_ASPECT_RATIOS)
76
+ self._validate_optional(params, "output_resolution", OUTPUT_RESOLUTIONS)
77
+ self._validate_optional(params, "output_format", OUTPUT_FORMATS)
78
+
79
+ def _validate_source_image_urls(self, params: Dict[str, Any]) -> None:
80
+ urls = params.get("source_image_urls")
81
+ if urls is None or (hasattr(urls, "__len__") and len(urls) == 0):
82
+ raise ValidationError("source_image_urls is required")
83
+ if hasattr(urls, "__len__") and len(urls) > self.SOURCE_IMAGE_URLS_MAX:
84
+ raise ValidationError(f"source_image_urls supports up to {self.SOURCE_IMAGE_URLS_MAX} images")
@@ -0,0 +1,81 @@
1
+ """Imagen 4 text-to-image resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict
6
+
7
+ from runapi.core import Resource, ValidationError
8
+
9
+ from ..types import (
10
+ MODELS,
11
+ OUTPUT_COUNTS,
12
+ TEXT_ASPECT_RATIOS,
13
+ CompletedTextToImageResponse,
14
+ TextToImageResponse,
15
+ )
16
+
17
+
18
+ class TextToImage(Resource):
19
+ """Generate images from text prompts with Imagen 4 models."""
20
+
21
+ ENDPOINT = "/api/v1/imagen_4/text_to_image"
22
+
23
+ RESPONSE_CLASS = TextToImageResponse
24
+ COMPLETED_RESPONSE_CLASS = CompletedTextToImageResponse
25
+
26
+ def run(self, **params: Any) -> Any:
27
+ """Generate images from text and poll until it completes.
28
+
29
+ Args:
30
+ **params: Text-to-image parameters (model, prompt, ...).
31
+
32
+ Returns:
33
+ The completed task with images.
34
+ """
35
+ task = self.create(**params)
36
+ return self._poll_until_complete(lambda: self.get(task.id))
37
+
38
+ def create(self, **params: Any) -> Any:
39
+ """Create a text-to-image task and return immediately with an ``id``.
40
+
41
+ Args:
42
+ **params: Text-to-image parameters (model, prompt, ...).
43
+
44
+ Returns:
45
+ The task creation result with an id.
46
+ """
47
+ compacted = self._compact_params(params)
48
+ self._validate_params(compacted)
49
+ return self._request("post", self.ENDPOINT, body=compacted)
50
+
51
+ def get(self, id: str) -> Any:
52
+ """Fetch the current status of a text-to-image task.
53
+
54
+ Args:
55
+ id: The task id.
56
+
57
+ Returns:
58
+ The current task status.
59
+ """
60
+ return self._request("get", f"{self.ENDPOINT}/{id}")
61
+
62
+ def _validate_params(self, params: Dict[str, Any]) -> None:
63
+ if not params.get("model"):
64
+ raise ValidationError("model is required")
65
+ if not params.get("prompt"):
66
+ raise ValidationError("prompt is required")
67
+
68
+ model = params.get("model")
69
+ if model not in MODELS:
70
+ raise ValidationError(f"Invalid model: {model}. Must be: {', '.join(MODELS)}")
71
+
72
+ self._validate_text_params(params, model)
73
+
74
+ def _validate_text_params(self, params: Dict[str, Any], model: str) -> None:
75
+ self._validate_optional(params, "aspect_ratio", TEXT_ASPECT_RATIOS)
76
+ if not params.get("output_count"):
77
+ return
78
+
79
+ if model != "imagen-4-fast":
80
+ raise ValidationError("output_count is only supported for imagen-4-fast")
81
+ self._validate_optional(params, "output_count", OUTPUT_COUNTS)
@@ -0,0 +1,46 @@
1
+ """Imagen 4 model lists, enums, and response models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from runapi.core import BaseModel, TaskResponse, optional, required
6
+
7
+ TEXT_MODELS = ["imagen-4", "imagen-4-fast", "imagen-4-ultra"]
8
+ REMIX_MODELS = ["imagen-4-pro-remix-image"]
9
+ MODELS = TEXT_MODELS + REMIX_MODELS
10
+ TEXT_ASPECT_RATIOS = ["1:1", "16:9", "9:16", "3:4", "4:3"]
11
+ PRO_ASPECT_RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9", "auto"]
12
+ OUTPUT_RESOLUTIONS = ["1k", "2k", "4k"]
13
+ OUTPUT_FORMATS = ["png", "jpg"]
14
+ OUTPUT_COUNTS = [1, 2, 3, 4]
15
+
16
+
17
+ class Image(BaseModel):
18
+ url = optional(str)
19
+ origin_url = optional(str)
20
+
21
+
22
+ class TextToImageResponse(TaskResponse):
23
+ """Response for a text-to-image task."""
24
+
25
+ id = required(str)
26
+ status = optional(str, enum=lambda: TaskResponse.Status.ALL)
27
+ images = optional([lambda: Image])
28
+ error = optional(str)
29
+
30
+
31
+ class CompletedTextToImageResponse(TextToImageResponse):
32
+ """Narrowed response from ``run()`` once polling observes completion."""
33
+
34
+ images = required([lambda: Image])
35
+
36
+
37
+ class RemixImageResponse(TextToImageResponse):
38
+ """Response for a remix-image task."""
39
+
40
+ pass
41
+
42
+
43
+ class CompletedRemixImageResponse(CompletedTextToImageResponse):
44
+ """Narrowed remix-image response from ``run()`` once polling observes completion."""
45
+
46
+ pass
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: runapi-imagen-4
3
+ Version: 0.1.0
4
+ Summary: Imagen 4 text-to-image and remix-image client for RunAPI
5
+ Project-URL: Homepage, https://runapi.ai/models/imagen-4
6
+ Project-URL: Documentation, https://runapi.ai/docs#sdk-imagen-4
7
+ Author-email: RunAPI <contact@runapi.ai>
8
+ License-Expression: Apache-2.0
9
+ Keywords: ai,imagen-4,remix-image,runapi,sdk,text-to-image
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: runapi-core
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Imagen 4 Python SDK for RunAPI
15
+
16
+ The Imagen 4 Python SDK is the language-specific package for Imagen 4 on RunAPI.
17
+ Use it for text-to-image and remix-image flows when your application needs JSON
18
+ request bodies, task status lookup, and consistent RunAPI errors in Python.
19
+
20
+ For model details, use https://runapi.ai/models/imagen-4; for API reference, use
21
+ https://runapi.ai/docs#imagen-4; for SDK docs, use https://runapi.ai/docs#sdk-imagen-4.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install runapi-imagen-4
27
+ ```
28
+
29
+ ## Quick start
30
+
31
+ ```python
32
+ from runapi.imagen_4 import Imagen4Client
33
+
34
+ client = Imagen4Client() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
35
+
36
+ task = client.text_to_image.create(
37
+ model="imagen-4",
38
+ prompt="A neon city street after rain, cinematic",
39
+ aspect_ratio="16:9",
40
+ )
41
+ status = client.text_to_image.get(task.id)
42
+
43
+ remix = client.remix_image.create(
44
+ model="imagen-4-pro-remix-image",
45
+ prompt="Make it golden hour",
46
+ source_image_urls=["https://example.com/source.jpg"],
47
+ )
48
+ ```
49
+
50
+ Use `create` to submit a task and return quickly, `get` to fetch the latest task
51
+ state, and `run` to create and poll until completion:
52
+
53
+ ```python
54
+ result = client.text_to_image.run(
55
+ model="imagen-4",
56
+ prompt="A serene mountain lake at dawn",
57
+ )
58
+ print(result.images[0].url)
59
+ ```
60
+
61
+ In web request handlers, prefer `create` plus webhook or later `get` polling so a
62
+ worker is not held open.
63
+
64
+ RunAPI-generated file URLs are temporary. Download and store generated images in
65
+ your own durable storage within 7 days; do not treat returned URLs as long-term
66
+ assets.
67
+
68
+ ## Language notes
69
+
70
+ Pass parameters as keyword arguments and catch the `runapi.imagen_4` error
71
+ classes when building image jobs or scripts. The available resources are
72
+ `text_to_image` and `remix_image`. Keep `RUNAPI_API_KEY` in the environment or
73
+ your secret manager; never commit API keys or callback secrets.
74
+
75
+ ## Links
76
+
77
+ - Model page: https://runapi.ai/models/imagen-4
78
+ - SDK docs: https://runapi.ai/docs#sdk-imagen-4
79
+ - Product docs: https://runapi.ai/docs#imagen-4
80
+ - Pricing and rate limits: https://runapi.ai/models/imagen-4
81
+ - Full catalog: https://runapi.ai/models
82
+
83
+ ## License
84
+
85
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,10 @@
1
+ runapi/imagen_4/__init__.py,sha256=3IqQXNgvfEzVfaPAggf9l46IB6yp3BMVW_ugr4R-x-A,464
2
+ runapi/imagen_4/client.py,sha256=Ke1OiqJOmCLdADRIfH9JSF_kouM5-An5zgqlnvj0DR0,889
3
+ runapi/imagen_4/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ runapi/imagen_4/types.py,sha256=e4hXY2x7UtPiRakHIrIg55Jju38PwrD9QYz2MS8auMo,1333
5
+ runapi/imagen_4/resources/__init__.py,sha256=_qgSycx9qXoXiFBejkxC4N-fuGhZ9MVuqjGUYbRWApI,116
6
+ runapi/imagen_4/resources/remix_image.py,sha256=4fiiLs-SKdcjqZoMTGvvzB60fAsmzQncn9l6rqI1HHY,2847
7
+ runapi/imagen_4/resources/text_to_image.py,sha256=mcoKX3V6UBBpH7IzFRiLYQizTU0kPSM0Xpwvr1OoDqc,2502
8
+ runapi_imagen_4-0.1.0.dist-info/METADATA,sha256=K5qqiQfnoxKyJHRZg52vWBzLOz5Tk2IcQT3nxgV8h2A,2653
9
+ runapi_imagen_4-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
10
+ runapi_imagen_4-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any