o
    6ti                     @   s  d Z ddlZddlZddlZddlZddlZddlZddlmZm	Z	m
Z
mZ ddlZddlmZ eeZe	eeeeee
e f f  ZejZdZdZdZdZd	Zd
ZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(G dd dZ)G dd de)Z*G dd de)Z+G dd de)Z,G dd de)Z-G dd de)Z.G dd  d e)Z/G d!d" d"e)Z0G d#d$ d$e)Z1G d%d& d&e)Z2G d'd( d(e)Z3G d)d* d*e)Z4G d+d, d,e)Z5G d-d. d.e)Z6G d/d0 d0e)Z7G d1d2 d2e)Z8G d3d4 d4e)Z9G d5d6 d6e)Z:G d7d8 d8e)Z;G d9d: d:e)Z<G d;d< d<e)Z=G d=d> d>e)Z>G d?d@ d@e)Z?G dAdB dBe)Z@G dCdD dDe)ZAG dEdF dFe)ZBG dGdH dHe)ZCG dIdJ dJe)ZDG dKdL dLe)ZEG dMdN dNe)ZFdS )OzLibrary of instructions.    N)DictOptionalSequenceUnion)instructions_util)z	less thanzat least         )zMy answer is yes.zMy answer is no.zMy answer is maybe.)zI would sayzMy answer isz	I believezIn my opinionzI thinkzI reckonzI feelzFrom my perspectivezAs I see itzAccording to mezAs far as I'm concernedzTo my understandingz
In my viewzMy take on it iszAs per my perception)zAny other questions?z'Is there anything else I can help with?)SectionSECTION)P.S.P.P.S      
   d   i  c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )InstructionzAn instruction template.c                 C   s
   || _ d S N)id)selfinstruction_id r   a/home/ubuntu/.local/lib/python3.10/site-packages/lm_eval/tasks/leaderboard/ifeval/instructions.py__init__q      
zInstruction.__init__c                 K      t d)Nz$`build_description` not implemented.NotImplementedError)r   kwargsr   r   r   build_descriptiont      zInstruction.build_descriptionc                 C   r   )Nz'`get_instruction_args` not implemented.r   r   r   r   r   get_instruction_argsw   r    z Instruction.get_instruction_argsc                 C   r   )Nz,`get_instruction_args_keys` not implemented.r   r!   r   r   r   get_instruction_args_keysz   r    z%Instruction.get_instruction_args_keysc                 C   r   )Nz"`check_following` not implemented.r   r   valuer   r   r   check_following}   r    zInstruction.check_followingN)	__name__
__module____qualname____doc__r   r   r"   r#   r&   r   r   r   r   r   n   s    r   c                   @   6   e Zd ZdZddddZdd Zdd	 Zd
d ZdS )ResponseLanguageCheckerz*Check the language of the entire response.Nlanguagec                C   s>   || _ | j du rttt | _ d| _| jjt| j  dS )a  Build the instruction description.

        Args:
          language: A string representing the expected language of the response. The
            language has to comply to the 97 types defined in
            `langid.py` (https://pypi.org/project/langid/1.1.5/), which follows
            ISO 639-1 codes (https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes);
            for example, `en` for English, `zh` for Chinese, `fr` for French.

        Returns:
          A string representing the instruction description.
        NzTYour ENTIRE response should be in {language} language, no other language is allowed.r-   )	_languagerandomchoicelist
_LANGUAGESkeys_description_patternformat)r   r.   r   r   r   r      s   
z)ResponseLanguageChecker.build_descriptionc                 C   
   d| j iS )0Returns the keyword args of `build_description`.r.   )r/   r!   r   r   r   r"         
z,ResponseLanguageChecker.get_instruction_argsc                 C      dgS )-Returns the args keys of `build_description`.r.   r   r!   r   r   r   r#         z1ResponseLanguageChecker.get_instruction_args_keysc              
   C   sX   t |tsJ z	t|| jkW S  tjy+ } ztd|| W Y d}~dS d}~ww )zCheck if the language of the entire response follows the instruction.

        Args:
          value: A string representing the response.

        Returns:
          True if the language of `value` follows instruction; otherwise False.
        /Unable to detect language for text %s due to %sNT)
isinstancestr
langdetectdetectr/   LangDetectExceptionloggingerrorr   r%   er   r   r   r&      s   	z'ResponseLanguageChecker.check_followingr'   r(   r)   r*   r   r"   r#   r&   r   r   r   r   r,          r,   c                   @   8   e Zd ZdZdddddZdd Zdd	 Zd
d ZdS )NumberOfSentenceszCheck the number of sentences.Nnum_sentencesrelationc                C   s|   || _ | j du s| j dk rtdt| _ |du rtt| _n|tvr.tdt d| d|| _d| _| jj	| j| j dS )	a:  Build the instruction description.

        Args:
          num_sentences: An integer specifying the number of sentences as a
            threshold.
          relation: A string in (`less than`, `at least`), defining the relational
            operator for comparison.
            Two relational comparisons are supported for now:
            if 'less than', the actual number of sentences < the threshold;
            if 'at least', the actual number of sentences >= the threshold.

        Returns:
          A string representing the instruction description.
        Nr      1The supported relation for comparison must be in , but 
 is given.zBYour response should contain {relation} {num_sentences} sentences.)rM   rL   )
