8000 fix(output_parsers): iterable unpacking compatibility in content safety parsers by Pouyanpi · Pull Request #1242 · NVIDIA/NeMo-Guardrails · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix(output_parsers): iterable unpacking compatibility in content safety parsers #1242

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

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

Pouyanpi
Copy link
Collaborator
@Pouyanpi Pouyanpi commented Jun 26, 2025

Problem

Content safety actions were failing due to output parser interface incompatibility. The parsers returned Tuple[bool, List[str]] format, but actions used starred unpacking syntax is_safe, *violated_policies = result which expected list format.

Root Cause

Multiple bugs in output parsers:

  1. Iterable Unpacking Bug: Tuple format (True, []) incompatible with is_safe, *violated_policies = result that is introduced in fix(content_safety): replace try-except with iterable unpacking for policy violations #1207
  2. Empty Violations Bug: Returned [""] instead of [] for no violations
  3. Case Sensitivity Bug: Violations converted to lowercase, losing original case ("s1" vs "S1")

Solution

  • Changed return type: Tuple[bool, List[str]]Sequence[Union[bool, str]]
  • Fixed starred unpacking: Now returns [True] or [False, "policy1", "policy2"] format
  • Preserved violation case: "S1" stays "S1", not "s1"
  • Added helper function: _parse_unsafe_violations() for robust parsing
  • Tests: tests covering edge cases and different scenarios

Impact

  • Content safety actions now work correctly with iterable unpacking syntax
  • Better violation parsing with preserved case information
  • Type system compliance (resolved covariance issues)
  • Complete test coverage for future maintainability

Breaking Changes

None: this is a bug fix that makes the newly introduced interable unpacking syntax work as intended.

Closes #1241

@Pouyanpi Pouyanpi added this to the v0.14.1 milestone Jun 26, 2025
@Pouyanpi Pouyanpi self-assigned this Jun 26, 2025
@Pouyanpi Pouyanpi added the bug Something isn't working label Jun 26, 2025
@Pouyanpi Pouyanpi requested a review from Copilot June 26, 2025 10:00
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes iterable unpacking compatibility issues in output parsers by switching the return type from tuples to list-based sequences. Key changes include:

  • Updating output parser functions (is_content_safe, nemoguard_parse_prompt_safety, nemoguard_parse_response_safety) to return Sequence[Union[bool, str]].
  • Adding a helper function (_parse_unsafe_violations) to robustly parse policy violations.
  • Updating integration and unit tests to verify proper unpacking and correct behavior in edge-case scenarios.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
tests/test_output_parsers.py Removed obsolete user intent test to focus solely on content safety.
tests/test_content_safety_output_parsers.py Added comprehensive tests for both JSON and plain-text responses covering multiple safety cases.
tests/test_content_safety_integration.py Added integration tests ensuring compatibility of the new list-based parser outputs with starred unpacking.
nemoguardrails/llm/output_parsers.py Updated parser functions to return lists and introduced a helper to maintain case-preservation for violations.
Comments suppressed due to low confidence (1)

nemoguardrails/llm/output_parsers.py:149

  • When 'Safety Categories' is present but is an empty string, consider returning a list with an empty string (i.e. ['']) instead of an empty list to align with the expected behavior in tests.
    }

@codecov-commenter
Copy link
codecov-commenter commented Jun 26, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 69.51%. Comparing base (8d27470) to head (a3b1cb6).
Report is 3 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1242      +/-   ##
===========================================
+ Coverage    69.04%   69.51%   +0.47%     
===========================================
  Files          161      161              
  Lines        15995    16012      +17     
===========================================
+ Hits         11043    11131      +88     
+ Misses        4952     4881      -71     
Flag Coverage Δ
python 69.51% <100.00%> (+0.47%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
nemoguardrails/library/self_check/facts/actions.py 89.18% <100.00%> (ø)
...ardrails/library/self_check/input_check/actions.py 97.14% <100.00%> (ø)
...rdrails/library/self_check/output_check/actions.py 96.96% <100.00%> (ø)
nemoguardrails/llm/output_parsers.py 97.22% <100.00%> (+42.67%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Pouyanpi Pouyanpi force-pushed the fix/content-safey-parser branch 4 times, most recently from 858561a to 435c772 Compare June 26, 2025 14:37
@Pouyanpi
Copy link
Collaborator Author
Pouyanpi commented Jun 26, 2025

@trebedea @prasoonvarshney

would you please review the test cases to see if the expected behavior is OK?

The interface of output parser has changed and it requires us to use iterable unpacking

is_safe, *violated_policies = is_content_safe(response)

The safe/unsafe is always the first element of the sequence.

if a response is considered safe, violations will always be an empty list. Is this assumption correct? if not, do we need to modify the safe/unsafe logic? (see https://github.com/NVIDIA/NeMo-Guardrails/pull/1242/files#r2169265190)

context=context,
)

# TODO: @trebedea @prasoonvarshney is this the expected behavior?
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

…ent safety parsers

- Change return type from Tuple[bool, List[str]] to Sequence[Union[bool, str]]
- Fix empty violations bug that returned [""] instead of []
- Preserve original case in violation parsing (S1 vs s1)
- Add helper function _parse_unsafe_violations() for robust parsing
- Remove duplicate test file tests/test_output_parsers.py
- Add comprehensive test coverage (38 tests) in test_content_safety_output_parsers.py

Fixes starred unpacking syntax: is_safe, *violated_policies = result
Previously failed due to tuple format incompatibility with actions expecting list format.

Closes #1241

refactor tests
@Pouyanpi Pouyanpi force-pushed the fix/content-safey-parser branch from d60a06e to a3b1cb6 Compare June 26, 2025 14:53
@Pouyanpi Pouyanpi changed the title fix(output_parsers): resolve iterable unpacking compatibility in cont… fix(output_parsers): iterable unpacking compatibility in content safety parsers Jun 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: investigate parser malformed output causing >2-tuple returns
2 participants
0