code: def timeout(
      timeout_duration: float = 0.0, exception_to_raise=Timeout
  ):
      """
      Wraps a function to raise the specified exception if execution time
      is greater than the specified timeout.
  
      Works with both synchronous and asynchronous callables, but with synchronous ones will introduce
      some overhead due to the backend use of threads and asyncio.
  
          :param float timeout_duration: Timeout duration in seconds. If none callable won't time out.
          :param OpenAIError exception_to_raise: Exception to raise when the callable times out.
              Defaults to TimeoutError.
          :return: The decorated function.
          :rtype: callable
      """
  
      def decorator(func):
          @wraps(func)
          def wrapper(*args, **kwargs):
              async def async_func():
                  return func(*args, **kwargs)
  
              thread = _LoopWrapper()
              thread.start()
              future = asyncio.run_coroutine_threadsafe(
                  async_func(), thread.loop
              )
              local_timeout_duration = timeout_duration
              if (
                  "force_timeout" in kwargs
                  and kwargs["force_timeout"] is not None
              ):
                  local_timeout_duration = kwargs["force_timeout"]
              elif (
                  "request_timeout" in kwargs
                  and kwargs["request_timeout"] is not None
              ):
                  local_timeout_duration = kwargs["request_timeout"]
              try:
                  result = future.result(timeout=local_timeout_duration)
              except futures.TimeoutError:
                  thread.stop_loop()
                  model = args[0] if len(args) > 0 else kwargs["model"]
                  raise exception_to_raise(
                      f"A timeout error occurred. The function call took longer than {local_timeout_duration} second(s).",
                      model=model,  # [TODO]: replace with logic for parsing out llm provider from model name
                      llm_provider="openai",
                  )
              thread.stop_loop()
              return result
  
          @wraps(func)
          async def async_wrapper(*args, **kwargs):
              local_timeout_duration = timeout_duration
              if "force_timeout" in kwargs:
                  local_timeout_duration = kwargs["force_timeout"]
              elif (
                  "request_timeout" in kwargs
                  and kwargs["request_timeout"] is not None
              ):
                  local_timeout_duration = kwargs["request_timeout"]
              try:
                  value = await asyncio.wait_for(
                      func(*args, **kwargs), timeout=timeout_duration
                  )
                  return value
              except asyncio.TimeoutError:
                  model = args[0] if len(args) > 0 else kwargs["model"]
                  raise exception_to_raise(
                      f"A timeout error occurred. The function call took longer than {local_timeout_duration} second(s).",
                      model=model,  # [TODO]: replace with logic for parsing out llm provider from model name
                      llm_provider="openai",
                  )
  
          if iscoroutinefunction(func):
              return async_wrapper
          return wrapper
  
      return decorator
  
file_path: litellm/litellm/timeout.py
imports: import asyncio
  from concurrent import futures
  from inspect import iscoroutinefunction
  from functools import wraps
  from threading import Thread
  from litellm.exceptions import Timeout
label_desc: Use image node_id 1 for calling a global function with example usage: timeout(timeout_duration, exception_to_raise) and returns: decorator, wrapper, result, async_wrapper, func, value