_num_sentences_thresholdr0   randint_MAX_NUM_SENTENCESr1   _COMPARISON_RELATION_comparison_relation
ValueErrorr5   r6   )r   rL   rM   r   r   r   r      s(   z#NumberOfSentences.build_descriptionc                 C      | j | jdS )r8   rK   )rR   rV   r!   r   r   r   r"         z&NumberOfSentences.get_instruction_argsc                 C      ddgS )r;   rL   rM   r   r!   r   r   r   r#         z+NumberOfSentences.get_instruction_args_keysc                 C   >   t |}| jtd kr|| jk S | jtd kr|| jkS dS )aL  Check if the number of sentences follows the instruction.

        Args:
          value: A string representing the response.

        Returns:
          True if the response follows the instruction.

        Raise:
            ValueError if the string in `instruction_args` is not in
            [`less_than`, `at_least`].
        r   rN   N)r   count_sentencesrV   rU   rR   )r   r%   rL   r   r   r   r&      s   


z!NumberOfSentences.check_followingrG   r   r   r   r   rJ      s    &rJ   c                   @   r+   )PlaceholderCheckerz+Check the placeholders in template writing.Nnum_placeholdersc                C   >   || _ | j du s| j dk rtdt| _ d| _| jj| j dS )a  Build the instruction description.

        Args:
          num_placeholders: An integer denoting the minimum number of
            placeholders required in the response.

        Returns:
          A string representing the instruction description.
        Nr   rN   zuThe response must contain at least {num_placeholders} placeholders represented by square brackets, such as [address].r_   )_num_placeholdersr0   rS   _NUM_PLACEHOLDERSr5   r6   )r   r`   r   r   r   r     s   
z$PlaceholderChecker.build_descriptionc                 C   r7   )r8   r`   )rb   r!   r   r   r   r"     r9   z'PlaceholderChecker.get_instruction_argsc                 C   r:   )r;   r`   r   r!   r   r   r   r#     r<   z,PlaceholderChecker.get_instruction_args_keysc                 C   s   t d|}t|}|| jkS )a+  Check if the number of placeholders follows the instruction.

        Args:
          value: A string representing the response.

        Returns:
          True if the actual number of placeholders in the response is greater than
          or equal to `num_placeholders`; otherwise, False.
        z\[.*?\])refindalllenrb   )r   r%   placeholdersr`   r   r   r   r&     s   

z"PlaceholderChecker.check_followingrG   r   r   r   r   r^          r^   c                   @   r+   )BulletListCheckerz%Checks the bullet list in the prompt.Nnum_bulletsc                C   ra   )a  Build the instruction description.

        Args:
          num_bullets: An integer specifying the exact number of bullet lists
            that is required to appear in the response.

        Returns:
          A string representing the instruction description.
        Nr   rN   zYour answer must contain exactly {num_bullets} bullet points. Use the markdown bullet points such as:
* This is point 1. 
* This is point 2rj   )_num_bulletsr0   rS   _NUM_BULLETSr5   r6   )r   rk   r   r   r   r   0  s   
z#BulletListChecker.build_descriptionc                 C   r7   )r8   rk   )rl   r!   r   r   r   r"   E  r9   z&BulletListChecker.get_instruction_argsc                 C   r:   )r;   rk   r   r!   r   r   r   r#   I  r<   z+BulletListChecker.get_instruction_args_keysc                 C   s>   t jd|t jd}t jd|t jd}t|t| }|| jkS )aV  Check if the number of bullet lists meets the requirement.

        Args:
          value: A string representing the response. The response is expected to
            contain some bullet lists that start with `\*`.

        Returns:
          True if the actual number of bullet lists in the response meets the
          requirement.
        z^\s*\*[^\*].*$flagsz^\s*-.*$)rd   re   	MULTILINErf   rl   )r   r%   bullet_listsbullet_lists_2num_bullet_listsr   r   r   r&   M  s   
z!BulletListChecker.check_followingrG   r   r   r   r   ri   -      ri   c                   @   0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )ConstrainedResponseCheckerz Checks the constrained response.c                 C   s   t | _d| _| jj| jdS )"Build the instruction description.z<Answer with one of the following options: {response_options})response_options)_CONSTRAINED_RESPONSE_OPTIONS_constrained_responsesr5   r6   r!   r   r   r   r   a  s   z,ConstrainedResponseChecker.build_descriptionc                 C      dS r8   Nr   r!   r   r   r   r"   l     z/ConstrainedResponseChecker.get_instruction_argsc                 C      g S r;   r   r!   r   r   r   r#   p  r}   z4ConstrainedResponseChecker.get_instruction_args_keysc                 C   s&   |  }| jD ]	}||v r dS qdS )a  Checks if the response matches the constrained options.

        Args:
          value: A string representing the response.

        Returns:
          True if the actual response contains one of the options in the constrained
          responses; otherwise False.
        TF)striprz   )r   r%   constrained_responser   r   r   r&   t  s   

z*ConstrainedResponseChecker.check_followingNrG   r   r   r   r   rv   ^  s    rv   c                   @   r+   )ConstrainedStartCheckerzChecks the response start.Nstarterc                C   D   t |tr	| n|| _| jdu rtt| _d| _| jj| jdS )zBuild the instruction description.

        Args:
          starter: A string representing the keyword that the response should start
            with.

        Returns:
          A string representing the instruction description.
        NzQDuring the conversation, when it is your turn, please always start with {starter}r   )	r>   r?   r   _starterr0   r1   _STARTER_OPTIONSr5   r6   )r   r   r   r   r   r     s   

z)ConstrainedStartChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"     r9   z,ConstrainedStartChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#     r<   z1ConstrainedStartChecker.get_instruction_args_keysc                 C   s,   d| j  d }tj||tjd}|rdS dS )a0  Checks if the response starts with the constrained keyword or phrase.

        Args:
          value: A string representing the response.

        Returns:
          True if the response starts with the given phrase or keyword that is
          contained in `instruction_args`; otherwise, False.
        z^\s*.*$rn   TF)r   rd   searchrp   )r   r%   response_patternresponse_with_constrained_startr   r   r   r&     s
   
z'ConstrainedStartChecker.check_followingrG   r   r   r   r   r     rh   r   c                   @   r+   )HighlightSectionCheckerzChecks the highlighted section.Nnum_highlightsc                C   ra   )zBuild the instruction description.

        Args:
          num_highlights: An integer specifying the minimum number of highlighted
            sections.

        Returns:
          A string representing the instruction description.
        Nr   rN   zfHighlight at least {num_highlights} sections in your answer with markdown, i.e. *highlighted section*.r   )_num_highlightsr0   rS   _NUM_HIGHLIGHTED_SECTIONSr5   r6   )r   r   r   r   r   r     s   
z)HighlightSectionChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"     r9   z,HighlightSectionChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#     r<   z1HighlightSectionChecker.get_instruction_args_keysc                 C   sl   d}t d|}t d|}|D ]}|d r|d7 }q|D ]}|dd r0|d7 }q || jkS )a  Checks if the number of highlighted sections meets the requirement.

        Args:
          value: a string representing the response. The response is expected to
            contain highlighted sections in the format of *highlighted*.

        Returns:
          True if the actual number of highlighted sections in the format of
          *highlighted sections* meets the minimum requirement; otherwise False.
        r   z\*[^\n\*]*\*z\*\*[^\n\*]*\*\**rN   z**)rd   re   r   removeprefixremovesuffixr   )r   r%   r   
highlightsdouble_highlights	highlightr   r   r   r&     s   
z'HighlightSectionChecker.check_followingrG   r   r   r   r   r     rt   r   c                   @   rI   )SectionCheckerzChecks the sections.Nsection_spliternum_sectionsc                C   sp   t |tr	| n|| _| jdu rtt| _|| _| jdu s$| jdk r+tdt	| _d| _
| j
j| j| jdS )a^  Build the instruction description.

        Args:
          section_spliter: A string represents the section spliter keyword that
            marks a new section, i.e., `Section` or `SECTION`.
          num_sections: An integer specifying the number of sections.

        Returns:
          A string representing the instruction description.
        Nr   rN   zYour response must have {num_sections} sections. Mark the beginning of each section with {section_spliter} X, such as:
{section_spliter} 1
[content of section 1]
{section_spliter} 2
[content of section 2])r   r   )r>   r?   r   _section_spliterr0   r1   _SECTION_SPLITER_num_sectionsrS   _NUM_SECTIONSr5   r6   )r   r   r   r   r   r   r     s   

	z SectionChecker.build_descriptionc                 C   rX   )r8   r   )r   r   r!   r   r   r   r"     rY   z#SectionChecker.get_instruction_argsc                 C   rZ   )r;   r   r   r   r!   r   r   r   r#     r[   z(SectionChecker.get_instruction_args_keysc                 C   s0   d| j  d }t||}t|d }|| jkS )a  Checks the response contains multiple sections.

        Args:
          value: A string representing the response. The response is expected
            to contain multiple sections (number of sections is greater than 1).
            A new section starts with `Section 1`, where the number denotes the
            section index.

        Returns:
          True if the number of sections in the response is greater than or equal to
          the minimum number of sections; otherwise, False.
        z\s?z	\s?\d+\s?rN   )r   rd   splitrf   r   )r   r%   section_splitter_pattensectionsr   r   r   r   r&     s   
zSectionChecker.check_followingrG   r   r   r   r   r     s    $r   c                   @   r+   )ParagraphCheckerzChecks the paragraphs.Nnum_paragraphsc                C   ra   )zBuild the instruction description.

        Args:
          num_paragraphs: An integer specifying the number of paragraphs.

        Returns:
          A string representing the instruction description.
        Nr   rN   zdThere should be {num_paragraphs} paragraphs. Paragraphs are separated with the markdown divider: ***r   )_num_paragraphsr0   rS   _NUM_PARAGRAPHSr5   r6   )r   r   r   r   r   r   4  s   	z"ParagraphChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"   H  r9   z%ParagraphChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#   L  r<   z*ParagraphChecker.get_instruction_args_keysc                 C   s`   t d|}t|}t|D ]\}}| s*|dks"|t|d kr'|d8 }q dS q|| jkS )ad  Checks the response contains required number of paragraphs.

        Args:
          value: A string representing the response. The response may contain
            paragraphs that are separated by the markdown divider: `***`.

        Returns:
          True if the actual number of paragraphs is the same as required;
          otherwise, False.
        z\s?\*\*\*\s?r   rN   F)rd   r   rf   	enumerater   r   )r   r%   
