Download augmentoolkit/generation_functions/process_multiturn_functions.py from Leon4gr45/agent-0: direct link, hf CLI and curl.
- Browser
- Download file 18.3 kB
-
https://huggingface.co/spaces/Leon4gr45/agent-0/resolve/main/augmentoolkit/generation_functions/process_multiturn_functions.py
- Command line
-
hf download hf://spaces/Leon4gr45/agent-0/augmentoolkit/generation_functions/process_multiturn_functions.py
-
curl -L -o process_multiturn_functions.py https://huggingface.co/spaces/Leon4gr45/agent-0/resolve/main/augmentoolkit/generation_functions/process_multiturn_functions.py
18.3 kB
| import re | |
| def has_sequential_chars(string1, string2, n): | |
| """ | |
| Check if any n sequential characters from string1 appear in string2. | |
| Args: | |
| string1 (str): The first string to check. | |
| string2 (str): The second string in which to look for sequences. | |
| n (int): The length of the sequence to check. | |
| Returns: | |
| bool: True if any n sequential characters from string1 are found in string2, False otherwise. | |
| """ | |
| # Check if n is larger than the length of string1. | |
| if n > len(string1): | |
| return False, "" | |
| # Iterate over string1 and check for each n-length substring in string2 | |
| comparison_string = "" | |
| for i in range(len(string1) - n + 1): | |
| comparison_string = string1[i : i + n] | |
| if comparison_string in string2: | |
| return True, comparison_string | |
| return False, comparison_string | |
| def extract_conversation(conversation): | |
| """ | |
| Extracts conversation from a string and returns it as a list of tuples. | |
| Parameters: | |
| conversation (str): A string representing the conversation. | |
| Returns: | |
| list of tuples: Each tuple contains the character's name and their message. | |
| """ | |
| lines = conversation.strip().split("\n") | |
| dialogues = [] | |
| current_speaker = None | |
| current_message = "" | |
| for line in lines: | |
| line = line.strip() | |
| if line in ["**AI Assistant:**", "**User:**"]: | |
| if current_speaker: | |
| dialogues.append((current_speaker, current_message.strip())) | |
| current_message = "" | |
| current_speaker = line[2:-2].strip() | |
| else: | |
| if current_speaker: | |
| current_message += line + "\n" | |
| if current_speaker: | |
| dialogues.append((current_speaker, current_message.strip())) | |
| return dialogues | |
| def compare_answers_with_qatuples(dialogues, qatuples, n): | |
| """ | |
| Compares each answer in dialogues with the corresponding answer from qatuples. | |
| Parameters: | |
| dialogues (list): List of tuples containing the dialogues. | |
| qatuples (list): List of tuples containing questions and answers. | |
| n (int): Number of sequential characters to check. | |
| Returns: | |
| bool: True if all answers match the corresponding answers in qatuples, False otherwise. | |
| """ | |
| truth_list = [] | |
| for i in range(1, len(dialogues), 2): # Answers are at odd indices, starting from 1 | |
| if (i - 1) // 2 >= len( | |
| qatuples | |
| ): # at this point we've reached added stuff that doesn't have a corresponding qatuple | |
| break | |
| sequential, comp = has_sequential_chars( | |
| qatuples[(i - 1) // 2][1], dialogues[i][1], n | |
| ) | |
| # print(sequential) | |
| # print(n) | |
| truth_list.append(sequential) | |
| if all(truth_list): | |
| return True | |
| # Account for the case where the AI has an initial back-and-forth with no questions asked or answered. In this case, answers start at 3. | |
| for i in range(3, len(dialogues), 2): | |
| if (i - 2) // 2 >= len(qatuples): | |
| break | |
| sequential, comp = has_sequential_chars( | |
| qatuples[(i - 2) // 2][1], dialogues[i][1], n | |
| ) | |
| if not sequential: | |
| print( | |
| f"Answer {(i + 1) // 2}: {dialogues[i][1]} does not match the corresponding answer in qatuples: {qatuples[(i - 1) // 2][1]}, {comp}" | |
| ) | |
| return False | |
| return True | |
| # def check_repeated_answer(dialogues, qatuples): | |
| # # Get the length of the dialogues | |
| # conv_length = len(dialogues) | |
| # # Loop through even indices starting from 2 (first answer is at index 2) | |
| # for i in range(2, conv_length, 2): | |
| # current_answer = dialogues[i][1][:n_characters_same] | |
| # next_answer_index = i + 2 | |
| # if next_answer_index < conv_length: | |
| # next_answer = dialogues[next_answer_index][1][:n_characters_same] | |
| # if current_answer == next_answer: | |
| # return False | |
| # return True | |
| def check_conversation_length(conv, qatuples): | |
| """Checks the length of the conversation""" | |
| # Dialogues with answers should be at even indices that are not 0 | |
| # qatuples are of the format (question, answer,source_text,name_of_text) -- only the first two are used here | |
| # Get the length of the dialogues | |
| conv_length = len(conv) | |
| target_length = len(qatuples) * 2 | |
| if ( | |
| conv_length < target_length | |
| ): # we can have more messages since the AI might add some stuff at the end to wrap up the scene | |
| return False | |
| else: | |
| return True | |
| def check_each_question_contains_q_from_tuples(conv, qatuples, n): | |
| """ | |
| Ensures that each question contains at least n sequential characters from the corresponding question in qatuples. | |
| If the first check fails, it checks again assuming questions are at even indices starting from 2. | |
| If the first question fails both checks, return None for special handling. | |
| Parameters: | |
| conv (list): List of tuples containing the dialogues. | |
| qatuples (list): List of tuples containing questions and answers. | |
| n (int): Number of sequential characters to check. | |
| Returns: | |
| bool or None: True if all questions pass the check, False if any fail, None if the first question fails both checks. | |
| """ | |
| def check_questions(start_index): | |
| for i in range(start_index, len(conv), 2): | |
| if (i - start_index) // 2 < len(qatuples): | |
| question_from_conv = conv[i][1] | |
| question_from_tuples = qatuples[(i - start_index) // 2][0] | |
| sequential, _ = has_sequential_chars( | |
| question_from_tuples, question_from_conv, n | |
| ) | |
| if not sequential: | |
| return False | |
| return True | |
| # First check: questions at even indices starting from 0 | |
| if check_questions(0): | |
| return True | |
| # Second check: questions at even indices starting from 2 | |
| if check_questions(2): | |
| return True | |
| # If both checks fail and the first question was involved, return None | |
| if len(conv) >= 2 and len(qatuples) > 0: | |
| question_from_conv = conv[0][1] if len(conv) > 0 else "" | |
| question_from_tuples = qatuples[0][0] | |
| sequential, _ = has_sequential_chars( | |
| question_from_tuples, question_from_conv, n | |
| ) | |
| if not sequential: | |
| return None | |
| return False | |
| def check_for_unintended_repeated_quotes(dialogues, qatuples, n_characters_shared): | |
| """ | |
| Checks if answers in the conversation inadvertently use a long quote from another QA pair. | |
| Args: | |
| dialogues (list): List of tuples containing the dialogues. | |
| qatuples (list): List of tuples containing questions and answers. | |
| n_characters_shared (int): Number of sequential characters to check for repetition. | |
| Returns: | |
| bool: True if no unintended repeated quotes are found, False otherwise. | |
| """ | |
| # Extract only the answers from the QA tuples for comparison | |
| qa_answers = [qa[1] for qa in qatuples] | |
| for i in range( | |
| 2, len(dialogues), 2 | |
| ): # Answers are at even indices, starting from 2 | |
| # Skip if there's no corresponding QA tuple | |
| if int(i / 2) - 1 >= len(qatuples): | |
| break | |
| dialogue_answer = dialogues[i][1] | |
| corresponding_qa_answer = qatuples[int(i / 2) - 1][1] | |
| # Check for each answer in the QA tuples | |
| for idx, qa_answer in enumerate(qa_answers): | |
| # Skip the comparison for the current QA pair itself | |
| if qa_answer == corresponding_qa_answer: | |
| continue | |
| # Check if the dialogue answer contains a long quote from another QA answer | |
| sequential, comp_string = has_sequential_chars( | |
| qa_answer, dialogue_answer, n_characters_shared | |
| ) | |
| if sequential: | |
| if comp_string in corresponding_qa_answer: | |
| continue # This is a quote from the corresponding answer, so it's fine | |
| else: | |
| # Found an unintended repeated quote | |
| return False | |
| return True | |
| def call_all_processors(multiturn_conversation, qatuples): | |
| convs_split = extract_conversation(multiturn_conversation) | |
| # Check if answers in dialogues match corresponding answers in qatuples | |
| if not compare_answers_with_qatuples(convs_split, qatuples, 15): | |
| print("Answers in dialogues do not match corresponding answers in qatuples.") | |
| return False | |
| # Check the conversation length | |
| if not check_conversation_length(convs_split, qatuples): | |
| print("Conversation is too short! Validation failed!") | |
| print(convs_split) | |
| return False | |
| # Check for unintended repeated quotes | |
| if not check_for_unintended_repeated_quotes(convs_split, qatuples, 100): | |
| print("Conversation contains unintended repeated quotes. Validation failed!") | |
| return False | |
| # Check each question contains a part of the question from tuples | |
| result = check_each_question_contains_q_from_tuples(convs_split, qatuples, 15) | |
| if result is None: | |
| print( | |
| "First question does not contain a part of the question from tuples. Validation failed!" | |
| ) | |
| return None | |
| elif not result: | |
| print( | |
| "Each question does not contain a part of the question from tuples. Validation failed!" | |
| ) | |
| return False | |
| # If all checks pass | |
| return True | |
| if __name__ == "__main__": | |
| # Test cases for has_sequential_chars | |
| print("Testing has_sequential_chars:") | |
| print(has_sequential_chars("hello", "worldhello", 3)) # | |
| print("Expected True") | |
| print(has_sequential_chars("abc", "defghijkl", 2)) # Expected False | |
| print("Expected False") | |
| print(has_sequential_chars("", "empty", 1)) # Expected False (empty string1) | |
| print("Expected False") | |
| print( | |
| has_sequential_chars("longstring", "short", 5) | |
| ) # Expected False (n is longer than string2) | |
| print("Expected False") | |
| print( | |
| has_sequential_chars("overlap", "laptopp", 3) | |
| ) # Expected True (partial overlap) | |
| print("Expected True") | |
| # Test cases for extract_conversation | |
| print("\nTesting extract_conversation:") | |
| test_conversation1 = "Charname1: Hello\nCharname2: Hi\nCharname3: How are you?" | |
| print( | |
| extract_conversation(test_conversation1) | |
| ) # Expected [('Charname1', 'Hello'), ('Charname2', 'Hi'), ('Charname3', 'How are you?')] | |
| print( | |
| "Expected [('Charname1', 'Hello'), ('Charname2', 'Hi'), ('Charname3', 'How are you?')]" | |
| ) | |
| test_conversation2 = "No colons here" | |
| print(extract_conversation(test_conversation2)) # Expected [] | |
| print("Expected []") | |
| test_conversation3 = "" | |
| print(extract_conversation(test_conversation3)) # Expected [] | |
| print("Expected []") | |
| # Test cases for compare_answers_with_qatuples | |
| print("\nTesting compare_answers_with_qatuples:") | |
| dialogues1 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "Hi how are you"), | |
| "Totally Fantastic and Amazing!", | |
| ] | |
| qatuples1 = [("How are you?", "Fine")] | |
| print(compare_answers_with_qatuples(dialogues1, qatuples1, 2)) # Expected False | |
| print("Expected False") | |
| dialogues2 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "Hi how are you"), | |
| ("Charname1", "Mostly Fine I think, yeah"), | |
| ] | |
| print(compare_answers_with_qatuples(dialogues2, qatuples1, 2)) # Expected True | |
| print("Expected True") | |
| dialogues3 = [] | |
| qatuples2 = [] | |
| print( | |
| compare_answers_with_qatuples(dialogues3, qatuples2, 2) | |
| ) # Expected True (both empty) | |
| print("Expected True (both empty)") | |
| # Test cases for check_for_repeated_dialogue_answers | |
| print("\nTesting check_for_repeated_dialogue_answers:") | |
| qatuples_repeated_answers = [("How are you?", "Fine, thank you for asking!")] | |
| dialogues4 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "How are you?"), | |
| ("Charname1", "Fine, thank you for asking!"), | |
| ] | |
| print( | |
| check_for_repeated_dialogue_answers(dialogues4, qatuples_repeated_answers, 2) | |
| ) # Expected True (no repetition) | |
| print("Expected True (no repetition)") | |
| dialogues5 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "How are you?"), | |
| ( | |
| "Charname1", | |
| "Fine, thank you for asking! It's nice today, after all, so I'm Fine, thank you for asking!", | |
| ), | |
| ] | |
| print( | |
| check_for_repeated_dialogue_answers(dialogues5, qatuples_repeated_answers, 2) | |
| ) # Expected False (repetition) | |
| print("Expected False (repetition)") | |
| # Test cases for check_repeated_answer | |
| # print("\nTesting check_repeated_answer:") | |
| # dialogues6 = [("Charname1", "Question"), ("Charname2", "Answer1"), ("Charname3", "Question"), ("Charname4", "Answer1")] | |
| # print(check_repeated_answer(dialogues6)) # Expected False (repeated answers) | |
| # dialogues7 = [("Charname1", "Question"), ("Charname2", "Answer1"), ("Charname3", "Question"), ("Charname4", "Answer2")] | |
| # print(check_repeated_answer(dialogues7)) # Expected True (different answers) | |
| # Test cases for check_conversation_length | |
| print("\nTesting check_conversation_length:") | |
| conv1 = [("Charname1", "Hello"), ("Charname2", "Hi, How are you?")] | |
| print( | |
| check_conversation_length(conv1, qatuples1) | |
| ) # Expected False (conversation too short) | |
| print("Expected False (conversation too short)") | |
| conv2 = [("Charname1", "Hello"), ("Charname2", "Hi"), ("Charname3", "How are you?")] | |
| print(check_conversation_length(conv2, qatuples1)) # Expected True (correct length) | |
| print("Expected True (correct length)") | |
| # Test cases for check_conversation_for_text_from_examples (commented out as implementation is assumed elsewhere) | |
| # print("\nTesting check_conversation_for_text_from_examples:") | |
| # conv3 = "This conversation contains lipstick-colored lips and a coquettishly tilting head." | |
| # print(check_conversation_for_text_from_examples(conv3)) # Expected False (contains example texts) | |
| # Test cases for check_each_question_contains_q_from_tuples | |
| print("\nTesting check_each_question_contains_q_from_tuples:") | |
| conv4 = [ | |
| ("Charname2", "Hiya~!"), | |
| ("Charname1", "What's your favorite color?"), | |
| ("Charname2", "I'm Fine, thank you very much!"), | |
| ] | |
| print(check_each_question_contains_q_from_tuples(conv4, qatuples1, 6)) | |
| print("Expected None (no matching question, first Q)") | |
| conv45 = [ | |
| ("Charname2", "Hiya~!"), | |
| ("Charname1", "How are you?"), | |
| ("Charname2", "I'm Fine, thank you very much!"), | |
| ("Charname1", "What is the airspeed velocity of an unladen swallow?"), | |
| ("Charname2", "Black, like my soul."), | |
| ] | |
| qatuples3 = [ | |
| ("How are you?", "I'm Fine, thank you very much!"), | |
| ("What's your favorite color?", "Black, like my soul."), | |
| ] | |
| print(check_each_question_contains_q_from_tuples(conv45, qatuples3, 6)) | |
| print("Expected False (no matching question, second Q)") | |
| conv5 = [ | |
| ("Charname1", "Hiya~!"), | |
| ("Charname2", "How are you?"), | |
| ("Charname2", "I'm Fine, thank you very much!"), | |
| ("Charname1", "What's your favorite color?"), | |
| ("Charname2", "Black, like my soul."), | |
| ] | |
| print(check_each_question_contains_q_from_tuples(conv5, qatuples1 + [], 6)) # | |
| print("Expected True (question contains part of qatuple question)") | |
| # Test cases for check_for_unintended_repeated_quotes | |
| print("\nTesting check_for_unintended_repeated_quotes:") | |
| # Creating a set of dialogues and qatuples where there is an unintended repeated quote | |
| qatuples_shared = [ | |
| ("What is your favorite book?", "I love reading The Hobbit."), | |
| ( | |
| "Tell me about a recent happy moment.", | |
| "My friends threw me a surprise party!", | |
| ), | |
| ] | |
| dialogues_shared1 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "What is your favorite book?"), | |
| ("Charname1", "I love reading The Hobbit."), | |
| ("Charname2", "Tell me about a recent happy moment."), | |
| ( | |
| "Charname1", | |
| "My friends threw me a surprise party! It felt just like I was in The Hobbit.", | |
| ), | |
| ] | |
| print( | |
| check_for_unintended_repeated_quotes(dialogues_shared1, qatuples_shared, 10) | |
| ) # Expected False (repeated long quote from another answer) | |
| print("Expected False (repeated long quote from another answer)") | |
| # Creating a set of dialogues and qatuples where there are no unintended repeated quotes | |
| dialogues_shared2 = [ | |
| ("Charname1", "Hello"), | |
| ("Charname2", "What is your favorite book?"), | |
| ("Charname1", "I absolutely adore The Lord of the Rings."), | |
| ("Charname2", "Tell me about a recent happy moment."), | |
| ("Charname1", "I had a great time at the beach last weekend!"), | |
| ] | |
| print( | |
| check_for_unintended_repeated_quotes(dialogues_shared2, qatuples_shared, 10) | |
| ) # Expected True (no repeated long quotes) | |
| print("Expected True (no repeated long quotes)") | |
| # Test cases for call_all_processors | |
| print("\nTesting call_all_processors:") | |
| complete_conversation = """ | |
| Charname1: Hello | |
| Charname2: How are you doing today? | |
| Charname1: I'm fine, thank you very much! | |
| Charname2: What's the weather like? | |
| Charname1: It's sunny and warm. I don't like sand. It's coarse and rough and irritating and it gets everywhere. | |
| Foo: Bar | |
| Baz: Quux | |
| """ | |
| qatuples_complete = [ | |
| ("How are you doing today?", "I'm fine, thank you very much!"), | |
| ( | |
| "What's the weather like?", | |
| "It's sunny and warm. I don't like sand. It's coarse and rough and irritating and it gets everywhere.", | |
| ), | |
| ] | |
| print(call_all_processors(complete_conversation, qatuples_complete)) # | |
| print("Expected True (all checks pass)") | |
| incomplete_conversation = """ | |
| Charname1: How's it going? | |
| Charname2: Good. | |
| Charname1: Any plans? | |
| Charname2: None. | |
| Foo: Bar | |
| Baz: Quux | |
| """ | |
| print(call_all_processors(incomplete_conversation, qatuples_complete)) # | |
| print("Expected False (checks fail)") | |