llamagen-python 0.1.13__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.13 → llamagen_python-0.1.14}/PKG-INFO +6 -8
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/README.md +5 -7
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/pyproject.toml +1 -1
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/__init__.py +1 -1
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/_http.py +5 -3
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/tests/test_client.py +25 -11
- llamagen_python-0.1.13/examples/Untitled.ipynb +0 -113
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/.gitignore +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/LICENSE +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/docs/RELEASE.md +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/examples/quickstart.py +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/_client.py +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/_errors.py +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/_types.py +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/py.typed +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/resources/__init__.py +0 -0
- {llamagen_python-0.1.13 → llamagen_python-0.1.14}/src/llamagen/resources/animations.py +0 -0
- {llamagen_python-0.1.13 → 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
|
|
|
@@ -420,5 +418,5 @@ except LlamaGenTimeoutError as error:
|
|
|
420
418
|
```
|
|
421
419
|
|
|
422
420
|
- `LlamaGenAPIError`: the API returned a non-2xx response, such as `401`, `403`, or `429`.
|
|
423
|
-
- `LlamaGenConnectionError`: the SDK could not connect to the API
|
|
424
|
-
- `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
|
|
|
@@ -395,5 +393,5 @@ except LlamaGenTimeoutError as error:
|
|
|
395
393
|
```
|
|
396
394
|
|
|
397
395
|
- `LlamaGenAPIError`: the API returned a non-2xx response, such as `401`, `403`, or `429`.
|
|
398
|
-
- `LlamaGenConnectionError`: the SDK could not connect to the API
|
|
399
|
-
- `LlamaGenTimeoutError`: the request timed out
|
|
396
|
+
- `LlamaGenConnectionError`: the SDK could not connect to the API.
|
|
397
|
+
- `LlamaGenTimeoutError`: the request timed out.
|
|
@@ -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,113 +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": 2,
|
|
46
|
-
"id": "f0c6df20-22f8-410e-9920-691f2d9b6557",
|
|
47
|
-
"metadata": {},
|
|
48
|
-
"outputs": [
|
|
49
|
-
{
|
|
50
|
-
"name": "stdout",
|
|
51
|
-
"output_type": "stream",
|
|
52
|
-
"text": [
|
|
53
|
-
"comic.create: cmrfstpbx0003l604n4njl7e3 LOADING\n",
|
|
54
|
-
"comic.wait_for_completion: cmrfstpbx0003l604n4njl7e3 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/bfa3c3a1-9ab7-491a-9937-c1682332cea4.png', 'panel': 0, 'caption': \"It's so peaceful here... So many books I've never read.\", 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/9074f3ac-b3b4-4dd5-b908-5a203065e5b4.png', 'panel': 1, 'caption': 'What is that light...?', 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/a5b6902d-bb04-4519-9f95-f99926bcb260.png', 'panel': 2, 'caption': \"Is this someone's lost key? It's so bright...\", 'image': []}, {'assetUrl': 'https://s.llamagen.ai/clr907a8t0000jp08cgdqv78h/30c758d6-209f-46f4-8f0d-84ca156151c3.png', 'panel': 3, 'caption': 'What secrets do you hold?', 'image': []}], 'update': 1783740192609, 'firstUpdate': 1783740192609}]\n"
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
|
-
"source": [
|
|
59
|
-
"import os\n",
|
|
60
|
-
"\n",
|
|
61
|
-
"from llamagen import LlamaGenClient\n",
|
|
62
|
-
"\n",
|
|
63
|
-
"WAIT_TIMEOUT_MS = 30 * 60 * 1000\n",
|
|
64
|
-
"\n",
|
|
65
|
-
"client = LlamaGenClient(\n",
|
|
66
|
-
" api_key=\"sk-5d609cd64379d048edcb04dcc109a6cfaf7c066f12138c13c8c404766ab9629d\",\n",
|
|
67
|
-
" timeout_ms=30000,\n",
|
|
68
|
-
" max_retries=5,\n",
|
|
69
|
-
" retry_delay_ms=500,\n",
|
|
70
|
-
")\n",
|
|
71
|
-
"\n",
|
|
72
|
-
"created = client.comic.create({\n",
|
|
73
|
-
" \"prompt\": \"A 4-panel comic about Leo finding a glowing key in a quiet library.\",\n",
|
|
74
|
-
" \"preset\": \"japanese_manga\",\n",
|
|
75
|
-
" \"fixPanelNum\": 4,\n",
|
|
76
|
-
"})\n",
|
|
77
|
-
"print(\"comic.create:\", created[\"id\"], created.get(\"status\"))\n",
|
|
78
|
-
"\n",
|
|
79
|
-
"done = client.comic.wait_for_completion(created[\"id\"], timeout_ms=WAIT_TIMEOUT_MS)\n",
|
|
80
|
-
"print(\"comic.wait_for_completion:\", done[\"id\"], done.get(\"status\"), done.get(\"comics\"))"
|
|
81
|
-
]
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"cell_type": "code",
|
|
85
|
-
"execution_count": null,
|
|
86
|
-
"id": "77cc80bf-967e-4da5-bf9e-d8858914f2a4",
|
|
87
|
-
"metadata": {},
|
|
88
|
-
"outputs": [],
|
|
89
|
-
"source": []
|
|
90
|
-
}
|
|
91
|
-
],
|
|
92
|
-
"metadata": {
|
|
93
|
-
"kernelspec": {
|
|
94
|
-
"display_name": "Python 3 (ipykernel)",
|
|
95
|
-
"language": "python",
|
|
96
|
-
"name": "python3"
|
|
97
|
-
},
|
|
98
|
-
"language_info": {
|
|
99
|
-
"codemirror_mode": {
|
|
100
|
-
"name": "ipython",
|
|
101
|
-
"version": 3
|
|
102
|
-
},
|
|
103
|
-
"file_extension": ".py",
|
|
104
|
-
"mimetype": "text/x-python",
|
|
105
|
-
"name": "python",
|
|
106
|
-
"nbconvert_exporter": "python",
|
|
107
|
-
"pygments_lexer": "ipython3",
|
|
108
|
-
"version": "3.12.7"
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
"nbformat": 4,
|
|
112
|
-
"nbformat_minor": 5
|
|
113
|
-
}
|
|
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
|
|
File without changes
|