Skip to main content

bead

CI Python 3.14 License: MIT Documentation

A Python framework for constructing, deploying, and analyzing large-scale linguistic judgment experiments with active learning.

Overview

bead implements a complete pipeline for linguistic research: from lexical resource construction through experimental deployment to model training with active learning. It handles the combinatorial explosion of linguistic stimuli while maintaining full provenance tracking.

The name refers to the way sealant is applied while glazing a window, a play on the glazing package for accessing VerbNet, PropBank, and FrameNet.

Installation

# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install bead
uv pip install bead

# With optional dependencies
uv pip install bead[api]       # OpenAI, Anthropic, Google APIs
uv pip install bead[training]  # PyTorch Lightning, TensorBoard

Development

git clone https://github.com/FACTSlab/bead.git
cd bead
uv sync --all-extras
uv run pytest tests/

Always use uv run to execute commands.

Integration tests that exercise the layers publish path against a real ATProto PDS are deselected by default. With docker running, opt in with uv run pytest --run-integration; the test stands up a throwaway bluesky PDS container and skips cleanly when docker is unavailable.

Quick Start

from bead.items.forced_choice import create_forced_choice_item
from bead.lists.partitioner import ListPartitioner
from bead.protocol import (
    AnnotationProtocol,
    QuestionFamily,
    ResponseSpace,
    ScaleType,
    SemanticAnchor,
)
from bead.protocol.items import family_to_item_template

# 1. Declare the question being asked
anchor = SemanticAnchor(
    name="acceptability",
    target_property="acceptability",
    canonical_prompt="Which sentence sounds more natural?",
    response_space=ResponseSpace(
        options=("first", "second"),
        is_ordered=False,
        scale_type=ScaleType.FORCED_CHOICE,
    ),
    required_keywords=frozenset({"natural"}),
)
protocol = AnnotationProtocol(families=[QuestionFamily(anchor=anchor)])

# 2. Build the deployable item template from the protocol
template = family_to_item_template(
    protocol.family_by_name("acceptability"),
    judgment_type="acceptability",
)

# 3. Build forced-choice items (one per minimal pair)
items = [
    create_forced_choice_item(
        "The cat sat on the mat.",
        "The cats sat on the mat.",
        item_template_id=template.id,
        metadata={"anchor": "acceptability", "contrast": "number"},
    ),
    # ... more pairs
]

# 4. Partition into experiment lists
partitioner = ListPartitioner(random_seed=42)
lists = partitioner.partition(
    [item.id for item in items],
    n_lists=4,
    metadata={item.id: dict(item.item_metadata) for item in items},
)

Or, drive the same pipeline from a single declarative config:

from bead.config import load_config

# Composes profile defaults → defaults: [...] entries → primary YAML
# → extras → CLI-style overrides → resolves ${...} interpolation
config = load_config(
    "config.yaml",
    overrides=["paths.data_dir=/tmp/data"],
)
protocol = config.protocol.build()

Pipeline Stages

Stage Purpose Output
Resources Define lexical items and templates lexicons/*.jsonl, templates/*.jsonl
Templates Fill templates with lexical items filled_templates/*.jsonl
Items Construct experimental items items/*.jsonl
Lists Partition into balanced lists lists/*.jsonl
Deployment Generate jsPsych experiments deployment/*.jzip
Training Active learning until convergence Model checkpoints

Key Features

  • Stand-off annotation: UUID-based references for full provenance tracking
  • 8 task types: forced-choice, ordinal scale, binary, categorical, multi-select, magnitude, free text, cloze
  • Constraint satisfaction: batch and list-level constraints for balanced designs
  • Model integration: HuggingFace, OpenAI, Anthropic with caching
  • Active learning: uncertainty sampling with convergence detection
  • Annotation protocols: type-theoretic stack of SemanticAnchor (the question type), ProtocolContext (the dependent index), RealizationStrategy (template / contextual / LM phrasings), and DriftGuard (the type-checker over realized prompts), composed into conditional AnnotationProtocols
  • Config composer (bead.config.compose): the full OmegaConf interpolation grammar — ${section.field}, ${.x} / ${..y} relative references, ${a.b[0]} / ${a.b.0} list indexing, ${a.${b}} nesting, \${literal} escape, built-in resolvers (oc.env, oc.select, oc.decode, oc.deprecated, oc.create, oc.dict.keys, oc.dict.values); defaults: [...] composition; strict-merge against didactic schemas; YAML and TOML
  • jsPsych 8.x: Material Design UI with JATOS deployment

CLI

bead init my-experiment            # Create project structure
bead templates fill                # Fill templates
bead items construct               # Construct items
bead lists partition               # Create experiment lists
bead deploy                        # Generate jsPsych experiment
bead training run                  # Train with active learning
bead protocol validate             # Validate the protocol section of a config
bead protocol realize              # Materialize realizations for contexts
bead protocol items                # Bridge a protocol to item templates

Every command accepts repeatable --set KEY=VALUE overrides applied through the config composer, so any field of BeadConfig (including nested paths.data_dir, protocol.drift.min_length, etc.) can be overridden from the shell without editing the YAML.

Documentation

Full documentation: bead.readthedocs.io

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

Citation

@software{white2026bead,
  author = {White, Aaron Steven},
  title = {bead: A framework for large-scale linguistic judgment experiments},
  year = {2026},
  url = {https://github.com/FACTSlab/bead},
}

License

MIT License. See LICENSE for details.

Acknowledgments

This project was developed by Aaron Steven White at the University of Rochester with support from the National Science Foundation (NSF-BCS-2237175 CAREER: Logical Form Induction, NSF-BCS-2040831 Computational Modeling of the Internal Structure of Events). It was architected and implemented with the assistance of Claude Code.

Download files

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

Source Distribution

bead-0.8.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

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

bead-0.8.0-py3-none-any.whl (777.5 kB view details)

Uploaded Python 3

File details

Details for the file bead-0.8.0.tar.gz.

File metadata

  • Download URL: bead-0.8.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for bead-0.8.0.tar.gz
Algorithm Hash digest
SHA256 deb7fe7d6d3456cd2fa713b9c2843c7d57e22815db655ed2da0ac1884c3480c2
MD5 090a4bc3c7aa53a4f2d461ab8c5cfca9
BLAKE2b-256 680a9f651c8209c490c90a5bd92ca1a5736124cd10db30bd28b9999088c9139c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bead-0.8.0.tar.gz:

Publisher: publish.yml on FACTSlab/bead

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

File details

Details for the file bead-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: bead-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 777.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for bead-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 af32193dd5bacc73aed145b479ffca8aa6f6e0d64c9423c51d7d365297cf381d
MD5 30ff41c55f237023777660add8f13331
BLAKE2b-256 ccc709c8826f05d34813512e0cf106210b3d20f14f0ac6a9742d21c57eec8fa9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bead-0.8.0-py3-none-any.whl:

Publisher: publish.yml on FACTSlab/bead

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

Release history Release notifications | RSS feed

0.9.0

2 files

This release

0.8.0 This release

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

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