def METHOD_NAME(animation_prompts, max_frames):
    import numpy as np
    import pandas as pd
    # Get prompts sorted by keyframe
    max_f = max_frames
    parsed_animation_prompts = {}
    for key, value in animation_prompts.items():
        if check_is_number(key):  # default case 0:(1 + t %5), 30:(5-t%2)
            parsed_animation_prompts[key] = value
        else:  # math on the left hand side case 0:(1 + t %5), maxKeyframes/2:(5-t%2)
            parsed_animation_prompts[int(numexpr.evaluate(key))] = value
    sorted_prompts = sorted(parsed_animation_prompts.items(), key=lambda item: int(item[0]))
    # Setup container for interpolated prompts
    prompt_series = pd.Series([np.nan for a in range(max_frames)])
    # For every keyframe prompt except the last
    for i in range(0, len(sorted_prompts) - 1):
        # Get current and next keyframe
        current_frame = int(sorted_prompts[i][0])
        next_frame = int(sorted_prompts[i + 1][0])
        # Ensure there's no weird ordering issues or duplication in the animation prompts
        # (unlikely because we sort above, and the json parser will strip dupes)
        if current_frame >= next_frame:
            print(f"WARNING: Sequential prompt keyframes {i}:{current_frame} and {i + 1}:{next_frame} are not monotonously increasing; skipping interpolation.")
            continue
        # Get current and next keyframes' positive and negative prompts (if any)
        current_prompt = sorted_prompts[i][1]
        next_prompt = sorted_prompts[i + 1][1]
        current_positive, current_negative, *_ = current_prompt.split("--neg") + [None]
        next_positive, next_negative, *_ = next_prompt.split("--neg") + [None]
        # Calculate how much to shift the weight from current to next prompt at each frame
        weight_step = 1 / (next_frame - current_frame)
        # Apply weighted prompt interpolation for each frame between current and next keyframe
        # using the syntax:  prompt1 :weight1 AND prompt1 :weight2 --neg nprompt1 :weight1 AND nprompt1 :weight2
        # (See: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#composable-diffusion )
        for f in range(current_frame, next_frame):
            next_weight = weight_step * (f - current_frame)
            current_weight = 1 - next_weight
            # We will build the prompt incrementally depending on which prompts are present
            prompt_series[f] = ''
            # Cater for the case where neither, either or both current & next have positive prompts:
            if current_positive:
                prompt_series[f] += f" ({current_positive}):{current_weight}"
            if current_positive and next_positive:
                prompt_series[f] += f" AND "
            if next_positive:
                prompt_series[f] += f" ({next_positive}):{next_weight}"
            # Cater for the case where neither, either or both current & next have negative prompts:
            if len(current_negative) > 1 or len(next_negative) > 1:
                prompt_series[f] += " --neg "
                if len(current_negative) > 1:
                    prompt_series[f] += f" ({current_negative}):{current_weight}"
                if len(current_negative) > 1 and len(next_negative) > 1:
                    prompt_series[f] += f" AND "
                if len(next_negative) > 1:
                    prompt_series[f] += f" ({next_negative}):{next_weight}"
    # Set explicitly declared keyframe prompts (overwriting interpolated values at the keyframe idx). This ensures:
    # - That final prompt is set, and
    # - Gives us a chance to emit warnings if any keyframe prompts are already using composable diffusion
    for i, prompt in parsed_animation_prompts.items():
        prompt_series[int(i)] = prompt
        if ' AND ' in prompt:
            print(f"WARNING: keyframe {i}'s prompt is using composable diffusion (aka the 'AND' keyword). This will cause unexpected behaviour with interpolation.")
    # Return the filled series, in case max_frames is greater than the last keyframe or any ranges were skipped.
    return prompt_series.ffill().bfill()