docstr: Returns a list of acceptability guidelines that the input messages violate.
  
  :param messages: List of all messages by one speaker
  :param is_worker_0: True if `messages` represent the messages from the first
      speaker in the conversation
  :param violation_types: Set of all violation types to check messages for. See
      `self.ALL_VIOLATION_TYPES` for a list of all possible violation types.
  :return: comma-separated list of all violations
docstr_tok: ["Returns","a","list","of","acceptability","guidelines","that","the","input","messages","violate",".",":","param","messages",":","List","of","all","messages","by","one","speaker",":","param","is_worker_0",":","True","if","`","messages","`","represent","the","messages","from","the","first","speaker","in","the","conversation",":","param","violation_types",":","Set","of","all","violation","types","to","check","messages","for",".","See","`","self.ALL_VIOLATION_TYPES","`","for","a","list","of","all","possible","violation","types",".",":","return",":","comma-separated","list","of","all","violations"]
code: def check_messages(
      self,
      messages: List[str],
      is_worker_0: bool,
      violation_types: Iterable[str] = (),
  ) -> str:
      """
      Returns a list of acceptability guidelines that the input messages violate.
  
      :param messages: List of all messages by one speaker
      :param is_worker_0: True if `messages` represent the messages from the first
          speaker in the conversation
      :param violation_types: Set of all violation types to check messages for. See
          `self.ALL_VIOLATION_TYPES` for a list of all possible violation types.
      :return: comma-separated list of all violations
      """
  
      if any(
          [
              violation_type not in self.ALL_VIOLATION_TYPES
              for violation_type in violation_types
          ]
      ):
          raise ValueError(
              "One or more violation types are unrecognized!"
          )
  
      if len(messages) == 0:
          # There may have been a disconnect, so in this case let's give them a pass
          return ""
  
      violations = []
  
      # Do messages have the minimum acceptable average number of words?
      if "min_words" in violation_types:
          total_num_words = sum(
              [len(message.split()) for message in messages]
          )
          if (
              total_num_words / len(messages)
              < self.min_words_violation_threshold
          ):
              violations.append("under_min_length")
  
      # Does the first message start with a greeting, indicating that the Turker
      # hasn't understood the directions (i.e. continue along with the previous lines
      # of conversation)? Only penalize the worker who speaks first for this, because
      # the worker who speaks second should not be at fault if the first worker does
      # this and the second just follows along.
      if "penalize_greetings" in violation_types:
          greetings = [
              "hi",
              "hii",
              "hiii",
              "hiiii",
              "hai",
              "hello",
              "hey",
              "howdy",
              "greetings",
          ]
          if is_worker_0 and (
              sum(
                  [
                      messages[0].split()[0].lower() == greeting
                      for greeting in greetings
                  ]
              )
              > 0
          ):
              violations.append("starts_with_greeting")
  
      # Does the Turker tend to speak in all caps?
      if "all_caps" in violation_types:
          num_all_caps = sum(
              [message == message.upper() for message in messages]
          )
          if num_all_caps >= 2 or (
              num_all_caps == 1 and len(messages) == 1
          ):
              violations.append("too_much_all_caps")
  
      # Are later messages an exact match of the first one?
      if "exact_match" in violation_types:
          if len(messages) >= 2:
              c = messages[0]
              if exact_match(c, messages[1:]):
                  violations.append("exact_match")
  
      # Do the messages not pass the safety classifier?
      if "safety" in violation_types:
          for idx, message in enumerate(messages):
              if self.offensive_lang_detector.contains_offensive_language(
                  message
              ):
                  violations.append(f"unsafe:{idx+1:d}")
                  # The messages are 1-indexed
  
      return ",".join(violations)
  
file_path: ParlAI/parlai/crowdsourcing/utils/acceptability.py
imports: import re
  from typing import Iterable, List
  from parlai.utils.safety import OffensiveStringMatcher
label_desc: Use image node_id 2 for calling the AcceptabilityChecker obj's underlying member method code with example usage: obj.check_messages(messages, is_worker_0, violation_types) and returns: str, str