New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] FEAT Add adversarial suffix attack GCG #180
base: main
Are you sure you want to change the base?
Conversation
@NaijingGuo please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
pyrit/adv_suffix/experiments/main.py
Outdated
worker.stop() | ||
|
||
|
||
if __name__ == "__main__": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a "main" script, let's have a class, e.g., GreedyCoordinateGradientAdversarialSuffixGenerator
(wow that's long...) that takes the parameters as inputs and has a method generate_suffix
. We can call it from a notebook (I would put it under doc/demo/7_adversarial_suffix
(the number may change but that's fine).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed the code to put things in a class as suggested, generate_suffix under the class can be called from outside. The change can be seen in 2 files, named test_main.py
(contains the class) and test_demo.py
(contains example usage of the class).
However, because the original code uses multiprocessing, if __name__ == "__main__"
guard is required to run the code, and this would also introduces difficulty running in Jupyter notebook (although I have been using python scripts only, since the school cluster does not support notebook). My main reference is here:
- Torch.multiprocessing pool hangs in Jupyter notebooks pytorch/pytorch#17680
- https://stackoverflow.com/questions/20360686/compulsory-usage-of-if-name-main-in-windows-while-using-multiprocessi
In other words, in my test_demo.py
, I cannot remove if __name__ == "__main__
and run generate_suffix
directly. I have not found a way to circumvent this yet (but I'm completely new to multiprocessing, there might be ways that I have not dug up yet somewhere in Stack Overflow...)
I was wondering if if __name__ == "__main__"
guard is a huge problem and we should stop using multiprocessing altogether, or we can keep the demo like test_demo.py
for now, or there are some ways that you know that can help circumvent this problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry about notebooks. I expect this code will always be executed on a compute node of some kind using a little script that has the main guard BUT the logic should be only in the code files if that makes sense. For example, we have all our logic in the pyrit package today and can call it in a notebook. But we could just as well use a little python script to call it without a notebook. The notebook is just one way.
Do you have a recommendation on how to run it? I can try if it works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the test_demo.py
file would be the little script to run suffix generation (I can run it without any problem, but please let me know if it doesn't work for you). The main logic is in the test_main.py
, and test_demo.py
only specifies model name and training parameters, like training steps, batch size, etc..
(The two files were called test_xxx
because they are my draft to refactor the original main and the bash script to run main. I have not deleted the original code yet.)
# data = json.load(open('eval/individual_behavior_controls.json', 'r')) | ||
|
||
|
||
if __name__ == "__main__": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's try to put everything in classes & functions, and call them from notebooks under doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have refactored the parse_scirpt.py
and the evaluation into a class called AdversarialSuffixEvaluator
(this class in the new test_evaluation.py
. And an example to run the evaluation can be found in the new test_eval_demo.py
.
If the evaluator and generator class both looks good, I will combine the demo code files such that it can run both generation and evaluation.
del control_cands, loss | ||
gc.collect() | ||
|
||
print("Current length:", len(self.workers[0].tokenizer(next_control).input_ids[1:])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not urgent, but eventually we'd want to use the logger the same way we do elsewhere in the repo. That way, you can specify the desired log level and only see the corresponding output.
FYI #192 (comment) |
… files to read from YAML.
Description
suffix attack from https://arxiv.org/pdf/2307.15043.pdf
TODO:
Tests and Documentation
Tests and documentation to be added.