Skip to content

Basic Usage Examples

The first two examples use the high-level process_prompts() API, which covers most batches. The rest drive ParallelBatchProcessor directly for full control over queueing and lifecycle.

Simple Batch Processing

Process multiple prompts in parallel:

import asyncio
from async_batch_llm import llm, process_prompts

async def main():
    prompts = ["What is Python?", "What is async/await?", "What is asyncio?"]
    batch = await process_prompts(llm("openai:gpt-6-luna"), prompts, concurrency=5)

    for result in batch.results:  # completion order
        if result.success:
            print(f"{result.item_id}: {result.output}")
        else:
            print(f"{result.item_id}: Failed - {result.error}")

asyncio.run(main())

Context Passing

Pass (item_id, prompt, context) triples to carry application data into each result:

from dataclasses import dataclass

from async_batch_llm import llm, process_prompts

@dataclass
class FileContext:
    filepath: str
    original_content: str

async def process_with_context():
    files = [("file1.py", "content1"), ("file2.py", "content2")]
    batch = await process_prompts(
        llm("openai:gpt-6-luna"),
        [
            (path, f"Summarize: {content}", FileContext(path, content))
            for path, content in files
        ],
    )

    for result in batch.results:
        if result.success and result.context:
            print(f"File: {result.context.filepath}")
            print(f"Summary: {result.output}")

Full control: ParallelBatchProcessor

The remaining examples build work items and drive the processor yourself. They use a PydanticAI agent (pip install 'async-batch-llm[pydantic-ai,gemini]'). GoogleModel reads GOOGLE_API_KEY when it is constructed. Pass a model object, as here, rather than a bare model name: pydantic-ai 2.x rejects bare names, and the provider prefixes differ between the 1.x and 2.x lines.

import asyncio
from async_batch_llm import (
    ParallelBatchProcessor,
    LLMWorkItem,
    ProcessorConfig,
    PydanticAIStrategy,
)
from pydantic_ai import Agent
from pydantic_ai.models.google import GoogleModel

async def main():
    agent = Agent(GoogleModel("gemini-3.5-flash"), output_type=str)
    strategy = PydanticAIStrategy(agent=agent)

    config = ProcessorConfig(concurrency=5)

    async with ParallelBatchProcessor(config=config) as processor:
        prompts = [
            "What is Python?",
            "What is async/await?",
            "What is asyncio?"
        ]

        for i, prompt in enumerate(prompts):
            await processor.add_work(
                LLMWorkItem(
                    item_id=f"item_{i}",
                    strategy=strategy,
                    prompt=prompt
                )
            )

        result = await processor.process_all()

        for work_result in result.results:
            if work_result.success:
                print(f"{work_result.item_id}: {work_result.output}")
            else:
                print(f"{work_result.item_id}: Failed - {work_result.error}")

asyncio.run(main())

Structured Output

Use Pydantic models for validated output:

from pydantic import BaseModel

class CodeReview(BaseModel):
    issues: list[str]
    suggestions: list[str]
    rating: int

async def review_code():
    agent = Agent(GoogleModel("gemini-3.5-flash"), output_type=CodeReview)
    strategy = PydanticAIStrategy(agent=agent)

    config = ProcessorConfig(concurrency=3)

    async with ParallelBatchProcessor(config=config) as processor:
        code_snippets = ["def foo(): pass", "def bar(): return 42"]

        for snippet in code_snippets:
            await processor.add_work(
                LLMWorkItem(
                    item_id=snippet[:20],
                    strategy=strategy,
                    prompt=f"Review this code:\n{snippet}"
                )
            )

        result = await processor.process_all()

        for work_result in result.results:
            if work_result.success:
                review = work_result.output
                print(f"Rating: {review.rating}/10")
                print(f"Issues: {review.issues}")

Post-Processing

Use post-processors to handle results as they complete:

async def save_result(result):
    """Called for each completed work item."""
    if result.success:
        # Save to database, file, etc.
        await save_to_db(result.item_id, result.output)
        print(f"Saved {result.item_id}")

async def process_with_post_processor():
    agent = Agent(GoogleModel("gemini-3.5-flash"), output_type=str)
    strategy = PydanticAIStrategy(agent=agent)

    config = ProcessorConfig(concurrency=5)

    async with ParallelBatchProcessor(
        config=config,
        post_processor=save_result  # Called for each result
    ) as processor:
        # Add work items...
        result = await processor.process_all()

Metrics Collection

Track metrics using observers:

from async_batch_llm.observers import MetricsObserver

async def process_with_metrics():
    metrics = MetricsObserver()

    agent = Agent(GoogleModel("gemini-3.5-flash"), output_type=str)
    strategy = PydanticAIStrategy(agent=agent)

    config = ProcessorConfig(concurrency=5)

    async with ParallelBatchProcessor(
        config=config,
        observers=[metrics]
    ) as processor:
        # Add work items...
        result = await processor.process_all()

        # Get collected metrics
        collected_metrics = await metrics.get_metrics()
        print(f"Items processed: {collected_metrics['items_processed']}")
        print(f"Succeeded: {collected_metrics['items_succeeded']}")
        print(f"Failed: {collected_metrics['items_failed']}")