FEAT Add dedicated LlamaGuard scorer#1867
Conversation
…rd support Per the design discussion in microsoft#1830, extend SelfAskTrueFalseScorer with an optional response_parser callable so the same scorer can wrap fine-tuned safety classifiers (LlamaGuard, ShieldGemma, WildGuard, HarmBench-paper) whose output is not JSON. Default behavior is unchanged. Ships a parse_llamaguard_response helper plus YAML assets (TrueFalseQuestion and system prompt) so users can drop in any LlamaGuard-serving endpoint via PromptChatTarget. No local transformers or torch dependency. Also fixes a latent typing issue in Scorer._score_value_with_llm: score_value_description now defaults to '' when the response omits the description field, instead of being None against a str-typed field.
romanlutz
left a comment
There was a problem hiding this comment.
I don't have a llama-guard deployment and can't test this. Can you confirm that you did test it?
The PR has not been exercised against a live LlamaGuard endpoint. The tests cover the plumbing in two places:
What is not covered: the actual LlamaGuard-3-8B chat template rendering and the round-trip through a real endpoint. If a live smoke test against Together/Groq/Fireworks would help you merge with confidence, I am happy to run one and paste the transcript here. I held off on writing that as a unit-suite test because it would require a configured API key and would not be reproducible in CI. |
- Wire YAMLs into discoverable paths: add TrueFalseQuestionPaths.LLAMAGUARD and LLAMAGUARD_SYSTEM_PROMPT_PATH module-level constant. - Drop misleading 'parameters' declaration in llamaguard_system_prompt.yaml; template is static. - Switch :class: reST cross-references to plain double-backticks in scorer.py and self_ask_true_false_scorer.py (PyRIT docs build is MyST). - Reorder __all__ in pyrit/score/__init__.py: parse_llamaguard_response between ObjectiveScorerMetrics and PlagiarismMetric, LLAMAGUARD_SYSTEM_PROMPT_PATH between LikertScalePaths and MarkdownInjectionScorer.
# Conflicts: # pyrit/score/__init__.py
# Conflicts: # pyrit/score/__init__.py # pyrit/score/scorer.py # pyrit/score/true_false/self_ask_true_false_scorer.py
# Conflicts: # pyrit/score/scorer.py # pyrit/score/true_false/self_ask_true_false_scorer.py
|
Friendly bump on this. Conflicts resolved twice now and merge-state is clean apart from the four conversations I've marked addressed. Happy to apply any further changes if you'd like, or close if direction has shifted. |
|
Closing this. The Glad Thanks for the review time on this one. |
…r' into feat/llamaguard-scorer # Conflicts: # pyrit/score/true_false/self_ask_true_false_scorer.py
# Conflicts: # pyrit/score/__init__.py # pyrit/score/scorer.py # pyrit/score/true_false/self_ask_true_false_scorer.py
Ship the LlamaGuard parser and static prompt as production components for SelfAskTrueFalseScorer through CallableResponseHandler. Replace the architecture pilot with coverage of the exported assets and metadata contract. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9be2dff6-a4fb-4690-9f8d-767dea2f98bd
Not at all, I am glad it was useful, and happy to revive it. Seeing the series land, the composition approach is clearly the better home for this than the Since #2125 through #2157 removed that hook, reviving this means reworking the PR onto the new API rather than merging as is. Concretely: drop the old One consolidation note: a few hours before you reopened this, I filed #2172 proposing exactly that, the LlamaGuard parser and prompt on I will start the rework unless you would rather shape the approach first. |
|
@immu4989 i was curious to see if it would go as cleanly as I thought. See the current PR state. Is this in line with your thinking? |
|
Yes, this is exactly it. I pulled the branch and ran it: the two new test files pass (16), the full One small optional thing from reading the parser: the On consolidation: this supersedes #2172, which I filed proposing this same work a few hours before you reopened here, so this PR can close it. I will add a pointer there. I would also be glad to follow up with ShieldGemma and WildGuard on the same handler once this lands. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9be2dff6-a4fb-4690-9f8d-767dea2f98bd
|
I suspect it's better to have a proper scorer vs what's in the PR right now. I'll just push now so that you can see what that looks like but I can remove that commit, too. |
Fixes #1830.
Summary
Adds a dedicated
LlamaGuardScorerbuilt on the scorer-composition API introduced by #2125, #2146, and #2157. The scorer sends Llama Guard's native plain-text classification request and parses its nativesafe/unsafe\nS1,S6response without adding a genericSelfAskTrueFalseScorerhook.LlamaGuardMessageRole.USERand.AGENTrequest framing, defaulting to Agent for model-response classification.Scorewithout inserting it into the Llama Guard conversation.pyrit/datasets/score/llamaguard/.LlamaGuardPolicyandLlamaGuardCategoryvalue types for validated custom taxonomies and optional category descriptions.Usage
User-input classification is available with
message_role=LlamaGuardMessageRole.USER. Custom policies can be loaded withLlamaGuardPolicy.from_yaml(...)and passed through thepolicyargument.Validation
ty: passed.The endpoint round trip is covered with a mocked
PromptTarget; this has not been exercised against a live Llama Guard deployment.