verifiers 0.3.2.dev184__py3-none-any.whl → 0.3.2.dev185__py3-none-any.whl

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.
verifiers/v1/__init__.py CHANGED
@@ -66,6 +66,8 @@ from verifiers.v1.harness import Harness, HarnessSession
66
66
  from verifiers.v1.judge import Judge, JudgeResponse, JudgeView
67
67
  from verifiers.v1.judges import (
68
68
  Criterion,
69
+ DecisionJudge,
70
+ DecisionJudgeConfig,
69
71
  ReferenceJudge,
70
72
  ReferenceJudgeConfig,
71
73
  RubricJudge,
@@ -358,6 +360,8 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
358
360
  "Judges",
359
361
  "JudgeResponse",
360
362
  "JudgeView",
363
+ "DecisionJudge",
364
+ "DecisionJudgeConfig",
361
365
  "ReferenceJudge",
362
366
  "ReferenceJudgeConfig",
363
367
  "RubricJudge",
@@ -60,7 +60,10 @@ class BaseClientConfig(BaseConfig):
60
60
  or prime_config.get("inference_url")
61
61
  or DEFAULT_PRIME_INFERENCE_URL
62
62
  )
63
- if "base_url" not in self.model_fields_set:
63
+ if (
64
+ "base_url" not in self.model_fields_set
65
+ and self.base_url == DEFAULT_PRIME_INFERENCE_URL
66
+ ):
64
67
  self.base_url = prime_base_url
65
68
  host = urlparse(self.base_url).hostname or ""
