class_docstr: Enables text generation using OpenAI's large language models (LLMs). It supports gpt-4 and gpt-3.5-turbo
  family of models accessed through the chat completions API endpoint.
  
  Users can pass any text generation parameters valid for the `openai.ChatCompletion.create` method
  directly to this component via the `**generation_kwargs` parameter in __init__ or the `**generation_kwargs`
  parameter in `run` method.
  
  For more details on the parameters supported by the OpenAI API, refer to the OpenAI
  [documentation](https://platform.openai.com/docs/api-reference/chat).
  
  ```python
  from haystack.components.generators.chat import OpenAIChatGenerator
  from haystack.dataclasses import ChatMessage
  
  messages = [ChatMessage.from_user("What's Natural Language Processing?")]
  
  client = OpenAIChatGenerator()
  response = client.run(messages)
  print(response)
  
  >>{'replies': [ChatMessage(content='Natural Language Processing (NLP) is a branch of artificial intelligence
  >>that focuses on enabling computers to understand, interpret, and generate human language in a way that is
  >>meaningful and useful.', role=<ChatRole.ASSISTANT: 'assistant'>, name=None,
  >>meta={'model': 'gpt-3.5-turbo-0613', 'index': 0, 'finish_reason': 'stop',
  >>'usage': {'prompt_tokens': 15, 'completion_tokens': 36, 'total_tokens': 51}})]}
  
  ```
  
   Key Features and Compatibility:
       - **Primary Compatibility**: Designed to work seamlessly with the OpenAI API Chat Completion endpoint
          and gpt-4 and gpt-3.5-turbo family of models.
       - **Streaming Support**: Supports streaming responses from the OpenAI API Chat Completion endpoint.
       - **Customizability**: Supports all parameters supported by the OpenAI API Chat Completion endpoint.
  
   Input and Output Format:
       - **ChatMessage Format**: This component uses the ChatMessage format for structuring both input and output,
         ensuring coherent and contextually relevant responses in chat-based text generation scenarios. Details on the
         ChatMessage format can be found at: https://github.com/openai/openai-python/blob/main/chatml.md.
class_docstr_tok: ["Enables","text","generation","using","OpenAI","'s","large","language","models","(","LLMs",")",".","It","supports","gpt-4","and","gpt-3.5-turbo","family","of","models","accessed","through","the","chat","completions","API","endpoint",".","Users","can","pass","any","text","generation","parameters","valid","for","the","`","openai.ChatCompletion.create","`","method","directly","to","this","component","via","the","`","*","*","generation_kwargs","`","parameter","in","__init__","or","the","`","*","*","generation_kwargs","`","parameter","in","`","run","`","method",".","For","more","details","on","the","parameters","supported","by","the","OpenAI","API",",","refer","to","the","OpenAI","[","documentation","]","(","https",":","\/\/platform.openai.com\/docs\/api-reference\/chat",")",".","``","`","python","from","haystack.components.generators.chat","import","OpenAIChatGenerator","from","haystack.dataclasses","import","ChatMessage","messages","=","[","ChatMessage.from_user","(","``","What","'s","Natural","Language","Processing","?","''",")","]","client","=","OpenAIChatGenerator","(",")","response","=","client.run","(","messages",")","print","(","response",")",">",">","{","'replies","'",":","[","ChatMessage","(","content='Natural","Language","Processing","(","NLP",")","is","a","branch","of","artificial","intelligence",">",">","that","focuses","on","enabling","computers","to","understand",",","interpret",",","and","generate","human","language","in","a","way","that","is",">",">","meaningful","and","useful",".","'",",","role=","<","ChatRole.ASSISTANT",":","'assistant","'",">",",","name=None",",",">",">","meta=","{","'model","'",":","'gpt-3.5-turbo-0613","'",",","'index","'",":","0",",","'finish_reason","'",":","'stop","'",",",">",">","'usage","'",":","{","'prompt_tokens","'",":","15",",","'completion_tokens","'",":","36",",","'total_tokens","'",":","51","}","}",")","]","}","``","`","Key","Features","and","Compatibility",":","-","*","*","Primary","Compatibility","*","*",":","Designed","to","work","seamlessly","with","the","OpenAI","API","Chat","Completion","endpoint","and","gpt-4","and","gpt-3.5-turbo","family","of","models",".","-","*","*","Streaming","Support","*","*",":","Supports","streaming","responses","from","the","OpenAI","API","Chat","Completion","endpoint",".","-","*","*","Customizability","*","*",":","Supports","all","parameters","supported","by","the","OpenAI","API","Chat","Completion","endpoint",".","Input","and","Output","Format",":","-","*","*","ChatMessage","Format","*","*",":","This","component","uses","the","ChatMessage","format","for","structuring","both","input","and","output",",","ensuring","coherent","and","contextually","relevant","responses","in","chat-based","text","generation","scenarios",".","Details","on","the","ChatMessage","format","can","be","found","at",":","https",":","\/\/github.com\/openai\/openai-python\/blob\/main\/chatml.md","."]
docstr: Connects the streaming chunks into a single ChatMessage.
  :param chunk: The last chunk returned by the OpenAI API.
  :param chunks: The list of all chunks returned by the OpenAI API.
docstr_tok: ["Connects","the","streaming","chunks","into","a","single","ChatMessage",".",":","param","chunk",":","The","last","chunk","returned","by","the","OpenAI","API",".",":","param","chunks",":","The","list","of","all","chunks","returned","by","the","OpenAI","API","."]
code: def _connect_chunks(
      self, chunk: Any, chunks: List[StreamingChunk]
  ) -> ChatMessage:
      """
      Connects the streaming chunks into a single ChatMessage.
      :param chunk: The last chunk returned by the OpenAI API.
      :param chunks: The list of all chunks returned by the OpenAI API.
      """
      is_tools_call = bool(chunks[0].meta.get("tool_calls"))
      is_function_call = bool(chunks[0].meta.get("function_call"))
      # if it's a tool call or function call, we need to build the payload dict from all the chunks
      if is_tools_call or is_function_call:
          tools_len = (
              1
              if is_function_call
              else len(chunks[0].meta.get("tool_calls", []))
          )
          # don't change this approach of building payload dicts, otherwise mypy will complain
          p_def: Dict[str, Any] = {
              "index": 0,
              "id": "",
              "function": {"arguments": "", "name": ""},
              "type": "function",
          }
          payloads = [copy.deepcopy(p_def) for _ in range(tools_len)]
          for chunk_payload in chunks:
              if is_tools_call:
                  deltas = chunk_payload.meta.get("tool_calls") or []
              else:
                  deltas = (
                      [chunk_payload.meta["function_call"]]
                      if chunk_payload.meta.get("function_call")
                      else []
                  )
  
              # deltas is a list of ChoiceDeltaToolCall or ChoiceDeltaFunctionCall
              for i, delta in enumerate(deltas):
                  payload = payloads[i]
                  if is_tools_call:
                      payload["id"] = delta.id or payload["id"]
                      payload["type"] = delta.type or payload["type"]
                      if delta.function:
                          payload["function"]["name"] += (
                              delta.function.name or ""
                          )
                          payload["function"]["arguments"] += (
                              delta.function.arguments or ""
                          )
                  elif is_function_call:
                      payload["function"]["name"] += delta.name or ""
                      payload["function"]["arguments"] += (
                          delta.arguments or ""
                      )
          complete_response = ChatMessage.from_assistant(
              json.dumps(payloads)
          )
      else:
          complete_response = ChatMessage.from_assistant(
              "".join([chunk.content for chunk in chunks])
          )
      complete_response.meta.update(
          {
              "model": chunk.model,
              "index": 0,
              "finish_reason": chunk.choices[0].finish_reason,
              "usage": {},  # we don't have usage data for streaming responses
          }
      )
      return complete_response
  
imports: import copy
  import dataclasses
  import json
  import logging
  import warnings
  from typing import Optional, List, Callable, Dict, Any, Union
  from openai import OpenAI, Stream
  from openai.types.chat import ChatCompletionChunk, ChatCompletion, ChatCompletionMessage
  from openai.types.chat.chat_completion import Choice
  from openai.types.chat.chat_completion_chunk import Choice
  from haystack import component, default_from_dict, default_to_dict
  from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler
  from haystack.dataclasses import StreamingChunk, ChatMessage
label_desc: Use image node_id 7 for calling the OpenAIChatGenerator obj's underlying member method code with example usage: obj._connect_chunks(chunk, chunks) and returns: complete_response