paragraphsr   index	paragraphr   r   r   r&   P  s   

z ParagraphChecker.check_followingrG   r   r   r   r   r   1  s    r   c                   @   r+   )PostscriptCheckerzChecks the postscript.N)postscript_markerc                C   r   )a  Build the instruction description.

        Args:
          postscript_marker: A string containing the keyword that marks the start
            of the postscript section.

        Returns:
          A string representing the instruction description.
        NzZAt the end of your response, please explicitly add a postscript starting with {postscript})
postscript)	r>   r?   r   _postscript_markerr0   r1   _POSTSCRIPT_MARKERr5   r6   )r   r   r   r   r   r   k  s   

z#PostscriptChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"     r9   z&PostscriptChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#     r<   z+PostscriptChecker.get_instruction_args_keysc                 C   sX   |  }| jdkrd}n| jdkrd}n	d| j   d }tj||tjd}|r*dS d	S )
ar  Checks if the response follows the postscript format.

        Args:
          value: a string representing the response. The response is expected to
            contain a postscript section.

        Returns:
          True if the response contains a postscript section starting with
          the keyword containing in the `instruction_args`; otherwise False.
        r   z\s*p\.\s?p\.\s?s.*$r   z\s*p\.\s?s\..*$z\s*r   rn   TF)lowerr   rd   re   rp   )r   r%   postscript_patternr   r   r   r   r&     s   

