class_docstr: Example usage:
  ```python
  from litellm import Router
  model_list = [
  {
      "model_name": "azure-gpt-3.5-turbo", # model alias
      "litellm_params": { # params for litellm completion/embedding call
          "model": "azure/<your-deployment-name-1>",
          "api_key": <your-api-key>,
          "api_version": <your-api-version>,
          "api_base": <your-api-base>
      },
  },
  {
      "model_name": "azure-gpt-3.5-turbo", # model alias
      "litellm_params": { # params for litellm completion/embedding call
          "model": "azure/<your-deployment-name-2>",
          "api_key": <your-api-key>,
          "api_version": <your-api-version>,
          "api_base": <your-api-base>
      },
  },
  {
      "model_name": "openai-gpt-3.5-turbo", # model alias
      "litellm_params": { # params for litellm completion/embedding call
          "model": "gpt-3.5-turbo",
          "api_key": <your-api-key>,
      },
  ]
  
  router = Router(model_list=model_list, fallbacks=[{"azure-gpt-3.5-turbo": "openai-gpt-3.5-turbo"}])
  ```
code: def __init__(
      self,
      model_list: Optional[list] = None,
      ## CACHING ##
      redis_url: Optional[str] = None,
      redis_host: Optional[str] = None,
      redis_port: Optional[int] = None,
      redis_password: Optional[str] = None,
      cache_responses: Optional[bool] = False,
      cache_kwargs: dict = {},  # additional kwargs to pass to RedisCache (see caching.py)
      caching_groups: Optional[
          List[tuple]
      ] = None,  # if you want to cache across model groups
      client_ttl: int = 3600,  # ttl for cached clients - will re-initialize after this time in seconds
      ## RELIABILITY ##
      num_retries: int = 0,
      timeout: Optional[float] = None,
      default_litellm_params={},  # default params for Router.chat.completion.create
      set_verbose: bool = False,
      fallbacks: List = [],
      allowed_fails: Optional[int] = None,
      context_window_fallbacks: List = [],
      model_group_alias: Optional[dict] = {},
      retry_after: int = 0,  # min time to wait before retrying a failed request
      routing_strategy: Literal[
          "simple-shuffle",
          "least-busy",
          "usage-based-routing",
          "latency-based-routing",
      ] = "simple-shuffle",
      routing_strategy_args: dict = {},  # just for latency-based routing
  ) -> None:
      self.set_verbose = set_verbose
      self.deployment_names: List = (
          []
      )  # names of models under litellm_params. ex. azure/chatgpt-v-2
      self.deployment_latency_map = {}
      ### CACHING ###
      cache_type: Literal[
          "local", "redis"
      ] = "local"  # default to an in-memory cache
      redis_cache = None
      cache_config = {}
      self.client_ttl = client_ttl
      if redis_url is not None or (
          redis_host is not None
          and redis_port is not None
          and redis_password is not None
      ):
          cache_type = "redis"
  
          if redis_url is not None:
              cache_config["url"] = redis_url
  
          if redis_host is not None:
              cache_config["host"] = redis_host
  
          if redis_port is not None:
              cache_config["port"] = str(redis_port)  # type: ignore
  
          if redis_password is not None:
              cache_config["password"] = redis_password
  
          # Add additional key-value pairs from cache_kwargs
          cache_config.update(cache_kwargs)
          redis_cache = RedisCache(**cache_config)
  
      if cache_responses:
          if litellm.cache is None:
              # the cache can be initialized on the proxy server. We should not overwrite it
              litellm.cache = litellm.Cache(type=cache_type, **cache_config)  # type: ignore
          self.cache_responses = cache_responses
      self.cache = DualCache(
          redis_cache=redis_cache, in_memory_cache=InMemoryCache()
      )  # use a dual cache (Redis+In-Memory) for tracking cooldowns, usage, etc.
  
      if model_list:
          model_list = copy.deepcopy(model_list)
          self.set_model_list(model_list)
          self.healthy_deployments: List = self.model_list
          for m in model_list:
              self.deployment_latency_map[
                  m["litellm_params"]["model"]
              ] = 0
  
      self.allowed_fails = allowed_fails or litellm.allowed_fails
      self.failed_calls = (
          InMemoryCache()
      )  # cache to track failed call per deployment, if num failed calls within 1 minute > allowed fails, then add it to cooldown
      self.num_retries = num_retries or litellm.num_retries or 0
      self.timeout = timeout or litellm.request_timeout
      self.retry_after = retry_after
      self.routing_strategy = routing_strategy
      self.fallbacks = fallbacks or litellm.fallbacks
      self.context_window_fallbacks = (
          context_window_fallbacks or litellm.context_window_fallbacks
      )
      self.model_exception_map: dict = (
          {}
      )  # dict to store model: list exceptions. self.exceptions = {"gpt-3.5": ["API KEY Error", "Rate Limit Error", "good morning error"]}
      self.total_calls: defaultdict = defaultdict(
          int
      )  # dict to store total calls made to each model
      self.fail_calls: defaultdict = defaultdict(
          int
      )  # dict to store fail_calls made to each model
      self.success_calls: defaultdict = defaultdict(
          int
      )  # dict to store success_calls  made to each model
      self.previous_models: List = (
          []
      )  # list to store failed calls (passed in as metadata to next call)
      self.model_group_alias: dict = (
          model_group_alias or {}
      )  # dict to store aliases for router, ex. {"gpt-4": "gpt-3.5-turbo"}, all requests with gpt-4 -> get routed to gpt-3.5-turbo group
  
      # make Router.chat.completions.create compatible for openai.chat.completions.create
      self.chat = litellm.Chat(params=default_litellm_params)
  
      # default litellm args
      self.default_litellm_params = default_litellm_params
      self.default_litellm_params.setdefault("timeout", timeout)
      self.default_litellm_params.setdefault("max_retries", 0)
      self.default_litellm_params.setdefault("metadata", {}).update(
          {"caching_groups": caching_groups}
      )
  
      ### ROUTING SETUP ###
      if routing_strategy == "least-busy":
          self.leastbusy_logger = LeastBusyLoggingHandler(
              router_cache=self.cache, model_list=self.model_list
          )
          ## add callback
          if isinstance(litellm.input_callback, list):
              litellm.input_callback.append(self.leastbusy_logger)  # type: ignore
          else:
              litellm.input_callback = [self.leastbusy_logger]  # type: ignore
          if isinstance(litellm.callbacks, list):
              litellm.callbacks.append(self.leastbusy_logger)  # type: ignore
      elif routing_strategy == "usage-based-routing":
          self.lowesttpm_logger = LowestTPMLoggingHandler(
              router_cache=self.cache, model_list=self.model_list
          )
          if isinstance(litellm.callbacks, list):
              litellm.callbacks.append(self.lowesttpm_logger)  # type: ignore
      elif routing_strategy == "latency-based-routing":
          self.lowestlatency_logger = LowestLatencyLoggingHandler(
              router_cache=self.cache,
              model_list=self.model_list,
              routing_args=routing_strategy_args,
          )
          if isinstance(litellm.callbacks, list):
              litellm.callbacks.append(self.lowestlatency_logger)  # type: ignore
      ## COOLDOWNS ##
      if isinstance(litellm.failure_callback, list):
          litellm.failure_callback.append(
              self.deployment_callback_on_failure
          )
      else:
          litellm.failure_callback = [
              self.deployment_callback_on_failure
          ]
      verbose_router_logger.debug(
          f"Intialized router with Routing strategy: {self.routing_strategy}\n"
      )
  
