batchor 0.0.3__tar.gz → 0.0.4__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.
- {batchor-0.0.3 → batchor-0.0.4}/.agents/plugins/marketplace.json +12 -0
- {batchor-0.0.3 → batchor-0.0.4}/PKG-INFO +102 -14
- {batchor-0.0.3 → batchor-0.0.4}/README.md +96 -11
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/ARCHITECTURE.md +16 -7
- batchor-0.0.4/docs/design_docs/GEMINI_BATCHING.md +96 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/OPENAI_BATCHING.md +3 -2
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/ROADMAP.md +2 -1
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/STORAGE_AND_RUNS.md +3 -2
- {batchor-0.0.3 → batchor-0.0.4}/docs/doc-map.md +2 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/getting-started/cli.md +43 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/getting-started/installation.md +37 -1
- {batchor-0.0.3 → batchor-0.0.4}/docs/getting-started/python-api.md +41 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/index.md +2 -2
- {batchor-0.0.3 → batchor-0.0.4}/docs/reference/api.md +10 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/smoke-test.md +28 -0
- {batchor-0.0.3 → batchor-0.0.4}/mkdocs.yml +2 -1
- batchor-0.0.4/plugins/batchor/.codex-plugin/plugin.json +44 -0
- batchor-0.0.4/plugins/batchor/.mcp.json +10 -0
- batchor-0.0.4/plugins/batchor/scripts/batchor_user_mcp.py +205 -0
- batchor-0.0.4/plugins/batchor/skills/use-batchor/SKILL.md +57 -0
- batchor-0.0.4/plugins/batchor/skills/use-batchor/agents/openai.yaml +4 -0
- batchor-0.0.4/plugins/batchor/skills/use-batchor/references/cli-workflows.md +45 -0
- batchor-0.0.4/plugins/batchor/skills/use-batchor/references/python-pipelines.md +64 -0
- {batchor-0.0.3 → batchor-0.0.4}/plugins/batchor-agent-tools/scripts/batchor_repo_mcp.py +10 -3
- {batchor-0.0.3 → batchor-0.0.4}/pyproject.toml +10 -4
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/__init__.py +8 -2
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/cli.py +93 -3
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/core/enums.py +16 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/core/models.py +148 -1
- batchor-0.0.4/src/batchor/core/responses.py +60 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/core/types.py +10 -7
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/providers/base.py +33 -3
- batchor-0.0.4/src/batchor/providers/gemini.py +554 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/providers/registry.py +20 -7
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/polling.py +3 -2
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/submission.py +13 -9
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/validation.py +12 -67
- batchor-0.0.4/tests/integration/test_batchor_gemini_runner.py +219 -0
- batchor-0.0.4/tests/integration/test_batchor_live_gemini.py +157 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/integration/test_batchor_runner.py +15 -0
- batchor-0.0.4/tests/unit/test_agent_tooling.py +163 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_architecture.py +31 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_cli.py +123 -1
- batchor-0.0.4/tests/unit/test_batchor_gemini_provider.py +355 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_runtime_polling.py +3 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_runtime_submission.py +94 -2
- {batchor-0.0.3 → batchor-0.0.4}/uv.lock +367 -1
- batchor-0.0.3/tests/unit/test_agent_tooling.py +0 -49
- {batchor-0.0.3 → batchor-0.0.4}/.agents/skills/batchor-dev/SKILL.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.agents/skills/batchor-dev/agents/openai.yaml +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.github/workflows/ci.yml +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.github/workflows/docs.yml +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.github/workflows/publish.yml +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.gitignore +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/.pre-commit-config.yaml +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/AGENTS.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/CONTRIBUTING.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/LICENSE +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/SUPPORT.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/VERSIONING.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/assets/stylesheets/extra.css +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/BOUNDARY_AND_PHILOSOPHY.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/design_docs/STORAGE_MIGRATIONS.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/getting-started/use-cases.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/policies/contributing.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/policies/support.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/docs/policies/versioning.md +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/plugins/batchor-agent-tools/.codex-plugin/plugin.json +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/plugins/batchor-agent-tools/.mcp.json +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/artifacts/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/artifacts/base.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/artifacts/local.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/core/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/core/exceptions.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/providers/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/providers/openai.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/py.typed +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/artifacts.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/context.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/ingestion.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/results.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/retry.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/run_handle.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/runner.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/runtime/tokens.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/sources/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/sources/base.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/sources/composite.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/sources/files.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/__init__.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/memory.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/postgres.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/postgres_store.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/registry.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_codec.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_lifecycle.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_protocol.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_queries.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_results.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_schema.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/sqlite_store.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/state.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/src/batchor/storage/state_models.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/integration/test_batchor_live_openai.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_artifacts.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_openai_provider.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_results.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_retry.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_runtime_ingestion.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_sources.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_sqlite_storage_flow.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_storage.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_storage_contracts.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_tokens.py +0 -0
- {batchor-0.0.3 → batchor-0.0.4}/tests/unit/test_batchor_validation.py +0 -0
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
"authentication": "ON_INSTALL"
|
|
16
16
|
},
|
|
17
17
|
"category": "Coding"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "batchor",
|
|
21
|
+
"source": {
|
|
22
|
+
"source": "local",
|
|
23
|
+
"path": "./plugins/batchor"
|
|
24
|
+
},
|
|
25
|
+
"policy": {
|
|
26
|
+
"installation": "AVAILABLE",
|
|
27
|
+
"authentication": "ON_INSTALL"
|
|
28
|
+
},
|
|
29
|
+
"category": "Coding"
|
|
18
30
|
}
|
|
19
31
|
]
|
|
20
32
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batchor
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: Structured-first
|
|
3
|
+
Version: 0.0.4
|
|
4
|
+
Summary: Structured-first provider Batch runner with typed Pydantic results.
|
|
5
5
|
Project-URL: Documentation, https://github.com/AnsonDev42/batchor#readme
|
|
6
6
|
Project-URL: Repository, https://github.com/AnsonDev42/batchor
|
|
7
7
|
Project-URL: Issues, https://github.com/AnsonDev42/batchor/issues
|
|
@@ -79,7 +79,7 @@ License: # PolyForm Noncommercial License 1.0.0
|
|
|
79
79
|
|
|
80
80
|
**Use** means anything you do with the software requiring one of your licenses.
|
|
81
81
|
License-File: LICENSE
|
|
82
|
-
Keywords: batch,cli,openai,pydantic,sqlite
|
|
82
|
+
Keywords: batch,cli,gemini,openai,pydantic,sqlite
|
|
83
83
|
Classifier: Development Status :: 3 - Alpha
|
|
84
84
|
Classifier: Environment :: Console
|
|
85
85
|
Classifier: Intended Audience :: Developers
|
|
@@ -99,13 +99,16 @@ Requires-Dist: python-dotenv<2,>=1.0.1
|
|
|
99
99
|
Requires-Dist: sqlalchemy<3,>=2.0.43
|
|
100
100
|
Requires-Dist: tiktoken>=0.12.0
|
|
101
101
|
Requires-Dist: typer<1,>=0.16.0
|
|
102
|
+
Provides-Extra: gemini
|
|
103
|
+
Requires-Dist: google-cloud-storage<4,>=3.4.0; extra == 'gemini'
|
|
104
|
+
Requires-Dist: google-genai<2,>=1.55.0; extra == 'gemini'
|
|
102
105
|
Description-Content-Type: text/markdown
|
|
103
106
|
|
|
104
107
|
# batchor
|
|
105
108
|
|
|
106
109
|
`batchor` grew out of a recurring problem in academic research: running large datasets through LLMs in batch — reliably, reproducibly, and without reinventing the same glue code across every project. The patterns that kept emerging (durable state, typed results, safe resume after failure) were extracted into this library so they do not have to be rebuilt each time.
|
|
107
110
|
|
|
108
|
-
`batchor` is a durable
|
|
111
|
+
`batchor` is a durable provider Batch runner for Python teams that want:
|
|
109
112
|
|
|
110
113
|
- typed Pydantic results
|
|
111
114
|
- resumable durable runs
|
|
@@ -115,7 +118,7 @@ Description-Content-Type: text/markdown
|
|
|
115
118
|
- library-first run controls
|
|
116
119
|
- a small operator CLI for CSV and JSONL jobs
|
|
117
120
|
|
|
118
|
-
It is intentionally narrow today: OpenAI
|
|
121
|
+
It is intentionally narrow today: OpenAI is the CLI default, Gemini is opt-in through `batchor[gemini]`, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
|
|
119
122
|
|
|
120
123
|
## What problem it solves
|
|
121
124
|
|
|
@@ -140,6 +143,7 @@ Most OpenAI Batch examples stop at "upload a JSONL file and poll until it finish
|
|
|
140
143
|
Built-in implementations:
|
|
141
144
|
|
|
142
145
|
- `OpenAIProviderConfig` + `OpenAIBatchProvider`
|
|
146
|
+
- `GeminiProviderConfig` + `GeminiBatchProvider` for text-only Gemini Batch jobs
|
|
143
147
|
- `SQLiteStorage`
|
|
144
148
|
- `PostgresStorage` as an opt-in durable control-plane backend
|
|
145
149
|
- `MemoryStateStore`
|
|
@@ -155,6 +159,8 @@ Important constraints:
|
|
|
155
159
|
- the CLI supports file-backed inputs only
|
|
156
160
|
- users still own selecting and ordering input files or partitions
|
|
157
161
|
- the built-in CLI uses SQLite durability only
|
|
162
|
+
- the CLI supports OpenAI plus Gemini Developer API and Vertex AI text jobs
|
|
163
|
+
- Gemini support is text-only for now and does not build multimodal requests
|
|
158
164
|
- structured-output rehydration requires an importable module-level Pydantic model
|
|
159
165
|
- raw output artifacts are retained by default and must be exported before raw pruning
|
|
160
166
|
- pause/resume/cancel and incremental terminal-result APIs are library-first today
|
|
@@ -193,6 +199,7 @@ graph LR
|
|
|
193
199
|
|
|
194
200
|
subgraph providers["providers/"]
|
|
195
201
|
OpenAI["OpenAIBatchProvider"]
|
|
202
|
+
Gemini["GeminiBatchProvider"]
|
|
196
203
|
end
|
|
197
204
|
|
|
198
205
|
subgraph sources["sources/"]
|
|
@@ -212,6 +219,7 @@ graph LR
|
|
|
212
219
|
User -->|"start() / run_and_wait()"| BatchRunner
|
|
213
220
|
BatchRunner --> Run
|
|
214
221
|
BatchRunner --> OpenAI
|
|
222
|
+
BatchRunner --> Gemini
|
|
215
223
|
BatchRunner --> SQLite
|
|
216
224
|
BatchRunner --> LocalFS
|
|
217
225
|
Files -->|"BatchItem stream"| BatchRunner
|
|
@@ -247,16 +255,31 @@ Operational semantics for resume, run control, and artifact retention live in
|
|
|
247
255
|
pip install batchor
|
|
248
256
|
```
|
|
249
257
|
|
|
250
|
-
|
|
258
|
+
For Gemini Batch support, install the optional extra:
|
|
251
259
|
|
|
252
|
-
|
|
260
|
+
```bash
|
|
261
|
+
pip install "batchor[gemini]"
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Agent setup
|
|
265
|
+
|
|
266
|
+
Batchor keeps contributor tooling separate from the tools intended for researchers and downstream projects:
|
|
253
267
|
|
|
254
|
-
-
|
|
255
|
-
-
|
|
256
|
-
-
|
|
257
|
-
-
|
|
268
|
+
- `plugins/batchor/` is the user-facing Codex plugin. Its `$use-batchor` skill and MCP helpers turn datasets and prompts into safe CLI or Python workflows without assuming a Batchor source checkout.
|
|
269
|
+
- `.agents/skills/batchor-dev/` and `plugins/batchor-agent-tools/` are contributor-only. They teach agents how to change this repository, find design docs, and run its validation suite.
|
|
270
|
+
- `.agents/plugins/marketplace.json` registers both plugins for local development.
|
|
271
|
+
- `.vscode/mcp.json` configures the contributor MCP for this workspace.
|
|
258
272
|
|
|
259
|
-
The
|
|
273
|
+
The PyPI package remains the runtime dependency: `pip install batchor` installs the library and CLI. Agent skills and MCP configuration are distributed as the separate `batchor` plugin so Python environments do not receive Codex-specific files implicitly.
|
|
274
|
+
|
|
275
|
+
To try the user plugin from a local checkout:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
codex plugin marketplace add /path/to/batchor
|
|
279
|
+
codex plugin add batchor@batchor-local
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Start a new Codex task after installation, then ask: `Use $use-batchor to turn my CSV and research prompt into a resumable batch job.`
|
|
260
283
|
|
|
261
284
|
Supported Python versions:
|
|
262
285
|
|
|
@@ -268,8 +291,9 @@ Supported Python versions:
|
|
|
268
291
|
|
|
269
292
|
For Python API usage, auth resolution is:
|
|
270
293
|
|
|
271
|
-
1. explicit `OpenAIProviderConfig(api_key=...)`
|
|
272
|
-
2. ambient `OPENAI_API_KEY`
|
|
294
|
+
1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)` or `GeminiProviderConfig(api_key=...)`
|
|
295
|
+
2. ambient provider environment variables, currently `OPENAI_API_KEY` or `GEMINI_API_KEY`
|
|
296
|
+
3. Vertex AI Application Default Credentials when `GeminiProviderConfig(vertexai=True, ...)` or `GOOGLE_GENAI_USE_VERTEXAI=true` is used
|
|
273
297
|
|
|
274
298
|
The Python library does not auto-load `.env`.
|
|
275
299
|
|
|
@@ -298,6 +322,43 @@ run = runner.run_and_wait(
|
|
|
298
322
|
print(run.results()[0].output_text)
|
|
299
323
|
```
|
|
300
324
|
|
|
325
|
+
### Gemini text job
|
|
326
|
+
|
|
327
|
+
```python
|
|
328
|
+
from batchor import BatchItem, BatchJob, BatchRunner, GeminiProviderConfig, PromptParts
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
runner = BatchRunner(storage="memory")
|
|
332
|
+
run = runner.run_and_wait(
|
|
333
|
+
BatchJob(
|
|
334
|
+
items=[BatchItem(item_id="row1", payload="Summarize this text")],
|
|
335
|
+
build_prompt=lambda item: PromptParts(prompt=item.payload),
|
|
336
|
+
provider_config=GeminiProviderConfig(
|
|
337
|
+
model="gemini-2.5-flash",
|
|
338
|
+
api_key="YOUR_GEMINI_API_KEY",
|
|
339
|
+
),
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
print(run.results()[0].output_text)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Gemini support currently builds text-only `GenerateContent` batch requests. It uses Gemini JSONL `key` values internally while keeping `batchor`'s durable item and attempt tracking unchanged.
|
|
347
|
+
|
|
348
|
+
For Vertex AI, provide a Cloud Storage staging prefix and use Application Default Credentials:
|
|
349
|
+
|
|
350
|
+
```python
|
|
351
|
+
provider_config = GeminiProviderConfig(
|
|
352
|
+
model="gemini-2.5-flash",
|
|
353
|
+
vertexai=True,
|
|
354
|
+
project="my-project",
|
|
355
|
+
location="europe-west8",
|
|
356
|
+
gcs_uri="gs://my-bucket/batchor",
|
|
357
|
+
)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Vertex AI stages JSONL input and output in that prefix. The Gemini Developer API uses inline requests for batches below 20 MB and the Files API for larger batches; `input_mode=` can override that automatic choice. Vertex request/output correlation uses a generated request label because Vertex output does not include the Developer API JSONL `key`.
|
|
361
|
+
|
|
301
362
|
### Structured output
|
|
302
363
|
|
|
303
364
|
```python
|
|
@@ -351,6 +412,8 @@ Structured-output models are validated up front against the OpenAI strict-schema
|
|
|
351
412
|
|
|
352
413
|
If you need a field to be optional in Python, model it as nullable in the schema shape OpenAI accepts rather than relying on omitted required fields.
|
|
353
414
|
|
|
415
|
+
The same `structured_output=` API is available with `GeminiProviderConfig`; batchor sends the schema through Gemini `generation_config.response_json_schema` and validates the returned JSON text with the same Pydantic model.
|
|
416
|
+
|
|
354
417
|
### Rehydrate a durable run
|
|
355
418
|
|
|
356
419
|
```python
|
|
@@ -498,6 +561,31 @@ The CLI is intentionally narrower than the Python API:
|
|
|
498
561
|
- CSV and JSONL only
|
|
499
562
|
- SQLite-backed durable runs only
|
|
500
563
|
|
|
564
|
+
OpenAI remains the default provider. For Gemini, install `batchor[gemini]` and select the backend explicitly or let `auto` follow `GOOGLE_GENAI_USE_VERTEXAI`:
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
batchor start \
|
|
568
|
+
--input input/items.jsonl \
|
|
569
|
+
--id-field id \
|
|
570
|
+
--prompt-field text \
|
|
571
|
+
--provider gemini \
|
|
572
|
+
--model gemini-2.5-flash \
|
|
573
|
+
--gemini-backend developer
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
Vertex AI additionally needs a writable staging prefix:
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
batchor start \
|
|
580
|
+
--input input/items.jsonl \
|
|
581
|
+
--id-field id \
|
|
582
|
+
--prompt-field text \
|
|
583
|
+
--provider gemini \
|
|
584
|
+
--model gemini-2.5-flash \
|
|
585
|
+
--gemini-backend vertex \
|
|
586
|
+
--gcs-uri gs://my-bucket/batchor
|
|
587
|
+
```
|
|
588
|
+
|
|
501
589
|
Start a run from JSONL:
|
|
502
590
|
|
|
503
591
|
```bash
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`batchor` grew out of a recurring problem in academic research: running large datasets through LLMs in batch — reliably, reproducibly, and without reinventing the same glue code across every project. The patterns that kept emerging (durable state, typed results, safe resume after failure) were extracted into this library so they do not have to be rebuilt each time.
|
|
4
4
|
|
|
5
|
-
`batchor` is a durable
|
|
5
|
+
`batchor` is a durable provider Batch runner for Python teams that want:
|
|
6
6
|
|
|
7
7
|
- typed Pydantic results
|
|
8
8
|
- resumable durable runs
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- library-first run controls
|
|
13
13
|
- a small operator CLI for CSV and JSONL jobs
|
|
14
14
|
|
|
15
|
-
It is intentionally narrow today: OpenAI
|
|
15
|
+
It is intentionally narrow today: OpenAI is the CLI default, Gemini is opt-in through `batchor[gemini]`, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
|
|
16
16
|
|
|
17
17
|
## What problem it solves
|
|
18
18
|
|
|
@@ -37,6 +37,7 @@ Most OpenAI Batch examples stop at "upload a JSONL file and poll until it finish
|
|
|
37
37
|
Built-in implementations:
|
|
38
38
|
|
|
39
39
|
- `OpenAIProviderConfig` + `OpenAIBatchProvider`
|
|
40
|
+
- `GeminiProviderConfig` + `GeminiBatchProvider` for text-only Gemini Batch jobs
|
|
40
41
|
- `SQLiteStorage`
|
|
41
42
|
- `PostgresStorage` as an opt-in durable control-plane backend
|
|
42
43
|
- `MemoryStateStore`
|
|
@@ -52,6 +53,8 @@ Important constraints:
|
|
|
52
53
|
- the CLI supports file-backed inputs only
|
|
53
54
|
- users still own selecting and ordering input files or partitions
|
|
54
55
|
- the built-in CLI uses SQLite durability only
|
|
56
|
+
- the CLI supports OpenAI plus Gemini Developer API and Vertex AI text jobs
|
|
57
|
+
- Gemini support is text-only for now and does not build multimodal requests
|
|
55
58
|
- structured-output rehydration requires an importable module-level Pydantic model
|
|
56
59
|
- raw output artifacts are retained by default and must be exported before raw pruning
|
|
57
60
|
- pause/resume/cancel and incremental terminal-result APIs are library-first today
|
|
@@ -90,6 +93,7 @@ graph LR
|
|
|
90
93
|
|
|
91
94
|
subgraph providers["providers/"]
|
|
92
95
|
OpenAI["OpenAIBatchProvider"]
|
|
96
|
+
Gemini["GeminiBatchProvider"]
|
|
93
97
|
end
|
|
94
98
|
|
|
95
99
|
subgraph sources["sources/"]
|
|
@@ -109,6 +113,7 @@ graph LR
|
|
|
109
113
|
User -->|"start() / run_and_wait()"| BatchRunner
|
|
110
114
|
BatchRunner --> Run
|
|
111
115
|
BatchRunner --> OpenAI
|
|
116
|
+
BatchRunner --> Gemini
|
|
112
117
|
BatchRunner --> SQLite
|
|
113
118
|
BatchRunner --> LocalFS
|
|
114
119
|
Files -->|"BatchItem stream"| BatchRunner
|
|
@@ -144,16 +149,31 @@ Operational semantics for resume, run control, and artifact retention live in
|
|
|
144
149
|
pip install batchor
|
|
145
150
|
```
|
|
146
151
|
|
|
147
|
-
|
|
152
|
+
For Gemini Batch support, install the optional extra:
|
|
148
153
|
|
|
149
|
-
|
|
154
|
+
```bash
|
|
155
|
+
pip install "batchor[gemini]"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Agent setup
|
|
159
|
+
|
|
160
|
+
Batchor keeps contributor tooling separate from the tools intended for researchers and downstream projects:
|
|
150
161
|
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
162
|
+
- `plugins/batchor/` is the user-facing Codex plugin. Its `$use-batchor` skill and MCP helpers turn datasets and prompts into safe CLI or Python workflows without assuming a Batchor source checkout.
|
|
163
|
+
- `.agents/skills/batchor-dev/` and `plugins/batchor-agent-tools/` are contributor-only. They teach agents how to change this repository, find design docs, and run its validation suite.
|
|
164
|
+
- `.agents/plugins/marketplace.json` registers both plugins for local development.
|
|
165
|
+
- `.vscode/mcp.json` configures the contributor MCP for this workspace.
|
|
155
166
|
|
|
156
|
-
The
|
|
167
|
+
The PyPI package remains the runtime dependency: `pip install batchor` installs the library and CLI. Agent skills and MCP configuration are distributed as the separate `batchor` plugin so Python environments do not receive Codex-specific files implicitly.
|
|
168
|
+
|
|
169
|
+
To try the user plugin from a local checkout:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
codex plugin marketplace add /path/to/batchor
|
|
173
|
+
codex plugin add batchor@batchor-local
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Start a new Codex task after installation, then ask: `Use $use-batchor to turn my CSV and research prompt into a resumable batch job.`
|
|
157
177
|
|
|
158
178
|
Supported Python versions:
|
|
159
179
|
|
|
@@ -165,8 +185,9 @@ Supported Python versions:
|
|
|
165
185
|
|
|
166
186
|
For Python API usage, auth resolution is:
|
|
167
187
|
|
|
168
|
-
1. explicit `OpenAIProviderConfig(api_key=...)`
|
|
169
|
-
2. ambient `OPENAI_API_KEY`
|
|
188
|
+
1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)` or `GeminiProviderConfig(api_key=...)`
|
|
189
|
+
2. ambient provider environment variables, currently `OPENAI_API_KEY` or `GEMINI_API_KEY`
|
|
190
|
+
3. Vertex AI Application Default Credentials when `GeminiProviderConfig(vertexai=True, ...)` or `GOOGLE_GENAI_USE_VERTEXAI=true` is used
|
|
170
191
|
|
|
171
192
|
The Python library does not auto-load `.env`.
|
|
172
193
|
|
|
@@ -195,6 +216,43 @@ run = runner.run_and_wait(
|
|
|
195
216
|
print(run.results()[0].output_text)
|
|
196
217
|
```
|
|
197
218
|
|
|
219
|
+
### Gemini text job
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from batchor import BatchItem, BatchJob, BatchRunner, GeminiProviderConfig, PromptParts
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
runner = BatchRunner(storage="memory")
|
|
226
|
+
run = runner.run_and_wait(
|
|
227
|
+
BatchJob(
|
|
228
|
+
items=[BatchItem(item_id="row1", payload="Summarize this text")],
|
|
229
|
+
build_prompt=lambda item: PromptParts(prompt=item.payload),
|
|
230
|
+
provider_config=GeminiProviderConfig(
|
|
231
|
+
model="gemini-2.5-flash",
|
|
232
|
+
api_key="YOUR_GEMINI_API_KEY",
|
|
233
|
+
),
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
print(run.results()[0].output_text)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Gemini support currently builds text-only `GenerateContent` batch requests. It uses Gemini JSONL `key` values internally while keeping `batchor`'s durable item and attempt tracking unchanged.
|
|
241
|
+
|
|
242
|
+
For Vertex AI, provide a Cloud Storage staging prefix and use Application Default Credentials:
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
provider_config = GeminiProviderConfig(
|
|
246
|
+
model="gemini-2.5-flash",
|
|
247
|
+
vertexai=True,
|
|
248
|
+
project="my-project",
|
|
249
|
+
location="europe-west8",
|
|
250
|
+
gcs_uri="gs://my-bucket/batchor",
|
|
251
|
+
)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Vertex AI stages JSONL input and output in that prefix. The Gemini Developer API uses inline requests for batches below 20 MB and the Files API for larger batches; `input_mode=` can override that automatic choice. Vertex request/output correlation uses a generated request label because Vertex output does not include the Developer API JSONL `key`.
|
|
255
|
+
|
|
198
256
|
### Structured output
|
|
199
257
|
|
|
200
258
|
```python
|
|
@@ -248,6 +306,8 @@ Structured-output models are validated up front against the OpenAI strict-schema
|
|
|
248
306
|
|
|
249
307
|
If you need a field to be optional in Python, model it as nullable in the schema shape OpenAI accepts rather than relying on omitted required fields.
|
|
250
308
|
|
|
309
|
+
The same `structured_output=` API is available with `GeminiProviderConfig`; batchor sends the schema through Gemini `generation_config.response_json_schema` and validates the returned JSON text with the same Pydantic model.
|
|
310
|
+
|
|
251
311
|
### Rehydrate a durable run
|
|
252
312
|
|
|
253
313
|
```python
|
|
@@ -395,6 +455,31 @@ The CLI is intentionally narrower than the Python API:
|
|
|
395
455
|
- CSV and JSONL only
|
|
396
456
|
- SQLite-backed durable runs only
|
|
397
457
|
|
|
458
|
+
OpenAI remains the default provider. For Gemini, install `batchor[gemini]` and select the backend explicitly or let `auto` follow `GOOGLE_GENAI_USE_VERTEXAI`:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
batchor start \
|
|
462
|
+
--input input/items.jsonl \
|
|
463
|
+
--id-field id \
|
|
464
|
+
--prompt-field text \
|
|
465
|
+
--provider gemini \
|
|
466
|
+
--model gemini-2.5-flash \
|
|
467
|
+
--gemini-backend developer
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Vertex AI additionally needs a writable staging prefix:
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
batchor start \
|
|
474
|
+
--input input/items.jsonl \
|
|
475
|
+
--id-field id \
|
|
476
|
+
--prompt-field text \
|
|
477
|
+
--provider gemini \
|
|
478
|
+
--model gemini-2.5-flash \
|
|
479
|
+
--gemini-backend vertex \
|
|
480
|
+
--gcs-uri gs://my-bucket/batchor
|
|
481
|
+
```
|
|
482
|
+
|
|
398
483
|
Start a run from JSONL:
|
|
399
484
|
|
|
400
485
|
```bash
|
|
@@ -11,6 +11,8 @@ batchor/
|
|
|
11
11
|
.agents/
|
|
12
12
|
docs/
|
|
13
13
|
plugins/
|
|
14
|
+
batchor/
|
|
15
|
+
batchor-agent-tools/
|
|
14
16
|
src/batchor/
|
|
15
17
|
artifacts/
|
|
16
18
|
cli.py
|
|
@@ -22,13 +24,14 @@ batchor/
|
|
|
22
24
|
tests/
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
Agent tooling lives outside the shipped Python package so Python installation does not mutate or assume a particular coding-agent environment:
|
|
26
28
|
|
|
27
29
|
- `.agents/skills/batchor-dev/` contains the repo skill for AI-agent onboarding
|
|
28
30
|
- `.agents/plugins/marketplace.json` registers repo-local plugins for Codex-style discovery
|
|
29
|
-
- `plugins/batchor-agent-tools/` contains
|
|
31
|
+
- `plugins/batchor-agent-tools/` contains contributor-only repo guidance and validation tools
|
|
32
|
+
- `plugins/batchor/` contains the downstream user skill and repo-independent workflow MCP for researchers and agents integrating Batchor into other projects
|
|
30
33
|
|
|
31
|
-
These directories are
|
|
34
|
+
These directories are not part of the published `src/batchor` package. PyPI distributes the runtime and CLI; the agent marketplace distributes agent-specific skills and MCP configuration.
|
|
32
35
|
|
|
33
36
|
The package is organized around one core concern: durable batch execution. Most modules exist to support one of five responsibilities:
|
|
34
37
|
|
|
@@ -58,6 +61,7 @@ graph TB
|
|
|
58
61
|
subgraph providers["providers/"]
|
|
59
62
|
BatchProvider["BatchProvider (ABC)"]
|
|
60
63
|
OpenAIProvider["OpenAIBatchProvider"]
|
|
64
|
+
GeminiProvider["GeminiBatchProvider"]
|
|
61
65
|
ProviderRegistry
|
|
62
66
|
end
|
|
63
67
|
|
|
@@ -91,6 +95,7 @@ graph TB
|
|
|
91
95
|
MemoryStateStore -.->|implements| StateStore
|
|
92
96
|
BatchRunner -->|submits/polls| BatchProvider
|
|
93
97
|
OpenAIProvider -.->|implements| BatchProvider
|
|
98
|
+
GeminiProvider -.->|implements| BatchProvider
|
|
94
99
|
BatchRunner -->|stores artifacts| ArtifactStore
|
|
95
100
|
LocalArtifactStore -.->|implements| ArtifactStore
|
|
96
101
|
BatchRunner -->|creates via| ProviderRegistry
|
|
@@ -120,6 +125,10 @@ The public runtime model centers on four types:
|
|
|
120
125
|
one logical source, while callers remain responsible for selecting and ordering
|
|
121
126
|
the child sources up front.
|
|
122
127
|
|
|
128
|
+
Provider adaptation is intentionally concentrated behind `BatchProvider`.
|
|
129
|
+
The runtime stores one durable internal custom identifier per item attempt, while each provider maps that identifier to its own request shape. OpenAI uses `custom_id`; the Gemini Developer API uses `key`; Vertex AI uses a request label that is returned with the original request in GCS output.
|
|
130
|
+
Provider hooks also own response-text extraction so structured-output parsing can stay generic across provider payload shapes.
|
|
131
|
+
|
|
123
132
|
## Main user-facing flow
|
|
124
133
|
|
|
125
134
|
The normal public flow is:
|
|
@@ -137,7 +146,7 @@ Internally that expands to:
|
|
|
137
146
|
4. Claim a bounded submission window from pending items.
|
|
138
147
|
5. Build or replay request JSONL rows.
|
|
139
148
|
6. Persist request artifacts before upload.
|
|
140
|
-
7. Submit one or more
|
|
149
|
+
7. Submit one or more provider batch files.
|
|
141
150
|
8. Poll active batches.
|
|
142
151
|
9. Download output/error files.
|
|
143
152
|
10. Parse terminal item results back into the state store.
|
|
@@ -201,7 +210,7 @@ sequenceDiagram
|
|
|
201
210
|
BatchRunner->>Provider: upload_input_file(local_path)
|
|
202
211
|
Provider-->>BatchRunner: remote_file_id
|
|
203
212
|
BatchRunner->>Provider: create_batch(remote_file_id)
|
|
204
|
-
Provider-->>BatchRunner: BatchRemoteRecord (status=validating)
|
|
213
|
+
Provider-->>BatchRunner: BatchRemoteRecord (status=submitted/validating)
|
|
205
214
|
BatchRunner->>StateStore: register_batch()
|
|
206
215
|
BatchRunner->>StateStore: mark_items_submitted()
|
|
207
216
|
end
|
|
@@ -423,7 +432,7 @@ That split gives `batchor`:
|
|
|
423
432
|
## Current invariants
|
|
424
433
|
|
|
425
434
|
1. Public execution is run-oriented: `start()`, `get_run()`, `run_and_wait()`.
|
|
426
|
-
2. OpenAI Batch
|
|
435
|
+
2. OpenAI Batch and text-only Gemini Batch are built-in Python and CLI providers; OpenAI remains the CLI default.
|
|
427
436
|
3. SQLite is the default durable backend.
|
|
428
437
|
4. Postgres is an opt-in durable backend for shared control-plane state.
|
|
429
438
|
5. Structured outputs require a module-level Pydantic v2 model for rehydration.
|
|
@@ -456,7 +465,7 @@ The code is shaped for future providers and backends, but within explicit bounda
|
|
|
456
465
|
|
|
457
466
|
## Current gaps
|
|
458
467
|
|
|
459
|
-
-
|
|
468
|
+
- Gemini request construction is text-only
|
|
460
469
|
- the only built-in artifact backend is local filesystem storage
|
|
461
470
|
- arbitrary non-checkpointable iterables do not support mid-ingest crash recovery
|
|
462
471
|
- the CLI does not expose the full Python API surface
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Gemini Batching
|
|
2
|
+
|
|
3
|
+
This document describes the Gemini-specific behavior inside `batchor`.
|
|
4
|
+
|
|
5
|
+
Status: implemented for text-only Python API and CLI jobs through both the Gemini Developer API and Vertex AI. Multimodal request construction remains out of scope.
|
|
6
|
+
|
|
7
|
+
## API split
|
|
8
|
+
|
|
9
|
+
The two Google backends do not expose the same batch transport:
|
|
10
|
+
|
|
11
|
+
| Backend | Input | Output | Authentication |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| Gemini Developer API | inline requests below 20 MB; Files API JSONL for larger batches | inline responses or a Files API JSONL file | API key |
|
|
14
|
+
| Vertex AI | Cloud Storage JSONL (BigQuery is supported by Google but not by batchor) | Cloud Storage JSONL | Application Default Credentials |
|
|
15
|
+
|
|
16
|
+
`GeminiProviderConfig.input_mode="auto"` follows that table. `inline`, `file`, and `gcs` are explicit overrides, and incompatible backend/mode combinations fail locally.
|
|
17
|
+
|
|
18
|
+
Vertex selection is explicit through `vertexai=True` or ambient through `GOOGLE_GENAI_USE_VERTEXAI=true`. Project and location resolve from config first, then `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`. Vertex also requires `gcs_uri="gs://bucket/prefix"` for request and output staging.
|
|
19
|
+
|
|
20
|
+
## Request construction and correlation
|
|
21
|
+
|
|
22
|
+
Developer file requests use the documented JSONL shape:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{"key":"row1:a1","request":{"contents":[{"role":"user","parts":[{"text":"Summarize this text"}]}]}}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Inline mode converts those durable request artifacts to SDK `InlinedRequest` objects and carries the key in request metadata. Returned inline metadata is converted back to the same JSONL-style record before the generic runtime consumes it.
|
|
29
|
+
|
|
30
|
+
Vertex output returns the original `request`, a `response`, and a string `status`; it does not return the Developer API `key`. For Vertex, batchor hashes the internal attempt identifier into a GCP-safe `request.labels.batchor_key` value. The original request and label round-trip through GCS output, so the runtime can correlate each row without relying on output ordering.
|
|
31
|
+
|
|
32
|
+
`PromptParts.prompt` becomes a user text part. `PromptParts.system_prompt` becomes `system_instruction`. `GeminiProviderConfig.generation_config` is copied into every request.
|
|
33
|
+
|
|
34
|
+
Structured jobs additionally set:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"generation_config": {
|
|
39
|
+
"response_mime_type": "application/json",
|
|
40
|
+
"response_json_schema": {"type": "object"}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The schema comes from the same `structured_output=` Pydantic model used by OpenAI jobs and returned JSON is validated with that model.
|
|
46
|
+
|
|
47
|
+
## Lifecycle
|
|
48
|
+
|
|
49
|
+
Developer API auto mode:
|
|
50
|
+
|
|
51
|
+
1. use inline requests when the staged JSONL is under 20 MB, otherwise upload it through the Files API
|
|
52
|
+
2. create and poll the batch with `client.batches`
|
|
53
|
+
3. normalize inline responses or download the result file
|
|
54
|
+
|
|
55
|
+
Vertex AI:
|
|
56
|
+
|
|
57
|
+
1. upload the durable request JSONL under `gcs_uri/inputs/`
|
|
58
|
+
2. create a batch with that `gs://` source and a unique `gcs_uri/outputs/` destination
|
|
59
|
+
3. poll with `client.batches.get`
|
|
60
|
+
4. read every output object from the returned `output_info.gcs_output_directory`
|
|
61
|
+
|
|
62
|
+
Terminal states normalize to batchor's generic `completed`, `failed`, `cancelled`, and `expired` states. Vertex rows with a non-empty `status` become item errors; rows with an object `response` and empty status become successes.
|
|
63
|
+
|
|
64
|
+
## Durable replay
|
|
65
|
+
|
|
66
|
+
Provider-specific request rows remain in batchor's local artifact store. Retry or fresh-process resume replaces only the provider correlation identifier. Developer rows update `key`; Vertex rows update the hashed correlation label. The prompt and generation request otherwise remain unchanged.
|
|
67
|
+
|
|
68
|
+
GCS input/output objects are remote provider payloads, separate from batchor's durable local artifact store. A failed create deletes its just-uploaded input on a best-effort basis. Successfully submitted Vertex payloads follow the bucket's retention/lifecycle policy.
|
|
69
|
+
|
|
70
|
+
## Limits verified July 10, 2026
|
|
71
|
+
|
|
72
|
+
Current official Vertex behavior:
|
|
73
|
+
|
|
74
|
+
- no predefined Gemini batch inference quota or enqueue-token limit; work can queue against a shared resource pool
|
|
75
|
+
- at most 200,000 requests per job
|
|
76
|
+
- at most 1 GB for a Cloud Storage input file
|
|
77
|
+
- jobs can queue for up to 72 hours and generally process within 24 hours after starting
|
|
78
|
+
|
|
79
|
+
Batchor therefore does not apply OpenAI enqueue-token budgeting to Gemini. Generic `ChunkPolicy` defaults remain more conservative at 50,000 requests and 150 MiB, and callers may raise them within Google's limits.
|
|
80
|
+
|
|
81
|
+
Developer API limits differ: inline batch creation must stay below 20 MB, input files may be up to 2 GB, concurrent batches are currently limited to 100, and model/tier-specific enqueued-token limits still apply. Batchor automatically switches Developer auto mode from inline to Files API by request size; it does not yet model Developer tier-specific token quotas.
|
|
82
|
+
|
|
83
|
+
## Current limits
|
|
84
|
+
|
|
85
|
+
- the CLI exposes the common text-job configuration; advanced source, storage, and lifecycle composition remains Python-first.
|
|
86
|
+
- text request construction only.
|
|
87
|
+
- Vertex BigQuery input/output is not implemented.
|
|
88
|
+
- provider-side remote cancellation is not implemented.
|
|
89
|
+
|
|
90
|
+
## References
|
|
91
|
+
|
|
92
|
+
- [Vertex AI Gemini batch inference](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/batch-prediction-gemini)
|
|
93
|
+
- [Vertex AI batch inference from Cloud Storage](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/batch-prediction-from-cloud-storage)
|
|
94
|
+
- [Vertex AI quotas and limits](https://cloud.google.com/vertex-ai/docs/quotas)
|
|
95
|
+
- [Gemini Developer API Batch API](https://ai.google.dev/gemini-api/docs/batch-api)
|
|
96
|
+
- [Google Gen AI Python SDK batch documentation](https://googleapis.github.io/python-genai/#batch-prediction)
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
This document describes the OpenAI-specific behavior inside `batchor`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
OpenAI remains the default and most feature-complete provider path. Gemini has its own design note in [`GEMINI_BATCHING.md`](GEMINI_BATCHING.md), while this page focuses only on OpenAI Batch semantics.
|
|
6
6
|
|
|
7
7
|
## Current behavior
|
|
8
8
|
|
|
9
|
+
The Python API and CLI both support OpenAI. The CLI is OpenAI-only today.
|
|
10
|
+
|
|
9
11
|
## Request construction
|
|
10
12
|
|
|
11
13
|
The built-in provider converts each prepared item into one OpenAI Batch JSONL request row.
|
|
@@ -187,7 +189,6 @@ Provider-side remote batch cancellation is not implemented in v1.
|
|
|
187
189
|
|
|
188
190
|
## Current limits
|
|
189
191
|
|
|
190
|
-
- only the built-in OpenAI Batch provider path is implemented
|
|
191
192
|
- the docs do not yet provide a full capability matrix across all OpenAI endpoint features
|
|
192
193
|
- artifact storage is still local-filesystem-only
|
|
193
194
|
|
|
@@ -8,11 +8,12 @@ This file tracks important work that should be explicit in the extracted reposit
|
|
|
8
8
|
- extend resumable ingestion beyond the built-in CSV/JSONL sources
|
|
9
9
|
- add automated retention windows on top of the explicit export/prune lifecycle
|
|
10
10
|
- add more input adapters beyond CSV and JSONL
|
|
11
|
+
- expose non-OpenAI providers through CLI workflows once provider-specific auth and flags are stable
|
|
11
12
|
- add CLI structured-output workflows if the importability story can stay durable and predictable
|
|
12
13
|
|
|
13
14
|
## Longer-Term Ideas
|
|
14
15
|
|
|
15
|
-
- additional
|
|
16
|
+
- additional provider coverage beyond OpenAI and text-only Gemini
|
|
16
17
|
- artifact store abstraction
|
|
17
18
|
- partial-result streaming APIs
|
|
18
19
|
- richer CLI or operator workflow beyond the current file-backed text-job surface
|
|
@@ -74,7 +74,7 @@ Postgres is also implemented for shared control-plane state when callers explici
|
|
|
74
74
|
|
|
75
75
|
In-memory storage exists for tests and short-lived local runs.
|
|
76
76
|
|
|
77
|
-
The SQLite/OpenAI path is covered by the default smoke test. Postgres storage compatibility is validated in a dedicated storage-contract CI job and requires `BATCHOR_TEST_POSTGRES_DSN` for equivalent local coverage.
|
|
77
|
+
The SQLite/OpenAI path is covered by the default smoke test. Gemini provider wiring is covered with fake-client integration tests, and an opt-in live Vertex/GCS smoke test covers the real control and payload planes. Postgres storage compatibility is validated in a dedicated storage-contract CI job and requires `BATCHOR_TEST_POSTGRES_DSN` for equivalent local coverage.
|
|
78
78
|
|
|
79
79
|
## Storage responsibilities
|
|
80
80
|
|
|
@@ -179,7 +179,7 @@ Successful rehydration depends on:
|
|
|
179
179
|
Fresh-process resume also requeues any `queued_local` items back to `pending` before submission resumes.
|
|
180
180
|
When `start(job, run_id=...)` resumes a run with active provider batches, it first performs a poll-only reconciliation pass. Terminal provider batches are consumed, failed batches update retry backoff, and any active backoff prevents new source materialization or submission until the backoff expires.
|
|
181
181
|
|
|
182
|
-
Resume compatibility intentionally ignores non-persisted secret fields such as provider API keys.
|
|
182
|
+
Resume compatibility intentionally ignores non-persisted secret fields such as provider API keys. Rehydrated OpenAI runs need `OPENAI_API_KEY` when no explicit in-memory config is supplied. Gemini Developer API runs need `GEMINI_API_KEY`; Vertex runs need Application Default Credentials plus the persisted or ambient project, location, and GCS prefix configuration.
|
|
183
183
|
|
|
184
184
|
For deterministic-source resume, the caller must also reuse the same `run_id` and provide the same source identity/fingerprint.
|
|
185
185
|
For composite sources, that includes the same ordered child identities; changing the child order or swapping one file changes the logical source identity.
|
|
@@ -194,6 +194,7 @@ Built-in deterministic sources currently include:
|
|
|
194
194
|
For checkpointed ingestion, durable stores append materialized item chunks and advance the ingest checkpoint in one storage operation. Parquet and composite sources can also identify an end-of-source checkpoint from cheap metadata, so a resume after all rows were materialized but before the final completion flag was written can mark ingestion complete without re-reading the source data or re-rendering prompts.
|
|
195
195
|
|
|
196
196
|
Once an item has a durable request artifact pointer, `batchor` prunes large inline request-building fields from the control-plane store and relies on the artifact for later retries.
|
|
197
|
+
Provider-specific request rows are preserved in those artifacts. During replay, OpenAI updates `custom_id`; Gemini updates either the Developer API `key` or the Vertex correlation label. All map back to the same internal durable attempt identifier.
|
|
197
198
|
|
|
198
199
|
## Artifact lifecycle
|
|
199
200
|
|