def prepare_io_bindings(
    session: "InferenceSession",
    input_data: dict[str, "NDArray"],
    device: str,
    device_id: int = 0,
    shared_kv_buffer: bool = False,
    kv_cache_ortvalues: dict = None,
) -> "IOBinding":
    """Convert input from numpy array to OrtValue.

    session: ONNXRuntime session
    input_data: dict of input data, value is numpy array
    device: olive device
    device_id: 0 by default. TODO(trajep): support user to specified device id
    shared_kv_buffer: whether to share the key/value buffer across multiple runs, it is False by default,
        and only used when we observe kv cache and fp16 is used.
        TODO(trajep): how shared_kv_buffer works with generation task
    kv_cache_ortvalues: dict of OrtValue for shared kv cache, it is None by default.
    """
    use_fp16 = any(v.dtype == np.float16 for v in input_data.values())
    io_bind_op = session.io_binding()

    if shared_kv_buffer:
        kv_cache_ortvalues = kv_cache_ortvalues or {}

    bind_input_data(io_bind_op, input_data, use_fp16, device, device_id, shared_kv_buffer, kv_cache_ortvalues)
    bind_output_data(io_bind_op, session.get_outputs(), use_fp16, device, shared_kv_buffer, kv_cache_ortvalues)
    return io_bind_op
Convert input from numpy array to OrtValue.

    session: ONNXRuntime session
    input_data: dict of input data, value is numpy array
    device: olive device
    device_id: 0 by default. TODO(trajep): support user to specified device id
    shared_kv_buffer: whether to share the key/value buffer across multiple runs, it is False by default,
        and only used when we observe kv cache and fp16 is used.
        TODO(trajep): how shared_kv_buffer works with generation task
    kv_cache_ortvalues: dict of OrtValue for shared kv cache, it is None by default.
    
olive/common/ort_inference.py