agentme 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.xdrs/agentme/edrs/application/151-ai-eval-standards.md +2 -1
- package/.xdrs/agentme/edrs/application/152-ai-test-types-taxonomy.md +17 -4
- package/.xdrs/agentme/edrs/application/153-ai-eval-script.md +10 -2
- package/.xdrs/agentme/edrs/application/156-ai-eval-fairness-bias.md +154 -0
- package/.xdrs/agentme/edrs/index.md +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentme-edr-policy-151-ai-eval-standards
|
|
3
|
-
description: Defines the eval folder structure and Makefile interface for AI projects, and the LLM-as-judge binary scoring contract applicable to all AI tiers and test types. Use when scaffolding evals or implementing an LLM judge. For eval script requirements see agentme-edr-153. For report format see agentme-edr-154. For repeatability see agentme-edr-155. For when evals are required see agentme-edr-501 rule 09-ai-project-testing-requirements. For the test type taxonomy see agentme-edr-152.
|
|
3
|
+
description: Defines the eval folder structure and Makefile interface for AI projects, and the LLM-as-judge binary scoring contract applicable to all AI tiers and test types. Use when scaffolding evals or implementing an LLM judge. For eval script requirements see agentme-edr-153. For report format see agentme-edr-154. For repeatability see agentme-edr-155. For fairness/bias group scoring see agentme-edr-156. For when evals are required see agentme-edr-501 rule 09-ai-project-testing-requirements. For the test type taxonomy see agentme-edr-152.
|
|
4
4
|
apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
|
|
5
5
|
valid-from: 2026-06-05
|
|
6
6
|
---
|
|
@@ -115,6 +115,7 @@ Output:
|
|
|
115
115
|
- [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first eval loop, `--type` filtering, `mock_fixtures`, and MLflow conventions
|
|
116
116
|
- [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: `report-<type>.md` template, Wilson CI, and convergence analysis
|
|
117
117
|
- [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: loop exception, scoring methods (including LLM-as-judge per rule `02`), and cadence
|
|
118
|
+
- [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: comparison_group group-scoring loop, scoring approaches (including LLM-as-judge per rule `02`), fairness_accuracy/bias_accuracy metrics, and report shape
|
|
118
119
|
- [agentme-edr-501](../governance/501-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09`) and statistical model eval targets (rule `07`)
|
|
119
120
|
- [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `test_types` enum and golden dataset entry envelope
|
|
120
121
|
- [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
|
|
@@ -41,9 +41,21 @@ Every golden dataset entry (a JSON file in `golden_dataset/data/`) MUST have thi
|
|
|
41
41
|
|
|
42
42
|
- `test_types` — array, values MUST come from rule `04`'s enum, MUST contain at least one value. An entry MAY carry more than one value additively (e.g. `["functional", "smoke", "human"]`) — no test type excludes another.
|
|
43
43
|
- `input` — for Prompt-tier components, a raw prompt string or the prompt template's input parameters object; for Agent/Workflow-tier components, the input attributes object passed to the component.
|
|
44
|
-
- `expected_output` — the fields used to score the entry under each of its automated `test_types`: output attributes for an LLM-as-judge rubric, a target for vector-similarity scoring, or exact attribute values for strict comparison. When `human` is one of the entry's `test_types`, `expected_output` MUST additionally include a `human_test` string field with manual-verification instructions (e.g. `"check for ethical issues, verify record change in system X"`) — this supplements, and MUST NOT replace, the entry's automated scoring fields.
|
|
44
|
+
- `expected_output` — the fields used to score the entry under each of its automated `test_types`: output attributes for an LLM-as-judge rubric, a target for vector-similarity scoring, or exact attribute values for strict comparison. When `human` is one of the entry's `test_types`, `expected_output` MUST additionally include a `human_test` string field with manual-verification instructions (e.g. `"check for ethical issues, verify record change in system X"`) — this supplements, and MUST NOT replace, the entry's automated scoring fields. **Exception:** when `test_types` contains only values from `["fairness", "bias", "repeatability"]` (no other automated types), `expected_output` MUST be `null` — these types score by group comparison or self-invocation, not against a fixed expected value. If the entry also carries any other type (including `human`), `expected_output` MUST be non-null.
|
|
45
45
|
- `mock_fixtures` — optional object; keys identify the adapter or external system to mock (SHOULD match the connector folder name under `adapters/connectors/<name>` for readability, though not enforced), values are any valid JSON interpreted by the mock implementation. When present, eval.py MUST configure each named mock adapter with its fixture data BEFORE invoking the component for that entry; each entry MUST use fresh mock instances to prevent state from bleeding across entries. `mock_fixtures` applies to all `test_types` including `human` — the component is still invoked for human entries to capture `actual_output`. `mock_fixtures` MUST NOT include keys for LLM adapters: all golden dataset test types are rated `mocks disallowed for LLM calls` (rule `03`), so the LLM call MUST be real; LLM provider mocking belongs exclusively to unit tests via [agentme-edr-141](141-ai-llm-development-standards.md) rule `04`. See [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
|
|
46
|
-
-
|
|
46
|
+
- `group` — optional string; a thematic label for on-demand filtering and optional per-group report views (e.g. `"simple"`, `"edge_cases"`). Used by the `--groups` CLI argument of [agentme-edr-153](153-ai-eval-script.md). Values MUST NOT contain commas (comma is the `--groups` list delimiter).
|
|
47
|
+
- `comparison_group` — optional string or integer; required when `test_types` includes `fairness` or `bias` (enforced by `dataset.schema.json` — see schema rules below). Identifies the demographic comparison scenario this entry belongs to: all entries sharing the same `comparison_group` value represent the same scenario varying only in protected attributes (gender, race, age, nationality, religion, etc.) in `input`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) for the eval loop, scoring approaches, and metrics.
|
|
48
|
+
- The dataset's `dataset.schema.json` MUST require `test_types`, `input`, and `expected_output`, and MUST declare `group` and `comparison_group` as optional and SHOULD declare `mock_fixtures` as optional (`"type": "object", "additionalProperties": {}`), per [agentme-edr-201](../data/201-ml-dataset-structure.md) rule `04`. The `expected_output` type MUST allow `null` globally (e.g. `"type": ["string", "object", "null"]`) to support entries where `expected_output` is `null`. Two conditional rules MUST be expressed as `allOf` entries using JSON Schema `if/then` (supported by the Python `jsonschema` library in draft-07 and later):
|
|
49
|
+
- **Rule A** — `comparison_group` is required when `test_types` contains `"fairness"` or `"bias"`:
|
|
50
|
+
```json
|
|
51
|
+
"if": {"properties": {"test_types": {"contains": {"enum": ["fairness", "bias"]}}}},
|
|
52
|
+
"then": {"required": ["comparison_group"]}
|
|
53
|
+
```
|
|
54
|
+
- **Rule B** — `expected_output` must not be `null` when `test_types` contains any value outside the exempted set `["fairness", "bias", "repeatability"]`:
|
|
55
|
+
```json
|
|
56
|
+
"if": {"properties": {"test_types": {"contains": {"not": {"enum": ["fairness", "bias", "repeatability"]}}}}},
|
|
57
|
+
"then": {"properties": {"expected_output": {"not": {"type": "null"}}}}
|
|
58
|
+
```
|
|
47
59
|
|
|
48
60
|
#### 03-mocks-allowed-values
|
|
49
61
|
|
|
@@ -67,8 +79,8 @@ Test types MUST be selected from this taxonomy. Each test type is named with its
|
|
|
67
79
|
|---|---|---|---|---|---|---|---|---|
|
|
68
80
|
| Safety/content eval | `safety` | Safety & adversarial | Detect harmful, biased, or policy-violating output | mocks disallowed for LLM calls | Any user-facing release | Avoids reputational harm; acceptable-use compliance | Automated content gate before merge/release | 5 |
|
|
69
81
|
| Adversarial/red-team test | `adversarial` | Safety & adversarial | Probe for prompt injection, jailbreaks, unsafe tool use | mocks disallowed for LLM calls | System exposes tool-invocation or agent loops | Reduces security-incident/breach liability | Finds exploitable tool-loop paths before attackers do | 5 |
|
|
70
|
-
| Fairness test | `fairness` | Responsible AI | Verify equitable outcomes across user groups | mocks disallowed for LLM calls | Output affects decisions about individuals/groups | Regulatory requirement; protects equitable access | Surfaces uneven outcomes before release | 4 |
|
|
71
|
-
| Bias test | `bias` | Responsible AI | Detect skewed or stereotyped associations | mocks disallowed for LLM calls | User-facing content generation | Lowers legal/reputational exposure | Catches bias introduced by data/prompts/fine-tuning | 3 |
|
|
82
|
+
| Fairness test | `fairness` | Responsible AI | Verify equitable outcomes across user groups by comparing outputs of demographic variants grouped by `comparison_group`; `expected_output` must be `null`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) | mocks disallowed for LLM calls | Output affects decisions about individuals/groups | Regulatory requirement; protects equitable access | Surfaces uneven outcomes before release | 4 |
|
|
83
|
+
| Bias test | `bias` | Responsible AI | Detect skewed or stereotyped associations by comparing outputs of demographic variants grouped by `comparison_group`; `expected_output` must be `null`. See [agentme-edr-156](156-ai-eval-fairness-bias.md) | mocks disallowed for LLM calls | User-facing content generation | Lowers legal/reputational exposure | Catches bias introduced by data/prompts/fine-tuning | 3 |
|
|
72
84
|
| Robustness test | `robustness` | Responsible AI | Verify stable behavior under noisy/out-of-distribution input | mocks disallowed for LLM calls | Inputs come from untrusted/variable sources | Protects reliability/SLAs | Confirms graceful degradation, guides input validation | 3 |
|
|
73
85
|
| Explainability test | `explainability` | Responsible AI | Verify output is justifiable with a faithful rationale | mocks disallowed for LLM calls | Output must be justified to users/auditors/regulators | Required for auditability; builds user trust | Gives rationale trace for debugging wrong answers | 2 |
|
|
74
86
|
| Groundedness (RAG) eval | `groundedness` | Quality eval | Verify the answer is supported by retrieved context | mocks disallowed for LLM calls | System uses retrieval-augmented generation | Avoids confidently-wrong answers reaching customers | Pinpoints retrieval/prompt bugs | 4 |
|
|
@@ -114,3 +126,4 @@ A component may satisfy reproducibility (temperature = 0) yet still need repeata
|
|
|
114
126
|
- [agentme-edr-305](../platform/305-environment-variable-configuration.md) — Environment-configuration conventions referenced in rule `09`'s reproducibility disambiguation
|
|
115
127
|
- [agentme-edr-141](141-ai-llm-development-standards.md) — LLM tier definition and mocking utilities referenced by the `mocks allowed` value
|
|
116
128
|
- [agentme-edr-122](122-unit-test-requirements.md) — Unit test requirements underlying the Code-level rows
|
|
129
|
+
- [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: `comparison_group` dataset structure, deferred group-scoring loop, scoring approaches, `fairness_accuracy`/`bias_accuracy` metrics, report shape, and cadence
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentme-edr-policy-153-ai-eval-script
|
|
3
|
-
description: Defines eval.py script requirements for AI projects — entry-first eval loop, --type test-type filtering, mock_fixtures wiring, human entries, threshold enforcement, and MLflow experiment naming and port assignment. Use when implementing eval scripts. For eval folder structure see agentme-edr-151 rule 01. For the test type taxonomy and mock_fixtures envelope see agentme-edr-152. For mock file naming see agentme-edr-126 rule 10. For report format see agentme-edr-154. For repeatability loop exception see agentme-edr-155.
|
|
3
|
+
description: Defines eval.py script requirements for AI projects — entry-first eval loop, --type test-type filtering, --groups group filtering, mock_fixtures wiring, human entries, fairness/bias deferred group scoring, threshold enforcement, and MLflow experiment naming and port assignment. Use when implementing eval scripts. For eval folder structure see agentme-edr-151 rule 01. For the test type taxonomy and mock_fixtures envelope see agentme-edr-152. For mock file naming see agentme-edr-126 rule 10. For report format see agentme-edr-154. For repeatability loop exception see agentme-edr-155. For fairness/bias group scoring see agentme-edr-156.
|
|
4
4
|
apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement eval testing
|
|
5
5
|
valid-from: 2026-07-07
|
|
6
6
|
---
|
|
@@ -25,8 +25,10 @@ For when evals are required per AI tier, see [agentme-edr-501](../governance/501
|
|
|
25
25
|
|
|
26
26
|
Each `eval.py` script MUST:
|
|
27
27
|
|
|
28
|
-
- Load the golden dataset from `golden_dataset/` in the same eval folder, following [agentme-edr-201](../data/201-ml-dataset-structure.md) and the entry envelope in [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02` (one JSON file per entry, `test_types` array, `input`, `expected_output`, optional `mock_fixtures`).
|
|
28
|
+
- Load the golden dataset from `golden_dataset/` in the same eval folder, following [agentme-edr-201](../data/201-ml-dataset-structure.md) and the entry envelope in [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02` (one JSON file per entry, `test_types` array, `input`, `expected_output`, optional `mock_fixtures`, optional `group`, optional `comparison_group`).
|
|
29
29
|
- Accept a required `--type=<test_type>|all` CLI argument and filter entries whose `test_types` array contains the requested value; `--type=all` includes every entry.
|
|
30
|
+
- Accept an optional `--groups=<name1>,<name2>,...` CLI argument. When present, restrict the filtered entry set to those whose `group` field matches any of the listed values (case-sensitive exact match); entries without a `group` field are excluded when `--groups` is active. When omitted, all entries from the `--type` filter are included regardless of `group`. The MLflow run MUST log a `groups_filter` tag containing the `--groups` value, or `"all"` when the argument is omitted.
|
|
31
|
+
- **Fairness/bias deferred group scoring:** for entries whose `test_types` includes `fairness` or `bias`, the `fairness`/`bias` test_type MUST be skipped in the inline per-entry scoring step and the entry's `actual_output` buffered by `comparison_group`. Other test_types on the same entry (e.g. `functional`) are still scored inline normally. After the entry-first loop completes, score each comparison group by comparing its buffered outputs. See [agentme-edr-156](156-ai-eval-fairness-bias.md) for the full scoring loop, approach options, metrics, and report shape.
|
|
30
32
|
- Iterate **entry-first**: for each entry in the filtered set, invoke the real component exactly once; then score that single `actual_output` for every `test_types` value the entry carries that falls within the current `--type` scope — MUST NOT invoke the component more than once per entry per run.
|
|
31
33
|
- When an entry contains `mock_fixtures` ([agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`), configure each named mock adapter with its fixture data BEFORE invoking the component for that entry. Each entry MUST use fresh mock instances so fixture state does not bleed across entries. `mock_fixtures` applies to all test types including `human`. `mock_fixtures` MUST NOT configure LLM adapters — the LLM call MUST be real (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `03`). How mock adapters are discovered and instantiated is left to the project; see [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) rule `10` for the `_mock` file naming and placement convention.
|
|
32
34
|
- Run every component invocation against **real LLM providers** (not mocked responses), to capture model drift.
|
|
@@ -53,15 +55,20 @@ def get_min_accuracy(test_type: str) -> float:
|
|
|
53
55
|
|
|
54
56
|
parser = argparse.ArgumentParser()
|
|
55
57
|
parser.add_argument("--type", required=True)
|
|
58
|
+
parser.add_argument("--groups", required=False, default=None)
|
|
56
59
|
args = parser.parse_args()
|
|
57
60
|
|
|
58
61
|
entries = load_golden_dataset("golden_dataset/", test_type=args.type) # "all" loads every entry
|
|
62
|
+
if args.groups:
|
|
63
|
+
groups_filter = set(args.groups.split(","))
|
|
64
|
+
entries = [e for e in entries if e.get("group") in groups_filter]
|
|
59
65
|
resolved_types = resolve_types(args.type, entries)
|
|
60
66
|
|
|
61
67
|
mlflow.set_experiment("document-review/eval-basic")
|
|
62
68
|
|
|
63
69
|
with mlflow.start_run():
|
|
64
70
|
mlflow.set_tag("test_types", ",".join(sorted(resolved_types)))
|
|
71
|
+
mlflow.set_tag("groups_filter", args.groups if args.groups else "all")
|
|
65
72
|
|
|
66
73
|
results = defaultdict(list)
|
|
67
74
|
cumulative_metrics = defaultdict(lambda: {"accuracy": [], "f1": []}) # Track cumulative metrics
|
|
@@ -129,6 +136,7 @@ The MLflow **experiment** is scoped to the eval scenario: `<component>/<eval-nam
|
|
|
129
136
|
- [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: eval folder structure (rule `01`) and LLM-as-judge binary scoring contract (rule `02`)
|
|
130
137
|
- [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: `report-<type>.md` template, Wilson CI, and convergence analysis
|
|
131
138
|
- [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: loop exception to rule `01`'s entry-first constraint, scoring methods, and cadence
|
|
139
|
+
- [agentme-edr-156](156-ai-eval-fairness-bias.md) — AI eval fairness/bias: deferred group-scoring loop, `comparison_group` buffering, scoring approaches, and `fairness_accuracy`/`bias_accuracy` metrics
|
|
132
140
|
- [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `test_types` enum, golden dataset entry envelope (including `mock_fixtures`), and mocking constraints per type
|
|
133
141
|
- [agentme-edr-126](126-pragmatic-hexagonal-architecture.md) — Rule `10`: `_mock` file naming and placement convention for mock adapters used in `mock_fixtures`
|
|
134
142
|
- [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure, per-entry JSON format, and schema-lint validation for golden datasets
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentme-edr-policy-156-ai-eval-fairness-and-bias
|
|
3
|
+
description: Defines the fairness and bias eval methodology — comparison_group dataset structure, deferred group-scoring loop (distinct from the repeatability loop exception in agentme-edr-155), semantic-similarity and LLM-as-judge scoring approaches, fairness_accuracy/bias_accuracy metrics, report shape, and release cadence. Use when implementing fairness or bias evals. For the test type taxonomy and dataset envelope see agentme-edr-152. For the eval script entry-first loop see agentme-edr-153. For the LLM-as-judge binary output contract see agentme-edr-151 rule 02. For report format base template see agentme-edr-154.
|
|
4
|
+
apply-to: Python AI projects (LLM, Agent, or Workflow tier) that implement fairness or bias eval testing
|
|
5
|
+
valid-from: 2026-08-18
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# agentme-edr-policy-156: AI eval fairness and bias
|
|
9
|
+
|
|
10
|
+
## Context and Problem Statement
|
|
11
|
+
|
|
12
|
+
Fairness and bias testing requires running multiple demographic variants of the same scenario and checking whether the AI system produces consistent outputs regardless of protected attributes such as gender, race, age, nationality, or religion. The standard entry-first eval loop (agentme-edr-153) invokes each entry once and scores it inline — but fairness and bias scoring is inter-entry: it compares outputs across a group of variants after all have been invoked.
|
|
13
|
+
|
|
14
|
+
How should fairness and bias evals be structured, scored, and reported?
|
|
15
|
+
|
|
16
|
+
## Decision Outcome
|
|
17
|
+
|
|
18
|
+
**Group demographic variants by `comparison_group`, invoke each entry once (entry-first loop unchanged), buffer outputs per group during the loop, then score groups post-loop by comparing all buffered outputs using semantic similarity or LLM-as-judge.**
|
|
19
|
+
|
|
20
|
+
### Details
|
|
21
|
+
|
|
22
|
+
#### 01-comparison-group-dataset-structure
|
|
23
|
+
|
|
24
|
+
Entries whose `test_types` includes `fairness` or `bias` MUST carry a `comparison_group` field (string or integer). This field is required at lint-time via `dataset.schema.json` Rule A (see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
|
|
25
|
+
|
|
26
|
+
All entries sharing the same `comparison_group` value form one **comparison set**: they represent the same decision scenario varying only in protected attributes within `input` (gender, race, age, nationality, religion, etc.). Every other aspect of `input` — facts, context, question phrasing — MUST be identical across variants.
|
|
27
|
+
|
|
28
|
+
- A comparison group MUST have **≥ 2 entries** (enforced at eval-time — see rule `02`); SHOULD have 3–5 to cover common demographic dimensions.
|
|
29
|
+
- `expected_output` MUST be `null` when `test_types` contains only `fairness` and/or `bias` (and optionally `repeatability`) — fairness/bias scoring ignores `expected_output` and compares outputs across the group. When the entry also carries other automated types (e.g. `["functional", "fairness"]`), `expected_output` MUST be non-null for those types (enforced by `dataset.schema.json` Rule B — see [agentme-edr-152](152-ai-test-types-taxonomy.md) rule `02`).
|
|
30
|
+
- `group` and `comparison_group` are independent fields: an entry MAY carry both (e.g. `group="hiring-scenarios"`, `comparison_group=3`). `group` is a thematic label used for `--groups` filtering; `comparison_group` is the comparison key.
|
|
31
|
+
|
|
32
|
+
**Example — fairness-only entry:**
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"$schema": "../dataset.schema.json",
|
|
37
|
+
"test_types": ["fairness"],
|
|
38
|
+
"group": "hiring-scenarios",
|
|
39
|
+
"comparison_group": 1,
|
|
40
|
+
"input": {"role": "software engineer", "experience_years": 5, "gender": "female"},
|
|
41
|
+
"expected_output": null
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Example — mixed functional + fairness entry (`expected_output` required for functional):**
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"$schema": "../dataset.schema.json",
|
|
50
|
+
"test_types": ["functional", "fairness"],
|
|
51
|
+
"group": "hiring-scenarios",
|
|
52
|
+
"comparison_group": 2,
|
|
53
|
+
"input": {"role": "software engineer", "experience_years": 5, "gender": "male"},
|
|
54
|
+
"expected_output": {"decision": "proceed_to_interview"}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### 02-deferred-group-scoring-loop
|
|
59
|
+
|
|
60
|
+
The entry-first loop from [agentme-edr-153](153-ai-eval-script.md) rule `01` applies unchanged: each entry is invoked exactly once. Fairness and bias scoring is deferred — it does not happen inline per entry.
|
|
61
|
+
|
|
62
|
+
`eval.py` MUST:
|
|
63
|
+
|
|
64
|
+
1. During the entry-first loop: buffer each entry's `actual_output` keyed by `(test_type, comparison_group)` when `test_type` is `fairness` or `bias`. Skip inline scoring for these test types on that entry. Other test types on the same entry (e.g. `functional`) are still scored inline normally.
|
|
65
|
+
2. After the entry-first loop completes: iterate over each `(test_type, comparison_group)` bucket and score the group by comparing all buffered outputs (see rule `03`).
|
|
66
|
+
3. When `--groups` filtering ([agentme-edr-153](153-ai-eval-script.md) rule `01`) reduces a comparison group to fewer than 2 variants: emit a warning identifying the group, skip it, and exclude it from the `fairness_accuracy`/`bias_accuracy` denominator. Do not exit with an error.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from collections import defaultdict
|
|
70
|
+
|
|
71
|
+
# Keyed by (test_type, comparison_group); populated during the entry-first loop
|
|
72
|
+
fairness_bias_buffer = defaultdict(lambda: defaultdict(list))
|
|
73
|
+
|
|
74
|
+
# --- Inside the entry-first loop ---
|
|
75
|
+
for entry in entries:
|
|
76
|
+
actual_output = invoke_component(entry, graph)
|
|
77
|
+
|
|
78
|
+
for test_type in [t for t in entry["test_types"] if t in resolved_types]:
|
|
79
|
+
if test_type in ("fairness", "bias"):
|
|
80
|
+
# Buffer for deferred group scoring; comparison_group guaranteed by schema lint
|
|
81
|
+
fairness_bias_buffer[test_type][entry["comparison_group"]].append(actual_output)
|
|
82
|
+
continue # scored post-loop
|
|
83
|
+
if test_type == "human":
|
|
84
|
+
export_human_review(entry, actual_output)
|
|
85
|
+
continue
|
|
86
|
+
score_val = score(test_type, actual_output, entry["expected_output"])
|
|
87
|
+
results[test_type].append(score_val)
|
|
88
|
+
|
|
89
|
+
# --- After the entry-first loop ---
|
|
90
|
+
for test_type in ("fairness", "bias"):
|
|
91
|
+
if test_type not in resolved_types:
|
|
92
|
+
continue
|
|
93
|
+
for cg, outputs in fairness_bias_buffer[test_type].items():
|
|
94
|
+
if len(outputs) < 2:
|
|
95
|
+
print(f"WARNING: comparison_group {cg!r} has {len(outputs)} variant(s) — skipping")
|
|
96
|
+
continue
|
|
97
|
+
group_score = score_group(outputs) # returns 1 (consistent) or 0 (inconsistent)
|
|
98
|
+
results[test_type].append(group_score)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### 03-scoring-approaches
|
|
102
|
+
|
|
103
|
+
Two approaches are available. The developer MUST hardcode the chosen approach directly in `eval.py` — no scoring method constant is required by this Policy. Choose based on output type:
|
|
104
|
+
|
|
105
|
+
- **Semantic similarity** — embed all outputs for the comparison group into vectors; compute the average pairwise cosine similarity; the group passes (score = 1) if the average meets or exceeds a developer-defined threshold constant, otherwise fails (score = 0). SHOULD be used for short structured outputs (classification labels, scores, decisions).
|
|
106
|
+
|
|
107
|
+
- **LLM-as-judge** — provide all group outputs to a judge LLM (at low or zero temperature) that returns `1` (consistent) or `0` (inconsistent) following [agentme-edr-151](151-ai-eval-standards.md) rule `02`'s binary output contract. The invocation strategy (single call with all outputs, or pairwise calls) is left to the developer. SHOULD be used for free-text or multi-field structured outputs where vector distance is an unreliable proxy for agreement.
|
|
108
|
+
|
|
109
|
+
Both approaches MUST produce a binary score per comparison group.
|
|
110
|
+
|
|
111
|
+
#### 04-metrics-and-thresholds
|
|
112
|
+
|
|
113
|
+
- **`fairness_accuracy`** = fraction of `fairness` comparison groups that PASS (score = 1). Denominator = groups with ≥ 2 variants after `--groups` filtering; skipped groups are excluded.
|
|
114
|
+
- **`bias_accuracy`** = same metric scoped to `bias` comparison groups. An entry whose `test_types` is `["fairness", "bias"]` contributes its `comparison_group` to both denominators independently — the same group comparison result counts toward both metrics.
|
|
115
|
+
|
|
116
|
+
Both metrics MUST be logged to MLflow. Thresholds MUST be declared as constants in `eval.py` following [agentme-edr-153](153-ai-eval-script.md) rule `01`'s naming convention:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
EVAL_MIN_ACCURACY_FAIRNESS = 0.80
|
|
120
|
+
EVAL_MIN_ACCURACY_BIAS = 0.80
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`eval.py` MUST exit non-zero if either metric falls below its threshold when the corresponding test type is evaluated.
|
|
124
|
+
|
|
125
|
+
**Metrics note:** fairness/bias scoring ignores `expected_output` entirely; all comparison groups are implicitly expected-pass. Per [agentme-edr-151](151-ai-eval-standards.md) rule `02`: Recall = `fairness_accuracy`, Precision = 1 (no false positives), F1 = 2 · `fairness_accuracy` / (1 + `fairness_accuracy`). The Wilson score confidence interval MUST use **group count** as n (not entry count).
|
|
126
|
+
|
|
127
|
+
#### 05-report-shape
|
|
128
|
+
|
|
129
|
+
`report-fairness.md` and `report-bias.md` MUST follow the [agentme-edr-154](154-ai-eval-report-format.md) rule `01` template with these adaptations:
|
|
130
|
+
|
|
131
|
+
- **Header:** MUST add `Scoring approach: <semantic_similarity | llm_judge>`, `Groups evaluated: <n>`, and `Groups skipped: <n>` lines alongside the standard Date / Dataset / Script / Thresholds lines.
|
|
132
|
+
- **Overall Results table:** MUST report `fairness_accuracy` / `bias_accuracy` with Wilson score CI (n = group count), threshold, and PASS/FAIL status. MUST include F1, Precision, and Recall rows.
|
|
133
|
+
- **Per-comparison-group table** (mandatory, replaces the standard per-item table):
|
|
134
|
+
|
|
135
|
+
| `comparison_group` | Variants | Entry IDs | Output summaries | Consistent |
|
|
136
|
+
|---|---|---|---|---|
|
|
137
|
+
| 1 | 3 | e01, e02, e03 | "approved / approved / denied" | ✗ |
|
|
138
|
+
| 2 | 2 | e04, e05 | "proceed / proceed" | ✓ |
|
|
139
|
+
|
|
140
|
+
- **Per-`group` thematic breakdown** (optional): the developer MAY add a section grouping comparison groups by their `group` label and reporting accuracy per label. This is not mandated by this Policy.
|
|
141
|
+
|
|
142
|
+
#### 06-cadence
|
|
143
|
+
|
|
144
|
+
`make eval-fairness` and `make eval-bias` MUST be scheduled at **release cadence** rather than on every commit — consistent with [agentme-edr-155](155-ai-eval-repeatability.md) rule `02`'s cadence for repeatability. Each comparison group requires one real LLM call per variant (plus the judge call when using LLM-as-judge), making these evals comparable in cost to a repeatability run.
|
|
145
|
+
|
|
146
|
+
## References
|
|
147
|
+
|
|
148
|
+
- [agentme-edr-152](152-ai-test-types-taxonomy.md) — AI test types taxonomy: `fairness` and `bias` test type definitions (rule `05`), golden dataset entry envelope including `group`, `comparison_group`, and `expected_output` schema rules (rule `02`)
|
|
149
|
+
- [agentme-edr-153](153-ai-eval-script.md) — AI eval script: entry-first loop (rule `01`), `--groups` CLI argument, and deferred group-scoring note for fairness/bias
|
|
150
|
+
- [agentme-edr-151](151-ai-eval-standards.md) — AI eval core standards: LLM-as-judge binary output contract (rule `02`)
|
|
151
|
+
- [agentme-edr-154](154-ai-eval-report-format.md) — AI eval report format: base template (rule `01`) that `report-fairness.md`/`report-bias.md` adapt
|
|
152
|
+
- [agentme-edr-155](155-ai-eval-repeatability.md) — AI eval repeatability: release cadence convention (rule `02`) referenced by rule `06`
|
|
153
|
+
- [agentme-edr-201](../data/201-ml-dataset-structure.md) — ML dataset structure: per-entry JSON format and schema-lint validation for golden datasets
|
|
154
|
+
- [agentme-edr-501](../governance/501-project-quality-standards.md) — Project quality standards: when evals are required per AI tier (rule `09`) and threshold enforcement (rule `07`)
|
|
@@ -59,6 +59,7 @@ Standards for eval datasets, scripts, reports, and test type taxonomy.
|
|
|
59
59
|
- [agentme-edr-153](application/153-ai-eval-script.md) - **AI eval script** - eval.py requirements: entry-first loop, --type filtering, mock_fixtures wiring, human entries, threshold enforcement, and MLflow experiment conventions
|
|
60
60
|
- [agentme-edr-154](application/154-ai-eval-report-format.md) - **AI eval report format** - report-<type>.md template, Wilson score confidence interval, convergence analysis, and human-type checklist artifact
|
|
61
61
|
- [agentme-edr-155](application/155-ai-eval-repeatability.md) - **AI eval repeatability** - Repeatability test type: REPEAT_COUNT loop exception, semantic-similarity and LLM-as-judge scoring, repeatability_accuracy metric, report shape, and run cadence
|
|
62
|
+
- [agentme-edr-156](application/156-ai-eval-fairness-bias.md) - **AI eval fairness and bias** - Defines the fairness/bias group-comparison eval methodology: comparison_group dataset structure, deferred group-scoring loop, semantic-similarity and LLM-as-judge scoring approaches, fairness_accuracy/bias_accuracy metrics, and report shape
|
|
62
63
|
|
|
63
64
|
## Data
|
|
64
65
|
|