def split_online_stream(
    original_stream: Iterable[DatasetExperience],
    experience_size: int,
    shuffle: bool = True,
    drop_last: bool = False,
    experience_split_strategy: Optional[
        Callable[
            [DatasetExperience[TCLDataset], int],
            Iterable[OnlineCLExperience[TCLDataset]],
        ]
    ] = None,
    access_task_boundaries: bool = False,
    seed: int = None,
) -> CLStream[DatasetExperience[TCLDataset]]:
    """Split a stream of large batches to create an online stream of small
    mini-batches.

    The resulting stream can be used for Online Continual Learning (OCL)
    scenarios (or data-incremental, or other online-based settings).

    For efficiency reasons, the resulting stream is an iterator, generating
    experience on-demand.

    :param original_stream: The stream with the original data.
    :param experience_size: The size of the experience, as an int. Ignored
        if `custom_split_strategy` is used.
    :param shuffle: If True, experiences will be split by first shuffling
        instances in each experience. This will use the default PyTorch
        random number generator at its current state. Defaults to False.
        Ignored if `experience_split_strategy` is used.
    :param drop_last: If True, if the last experience doesn't contain
        `experience_size` instances, then the last experience will be dropped.
        Defaults to False. Ignored if `experience_split_strategy` is used.
    :param experience_split_strategy: A function that implements a custom
        splitting strategy. The function must accept an experience and return
        an experience's iterator. Defaults to None, which means
        that the standard splitting strategy will be used (which creates
        experiences of size `experience_size`).
        A good starting to understand the mechanism is to look at the
        implementation of the standard splitting function
        :func:`fixed_size_experience_split`.
    :param seed: random seed used for shuffling by the default splitter.
    :return: A lazy online stream with experiences of size `experience_size`.
    """

    if experience_split_strategy is None:
        # functools.partial is a more compact option
        # However, MyPy does not understand what a partial is -_-
        def default_online_split_wrapper(e, e_sz):
            return _default_online_split(
                shuffle, drop_last, access_task_boundaries, e, e_sz, seed=seed
            )

        split_strategy = default_online_split_wrapper
    else:
        split_strategy = experience_split_strategy

    def exps_iter():
        for exp in original_stream:
            for sub_exp in split_strategy(exp, experience_size):
                yield sub_exp

    stream_name: str = getattr(original_stream, "name", "train") + "_online"
    return CLStream(
        name=stream_name,
        exps_iter=exps_iter(),
        set_stream_info=True,
    )
Split a stream of large batches to create an online stream of small
    mini-batches.

    The resulting stream can be used for Online Continual Learning (OCL)
    scenarios (or data-incremental, or other online-based settings).

    For efficiency reasons, the resulting stream is an iterator, generating
    experience on-demand.

    :param original_stream: The stream with the original data.
    :param experience_size: The size of the experience, as an int. Ignored
        if `custom_split_strategy` is used.
    :param shuffle: If True, experiences will be split by first shuffling
        instances in each experience. This will use the default PyTorch
        random number generator at its current state. Defaults to False.
        Ignored if `experience_split_strategy` is used.
    :param drop_last: If True, if the last experience doesn't contain
        `experience_size` instances, then the last experience will be dropped.
        Defaults to False. Ignored if `experience_split_strategy` is used.
    :param experience_split_strategy: A function that implements a custom
        splitting strategy. The function must accept an experience and return
        an experience's iterator. Defaults to None, which means
        that the standard splitting strategy will be used (which creates
        experiences of size `experience_size`).
        A good starting to understand the mechanism is to look at the
        implementation of the standard splitting function
        :func:`fixed_size_experience_split`.
    :param seed: random seed used for shuffling by the default splitter.
    :return: A lazy online stream with experiences of size `experience_size`.
    
avalanche/benchmarks/scenarios/online.py