Skip to content
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

Feature/multilingual #943

Open
wants to merge 40 commits into
base: main
Choose a base branch
from

Conversation

SnowMasaya
Copy link

@SnowMasaya SnowMasaya commented Oct 9, 2024

This revision enables translation support for a streamlined the use case. Some items such
as support for multiple target languages in a single run have been omitted in favor of a
more straight forward user experience and reduced ambiguity in the scope of results.

Translator classes have been implemented using the Configurable pattern and the plugin
loader. This introduced a new paradigm of providing configuration for a list of instances
with specific configuration required at runtime where previous Configurable class
configuration has been for all instances of a specific class or module. The processing and
attribute names used to create this instance list may evolve further.

Usage

Translation function is configured in the run section of a configuration see the doc
page in the PR for details.

New default configuration values for run.lang_spec and run.translators are in the
updated documentation and allow for backwards compatible configuration with existing runs.

There are still some existing TODO: comments and notes about location that may need
further testing before landing this upstream. Most noteworthy are comments still in the
code of the atkgen probe that require further scrutiny to validate the attack technique
is applied correctly.

It may be appropriate to gate this functionality as experimental for initial release, this
would required some additional guard code to ensure limited impact to report formats and
internal state.

Example

python -m garak -m huggingface.Model --config hf_RigoChat_gpu.yml -p lmrc --report_prefix RigoChat-21fde039

hf_RigoChat_gpu.yml:

run:
  lang_spec: "es"
  translators:
    - language: es-en
      model_type: local
      model_name: facebook/m2m100_418M
      hf_args:
        device: cuda
    - language: en-es
      model_type: local
      model_name: facebook/m2m100_418M
      hf_args:
        device: cuda
plugins:
  generators:
    huggingface:
      Model:
        name: IIC/RigoChat-7b-v2
        hf_args:
          device: cuda
          trust_remote_code: true
          torch_dtype: float16

Copy link
Contributor

github-actions bot commented Oct 9, 2024

DCO Assistant Lite bot All contributors have signed the DCO ✍️ ✅

- Integrated support for multiple translation services including local and external APIs.
  - local: Huggingface model uses for translation
  - deepl:DeepL uses for translation
  - nim: NIM uses for translation
- Implemented utility functions for language detection and text processing.

Signed-off-by: Masaya Ogushi <[email protected]>
- Addd translation function for base probe class
- prompts and triggers translate by base class method
- attempt_descr translation

Signed-off-by: Masaya Ogushi <[email protected]>
- Translation handling for detector keywords and substrings, triggers.

Signed-off-by: Masaya Ogushi <[email protected]>
- Added support for specifying translation services directly from the CLI.
- Implemented options to set  target languages for translation.

Signed-off-by: Masaya Ogushi <[email protected]>
- Added new dependencies required for enhanced translation features.

Signed-off-by: Masaya Ogushi <[email protected]>
- Added detailed explanations of the translationn method
- Included examples of how translation services are configured and utilized within the codebase.

Signed-off-by: Masaya Ogushi <[email protected]>
@SnowMasaya SnowMasaya force-pushed the feature/multilingual branch from b781a6f to 6bb7da3 Compare October 9, 2024 01:41
@SnowMasaya
Copy link
Author

SnowMasaya commented Oct 9, 2024

I have read the DCO Document and I hereby sign the DCO

Copy link
Collaborator

@jmartin-tech jmartin-tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review, testing is still in progress.

The test failures in macOS look to be an incomplete dependency requirement that may need to be reworked or removed. A default installation should not require install of an external library. Hence the dependency on pyenchant here may be problematic.

Traceback:
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/detectors/test_detectors_riskywords.py:8: in <module>
    import garak.detectors.base
garak/detectors/__init__.py:1: in <module>
    from .base import *
garak/detectors/base.py:17: in <module>
    from garak.translator import SimpleTranslator, LocalTranslator, is_english