z!PostscriptChecker.check_followingrG   r   r   r   r   r   h  s    r   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )RephraseCheckerzChecks the rephrase.c                C   s,   |  |std| d|| _d| _| jS )a  Build the instruction description.

        Args:
          original_message: A string representing the original message. The
            rephrased response should only change its words/sentences in between
            its two asterisks, for example, *change me*. Both original and rephrased
            messages should contain the changes in the form of *change me*.

        Returns:
          A string representing the instruction description.
        zMessage 5 does not contain changes in the form of *change me*.zvRephrasing: Your rephrased response should onlychange the words/sentences in between two asteriskssuch as *change me*.)	is_changerW   _reference_without_change_description)r   original_messager   r   r   r     s   

z!RephraseChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"     r9   z$RephraseChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#     r<   z)RephraseChecker.get_instruction_args_keysc                 C   s8   |  |std| d| |}| | j}||kS )ay  Checks if the rephrasing follows the instruction.

        Args:
          value: A string representing the response, which is expected to rephras
            the string of `instruction_args`.

        Returns:
          True if `value` and `instruction_args` only differ by the words/sentences
          in between two asterisks such as *change me*; otherwise, False.
        zvalue r   )r   rW   strip_changesr   )r   r%   response_without_changesreference_without_changesr   r   r   r&     s   


zRephraseChecker.check_followingc                 C   s   t d|S )zDCheck if there is change in the response in the form of *change me*.\*.*\*rd   r   r   responser   r   r   r     s   zRephraseChecker.is_changec                 C   s   t dd|S )zStrips off the changes.r    )rd   subr   r   r   r   r        zRephraseChecker.strip_changesN)
r'   r(   r)   r*   r   r"   r#   r&   r   r   r   r   r   r   r     s    r   c                   @   r+   )KeywordCheckerz)Check the exisitence of certain keywords.Nkeywordsc                C   s<   |s
t jtd| _n|| _t| j| _d| _| jj| jdS )zBuild the instruction description.

        Args:
          keywords: A sequence of strings representing the keywords that are
            expected in the response.

        Returns:
          A string representing the instruction description.
        num_keywordsz,Include keywords {keywords} in the response.r   )r   generate_keywords_NUM_KEYWORDS	_keywordssortedr5   r6   )r   r   r   r   r   r     s   
z KeywordChecker.build_descriptionc                 C   r7   )r8   r   )r   r!   r   r   r   r"      r9   z#KeywordChecker.get_instruction_argsc                 C   r:   )r;   r   r   r!   r   r   r   r#     r<   z(KeywordChecker.get_instruction_args_keysc                 C   s(   | j D ]}tj||tjds dS qdS )z4Check if the response contain the expected keywords.rn   FT)r   rd   r   
IGNORECASE)r   r%   keywordr   r   r   r&     s
   
zKeywordChecker.check_followingrG   r   r   r   r   r     rH   r   c                   @   :   e Zd ZdZddddddZdd Zdd	 Zd
d ZdS )KeywordFrequencyCheckerzCheck the keyword frequency.Nr   	frequencyrM   c                C   s   |st jddd | _n| | _|| _| jdu s| jdk r%tdt| _|du r0tt	| _
n|t	vr?tdt	 d| d|| _
d| _| jj| j| j
| jd	S )
a  Build the instruction description.

        Args:
          keyword: A string representing a keyword that is expected in the response.
          frequency: An integer specifying the number of times `keyword` is expected
            to appear in the response.
          relation: A string in (`less than`, `at least`), defining the relational
            operator for comparison.
            Two relational comparisons are supported for now:
            if 'less than', the actual number of occurrences < frequency;
            if 'at least', the actual number of occurrences >= frequency.

        Returns:
          A string representing the instruction description.
        rN   r   r   NrO   rP   rQ   zPIn your response, the word {keyword} should appear {relation} {frequency} times.)r   rM   r   )r   r   _keywordr   
