Skip to content

fix(attempt): default reverse_translation_outputs to a list - #2041

Open
feiiiiii5 wants to merge 1 commit into
NVIDIA:mainfrom
feiiiiii5:fix/attempt-reverse-trans-output-type
Open

fix(attempt): default reverse_translation_outputs to a list#2041
feiiiiii5 wants to merge 1 commit into
NVIDIA:mainfrom
feiiiiii5:fix/attempt-reverse-trans-output-type

Conversation

@feiiiiii5

Copy link
Copy Markdown
Contributor

Root Cause

Attempt.__init__ defaulted reverse_translation_outputs to {} while the docstring describes a list and every production caller assigns a list of Optional[Message] (_postprocess_attempt in garak/probes/base.py, probes/atkgen.py). For translated runs that never populate the field, outputs_for(lang) therefore returned an empty dict: detectors that iterate the result (e.g. garak/detectors/base.py) saw string keys instead of messages and could raise AttributeError on output.text, and as_dict() likewise iterated dict keys when serializing the attempt.

Fix

Default reverse_translation_outputs to [], matching the documented type and all existing callers, and correct the docstring to List[Optional[Message]] (the list legitimately contains None for missing generator outputs). The empty list preserves the falsy behavior of the old default, so no caller relying on truthiness changes behavior.

Test

  • test_reverse_translation_outputs_defaults_to_list: the default is a list, not a dict.
  • test_outputs_for_unset_reverse_translation_returns_empty_list: outputs_for() returns the original outputs for the matching language and [] for a translated language when the field was never populated.
  • test_reverse_translation_outputs_as_dict_round_trip: Message/None entries serialize via as_dict() and can be reconstructed field-for-field.
  • Verified locally: pytest tests/test_attempt.py → 26 passed; tests/langservice/probes/test_probes_base.py postprocess tests → 5 passed. (Full tests/langservice/detectors suites require Hugging Face model downloads and were not run to completion locally.)

Diff scope

2 files, +47/-2: garak/attempt.py, tests/test_attempt.py.

AI Disclosure

AI-assisted implementation and regression tests; the type-semantics decision (all callers already assign lists; empty list preserves falsy behavior) was human-reviewed before submission.

The Attempt constructor defaulted reverse_translation_outputs to an empty
dict while every production caller assigns a list of Optional[Message]
(probes/base.py, probes/atkgen.py). This type drift made outputs_for(lang)
return a dict for translated runs that never populated the field, so
detectors iterating the result saw string keys instead of messages and
could raise AttributeError; as_dict() would also serialize dict keys.

Align the default with the documented type: an empty list. Callers and
serialization already expect list semantics, and empty list preserves the
falsy behavior of the old default.

Adds regression tests for the default value, outputs_for() behavior when
reverse_translation_outputs is unset, and serialization round-trip of
Message/None entries.

Signed-off-by: fei <204683769+feiiiiii5@users.noreply.github.com>
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.

1 participant