def get_runnable(
    bento_model: bentoml.Model,
):
    """
    Private API: use :obj:`~bentoml.Model.to_runnable` instead.
    """

    partial_kwargs: t.Dict[str, t.Any] = bento_model.info.options.partial_kwargs  # type: ignore

    class KerasRunnable(Runnable):
        SUPPORTED_RESOURCES = ("nvidia.com/gpu", "cpu")
        SUPPORTS_CPU_MULTI_THREADING = True

        def __init__(self):
            super().__init__()
            if len(tf.config.list_physical_devices("GPU")) > 0:
                # In Multi-GPU scenarios, the visible cuda devices will be set for each Runner worker
                # by the runner's Scheduling Strategy. So that the Runnable implementation only needs
                # to find the first GPU device visible to current process.
                self.device_name = "/device:GPU:0"
            else:
                self.device_name = "/device:CPU:0"

            self.model = load_model(bento_model, device_name=self.device_name)
            self.methods_cache: t.Dict[str, t.Callable[..., t.Any]] = {}

    def _gen_run_method(runnable_self: KerasRunnable, method_name: str):
        raw_method = getattr(runnable_self.model, method_name)
        method_partial_kwargs = partial_kwargs.get(method_name)
        if method_partial_kwargs:
            raw_method = functools.partial(raw_method, **method_partial_kwargs)

        def _mapping(item: "KerasArgType") -> "tf_ext.TensorLike":
            if not LazyType["tf_ext.TensorLike"]("tensorflow.Tensor").isinstance(item):
                return t.cast("tf_ext.TensorLike", tf.convert_to_tensor(item))
            else:
                return item

        def _run_method(
            runnable_self: KerasRunnable, *args: "KerasArgType"
        ) -> "ext.NpNDArray" | t.Tuple["ext.NpNDArray", ...]:
            params = Params["KerasArgType"](*args)

            with tf.device(runnable_self.device_name):
                params = params.map(_mapping)
                if len(params.args) == 1:
                    arg = params.args[0]
                else:
                    arg = params.args

                res: "tf_ext.EagerTensor" | "ext.NpNDArray" = raw_method(arg)

                if LazyType["tf_ext.EagerTensor"](
                    "tensorflow.python.framework.ops._EagerTensorBase"
                ).isinstance(res):
                    return t.cast("ext.NpNDArray", res.numpy())

                if isinstance(res, list):
                    return tuple(res)
                return res

        return _run_method

    def add_run_method(method_name: str, options: ModelSignature):
        def run_method(runnable_self: KerasRunnable, *args: t.Any) -> t.Any:
            _run_method = runnable_self.methods_cache.get(method_name)
            if not _run_method:
                _run_method = _gen_run_method(runnable_self, method_name)
                runnable_self.methods_cache[method_name] = _run_method

            return _run_method(runnable_self, *args)

        KerasRunnable.add_method(
            run_method,
            name=method_name,
            batchable=options.batchable,
            batch_dim=options.batch_dim,
            input_spec=options.input_spec,
            output_spec=options.output_spec,
        )

    for method_name, options in bento_model.info.signatures.items():
        add_run_method(method_name, options)

    return KerasRunnable
Private API: use :obj:`~bentoml.Model.to_runnable` instead.
src/bentoml/_internal/frameworks/keras.py