garak/translator.py:15: in <module>
    import enchant
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/enchant/__init__.py:81: in <module>
    from enchant import _enchant as _e
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/enchant/_enchant.py:[157](https://github.com/leondz/garak/actions/runs/11246708414/job/31296143918?pr=943#step:5:158): in <module>
    raise ImportError(msg)
E   ImportError: The 'enchant' C library was not found and maybe needs to be installed.
E   See  https://pyenchant.github.io/pyenchant/install.html
E   for details

requirements.txt Outdated Show resolved Hide resolved
garak/probes/base.py Outdated Show resolved Hide resolved
garak/probes/base.py Outdated Show resolved Hide resolved
tests/detectors/test_detectors.py Outdated Show resolved Hide resolved
tests/detectors/test_leakreplay.py Outdated Show resolved Hide resolved
tests/test_translator.py Outdated Show resolved Hide resolved
tests/test_translator.py Outdated Show resolved Hide resolved
garak/cli.py Outdated Show resolved Hide resolved
tests/test_translator.py Outdated Show resolved Hide resolved
garak/translator.py Outdated Show resolved Hide resolved
update remove punctuation
update english judge
add translate function
add logging translate result
add Reverse translate for hf detector and snowball probes

Signed-off-by: Masaya Ogushi <[email protected]>
check translator instance
remove translate function
reset config

Signed-off-by: Masaya Ogushi <[email protected]>
check translator instance
add reverse translator
add test reverse translator

Signed-off-by: Masaya Ogushi <[email protected]>
remove argument
using generator_option_file

Signed-off-by: Masaya Ogushi <[email protected]>
add load translator instance

Signed-off-by: Masaya Ogushi <[email protected]>
check storage size
set up each instance for each test

Signed-off-by: Masaya Ogushi <[email protected]>
remove pyenchant
Using nltk instead of pyenchant

Signed-off-by: Masaya Ogushi <[email protected]>
update how to use translation function

Signed-off-by: Masaya Ogushi <[email protected]>
github-actions bot added a commit that referenced this pull request Oct 23, 2024
Copy link
Collaborator

@leondz leondz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, this is a significant amount of work.

This is for translation-based multilingual, rather than general multilingual support, so we should be careful to separate these two functions. The ability to select which languages garak uses is distinct from how that language is achieved (in prompts, detectors, and so on).

There are some refactorings needed to get the PR to a sustainable state. We may need a couple more hooks, either injected into base classes or added there. It might be simplest to add these hooks to the harness. Happy to set up a call or instant message chat to discuss this. Given the breadth of the changes, it is likely to be beneficial to discuss plans and get good alignment while doing the rest of the changes.

garak/detectors/base.py Outdated Show resolved Hide resolved
garak/detectors/base.py Outdated Show resolved Hide resolved
Comment on lines 161 to 163
if hasattr(self, 'reverse_translator'):
if self.reverse_translator is not None:
non_none_outputs = self.reverse_translator.translate_prompts(non_none_outputs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we handle this in the harness rather than the detector? It's an orchestration issue

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I try it.

Comment on lines 200 to 202
if hasattr(self, 'translator'):
if self.translator is not None:
self.substrings = self.translator.translate_prompts(self.substrings)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we handle this in the harness?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I try it.

garak/detectors/leakreplay.py Outdated Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider factoring up to harness

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider factoring up to harness

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

garak/detectors/base.py Outdated Show resolved Hide resolved
docs/source/translator.rst Outdated Show resolved Hide resolved
docs/source/translator.rst Outdated Show resolved Hide resolved
Copy link
Collaborator

@jmartin-tech jmartin-tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SnowMasaya thank you, this is a significant benefit for the project.

Adding a number of my pending comments here, please be aware these are likely similar to many @leondz made, although possibly from different reasoning. Happy to continue iterating.

garak/detectors/base.py Outdated Show resolved Hide resolved
docs/source/translator.rst Outdated Show resolved Hide resolved
garak/detectors/base.py Outdated Show resolved Hide resolved
Comment on lines 143 to 147
if hasattr(self, 'translator'):
if self.translator is not None:
challenges = self.translator.translate_prompts([challenge])
else:
challenges = [challenge]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to create a list and then iterate inside the turn?

I suspect this is misplaced, translation in this probe should only need to happen for the initial challenge in the probe and all generators used to perform red_team actions by manipulating on that prompt using a model in the target language.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got same review comment.

I will recheck code and considering which part is the better place to implement translation function.

If you have any recommend way to implement it, please let me know.

garak/probes/atkgen.py Outdated Show resolved Hide resolved
tests/probes/test_probes_encoding.py Outdated Show resolved Hide resolved
@@ -12,6 +23,7 @@ def test_InjectBase64_len_cap():
assert len(p.prompts) < num_payloads * num_templates * num_encoders


@pytest.fixture(scope="function")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing? Tests should not be annotated as fixtures.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. This test does not need it. I remove it this part.

@@ -20,6 +32,7 @@ def test_InjectBase64_prompt_trigger_match():
assert len(p.prompts) == len(p.triggers)


@pytest.fixture(scope="function")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing? Tests should not be annotated as fixtures.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. This part does not need it. I remove it this part.

tests/test_translator.py Outdated Show resolved Hide resolved
garak/_config.py Show resolved Hide resolved
@leondz
Copy link
Collaborator

leondz commented Oct 30, 2024

Adding a number of my pending comments here, please be aware these are likely similar to many @leondz made, although possibly from different reasoning. Happy to continue iterating.

Indeed, sorry for the dupe review, there was quite a lot of code so I reviewed directly instead of processing @jmartin-tech 's comments as well

add mean judge for reverse translation
change translation model size

Signed-off-by: Masaya Ogushi <[email protected]>
translate trigger words

Signed-off-by: Masaya Ogushi <[email protected]>
add reverse translation
remove trigger translation
fix test code

Signed-off-by: Masaya Ogushi <[email protected]>
add translation instance

Signed-off-by: Masaya Ogushi <[email protected]>
add library for reverse translation

Signed-off-by: Masaya Ogushi <[email protected]>
@SnowMasaya
Copy link
Author

SnowMasaya commented Oct 31, 2024

Thank you, this is a significant amount of work.

This is for translation-based multilingual, rather than general multilingual support, so we should be careful to separate these two functions. The ability to select which languages garak uses is distinct from how that language is achieved (in prompts, detectors, and so on).

There are some refactorings needed to get the PR to a sustainable state. We may need a couple more hooks, either injected into base classes or added there. It might be simplest to add these hooks to the harness. Happy to set up a call or instant message chat to discuss this. Given the breadth of the changes, it is likely to be beneficial to discuss plans and get good alignment while doing the rest of the changes.

Thank you for review.
I would like to set up a call for understanding the best way to implement this function.
Please stop the review the following commit because it has not apply your review.
The following commit for my coworker request.

masayaOgushi and others added 13 commits December 12, 2024 09:39
remove extra test code

Signed-off-by: Masaya Ogushi <[email protected]>
Add attributes lang_type, reverse_translation for analysis translation result

Signed-off-by: Masaya Ogushi <[email protected]>
move translation check code to another test code

Signed-off-by: Masaya Ogushi <[email protected]>
check attempt language
save reverse translation for analysis result

Signed-off-by: Masaya Ogushi <[email protected]>
Signed-off-by: Masaya Ogushi <[email protected]>
Check StringDetector
Check HF detector
Check Yes, No start Detector

Signed-off-by: Masaya Ogushi <[email protected]>
Only 1st probes translation atkgen
goodside.py move translation function to translator.py
base.py has get_translator function
base.py add lang_type for attempt

Signed-off-by: Masaya Ogushi <[email protected]>
save reverse translation which made by the dtector

Signed-off-by: Masaya Ogushi <[email protected]>
Don't check non prompt probes
Don't check visual probes

Signed-off-by: Masaya Ogushi <[email protected]>
update remove english punctuation
update english judge
update split text
add translate description
remove some class and integrate with function to base class
add lang class for analysis result

Signed-off-by: Masaya Ogushi <[email protected]>
remove extra class check
encode text translaiton check
long sentence translation check
add yaml for test without api key

Signed-off-by: Masaya Ogushi <[email protected]>
using yaml file for translation

Signed-off-by: Masaya Ogushi <[email protected]>
jmartin-tech and others added 3 commits February 13, 2025 09:34
* refactor for encapsulation
* set default config entries for early load support
  * adds docs for new entries
  * initializes `lang_spec` to `en`
  * intializes `translators` to an empty list
* revised test config formats
* only maintain prompts in one language
* limit to only translated prompts
* treat "$" as a special line bypassing translation attempt
* NLI detector should support None response
* check translation required carefully
  * strings that do not contain "words" should bypass translation
  * tests of translation configuration require `lang_spec`
  * add remote translator specific class to tests
* clarify base model prefix as opus-mt-*
* detectors need translators in config
* always return a translator even if just target to target
  * always have a translator
  * only attempt to translate output that is not None
* force garbage collection after translator tests
* validate probe trigger type during tranlation
* translation needs lists of strings
  * support for nested lists is added for existing probes content
* remove direct _config access in plugins
  * remove access to _config.run from `probe` classes
  * adjust goodside translations to not retain original prompts
* refactor probe translation tests for unit testing
  * In the interest of reasonable execution time test probe
    call translation instead of executing translation.
  * probe translation tests as unit testing only
* Translation actions are tested with there own tests.
* remove side-effects for internal translation methods
* latentinjection init adjustment
  * Remove extra call for translator
  * Ensure `_build_prompts_triggers` is called only once during init
    for all implemented classes.
* bugfix - goodside instance instead of class attributes
* remote test case corrections
* extract translator base config restrictions
  * ENV var needs are handled by `remote` module
  * adjust docs for each class
  * match extending class method signature
* consolidate nltk overrides in resources.api
* remove no longer used "only_translate_word"
* remove lang_list references, support a single target language
* use pythonic code-style, adjust inline comments
* refactor report file to rely on global fixture
* rename base class to `Translator`
  * rename `SimpleTranslator` to `Translator`
  * source and target language determined via translator held values
* update translation configuration docs

Signed-off-by: Jeffrey Martin <[email protected]>
Signed-off-by: Jeffrey Martin <[email protected]>
jmartin-tech added a commit that referenced this pull request Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants