def convert_prm800k_item(
    original_item: PRM800KItem,
    step_tag: str,
    add_step_prefix: bool = False,
    neutral_is_good: bool = True,
) -> list[ConvertedItem]:
    """Convert the original dataset item to desired format.

    PRM800K may have multiple completions for a single reasoning step. For
    example, a single item in the original dataset has the following steps:
    - Step 1: [choice 1]
    - Step 2: [choice 1, choice 2, choice 3]
    - Step 3: [choice 1, choice 2]
    This item will produce 1x3x2=6 converted items, each contains one possible
    reasoning process that is a combination of these steps:
    - Item 1: [step1-choice1, step2-choice1, step3-choice1]
    - Item 2: [step1-choice1, step2-choice1, step3-choice2]
    - Item 3: [step1-choice1, step2-choice2, step3-choice1], ...

    Args:
      original_item: An `PRM800KItem` instance obtained by parsing a single line
        of the original dataset JSON file.
      neutral_is_good: Cast `neutral` label to `good` if True, `bad` otherwise.
        PRM800K has three labels, while we only need binary classification.

    Returns:
      A list of `ConvertedItem` that contain all combinations of reasoning steps.
    """
    # Some `Step` of the original item may contain all-null `Completion`.
    filtered_steps = filter(
        lambda x: x.completions is not None, original_item.label.steps
    )

    processes_and_labels_for_each_step = extract_processes_and_labels_for_steps(
        filtered_steps, step_tag, add_step_prefix, neutral_is_good
    )  # [([str], [str])]

    saved_processes: list[str] = [""]
    updated_processes: list[str] = []
    saved_labels: list[list[str]] = [[]]
    updated_labels: list[list[str]] = []

    for completions, labels in processes_and_labels_for_each_step:
        for step_cache, label_cache in zip(saved_processes, saved_labels):
            for completion, label in zip(completions, labels):
                updated_processes.append(f"{step_cache} {completion}".strip(" "))
                updated_labels.append(label_cache + [label])

            saved_processes, saved_labels = updated_processes, updated_labels
            updated_processes, updated_labels = [], []

    return list(
        map(
            lambda proc_lbl: ConvertedItem(original_item.question.problem, *proc_lbl),
            zip(saved_processes, saved_labels),
        )
    )
Convert the original dataset item to desired format.

    PRM800K may have multiple completions for a single reasoning step. For
    example, a single item in the original dataset has the following steps:
    - Step 1: [choice 1]
    - Step 2: [choice 1, choice 2, choice 3]
    - Step 3: [choice 1, choice 2]
    This item will produce 1x3x2=6 converted items, each contains one possible
    reasoning process that is a combination of these steps:
    - Item 1: [step1-choice1, step2-choice1, step3-choice1]
    - Item 2: [step1-choice1, step2-choice1, step3-choice2]
    - Item 3: [step1-choice1, step2-choice2, step3-choice1], ...

    Args:
      original_item: An `PRM800KItem` instance obtained by parsing a single line
        of the original dataset JSON file.
      neutral_is_good: Cast `neutral` label to `good` if True, `bad` otherwise.
        PRM800K has three labels, while we only need binary classification.

    Returns:
      A list of `ConvertedItem` that contain all combinations of reasoning steps.
    
preprocess/src/preprocessors/prm800k.py