_frequencyr0   rS   _KEYWORD_FREQUENCYr1   rU   rV   rW   r5   r6   )r   r   r   rM   r   r   r   r     s0   
z)KeywordFrequencyChecker.build_descriptionc                 C      | j | j| jdS )r8   r   )r   r   rV   r!   r   r   r   r"   A     z,KeywordFrequencyChecker.get_instruction_argsc                 C      g dS )r;   r   r   r!   r   r   r   r#   I  r[   z1KeywordFrequencyChecker.get_instruction_args_keysc                 C   sL   t tj| j|tjd}| jtd kr|| jk S | jtd kr$|| jkS dS )zCChecks if the response contain the keyword with required frequency.rn   r   rN   N)rf   rd   re   r   r   rV   rU   r   )r   r%   actual_occurrencesr   r   r   r&   M  s   

z'KeywordFrequencyChecker.check_followingrG   r   r   r   r   r     s    .r   c                   @   rI   )NumberOfWordszChecks the number of words.N	num_wordsrM   c                C   s|   || _ | j du s| j dk rttt| _ |du rtt| _n|tvr.tdt d| d|| _d| _	| j	j
| j| j dS )a-  Build the instruction description.

        Args:
          num_words: An integer specifying the number of words contained in the
            response.
          relation: A string in (`less than`, `at least`), defining the relational
            operator for comparison.
            Two relational comparisons are supported for now:
            if 'less than', the actual number of words < num_words;
            if 'at least', the actual number of words >= num_words.

        Returns:
          A string representing the instruction description.
        Nr   rO   rP   rQ   z)Answer with {relation} {num_words} words.)rM   r   )
_num_wordsr0   rS   _NUM_WORDS_LOWER_LIMIT_NUM_WORDS_UPPER_LIMITr1   rU   rV   rW   r5   r6   )r   r   rM   r   r   r   r   Z  s(   zNumberOfWords.build_descriptionc                 C   rX   )r8   r   )r   rV   r!   r   r   r   r"     r   z"NumberOfWords.get_instruction_argsc                 C   rZ   )r;   r   rM   r   r!   r   r   r   r#     r[   z'NumberOfWords.get_instruction_args_keysc                 C   r\   )z=Checks if the response contains the expected number of words.r   rN   N)r   count_wordsrV   rU   r   )r   r%   r   r   r   r   r&     s   


