Skip to main content

Batch processing for AI models with cost tracking and state persistence

Project description

Batchata

Batchata AI Batch Build StatusBatchata AI Batch PyPI version

Unified Python API for AI Batch requests with cost tracking, Pydantic responses, citation mapping and parallel execution.

image

This library is currently in alpha - so there will be breaking changes

Why AI-batching?

AI providers offer batch APIs that process requests asynchronously at 50% reduced cost compared to real-time APIs. This is ideal for workloads like document processing, data analysis, and content generation where immediate responses aren't required. However, managing batch jobs across providers, tracking costs, handling failures, and mapping citations back to source documents quickly becomes complex - that's where Batchata comes in.

Batchata Features

  • Native batch processing (50% cost savings via provider APIs)
  • Set max_cost_usd limits for batch requests
  • Time limit control with .add_time_limit(seconds=, minutes=, hours=)
  • State persistence in case of network interruption
  • Structured output .json format with Pydantic models
  • Citation support and field mapping (Anthropic only)
  • Multiple provider support (Anthropic, OpenAI)

Installation

pip

pip install batchata

uv

uv add batchata

Quick Start

from batchata import Batch

# Simple batch processing
batch = Batch(results_dir="./output")
    .set_default_params(model="claude-sonnet-4-20250514")  # or "gpt-4.1-2025-04-14"
    .add_cost_limit(usd=5.0)

for file in files:
    batch.add_job(file=file, prompt="Summarize")

run = batch.run()

results = run.results()  # {"completed": [JobResult], "failed": [JobResult], "cancelled": [JobResult]}

Complete Example

from batchata import Batch
from pydantic import BaseModel
from dotenv import load_dotenv

load_dotenv()  # Load API keys from .env

# Define structured output
class InvoiceAnalysis(BaseModel):
    invoice_number: str
    total_amount: float
    vendor: str
    payment_status: str

# Create batch configuration
batch = Batch(
        results_dir="./invoice_results",
        max_parallel_batches=1,
        items_per_batch=3
    )
    .set_state(file="./invoice_state.json", reuse_state=False)
    .set_default_params(model="claude-sonnet-4-20250514", temperature=0.0)
    .add_cost_limit(usd=5.0)
    .add_time_limit(minutes=10)  # Time limit of 10 minutes
    .set_verbosity("warn") 

# Add jobs with structured output and citations
invoice_files = ["path/to/invoice1.pdf", "path/to/invoice2.pdf", "path/to/invoice3.pdf"]
for invoice_file in invoice_files:
    batch.add_job(
        file=invoice_file,
        prompt="Extract the invoice number, total amount, vendor name, and payment status.",
        response_model=InvoiceAnalysis,
        enable_citations=True
    )

# Execute with rich progress display
print("Starting batch processing...")
run = batch.run(print_status=True)

# Or use custom progress callback
run = batch.run(
    on_progress=lambda s, t, b: print(
        f"\rProgress: {s['completed']}/{s['total']} jobs | "
        f"Batches: {s['batches_completed']}/{s['batches_total']} | "
        f"Cost: ${s['cost_usd']:.3f}/{s['cost_limit_usd']} | "
        f"Time: {t:.1f}s", 
        end=""
    )
)

# Get results
results = run.results()

# Process successful results
for result in results["completed"]:
    analysis = result.parsed_response
    citations = result.citation_mappings
    print(f"\nInvoice: {analysis.invoice_number} (page: {citations.get("invoice_number").page})")
    print(f"  Vendor: {analysis.vendor} (page: {citations.get("vendor").page})")
    print(f"  Total: ${analysis.total_amount:.2f} (page: {citations.get("total_amount").page})")
    print(f"  Status: {analysis.payment_status} (page: {citations.get("payment_status").page})")

# Process failed/cancelled results  
for result in results["failed"]:
    print(f"\nJob {result.job_id} failed: {result.error}")

for result in results["cancelled"]:
    print(f"\nJob {result.job_id} was cancelled: {result.error}")

Interactive Progress Display

Batchata provides an interactive real-time progress display when using print_status=True:

run = batch.run(print_status=True)
image

The interactive display shows:

  • Job Progress: Completed/total jobs with progress bar
  • Batch Status: Provider batch completion status
  • Real-time Cost: Current spend vs limit (if set)
  • Elapsed Time: Time since batch started
  • Live Updates: Refreshes automatically as jobs complete

File Structure

./results/
├── job-abc123.json
├── job-def456.json
├── job-ghi789.json
└── raw_files/
    └── responses/
        ├── job-abc123_raw.json
        ├── job-def456_raw.json
        └── job-ghi789_raw.json

./batch_state.json  # Batch state

Supported Providers

Feature Anthropic OpenAI
Models All Claude models All GPT models
Batch Discount 50% 50%
Polling Interval 1s 5s
Citations
Structured Output
File Types PDF, TXT, DOCX, Images PDF, Images

Configuration

Set your API keys as environment variables:

export ANTHROPIC_API_KEY="your-key"
export OPENAI_API_KEY="your-key"

You can also use a .env file in your project root (requires python-dotenv):

from dotenv import load_dotenv
load_dotenv()

from batchata import Batch
# Your API keys will now be loaded from .env

Limitations

  • Field/citation mapping is heuristic, which means it isn't perfect.
  • Citation mapping only works with flat Pydantic models (no nested BaseModel fields).
  • No Gemini or Groq support yet.
  • Cost tracking is not precise as the actual usage is only known after the batch is complete, try setting items_per_batch to a lower value for more accurate cost tracking.

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

batchata-0.3.8.tar.gz (242.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

batchata-0.3.8-py3-none-any.whl (58.6 kB view details)

Uploaded Python 3

File details

Details for the file batchata-0.3.8.tar.gz.

File metadata

  • Download URL: batchata-0.3.8.tar.gz
  • Upload date:
  • Size: 242.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for batchata-0.3.8.tar.gz
Algorithm Hash digest
SHA256 654396b1a2737a7839fa3312f8af6b8c63a2cfab1d25a55528db1a418ade5aba
MD5 282cc2b99e5a5eb4e3c915259215d891
BLAKE2b-256 83527afd9293c11d33d8a739745da6119ac83c5078080948f37ea5cf50031f09

See more details on using hashes here.

Provenance

The following attestation bundles were made for batchata-0.3.8.tar.gz:

Publisher: publish.yml on agamm/batchata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file batchata-0.3.8-py3-none-any.whl.

File metadata

  • Download URL: batchata-0.3.8-py3-none-any.whl
  • Upload date:
  • Size: 58.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for batchata-0.3.8-py3-none-any.whl
Algorithm Hash digest
SHA256 fb3a37c2c46b76fd8b95a41a0293cc586692b7f0da06bd81e6069cf58e64047e
MD5 4dd619a30d9ee1b33fb5b5e095aaec59
BLAKE2b-256 403997f4d36aeaa41f372e461521b0b408ad8ae7c8cbf7b415345557f8b16d81

See more details on using hashes here.

Provenance

The following attestation bundles were made for batchata-0.3.8-py3-none-any.whl:

Publisher: publish.yml on agamm/batchata

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page