66
69
  if host != PRIME_INFERENCE_HOST and not host.endswith(
@@ -40,7 +40,7 @@ def resolve_judges(entries: Sequence[Any]) -> list[JudgeConfig]:
40
40
  if not raw.get("id"):
41
41
  raise ValueError(
42
42
  "each `judges` entry needs an `id` (a judge plugin: `reference`, "
43
- "`rubric`, or an installed package)"
43
+ "`rubric`, `decision`, or an installed package)"
44
44
  )
45
45
  resolved.append(judge_config_type(raw["id"]).model_validate(raw))
46
46
  return resolved
@@ -51,7 +51,7 @@ def check_judges(entries: Sequence[JudgeConfig]) -> None:
51
51
  if not entry.id:
52
52
  raise ValueError(
53
53
  "each `judges` entry needs an `id` (a judge plugin: `reference`, "
54
- "`rubric`, or an installed package)"
54
+ "`rubric`, `decision`, or an installed package)"
55
55
  )
56
56
  keys = [judge_key(entry) for entry in entries]
57
57
  if duplicates := {key for key in keys if keys.count(key) > 1}:
@@ -1,8 +1,11 @@
1
+ from verifiers.v1.judges.decision import DecisionJudge, DecisionJudgeConfig
1
2
  from verifiers.v1.judges.reference import ReferenceJudge, ReferenceJudgeConfig
2
3
  from verifiers.v1.judges.rubric import Criterion, RubricJudge, RubricJudgeConfig
3
4
 
4
5
  __all__ = [
5
6
  "Criterion",
7
+ "DecisionJudge",
8
+ "DecisionJudgeConfig",
6
9
  "ReferenceJudge",
7
10
  "ReferenceJudgeConfig",
8
11
  "RubricJudge",
@@ -0,0 +1,105 @@
1
+ """Decision-model judge using Prime's evaluations API by default."""
2
+
3
+ import json
4
+ from typing import Any, cast
5
+
6
+ from pydantic import Field
7
+
8
+ from verifiers.v1.clients.base import build_async_openai
9
+ from verifiers.v1.configs.judge import JudgeConfig
10
+ from verifiers.v1.judge import (
11
+ Judge,
12
+ JudgeResponse,
13
+ JudgeView,
14
+ judge_question,
15
+ judge_response,
16
+ )
17
+ from verifiers.v1.task import TaskData
18
+ from verifiers.v1.trace import Trace
19
+ from verifiers.v1.types import ID, Usage
20
+
21
+
22
+ class DecisionJudgeConfig(JudgeConfig):
23
+ id: ID = "decision"
24
+ model: str = "typesafe-ai/jev"
25
+ base_url: str = "https://api.pinference.ai/api/v1/evaluations"
26
+ """Full URL to POST evaluation requests to."""
27
+ levels: list[str] = Field(
28
+ default_factory=lambda: ["Incorrect", "Correct"], min_length=2, max_length=10
29
+ )
30
+ """Grading levels, worst to best. The model's probability-weighted level is
31
+ normalized to [0, 1], so a two-level grade is the probability of correctness."""
32
+ question_field: str = ""
33
+ """Task field containing the question; empty uses the task's prompt text."""
34
+ answer_field: str = ""
35
+ """Optional task field containing a reference answer to include in the state."""
36
+ view: JudgeView = "last_reply"
37
+
38
+
39
+ class DecisionJudge(Judge[float, DecisionJudgeConfig]):
40
+ prompt = (
41
+ "Grade how well the response satisfies the task in question. "
42
+ "Use the reference answer when provided; equivalent answers are acceptable."
43
+ )
44
+
45
+ async def evaluate(
46
+ self, *, trace: Trace | None = None, **fields: Any
47
+ ) -> JudgeResponse[float]:
48
+ request = {
49
+ "model": self.config.model,
50
+ "state": fields,
51
+ "questions": {
52
+ "grade": {
53
+ "type": "score",
54
+ "instructions": self.build_messages(**fields),
55
+ "criteria": self.config.levels,
56
+ }
57
+ },
58
+ }
59
+ async with build_async_openai(self.config) as client:
60
+ raw = await client.post(
61
+ self.config.base_url, cast_to=dict[str, Any], body=request
62
+ )
63
+ result = raw.get("result", raw) # Workers AI wraps its response in `result`.
64
+ response = JudgeResponse[float](text=json.dumps(raw))
65
+ try:
66
+ if usage := result.get("usage"):
67
+ response.usage = Usage(
68
+ prompt_tokens=usage.get("inputTokens", usage.get("input_tokens")),
69
+ completion_tokens=usage.get(
70
+ "outputTokens", usage.get("output_tokens")
71
+ ),
72
+ cost=usage.get("cost"),
73
+ )
74
+ score = result["answers"]["grade"]["score"] / (len(self.config.levels) - 1)
75
+ if not 0 <= score <= 1:
76
+ raise ValueError(f"decision judge score {score!r} is outside [0, 1]")
77
+ response.parsed = score
78
+ return response
79
+ finally:
80
+ # The call was billed even if the score could not be parsed.
81
+ if trace is not None:
82
+ trace.record_judge_call(
83
+ name=self.reward_name, request=request, response=response
84
+ )
85
+
86
+ async def score(self, task: TaskData, trace: Trace) -> float:
87
+ response = judge_response(trace, self.config.view)
88
+ if not response.strip():
89
+ return 0.0
90
+ fields = {
91
+ "question": judge_question(task, self.config.question_field),
92
+ "response": response,
93
+ }
94
+ if self.config.answer_field:
95
+ answer = getattr(task, self.config.answer_field, None)
96
+ if answer is None:
97
+ raise ValueError(
98
+ f"decision judge found no {self.config.answer_field!r} field on the task"
99
+ )
100
+ fields["answer"] = answer
101
+ result = await self.evaluate(trace=trace, **fields)
102
+ return cast(float, result.parsed)
103
+
104
+
105
+ __all__ = ["DecisionJudge", "DecisionJudgeConfig"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev184
3
+ Version: 0.3.2.dev185
4
4
  Summary: Verifiers: Environments for LLM Reinforcement Learning
5
5
  Project-URL: Homepage, https://github.com/primeintellect-ai/verifiers
6
6
  Project-URL: Documentation, https://github.com/primeintellect-ai/verifiers
@@ -1,5 +1,5 @@
1
1
  verifiers/__init__.py,sha256=F5IVMw6mhGaPBMCw7QKk0la_r5mMwydP2hdTTdQucik,352
2
- verifiers/v1/__init__.py,sha256=ybCeLKoVNDU9nwla4BG8HrcZ2oXOuXquRBhaorGevxI,8792
2
+ verifiers/v1/__init__.py,sha256=xvS_VfN7QwTethhEJsZCi7lHicKvQdQKh2nhB2h9Lu8,8884
3
3
  verifiers/v1/agent.py,sha256=zBqbHDeqdPghg_QOkcyFplIDY3f34qCOtwcxJnl5N-U,45088
4
4
  verifiers/v1/env.py,sha256=fxXBjVyi0milYViHt6O0vBK3JdM2TYSOoQpXd0P0rFE,18110
5
5
  verifiers/v1/episode.py,sha256=UPtA02aGWA-fY8cJKEuYCMtQVnPN1C0BSN13LggNT8U,5986
@@ -43,10 +43,10 @@ verifiers/v1/clients/eval.py,sha256=x_5E8XnhFu4v-k4yI8WWHd39rDkvB7mSEPCVAWL4AiE,
43
43
  verifiers/v1/clients/train.py,sha256=lSJTwHjwOET3D_CI_eYZSoXSQcv2H0K5sYJ7kD_kdw4,19489
44
44
  verifiers/v1/configs/__init__.py,sha256=X7u6X7B3ieD1HZl79Tv1kg-yPHbT0QLvAebaGqxVtvA,317
45
45
  verifiers/v1/configs/agent.py,sha256=Vut73R2EW8QuL5c0iTnNFC_g-Obvl8YUKsjlvkABuL0,5311
46
- verifiers/v1/configs/client.py,sha256=vl46nrayZa84zrPBuEVpJIjDjbmYUIrDIuR0vZvvugw,5212
46
+ verifiers/v1/configs/client.py,sha256=i45QOop2Wb-LQRpNgUZGTCT1_HpNmdcG41eQrGMgJKQ,5297
47
47
  verifiers/v1/configs/env.py,sha256=k47XBYYWLOf-8P1dbek3x_s0ucNb726xxoryG69DIr4,7256
48
48
  verifiers/v1/configs/harness.py,sha256=ZrR-Egzfft95oMoqQ78bAq9TqP882Q68M_47Ajw9lE8,2918
49
- verifiers/v1/configs/judge.py,sha256=WEwA8D4X5JSaIP3c-E2wPnvgByWeT6JRAn1d8gfiQ40,2142
49
+ verifiers/v1/configs/judge.py,sha256=3ZvxcTf-3clj8bDLyaqsMSKCRclTQCvbyb2qp3QSRD8,2166
50
50
  verifiers/v1/configs/retries.py,sha256=BgpGbdMBmjyjcIGnvb5VTJzKMDA6TdKil-PBQaRwGZM,1770
51
51
  verifiers/v1/configs/runtime.py,sha256=3LDAnKy-BotE6MqyT1l07Y_bAq9Wye1OU8JZ7lyUVvY,5474
52
52
  verifiers/v1/configs/select.py,sha256=_HdcepQaJ1sDCYcs7Vqx72npDwHGOgUjsLDZmcgnonU,4743
@@ -131,7 +131,8 @@ verifiers/v1/interception/tunnel/__init__.py,sha256=eVNZJszj6myrKhx9jmJz7VRd9qlf
131
131
  verifiers/v1/interception/tunnel/base.py,sha256=DZB6uPLwM4Qy7n7m0vKeyg-Px87MhsmpYTpe2vpPEng,1998
132
132
  verifiers/v1/interception/tunnel/custom.py,sha256=yL4UbGf4bAuMsxk42mEP-t1wITQCT8BE9FHQIz0qRMA,1708
133
133
  verifiers/v1/interception/tunnel/prime.py,sha256=jVk_6xyrxXiHtsVFErcRNd4MoENdFbqzfC0i20nlizU,2803
134
- verifiers/v1/judges/__init__.py,sha256=MUIBWcx6c70BykrTDHhB0ITIyJPxXe6xDBou4VM7jDQ,286
134
+ verifiers/v1/judges/__init__.py,sha256=z-16awBqEZJrlVYIb9HD-rk12RaABh6jodJgwX4blnA,410
135
+ verifiers/v1/judges/decision.py,sha256=U8BKuzJVMWfX76fa6jaG_rmcOhzMkZoXSnkUuHKpoV4,3991
135
136
  verifiers/v1/judges/reference.py,sha256=iEVHw-iJ6dbwLOOqrvWrEMJOcUEYJ0YspT04rZz7Sd4,3868
136
137
  verifiers/v1/judges/reference.txt,sha256=Ej35kGXiT2uJ0LcHIeez49rCS_9uHmCQKoVdn93V6A8,353
137
138
  verifiers/v1/judges/rubric.py,sha256=HGQYI3xdq8I84Ce0_sDeNgk5JM597es8rOVPipjCyxU,12025
@@ -194,8 +195,8 @@ verifiers/v1/utils/scope.py,sha256=bzUEiWDOVdbj7dXOwGOlzsQ_-Xu0j9NR5TalQB-8TS8,8
194
195
  verifiers/v1/utils/score.py,sha256=493yJVMw8teCu9JxapxMFPFzI0hNUqdo0Y2nGW4kckk,6200
195
196
  verifiers/v1/utils/trace_store.py,sha256=RsCDonGR-bs-tvEstcppiJm3jFmAdIiG83fA5KtCbAw,2801
196
197
  verifiers/v1/utils/version.py,sha256=-obEo_-l9-D8FLef4hYxncOe-uJpxrM1g2Hig_37Sgs,1607
197
- verifiers-0.3.2.dev184.dist-info/METADATA,sha256=2jIg7eRwvlbVGsPE_AYQvvGKAPnBCZiY1E7GXeE66Ck,4227
198
- verifiers-0.3.2.dev184.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
199
- verifiers-0.3.2.dev184.dist-info/entry_points.txt,sha256=iugElcdWPKbQM7uFF0lZ8iUpHsNr17-BwEAAjJWxV3U,259
200
- verifiers-0.3.2.dev184.dist-info/licenses/LICENSE,sha256=v0RrUsdV3IDoZhrRce297IXS3xMHNJ-_LdLpFAUWb9k,1072
201
- verifiers-0.3.2.dev184.dist-info/RECORD,,
198
+ verifiers-0.3.2.dev185.dist-info/METADATA,sha256=DF9K7iZDqE_b9Sf8WSNbMwPW1mZlDdTxqrUZtxUQNrY,4227
199
+ verifiers-0.3.2.dev185.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
200
+ verifiers-0.3.2.dev185.dist-info/entry_points.txt,sha256=iugElcdWPKbQM7uFF0lZ8iUpHsNr17-BwEAAjJWxV3U,259
201
+ verifiers-0.3.2.dev185.dist-info/licenses/LICENSE,sha256=v0RrUsdV3IDoZhrRce297IXS3xMHNJ-_LdLpFAUWb9k,1072
202
+ verifiers-0.3.2.dev185.dist-info/RECORD,,