Skip to main content

Domain-agnostic adaptive experimentation framework: experiment → measure → learn → challenge.

Project description

adaptive_iteration

Domain-agnostic adaptive experimentation framework.

A lightweight Python framework that abstracts the experiment → measure → learn → challenge cycle into reusable components. Bring your own domain; the framework handles the rest.


What It Is

adaptive_iteration/
├── core/               # pure Python stdlib, zero domain deps
│   ├── experiment.py   # Experiment / Variant dataclasses + ExperimentState
│   ├── ledger.py       # JSON append-only results ledger
│   ├── analyzer.py     # top/bottom performer detection, variance per dimension
│   ├── hypothesis.py   # HypothesisEngine: ledger + analysis → LLM → Experiment candidates
│   └── config.py       # AdaptiveConfig: JSON config + winner hints
└── adapters/
    ├── base.py         # DomainAdapter ABC (3 methods to implement)
    └── short_video.py  # Example adapter: YouTube + Instagram (simulated data)

Installation

# with uv (recommended)
uv add adaptive-iteration

# with pip
pip install adaptive-iteration

Requires Python 3.10+. The only runtime dependency is openai (used only in HypothesisEngine; the rest of core/ is stdlib-only).


Quick Start

import os
from pathlib import Path
from adaptive_iteration.core.ledger import Ledger
from adaptive_iteration.core.analyzer import Analyzer
from adaptive_iteration.core.hypothesis import HypothesisEngine
from adaptive_iteration.core.config import AdaptiveConfig

# 1. Load / create config
cfg = AdaptiveConfig(Path("data/adaptive_config.json"))
cfg.update({"domain": "my_domain", "primary_metric": "conversion_rate"})

# 2. Open ledger
ledger = Ledger(Path("data/adaptive_ledger.json"))

# 3. Record experiment results
ledger.append(
    domain="my_domain",
    experiment_id="exp001",
    variable="cta_style",
    variant="soft",
    metric_values={"conversion_rate": 4.2, "bounce_rate": 31.0},
    winner=True,
)

# 4. Analyse
analyzer = Analyzer(ledger, primary_metric="conversion_rate")
analysis = analyzer.analyze(domain="my_domain")
print(f"Top performers: {[p['variant'] for p in analysis.top_performers]}")
print(f"Winning patterns: {analysis.winning_patterns}")

# 5. Generate next hypotheses (requires OPENAI_API_KEY)
engine = HypothesisEngine(
    ledger=ledger,
    api_key=os.environ["OPENAI_API_KEY"],
)
candidates = engine.generate(domain="my_domain", analysis=analysis)
for exp in candidates:
    print(f"  [{exp.tier}] {exp.variable}: {exp.description}")

Integrating a New Domain

Subclass DomainAdapter and implement three methods:

from adaptive_iteration.adapters.base import DomainAdapter

class MyDomainAdapter(DomainAdapter):

    def collect_metrics(self, item_ids: list[str]) -> list[dict]:
        """Pull raw metrics from your external system for each item_id."""
        results = []
        for item_id in item_ids:
            raw = my_api.get_metrics(item_id)
            results.append({"id": item_id, **raw})
        return results

    def get_signals(self, metrics: list[dict]) -> dict:
        """Normalise to framework signals."""
        primary = sum(m["conversion_rate"] for m in metrics) / len(metrics)
        return {
            "primary_metric": primary,
            "secondary_metrics": {
                "bounce_rate": sum(m["bounce_rate"] for m in metrics) / len(metrics),
            },
        }

    def format_context(self, top_items, bottom_items) -> str:
        lines = ["Top performers:"]
        for item in top_items:
            lines.append(f"  [{item['id']}] conversion_rate={item.get('conversion_rate')}")
        lines.append("Bottom performers:")
        for item in bottom_items:
            lines.append(f"  [{item['id']}] conversion_rate={item.get('conversion_rate')}")
        return "\n".join(lines)

See adapters/short_video.py for a complete reference implementation.


Experiment Modes

Mode When to use Description
interleaved Tier 2 Rotate variants across different items; maximises volume
paired Tier 1 Generate two variants for the same item; cleaner causal inference

Tier 1 experiments (high-impact variables) should use paired mode to eliminate confounding factors introduced by item-level differences.


Import Verification

python3 -c "from adaptive_iteration.core.experiment import Experiment; print('ok')"

Design Principles

  1. core/ has zero external deps — pure Python stdlib only (openai in hypothesis.py is lazy-imported and optional until you call HypothesisEngine).
  2. DomainAdapter is the only layer that touches external systems.
  3. Ledger is the single source of truth — append-only JSON, no database required.
  4. HypothesisEngine uses structured JSON output prompting so parsing is deterministic.

Project details


Download files

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

Source Distribution

adaptive_iteration-0.1.0.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

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

adaptive_iteration-0.1.0-py3-none-any.whl (16.7 kB view details)

Uploaded Python 3

File details

Details for the file adaptive_iteration-0.1.0.tar.gz.

File metadata

  • Download URL: adaptive_iteration-0.1.0.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for adaptive_iteration-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5ba960fe90d517b50e659e3b90c9a7ba7bf6aa962dcc8fa266588ee71a7b1655
MD5 e6455ff39565c021962013d95db6d7e4
BLAKE2b-256 8f05e788ff806d031fda1c31983fb7ea9204fb1e673dad6e6393895e101f48a1

See more details on using hashes here.

File details

Details for the file adaptive_iteration-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: adaptive_iteration-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for adaptive_iteration-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8dda3731cdffcfce61dffb9756424e83926dba2af1cb1a60cf719e6b8855a5a4
MD5 a62a2b6ab117841d3462a6340a8db711
BLAKE2b-256 1cf9d6ce4d04d22b0638cd7ea33af8fb441c1558cf83aa5117ce0371b7a70b68

See more details on using hashes here.

Supported by

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