Thank you for your interest in contributing! This guide covers everything you need to get started.
# Clone the repo
git clone https://github.com/marmutapp/needlehaystack.git
cd haystackbench
# Create a virtual environment
python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
# Install in editable mode with dev dependencies
pip install -e ".[all,dev]"
# Verify installation
haystackbench --version# Run all tests
pytest
# Run with coverage report
pytest --cov=haystackbench --cov-report=html
# Run a specific test file
pytest tests/unit/test_needle.py -v
# Run tests without slow integration tests
pytest tests/unit/ -vWe use:
- ruff for linting:
ruff check haystackbench/ - black for formatting:
black haystackbench/ - mypy for type checking:
mypy haystackbench/
All three must pass before a PR is merged.
# Run all checks at once
ruff check haystackbench/ && black --check haystackbench/ && mypy haystackbench/
# Auto-fix what's possible
ruff check --fix haystackbench/ && black haystackbench/- Create
haystackbench/providers/myprovider.py - Subclass
BaseProviderand implement all 3 abstract methods - Register it in
haystackbench/providers/__init__.py - Add model info to the provider's
list_models()return - Update the cost table in
haystackbench/core/runner.py - Write tests in
tests/unit/test_providers.py - Add the provider to the README table
- Add the optional dependency to
pyproject.toml
# haystackbench/providers/myprovider.py
from haystackbench.providers.base import BaseProvider, ModelInfo, ProviderResponse
class MyProvider(BaseProvider):
async def complete(self, prompt, model, max_tokens, temperature, system_prompt):
# Call your provider's API
...
return ProviderResponse(content=..., prompt_tokens=..., completion_tokens=..., model=..., provider="myprovider")
def list_models(self):
return [ModelInfo("my-model-v1", "My Model v1", 128000, True, 1.0, 3.0)]
def validate_credentials(self):
try:
self._get_client()
return True
except Exception:
return False- Create
haystackbench/tasks/mytask.py - Subclass
BaseTaskand implement all abstract methods - Register in
haystackbench/tasks/__init__.py - Add to
TaskTypeenum inhaystackbench/config/schema.py - Write tests in
tests/unit/test_tasks.py
- Create or update
haystackbench/haystacks/standard/mysource.py - Implement
fetch(target_tokens, **kwargs) -> str - Register in
HaystackSourceenum in schema.py - Handle caching in
HaystackBuilder._fetch_source()
We use Conventional Commits:
feat(tasks): implement distractor needles task
fix(injector): handle edge case at depth=100%
docs(methodology): clarify ATC scoring formula
test(evaluator): add LLM judge scoring tests
chore(deps): bump anthropic to 0.42.0
refactor(runner): extract cost estimation to helper module
- Fork the repo and create a feature branch:
git checkout -b feat/my-feature - Write your code with type hints and docstrings
- Add tests (coverage must stay ≥ 80%)
- Run
ruff,black, andmypy— all must pass - Open a PR with a clear description of what and why
- A maintainer will review within a few days
- Issues are the preferred way to discuss bugs and features
- For large changes, open an issue first to discuss the approach
- PRs that reduce test coverage will not be merged
This project follows the Contributor Covenant Code of Conduct. Be kind, be constructive, be patient.