llamagen-python 0.1.12__tar.gz → 0.1.14__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.
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/PKG-INFO +13 -10
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/README.md +12 -9
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/examples/quickstart.py +7 -2
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/pyproject.toml +1 -1
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/__init__.py +1 -1
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/_http.py +5 -3
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/tests/test_client.py +25 -11
- llamagen_python-0.1.12/examples/Untitled.ipynb +0 -96
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/.gitignore +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/LICENSE +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/docs/RELEASE.md +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/_client.py +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/_errors.py +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/_types.py +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/py.typed +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/resources/__init__.py +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/resources/animations.py +0 -0
- {llamagen_python-0.1.12 → llamagen_python-0.1.14}/src/llamagen/resources/comics.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llamagen-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.14
|
|
4
4
|
Summary: Official Python SDK for LlamaGen Comic API and Animation API
|
|
5
5
|
Project-URL: Homepage, https://llamagen.ai/comic-api
|
|
6
6
|
Project-URL: Documentation, https://llamagen.ai/comic-api/docs
|
|
@@ -66,8 +66,6 @@ WAIT_TIMEOUT_MS = 30 * 60 * 1000
|
|
|
66
66
|
client = LlamaGenClient(
|
|
67
67
|
api_key=os.environ["LLAMAGEN_API_KEY"],
|
|
68
68
|
timeout_ms=30000,
|
|
69
|
-
max_retries=5,
|
|
70
|
-
retry_delay_ms=500,
|
|
71
69
|
)
|
|
72
70
|
|
|
73
71
|
created = client.comic.create({
|
|
@@ -95,13 +93,13 @@ client = LlamaGenClient(
|
|
|
95
93
|
api_key="YOUR_API_KEY",
|
|
96
94
|
base_url="https://api.llamagen.ai/v1",
|
|
97
95
|
timeout_ms=30000,
|
|
98
|
-
max_retries=5,
|
|
99
|
-
retry_delay_ms=500,
|
|
100
96
|
)
|
|
101
97
|
```
|
|
102
98
|
|
|
103
99
|
The SDK uses Python's standard library HTTP stack and does not require runtime
|
|
104
|
-
dependencies.
|
|
100
|
+
dependencies. The legacy `max_retries` and `retry_delay_ms` options remain
|
|
101
|
+
accepted for compatibility, but automatic HTTP retries are disabled to avoid
|
|
102
|
+
duplicating billable generation requests.
|
|
105
103
|
|
|
106
104
|
## Comic API
|
|
107
105
|
|
|
@@ -125,11 +123,16 @@ generation = client.comic.create({
|
|
|
125
123
|
"comicRoles": [
|
|
126
124
|
{
|
|
127
125
|
"name": "The Little Prince",
|
|
128
|
-
"image": "https://
|
|
126
|
+
"image": "https://s.llamagen.ai/public/61965b97-23fe-4405-853d-efe17b5d6f08-prince.webp",
|
|
129
127
|
"dress": "green coat and yellow scarf",
|
|
130
128
|
}
|
|
131
129
|
],
|
|
132
|
-
"attachments": [
|
|
130
|
+
"attachments": [
|
|
131
|
+
{
|
|
132
|
+
"type": "image",
|
|
133
|
+
"url": "https://s.llamagen.ai/public/7eeaad2c-fd6b-4679-90ce-884503f011b7-reference.webp",
|
|
134
|
+
}
|
|
135
|
+
],
|
|
133
136
|
"language": "en",
|
|
134
137
|
"upscale": "2K",
|
|
135
138
|
})
|
|
@@ -415,5 +418,5 @@ except LlamaGenTimeoutError as error:
|
|
|
415
418
|
```
|
|
416
419
|
|
|
417
420
|
- `LlamaGenAPIError`: the API returned a non-2xx response, such as `401`, `403`, or `429`.
|
|
418
|
-
- `LlamaGenConnectionError`: the SDK could not connect to the API
|
|
419
|
-
- `LlamaGenTimeoutError`: the request timed out
|
|
421
|
+
- `LlamaGenConnectionError`: the SDK could not connect to the API.
|
|
422
|
+
- `LlamaGenTimeoutError`: the request timed out.
|
|
@@ -41,8 +41,6 @@ WAIT_TIMEOUT_MS = 30 * 60 * 1000
|
|
|
41
41
|
client = LlamaGenClient(
|
|
42
42
|
api_key=os.environ["LLAMAGEN_API_KEY"],
|
|
43
43
|
timeout_ms=30000,
|
|
44
|
-
max_retries=5,
|
|
45
|
-
retry_delay_ms=500,
|
|
46
44
|
)
|
|
47
45
|
|
|
48
46
|
created = client.comic.create({
|
|
@@ -70,13 +68,13 @@ client = LlamaGenClient(
|
|
|
70
68
|
api_key="YOUR_API_KEY",
|
|
71
69
|
base_url="https://api.llamagen.ai/v1",
|
|
72
70
|
timeout_ms=30000,
|
|
73
|
-
max_retries=5,
|
|
74
|
-
retry_delay_ms=500,
|
|
75
71
|
)
|
|
76
72
|
```
|
|
77
73
|
|
|
78
74
|
The SDK uses Python's standard library HTTP stack and does not require runtime
|
|
79
|
-
dependencies.
|
|
75
|
+
dependencies. The legacy `max_retries` and `retry_delay_ms` options remain
|
|
76
|
+
accepted for compatibility, but automatic HTTP retries are disabled to avoid
|
|
77
|
+
duplicating billable generation requests.
|
|
80
78
|
|
|
81
79
|
## Comic API
|
|
82
80
|
|
|
@@ -100,11 +98,16 @@ generation = client.comic.create({
|
|
|
100
98
|
"comicRoles": [
|
|
101
99
|
{
|
|
102
100
|
"name": "The Little Prince",
|
|
103
|
-
"image": "https://
|
|
101
|
+
"image": "https://s.llamagen.ai/public/61965b97-23fe-4405-853d-efe17b5d6f08-prince.webp",
|
|
104
102
|
"dress": "green coat and yellow scarf",
|
|
105
103
|
}
|
|
106
104
|
],
|
|
107
|
-
"attachments": [
|
|
105
|
+
"attachments": [
|
|
106
|
+
{
|
|
107
|
+
"type": "image",
|
|
108
|
+
"url": "https://s.llamagen.ai/public/7eeaad2c-fd6b-4679-90ce-884503f011b7-reference.webp",
|
|
109
|
+
}
|
|
110
|
+
],
|
|
108
111
|
"language": "en",
|
|
109
112
|
"upscale": "2K",
|
|
110
113
|
})
|
|
@@ -390,5 +393,5 @@ except LlamaGenTimeoutError as error:
|
|
|
390
393
|
```
|
|
391
394
|
|
|
392
395
|
- `LlamaGenAPIError`: the API returned a non-2xx response, such as `401`, `403`, or `429`.
|
|
393
|
-
- `LlamaGenConnectionError`: the SDK could not connect to the API
|
|
394
|
-
- `LlamaGenTimeoutError`: the request timed out
|
|
396
|
+
- `LlamaGenConnectionError`: the SDK could not connect to the API.
|
|
397
|
+
- `LlamaGenTimeoutError`: the request timed out.
|
|
@@ -71,11 +71,16 @@ def create_comic_with_advanced_options(client: LlamaGenClient) -> None:
|
|
|
71
71
|
"comicRoles": [
|
|
72
72
|
{
|
|
73
73
|
"name": "The Little Prince",
|
|
74
|
-
"image": "https://
|
|
74
|
+
"image": "https://s.llamagen.ai/public/61965b97-23fe-4405-853d-efe17b5d6f08-prince.webp",
|
|
75
75
|
"dress": "green coat and yellow scarf",
|
|
76
76
|
}
|
|
77
77
|
],
|
|
78
|
-
"attachments": [
|
|
78
|
+
"attachments": [
|
|
79
|
+
{
|
|
80
|
+
"type": "image",
|
|
81
|
+
"url": "https://s.llamagen.ai/public/7eeaad2c-fd6b-4679-90ce-884503f011b7-reference.webp",
|
|
82
|
+
}
|
|
83
|
+
],
|
|
79
84
|
"language": "en",
|
|
80
85
|
"upscale": "2K",
|
|
81
86
|
}
|
|
@@ -10,7 +10,7 @@ from typing import Any, Dict, Mapping, Optional, Protocol, Tuple
|
|
|
10
10
|
|
|
11
11
|
from ._errors import LlamaGenAPIError, LlamaGenConnectionError, LlamaGenTimeoutError
|
|
12
12
|
|
|
13
|
-
DEFAULT_USER_AGENT = "llamagen-python/0.1.
|
|
13
|
+
DEFAULT_USER_AGENT = "llamagen-python/0.1.14"
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class Transport(Protocol):
|
|
@@ -60,8 +60,10 @@ class HTTPClient:
|
|
|
60
60
|
self.api_key = api_key
|
|
61
61
|
self.base_url = base_url.rstrip("/")
|
|
62
62
|
self.timeout = timeout_ms / 1000
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
# Kept in the public API for compatibility; automatic retries can
|
|
64
|
+
# duplicate non-idempotent, billable generation requests.
|
|
65
|
+
self.max_retries = 0
|
|
66
|
+
self.retry_delay = 60
|
|
65
67
|
self.transport = transport or UrllibTransport()
|
|
66
68
|
|
|
67
69
|
def request(
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import socket
|
|
4
5
|
import ssl
|
|
5
6
|
import unittest
|
|
6
7
|
import urllib.error
|
|
7
8
|
from typing import Mapping, Optional, Tuple
|
|
8
9
|
|
|
9
|
-
from llamagen import LlamaGenAPIError, LlamaGenClient, LlamaGenConnectionError
|
|
10
|
+
from llamagen import LlamaGenAPIError, LlamaGenClient, LlamaGenConnectionError, LlamaGenTimeoutError
|
|
10
11
|
from llamagen.resources.animations import DEFAULT_WAIT_TIMEOUT_MS as ANIMATION_WAIT_TIMEOUT_MS
|
|
11
12
|
from llamagen.resources.comics import DEFAULT_WAIT_TIMEOUT_MS as COMIC_WAIT_TIMEOUT_MS
|
|
12
13
|
|
|
@@ -80,7 +81,7 @@ class ClientTests(unittest.TestCase):
|
|
|
80
81
|
self.assertEqual(call["url"], "https://api.llamagen.ai/v1/comics/generations")
|
|
81
82
|
self.assertEqual(call["headers"]["Authorization"], "Bearer test-key")
|
|
82
83
|
self.assertEqual(call["headers"]["Accept"], "application/json")
|
|
83
|
-
self.assertEqual(call["headers"]["User-Agent"], "llamagen-python/0.1.
|
|
84
|
+
self.assertEqual(call["headers"]["User-Agent"], "llamagen-python/0.1.14")
|
|
84
85
|
body = json.loads(call["body"].decode("utf-8"))
|
|
85
86
|
self.assertEqual(body["preset"], "neutral")
|
|
86
87
|
self.assertEqual(body["size"], "1024x1024")
|
|
@@ -157,20 +158,33 @@ class ClientTests(unittest.TestCase):
|
|
|
157
158
|
body = json.loads(transport.calls[0]["body"].decode("utf-8"))
|
|
158
159
|
self.assertEqual(body["action"], "regeneratePanel")
|
|
159
160
|
|
|
160
|
-
def
|
|
161
|
-
transport = FailingTransport(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
def test_max_retries_is_ignored_for_connection_errors(self):
|
|
162
|
+
transport = FailingTransport([urllib.error.URLError(ssl.SSLEOFError("unexpected eof"))])
|
|
163
|
+
client = LlamaGenClient(
|
|
164
|
+
api_key="test-key",
|
|
165
|
+
max_retries=5,
|
|
166
|
+
retry_delay_ms=1,
|
|
167
|
+
transport=transport,
|
|
167
168
|
)
|
|
168
|
-
client = LlamaGenClient(api_key="test-key", retry_delay_ms=1, transport=transport)
|
|
169
169
|
|
|
170
170
|
with self.assertRaises(LlamaGenConnectionError):
|
|
171
171
|
client.comic.usage()
|
|
172
172
|
|
|
173
|
-
self.assertEqual(len(transport.calls),
|
|
173
|
+
self.assertEqual(len(transport.calls), 1)
|
|
174
|
+
|
|
175
|
+
def test_max_retries_is_ignored_for_create_timeouts(self):
|
|
176
|
+
transport = FailingTransport([socket.timeout("timed out")])
|
|
177
|
+
client = LlamaGenClient(
|
|
178
|
+
api_key="test-key",
|
|
179
|
+
max_retries=5,
|
|
180
|
+
retry_delay_ms=1,
|
|
181
|
+
transport=transport,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
with self.assertRaises(LlamaGenTimeoutError):
|
|
185
|
+
client.comic.create({"prompt": "A short comic.", "fixPanelNum": 1})
|
|
186
|
+
|
|
187
|
+
self.assertEqual(len(transport.calls), 1)
|
|
174
188
|
|
|
175
189
|
def test_wait_for_completion_continues_after_transient_connection_error(self):
|
|
176
190
|
transport = MixedTransport(
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cells": [
|
|
3
|
-
{
|
|
4
|
-
"cell_type": "code",
|
|
5
|
-
"execution_count": 1,
|
|
6
|
-
"id": "1a448d8d-251a-4351-a830-0372b055fb65",
|
|
7
|
-
"metadata": {},
|
|
8
|
-
"outputs": [
|
|
9
|
-
{
|
|
10
|
-
"name": "stdout",
|
|
11
|
-
"output_type": "stream",
|
|
12
|
-
"text": [
|
|
13
|
-
"comic.create: cmrfqxwsu0003l404hr39nmhm LOADING\n",
|
|
14
|
-
"comic.wait_for_completion: cmrfqxwsu0003l404hr39nmhm PROCESSED [{'page': 0, 'prompt': 'A 4-panel comic about Leo finding a glowing key in a quiet library.', 'beginPageIndex': 0, 'totalPages': 1, 'panelsPerPage': 4, 'layout': 'Layout0', 'panels': [{'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/f521f8e4-abcd-4e1f-9e42-48f6b7a8715c.png', 'panel': 0, 'caption': 'Leo quietly browses the library shelves, lost in the peaceful atmosphere.', 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/72b6b5f4-05bb-499e-9528-0c5b418b5eba.png', 'panel': 1, 'caption': 'Leo notices a faint glow beneath one of the lower shelves.', 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/62e36e8c-0a74-4bc8-a44a-c3bbf9f880c7.png', 'panel': 2, 'caption': 'Leo carefully reaches under the shelf and retrieves the glowing key.', 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/7ed32fee-379f-4f48-9880-1c06739ee240.png', 'panel': 3, 'caption': 'Leo gazes at the glowing key, his eyes full of wonder and imagination.', 'image': []}], 'update': 1783737031958, 'firstUpdate': 1783737031958}]\n"
|
|
15
|
-
]
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
"source": [
|
|
19
|
-
"import os\n",
|
|
20
|
-
"\n",
|
|
21
|
-
"from llamagen import LlamaGenClient\n",
|
|
22
|
-
"\n",
|
|
23
|
-
"WAIT_TIMEOUT_MS = 30 * 60 * 1000\n",
|
|
24
|
-
"\n",
|
|
25
|
-
"client = LlamaGenClient(\n",
|
|
26
|
-
" api_key=\"sk-5d609cd64379d048edcb04dcc109a6cfaf7c066f12138c13c8c404766ab9629d\",\n",
|
|
27
|
-
" timeout_ms=30000,\n",
|
|
28
|
-
" max_retries=5,\n",
|
|
29
|
-
" retry_delay_ms=500,\n",
|
|
30
|
-
")\n",
|
|
31
|
-
"\n",
|
|
32
|
-
"created = client.comic.create({\n",
|
|
33
|
-
" \"prompt\": \"A 4-panel comic about Leo finding a glowing key in a quiet library.\",\n",
|
|
34
|
-
" \"style\": \"manga\",\n",
|
|
35
|
-
" \"fixPanelNum\": 4,\n",
|
|
36
|
-
"})\n",
|
|
37
|
-
"print(\"comic.create:\", created[\"id\"], created.get(\"status\"))\n",
|
|
38
|
-
"\n",
|
|
39
|
-
"done = client.comic.wait_for_completion(created[\"id\"], timeout_ms=WAIT_TIMEOUT_MS)\n",
|
|
40
|
-
"print(\"comic.wait_for_completion:\", done[\"id\"], done.get(\"status\"), done.get(\"comics\"))"
|
|
41
|
-
]
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"cell_type": "code",
|
|
45
|
-
"execution_count": null,
|
|
46
|
-
"id": "f0c6df20-22f8-410e-9920-691f2d9b6557",
|
|
47
|
-
"metadata": {},
|
|
48
|
-
"outputs": [],
|
|
49
|
-
"source": [
|
|
50
|
-
"import os\n",
|
|
51
|
-
"\n",
|
|
52
|
-
"from llamagen import LlamaGenClient\n",
|
|
53
|
-
"\n",
|
|
54
|
-
"client = LlamaGenClient(api_key=\"sk-5d609cd64379d048edcb04dcc109a6cfaf7c066f12138c13c8c404766ab9629d\")\n",
|
|
55
|
-
"\n",
|
|
56
|
-
"generation = client.comic.create({\n",
|
|
57
|
-
" \"prompt\": \"The Little Prince meets the Fox in a luminous desert.\",\n",
|
|
58
|
-
" \"style\": \"storybook manga\",\n",
|
|
59
|
-
" \"size\": \"1024x1024\",\n",
|
|
60
|
-
" \"pagination\": {\"totalPages\": 2, \"panelsPerPage\": 4},\n",
|
|
61
|
-
" \"comicRoles\": [\n",
|
|
62
|
-
" {\n",
|
|
63
|
-
" \"name\": \"The Little Prince\",\n",
|
|
64
|
-
" \"image\": \"https://example.com/prince.png\",\n",
|
|
65
|
-
" \"clothing\": \"green coat and yellow scarf\",\n",
|
|
66
|
-
" }\n",
|
|
67
|
-
" ],\n",
|
|
68
|
-
" \"attachments\": [{\"type\": \"image\", \"url\": \"https://example.com/reference.png\"}],\n",
|
|
69
|
-
" \"language\": \"en\",\n",
|
|
70
|
-
" \"upscale\": \"2K\",\n",
|
|
71
|
-
"})"
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
"metadata": {
|
|
76
|
-
"kernelspec": {
|
|
77
|
-
"display_name": "Python 3 (ipykernel)",
|
|
78
|
-
"language": "python",
|
|
79
|
-
"name": "python3"
|
|
80
|
-
},
|
|
81
|
-
"language_info": {
|
|
82
|
-
"codemirror_mode": {
|
|
83
|
-
"name": "ipython",
|
|
84
|
-
"version": 3
|
|
85
|
-
},
|
|
86
|
-
"file_extension": ".py",
|
|
87
|
-
"mimetype": "text/x-python",
|
|
88
|
-
"name": "python",
|
|
89
|
-
"nbconvert_exporter": "python",
|
|
90
|
-
"pygments_lexer": "ipython3",
|
|
91
|
-
"version": "3.12.7"
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
"nbformat": 4,
|
|
95
|
-
"nbformat_minor": 5
|
|
96
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|