caption-flow 0.5.6__tar.gz → 0.5.7__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.
- {caption_flow-0.5.6 → caption_flow-0.5.7}/PKG-INFO +45 -24
- {caption_flow-0.5.6 → caption_flow-0.5.7}/README.md +22 -1
- {caption_flow-0.5.6 → caption_flow-0.5.7}/setup.py +11 -11
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/__init__.py +1 -1
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/models.py +8 -5
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/orchestrator.py +21 -13
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/processors/webdataset.py +187 -15
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/storage/exporter.py +20 -6
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/storage/manager.py +14 -2
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/chunk_tracker.py +45 -11
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/image_processor.py +8 -3
- caption_flow-0.5.7/src/caption_flow/utils/output_policy.py +207 -0
- caption_flow-0.5.7/src/caption_flow/utils/retry_queue.py +50 -0
- caption_flow-0.5.7/src/caption_flow/utils/unicode_utils.py +30 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/vllm_config.py +39 -11
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/workers/caption.py +177 -206
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/workers/openai_compatible.py +71 -361
- caption_flow-0.5.7/src/caption_flow/workers/pipeline.py +127 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/PKG-INFO +45 -24
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/SOURCES.txt +15 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/requires.txt +22 -22
- caption_flow-0.5.7/tests/test_caption_pipeline.py +413 -0
- caption_flow-0.5.7/tests/test_chunk_completion_index.py +193 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_config_reload.py +20 -0
- caption_flow-0.5.7/tests/test_dependency_config.py +71 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_exporter.py +76 -3
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_openai_compatible_worker.py +2 -1
- caption_flow-0.5.7/tests/test_orchestrator_storage_order.py +32 -0
- caption_flow-0.5.7/tests/test_result_acceptance.py +229 -0
- caption_flow-0.5.7/tests/test_retry_queue.py +132 -0
- caption_flow-0.5.7/tests/test_unicode_utils.py +69 -0
- caption_flow-0.5.7/tests/test_webdataset_cache_wait.py +118 -0
- caption_flow-0.5.7/tests/test_webdataset_prefetch.py +140 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_webdataset_ranges.py +31 -2
- caption_flow-0.5.7/tests/test_webshart_dependency.py +27 -0
- caption_flow-0.5.7/tests/test_webshart_export_contract.py +183 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_worker_caption.py +9 -28
- {caption_flow-0.5.6 → caption_flow-0.5.7}/LICENSE +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/pyproject.toml +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/setup.cfg +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/cli.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/monitor.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/processors/__init__.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/processors/base.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/processors/huggingface.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/processors/local_filesystem.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/storage/__init__.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/__init__.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/auth.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/caption_utils.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/certificates.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/checkpoint_tracker.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/json_utils.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/utils/prompt_template.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/viewer.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/workers/base.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow/workers/data.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/dependency_links.txt +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/entry_points.txt +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/src/caption_flow.egg-info/top_level.txt +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_caption_utils.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_certificates.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_cli.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_duplicate_job_assignments.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_fix_verification.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_huggingface_ranges.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_image_processor.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_json_utils.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_main.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_monitor.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_processors.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_range_level_distribution.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_storage_components.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_viewer.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_vllm_config.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_worker_reconnection_complete.py +0 -0
- {caption_flow-0.5.6 → caption_flow-0.5.7}/tests/test_worker_reconnection_sequence.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caption-flow
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.7
|
|
4
4
|
Summary: Self-contained distributed community captioning system
|
|
5
5
|
Author: bghira
|
|
6
6
|
Author-email: bghira <bghira@users.github.com>
|
|
@@ -31,7 +31,7 @@ Requires-Dist: trainingsample<0.4.0,>=0.3.2
|
|
|
31
31
|
Requires-Dist: pandas<4.0.0,>=3.0.0
|
|
32
32
|
Requires-Dist: datasets<6.0.0,>=5.0.0
|
|
33
33
|
Requires-Dist: boto3<2.0.0,>=1.43.0
|
|
34
|
-
Requires-Dist: webshart<0.
|
|
34
|
+
Requires-Dist: webshart<0.7.0,>=0.6.0
|
|
35
35
|
Requires-Dist: pylance<9.0.0,>=8.0.0
|
|
36
36
|
Requires-Dist: duckdb<2.0.0,>=1.5.0
|
|
37
37
|
Requires-Dist: aiohttp<4.0.0,>=3.13.3
|
|
@@ -43,35 +43,35 @@ Requires-Dist: requests<3.0.0,>=2.32.0
|
|
|
43
43
|
Requires-Dist: tqdm<5.0.0,>=4.67.0
|
|
44
44
|
Requires-Dist: urwid<5.0.0,>=3.0.2
|
|
45
45
|
Provides-Extra: vllm
|
|
46
|
-
Requires-Dist: vllm<0.
|
|
47
|
-
Requires-Dist: torch==2.
|
|
48
|
-
Requires-Dist: torchvision==0.
|
|
46
|
+
Requires-Dist: vllm<0.32.0,>=0.31.0; extra == "vllm"
|
|
47
|
+
Requires-Dist: torch==2.13.0; extra == "vllm"
|
|
48
|
+
Requires-Dist: torchvision==0.28.0; extra == "vllm"
|
|
49
49
|
Requires-Dist: torchaudio==2.11.0; extra == "vllm"
|
|
50
|
-
Requires-Dist: transformers<
|
|
50
|
+
Requires-Dist: transformers<5.18.0,>=5.10.4; extra == "vllm"
|
|
51
51
|
Requires-Dist: qwen-vl-utils<0.1.0,>=0.0.14; extra == "vllm"
|
|
52
52
|
Provides-Extra: captioning
|
|
53
|
-
Requires-Dist: vllm<0.
|
|
54
|
-
Requires-Dist: torch==2.
|
|
55
|
-
Requires-Dist: torchvision==0.
|
|
53
|
+
Requires-Dist: vllm<0.32.0,>=0.31.0; extra == "captioning"
|
|
54
|
+
Requires-Dist: torch==2.13.0; extra == "captioning"
|
|
55
|
+
Requires-Dist: torchvision==0.28.0; extra == "captioning"
|
|
56
56
|
Requires-Dist: torchaudio==2.11.0; extra == "captioning"
|
|
57
|
-
Requires-Dist: transformers<
|
|
57
|
+
Requires-Dist: transformers<5.18.0,>=5.10.4; extra == "captioning"
|
|
58
58
|
Requires-Dist: qwen-vl-utils<0.1.0,>=0.0.14; extra == "captioning"
|
|
59
59
|
Provides-Extra: openai
|
|
60
60
|
Provides-Extra: cpu
|
|
61
|
-
Requires-Dist: torch>=2.
|
|
62
|
-
Requires-Dist: torchvision>=0.
|
|
61
|
+
Requires-Dist: torch>=2.13.0; extra == "cpu"
|
|
62
|
+
Requires-Dist: torchvision>=0.28.0; extra == "cpu"
|
|
63
63
|
Requires-Dist: torchaudio>=2.11.0; extra == "cpu"
|
|
64
64
|
Provides-Extra: cuda
|
|
65
|
-
Requires-Dist: torch>=2.
|
|
66
|
-
Requires-Dist: torchvision>=0.
|
|
65
|
+
Requires-Dist: torch>=2.13.0; extra == "cuda"
|
|
66
|
+
Requires-Dist: torchvision>=0.28.0; extra == "cuda"
|
|
67
67
|
Requires-Dist: torchaudio>=2.11.0; extra == "cuda"
|
|
68
68
|
Provides-Extra: cuda13
|
|
69
|
-
Requires-Dist: torch>=2.
|
|
70
|
-
Requires-Dist: torchvision>=0.
|
|
69
|
+
Requires-Dist: torch>=2.13.0; extra == "cuda13"
|
|
70
|
+
Requires-Dist: torchvision>=0.28.0; extra == "cuda13"
|
|
71
71
|
Requires-Dist: torchaudio>=2.11.0; extra == "cuda13"
|
|
72
72
|
Provides-Extra: rocm
|
|
73
|
-
Requires-Dist: torch>=2.
|
|
74
|
-
Requires-Dist: torchvision>=0.
|
|
73
|
+
Requires-Dist: torch>=2.13.0; extra == "rocm"
|
|
74
|
+
Requires-Dist: torchvision>=0.28.0; extra == "rocm"
|
|
75
75
|
Requires-Dist: torchaudio>=2.11.0; extra == "rocm"
|
|
76
76
|
Provides-Extra: apple
|
|
77
77
|
Requires-Dist: torch>=2.13.0; extra == "apple"
|
|
@@ -82,16 +82,16 @@ Provides-Extra: dev
|
|
|
82
82
|
Requires-Dist: pytest<9.0.0,>=8.0.0; extra == "dev"
|
|
83
83
|
Requires-Dist: pytest-asyncio<2.0.0,>=1.1.0; extra == "dev"
|
|
84
84
|
Requires-Dist: pytest-cov<7.0.0,>=6.0.0; extra == "dev"
|
|
85
|
-
Requires-Dist: transformers<
|
|
85
|
+
Requires-Dist: transformers<5.18.0,>=5.10.4; extra == "dev"
|
|
86
86
|
Requires-Dist: black<26.0.0,>=25.0.0; extra == "dev"
|
|
87
87
|
Requires-Dist: ruff<1.0.0,>=0.12.0; extra == "dev"
|
|
88
88
|
Requires-Dist: mypy<2.0.0,>=1.17.0; extra == "dev"
|
|
89
89
|
Provides-Extra: all
|
|
90
|
-
Requires-Dist: vllm<0.
|
|
91
|
-
Requires-Dist: torch==2.
|
|
92
|
-
Requires-Dist: torchvision==0.
|
|
90
|
+
Requires-Dist: vllm<0.32.0,>=0.31.0; extra == "all"
|
|
91
|
+
Requires-Dist: torch==2.13.0; extra == "all"
|
|
92
|
+
Requires-Dist: torchvision==0.28.0; extra == "all"
|
|
93
93
|
Requires-Dist: torchaudio==2.11.0; extra == "all"
|
|
94
|
-
Requires-Dist: transformers<
|
|
94
|
+
Requires-Dist: transformers<5.18.0,>=5.10.4; extra == "all"
|
|
95
95
|
Requires-Dist: qwen-vl-utils<0.1.0,>=0.0.14; extra == "all"
|
|
96
96
|
Dynamic: author
|
|
97
97
|
Dynamic: license-file
|
|
@@ -128,6 +128,11 @@ pip install --upgrade pip
|
|
|
128
128
|
pip install "caption-flow[vllm]"
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
The Linux GPU worker extra targets vLLM 0.31.x with PyTorch 2.13.0,
|
|
132
|
+
torchvision 0.28.0, and torchaudio 2.11.0 (as required by vLLM), plus
|
|
133
|
+
Transformers 5.10.4–5.17.x. To upgrade an existing worker from a checkout,
|
|
134
|
+
run `pip install --upgrade -e ".[vllm]"` in its environment and restart it.
|
|
135
|
+
|
|
131
136
|
An OpenAI-compatible API worker does not need the GPU dependencies:
|
|
132
137
|
|
|
133
138
|
```bash
|
|
@@ -220,7 +225,7 @@ Options:
|
|
|
220
225
|
* **csv**: exports CSV-compatible data columns to the `--output` path containing incomplete metadata
|
|
221
226
|
* **json**: creates a `.json` file for each sample inside the `--output` subdirectory containing **complete** metadata; useful for webdatasets
|
|
222
227
|
* **txt**: creates `.txt` file for each sample inside the `--output` subdirectory containing ONLY captions
|
|
223
|
-
* **webshart**: updates an **existing per-shard metadata `.json` file** by writing captions under the plural `captions` key. for this format, pass `--output` as the path to the existing shard metadata JSON file when exporting one shard.
|
|
228
|
+
* **webshart**: updates an **existing per-shard metadata `.json` file** by writing captions under the plural `captions` key. Strings, native JSON objects, and mixed lists are supported. JSON objects stored as text in Lance output columns are decoded during export, preserving nested values instead of writing Python dictionary representations. Native objects supplied through `Caption.outputs` are encoded as JSON only for Lance persistence. Requires webshart 0.6.0 or newer for native JSON caption support (included in the base dependencies). For this format, pass `--output` as the path to the existing shard metadata JSON file when exporting one shard. If you export multiple shards, pass `--output` as a directory containing one existing `{shard_name}.json` file per shard.
|
|
224
229
|
* **huggingface_hub**: creates a dataset on Hugging Face Hub, possibly `--private` and `--nsfw` where necessary
|
|
225
230
|
* **all**: creates the directory/file-generating export formats in a specified `--output` directory. prefer a directory here; `webshart` is a special case that expects existing per-shard metadata `.json` files rather than creating new metadata files.
|
|
226
231
|
|
|
@@ -279,6 +284,13 @@ prompts, sampling, and output fields. Existing `vllm:` configurations are also
|
|
|
279
284
|
accepted by API workers for backward compatibility; endpoint-local `model`
|
|
280
285
|
values take precedence over the broadcast model name.
|
|
281
286
|
|
|
287
|
+
Direct vLLM and API workers share JSON validation, output transformations,
|
|
288
|
+
refusal detection, and semantic retries. Configure those under
|
|
289
|
+
`inference.output_processing`; use `response_format` and `retry_response_format`
|
|
290
|
+
for constrained decoding on either backend. See the
|
|
291
|
+
[structured JSON recipe](recipes/STRUCTURED_JSON.md) for examples and native
|
|
292
|
+
vLLM tuning details.
|
|
293
|
+
|
|
282
294
|
---
|
|
283
295
|
|
|
284
296
|
## dataset formats
|
|
@@ -288,6 +300,15 @@ values take precedence over the broadcast model name.
|
|
|
288
300
|
* webdatasets shards containing full image data; also can be hosted on the hub
|
|
289
301
|
* local folder filled with images; orchestrator will serve the data to workers
|
|
290
302
|
|
|
303
|
+
For indexed Webshart reads, set `orchestrator.webshart_prefetch_shards: 1` to
|
|
304
|
+
download the next shard in the background while captioning the current one.
|
|
305
|
+
The default is `0` (disabled). This works with both direct vLLM and API workers,
|
|
306
|
+
does not move the sample cursor, and is ignored for explicit remote-range reads.
|
|
307
|
+
Size `shard_cache_gb` to hold the current shard plus the lookahead. Prefetch
|
|
308
|
+
retries are spaced by `webshart_cache_retry_interval` (30 seconds by default);
|
|
309
|
+
a prefetch failure never marks samples processed or prevents reading the
|
|
310
|
+
current cached shard.
|
|
311
|
+
|
|
291
312
|
## configuration path
|
|
292
313
|
|
|
293
314
|
### config discovery order
|
|
@@ -27,6 +27,11 @@ pip install --upgrade pip
|
|
|
27
27
|
pip install "caption-flow[vllm]"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
The Linux GPU worker extra targets vLLM 0.31.x with PyTorch 2.13.0,
|
|
31
|
+
torchvision 0.28.0, and torchaudio 2.11.0 (as required by vLLM), plus
|
|
32
|
+
Transformers 5.10.4–5.17.x. To upgrade an existing worker from a checkout,
|
|
33
|
+
run `pip install --upgrade -e ".[vllm]"` in its environment and restart it.
|
|
34
|
+
|
|
30
35
|
An OpenAI-compatible API worker does not need the GPU dependencies:
|
|
31
36
|
|
|
32
37
|
```bash
|
|
@@ -119,7 +124,7 @@ Options:
|
|
|
119
124
|
* **csv**: exports CSV-compatible data columns to the `--output` path containing incomplete metadata
|
|
120
125
|
* **json**: creates a `.json` file for each sample inside the `--output` subdirectory containing **complete** metadata; useful for webdatasets
|
|
121
126
|
* **txt**: creates `.txt` file for each sample inside the `--output` subdirectory containing ONLY captions
|
|
122
|
-
* **webshart**: updates an **existing per-shard metadata `.json` file** by writing captions under the plural `captions` key. for this format, pass `--output` as the path to the existing shard metadata JSON file when exporting one shard.
|
|
127
|
+
* **webshart**: updates an **existing per-shard metadata `.json` file** by writing captions under the plural `captions` key. Strings, native JSON objects, and mixed lists are supported. JSON objects stored as text in Lance output columns are decoded during export, preserving nested values instead of writing Python dictionary representations. Native objects supplied through `Caption.outputs` are encoded as JSON only for Lance persistence. Requires webshart 0.6.0 or newer for native JSON caption support (included in the base dependencies). For this format, pass `--output` as the path to the existing shard metadata JSON file when exporting one shard. If you export multiple shards, pass `--output` as a directory containing one existing `{shard_name}.json` file per shard.
|
|
123
128
|
* **huggingface_hub**: creates a dataset on Hugging Face Hub, possibly `--private` and `--nsfw` where necessary
|
|
124
129
|
* **all**: creates the directory/file-generating export formats in a specified `--output` directory. prefer a directory here; `webshart` is a special case that expects existing per-shard metadata `.json` files rather than creating new metadata files.
|
|
125
130
|
|
|
@@ -178,6 +183,13 @@ prompts, sampling, and output fields. Existing `vllm:` configurations are also
|
|
|
178
183
|
accepted by API workers for backward compatibility; endpoint-local `model`
|
|
179
184
|
values take precedence over the broadcast model name.
|
|
180
185
|
|
|
186
|
+
Direct vLLM and API workers share JSON validation, output transformations,
|
|
187
|
+
refusal detection, and semantic retries. Configure those under
|
|
188
|
+
`inference.output_processing`; use `response_format` and `retry_response_format`
|
|
189
|
+
for constrained decoding on either backend. See the
|
|
190
|
+
[structured JSON recipe](recipes/STRUCTURED_JSON.md) for examples and native
|
|
191
|
+
vLLM tuning details.
|
|
192
|
+
|
|
181
193
|
---
|
|
182
194
|
|
|
183
195
|
## dataset formats
|
|
@@ -187,6 +199,15 @@ values take precedence over the broadcast model name.
|
|
|
187
199
|
* webdatasets shards containing full image data; also can be hosted on the hub
|
|
188
200
|
* local folder filled with images; orchestrator will serve the data to workers
|
|
189
201
|
|
|
202
|
+
For indexed Webshart reads, set `orchestrator.webshart_prefetch_shards: 1` to
|
|
203
|
+
download the next shard in the background while captioning the current one.
|
|
204
|
+
The default is `0` (disabled). This works with both direct vLLM and API workers,
|
|
205
|
+
does not move the sample cursor, and is ignored for explicit remote-range reads.
|
|
206
|
+
Size `shard_cache_gb` to hold the current shard plus the lookahead. Prefetch
|
|
207
|
+
retries are spaced by `webshart_cache_retry_interval` (30 seconds by default);
|
|
208
|
+
a prefetch failure never marks samples processed or prevents reading the
|
|
209
|
+
current cached shard.
|
|
210
|
+
|
|
190
211
|
## configuration path
|
|
191
212
|
|
|
192
213
|
### config discovery order
|
|
@@ -38,7 +38,7 @@ base_deps = [
|
|
|
38
38
|
"pandas>=3.0.0,<4.0.0",
|
|
39
39
|
"datasets>=5.0.0,<6.0.0",
|
|
40
40
|
"boto3>=1.43.0,<2.0.0",
|
|
41
|
-
"webshart>=0.
|
|
41
|
+
"webshart>=0.6.0,<0.7.0",
|
|
42
42
|
"pylance>=8.0.0,<9.0.0",
|
|
43
43
|
"duckdb>=1.5.0,<2.0.0",
|
|
44
44
|
"aiohttp>=3.13.3,<4.0.0",
|
|
@@ -51,21 +51,21 @@ base_deps = [
|
|
|
51
51
|
"urwid>=3.0.2,<5.0.0",
|
|
52
52
|
]
|
|
53
53
|
|
|
54
|
-
# vLLM 0.
|
|
55
|
-
# explicit so a worker install cannot silently combine incompatible
|
|
56
|
-
# packages when another dependency broadens its requirements.
|
|
54
|
+
# Match vLLM 0.31's published requirements, including torchaudio 2.11.0.
|
|
55
|
+
# Keep these explicit so a worker install cannot silently combine incompatible
|
|
56
|
+
# torch packages when another dependency broadens its requirements.
|
|
57
57
|
vllm_deps = [
|
|
58
|
-
"vllm>=0.
|
|
59
|
-
"torch==2.
|
|
60
|
-
"torchvision==0.
|
|
58
|
+
"vllm>=0.31.0,<0.32.0",
|
|
59
|
+
"torch==2.13.0",
|
|
60
|
+
"torchvision==0.28.0",
|
|
61
61
|
"torchaudio==2.11.0",
|
|
62
|
-
"transformers>=5.
|
|
62
|
+
"transformers>=5.10.4,<5.18.0",
|
|
63
63
|
"qwen-vl-utils>=0.0.14,<0.1.0",
|
|
64
64
|
]
|
|
65
65
|
|
|
66
66
|
PYTORCH_DEPENDENCIES = [
|
|
67
|
-
"torch>=2.
|
|
68
|
-
"torchvision>=0.
|
|
67
|
+
"torch>=2.13.0",
|
|
68
|
+
"torchvision>=0.28.0",
|
|
69
69
|
"torchaudio>=2.11.0",
|
|
70
70
|
]
|
|
71
71
|
|
|
@@ -92,7 +92,7 @@ extras_require = {
|
|
|
92
92
|
"pytest>=8.0.0,<9.0.0",
|
|
93
93
|
"pytest-asyncio>=1.1.0,<2.0.0",
|
|
94
94
|
"pytest-cov>=6.0.0,<7.0.0",
|
|
95
|
-
"transformers>=5.
|
|
95
|
+
"transformers>=5.10.4,<5.18.0",
|
|
96
96
|
"black>=25.0.0,<26.0.0",
|
|
97
97
|
"ruff>=0.12.0,<1.0.0",
|
|
98
98
|
"mypy>=1.17.0,<2.0.0",
|
|
@@ -6,7 +6,7 @@ import os
|
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
9
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
10
10
|
|
|
11
11
|
from PIL import Image
|
|
12
12
|
|
|
@@ -128,7 +128,9 @@ class Caption:
|
|
|
128
128
|
caption_count: int = 1 # Number of captions generated for this item
|
|
129
129
|
caption: Optional[str] = None
|
|
130
130
|
captions: Optional[List[str]] = None
|
|
131
|
-
outputs: Dict[str, List[str]] = field(
|
|
131
|
+
outputs: Dict[str, Union[str, Dict[str, Any], List[Union[str, Dict[str, Any]]]]] = field(
|
|
132
|
+
default_factory=dict
|
|
133
|
+
)
|
|
132
134
|
quality_score: Optional[float] = None
|
|
133
135
|
quality_scores: Optional[List[float]] = None
|
|
134
136
|
|
|
@@ -179,12 +181,13 @@ class ProcessingStage:
|
|
|
179
181
|
dtype: Optional[str] = None
|
|
180
182
|
gpu_memory_utilization: Optional[float] = None
|
|
181
183
|
|
|
182
|
-
#
|
|
183
|
-
# workers can omit the image on the fallback request when an upstream
|
|
184
|
-
# provider rejects the image before inference.
|
|
184
|
+
# Caption policy and recovery apply to every inference backend.
|
|
185
185
|
retry_prompt: Optional[str] = None
|
|
186
186
|
retry_without_image: bool = False
|
|
187
187
|
retry_sampling: Optional[Dict[str, Any]] = None
|
|
188
|
+
output_processing: Optional[Dict[str, Any]] = None
|
|
189
|
+
response_format: Optional[Dict[str, Any]] = None
|
|
190
|
+
retry_response_format: Optional[Dict[str, Any]] = None
|
|
188
191
|
|
|
189
192
|
|
|
190
193
|
@dataclass
|
|
@@ -51,7 +51,7 @@ class Orchestrator:
|
|
|
51
51
|
assert (
|
|
52
52
|
processor_type is not None
|
|
53
53
|
), "You must supply processor_type in your orchestrator dataset configuration."
|
|
54
|
-
processor_config = ProcessorConfig(processor_type=processor_type, config=config)
|
|
54
|
+
self.processor_config = ProcessorConfig(processor_type=processor_type, config=config)
|
|
55
55
|
|
|
56
56
|
# Initialize processor
|
|
57
57
|
if processor_type == "webdataset":
|
|
@@ -70,7 +70,6 @@ class Orchestrator:
|
|
|
70
70
|
caption_buffer_size=storage_config.get("caption_buffer_size", 1000),
|
|
71
71
|
)
|
|
72
72
|
self.auth = AuthManager(config.get("auth", {}))
|
|
73
|
-
self.processor.initialize(processor_config, self.storage)
|
|
74
73
|
|
|
75
74
|
# Processing configuration
|
|
76
75
|
self.chunks_per_request = config.get("chunks_per_request", 2)
|
|
@@ -132,6 +131,8 @@ class Orchestrator:
|
|
|
132
131
|
|
|
133
132
|
# Initialize storage
|
|
134
133
|
await self.storage.initialize()
|
|
134
|
+
# Checkpoints can include results that had not reached a durable flush.
|
|
135
|
+
self.processor.initialize(self.processor_config, self.storage)
|
|
135
136
|
|
|
136
137
|
# Start background tasks
|
|
137
138
|
asyncio.create_task(self._heartbeat_loop())
|
|
@@ -410,7 +411,9 @@ class Orchestrator:
|
|
|
410
411
|
|
|
411
412
|
elif msg_type == "work_complete":
|
|
412
413
|
unit_id = data["unit_id"]
|
|
413
|
-
self.processor.mark_completed(unit_id, worker_id)
|
|
414
|
+
if self.processor.mark_completed(unit_id, worker_id) is False:
|
|
415
|
+
logger.warning(f"Work unit {unit_id} reported complete before all results arrived")
|
|
416
|
+
return
|
|
414
417
|
logger.debug(f"Work unit {unit_id} completed by worker {worker_id}")
|
|
415
418
|
await self._send_activity(f"Chunk completed: {unit_id}")
|
|
416
419
|
|
|
@@ -428,9 +431,8 @@ class Orchestrator:
|
|
|
428
431
|
logger.debug(f"Heartbeat from {worker_id}: {data}")
|
|
429
432
|
|
|
430
433
|
async def _handle_results_submission(self, worker_id: str, data: Dict):
|
|
431
|
-
"""
|
|
432
|
-
|
|
433
|
-
asyncio.create_task(self._process_result_async(worker_id, data))
|
|
434
|
+
"""Accept results in connection order before handling a completion message."""
|
|
435
|
+
await self._process_result_async(worker_id, data)
|
|
434
436
|
|
|
435
437
|
async def _process_result_async(self, worker_id: str, data: Dict):
|
|
436
438
|
"""Actually process the result in background."""
|
|
@@ -444,6 +446,9 @@ class Orchestrator:
|
|
|
444
446
|
shard_name = job_id.shard_id
|
|
445
447
|
chunk_name = job_id.chunk_id
|
|
446
448
|
|
|
449
|
+
if data.get("error") or not data.get("outputs"):
|
|
450
|
+
raise ValueError("A failed result cannot be recorded as completed work")
|
|
451
|
+
|
|
447
452
|
result = WorkResult(
|
|
448
453
|
unit_id=data["unit_id"],
|
|
449
454
|
source_id=shard_name,
|
|
@@ -455,11 +460,6 @@ class Orchestrator:
|
|
|
455
460
|
processing_time_ms=data.get("processing_time_ms", 0),
|
|
456
461
|
)
|
|
457
462
|
|
|
458
|
-
# Let processor handle any custom processing - this updates chunk tracker
|
|
459
|
-
# IMPORTANT: Call this BEFORE saving to storage so chunk tracker is updated
|
|
460
|
-
# regardless of whether the item is a duplicate
|
|
461
|
-
processed = self.processor.handle_result(result)
|
|
462
|
-
|
|
463
463
|
# Create caption record for storage
|
|
464
464
|
total_outputs = sum(len(v) for v in result.outputs.values())
|
|
465
465
|
|
|
@@ -480,7 +480,7 @@ class Orchestrator:
|
|
|
480
480
|
caption = Caption(
|
|
481
481
|
job_id=job_id,
|
|
482
482
|
dataset=result.dataset,
|
|
483
|
-
shard=
|
|
483
|
+
shard=result.source_id,
|
|
484
484
|
chunk_id=chunk_name,
|
|
485
485
|
item_key=item_key,
|
|
486
486
|
captions=result.outputs.get("captions", []),
|
|
@@ -501,6 +501,11 @@ class Orchestrator:
|
|
|
501
501
|
# Save to storage (might skip if duplicate)
|
|
502
502
|
saved = await self.storage.save_caption(caption)
|
|
503
503
|
|
|
504
|
+
# Progress may only follow storage acceptance. A duplicate is also
|
|
505
|
+
# accepted: its caption is already present. Startup reconstructs
|
|
506
|
+
# progress from durable storage if buffered results are lost.
|
|
507
|
+
self.processor.handle_result(result)
|
|
508
|
+
|
|
504
509
|
# Update contributor stats only if actually saved
|
|
505
510
|
if saved:
|
|
506
511
|
contributor = await self.storage.get_contributor(worker_user)
|
|
@@ -509,8 +514,11 @@ class Orchestrator:
|
|
|
509
514
|
await self.storage.save_contributor(contributor)
|
|
510
515
|
|
|
511
516
|
except Exception as e:
|
|
517
|
+
if data.get("unit_id"):
|
|
518
|
+
self.processor.mark_failed(data["unit_id"], worker_id, "Result acceptance failed")
|
|
512
519
|
logger.error(
|
|
513
|
-
f"Error processing result from {worker_id}
|
|
520
|
+
f"Error processing result from {worker_id} "
|
|
521
|
+
f"for unit {data.get('unit_id', 'unknown')}: {e}",
|
|
514
522
|
exc_info=True,
|
|
515
523
|
)
|
|
516
524
|
|