zNumberOfWords.check_followingrG   r   r   r   r   r   W  s    &r   c                   @   ru   )
JsonFormatzCheck the Json format.c                 C      d| _ | j S )NzWEntire output should be wrapped in JSON format. You can use markdown ticks such as ```.r5   r!   r   r   r   r     s   zJsonFormat.build_descriptionc                 C   r{   r|   r   r!   r   r   r   r"     r}   zJsonFormat.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#     r}   z$JsonFormat.get_instruction_args_keysc                 C   sP   |  ddddd  }zt| W dS  ty'   Y dS w )Nz```jsonz```Jsonz```JSONz```FT)r   r   r   jsonloadsrW   r$   r   r   r   r&     s   	zJsonFormat.check_followingNrG   r   r   r   r   r         r   c                   @   s4   e Zd ZdZ	dddZdd Zdd Zd	d
 ZdS )ParagraphFirstWordCheckz<Check the paragraph and the first word of the nth paragraph.Nc                 C   s   || _ | j du s| j dk rtdt| _ || _| jdu s'| jdks'| j| j kr1td| j d | _|| _| jdu rBtjddd | _| j | _d| _	| j	j
| j | j| jdS )a%  Build the instruction description.

        Args:
          num_paragraphs: An integer indicating the number of paragraphs expected
            in the response. A paragraph is a subset of the string that is
            expected to be separated by '\n\n'.
          nth_paragraph: An integer indicating the paragraph number that we look at.
            Note that n starts from 1.
          first_word: A string that represent the first word of the bth paragraph.

        Returns:
          A string representing the instruction description.
        Nr   rN   r   zThere should be {num_paragraphs} paragraphs. Paragraphs and only paragraphs are separated with each other by two new lines as if it was '\n\n' in python. Paragraph {nth_paragraph} must start with word {first_word}.r   nth_paragraph
first_word)r   r0   rS   r   _nth_paragraph_first_wordr   r   r   r5   r6   )r   r   r   r   r   r   r   r     s&   


z)ParagraphFirstWordCheck.build_descriptionc                 C   r   )r8   r   )r   r   r   r!   r   r   r   r"     r   z,ParagraphFirstWordCheck.get_instruction_argsc                 C   r   )r;   r   r   r!   r   r   r   r#     r[   z1ParagraphFirstWordCheck.get_instruction_args_keysc           	      C   s   t d|}t|}|D ]
}| s|d8 }q| j|kr*|| jd   }|s)dS ndS d}h d}| d  }|d}|d}|D ]}||v rN n|| 7 }qF|| jko^|| jkS )	a  Checks for required number of paragraphs and correct first word.

        Args:
          value: a string representing the response. The response may contain
            paragraphs that are separated by two new lines and the first word of
            the nth paragraph will have to match a specified word.

        Returns:
          True if the number of paragraphs is the same as required and the first
          word of the specified paragraph is the same as required. Otherwise, false.
        z\n\nrN   Fr   >   .!"',?r   r   r   )	rd   r   rf   r   r   lstripr   r   r   )	r   r%   r   r   r   r   punctuationwordletterr   r   r   r&     s,   


z'ParagraphFirstWordCheck.check_following)NNNrG   r   r   r   r   r     s    
.r   c                   @   2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )KeySentenceCheckerz-Check the existence of certain key sentences.Nc                 C   sR   |s	t dg| _n|| _|stdt| j| _n|| _d| _| jj| j| jdS )av  Build the instruction description.

        Args:
          key_sentences: A sequences of strings representing the key sentences that
            are expected in the response.
          num_sentences: The number of key sentences that are expected to be seen in
            the response.

        Returns:
          A string representing the instruction description.
        zFor now, this is fine.rN   zBInclude {num_sentences} of the following sentences {key_sentences}rL   key_sentences)set_key_sentencesr0   rS   rf   _num_sentencesr5   r6   )r   r   rL   r   r   r   r   #  s   z$KeySentenceChecker.build_descriptionc                 C   s   | j t| jdS )r8   r   )r   r2   r   r!   r   r   r   r"   C  s   z'KeySentenceChecker.get_instruction_argsc                 C   rZ   )r;   rL   r   r   r!   r   r   r   r#   J  r[   z,KeySentenceChecker.get_instruction_args_keysc                 C   s4   d}t |}| jD ]
}||v r|d7 }q
|| jkS )z;Checks if the response contains the expected key sentences.r   rN   )r   split_into_sentencesr   r   )r   r%   count	sentencessentencer   r   r   r&   N  s   


z"KeySentenceChecker.check_followingNNrG   r   r   r   r   r      s    
 r   c                   @   r   )ForbiddenWordsz5Checks that specified words are not used in response.Nc                 C   sD   |s
t jtd| _ntt|| _t| j| _d| _| jj| jdS )a   Build the instruction description.

        Args:
          forbidden_words: A sequences of strings representing words that are not
            allowed in the response.

        Returns:
          A string representing the instruction description.
        r   z:Do not include keywords {forbidden_words} in the response.)forbidden_words)	r   r   r   _forbidden_wordsr2   r   r   r5   r6   )r   r  r   r   r   r   \  s   
z ForbiddenWords.build_descriptionc                 C   r7   )r8   r  )r  r!   r   r   r   r"   t  r9   z#ForbiddenWords.get_instruction_argsc                 C   r:   )r;   r  r   r!   r   r   r   r#   x  r<   z(ForbiddenWords.get_instruction_args_keysc                 C   s0   | j D ]}tjd| d |tjdr dS qdS )z=Check if the response does not contain the expected keywords.z\brn   FT)r  rd   r   r   )r   r%   r   r   r   r   r&   |  s
   
zForbiddenWords.check_followingr   rG   r   r   r   r   r  Y  s    
r  c                   @   ru   )RephraseParagraphz'Checks that the paragraph is rephrased.c                C   s.   || _ || _|| _d| _| jj|| j| jdS )a  Builds the instruction description.

        Args:
          original_paragraph: A string presenting the original paragraph. The
            rephrases response should have betweeb low-high words in common.
          low: An integer presenting the lower bound of similar words.
          high: An integer representing the upper bound of similar words.

        Returns:
          A string representing the instruction description.
        a  Rephrase the following paragraph: {original_paragraph}
Your response should have between {low} and {high} of the same words. Words are the same if and only if all of the letters, ignoring cases, are the same. For example, 'run' is the same as 'Run' but different to 'ran'.original_paragraphlowhigh)_original_paragraph_low_highr   r6   )r   r  r  r  r   r   r   r     s   

z#RephraseParagraph.build_descriptionc                 C   r   )r8   r  )r	  r
  r  r!   r   r   r   r"     r   z&RephraseParagraph.get_instruction_argsc                 C   r   )r;   r  r   r!   r   r   r   r#     r[   z+RephraseParagraph.get_instruction_args_keysc                 C   sn   t d| }t d| j }d}t|}t|}|D ]}|t|| || 7 }q|| jko6|| jkS )Nz\w+r   )	rd   re   r   r	  collectionsCounterminr
  r  )r   r%   	val_wordsoriginal_wordssimilar_wordsdict_valdict_originalr   r   r   r   r&     s   

z!RephraseParagraph.check_followingNrG   r   r   r   r   r    s    r  c                   @   ru   )TwoResponsesCheckerz$Check that two responses were given.c                 C   r   )rw   zmGive two different responses. Responses and only responses should be separated by 6 asterisk symbols: ******.r   r!   r   r   r   r        z%TwoResponsesChecker.build_descriptionc                 C   r{   r|   r   r!   r   r   r   r"     r}   z(TwoResponsesChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#     r}   z-TwoResponsesChecker.get_instruction_args_keysc                 C   sx   t  }|d}t|D ]\}}| s$|dkr#|t|d kr# dS q|| qt|dko;|d  |d  kS )zChecks if the response has two different answers.

        Args:
          value: A string representing the response.

        Returns:
          True if two responses are detected and false otherwise.
        z******r   rN   Fr   )r2   r   r   r   rf   append)r   r%   valid_responses	responsesr   r   r   r   r   r&     s   	
z#TwoResponsesChecker.check_followingNrG   r   r   r   r   r    s    r  c                   @   r+   )RepeatPromptThenAnswerz3Checks that Prompt is first repeated then answered.N)prompt_to_repeatc                C   s   |st d|| _d| _| jS )zBuild the instruction description.

        Args:
          prompt_to_repeat: The prompt that is meant to be repeated.

        Returns:
          A string representing the instruction description.
        zprompt_to_repeat must be set.zFirst repeat the request word for word without change, then give your answer (1. do not say any words or characters before repeating the request; 2. the request you need to repeat does not include this sentence))rW   _prompt_to_repeatr5   )r   r  r   r   r   r     s   	z(RepeatPromptThenAnswer.build_descriptionc                 C   r7   )Nr  )r  r!   r   r   r   r"     r   z+RepeatPromptThenAnswer.get_instruction_argsc                 C   r:   )r;   r  r   r!   r   r   r   r#     r<   z0RepeatPromptThenAnswer.get_instruction_args_keysc                 C   s$   |   | j   rdS dS )NTF)r   r   
startswithr  r$   r   r   r   r&   	  s   z&RepeatPromptThenAnswer.check_followingrG   r   r   r   r   r    s    r  c                   @   r+   )
EndCheckerz0Checks that the prompt ends with a given phrase.N)
end_phrasec                C   r   )zBuild the instruction description.

        Args:
          end_phrase: A string representing the phrase the response should end with.

        Returns:
          A string representing the instruction description.
        Nz^Finish your response with this exact phrase {ender}. No other words should follow this phrase.)ender)	r>   r?   r   _end_phraser0   r1   _ENDING_OPTIONSr5   r6   )r   r  r   r   r   r     s   

zEndChecker.build_descriptionc                 C   r7   )Nr  )r   r!   r   r   r   r"   &  r   zEndChecker.get_instruction_argsc                 C   r:   )r;   r  r   r!   r   r   r   r#   )  r<   z$EndChecker.get_instruction_args_keysc                 C   s.   |   d }| j   | _|| jS )z5Checks if the response ends with the expected phrase.r   )r   r   r   endswithr$   r   r   r   r&   -  s   zEndChecker.check_followingrG   r   r   r   r   r    s    r  c                   @   ru   )TitleCheckerz Checks the response for a title.c                 C   r   )rw   z^Your answer must contain a title, wrapped in double angular brackets, such as <<poem of joy>>.r   r!   r   r   r   r   7  r  zTitleChecker.build_descriptionc                 C      d S r   r   r!   r   r   r   r"   ?     z!TitleChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#   B  r}   z&TitleChecker.get_instruction_args_keysc                 C   sB   d}t |}t ||}|D ]}|dd r dS qdS )z(Checks if the response contains a title.z
<<[^\n]+>><>TF)rd   compilere   r   rstripr   )r   r%   pattern
re_patterntitlestitler   r   r   r&   F  s   
zTitleChecker.check_followingNrG   r   r   r   r   r#  4      r#  c                   @   r   )LetterFrequencyCheckerzChecks letter frequency.Nr   let_frequencylet_relationc                C   s   |rt |dkst| dk st| dkr"tttj| _n|	 | _| j | _|| _
| j
du s:| j
dk rAtdt| _
|du rLtt| _n|tvr[tdt d| d|| _d	| _| jj| j| j
| jd
S )a  Build the instruction description.

        Args:
          letter: A string representing a letter that is expected in the response.
          let_frequency: An integer specifying the number of times `keyword` is
            expected to appear in the response.
          let_relation: A string in (`less than`, `at least`), defining the
            relational operator for comparison. Two relational comparisons are
            supported for now; if 'less than', the actual number of
            occurrences < frequency; if 'at least', the actual number of
            occurrences >= frequency.

        Returns:
          A string representing the instruction description.
        rN   a   z   Nr   rO   rP   rQ   zYIn your response, the letter {letter} should appear {let_relation} {let_frequency} times.r0  )rf   ordr   r0   r1   r2   stringascii_letters_letterr   r   rS   _LETTER_FREQUENCYrU   rV   rW   r5   r6   )r   r   r1  r2  r   r   r   r   U  s:   
z(LetterFrequencyChecker.build_descriptionc                 C   r   ).Returns the keyword args of build description.r0  )r8  r   rV   r!   r   r   r   r"     r   z+LetterFrequencyChecker.get_instruction_argsc                 C   r   )r;   r0  r   r!   r   r   r   r#     r[   z0LetterFrequencyChecker.get_instruction_args_keysc                 C   s@   |  }t|}| jtd kr|| j | jk S || j | jkS )zDChecks that the response contains the letter at the right frequency.r   )r   r  r  rV   rU   r8  r   )r   r%   lettersr   r   r   r&     s
   
z&LetterFrequencyChecker.check_followingrG   r   r   r   r   r/  R  s    4r/  c                   @   ru   )CapitalLettersEnglishCheckerzEChecks that the response is in english and is in all capital letters.c                 C   r   )rw   zFYour entire response should be in English, and in all capital letters.r   r!   r   r   r   r        z.CapitalLettersEnglishChecker.build_descriptionc                 C   r$  r   r   r!   r   r   r   r"     r%  z1CapitalLettersEnglishChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#     r}   z6CapitalLettersEnglishChecker.get_instruction_args_keysc              
   C   ^   t |tsJ z| ot|dkW S  tjy. } ztd|| W Y d}~dS d}~ww )zBChecks that the response is in English and in all capital letters.enr=   NT)r>   r?   isupperr@   rA   rB   rC   rD   rE   r   r   r   r&        z,CapitalLettersEnglishChecker.check_followingNrG   r   r   r   r   r<        r<  c                   @   ru   )LowercaseLettersEnglishCheckerzGChecks that the response is in english and is in all lowercase letters.c                 C   r   )rw   zhYour entire response should be in English, and in all lowercase letters. No capital letters are allowed.r   r!   r   r   r   r     r  z0LowercaseLettersEnglishChecker.build_descriptionc                 C   r$  r   r   r!   r   r   r   r"     r%  z3LowercaseLettersEnglishChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#     r}   z8LowercaseLettersEnglishChecker.get_instruction_args_keysc              
   C   r>  )zDChecks that the response is in English and in all lowercase letters.r?  r=   NT)r>   r?   islowerr@   rA   rB   rC   rD   rE   r   r   r   r&     rA  z.LowercaseLettersEnglishChecker.check_followingNrG   r   r   r   r   rC    r.  rC  c                   @   ru   )CommaCheckerz"Checks the response for no commas.c                 C   r   )rw   z<In your entire response, refrain from the use of any commas.r   r!   r   r   r   r     r=  zCommaChecker.build_descriptionc                 C   r$  r   r   r!   r   r   r   r"     r%  z!CommaChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#     r}   z&CommaChecker.get_instruction_args_keysc                 C   s   t d| S )z1Checks that the response does not contain commas.z\,r   r$   r   r   r   r&     r   zCommaChecker.check_followingNrG   r   r   r   r   rE    rB  rE  c                   @   s6   e Zd ZdZ		dddZdd Zdd Zd	d
 ZdS )CapitalWordFrequencyCheckerz3Checks frequency of words with all capital letters.Nc                 C   sr   || _ | j du rtdt| _ || _|du rtt| _n|tvr,tdt d| dd| _| jj	| j | jdS )aw  Build the instruction description.

        Args:
          capital_frequency: An integer that represents the number of words that
            should be in all capital letters.
          capital_relation: A string that is 'at least' or 'at most' that refers to
            the frequency.

        Returns:
          A string representing the instruction description.
        NrN   rO   rP   rQ   z\In your response, words with all capital letters should appear {relation} {frequency} times.)r   rM   )
r   r0   rS   _ALL_CAPITAL_WORD_FREQUENCYrV   r1   rU   rW   r5   r6   )r   capital_frequencycapital_relationr   r   r   r     s&   
z-CapitalWordFrequencyChecker.build_descriptionc                 C   rX   )r:  )rH  rI  )r   rV   r!   r   r   r   r"     rY   z0CapitalWordFrequencyChecker.get_instruction_argsc                 C   rZ   )r;   rH  rI  r   r!   r   r   r   r#   %  r[   z5CapitalWordFrequencyChecker.get_instruction_args_keysc                 C   sD   t j|}dd |D }t|}| jtd kr|| jk S || jkS )z7Checks the frequency of words with all capital letters.c                 S   s   g | ]}|  r|qS r   )r@  ).0r   r   r   r   
<listcomp>-  s    z?CapitalWordFrequencyChecker.check_following.<locals>.<listcomp>r   )r   nltkword_tokenizerf   rV   rU   r   )r   r%   wordscapital_wordsr   r   r   r&   )  s   

z+CapitalWordFrequencyChecker.check_followingr   rG   r   r   r   r   rF    s    
&rF  c                   @   ru   )QuotationCheckerz7Checks response is wrapped with double quotation marks.c                 C   r   )rw   z6Wrap your entire response with double quotation marks.r   r!   r   r   r   r   :  r=  z"QuotationChecker.build_descriptionc                 C   r{   )r:  Nr   r!   r   r   r   r"   A  r}   z%QuotationChecker.get_instruction_argsc                 C   r~   r   r   r!   r   r   r   r#   E  r}   z*QuotationChecker.get_instruction_args_keysc                 C   s,   |  }t|dko|d dko|d dkS )z>Checks if the response is wrapped with double quotation marks.rN   r   r   )r   rf   r$   r   r   r   r&   I  s   $z QuotationChecker.check_followingNrG   r   r   r   r   rP  7  r   rP  )Gr*   r  r   rC   r0   rd   r6  typingr   r   r   r   r@   lm_eval.tasks.ifevalr   	getLoggerr'   loggerr?   int_InstructionArgsDtypeLANGUAGE_CODESr3   rU   rT   rc   rm   ry   r   r!  r   r   r   r   r   r   r   r9  rG  r   r   r   r,   rJ   r^   ri   rv   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r#  r/  r<  rC  rE  rF  rP  r   r   r   r   <module>   sz   
7H-1'/8E7:D*G;#k9+<*%%N B