From 7c357e18c19490e49bbb1736cfa9da83c421d122 Mon Sep 17 00:00:00 2001 From: k-ivey Date: Wed, 13 Dec 2023 16:46:39 -0500 Subject: [PATCH 1/6] Fix type bug in convert_from_original_idxs The isinstance function requires a tuple of types as the second argument in multiple types are provided, not a list of types --- textattack/shared/attacked_text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textattack/shared/attacked_text.py b/textattack/shared/attacked_text.py index c82dd86a..d2221bb3 100644 --- a/textattack/shared/attacked_text.py +++ b/textattack/shared/attacked_text.py @@ -317,7 +317,7 @@ def convert_from_original_idxs(self, idxs: Iterable[int]) -> List[int]: elif isinstance(idxs, set): idxs = list(idxs) - elif not isinstance(idxs, [list, np.ndarray]): + elif not isinstance(idxs, (list, np.ndarray)): raise TypeError( f"convert_from_original_idxs got invalid idxs type {type(idxs)}" ) From 4741776923ac358078d2ad65f1460348352e5dc8 Mon Sep 17 00:00:00 2001 From: k-ivey Date: Wed, 13 Dec 2023 16:48:49 -0500 Subject: [PATCH 2/6] Add UnmodifiableIndices and UnmodifiablePhrases constraints --- ...tattack.constraints.pre_transformation.rst | 12 +++++++ .../test_pretransformation_constraints.py | 31 +++++++++++++++++ .../pre_transformation/__init__.py | 2 ++ .../unmodifiable_indices.py | 24 ++++++++++++++ .../unmodifiable_phrases.py | 33 +++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 textattack/constraints/pre_transformation/unmodifiable_indices.py create mode 100644 textattack/constraints/pre_transformation/unmodifiable_phrases.py diff --git a/docs/apidoc/textattack.constraints.pre_transformation.rst b/docs/apidoc/textattack.constraints.pre_transformation.rst index f78ed25a..62166d86 100644 --- a/docs/apidoc/textattack.constraints.pre_transformation.rst +++ b/docs/apidoc/textattack.constraints.pre_transformation.rst @@ -43,3 +43,15 @@ textattack.constraints.pre\_transformation package :members: :undoc-members: :show-inheritance: + + +.. automodule:: textattack.constraints.pre_transformation.unmodifiable_indices + :members: + :undoc-members: + :show-inheritance: + + +.. automodule:: textattack.constraints.pre_transformation.unmodifiable_phrases + :members: + :undoc-members: + :show-inheritance: diff --git a/tests/test_constraints/test_pretransformation_constraints.py b/tests/test_constraints/test_pretransformation_constraints.py index f1345796..429cff99 100644 --- a/tests/test_constraints/test_pretransformation_constraints.py +++ b/tests/test_constraints/test_pretransformation_constraints.py @@ -103,3 +103,34 @@ def test_stopword_modification( set(range(len(entailment_attacked_text.words))) - {1, 2, 3, 8, 9, 11, 16, 17, 20, 22, 25, 31, 34, 39, 40, 41, 43, 44} ) + + def test_unmodifiable_indices( + self, sentence_attacked_text, entailment_attacked_text + ): + constraint = textattack.constraints.pre_transformation.UnmodifiableIndices( + [4, 5] + ) + assert constraint._get_modifiable_indices(sentence_attacked_text) == ( + set(range(len(sentence_attacked_text.words))) - {4, 5} + ) + sentence_attacked_text = sentence_attacked_text.delete_word_at_index(2) + assert constraint._get_modifiable_indices(sentence_attacked_text) == ( + set(range(len(sentence_attacked_text.words))) - {3, 4} + ) + assert constraint._get_modifiable_indices(entailment_attacked_text) == ( + set(range(len(entailment_attacked_text.words))) - {4, 5} + ) + entailment_attacked_text = ( + entailment_attacked_text.insert_text_after_word_index(0, "two words") + ) + assert constraint._get_modifiable_indices(entailment_attacked_text) == ( + set(range(len(entailment_attacked_text.words))) - {6, 7} + ) + + def test_unmodifiable_phrases(self, sentence_attacked_text): + constraint = textattack.constraints.pre_transformation.UnmodifablePhrases( + ["South Korea's", "oil", "monday"] + ) + assert constraint._get_modifiable_indices(sentence_attacked_text) == ( + set(range(len(sentence_attacked_text.words))) - {0, 1, 9, 22} + ) diff --git a/textattack/constraints/pre_transformation/__init__.py b/textattack/constraints/pre_transformation/__init__.py index 9cfdd8cf..98ab8352 100644 --- a/textattack/constraints/pre_transformation/__init__.py +++ b/textattack/constraints/pre_transformation/__init__.py @@ -12,3 +12,5 @@ from .max_num_words_modified import MaxNumWordsModified from .min_word_length import MinWordLength from .max_modification_rate import MaxModificationRate +from .unmodifiable_indices import UnmodifiableIndices +from .unmodifiable_phrases import UnmodifablePhrases diff --git a/textattack/constraints/pre_transformation/unmodifiable_indices.py b/textattack/constraints/pre_transformation/unmodifiable_indices.py new file mode 100644 index 00000000..b8d141ce --- /dev/null +++ b/textattack/constraints/pre_transformation/unmodifiable_indices.py @@ -0,0 +1,24 @@ +from textattack.constraints import PreTransformationConstraint + + +class UnmodifiableIndices(PreTransformationConstraint): + """A constraint that prevents the modification of certain words at specific + indices. + + Args: + indices (list(int)): A list of indices which are unmodifiable + """ + + def __init__(self, indices): + self.unmodifiable_indices = indices + + def _get_modifiable_indices(self, current_text): + unmodifiable_set = current_text.convert_from_original_idxs( + self.unmodifiable_indices + ) + return set( + i for i in range(0, len(current_text.words)) if i not in unmodifiable_set + ) + + def extra_repr_keys(self): + return ["indices"] diff --git a/textattack/constraints/pre_transformation/unmodifiable_phrases.py b/textattack/constraints/pre_transformation/unmodifiable_phrases.py new file mode 100644 index 00000000..4b3ee51b --- /dev/null +++ b/textattack/constraints/pre_transformation/unmodifiable_phrases.py @@ -0,0 +1,33 @@ +from collections import defaultdict + +from textattack.constraints import PreTransformationConstraint + + +class UnmodifablePhrases(PreTransformationConstraint): + """A constraint that prevents the modification of specified phrases or + words. + + Args: + phrases (list(str)): A list of strings that cannot be modified + """ + + def __init__(self, phrases): + self.length_to_phrases = defaultdict(set) + for phrase in phrases: + self.length_to_phrases[len(phrase.split())].add(phrase.lower()) + + def _get_modifiable_indices(self, current_text): + phrase_indices = set() + + for phrase_length in self.length_to_phrases.keys(): + for i in range(len(current_text.words) - phrase_length + 1): + if ( + " ".join(current_text.words[i : i + phrase_length]) + in self.length_to_phrases[phrase_length] + ): + phrase_indices |= set(range(i, i + phrase_length)) + + return set(i for i in range(len(current_text.words)) if i not in phrase_indices) + + def extra_repr_keys(self): + return ["phrases"] From 26fa402333502ed7ec5ca0ba22c39d34964d3a56 Mon Sep 17 00:00:00 2001 From: k-ivey Date: Wed, 13 Dec 2023 16:49:21 -0500 Subject: [PATCH 3/6] Add pipeline for prompt augmentation --- .../apidoc/textattack.prompt_augmentation.rst | 13 ++++++ docs/apidoc/textattack.rst | 1 + tests/test_prompt_augmentation.py | 25 ++++++++++ textattack/prompt_augmentation/__init__.py | 10 ++++ .../prompt_augmentation_pipeline.py | 46 +++++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 docs/apidoc/textattack.prompt_augmentation.rst create mode 100644 tests/test_prompt_augmentation.py create mode 100644 textattack/prompt_augmentation/__init__.py create mode 100644 textattack/prompt_augmentation/prompt_augmentation_pipeline.py diff --git a/docs/apidoc/textattack.prompt_augmentation.rst b/docs/apidoc/textattack.prompt_augmentation.rst new file mode 100644 index 00000000..27740e7f --- /dev/null +++ b/docs/apidoc/textattack.prompt_augmentation.rst @@ -0,0 +1,13 @@ +textattack.prompt_augmentation package +======================================= + +.. automodule:: textattack.prompt_augmentation + :members: + :undoc-members: + :show-inheritance: + + +.. automodule:: textattack.prompt_augmentation.prompt_augmentation_pipeline + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/apidoc/textattack.rst b/docs/apidoc/textattack.rst index a95055f8..da90f022 100644 --- a/docs/apidoc/textattack.rst +++ b/docs/apidoc/textattack.rst @@ -22,6 +22,7 @@ textattack package textattack.loggers textattack.metrics textattack.models + textattack.prompt_augmentation textattack.search_methods textattack.shared textattack.transformations diff --git a/tests/test_prompt_augmentation.py b/tests/test_prompt_augmentation.py new file mode 100644 index 00000000..3e557062 --- /dev/null +++ b/tests/test_prompt_augmentation.py @@ -0,0 +1,25 @@ +def test_prompt_augmentation_pipeline(): + from transformers import AutoModelForSeq2SeqLM, AutoTokenizer + + from textattack.augmentation.recipes import CheckListAugmenter + from textattack.constraints.pre_transformation import UnmodifiableIndices + from textattack.llms import HuggingFaceLLMWrapper + from textattack.prompt_augmentation import PromptAugmentationPipeline + + model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small") + tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small") + model_wrapper = HuggingFaceLLMWrapper(model, tokenizer) + + augmenter = CheckListAugmenter() + + pipeline = PromptAugmentationPipeline(augmenter, model_wrapper) + + prompt = "As a sentiment classifier, determine whether the following text is 'positive' or 'negative'. Please classify: Poor Ben Bratt couldn't find stardom if MapQuest emailed him point-to-point driving directions." + prompt_constraints = [UnmodifiableIndices([2, 3, 10, 12, 14])] + + output = pipeline(prompt, prompt_constraints) + + assert len(output) == 1 + assert len(output[0]) == 2 + assert "could not" in output[0][0] + assert "negative" in output[0][1] diff --git a/textattack/prompt_augmentation/__init__.py b/textattack/prompt_augmentation/__init__.py new file mode 100644 index 00000000..10f87653 --- /dev/null +++ b/textattack/prompt_augmentation/__init__.py @@ -0,0 +1,10 @@ +""" +Prompt Augmentation +===================== + +This package includes functions used to augment a prompt for a LLM + +""" + + +from .prompt_augmentation_pipeline import PromptAugmentationPipeline diff --git a/textattack/prompt_augmentation/prompt_augmentation_pipeline.py b/textattack/prompt_augmentation/prompt_augmentation_pipeline.py new file mode 100644 index 00000000..06b17eab --- /dev/null +++ b/textattack/prompt_augmentation/prompt_augmentation_pipeline.py @@ -0,0 +1,46 @@ +from textattack.constraints import PreTransformationConstraint + + +class PromptAugmentationPipeline: + """A prompt augmentation pipeline to augment a prompt and obtain the + responses from a LLM on the augmented prompts. + + Args: + augmenter (textattack.Augmenter): the augmenter to use to + augment the prompt + llm (textattack.ModelWrapper): the LLM to generate responses + to the augmented data + """ + + def __init__(self, augmenter, llm): + self.augmenter = augmenter + self.llm = llm + + def __call__(self, prompt, prompt_constraints=[]): + """Augments the given prompt using the augmenter and generates + responses using the LLM. + + Args: + prompt (:obj:`str`): the prompt to augment and generate responses + prompt_constraints (List(textattack.constraints.PreTransformationConstraint)): a list of pretransformation + constraints to apply to the given prompt + + Returns a list of tuples of strings, where the first string in the pair is the augmented prompt and the second + is the response to the augmented prompt from the LLM + """ + for constraint in prompt_constraints: + if isinstance(constraint, PreTransformationConstraint): + self.augmenter.pre_transformation_constraints.append(constraint) + else: + raise ValueError( + "Prompt constraints must be of type PreTransformationConstraint" + ) + + augmented_prompts = self.augmenter.augment(prompt) + for _ in range(len(prompt_constraints)): + self.augmenter.pre_transformation_constraints.pop() + + outputs = [] + for augmented_prompt in augmented_prompts: + outputs.append((augmented_prompt, self.llm(augmented_prompt))) + return outputs From c68ac06a6ead78bfbf3056e3d2576afb47104d0d Mon Sep 17 00:00:00 2001 From: k-ivey Date: Wed, 13 Dec 2023 16:49:37 -0500 Subject: [PATCH 4/6] Add wrapper for LLMs --- docs/apidoc/textattack.llms.rst | 19 +++++++++++ docs/apidoc/textattack.rst | 1 + textattack/llms/__init__.py | 16 ++++++++++ textattack/llms/chat_gpt_wrapper.py | 37 ++++++++++++++++++++++ textattack/llms/huggingface_llm_wrapper.py | 29 +++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 docs/apidoc/textattack.llms.rst create mode 100644 textattack/llms/__init__.py create mode 100644 textattack/llms/chat_gpt_wrapper.py create mode 100644 textattack/llms/huggingface_llm_wrapper.py diff --git a/docs/apidoc/textattack.llms.rst b/docs/apidoc/textattack.llms.rst new file mode 100644 index 00000000..5dfd33ed --- /dev/null +++ b/docs/apidoc/textattack.llms.rst @@ -0,0 +1,19 @@ +textattack.llms package +========================= + +.. automodule:: textattack.llms + :members: + :undoc-members: + :show-inheritance: + + +.. automodule:: textattack.llms.huggingface_llm_wrapper + :members: + :undoc-members: + :show-inheritance: + + +.. automodule:: textattack.llms.chat_gpt_wrapper + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/apidoc/textattack.rst b/docs/apidoc/textattack.rst index da90f022..565caf12 100644 --- a/docs/apidoc/textattack.rst +++ b/docs/apidoc/textattack.rst @@ -19,6 +19,7 @@ textattack package textattack.datasets textattack.goal_function_results textattack.goal_functions + textattack.llms textattack.loggers textattack.metrics textattack.models diff --git a/textattack/llms/__init__.py b/textattack/llms/__init__.py new file mode 100644 index 00000000..df62043f --- /dev/null +++ b/textattack/llms/__init__.py @@ -0,0 +1,16 @@ +""" +Large Language Models +====================== + +TextAttack can generate responses to prompts using LLMs, which take in a list of strings and outputs a list of responses. + +We've provided an implementation around two common LLM patterns: + +1. `HuggingFaceLLMWrapper` for LLMs in HuggingFace +2. `ChatGptWrapper` for OpenAI's ChatGPT model + + +""" + +from .chat_gpt_wrapper import ChatGptWrapper +from .huggingface_llm_wrapper import HuggingFaceLLMWrapper diff --git a/textattack/llms/chat_gpt_wrapper.py b/textattack/llms/chat_gpt_wrapper.py new file mode 100644 index 00000000..7697c431 --- /dev/null +++ b/textattack/llms/chat_gpt_wrapper.py @@ -0,0 +1,37 @@ +import os + +from textattack.models.wrappers import ModelWrapper + + +class ChatGptWrapper(ModelWrapper): + """A wrapper around OpenAI's ChatGPT model. Note that you must provide your + own API key to use this wrapper. + + Args: + model_name (:obj:`str`): The name of the GPT model to use. See the OpenAI documentation + for a list of latest model names + key_environment_variable (:obj:`str`, 'optional`, defaults to :obj:`OPENAI_API_KEY`): + The environment variable that the API key is set to + """ + + def __init__( + self, model_name="gpt-3.5-turbo", key_environment_variable="OPENAI_API_KEY" + ): + from openai import OpenAI + + self.model_name = model_name + self.client = OpenAI(api_key=os.getenv(key_environment_variable)) + + def __call__(self, text_input_list): + """Returns a list of responses to the given input list.""" + if isinstance(text_input_list, str): + text_input_list = [text_input_list] + + outputs = [] + for text in text_input_list: + completion = self.client.chat.completions.create( + model=self.model_name, messages=[{"role": "user", "content": text}] + ) + outputs.append(completion.choices[0].message) + + return outputs diff --git a/textattack/llms/huggingface_llm_wrapper.py b/textattack/llms/huggingface_llm_wrapper.py new file mode 100644 index 00000000..7c33101a --- /dev/null +++ b/textattack/llms/huggingface_llm_wrapper.py @@ -0,0 +1,29 @@ +from textattack.models.wrappers import ModelWrapper + + +class HuggingFaceLLMWrapper(ModelWrapper): + """A wrapper around HuggingFace for LLMs. + + Args: + model: A HuggingFace pretrained LLM + tokenizer: A HuggingFace pretrained tokenizer + """ + + def __init__(self, model, tokenizer): + self.model = model + self.tokenizer = tokenizer + + def __call__(self, text_input_list): + """Returns a list of responses to the given input list.""" + model_device = next(self.model.parameters()).device + input_ids = self.tokenizer(text_input_list, return_tensors="pt").input_ids + input_ids.to(model_device) + + outputs = self.model.generate( + input_ids, max_new_tokens=512, pad_token_id=self.tokenizer.eos_token_id + ) + + responses = self.tokenizer.batch_decode(outputs, skip_special_tokens=True) + if len(text_input_list) == 1: + return responses[0] + return responses From b95a9876169f880edc12dd2c1aff289f728636a6 Mon Sep 17 00:00:00 2001 From: k-ivey Date: Wed, 13 Dec 2023 19:19:16 -0500 Subject: [PATCH 5/6] Add prompt augmentation example to README --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index c05e2026..25a803ce 100644 --- a/README.md +++ b/README.md @@ -391,6 +391,27 @@ You can also create your own augmenter from scratch by importing transformations ['What I cannot creae, I do not understand.', 'What I cannot creat, I do not understand.', 'What I cannot create, I do not nderstand.', 'What I cannot create, I do nt understand.', 'Wht I cannot create, I do not understand.'] ``` +#### Prompt Augmentation +In additional to augmentation of regular text, you can augment prompts and then generate responses to +the augmented prompts using a large language model (LLMs). The augmentation is performed using the same +`Augmenter` as above. To generate responses, you can use your own LLM, a HuggingFace LLM, or an OpenAI LLM. +Here's an example using a pretrained HuggingFace LLM: + +```python +>>> from textattack.augmentation import EmbeddingAugmenter +>>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer +>>> from textattack.llms import HuggingFaceLLMWrapper +>>> from textattack.prompt_augmentation import PromptAugmentationPipeline +>>> augmenter = EmbeddingAugmenter(transformations_per_example=3) +>>> model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small") +>>> tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small") +>>> model_wrapper = HuggingFaceLLMWrapper(model, tokenizer) +>>> pipeline = PromptAugmentationPipeline(augmenter, model_wrapper) +>>> pipeline("Classify the following piece of text as `positive` or `negative`: This movie is great!") +[('Classify the following piece of text as `positive` or `negative`: This film is great!', ['positive']), ('Classify the following piece of text as `positive` or `negative`: This movie is fabulous!', ['positive']), ('Classify the following piece of text as `positive` or `negative`: This movie is wonderful!', ['positive'])] +``` + + ### Training Models: `textattack train` Our model training code is available via `textattack train` to help you train LSTMs, From 64691382ddd97faac1d5202922f50867e3007c7c Mon Sep 17 00:00:00 2001 From: Yanjun Qi Date: Sun, 10 Mar 2024 20:44:49 -0400 Subject: [PATCH 6/6] format change --- .../test_command_line/update_test_outputs.py | 1 + textattack/__init__.py | 1 + textattack/attack.py | 6 ++-- textattack/attack_recipes/bae_garg_2019.py | 1 + .../attack_recipes/bert_attack_li_2020.py | 1 + .../attack_recipes/checklist_ribeiro_2020.py | 1 + .../attack_recipes/hotflip_ebrahimi_2017.py | 1 + textattack/attack_recipes/iga_wang_2019.py | 1 + .../input_reduction_feng_2018.py | 1 + textattack/attack_recipes/kuleshov_2017.py | 1 + .../attack_recipes/morpheus_tan_2020.py | 1 + textattack/attack_recipes/pruthi_2019.py | 1 + textattack/attack_recipes/pso_zang_2020.py | 1 + textattack/attack_recipes/pwws_ren_2019.py | 1 + .../seq2sick_cheng_2018_blackbox.py | 1 + .../successful_attack_result.py | 1 - textattack/augment_args.py | 1 - textattack/augmentation/__init__.py | 1 - textattack/augmentation/augmenter.py | 1 + textattack/augmentation/recipes.py | 1 + textattack/commands/__init__.py | 1 - textattack/commands/eval_model_command.py | 1 - textattack/commands/textattack_cli.py | 1 - textattack/commands/train_model_command.py | 1 - textattack/constraints/grammaticality/cola.py | 1 + .../language_models/__init__.py | 1 - .../google_language_model/__init__.py | 1 - .../google_language_model/alzantot_goog_lm.py | 1 - .../google_language_model.py | 1 + .../google_language_model/lm_utils.py | 1 + .../grammaticality/language_models/gpt2.py | 1 - .../learning_to_write/__init__.py | 1 + .../learning_to_write/adaptive_softmax.py | 1 - .../learning_to_write/rnn_model.py | 1 - .../grammaticality/language_tool.py | 1 + .../grammaticality/part_of_speech.py | 1 + .../constraints/overlap/meteor_score.py | 1 - .../pre_transformation/__init__.py | 1 + .../max_modification_rate.py | 1 + .../max_word_index_modification.py | 1 + textattack/constraints/semantics/__init__.py | 1 + .../semantics/sentence_encoders/__init__.py | 1 - .../sentence_encoders/infer_sent/__init__.py | 1 - .../infer_sent/infer_sent_model.py | 9 ++--- .../universal_sentence_encoder/__init__.py | 1 - textattack/datasets/helpers/ted_multi.py | 1 - textattack/goal_function_results/__init__.py | 1 + .../classification_goal_function.py | 1 - .../hardlabel_classification.py | 1 - .../classification/input_reduction.py | 1 - .../classification/targeted_classification.py | 1 - .../untargeted_classification.py | 1 - textattack/goal_functions/goal_function.py | 1 - .../text/non_overlapping_output.py | 1 - textattack/loggers/logger.py | 1 - textattack/loggers/visdom_logger.py | 1 - .../loggers/weights_and_biases_logger.py | 1 - .../metrics/attack_metrics/words_perturbed.py | 6 ++-- textattack/model_args.py | 1 - textattack/models/__init__.py | 1 - textattack/models/helpers/__init__.py | 1 - .../models/helpers/lstm_for_classification.py | 1 + .../models/helpers/t5_for_text_to_text.py | 1 + textattack/models/helpers/utils.py | 1 - .../helpers/word_cnn_for_classification.py | 1 + textattack/models/tokenizers/__init__.py | 1 - .../models/tokenizers/glove_tokenizer.py | 1 - .../models/wrappers/pytorch_model_wrapper.py | 1 - .../models/wrappers/sklearn_model_wrapper.py | 1 - .../wrappers/tensorflow_model_wrapper.py | 1 - textattack/prompt_augmentation/__init__.py | 1 - textattack/search_methods/__init__.py | 1 + textattack/search_methods/beam_search.py | 1 + .../search_methods/genetic_algorithm.py | 1 + textattack/search_methods/greedy_search.py | 1 + .../particle_swarm_optimization.py | 7 ++-- textattack/search_methods/search_method.py | 1 - textattack/shared/__init__.py | 1 - textattack/shared/checkpoint.py | 1 + textattack/shared/data.py | 36 +++++++++++++++++-- textattack/transformations/__init__.py | 1 + .../back_translation.py | 1 - .../sentence_transformation.py | 1 - .../transformations/word_innerswap_random.py | 1 - .../word_insertions/word_insertion.py | 1 + .../word_insertion_masked_lm.py | 1 + .../transformations/word_merges/word_merge.py | 1 + .../word_merges/word_merge_masked_lm.py | 1 + .../transformations/word_swaps/__init__.py | 1 - .../chinese_homophone_character_swap.py | 1 - .../transformations/word_swaps/word_swap.py | 1 + .../word_swaps/word_swap_change_location.py | 1 + .../word_swaps/word_swap_change_number.py | 1 + .../word_swaps/word_swap_embedding.py | 1 + .../word_swaps/word_swap_gradient_based.py | 1 + .../word_swaps/word_swap_homoglyph_swap.py | 1 + .../word_swaps/word_swap_hownet.py | 1 - .../word_swaps/word_swap_inflections.py | 1 - .../word_swaps/word_swap_masked_lm.py | 1 - .../word_swap_random_character_insertion.py | 1 + ...word_swap_random_character_substitution.py | 1 + .../word_swaps/word_swap_wordnet.py | 1 - 102 files changed, 96 insertions(+), 65 deletions(-) diff --git a/tests/test_command_line/update_test_outputs.py b/tests/test_command_line/update_test_outputs.py index 727aef1d..91e6d4f7 100644 --- a/tests/test_command_line/update_test_outputs.py +++ b/tests/test_command_line/update_test_outputs.py @@ -3,6 +3,7 @@ This is useful for large changes, but be wary: the outputs still may need to be manually edited to account for variance between runs. """ + from helpers import run_command_and_get_result from test_attack import attack_test_params from test_augment import augment_test_params diff --git a/textattack/__init__.py b/textattack/__init__.py index 30629406..28c5c856 100644 --- a/textattack/__init__.py +++ b/textattack/__init__.py @@ -9,6 +9,7 @@ TextAttack provides components for common NLP tasks like sentence encoding, grammar-checking, and word replacement that can be used on their own. """ + from .attack_args import AttackArgs, CommandLineAttackArgs from .augment_args import AugmenterArgs from .dataset_args import DatasetArgs diff --git a/textattack/attack.py b/textattack/attack.py index 47537d1b..7e05f93e 100644 --- a/textattack/attack.py +++ b/textattack/attack.py @@ -372,9 +372,9 @@ def filter_transformations( uncached_texts.append(transformed_text) else: # promote transformed_text to the top of the LRU cache - self.constraints_cache[ - (current_text, transformed_text) - ] = self.constraints_cache[(current_text, transformed_text)] + self.constraints_cache[(current_text, transformed_text)] = ( + self.constraints_cache[(current_text, transformed_text)] + ) if self.constraints_cache[(current_text, transformed_text)]: filtered_texts.append(transformed_text) filtered_texts += self._filter_transformations_uncached( diff --git a/textattack/attack_recipes/bae_garg_2019.py b/textattack/attack_recipes/bae_garg_2019.py index 76ed108c..f670d8f6 100644 --- a/textattack/attack_recipes/bae_garg_2019.py +++ b/textattack/attack_recipes/bae_garg_2019.py @@ -3,6 +3,7 @@ ============================================ """ + from textattack.constraints.grammaticality import PartOfSpeech from textattack.constraints.pre_transformation import ( RepeatModification, diff --git a/textattack/attack_recipes/bert_attack_li_2020.py b/textattack/attack_recipes/bert_attack_li_2020.py index 1801a6dc..360b8863 100644 --- a/textattack/attack_recipes/bert_attack_li_2020.py +++ b/textattack/attack_recipes/bert_attack_li_2020.py @@ -10,6 +10,7 @@ Consider using smaller values for "max_candidates". """ + from textattack import Attack from textattack.constraints.overlap import MaxWordsPerturbed from textattack.constraints.pre_transformation import ( diff --git a/textattack/attack_recipes/checklist_ribeiro_2020.py b/textattack/attack_recipes/checklist_ribeiro_2020.py index 3fb7a0e3..6491e046 100644 --- a/textattack/attack_recipes/checklist_ribeiro_2020.py +++ b/textattack/attack_recipes/checklist_ribeiro_2020.py @@ -5,6 +5,7 @@ (Beyond Accuracy: Behavioral Testing of NLP models with CheckList) """ + from textattack import Attack from textattack.constraints.pre_transformation import RepeatModification from textattack.goal_functions import UntargetedClassification diff --git a/textattack/attack_recipes/hotflip_ebrahimi_2017.py b/textattack/attack_recipes/hotflip_ebrahimi_2017.py index fa4ba944..18724907 100644 --- a/textattack/attack_recipes/hotflip_ebrahimi_2017.py +++ b/textattack/attack_recipes/hotflip_ebrahimi_2017.py @@ -5,6 +5,7 @@ (HotFlip: White-Box Adversarial Examples for Text Classification) """ + from textattack import Attack from textattack.constraints.grammaticality import PartOfSpeech from textattack.constraints.overlap import MaxWordsPerturbed diff --git a/textattack/attack_recipes/iga_wang_2019.py b/textattack/attack_recipes/iga_wang_2019.py index cb7dce22..a925d987 100644 --- a/textattack/attack_recipes/iga_wang_2019.py +++ b/textattack/attack_recipes/iga_wang_2019.py @@ -6,6 +6,7 @@ (Natural Language Adversarial Attacks and Defenses in Word Level) """ + from textattack import Attack from textattack.constraints.overlap import MaxWordsPerturbed from textattack.constraints.pre_transformation import StopwordModification diff --git a/textattack/attack_recipes/input_reduction_feng_2018.py b/textattack/attack_recipes/input_reduction_feng_2018.py index 85be1c2e..226edf99 100644 --- a/textattack/attack_recipes/input_reduction_feng_2018.py +++ b/textattack/attack_recipes/input_reduction_feng_2018.py @@ -5,6 +5,7 @@ (Pathologies of Neural Models Make Interpretations Difficult) """ + from textattack import Attack from textattack.constraints.pre_transformation import ( RepeatModification, diff --git a/textattack/attack_recipes/kuleshov_2017.py b/textattack/attack_recipes/kuleshov_2017.py index 8d2b7bf9..70ab5853 100644 --- a/textattack/attack_recipes/kuleshov_2017.py +++ b/textattack/attack_recipes/kuleshov_2017.py @@ -4,6 +4,7 @@ (Adversarial Examples for Natural Language Classification Problems) """ + from textattack import Attack from textattack.constraints.grammaticality.language_models import GPT2 from textattack.constraints.overlap import MaxWordsPerturbed diff --git a/textattack/attack_recipes/morpheus_tan_2020.py b/textattack/attack_recipes/morpheus_tan_2020.py index 74b61f04..e8f57d2d 100644 --- a/textattack/attack_recipes/morpheus_tan_2020.py +++ b/textattack/attack_recipes/morpheus_tan_2020.py @@ -5,6 +5,7 @@ """ + from textattack import Attack from textattack.constraints.pre_transformation import ( RepeatModification, diff --git a/textattack/attack_recipes/pruthi_2019.py b/textattack/attack_recipes/pruthi_2019.py index fb3804a9..213506eb 100644 --- a/textattack/attack_recipes/pruthi_2019.py +++ b/textattack/attack_recipes/pruthi_2019.py @@ -3,6 +3,7 @@ ================================================================= """ + from textattack import Attack from textattack.constraints.overlap import MaxWordsPerturbed from textattack.constraints.pre_transformation import ( diff --git a/textattack/attack_recipes/pso_zang_2020.py b/textattack/attack_recipes/pso_zang_2020.py index 0812c892..4147b3b8 100644 --- a/textattack/attack_recipes/pso_zang_2020.py +++ b/textattack/attack_recipes/pso_zang_2020.py @@ -6,6 +6,7 @@ (Word-level Textual Adversarial Attacking as Combinatorial Optimization) """ + from textattack import Attack from textattack.constraints.pre_transformation import ( InputColumnModification, diff --git a/textattack/attack_recipes/pwws_ren_2019.py b/textattack/attack_recipes/pwws_ren_2019.py index bf544c30..cd75c690 100644 --- a/textattack/attack_recipes/pwws_ren_2019.py +++ b/textattack/attack_recipes/pwws_ren_2019.py @@ -6,6 +6,7 @@ (Generating Natural Language Adversarial Examples through Probability Weighted Word Saliency) """ + from textattack import Attack from textattack.constraints.pre_transformation import ( RepeatModification, diff --git a/textattack/attack_recipes/seq2sick_cheng_2018_blackbox.py b/textattack/attack_recipes/seq2sick_cheng_2018_blackbox.py index 86b79aa2..a0122aa6 100644 --- a/textattack/attack_recipes/seq2sick_cheng_2018_blackbox.py +++ b/textattack/attack_recipes/seq2sick_cheng_2018_blackbox.py @@ -4,6 +4,7 @@ ================================================ (Seq2Sick: Evaluating the Robustness of Sequence-to-Sequence Models with Adversarial Examples) """ + from textattack import Attack from textattack.constraints.overlap import LevenshteinEditDistance from textattack.constraints.pre_transformation import ( diff --git a/textattack/attack_results/successful_attack_result.py b/textattack/attack_results/successful_attack_result.py index 2d1e489e..3ece9cee 100644 --- a/textattack/attack_results/successful_attack_result.py +++ b/textattack/attack_results/successful_attack_result.py @@ -4,7 +4,6 @@ """ - from .attack_result import AttackResult diff --git a/textattack/augment_args.py b/textattack/augment_args.py index 666ed2e3..65e9f66b 100644 --- a/textattack/augment_args.py +++ b/textattack/augment_args.py @@ -3,7 +3,6 @@ =================== """ - from dataclasses import dataclass AUGMENTATION_RECIPE_NAMES = { diff --git a/textattack/augmentation/__init__.py b/textattack/augmentation/__init__.py index c59a1141..25b32169 100644 --- a/textattack/augmentation/__init__.py +++ b/textattack/augmentation/__init__.py @@ -6,7 +6,6 @@ Transformations and constraints can be used outside of an attack for simple NLP data augmentation with the ``Augmenter`` class that returns all possible transformations for a given string. """ - from .augmenter import Augmenter from .recipes import ( WordNetAugmenter, diff --git a/textattack/augmentation/augmenter.py b/textattack/augmentation/augmenter.py index 1b8200e2..39b8269e 100644 --- a/textattack/augmentation/augmenter.py +++ b/textattack/augmentation/augmenter.py @@ -2,6 +2,7 @@ Augmenter Class =================== """ + import random import tqdm diff --git a/textattack/augmentation/recipes.py b/textattack/augmentation/recipes.py index fe647d9d..6d0c7d86 100644 --- a/textattack/augmentation/recipes.py +++ b/textattack/augmentation/recipes.py @@ -5,6 +5,7 @@ Transformations and constraints can be used for simple NLP data augmentations. Here is a list of recipes for NLP data augmentations """ + import random from textattack.constraints.pre_transformation import ( diff --git a/textattack/commands/__init__.py b/textattack/commands/__init__.py index b4446d34..b741e3c5 100644 --- a/textattack/commands/__init__.py +++ b/textattack/commands/__init__.py @@ -5,7 +5,6 @@ """ - from abc import ABC, abstractmethod from .textattack_command import TextAttackCommand from . import textattack_cli diff --git a/textattack/commands/eval_model_command.py b/textattack/commands/eval_model_command.py index 7957fbfe..c4dbb6b3 100644 --- a/textattack/commands/eval_model_command.py +++ b/textattack/commands/eval_model_command.py @@ -5,7 +5,6 @@ """ - from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser from dataclasses import dataclass diff --git a/textattack/commands/textattack_cli.py b/textattack/commands/textattack_cli.py index 219d6500..02ad8c5b 100644 --- a/textattack/commands/textattack_cli.py +++ b/textattack/commands/textattack_cli.py @@ -5,7 +5,6 @@ """ - # !/usr/bin/env python import argparse diff --git a/textattack/commands/train_model_command.py b/textattack/commands/train_model_command.py index b069c94b..36aa1bea 100644 --- a/textattack/commands/train_model_command.py +++ b/textattack/commands/train_model_command.py @@ -5,7 +5,6 @@ """ - from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser from textattack import CommandLineTrainingArgs, Trainer diff --git a/textattack/constraints/grammaticality/cola.py b/textattack/constraints/grammaticality/cola.py index 190bad25..0a4f1a05 100644 --- a/textattack/constraints/grammaticality/cola.py +++ b/textattack/constraints/grammaticality/cola.py @@ -3,6 +3,7 @@ -------------------------- """ + import lru import nltk from transformers import AutoModelForSequenceClassification, AutoTokenizer diff --git a/textattack/constraints/grammaticality/language_models/__init__.py b/textattack/constraints/grammaticality/language_models/__init__.py index ce726fc6..ddc20b98 100644 --- a/textattack/constraints/grammaticality/language_models/__init__.py +++ b/textattack/constraints/grammaticality/language_models/__init__.py @@ -4,7 +4,6 @@ """ - from .language_model_constraint import LanguageModelConstraint from .google_language_model import Google1BillionWordsLanguageModel diff --git a/textattack/constraints/grammaticality/language_models/google_language_model/__init__.py b/textattack/constraints/grammaticality/language_models/google_language_model/__init__.py index 803d2125..26045b75 100644 --- a/textattack/constraints/grammaticality/language_models/google_language_model/__init__.py +++ b/textattack/constraints/grammaticality/language_models/google_language_model/__init__.py @@ -4,7 +4,6 @@ """ - from .google_language_model import ( GoogleLanguageModel as Google1BillionWordsLanguageModel, ) diff --git a/textattack/constraints/grammaticality/language_models/google_language_model/alzantot_goog_lm.py b/textattack/constraints/grammaticality/language_models/google_language_model/alzantot_goog_lm.py index 005dda55..e23fcc61 100644 --- a/textattack/constraints/grammaticality/language_models/google_language_model/alzantot_goog_lm.py +++ b/textattack/constraints/grammaticality/language_models/google_language_model/alzantot_goog_lm.py @@ -7,7 +7,6 @@ All rights reserved. """ - import os import lru diff --git a/textattack/constraints/grammaticality/language_models/google_language_model/google_language_model.py b/textattack/constraints/grammaticality/language_models/google_language_model/google_language_model.py index 8e042ea5..fc79cc9c 100644 --- a/textattack/constraints/grammaticality/language_models/google_language_model/google_language_model.py +++ b/textattack/constraints/grammaticality/language_models/google_language_model/google_language_model.py @@ -3,6 +3,7 @@ -------------------------------------- """ + from collections import defaultdict import numpy as np diff --git a/textattack/constraints/grammaticality/language_models/google_language_model/lm_utils.py b/textattack/constraints/grammaticality/language_models/google_language_model/lm_utils.py index b4b15e0f..382a5977 100644 --- a/textattack/constraints/grammaticality/language_models/google_language_model/lm_utils.py +++ b/textattack/constraints/grammaticality/language_models/google_language_model/lm_utils.py @@ -5,6 +5,7 @@ Author: Moustafa Alzantot (malzantot@ucla.edu) All rights reserved. """ + import sys from textattack.shared.utils import LazyLoader diff --git a/textattack/constraints/grammaticality/language_models/gpt2.py b/textattack/constraints/grammaticality/language_models/gpt2.py index 7a8e862b..a7f8922d 100644 --- a/textattack/constraints/grammaticality/language_models/gpt2.py +++ b/textattack/constraints/grammaticality/language_models/gpt2.py @@ -4,7 +4,6 @@ """ - import os import torch diff --git a/textattack/constraints/grammaticality/language_models/learning_to_write/__init__.py b/textattack/constraints/grammaticality/language_models/learning_to_write/__init__.py index 16aa770d..a16e57b4 100644 --- a/textattack/constraints/grammaticality/language_models/learning_to_write/__init__.py +++ b/textattack/constraints/grammaticality/language_models/learning_to_write/__init__.py @@ -3,4 +3,5 @@ -------------------------- """ + from .learning_to_write import LearningToWriteLanguageModel diff --git a/textattack/constraints/grammaticality/language_models/learning_to_write/adaptive_softmax.py b/textattack/constraints/grammaticality/language_models/learning_to_write/adaptive_softmax.py index 610754f5..7de7ee58 100644 --- a/textattack/constraints/grammaticality/language_models/learning_to_write/adaptive_softmax.py +++ b/textattack/constraints/grammaticality/language_models/learning_to_write/adaptive_softmax.py @@ -3,7 +3,6 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ """ - import torch from torch import nn from torch.autograd import Variable diff --git a/textattack/constraints/grammaticality/language_models/learning_to_write/rnn_model.py b/textattack/constraints/grammaticality/language_models/learning_to_write/rnn_model.py index d43370eb..f486aadc 100644 --- a/textattack/constraints/grammaticality/language_models/learning_to_write/rnn_model.py +++ b/textattack/constraints/grammaticality/language_models/learning_to_write/rnn_model.py @@ -4,7 +4,6 @@ """ - from torch import nn as nn from torch.autograd import Variable diff --git a/textattack/constraints/grammaticality/language_tool.py b/textattack/constraints/grammaticality/language_tool.py index 0781b49f..50abcf0b 100644 --- a/textattack/constraints/grammaticality/language_tool.py +++ b/textattack/constraints/grammaticality/language_tool.py @@ -2,6 +2,7 @@ LanguageTool Grammar Checker ------------------------------ """ + import language_tool_python from textattack.constraints import Constraint diff --git a/textattack/constraints/grammaticality/part_of_speech.py b/textattack/constraints/grammaticality/part_of_speech.py index f531f33c..1cf2a404 100644 --- a/textattack/constraints/grammaticality/part_of_speech.py +++ b/textattack/constraints/grammaticality/part_of_speech.py @@ -2,6 +2,7 @@ Part of Speech Constraint -------------------------- """ + import flair from flair.data import Sentence from flair.models import SequenceTagger diff --git a/textattack/constraints/overlap/meteor_score.py b/textattack/constraints/overlap/meteor_score.py index 7a4eb9f1..fecb6256 100644 --- a/textattack/constraints/overlap/meteor_score.py +++ b/textattack/constraints/overlap/meteor_score.py @@ -6,7 +6,6 @@ """ - import nltk from textattack.constraints import Constraint diff --git a/textattack/constraints/pre_transformation/__init__.py b/textattack/constraints/pre_transformation/__init__.py index 98ab8352..acf8ad0c 100644 --- a/textattack/constraints/pre_transformation/__init__.py +++ b/textattack/constraints/pre_transformation/__init__.py @@ -5,6 +5,7 @@ Pre-transformation constraints determine if a transformation is valid based on only the original input and the position of the replacement. These constraints are applied before the transformation is even called. For example, these constraints can prevent search methods from swapping words at the same index twice, or from replacing stopwords. """ + from .stopword_modification import StopwordModification from .repeat_modification import RepeatModification from .input_column_modification import InputColumnModification diff --git a/textattack/constraints/pre_transformation/max_modification_rate.py b/textattack/constraints/pre_transformation/max_modification_rate.py index 0eba7b50..67a1e5a7 100644 --- a/textattack/constraints/pre_transformation/max_modification_rate.py +++ b/textattack/constraints/pre_transformation/max_modification_rate.py @@ -4,6 +4,7 @@ ----------------------------- """ + import math from textattack.constraints import PreTransformationConstraint diff --git a/textattack/constraints/pre_transformation/max_word_index_modification.py b/textattack/constraints/pre_transformation/max_word_index_modification.py index b0c796fc..520130e1 100644 --- a/textattack/constraints/pre_transformation/max_word_index_modification.py +++ b/textattack/constraints/pre_transformation/max_word_index_modification.py @@ -4,6 +4,7 @@ ----------------------------- """ + from textattack.constraints import PreTransformationConstraint diff --git a/textattack/constraints/semantics/__init__.py b/textattack/constraints/semantics/__init__.py index 716554eb..5f0d30d5 100644 --- a/textattack/constraints/semantics/__init__.py +++ b/textattack/constraints/semantics/__init__.py @@ -4,6 +4,7 @@ --------------------- Semantic constraints determine if a transformation is valid based on similarity of the semantics of the orignal input and the transformed input. """ + from . import sentence_encoders from .word_embedding_distance import WordEmbeddingDistance diff --git a/textattack/constraints/semantics/sentence_encoders/__init__.py b/textattack/constraints/semantics/sentence_encoders/__init__.py index 6c8e88b3..bcf3a1b0 100644 --- a/textattack/constraints/semantics/sentence_encoders/__init__.py +++ b/textattack/constraints/semantics/sentence_encoders/__init__.py @@ -3,7 +3,6 @@ ---------------------------- """ - from .sentence_encoder import SentenceEncoder from .bert import BERT diff --git a/textattack/constraints/semantics/sentence_encoders/infer_sent/__init__.py b/textattack/constraints/semantics/sentence_encoders/infer_sent/__init__.py index ecfaa05f..e4228248 100644 --- a/textattack/constraints/semantics/sentence_encoders/infer_sent/__init__.py +++ b/textattack/constraints/semantics/sentence_encoders/infer_sent/__init__.py @@ -3,5 +3,4 @@ ^^^^^^^^^^^^ """ - from .infer_sent import InferSent diff --git a/textattack/constraints/semantics/sentence_encoders/infer_sent/infer_sent_model.py b/textattack/constraints/semantics/sentence_encoders/infer_sent/infer_sent_model.py index 927d277d..b068960b 100644 --- a/textattack/constraints/semantics/sentence_encoders/infer_sent/infer_sent_model.py +++ b/textattack/constraints/semantics/sentence_encoders/infer_sent/infer_sent_model.py @@ -7,7 +7,6 @@ """ - # Copyright (c) 2017-present, Facebook, Inc. # All rights reserved. # @@ -209,9 +208,11 @@ def tokenize(self, s): def prepare_samples(self, sentences, bsize, tokenize, verbose): sentences = [ - [self.bos] + s.split() + [self.eos] - if not tokenize - else [self.bos] + self.tokenize(s) + [self.eos] + ( + [self.bos] + s.split() + [self.eos] + if not tokenize + else [self.bos] + self.tokenize(s) + [self.eos] + ) for s in sentences ] n_w = np.sum([len(x) for x in sentences]) diff --git a/textattack/constraints/semantics/sentence_encoders/universal_sentence_encoder/__init__.py b/textattack/constraints/semantics/sentence_encoders/universal_sentence_encoder/__init__.py index 2e3b5f10..4967402c 100644 --- a/textattack/constraints/semantics/sentence_encoders/universal_sentence_encoder/__init__.py +++ b/textattack/constraints/semantics/sentence_encoders/universal_sentence_encoder/__init__.py @@ -3,7 +3,6 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ """ - from .universal_sentence_encoder import UniversalSentenceEncoder from .multilingual_universal_sentence_encoder import ( MultilingualUniversalSentenceEncoder, diff --git a/textattack/datasets/helpers/ted_multi.py b/textattack/datasets/helpers/ted_multi.py index 9e36c269..2093b0a7 100644 --- a/textattack/datasets/helpers/ted_multi.py +++ b/textattack/datasets/helpers/ted_multi.py @@ -4,7 +4,6 @@ ------------------------------------ """ - import collections import datasets diff --git a/textattack/goal_function_results/__init__.py b/textattack/goal_function_results/__init__.py index 31891ecd..26b922dc 100644 --- a/textattack/goal_function_results/__init__.py +++ b/textattack/goal_function_results/__init__.py @@ -5,6 +5,7 @@ Goal function results report the result of a goal function evaluation, indicating whether an attack succeeded for a given example. """ + from .goal_function_result import GoalFunctionResult, GoalFunctionResultStatus from .classification_goal_function_result import ClassificationGoalFunctionResult diff --git a/textattack/goal_functions/classification/classification_goal_function.py b/textattack/goal_functions/classification/classification_goal_function.py index 77fb10b1..3c08ccef 100644 --- a/textattack/goal_functions/classification/classification_goal_function.py +++ b/textattack/goal_functions/classification/classification_goal_function.py @@ -3,7 +3,6 @@ --------------------------------------------------------------------- """ - import numpy as np import torch diff --git a/textattack/goal_functions/classification/hardlabel_classification.py b/textattack/goal_functions/classification/hardlabel_classification.py index 354225d8..5c707496 100644 --- a/textattack/goal_functions/classification/hardlabel_classification.py +++ b/textattack/goal_functions/classification/hardlabel_classification.py @@ -3,7 +3,6 @@ ------------------------------------------------------------------------ """ - from .classification_goal_function import ClassificationGoalFunction diff --git a/textattack/goal_functions/classification/input_reduction.py b/textattack/goal_functions/classification/input_reduction.py index 40769ae7..686a7a6a 100644 --- a/textattack/goal_functions/classification/input_reduction.py +++ b/textattack/goal_functions/classification/input_reduction.py @@ -4,7 +4,6 @@ --------------------------------------------------------------------- """ - from .classification_goal_function import ClassificationGoalFunction diff --git a/textattack/goal_functions/classification/targeted_classification.py b/textattack/goal_functions/classification/targeted_classification.py index 25336521..3b1ad3ac 100644 --- a/textattack/goal_functions/classification/targeted_classification.py +++ b/textattack/goal_functions/classification/targeted_classification.py @@ -4,7 +4,6 @@ ----------------------------------------------------------------------- """ - from .classification_goal_function import ClassificationGoalFunction diff --git a/textattack/goal_functions/classification/untargeted_classification.py b/textattack/goal_functions/classification/untargeted_classification.py index 5540488d..c9577b2b 100644 --- a/textattack/goal_functions/classification/untargeted_classification.py +++ b/textattack/goal_functions/classification/untargeted_classification.py @@ -4,7 +4,6 @@ ---------------------------------------------------- """ - from .classification_goal_function import ClassificationGoalFunction diff --git a/textattack/goal_functions/goal_function.py b/textattack/goal_functions/goal_function.py index 5d51bdf0..712ed703 100644 --- a/textattack/goal_functions/goal_function.py +++ b/textattack/goal_functions/goal_function.py @@ -4,7 +4,6 @@ =========================================================== """ - from abc import ABC, abstractmethod import lru diff --git a/textattack/goal_functions/text/non_overlapping_output.py b/textattack/goal_functions/text/non_overlapping_output.py index e2cb4982..347f163f 100644 --- a/textattack/goal_functions/text/non_overlapping_output.py +++ b/textattack/goal_functions/text/non_overlapping_output.py @@ -4,7 +4,6 @@ ------------------------------------------------------- """ - import functools import numpy as np diff --git a/textattack/loggers/logger.py b/textattack/loggers/logger.py index 7e979b2b..2c85cd12 100644 --- a/textattack/loggers/logger.py +++ b/textattack/loggers/logger.py @@ -3,7 +3,6 @@ ======================== """ - from abc import ABC diff --git a/textattack/loggers/visdom_logger.py b/textattack/loggers/visdom_logger.py index 80ab1b90..ccd3d10b 100644 --- a/textattack/loggers/visdom_logger.py +++ b/textattack/loggers/visdom_logger.py @@ -3,7 +3,6 @@ ======================== """ - import socket from textattack.shared.utils import LazyLoader, html_table_from_rows diff --git a/textattack/loggers/weights_and_biases_logger.py b/textattack/loggers/weights_and_biases_logger.py index 7b999042..92c47a38 100644 --- a/textattack/loggers/weights_and_biases_logger.py +++ b/textattack/loggers/weights_and_biases_logger.py @@ -3,7 +3,6 @@ ======================== """ - from textattack.shared.utils import LazyLoader, html_table_from_rows from .logger import Logger diff --git a/textattack/metrics/attack_metrics/words_perturbed.py b/textattack/metrics/attack_metrics/words_perturbed.py index 6104de1b..38c11b29 100644 --- a/textattack/metrics/attack_metrics/words_perturbed.py +++ b/textattack/metrics/attack_metrics/words_perturbed.py @@ -65,9 +65,9 @@ def calculate(self, results): self.all_metrics["avg_word_perturbed"] = self.avg_number_word_perturbed_num() self.all_metrics["avg_word_perturbed_perc"] = self.avg_perturbation_perc() self.all_metrics["max_words_changed"] = self.max_words_changed - self.all_metrics[ - "num_words_changed_until_success" - ] = self.num_words_changed_until_success + self.all_metrics["num_words_changed_until_success"] = ( + self.num_words_changed_until_success + ) return self.all_metrics diff --git a/textattack/model_args.py b/textattack/model_args.py index 73c133cf..a0086d43 100644 --- a/textattack/model_args.py +++ b/textattack/model_args.py @@ -3,7 +3,6 @@ =============== """ - from dataclasses import dataclass import json import os diff --git a/textattack/models/__init__.py b/textattack/models/__init__.py index c267e7b1..a3e96e24 100644 --- a/textattack/models/__init__.py +++ b/textattack/models/__init__.py @@ -35,7 +35,6 @@ We've also provided implementations of model wrappers for common patterns in some popular machine learning frameworks: including pytorch / sklearn / tensorflow. """ - from . import helpers from . import tokenizers from . import wrappers diff --git a/textattack/models/helpers/__init__.py b/textattack/models/helpers/__init__.py index 74adc8b2..04a90ae1 100644 --- a/textattack/models/helpers/__init__.py +++ b/textattack/models/helpers/__init__.py @@ -3,7 +3,6 @@ ------------------ """ - # Helper stuff, like embeddings. from . import utils from .glove_embedding_layer import GloveEmbeddingLayer diff --git a/textattack/models/helpers/lstm_for_classification.py b/textattack/models/helpers/lstm_for_classification.py index 8e2f32a0..1183b1a6 100644 --- a/textattack/models/helpers/lstm_for_classification.py +++ b/textattack/models/helpers/lstm_for_classification.py @@ -3,6 +3,7 @@ --------------------------------------------------------------------- """ + import json import os diff --git a/textattack/models/helpers/t5_for_text_to_text.py b/textattack/models/helpers/t5_for_text_to_text.py index e6df4df7..b044f580 100644 --- a/textattack/models/helpers/t5_for_text_to_text.py +++ b/textattack/models/helpers/t5_for_text_to_text.py @@ -3,6 +3,7 @@ --------------------------------------------------------------------- """ + import json import os diff --git a/textattack/models/helpers/utils.py b/textattack/models/helpers/utils.py index 445872a6..347e7e96 100644 --- a/textattack/models/helpers/utils.py +++ b/textattack/models/helpers/utils.py @@ -4,7 +4,6 @@ """ - import glob import os diff --git a/textattack/models/helpers/word_cnn_for_classification.py b/textattack/models/helpers/word_cnn_for_classification.py index d015f9dd..d7f57f9a 100644 --- a/textattack/models/helpers/word_cnn_for_classification.py +++ b/textattack/models/helpers/word_cnn_for_classification.py @@ -3,6 +3,7 @@ --------------------------------------------------------------------- """ + import json import os diff --git a/textattack/models/tokenizers/__init__.py b/textattack/models/tokenizers/__init__.py index 5c5cba32..4d483606 100644 --- a/textattack/models/tokenizers/__init__.py +++ b/textattack/models/tokenizers/__init__.py @@ -3,6 +3,5 @@ ------------------------------- """ - from .glove_tokenizer import GloveTokenizer from .t5_tokenizer import T5Tokenizer diff --git a/textattack/models/tokenizers/glove_tokenizer.py b/textattack/models/tokenizers/glove_tokenizer.py index 6deb616f..004bed24 100644 --- a/textattack/models/tokenizers/glove_tokenizer.py +++ b/textattack/models/tokenizers/glove_tokenizer.py @@ -4,7 +4,6 @@ """ - import json import tempfile diff --git a/textattack/models/wrappers/pytorch_model_wrapper.py b/textattack/models/wrappers/pytorch_model_wrapper.py index 054f8e33..094b4d8f 100644 --- a/textattack/models/wrappers/pytorch_model_wrapper.py +++ b/textattack/models/wrappers/pytorch_model_wrapper.py @@ -3,7 +3,6 @@ -------------------------- """ - import torch from torch.nn import CrossEntropyLoss diff --git a/textattack/models/wrappers/sklearn_model_wrapper.py b/textattack/models/wrappers/sklearn_model_wrapper.py index 728e02ac..9c9d8074 100644 --- a/textattack/models/wrappers/sklearn_model_wrapper.py +++ b/textattack/models/wrappers/sklearn_model_wrapper.py @@ -3,7 +3,6 @@ -------------------------- """ - import pandas as pd from .model_wrapper import ModelWrapper diff --git a/textattack/models/wrappers/tensorflow_model_wrapper.py b/textattack/models/wrappers/tensorflow_model_wrapper.py index 25d0a2b5..8ef13ac2 100644 --- a/textattack/models/wrappers/tensorflow_model_wrapper.py +++ b/textattack/models/wrappers/tensorflow_model_wrapper.py @@ -3,7 +3,6 @@ -------------------------- """ - import numpy as np from .model_wrapper import ModelWrapper diff --git a/textattack/prompt_augmentation/__init__.py b/textattack/prompt_augmentation/__init__.py index 10f87653..2f8a3c48 100644 --- a/textattack/prompt_augmentation/__init__.py +++ b/textattack/prompt_augmentation/__init__.py @@ -6,5 +6,4 @@ """ - from .prompt_augmentation_pipeline import PromptAugmentationPipeline diff --git a/textattack/search_methods/__init__.py b/textattack/search_methods/__init__.py index 660a1e1d..b5e26291 100644 --- a/textattack/search_methods/__init__.py +++ b/textattack/search_methods/__init__.py @@ -5,6 +5,7 @@ Search methods explore the transformation space in an attempt to find a successful attack as determined by a :ref:`Goal Functions ` and list of :ref:`Constraints ` """ + from .search_method import SearchMethod from .beam_search import BeamSearch from .greedy_search import GreedySearch diff --git a/textattack/search_methods/beam_search.py b/textattack/search_methods/beam_search.py index 49b9c855..208911a8 100644 --- a/textattack/search_methods/beam_search.py +++ b/textattack/search_methods/beam_search.py @@ -3,6 +3,7 @@ =============== """ + import numpy as np from textattack.goal_function_results import GoalFunctionResultStatus diff --git a/textattack/search_methods/genetic_algorithm.py b/textattack/search_methods/genetic_algorithm.py index b5d97cf1..c857f20c 100644 --- a/textattack/search_methods/genetic_algorithm.py +++ b/textattack/search_methods/genetic_algorithm.py @@ -2,6 +2,7 @@ Genetic Algorithm Word Swap ==================================== """ + from abc import ABC, abstractmethod import numpy as np diff --git a/textattack/search_methods/greedy_search.py b/textattack/search_methods/greedy_search.py index f59570ed..54c4a40f 100644 --- a/textattack/search_methods/greedy_search.py +++ b/textattack/search_methods/greedy_search.py @@ -2,6 +2,7 @@ Greedy Search ================= """ + from .beam_search import BeamSearch diff --git a/textattack/search_methods/particle_swarm_optimization.py b/textattack/search_methods/particle_swarm_optimization.py index b731c9ed..fdc48aa0 100644 --- a/textattack/search_methods/particle_swarm_optimization.py +++ b/textattack/search_methods/particle_swarm_optimization.py @@ -10,6 +10,7 @@ ``_ ``_ """ + import copy import numpy as np @@ -119,9 +120,9 @@ def _turn(self, source_text, target_text, prob, original_text): & indices_to_replace ) if "last_transformation" in source_text.attacked_text.attack_attrs: - new_text.attack_attrs[ - "last_transformation" - ] = source_text.attacked_text.attack_attrs["last_transformation"] + new_text.attack_attrs["last_transformation"] = ( + source_text.attacked_text.attack_attrs["last_transformation"] + ) if not self.post_turn_check or (new_text.words == source_text.words): break diff --git a/textattack/search_methods/search_method.py b/textattack/search_methods/search_method.py index 76b5981b..39026281 100644 --- a/textattack/search_methods/search_method.py +++ b/textattack/search_methods/search_method.py @@ -3,7 +3,6 @@ =============================== """ - from abc import ABC, abstractmethod from textattack.shared.utils import ReprMixin diff --git a/textattack/shared/__init__.py b/textattack/shared/__init__.py index 2855c219..2adaf6b2 100644 --- a/textattack/shared/__init__.py +++ b/textattack/shared/__init__.py @@ -6,7 +6,6 @@ """ - from . import data from . import utils from .utils import logger diff --git a/textattack/shared/checkpoint.py b/textattack/shared/checkpoint.py index f0e91d9f..1f78a5da 100644 --- a/textattack/shared/checkpoint.py +++ b/textattack/shared/checkpoint.py @@ -4,6 +4,7 @@ The ``AttackCheckpoint`` class saves in-progress attacks and loads saved attacks from disk. """ + import copy import datetime import os diff --git a/textattack/shared/data.py b/textattack/shared/data.py index 37594f57..59db4f36 100644 --- a/textattack/shared/data.py +++ b/textattack/shared/data.py @@ -8,7 +8,6 @@ """ - # fmt: off NAMED_ENTITIES = { "country": [ @@ -9431,7 +9430,23 @@ ["切", "彻", "砌", "沏"], ["高", "稿", "搞"], ["鬲", "隔", "融", "嗝"], - ["亘", "恒", "宣", "喧", "楦", "渲", "桓", "垣", "晅", "萱", "暄", "喧", "瑄", "烜", "楦"], + [ + "亘", + "恒", + "宣", + "喧", + "楦", + "渲", + "桓", + "垣", + "晅", + "萱", + "暄", + "喧", + "瑄", + "烜", + "楦", + ], ["更", "硬", "便", "梗", "更"], ["勾", "构", "钩", "沟"], ["谷", "俗", "裕", "豁", "浴"], @@ -9548,7 +9563,22 @@ ["正", "证", "症", "政", "征"], ["留", "溜", "榴", "榴"], ["旦", "担", "坦"], - ["非", "韭", "徘", "辈", "悲", "斐", "裴", "靠", "扉", "霏", "菲", "匪", "蜚", "排"], + [ + "非", + "韭", + "徘", + "辈", + "悲", + "斐", + "裴", + "靠", + "扉", + "霏", + "菲", + "匪", + "蜚", + "排", + ], ["旬", "询", "殉"], ["刑", "型"], ["弟", "第", "递", "梯", "剃", "涕"], diff --git a/textattack/transformations/__init__.py b/textattack/transformations/__init__.py index 97619986..a17ebd26 100644 --- a/textattack/transformations/__init__.py +++ b/textattack/transformations/__init__.py @@ -5,6 +5,7 @@ A transformation is a method which perturbs a text input through the insertion, deletion and substiution of words, characters, and phrases. All transformations take a ``TokenizedText`` as input and return a list of ``TokenizedText`` that contains possible transformations. Every transformation is a subclass of the abstract ``Transformation`` class. """ + from .transformation import Transformation from .sentence_transformations import * diff --git a/textattack/transformations/sentence_transformations/back_translation.py b/textattack/transformations/sentence_transformations/back_translation.py index 5cd4e385..ec0b772f 100644 --- a/textattack/transformations/sentence_transformations/back_translation.py +++ b/textattack/transformations/sentence_transformations/back_translation.py @@ -4,7 +4,6 @@ """ - import random from transformers import MarianMTModel, MarianTokenizer diff --git a/textattack/transformations/sentence_transformations/sentence_transformation.py b/textattack/transformations/sentence_transformations/sentence_transformation.py index ea7baea1..cbe0d727 100644 --- a/textattack/transformations/sentence_transformations/sentence_transformation.py +++ b/textattack/transformations/sentence_transformations/sentence_transformation.py @@ -6,7 +6,6 @@ """ - from textattack.transformations import Transformation diff --git a/textattack/transformations/word_innerswap_random.py b/textattack/transformations/word_innerswap_random.py index 2d0693bb..1ef8103c 100644 --- a/textattack/transformations/word_innerswap_random.py +++ b/textattack/transformations/word_innerswap_random.py @@ -3,7 +3,6 @@ ========================================================== """ - import random from textattack.transformations import Transformation diff --git a/textattack/transformations/word_insertions/word_insertion.py b/textattack/transformations/word_insertions/word_insertion.py index def4809b..da567cfb 100644 --- a/textattack/transformations/word_insertions/word_insertion.py +++ b/textattack/transformations/word_insertions/word_insertion.py @@ -5,6 +5,7 @@ For example, if we insert "new" in position 3 in the text "I like the movie", we get "I like the new movie". Subclasses can implement the abstract ``WordInsertion`` class by overriding ``self._get_new_words``. """ + from textattack.transformations import Transformation diff --git a/textattack/transformations/word_insertions/word_insertion_masked_lm.py b/textattack/transformations/word_insertions/word_insertion_masked_lm.py index d768a588..8dd759b6 100644 --- a/textattack/transformations/word_insertions/word_insertion_masked_lm.py +++ b/textattack/transformations/word_insertions/word_insertion_masked_lm.py @@ -2,6 +2,7 @@ WordInsertionMaskedLM Class ------------------------------- """ + import re import torch diff --git a/textattack/transformations/word_merges/word_merge.py b/textattack/transformations/word_merges/word_merge.py index 6194970a..b1078ed7 100644 --- a/textattack/transformations/word_merges/word_merge.py +++ b/textattack/transformations/word_merges/word_merge.py @@ -5,6 +5,7 @@ For example, if we can merge the words "the" and "movie" in the text "I like the movie" and get following text: "I like film". When we choose to "merge" word at index ``i``, we merge it with the next word at ``i+1``. """ + from textattack.transformations import Transformation diff --git a/textattack/transformations/word_merges/word_merge_masked_lm.py b/textattack/transformations/word_merges/word_merge_masked_lm.py index b13c43df..afb95730 100644 --- a/textattack/transformations/word_merges/word_merge_masked_lm.py +++ b/textattack/transformations/word_merges/word_merge_masked_lm.py @@ -3,6 +3,7 @@ ------------------------------------------------ """ + import re import torch diff --git a/textattack/transformations/word_swaps/__init__.py b/textattack/transformations/word_swaps/__init__.py index 431e0e34..31163d3d 100644 --- a/textattack/transformations/word_swaps/__init__.py +++ b/textattack/transformations/word_swaps/__init__.py @@ -4,7 +4,6 @@ """ - from .word_swap import WordSwap # Black box transformations diff --git a/textattack/transformations/word_swaps/chn_transformations/chinese_homophone_character_swap.py b/textattack/transformations/word_swaps/chn_transformations/chinese_homophone_character_swap.py index 1f2a47a1..31901078 100644 --- a/textattack/transformations/word_swaps/chn_transformations/chinese_homophone_character_swap.py +++ b/textattack/transformations/word_swaps/chn_transformations/chinese_homophone_character_swap.py @@ -3,7 +3,6 @@ ------------------------------------- """ - import os import pandas as pd diff --git a/textattack/transformations/word_swaps/word_swap.py b/textattack/transformations/word_swaps/word_swap.py index c51e8056..69c11fab 100644 --- a/textattack/transformations/word_swaps/word_swap.py +++ b/textattack/transformations/word_swaps/word_swap.py @@ -4,6 +4,7 @@ Word swap transformations act by replacing some words in the input. Subclasses can implement the abstract ``WordSwap`` class by overriding ``self._get_replacement_words`` """ + import random import string diff --git a/textattack/transformations/word_swaps/word_swap_change_location.py b/textattack/transformations/word_swaps/word_swap_change_location.py index 916b97d3..0e2d0218 100644 --- a/textattack/transformations/word_swaps/word_swap_change_location.py +++ b/textattack/transformations/word_swaps/word_swap_change_location.py @@ -2,6 +2,7 @@ Word Swap by Changing Location ------------------------------- """ + from collections import defaultdict import more_itertools as mit diff --git a/textattack/transformations/word_swaps/word_swap_change_number.py b/textattack/transformations/word_swaps/word_swap_change_number.py index d30df1cf..9cb6b16a 100644 --- a/textattack/transformations/word_swaps/word_swap_change_number.py +++ b/textattack/transformations/word_swaps/word_swap_change_number.py @@ -3,6 +3,7 @@ ------------------------------- """ + import more_itertools as mit from num2words import num2words import numpy as np diff --git a/textattack/transformations/word_swaps/word_swap_embedding.py b/textattack/transformations/word_swaps/word_swap_embedding.py index 386cddc3..e1bcbadc 100644 --- a/textattack/transformations/word_swaps/word_swap_embedding.py +++ b/textattack/transformations/word_swaps/word_swap_embedding.py @@ -7,6 +7,7 @@ Paper title: Counter-fitting Word Vectors to Linguistic Constraints """ + from textattack.shared import AbstractWordEmbedding, WordEmbedding from .word_swap import WordSwap diff --git a/textattack/transformations/word_swaps/word_swap_gradient_based.py b/textattack/transformations/word_swaps/word_swap_gradient_based.py index 0d12fa18..ff9a6ef3 100644 --- a/textattack/transformations/word_swaps/word_swap_gradient_based.py +++ b/textattack/transformations/word_swaps/word_swap_gradient_based.py @@ -3,6 +3,7 @@ ------------------------------- """ + import torch import textattack diff --git a/textattack/transformations/word_swaps/word_swap_homoglyph_swap.py b/textattack/transformations/word_swaps/word_swap_homoglyph_swap.py index 34a64297..089580bd 100644 --- a/textattack/transformations/word_swaps/word_swap_homoglyph_swap.py +++ b/textattack/transformations/word_swaps/word_swap_homoglyph_swap.py @@ -2,6 +2,7 @@ Word Swap by Homoglyph ------------------------------- """ + import numpy as np # from textattack.shared import utils diff --git a/textattack/transformations/word_swaps/word_swap_hownet.py b/textattack/transformations/word_swaps/word_swap_hownet.py index 1738e60c..926f1e29 100644 --- a/textattack/transformations/word_swaps/word_swap_hownet.py +++ b/textattack/transformations/word_swaps/word_swap_hownet.py @@ -3,7 +3,6 @@ ------------------------------- """ - import pickle from textattack.shared import utils diff --git a/textattack/transformations/word_swaps/word_swap_inflections.py b/textattack/transformations/word_swaps/word_swap_inflections.py index da238036..992e5a2f 100644 --- a/textattack/transformations/word_swaps/word_swap_inflections.py +++ b/textattack/transformations/word_swaps/word_swap_inflections.py @@ -5,7 +5,6 @@ """ - import random import lemminflect diff --git a/textattack/transformations/word_swaps/word_swap_masked_lm.py b/textattack/transformations/word_swaps/word_swap_masked_lm.py index e031f0ea..99788b83 100644 --- a/textattack/transformations/word_swaps/word_swap_masked_lm.py +++ b/textattack/transformations/word_swaps/word_swap_masked_lm.py @@ -3,7 +3,6 @@ ------------------------------- """ - import itertools import re diff --git a/textattack/transformations/word_swaps/word_swap_random_character_insertion.py b/textattack/transformations/word_swaps/word_swap_random_character_insertion.py index 517e1bfd..31de91c4 100644 --- a/textattack/transformations/word_swaps/word_swap_random_character_insertion.py +++ b/textattack/transformations/word_swaps/word_swap_random_character_insertion.py @@ -3,6 +3,7 @@ ------------------------------------------------ """ + import numpy as np # from textattack.shared import utils diff --git a/textattack/transformations/word_swaps/word_swap_random_character_substitution.py b/textattack/transformations/word_swaps/word_swap_random_character_substitution.py index 23c8427c..e040d159 100644 --- a/textattack/transformations/word_swaps/word_swap_random_character_substitution.py +++ b/textattack/transformations/word_swaps/word_swap_random_character_substitution.py @@ -2,6 +2,7 @@ Word Swap by Random Character Substitution ------------------------------------------------ """ + import numpy as np # from textattack.shared import utils diff --git a/textattack/transformations/word_swaps/word_swap_wordnet.py b/textattack/transformations/word_swaps/word_swap_wordnet.py index 5dfa1c18..9f98a8d4 100644 --- a/textattack/transformations/word_swaps/word_swap_wordnet.py +++ b/textattack/transformations/word_swaps/word_swap_wordnet.py @@ -3,7 +3,6 @@ ------------------------------------------------ """ - import nltk from nltk.corpus import wordnet