test: eval judges e2e #14

Merged
masi merged 4 commits from test/eval-judges-trigger into main 2026-09-01 00:26:59 +00:00
4 changed files with 25 additions and 10 deletions
+1
View File
@@ -0,0 +1 @@
# judge trigger 1788203999
+2
View File
@@ -185,3 +185,5 @@ review time.
## License ## License
Not yet chosen. Until one is added, no reuse rights are granted. Not yet chosen. Until one is added, no reuse rights are granted.
_pilot eval judges test 1788201461_
+13 -7
View File
@@ -208,18 +208,24 @@ def ensure_evaluators() -> dict:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def rule_body(name: str, judge_name: str, sampling: float) -> dict: def rule_body(name: str, judge_name: str, sampling: float) -> dict:
"""POST /evaluation-rules shape for an LLM-as-judge observation rule. """POST /evaluation-rules shape for an LLM-as-judge trace rule.
The judge is referenced by `name`+`scope`, not by id — ids name specific Target is `trace` rather than `observation` on purpose: the standard
versions, names name the evaluator across versions. Mapping is required at `/api/public/ingestion` path that ships review traces here feeds only
both the rule root (the server validates it there) and inside `evaluator` the trace-upsert queue, and `evalService.createEvalJobs` only creates
(the API echoes it back). Filter is on `traceName` because that is the only jobs for `targetObject ∈ {TRACE, DATASET}`. Observation rules are
stringOptions column the observation-rule schema exposes. triggered exclusively from the OTel ingestion pipeline, which this
pilot does not use. A trace rule reads the trace's own input/output —
`langfuse_trace` already writes `_review_input`/`_review_output` onto
the trace body for exactly this reason.
Mapping is required at both the rule root (server validates it there)
and inside `evaluator` (the API echoes it back).
""" """
return { return {
"name": name, "name": name,
"enabled": True, "enabled": True,
"target": "observation", "target": "trace",
"sampling": sampling, "sampling": sampling,
"filter": [ "filter": [
{"column": "traceName", "operator": "any of", {"column": "traceName", "operator": "any of",
1
+9 -3
View File
@@ -11,10 +11,16 @@ import eval_judges as ej # noqa: E402
# --- rule_body ------------------------------------------------------------ # --- rule_body ------------------------------------------------------------
def test_rule_body_targets_observations(): def test_rule_body_targets_traces():
"""Trace-level rules wouldn't see observation input/output.""" """Trace target matches the path `/api/public/ingestion` triggers.
Observation rules only fire from the OTel ingestion pipeline; this
pilot uses standard ingestion, so its jobs only come from
`evalService.createEvalJobs` and that dispatcher handles
`targetObject ∈ {TRACE, DATASET}`.
"""
body = ej.rule_body("rule-x", "finding_actionability", 1.0) body = ej.rule_body("rule-x", "finding_actionability", 1.0)
assert body["target"] == "observation" assert body["target"] == "trace"
assert body["enabled"] is True assert body["enabled"] is True