# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Utility functions for BIG-bench models.
"""

import re


def postprocess_output(text, max_length, stop_string, output_regex):
    """
    Modify model output to satisfy stop_string and output_regex keywords.

    Args:
      text: A string or list of strings containing model outputs.
      max_length: Model output will be truncated to be at most this length.
      stop_string: Model output will be truncated to the shortest string
        which includes stop_string. If None, no truncation will be performed.
        e.g. if stop_string='.', the model output "The apple is on the
        ground. What is" will be truncated to "The apple is on the ground."
        before being returned.
      output_regex: Rather than returning the full output, return the first
        match to the python regular expression output_regex in the output
        string. If there is no match, an empty string will be returned. If
        output_regex=None, no regular expression matching will be performed.
        e.g. if output_regex=r"\\d+", and the model output is "= 42. 7*7 =
        49. 7*8 =", then "42" will be returned.

    Returns: A string or list of strings, all processed as described for each
      argument.
    """

    if isinstance(text, list):
        return [
            postprocess_output(mo, max_length, stop_string, output_regex) for mo in text
        ]

    # Ensure it is a string (will convert from bytes, ... as needed)
    if not isinstance(text, str):
        text = str(text, "utf-8")

    # truncate at max_length
    if max_length:
        text = text[:max_length]

    # Remove all text after any stop_string
    if stop_string:
        index = text.find(stop_string)
        if index > 0:
            text = text[: index + len(stop_string)]

    # extract substring matching regex (empty string for no match)
    if output_regex:
        _text = text
        text = next(iter(re.findall(output_regex, text)), "")
        assert (
            not type(text) is tuple
        ), f'Regex {output_regex} returned multiple matching groups when applied to string {_text}. Try using non-capturing groups, by starting regex groups with ?: (e.g. "(stuff)" -> "(?:stuff)").'

    return text
