fix(metrics): parse LLM judge scores from structured JSON responses#214
fix(metrics): parse LLM judge scores from structured JSON responses#214syf2211 wants to merge 2 commits into
Conversation
Fixes OpenAgentHQ#74 - Request structured JSON scores in built-in judge prompts - Parse JSON (including fenced blocks) before regex fallbacks - Remove keyword heuristics that produced false positives - Log warnings when falling back to regex or default score
|
/oc review pr |
|
All 18 tests pass. Here's my review: Review:
|
| Issue | Location | Suggestion |
|---|---|---|
_json_score_candidates always appends text raw |
llm_judge.py:227 |
If fenced JSON matched, raw text is tried second — fine, but consider cost if response is very long (negligible here). |
_BARE_DECIMAL_RE uses match not search |
llm_judge.py:24 |
Intentional — only matches if the whole string is a number. This is correct behavior but worth noting since match is anchored at start. |
| No test for malformed JSON with valid score elsewhere | test_nli.py | e.g. {"score" 0.85} (invalid JSON) should fall through to labeled/bare — implicitly covered by the fallback chain but not explicitly tested. |
Verdict
Approve. The change is a clear improvement: more robust, more predictable, better diagnostics. Backward compatibility is maintained through explicit fallbacks. The test suite gives high confidence.
|
@syf2211 Could you plz review the Nitpicks (minor) suggest by the bot. This pr is ready to merge just took a look on suggestions. Thanks |

Summary
Improve
LLMJudgeMetricscore parsing to prefer structured JSON output instead of fragile regex/keyword heuristics.Fixes #74
Motivation
The previous
_parse_scoreimplementation could match the wrong number in free-form LLM text, treat keyword substrings like "excellent" as high scores, and silently fall back to an arbitrary 0.5 default.Changes
{"score": <0.0-1.0>}scorekey lookupScore: 0.85) and bare numeric responses (0.92)Tests
pytest tests/unit/test_metrics/test_nli.py -k llm_judge -q # 18 passedNotes
Custom
JudgeCriteriawithout the JSON instruction still get labeled/bare-numeric fallbacks, but ambiguous prose now returns the default score with a warning instead of guessing from the first digit.