{"id":29486431,"url":"https://github.com/agamm/batchata","last_synced_at":"2026-05-15T20:31:42.429Z","repository":{"id":304192579,"uuid":"1018057427","full_name":"agamm/batchata","owner":"agamm","description":"Unified Python API for AI Batch Requests (50% discount on most providers)","archived":false,"fork":false,"pushed_at":"2026-04-28T04:40:54.000Z","size":829,"stargazers_count":82,"open_issues_count":4,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-02T10:37:09.121Z","etag":null,"topics":["ai","ai-batch","batch","claude","llms","openai","python"],"latest_commit_sha":null,"homepage":"https://agamm.github.io/batchata/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agamm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-11T14:33:19.000Z","updated_at":"2026-04-30T18:25:34.000Z","dependencies_parsed_at":"2025-07-11T16:47:47.176Z","dependency_job_id":"350b3dad-da86-4790-93a1-9fc8daf29212","html_url":"https://github.com/agamm/batchata","commit_stats":null,"previous_names":["agamm/batchata"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/agamm/batchata","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agamm%2Fbatchata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agamm%2Fbatchata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agamm%2Fbatchata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agamm%2Fbatchata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agamm","download_url":"https://codeload.github.com/agamm/batchata/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agamm%2Fbatchata/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33078898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T20:25:35.270Z","status":"ssl_error","status_checked_at":"2026-05-15T20:25:34.732Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-batch","batch","claude","llms","openai","python"],"created_at":"2025-07-15T08:00:50.567Z","updated_at":"2026-05-15T20:31:42.417Z","avatar_url":"https://github.com/agamm.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Batchata\n\n\u003cimg alt=\"Batchata AI Batch Build Status\" src=\"https://github.com/agamm/batchata/workflows/Tests/badge.svg\" /\u003e\u003ca href=\"https://pypi.org/project/batchata/\"\u003e\u003cimg alt=\"Batchata AI Batch PyPI version\" src=\"https://badge.fury.io/py/batchata.svg\" /\u003e\u003c/a\u003e\n\nUnified Python API for AI Batch requests with cost tracking, Pydantic responses, citation mapping and parallel execution.\n\n\u003cimg width=\"1328\" height=\"598\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b1b43070-f664-41a2-a85d-e2c589df556c\" /\u003e\n\n*This library is currently in beta - so there will be breaking changes*\n\n## Why AI-batching?\n\nAI providers offer batch APIs that process requests asynchronously at 50% reduced cost compared to real-time APIs. This is ideal for offline or batch processing tasks. 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.\n\n## Batchata Features\n\n- Native batch processing (50% cost savings via provider APIs)\n- Set `max_cost_usd` limits for batch requests\n- Dry run mode for cost estimation and job planning\n- Time limit control with `.add_time_limit(seconds=, minutes=, hours=)`\n- State persistence in case of network interruption\n- Structured output `.json` format with Pydantic models\n- Citation support and field mapping (Anthropic only)\n- Multiple provider support (Anthropic, OpenAI, Google Gemini)\n\n## Installation\n\n### pip\n```bash\npip install batchata\n```\n\n### uv\n```bash\nuv add batchata\n```\n\n## Quick Start\n\n```python\nfrom batchata import Batch\n\n# Simple batch processing\nbatch = Batch(results_dir=\"./output\")\n    .set_default_params(model=\"gpt-5.2-latest\")  # or \"claude-sonnet-4-5-20250929\" or \"gemini-3.0-pro-latest\"\n    .add_cost_limit(usd=5.0)\n\nfor file in files:\n    batch.add_job(file=file, prompt=\"Summarize\")\n\nrun = batch.run()\n\nresults = run.results()  # {\"completed\": [JobResult], \"failed\": [JobResult], \"cancelled\": [JobResult]}\n\n# Or preview costs first with dry run\nrun = batch.run(dry_run=True)  # Shows cost estimates without executing\n```\n\n## Complete Example\n\n```python\nfrom batchata import Batch\nfrom pydantic import BaseModel\nfrom dotenv import load_dotenv\n\nload_dotenv()  # Load API keys from .env\n\n# Define structured output\nclass InvoiceAnalysis(BaseModel):\n    invoice_number: str\n    total_amount: float\n    vendor: str\n    payment_status: str\n\n# Create batch configuration\nbatch = Batch(\n        results_dir=\"./invoice_results\",\n        max_parallel_batches=1,\n        items_per_batch=3\n    )\n    .set_state(file=\"./invoice_state.json\", reuse_state=False)\n    .set_default_params(model=\"gpt-5.2-pro-2025-12-11\", temperature=0.0)\n    .add_cost_limit(usd=5.0)\n    .add_time_limit(minutes=10)  # Time limit of 10 minutes\n    .set_verbosity(\"warn\") \n\n# Add jobs with structured output and citations\ninvoice_files = [\"path/to/invoice1.pdf\", \"path/to/invoice2.pdf\", \"path/to/invoice3.pdf\"]\nfor invoice_file in invoice_files:\n    batch.add_job(\n        file=invoice_file,\n        prompt=\"Extract the invoice number, total amount, vendor name, and payment status.\",\n        response_model=InvoiceAnalysis,\n        enable_citations=True\n    )\n\n# Execute with rich progress display\nprint(\"Starting batch processing...\")\nrun = batch.run(print_status=True)\n\n# Or use custom progress callback\nrun = batch.run(print_status=True)\n\n# Get results\nresults = run.results()\n\n# Process successful results\nfor result in results[\"completed\"]:\n    analysis = result.parsed_response\n    citations = result.citation_mappings\n    print(f\"\\nInvoice: {analysis.invoice_number} (page: {citations.get(\"invoice_number\").page})\")\n    print(f\"  Vendor: {analysis.vendor} (page: {citations.get(\"vendor\").page})\")\n    print(f\"  Total: ${analysis.total_amount:.2f} (page: {citations.get(\"total_amount\").page})\")\n    print(f\"  Status: {analysis.payment_status} (page: {citations.get(\"payment_status\").page})\")\n    \n    # Save each result to JSON file\n    result.save_to_json(f\"./invoice_results/{result.job_id}.json\")\n\n# Process failed/cancelled results  \nfor result in results[\"failed\"]:\n    print(f\"\\nJob {result.job_id} failed: {result.error}\")\n\nfor result in results[\"cancelled\"]:\n    print(f\"\\nJob {result.job_id} was cancelled: {result.error}\")\n```\n\n## Interactive Progress Display\n\nBatchata provides an interactive real-time progress display when using `print_status=True`:\n\n```python\nrun = batch.run(print_status=True)\n```\n\n\u003cimg width=\"2230\" height=\"222\" alt=\"image\" src=\"https://github.com/user-attachments/assets/caf549a6-92a1-4ee0-8ac7-eda2d0f280a7\" /\u003e\n\nThe interactive display shows:\n- **Job Progress**: Completed/total jobs with progress bar\n- **Batch Status**: Provider batch completion status  \n- **Real-time Cost**: Current spend vs limit (if set)\n- **Elapsed Time**: Time since batch started\n- **Live Updates**: Refreshes automatically as jobs complete\n\n## File Structure\n\n```\n./results/\n├── job-abc123.json\n├── job-def456.json\n├── job-ghi789.json\n└── raw_files/\n    └── responses/\n        ├── job-abc123_raw.json\n        ├── job-def456_raw.json\n        └── job-ghi789_raw.json\n\n./batch_state.json  # Batch state\n```\n\n## Supported Providers\n\n| Feature | Anthropic | OpenAI | Google Gemini |\n|---------|-----------|--------|---------------|\n| Models | [All Claude models](https://github.com/agamm/batchata/blob/main/batchata/providers/anthropic/models.py) | [All GPT models](https://github.com/agamm/batchata/blob/main/batchata/providers/openai/models.py) | [Gemini models](https://github.com/agamm/batchata/blob/main/batchata/providers/gemini/models.py) |\n| Batch Discount | 50% | 50% | 50% |\n| Polling Interval | 1s | 5s | 2s |\n| Citations | ✅ | ❌ | ❌ |\n| Structured Output | ✅ | ✅ | ✅ |\n| File Types | PDF, TXT, DOCX, Images | PDF, Images | PDF, TXT, Images |\n\n## Configuration\n\nSet your API keys as environment variables:\n```bash\nexport ANTHROPIC_API_KEY=\"your-key\"\nexport OPENAI_API_KEY=\"your-key\"\nexport GOOGLE_API_KEY=\"your-key\"  # For Gemini models\n```\n\nYou can also use a `.env` file in your project root (requires python-dotenv):\n```python\nfrom dotenv import load_dotenv\nload_dotenv()\n\nfrom batchata import Batch\n# Your API keys will now be loaded from .env\n```\n\n## Limitations\n\n- Field/citation mapping is heuristic, which means it isn't perfect.\n- Citation mapping only works with flat Pydantic models (no nested BaseModel fields).\n- 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.\n\n\n## License\n\nMIT License - see LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagamm%2Fbatchata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagamm%2Fbatchata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagamm%2Fbatchata/lists"}