Skip to content

fix(protect): align metric names across Python and TypeScript SDKs - #56

Open
KarthikAvinashFI wants to merge 1 commit into
release/v1-agent-learning-kit-devfrom
fix/th-7040-protect-metric-parity-v1
Open

fix(protect): align metric names across Python and TypeScript SDKs#56
KarthikAvinashFI wants to merge 1 commit into
release/v1-agent-learning-kit-devfrom
fix/th-7040-protect-metric-parity-v1

Conversation

@KarthikAvinashFI

Copy link
Copy Markdown
Contributor

Why

The Python and TypeScript Protect SDKs exposed incompatible metric names for the same guardrail rules, so a rule config authored in one language was rejected by the other, and the docs had to document the two naming sets side by side with a warning that they do not mix. This aligns both SDKs on one canonical set of snake_case metrics, keeps every historical name working as a back-compatible alias, and removes Tone, which Protect does not support.

This is the v1-refactor-branch version of the change (supersedes the dev-based PR, whose file paths no longer exist on this branch).

What changed

Both SDKs now accept the same superset: 4 canonical metrics plus every legacy alias, each resolving to the correct guardrail evaluation. Legacy names still work and emit a one-shot deprecation warning.

Metric Type Resolves to
toxicity canonical toxicity
bias_detection canonical bias detection
prompt_injection canonical prompt injection
data_privacy_compliance canonical data-privacy compliance
content_moderation legacy alias (warns) toxicity
security legacy alias (warns) prompt injection
Toxicity legacy alias (warns) toxicity
Sexism legacy alias (warns) bias detection
Prompt Injection legacy alias (warns) prompt injection
Data Privacy legacy alias (warns) data-privacy compliance
Tone removed not supported

Files

File Change Preserved
src/fi/evals/protect.py metric_map extended with the TypeScript-origin legacy names; _deprecated_metrics extended so each alias emits a FutureWarning pointing at its canonical name; the data-privacy config is now selected by template identity (template_class is DataPrivacyCompliance) instead of a metric-name string comparison; the dead Tone validation branch is removed; the fallback default rule and docstring example use canonical toxicity protect() return shape, the action/reason validation, and the overall request flow are unchanged
src/fi/evals/guardrails/backends/turing.py classify() uses canonical toxicity/prompt_injection so it no longer emits a deprecation warning on every call; the category-lookup dict keeps the legacy keys so external callers still categorize correctly Classification behaviour and category mapping unchanged
typescript/agent-learning-kit/src/protect.ts metric_map rewritten to the same canonical + legacy set; module-level DEPRECATED_METRICS map + one-shot console.warn per alias; data-privacy config selected by template identity; Tone and the validTypes set removed; the default rule uses canonical toxicity protect() signature and result shape unchanged
tests/test_protect_metric_map.py New unit test file n/a
typescript/agent-learning-kit/src/__tests__/protect.test.ts Parity tests added for canonical + legacy metrics and Tone rejection; one pre-existing error-message assertion updated to the current message Existing protect tests unchanged

Behavior callouts

  • data_privacy_compliance now sends check_internet=false. The Python SDK previously selected this via a metric-name string that never matched its own map, so the flag was effectively never set; it is now selected by template identity and matches the TypeScript SDK. Data-privacy rules evaluate the input in isolation; a caller that relied on the old behaviour must opt in to internet lookups explicitly.
  • Sexism now resolves to the bias-detection evaluation. On the TypeScript side Sexism previously mapped to a separate sexist evaluation; it now maps to bias_detection (the canonical set), so existing Sexism callers run the bias-detection guardrail.
  • Legacy metric names are deprecated, not removed. Each still resolves correctly and emits a one-shot deprecation warning (FutureWarning in Python, console.warn in TypeScript). Removal is deferred to a future release.
  • Tone is rejected. It was never a supported Protect metric; a rule using it now fails validation on both SDKs.

Tests

Suite File Cases Covers
Python unit tests/test_protect_metric_map.py (new) 13 (5 parametrized functions) each canonical mapping, each of the 6 legacy-alias mappings, deprecation warning fires for aliases and not for canonicals, Tone rejected
TypeScript unit typescript/agent-learning-kit/src/__tests__/protect.test.ts (extended) 11 added (19 total) each canonical metric accepted, each legacy alias accepted with a deprecation warning, Tone rejected

Beyond the unit suites, every canonical and legacy metric name was exercised through protect() end to end against a running Future AGI backend on both SDKs, confirming each is accepted, resolves to the correct guardrail evaluation, and round-trips successfully; legacy names emit their deprecation warning and Tone is rejected.

Commands

# Python
uv run pytest tests/test_protect_metric_map.py -v

# TypeScript
cd typescript/agent-learning-kit && pnpm test src/__tests__/protect.test.ts

# TypeScript typecheck (CI gate)
cd typescript/agent-learning-kit && pnpm typecheck

Output

Python unit:

$ uv run pytest tests/test_protect_metric_map.py
collected 13 items

tests/test_protect_metric_map.py .............                        [100%]

13 passed

TypeScript unit:

$ pnpm test src/__tests__/protect.test.ts

  Canonical + legacy metric parity with Python
    ✓ accepts canonical metric toxicity
    ✓ accepts canonical metric bias_detection
    ✓ accepts canonical metric prompt_injection
    ✓ accepts canonical metric data_privacy_compliance
    ✓ accepts legacy alias Toxicity with a deprecation warning
    ✓ accepts legacy alias Sexism with a deprecation warning
    ✓ accepts legacy alias Prompt Injection with a deprecation warning
    ✓ accepts legacy alias Data Privacy with a deprecation warning
    ✓ accepts legacy alias content_moderation with a deprecation warning
    ✓ accepts legacy alias security with a deprecation warning
    ✓ rejects the previously-supported "Tone" metric

Test Suites: 1 passed, 1 total
Tests:       19 passed, 19 total

TypeScript typecheck: clean (tsc --noEmit, no errors).

End-to-end: every metric name sent through protect() against a running backend (identical result on both SDKs):

  [PASS] toxicity                 status=passed
  [PASS] bias_detection           status=passed
  [PASS] prompt_injection         status=passed
  [PASS] data_privacy_compliance  status=passed
  [PASS] content_moderation       status=passed (deprecated)
  [PASS] security                 status=passed (deprecated)
  [PASS] Toxicity                 status=passed (deprecated)
  [PASS] Sexism                   status=passed (deprecated)
  [PASS] Prompt Injection         status=passed (deprecated)
  [PASS] Data Privacy             status=passed (deprecated)
  [PASS] Tone rejected: InvalidValueType

  All checks passed.

Scope in / scope out

In scope: metric-name alignment across both SDKs, back-compatible aliases with deprecation warnings, Tone removal, and the data-privacy check_internet correction.

Out of scope: widening the TypeScript protect() input signature to accept string | list for parity with Python. Deferred to keep this diff scoped; tracked separately.

Design choices

  • Both SDKs accept a superset (canonical + every historical alias) rather than a hard cutover, so existing rule configs in either language keep working; aliases warn and removal is deferred.
  • Data-privacy config is chosen by comparing the resolved template class rather than matching a metric-name string, so every alias that resolves to the data-privacy template receives the correct config.

Linear

Fix TH-7040

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