Contributing to async-batch-llm
Thank you for considering contributing to async-batch-llm!
To report a security vulnerability, don't open a public issue; follow the security policy. Maintainer material, including the release process, lives in CONTRIBUTING.md.
Development Setup
1. Clone and Install
git clone https://github.com/geoff-davis/async-batch-llm.git
cd async-batch-llm
# Create virtual environment and install dependencies
uv venv
uv sync --all-extras
2. Install Git Hooks
Hooks are managed with prek, a drop-in
replacement for pre-commit (same .pre-commit-config.yaml):
This will automatically run code quality checks before each commit.
Development Workflow
Running Tests
# Run all tests
uv run pytest
# Run specific test file
uv run pytest tests/test_basic.py -v
# Run with coverage
uv run pytest --cov=async_batch_llm --cov-report=html
Code Quality
Always run quality checks before committing:
# Format code (make format)
uv run ruff format src/ tests/
# Lint and auto-fix issues (make lint-fix)
uv run ruff check src/ tests/ --fix
# Verify linting passes (make lint)
uv run ruff check src/ tests/
# Type check
uv run mypy src/async_batch_llm/ --ignore-missing-imports
# Or run all checks at once
make ci
examples/ is excluded from ruff on purpose: example scripts check environment
variables before importing optional dependencies, which ruff reports as E402.
Documentation
Build and preview documentation:
# Install docs dependencies
uv sync --extra docs
# Serve docs locally
uv run mkdocs serve
# Build docs
uv run mkdocs build
Then visit http://localhost:8000
Markdown Linting
Requires Node 20+; run npm ci once to install the pinned markdownlint-cli2.
Both targets lint every tracked .md file except docs/archive/, the same set as
the prek hook:
Pre-Commit Checklist
Before committing, ensure:
- ✅ All tests pass:
uv run pytest - ✅ Linting passes:
uv run ruff check src/ tests/ - ✅ Type checking passes:
uv run mypy src/async_batch_llm/ - ✅ Markdown is clean:
make markdown-lint
Or run everything at once:
Pull Request Guidelines
- Create a feature branch:
git checkout -b feature/your-feature - Write tests: Add tests for new functionality
- Update docs: Update relevant documentation
- Run quality checks: Ensure all checks pass
- Write clear commit messages: Explain the "why" not just "what"
- Open PR: Provide a clear description of changes
Project Structure
async-batch-llm/
├── src/async_batch_llm/ # Main package
│ ├── base.py # Core data models
│ ├── parallel.py # Main processor
│ ├── streaming.py # process_prompts / process_stream
│ ├── single.py # call / call_result
│ ├── call_pool.py # LLMCallPool
│ ├── factory.py # llm("provider:model")
│ ├── llm_strategies.py # LLMCallStrategy + built-in strategies
│ ├── callable_strategy.py # CallableStrategy for existing async clients
│ ├── models.py # Provider model classes
│ ├── artifacts.py # JsonlArtifactStore, ArtifactIdentity, ResumePolicy
│ ├── sqlite_artifacts.py # SqliteArtifactStore
│ ├── serialization.py # Result JSON/JSONL serialization
│ ├── classifiers/ # Provider error classifiers
│ ├── core/ # Config and protocols
│ ├── observers/ # Observer implementations
│ ├── middleware/ # Middleware protocol
│ ├── _internal/ # Private orchestration collaborators
│ └── testing/ # Testing utilities
├── tests/ # Test suite
├── examples/ # Example scripts
├── docs/ # Documentation
└── CLAUDE.md # AI assistant context
Adding New Strategies
To add a new LLM provider strategy:
- Add the strategy to
src/async_batch_llm/llm_strategies.py(or your own module) - Subclass the
LLMCallStrategyabstract base class - Add tests in
tests/ - Add example in
examples/ - Update documentation in
docs/examples/custom-strategies.md
Example:
from async_batch_llm import LLMCallStrategy
class MyProviderStrategy(LLMCallStrategy[str]):
async def execute(self, prompt: str, attempt: int, timeout: float, state=None):
# Your implementation
return output, tokens, None
Questions?
- Open an issue
- Start a discussion
License
By contributing, you agree that your contributions will be licensed under the MIT License.