Skip to main content

Overview

The Labellerr SDK uses Pydantic schemas to define annotation questions. Use the AnnotationQuestion schema to create type-safe questions for object-based annotations (bounding boxes, polygons, etc.) and classification workflows (dropdowns, radio buttons, etc.).

Required Question Structure

Using AnnotationQuestion Schema

Every question must be defined using the AnnotationQuestion schema with the following fields:
FieldTypeRequiredDescription
question_numberintYesSequential number for the question (1, 2, 3, …)
question_idstrYesUnique identifier (UUID) - generate with str(uuid.uuid4())
questionstrYesThe user-facing label or prompt
question_typeQuestionTypeYesEnum value (e.g., QuestionType.polygon, QuestionType.dropdown)
requiredboolYesSet to True if the annotator must answer
colorstrConditionalRequired for object types (bounding_box, polygon, polyline, dot)
optionsList[Option]ConditionalRequired for classification types (dropdown, radio, select, boolean)
Object-based questions (bounding_box, polygon, polyline, dot) require a color parameter (hex code).Classification questions (dropdown, radio, select, boolean) require options as a list of Option objects.Input questions don’t require either color or options.

Question Types Reference

Object-Based Annotations:
  • QuestionType.bounding_box - Rectangle annotations
  • QuestionType.polygon - Multi-point polygon shapes
  • QuestionType.polyline - Connected line segments
  • QuestionType.dot - Single point markers
Classification Annotations:
  • QuestionType.dropdown - Single selection dropdown
  • QuestionType.radio - Radio button selection
  • QuestionType.select - Multi-select options
  • QuestionType.boolean - Yes/No toggle
  • QuestionType.input - Free text input
Specialized:
  • QuestionType.stt - Speech-to-text
  • QuestionType.imc - Image classification

Examples

Multiple Questions Template

Create a template with multiple question types including object detection and classification:
from labellerr.client import LabellerrClient
from labellerr.core.annotation_templates import create_template
from labellerr.core.schemas import (
    CreateTemplateParams,
    AnnotationQuestion,
    QuestionType,
    Option,
    DatasetDataType
)
import uuid

# Initialize client
client = LabellerrClient(
    api_key='your_api_key',
    api_secret='your_api_secret',
    client_id='your_client_id'
)

# Define questions using schema
questions = [
    AnnotationQuestion(
        question_number=1,
        question="Draw crop boundary",
        question_type=QuestionType.polygon,
        required=True,
        question_id=str(uuid.uuid4()),
        color="#5F9EA0"  # Hex color for object types
    ),
    AnnotationQuestion(
        question_number=2,
        question="Mark vehicle",
        question_type=QuestionType.bounding_box,
        required=True,
        question_id=str(uuid.uuid4()),
        color="#FFAA00"
    ),
    AnnotationQuestion(
        question_number=3,
        question="Overall quality",
        question_type=QuestionType.radio,
        required=True,
        question_id=str(uuid.uuid4()),
        options=[
            Option(option_name="Good"),
            Option(option_name="Average"),
            Option(option_name="Poor")
        ]
    ),
    AnnotationQuestion(
        question_number=4,
        question="Additional remarks",
        question_type=QuestionType.input,
        required=False,
        question_id=str(uuid.uuid4())
    )
]

# Create template
template = create_template(
    client=client,
    params=CreateTemplateParams(
        template_name="Demo Template",
        data_type=DatasetDataType.image,
        questions=questions
    )
)

print(f"Template created: {template.annotation_template_id}")

Single Question Template

Create a simple template with a single annotation question:
from labellerr.client import LabellerrClient
from labellerr.core.annotation_templates import create_template
from labellerr.core.schemas import (
    CreateTemplateParams,
    AnnotationQuestion,
    QuestionType,
    DatasetDataType
)
import uuid

client = LabellerrClient(
    api_key='your_api_key',
    api_secret='your_api_secret',
    client_id='your_client_id'
)

questions = [
    AnnotationQuestion(
        question_number=1,
        question="Track object across frames",
        question_type=QuestionType.polygon,
        required=True,
        question_id=str(uuid.uuid4()),
        color="#FE1236"
    )
]

template = create_template(
    client=client,
    params=CreateTemplateParams(
        template_name="Video Tracking Template",
        data_type=DatasetDataType.video,
        questions=questions
    )
)

print(f"Template created: {template.annotation_template_id}")

Classification Only Template

Create a template with only classification questions (no object detection):
from labellerr.client import LabellerrClient
from labellerr.core.annotation_templates import create_template
from labellerr.core.schemas import (
    CreateTemplateParams,
    AnnotationQuestion,
    QuestionType,
    Option,
    DatasetDataType
)
import uuid

client = LabellerrClient(
    api_key='your_api_key',
    api_secret='your_api_secret',
    client_id='your_client_id'
)

questions = [
    AnnotationQuestion(
        question_number=1,
        question="Image category",
        question_type=QuestionType.dropdown,
        required=True,
        question_id=str(uuid.uuid4()),
        options=[
            Option(option_name="Nature"),
            Option(option_name="Urban"),
            Option(option_name="Portrait")
        ]
    ),
    AnnotationQuestion(
        question_number=2,
        question="Contains people?",
        question_type=QuestionType.boolean,
        required=True,
        question_id=str(uuid.uuid4()),
        options=[
            Option(option_name="Yes"),
            Option(option_name="No")
        ]
    ),
    AnnotationQuestion(
        question_number=3,
        question="Tags",
        question_type=QuestionType.select,
        required=False,
        question_id=str(uuid.uuid4()),
        options=[
            Option(option_name="Outdoor"),
            Option(option_name="Indoor"),
            Option(option_name="Daytime"),
            Option(option_name="Nighttime")
        ]
    )
]

template = create_template(
    client=client,
    params=CreateTemplateParams(
        template_name="Image Classification Template",
        data_type=DatasetDataType.image,
        questions=questions
    )
)

print(f"Template created: {template.annotation_template_id}")

Best Practices

Unique Question IDs

Always generate unique question IDs using str(uuid.uuid4()) to avoid conflicts. Reuse IDs only when intentionally updating an existing question.

Sequential Numbering

Ensure question_number values are sequential (1, 2, 3, …) to maintain proper ordering in the annotation interface.

Color Selection

Use distinct hex colors for different object types to make them easily distinguishable in the annotation interface.

Clear Labels

Write concise, descriptive question text that clearly communicates what annotators should label.

Create Projects

Learn how to create projects using annotation templates