imports: import copy, httpx
  from datetime import datetime
  from typing import Dict, List, Optional, Union, Literal, Any
  import random, threading, time, traceback, uuid
  import litellm, openai
  from litellm.caching import RedisCache, InMemoryCache, DualCache
  import logging, asyncio
  import inspect, concurrent
  from openai import AsyncOpenAI
  from collections import defaultdict
  from litellm.router_strategy.least_busy import LeastBusyLoggingHandler
  from litellm.router_strategy.lowest_tpm_rpm import LowestTPMLoggingHandler
  from litellm.router_strategy.lowest_latency import LowestLatencyLoggingHandler
  from litellm.llms.custom_httpx.azure_dall_e_2 import CustomHTTPTransport, AsyncCustomHTTPTransport
  from litellm.utils import ModelResponse, CustomStreamWrapper
  import copy
  from litellm._logging import verbose_router_logger
  import logging
label_desc: Use image node_id 1 to create a new Router object  with example: obj = Router(model_list, redis_url, redis_host, redis_port, redis_password, cache_responses, cache_kwargs, caching_groups, client_ttl, num_retries, timeout, default_litellm_params, set_verbose, fallbacks, allowed_fails, context_window_fallbacks, model_group_alias, retry_after, routing_strategy, routing_strategy_args)