verifiers 0.3.2.dev58__py3-none-any.whl → 0.3.2.dev60__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.
Potentially problematic release.
This version of verifiers might be problematic. Click here for more details.
- verifiers/v1/dialects/chat.py +7 -0
- verifiers/v1/dialects/responses.py +4 -1
- verifiers/v1/runtimes/base.py +22 -12
- verifiers/v1/runtimes/docker/__init__.py +12 -3
- verifiers/v1/runtimes/modal.py +3 -1
- verifiers/v1/runtimes/prime.py +3 -1
- verifiers/v1/runtimes/subprocess.py +24 -2
- {verifiers-0.3.2.dev58.dist-info → verifiers-0.3.2.dev60.dist-info}/METADATA +1 -1
- {verifiers-0.3.2.dev58.dist-info → verifiers-0.3.2.dev60.dist-info}/RECORD +12 -12
- {verifiers-0.3.2.dev58.dist-info → verifiers-0.3.2.dev60.dist-info}/WHEEL +0 -0
- {verifiers-0.3.2.dev58.dist-info → verifiers-0.3.2.dev60.dist-info}/entry_points.txt +0 -0
- {verifiers-0.3.2.dev58.dist-info → verifiers-0.3.2.dev60.dist-info}/licenses/LICENSE +0 -0
verifiers/v1/dialects/chat.py
CHANGED
|
@@ -15,6 +15,7 @@ from typing import Any
|
|
|
15
15
|
from urllib.parse import urlsplit
|
|
16
16
|
|
|
17
17
|
from openai.types.chat import ChatCompletion
|
|
18
|
+
from openai.types.chat.chat_completion import Choice
|
|
18
19
|
|
|
19
20
|
from verifiers.v1.configs.runtime import NetworkPolicyConfig
|
|
20
21
|
from verifiers.v1.dialects.base import (
|
|
@@ -44,12 +45,18 @@ from verifiers.v1.types import (
|
|
|
44
45
|
)
|
|
45
46
|
|
|
46
47
|
|
|
48
|
+
class ModdedChoice(Choice):
|
|
49
|
+
# Logprobs are relayed in Response.raw; trace conversion never reads them.
|
|
50
|
+
logprobs: Any = None
|
|
51
|
+
|
|
52
|
+
|
|
47
53
|
class ModdedChatCompletion(ChatCompletion):
|
|
48
54
|
"""The OpenAI SDK closes `service_tier` to a fixed `Literal`, but providers return tiers
|
|
49
55
|
outside it (e.g. Prime's `provisioned`), which makes `model_validate` reject an otherwise
|
|
50
56
|
valid completion. Widen the field to a plain string — we don't consume it — so parsing stays
|
|
51
57
|
lenient about the label instead of dropping it."""
|
|
52
58
|
|
|
59
|
+
choices: list[ModdedChoice]
|
|
53
60
|
service_tier: str | None = None
|
|
54
61
|
|
|
55
62
|
|
|
@@ -315,7 +315,10 @@ def fold_assistant(items: list[dict] | None) -> AssistantMessage:
|
|
|
315
315
|
def response_from_wire(response: OpenAIResponse) -> Response:
|
|
316
316
|
"""An OpenAI Responses object -> a vf `Response` (its `output` items folded into one
|
|
317
317
|
assistant message)."""
|
|
318
|
-
|
|
318
|
+
# Copy the output snapshot without traversing echoed tools or request settings.
|
|
319
|
+
data = response.model_dump(
|
|
320
|
+
include={"id", "created_at", "model", "status", "error", "output"}
|
|
321
|
+
)
|
|
319
322
|
status = data.get("status")
|
|
320
323
|
if status not in (None, "completed", "incomplete"):
|
|
321
324
|
error = data.get("error") or {}
|
verifiers/v1/runtimes/base.py
CHANGED
|
@@ -316,13 +316,30 @@ class Runtime(ABC):
|
|
|
316
316
|
"""Read `path` into host memory. `max_bytes` caps the transfer, raising past
|
|
317
317
|
the cap — for a file written by something we don't control, whose size we
|
|
318
318
|
can't assume. The cap is enforced inside the box rather than after the
|
|
319
|
-
transfer
|
|
320
|
-
override `_read`, not this."""
|
|
319
|
+
transfer. Framework method — override `_read`, not this."""
|
|
321
320
|
if max_bytes is None:
|
|
322
321
|
return await self._read(path)
|
|
322
|
+
if max_bytes < 0:
|
|
323
|
+
raise ValueError("max_bytes must be non-negative")
|
|
324
|
+
# One extra byte distinguishes an exact fit from a truncated file.
|
|
325
|
+
data = await self._read(path, max_bytes=max_bytes + 1)
|
|
326
|
+
if len(data) > max_bytes:
|
|
327
|
+
raise SandboxError(f"read {path!r}: over the {max_bytes} byte limit")
|
|
328
|
+
return data
|
|
329
|
+
|
|
330
|
+
@abstractmethod
|
|
331
|
+
async def _read(self, path: str, max_bytes: int | None = None) -> bytes:
|
|
332
|
+
"""Read at most `max_bytes` bytes at the source, or the whole file if None.
|
|
333
|
+
|
|
334
|
+
Overrides must accept `max_bytes` and enforce it before transferring data.
|
|
335
|
+
The public `read` method checks for overflow using one extra byte.
|
|
336
|
+
Runtimes without bounded binary reads delegate capped reads here, using
|
|
337
|
+
base64 because `run` returns decoded text.
|
|
338
|
+
"""
|
|
339
|
+
assert max_bytes is not None
|
|
323
340
|
# Through a temp file, not a pipe: `head | base64` exits with base64's 0
|
|
324
341
|
# even when the path is missing, and a missing file must raise here just
|
|
325
|
-
# as it does from
|
|
342
|
+
# as it does from a native binary read.
|
|
326
343
|
result = await self.run(
|
|
327
344
|
[
|
|
328
345
|
"sh",
|
|
@@ -333,21 +350,14 @@ class Runtime(ABC):
|
|
|
333
350
|
'base64 < "$t"; rc=$?; rm -f "$t"; exit $rc'
|
|
334
351
|
),
|
|
335
352
|
"sh",
|
|
336
|
-
str(max_bytes
|
|
353
|
+
str(max_bytes),
|
|
337
354
|
path,
|
|
338
355
|
],
|
|
339
356
|
{},
|
|
340
357
|
)
|
|
341
358
|
if result.exit_code:
|
|
342
359
|
raise SandboxError(f"read {path!r}: {result.stderr.strip()[-500:]}")
|
|
343
|
-
|
|
344
|
-
if len(data) > max_bytes:
|
|
345
|
-
raise SandboxError(f"read {path!r}: over the {max_bytes} byte limit")
|
|
346
|
-
return data
|
|
347
|
-
|
|
348
|
-
@abstractmethod
|
|
349
|
-
async def _read(self, path: str) -> bytes:
|
|
350
|
-
"""Read the whole file at `path`; `read` adds the optional transfer cap."""
|
|
360
|
+
return base64.b64decode(result.stdout)
|
|
351
361
|
|
|
352
362
|
@abstractmethod
|
|
353
363
|
async def write(self, path: str, data: bytes) -> None:
|
|
@@ -506,19 +506,28 @@ class DockerRuntime(Runtime):
|
|
|
506
506
|
if run.exit_code != 0:
|
|
507
507
|
raise SandboxError(f"docker exec -d failed: {run.stderr.strip()}")
|
|
508
508
|
|
|
509
|
-
async def _read(self, path: str) -> bytes:
|
|
509
|
+
async def _read(self, path: str, max_bytes: int | None = None) -> bytes:
|
|
510
|
+
argv = ["cat"] if max_bytes is None else ["head", "-c", str(max_bytes)]
|
|
510
511
|
proc = await asyncio.create_subprocess_exec(
|
|
511
512
|
"docker",
|
|
512
513
|
"exec",
|
|
513
514
|
"--workdir",
|
|
514
515
|
self.config.workdir,
|
|
515
516
|
self._container,
|
|
516
|
-
|
|
517
|
+
*argv,
|
|
518
|
+
"--",
|
|
517
519
|
path,
|
|
518
520
|
stdout=asyncio.subprocess.PIPE,
|
|
519
521
|
stderr=asyncio.subprocess.PIPE,
|
|
520
522
|
)
|
|
521
|
-
|
|
523
|
+
try:
|
|
524
|
+
stdout, stderr = await proc.communicate()
|
|
525
|
+
except BaseException:
|
|
526
|
+
if proc.returncode is None:
|
|
527
|
+
with contextlib.suppress(ProcessLookupError):
|
|
528
|
+
proc.kill()
|
|
529
|
+
await run_shielded(proc.communicate())
|
|
530
|
+
raise
|
|
522
531
|
if proc.returncode != 0:
|
|
523
532
|
raise SandboxError(
|
|
524
533
|
f"read {path!r}: {stderr.decode(errors='replace').strip()}"
|
verifiers/v1/runtimes/modal.py
CHANGED
|
@@ -279,7 +279,9 @@ class ModalRuntime(Runtime):
|
|
|
279
279
|
return path
|
|
280
280
|
return f"{self.config.workdir.rstrip('/')}/{path}"
|
|
281
281
|
|
|
282
|
-
async def _read(self, path: str) -> bytes:
|
|
282
|
+
async def _read(self, path: str, max_bytes: int | None = None) -> bytes:
|
|
283
|
+
if max_bytes is not None:
|
|
284
|
+
return await super()._read(path, max_bytes)
|
|
283
285
|
try:
|
|
284
286
|
return await self._sandbox.filesystem.read_bytes.aio(self._abs(path))
|
|
285
287
|
except Exception as e:
|
verifiers/v1/runtimes/prime.py
CHANGED
|
@@ -365,7 +365,9 @@ class PrimeRuntime(Runtime):
|
|
|
365
365
|
except Exception as e:
|
|
366
366
|
raise SandboxError(f"prime background launch failed: {e}") from e
|
|
367
367
|
|
|
368
|
-
async def _read(self, path: str) -> bytes:
|
|
368
|
+
async def _read(self, path: str, max_bytes: int | None = None) -> bytes:
|
|
369
|
+
if max_bytes is not None:
|
|
370
|
+
return await super()._read(path, max_bytes)
|
|
369
371
|
# Avoid background-job log limits and base64 overhead by downloading binary data directly.
|
|
370
372
|
# The temporary file is removed on every exit, and its byte read stays off the event loop.
|
|
371
373
|
target = (
|
|
@@ -5,12 +5,14 @@ import contextlib
|
|
|
5
5
|
import os
|
|
6
6
|
import shutil
|
|
7
7
|
import signal
|
|
8
|
+
import stat
|
|
8
9
|
from collections.abc import AsyncIterator
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import ClassVar, Literal
|
|
11
12
|
|
|
12
13
|
from pydantic_config import BaseConfig
|
|
13
14
|
|
|
15
|
+
from verifiers.v1.errors import SandboxError
|
|
14
16
|
from verifiers.v1.runtimes.base import (
|
|
15
17
|
BaseRuntimeInfo,
|
|
16
18
|
ProgramResult,
|
|
@@ -161,8 +163,28 @@ class SubprocessRuntime(Runtime):
|
|
|
161
163
|
proc
|
|
162
164
|
) # killed in stop() — a host process won't die on its own
|
|
163
165
|
|
|
164
|
-
async def _read(self, path: str) -> bytes:
|
|
165
|
-
|
|
166
|
+
async def _read(self, path: str, max_bytes: int | None = None) -> bytes:
|
|
167
|
+
if max_bytes is None:
|
|
168
|
+
return await asyncio.to_thread((self.workdir / path).read_bytes)
|
|
169
|
+
|
|
170
|
+
# Leave special files to the cancellable shell path without opening a
|
|
171
|
+
# FIFO and waking its writer. A nonblocking open and descriptor check
|
|
172
|
+
# also cover a regular path being replaced by a FIFO after the stat.
|
|
173
|
+
def read() -> bytes | None:
|
|
174
|
+
target = self.workdir / path
|
|
175
|
+
if not stat.S_ISREG(target.stat().st_mode):
|
|
176
|
+
return None
|
|
177
|
+
fd = os.open(target, os.O_RDONLY | os.O_NONBLOCK)
|
|
178
|
+
with os.fdopen(fd, "rb") as file:
|
|
179
|
+
if not stat.S_ISREG(os.fstat(file.fileno()).st_mode):
|
|
180
|
+
return None
|
|
181
|
+
return file.read(max_bytes)
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
data = await asyncio.to_thread(read)
|
|
185
|
+
except OSError as exc:
|
|
186
|
+
raise SandboxError(f"read {path!r}: {exc}") from exc
|
|
187
|
+
return data if data is not None else await super()._read(path, max_bytes)
|
|
166
188
|
|
|
167
189
|
async def write(self, path: str, data: bytes) -> None:
|
|
168
190
|
target = self.workdir / path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev60
|
|
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
|
|
@@ -62,8 +62,8 @@ verifiers/v1/configs/cli/validate.py,sha256=NXQ9KvhGLODLrg1fs3Jn-SOq1hhPxauVWiPS
|
|
|
62
62
|
verifiers/v1/dialects/__init__.py,sha256=MNOYM2NdTlSxGK4VtoEjMtD5zya2MpjPDX5jMvZUWEo,736
|
|
63
63
|
verifiers/v1/dialects/anthropic.py,sha256=abwcKRsKkgfgLSuntxBMdL03enG7roRdGoHTYfswafM,26887
|
|
64
64
|
verifiers/v1/dialects/base.py,sha256=pcFqWXSl50VtMuzcY5cyhsc4WpKCM5wT-tskTFZV7CM,12203
|
|
65
|
-
verifiers/v1/dialects/chat.py,sha256=
|
|
66
|
-
verifiers/v1/dialects/responses.py,sha256=
|
|
65
|
+
verifiers/v1/dialects/chat.py,sha256=qhjpduOfNnstfkLTtC0MTS_IfuiOkBwuSwpIg_y1Hjw,23881
|
|
66
|
+
verifiers/v1/dialects/responses.py,sha256=FRQXRubijMG7VuqW_I7ex2DnEzOjuZxwxATy-loEkm0,29254
|
|
67
67
|
verifiers/v1/envs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
68
|
verifiers/v1/envs/agentic_judge/__init__.py,sha256=LfEcRHLG_siKzhzWmODDXWSLpLgfum3UFdQDK9XG0gk,325
|
|
69
69
|
verifiers/v1/envs/agentic_judge/env.py,sha256=GovnHqgRm8nQLAM7wMx57-A_wJBRYopsfiy2Bgf32nA,15339
|
|
@@ -141,12 +141,12 @@ verifiers/v1/mcp/launch.py,sha256=K6M8ZaoOO7wt65s93wK_9Wl7bvjeQ4C8BLkrGE149DI,23
|
|
|
141
141
|
verifiers/v1/mcp/server.py,sha256=Jqi8OMT8DnoZegXqM3UNNRzhVnbdrPEwx0DjOJo_K2A,13256
|
|
142
142
|
verifiers/v1/mcp/toolset.py,sha256=G2wzNdEMGLXoQUcrwF0TartJkqokNPI3o7YUOAaaa6U,1007
|
|
143
143
|
verifiers/v1/runtimes/__init__.py,sha256=ppc1R_sx-aMcuJSx4t99rTSjloUXI0M6EUj676-1PeY,2862
|
|
144
|
-
verifiers/v1/runtimes/base.py,sha256=
|
|
144
|
+
verifiers/v1/runtimes/base.py,sha256=kPxbK-VPr4j3Ah0SYlHAMefUJpVF6jTCJkZm7TRVeAs,17376
|
|
145
145
|
verifiers/v1/runtimes/limiters.py,sha256=C6cWDD4pwyFwUY4QFke3oiMXwydSNIfSbJSIglUC2kE,3062
|
|
146
|
-
verifiers/v1/runtimes/modal.py,sha256=
|
|
147
|
-
verifiers/v1/runtimes/prime.py,sha256=
|
|
148
|
-
verifiers/v1/runtimes/subprocess.py,sha256=
|
|
149
|
-
verifiers/v1/runtimes/docker/__init__.py,sha256=
|
|
146
|
+
verifiers/v1/runtimes/modal.py,sha256=wUNik2Wul1YISausdABIMAoSaTA0MNDwKUayKxVLwAA,13342
|
|
147
|
+
verifiers/v1/runtimes/prime.py,sha256=k_ndI1KmAWixO-jp_Rbl2JOr9iBsUkDG4BuTQGRFT1M,18901
|
|
148
|
+
verifiers/v1/runtimes/subprocess.py,sha256=QmpQ235_xrX6gowrr8557VgbydOXpLbfFq0KKGfJThk,8774
|
|
149
|
+
verifiers/v1/runtimes/docker/__init__.py,sha256=JN0mI10a_BKQpRRJKX_NqStAoODAEk2dAJF9mrz69ug,20972
|
|
150
150
|
verifiers/v1/runtimes/docker/egress.py,sha256=iFH_1XotlEM-OCaW7GNu3TWVEq1sqesKYweyVBX8g90,14360
|
|
151
151
|
verifiers/v1/serve/__init__.py,sha256=doImCSxSYZEjVDXfRafLHkhHXcXQxzA6qUGMBQ8bSko,477
|
|
152
152
|
verifiers/v1/serve/client.py,sha256=biy46qOOFTjMXSIsY8W1vMEfctn7usCeNuBQsJqc2mc,7789
|
|
@@ -189,8 +189,8 @@ verifiers/v1/utils/prime.py,sha256=UTYRjp9cbjNb6CVmBHda-1wWZAIIfxNOmTyNuT7_wL4,9
|
|
|
189
189
|
verifiers/v1/utils/retries.py,sha256=Y2ZgrAjn-qNkRKZP_RVNL_7EK0iaRcZeCa404lpGYi4,5417
|
|
190
190
|
verifiers/v1/utils/score.py,sha256=493yJVMw8teCu9JxapxMFPFzI0hNUqdo0Y2nGW4kckk,6200
|
|
191
191
|
verifiers/v1/utils/version.py,sha256=-obEo_-l9-D8FLef4hYxncOe-uJpxrM1g2Hig_37Sgs,1607
|
|
192
|
-
verifiers-0.3.2.
|
|
193
|
-
verifiers-0.3.2.
|
|
194
|
-
verifiers-0.3.2.
|
|
195
|
-
verifiers-0.3.2.
|
|
196
|
-
verifiers-0.3.2.
|
|
192
|
+
verifiers-0.3.2.dev60.dist-info/METADATA,sha256=ZBW4-2QIcEGmUK99koWSzbbJEF9h_lGj9qpdEkNB4Jc,4204
|
|
193
|
+
verifiers-0.3.2.dev60.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
194
|
+
verifiers-0.3.2.dev60.dist-info/entry_points.txt,sha256=uqQje0TMsr7k6nXlWxlPs13Si0evb3pVCEDF6c-YL80,241
|
|
195
|
+
verifiers-0.3.2.dev60.dist-info/licenses/LICENSE,sha256=v0RrUsdV3IDoZhrRce297IXS3xMHNJ-_LdLpFAUWb9k,1072
|
|
196
|
+
verifiers-0.3.2.dev60.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|