Conditionals And Retries

Newer CodeBook Lab workflows support conditional annotations and invalid-response retries. These features make Lab closer to CodeBook Studio’s annotation behavior while keeping model outputs auditable.

Conditional Annotations

An annotation can depend on a previous annotation. Lab evaluates the condition row by row and skips inactive fields. Here a checkbox parent (annotation_1) gates a dropdown child (annotation_2): the model is only asked for a stance when the text is marked evaluative.

{
  "annotation_1": {
    "name": "Is evaluative",
    "type": "checkbox",
    "tooltip": "Tick if the text expresses a stance toward the policy."
  },
  "annotation_2": {
    "name": "Stance",
    "type": "dropdown",
    "options": ["Positive", "Negative"],
    "condition": {
      "section_key": "section_1",
      "annotation_key": "annotation_1",
      "value": "Yes"
    }
  }
}

The condition value is normalized the same way as the parent’s response, so for a checkbox parent "Yes", true, and 1 are all equivalent triggers.

If the parent annotation does not satisfy the condition, Lab stores a blank value for the child field and does not send the child prompt to the model. Metrics also ignore rows where the field is not applicable, so skipped conditionals do not count as model errors.

Conditions can point across sections and are evaluated in codebook order. If a condition target is missing or cyclic, Lab falls back to permissive behavior rather than crashing a run.

Response Validation

Lab does not silently invent defaults for invalid model responses.

  • dropdown values must match a configured option after normalization
  • checkbox values must parse to yes/no or 1/0
  • Likert values must parse to a number in the configured scale
  • textbox values must be non-empty
  • span values must parse to a JSON array or {"response": [...]} object with valid offsets

If no valid value can be extracted, Lab records a blank cell after retry attempts are exhausted.

Retry Strategies

run_annotation() supports invalid-response retries:

from codebook_lab import run_annotation

annotation = run_annotation(
    model="gemma3:270m",
    csv_path="texts.csv",
    codebook_path="codebook.json",
    output_path="outputs/model-labels.csv",
    experiment_directory="outputs/run-001",
    country_iso_code="IRL",
    retries=2,
    retry_strategy="reprompt",
)

Available strategies:

identical
Re-run the same prompt and model configuration. This is the default.
reprompt
Append a short format reminder to the prompt before retrying.
temperature
Retry with a second model chain at retry_temperature, useful when the main run is deterministic.
annotation = run_annotation(
    model="gemma3:270m",
    csv_path="texts.csv",
    codebook_path="codebook.json",
    output_path="outputs/model-labels.csv",
    experiment_directory="outputs/run-001",
    retries=1,
    retry_strategy="temperature",
    retry_temperature=0.3,
)

Experiment runs currently expose retry behavior through the lower-level run_annotation() path. run_experiment() uses the package defaults when it calls annotation internally.