code: def stream_chunk_builder(
      chunks: list, messages: Optional[list] = None
  ):
      model_response = litellm.ModelResponse()
      # set hidden params from chunk to model_response
      if model_response is not None and hasattr(
          model_response, "_hidden_params"
      ):
          model_response._hidden_params = chunks[0].get(
              "_hidden_params", {}
          )
      id = chunks[0]["id"]
      object = chunks[0]["object"]
      created = chunks[0]["created"]
      model = chunks[0]["model"]
      system_fingerprint = chunks[0].get("system_fingerprint", None)
  
      if isinstance(
          chunks[0]["choices"][0], litellm.utils.TextChoices
      ):  # route to the text completion logic
          return stream_chunk_builder_text_completion(
              chunks=chunks, messages=messages
          )
      role = chunks[0]["choices"][0]["delta"]["role"]
      finish_reason = chunks[-1]["choices"][0]["finish_reason"]
  
      # Initialize the response dictionary
      response = {
          "id": id,
          "object": object,
          "created": created,
          "model": model,
          "system_fingerprint": system_fingerprint,
          "choices": [
              {
                  "index": 0,
                  "message": {"role": role, "content": ""},
                  "finish_reason": finish_reason,
              }
          ],
          "usage": {
              "prompt_tokens": 0,  # Modify as needed
              "completion_tokens": 0,  # Modify as needed
              "total_tokens": 0,  # Modify as needed
          },
      }
  
      # Extract the "content" strings from the nested dictionaries within "choices"
      content_list = []
      combined_content = ""
      combined_arguments = ""
  
      if (
          "tool_calls" in chunks[0]["choices"][0]["delta"]
          and chunks[0]["choices"][0]["delta"]["tool_calls"] is not None
      ):
          argument_list = []
          delta = chunks[0]["choices"][0]["delta"]
          message = response["choices"][0]["message"]
          message["tool_calls"] = []
          id = None
          name = None
          type = None
          tool_calls_list = []
          prev_index = 0
          prev_id = None
          curr_id = None
          curr_index = 0
          for chunk in chunks:
              choices = chunk["choices"]
              for choice in choices:
                  delta = choice.get("delta", {})
                  tool_calls = delta.get("tool_calls", "")
                  # Check if a tool call is present
                  if tool_calls and tool_calls[0].function is not None:
                      if tool_calls[0].id:
                          id = tool_calls[0].id
                          curr_id = id
                          if prev_id is None:
                              prev_id = curr_id
                      if tool_calls[0].index:
                          curr_index = tool_calls[0].index
                      if tool_calls[0].function.arguments:
                          # Now, tool_calls is expected to be a dictionary
                          arguments = tool_calls[0].function.arguments
                          argument_list.append(arguments)
                      if tool_calls[0].function.name:
                          name = tool_calls[0].function.name
                      if tool_calls[0].type:
                          type = tool_calls[0].type
              if curr_index != prev_index:  # new tool call
                  combined_arguments = "".join(argument_list)
                  tool_calls_list.append(
                      {
                          "id": prev_id,
                          "index": prev_index,
                          "function": {
                              "arguments": combined_arguments,
                              "name": name,
                          },
                          "type": type,
                      }
                  )
                  argument_list = []  # reset
                  prev_index = curr_index
                  prev_id = curr_id
  
          combined_arguments = "".join(argument_list)
          tool_calls_list.append(
              {
                  "id": id,
                  "function": {
                      "arguments": combined_arguments,
                      "name": name,
                  },
                  "type": type,
              }
          )
          response["choices"][0]["message"]["content"] = None
          response["choices"][0]["message"][
              "tool_calls"
          ] = tool_calls_list
      elif (
          "function_call" in chunks[0]["choices"][0]["delta"]
          and chunks[0]["choices"][0]["delta"]["function_call"]
          is not None
      ):
          argument_list = []
          delta = chunks[0]["choices"][0]["delta"]
          function_call = delta.get("function_call", "")
          function_call_name = function_call.name
  
          message = response["choices"][0]["message"]
          message["function_call"] = {}
          message["function_call"]["name"] = function_call_name
  
          for chunk in chunks:
              choices = chunk["choices"]
              for choice in choices:
                  delta = choice.get("delta", {})
                  function_call = delta.get("function_call", "")
  
                  # Check if a function call is present
                  if function_call:
                      # Now, function_call is expected to be a dictionary
                      arguments = function_call.arguments
                      argument_list.append(arguments)
  
          combined_arguments = "".join(argument_list)
          response["choices"][0]["message"]["content"] = None
          response["choices"][0]["message"]["function_call"][
              "arguments"
          ] = combined_arguments
      else:
          for chunk in chunks:
              choices = chunk["choices"]
              for choice in choices:
                  delta = choice.get("delta", {})
                  content = delta.get("content", "")
                  if content == None:
                      continue  # openai v1.0.0 sets content = None for chunks
                  content_list.append(content)
  
          # Combine the "content" strings into a single string || combine the 'function' strings into a single string
          combined_content = "".join(content_list)
  
          # Update the "content" field within the response dictionary
          response["choices"][0]["message"][
              "content"
          ] = combined_content
  
      if len(combined_content) > 0:
          completion_output = combined_content
      elif len(combined_arguments) > 0:
          completion_output = combined_arguments
      else:
          completion_output = ""
      # # Update usage information if needed
      try:
          response["usage"]["prompt_tokens"] = token_counter(
              model=model, messages=messages
          )
      except:  # don't allow this failing to block a complete streaming response from being returned
          print_verbose(
              f"token_counter failed, assuming prompt tokens is 0"
          )
          response["usage"]["prompt_tokens"] = 0
      response["usage"]["completion_tokens"] = token_counter(
          model=model,
          text=completion_output,
          count_response_tokens=True,  # count_response_tokens is a Flag to tell token counter this is a response, No need to add extra tokens we do for input messages
      )
      response["usage"]["total_tokens"] = (
          response["usage"]["prompt_tokens"]
          + response["usage"]["completion_tokens"]
      )
      return convert_to_model_response_object(
          response_object=response, model_response_object=model_response
      )
  
imports: import os, openai, sys, json, inspect, uuid, datetime, threading
  from typing import Any, Literal, Union
  from functools import partial
  import dotenv, traceback, random, asyncio, time, contextvars
  from copy import deepcopy
  import httpx
  import litellm
  from litellm import client, exception_type, get_optional_params, get_litellm_params, Logging
  from litellm.utils import get_secret, CustomStreamWrapper, read_config_args, completion_with_fallbacks, get_llm_provider, get_api_key, mock_completion_streaming_obj, convert_to_model_response_object, token_counter, Usage, get_optional_params_embeddings, get_optional_params_image_gen
  from .llms import anthropic, together_ai, ai21, sagemaker, bedrock, huggingface_restapi, replicate, aleph_alpha, nlp_cloud, baseten, vllm, ollama, ollama_chat, cloudflare, cohere, petals, oobabooga, openrouter, palm, gemini, vertex_ai, maritalk
  from .llms.openai import OpenAIChatCompletion, OpenAITextCompletion
  from .llms.azure import AzureChatCompletion
  from .llms.huggingface_restapi import Huggingface
  from .llms.prompt_templates.factory import prompt_factory, custom_prompt, function_call_prompt
  import tiktoken
  from concurrent.futures import ThreadPoolExecutor
  from typing import Callable, List, Optional, Dict, Union, Mapping
  from .caching import enable_cache, disable_cache, update_cache
  from litellm.utils import get_secret, CustomStreamWrapper, TextCompletionStreamWrapper, ModelResponse, TextCompletionResponse, TextChoices, EmbeddingResponse, read_config_args, Choices, Message
label_desc: Use image node_id 14 for calling a global function with example usage: stream_chunk_builder(chunks, messages) and returns: convert_to_model_response_object, stream_chunk_builder_text_completion