verifiers 0.3.2.dev102__py3-none-any.whl → 0.3.2.dev105__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.
@@ -297,10 +297,10 @@ def _push_footer(push: "PushState | None") -> Group | None:
297
297
  line.append(f" not closed out: {push.error}", style="red")
298
298
  elif push.error:
299
299
  line = Text(f"Trace push failed ({push.error})", style="red", overflow="fold")
300
- elif push.incomplete and push.url:
301
- # Closed out, but the uploader lost records: what landed is there, say what didn't.
302
- line = Text(f"Traces pushed ({push.url})", style="white", overflow="fold")
303
- line.append(f" incomplete: {push.incomplete}", style="red")
300
+ elif (incomplete := push.incomplete) and push.url:
301
+ label = "Traces pushed" if push.finished else "Pushing traces"
302
+ line = Text(f"{label} ({push.url})", style="white", overflow="fold")
303
+ line.append(f" incomplete: {incomplete}", style="red")
304
304
  elif not push.finished:
305
305
  line = Text(f"Pushing traces ({push.url})", style="dim", overflow="fold")
306
306
  else:
@@ -4,12 +4,12 @@ The worker streams a served episode as it grows. Each trace announces its own ch
4
4
  (`Trace.notify`, fired by the rollout at every phase change and by the interception proxy
5
5
  after every recorded turn); the `DeltaStreamer` then diffs the run's live traces against
6
6
  what it has already sent and ships only the new part — the trace header once, then
7
- appended nodes / calls / errors, semantic links landing on earlier nodes, the scalar
7
+ appended nodes / calls / errors, semantic links and routing-row repairs on earlier nodes, the scalar
8
8
  fields whose value changed (timing spans, stop condition, rewards, ...), and the
9
9
  `pending` preview — the messages of the request in flight that no node holds yet, so a
10
10
  watcher sees a tool result before the model has answered it. The `Trace` is
11
- append-only at turn granularity (a turn's nodes are committed complete, with their
12
- tokens), so apart from the preview, which a committed turn repeats, every byte of the
11
+ append-only at turn granularity except for links and the last routing row of a node,
12
+ which the next prefill can repair. Apart from these and the preview, every byte of the
13
13
  episode crosses the wire once and the stream costs about what a single reply would; the
14
14
  reply that ends the run carries only the episode head and per-trace counts the client
15
15
  checks its assembly against. A cursor advances only once its delta is on the wire, so a
@@ -29,8 +29,10 @@ from collections.abc import Awaitable, Callable
29
29
  from typing import TYPE_CHECKING, Any, Self
30
30
 
31
31
  import msgpack
32
+ import numpy as np
32
33
  from pydantic import BaseModel
33
34
 
35
+ from verifiers.v1.graph import _decode_ndarray, _encode_ndarray
34
36
  from verifiers.v1.serve.encoding import msgpack_encoder
35
37
 
36
38
  if TYPE_CHECKING:
@@ -73,7 +75,7 @@ def pack(payload: Any) -> bytes:
73
75
 
74
76
 
75
77
  def unpack(data: bytes) -> Any:
76
- # `links` is keyed by node index (int).
78
+ # Node updates are keyed by node index (int).
77
79
  return msgpack.unpackb(data, raw=False, strict_map_key=False)
78
80
 
79
81
 
@@ -90,6 +92,8 @@ class TraceCursor:
90
92
  self.sent = dict.fromkeys(LIST_FIELDS, 0)
91
93
  self.links: list[int] = []
92
94
  """Per sent node, how many of its semantic links went out with or after it."""
95
+ self.final_rows: dict[int, bytes] = {}
96
+ """Per node that carries routing, its final row as packed when last sent."""
93
97
  self.scalars: dict[str, bytes] = {}
94
98
  self.pending: bytes = pack([])
95
99
 
@@ -157,6 +161,31 @@ class DeltaStreamer:
157
161
  else:
158
162
  self.cursors[trace_id] = cursor
159
163
 
164
+ def _maybe_add_routing_repairs(
165
+ self,
166
+ delta: dict[str, Any],
167
+ trace: Trace,
168
+ cursor: TraceCursor,
169
+ sent_nodes: int,
170
+ ) -> None:
171
+ """Add final rows repaired since they were sent, keyed by node index.
172
+
173
+ Record every node's current row on the cursor. `sent_nodes` is the pre-flush
174
+ count, so a node first sent in this delta is never reported as a repair.
175
+ """
176
+ repairs: dict[int, dict] = {}
177
+ for index, node in enumerate(trace.nodes):
178
+ if node.routed_experts is None:
179
+ continue
180
+ row = _encode_ndarray(node.routed_experts[-1:])
181
+ packed = pack(row)
182
+ if cursor.final_rows.get(index) != packed:
183
+ cursor.final_rows[index] = packed
184
+ if index < sent_nodes:
185
+ repairs[index] = row
186
+ if repairs:
187
+ delta["routing_repairs"] = repairs
188
+
160
189
  def diff(self) -> list[tuple[str, dict, TraceCursor | None]]:
161
190
  """Each trace's delta against its sent cursor, with the cursor as it stands once
162
191
  that delta is sent (None for a discard). Nothing here is committed: `flush`
@@ -183,6 +212,7 @@ class DeltaStreamer:
183
212
  cursor.links[index] = len(node_links)
184
213
  if links:
185
214
  delta["links"] = links
215
+ self._maybe_add_routing_repairs(delta, trace, cursor, cursor.sent["nodes"])
186
216
  for field in LIST_FIELDS:
187
217
  items = getattr(trace, field)
188
218
  sent = cursor.sent[field]
@@ -220,6 +250,20 @@ class EpisodeAssembly:
220
250
  def __init__(self) -> None:
221
251
  self.traces: dict[str, dict] = {}
222
252
 
253
+ def _maybe_apply_routing_repairs(self, delta: dict[str, Any], trace: dict) -> None:
254
+ """Replace repaired final rows in nodes the client already holds.
255
+
256
+ Rebuild each array: a repair can widen its dtype, and decoded rows alias
257
+ the original delta's bytes, which must remain unchanged for consumers.
258
+ """
259
+ for index, row in (delta.get("routing_repairs") or {}).items():
260
+ node = trace["nodes"][int(index)]
261
+ node["routed_experts"] = _encode_ndarray(
262
+ np.concatenate(
263
+ [_decode_ndarray(node["routed_experts"])[:-1], _decode_ndarray(row)]
264
+ )
265
+ )
266
+
223
267
  def apply(self, delta: dict) -> None:
224
268
  trace_id = delta["trace"]
225
269
  if delta.get("discard"):
@@ -234,6 +278,7 @@ class EpisodeAssembly:
234
278
  }
235
279
  for index, links in (delta.get("links") or {}).items():
236
280
  trace["nodes"][int(index)]["semantic_parents"].extend(links)
281
+ self._maybe_apply_routing_repairs(delta, trace)
237
282
  # a later `links` delta grows a node's semantic_parents in place, so the node
238
283
  # is copied: the delta stays as it was when the caller received it
239
284
  if "nodes" in delta:
@@ -24,9 +24,11 @@ class PushState:
24
24
 
25
25
  run: pr.Run | None = None
26
26
  error: str | None = None
27
- incomplete: str | None = None
28
- """Set when the run closed out but the uploader lost records on the way: the run
29
- exists and holds what did land, so the footer says so rather than "failed"."""
27
+
28
+ @property
29
+ def incomplete(self) -> str | None:
30
+ """Current upload errors and record losses, including while the run is active."""
31
+ return _losses(self.run) if self.run is not None else None
30
32
 
31
33
  @property
32
34
  def url(self) -> str | None:
@@ -157,9 +159,8 @@ def _close(
157
159
  if state.error is None:
158
160
  state.error = f"{type(e).__name__}: {e}"
159
161
  else:
160
- state.incomplete = _losses(run)
161
- if state.incomplete:
162
- logger.warning("--push: %s, but %s", status.value, state.incomplete)
162
+ if incomplete := state.incomplete:
163
+ logger.warning("--push: %s, but %s", status.value, incomplete)
163
164
  if run.url:
164
165
  # The run's own status: `finish()` is a no-op once another caller closed it.
165
166
  logger.info("--push: %s -> %s", run.status.value, run.url)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev102
3
+ Version: 0.3.2.dev105
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
@@ -35,7 +35,7 @@ Requires-Dist: msgpack>=1.1.2
35
35
  Requires-Dist: numpy>=2.1.0
36
36
  Requires-Dist: openai<3.0.0,>=2.54.0
37
37
  Requires-Dist: prime-pydantic-config[toml]>=0.4.3
38
- Requires-Dist: prime-runs>=0.1.2
38
+ Requires-Dist: prime-runs>=0.1.3
39
39
  Requires-Dist: prime-sandboxes>=0.2.39
40
40
  Requires-Dist: prime-tunnel>=0.1.8
41
41
  Requires-Dist: pydantic>=2.12.3
@@ -29,7 +29,7 @@ verifiers/v1/cli/resume.py,sha256=hqV5AxxqeIInJeEZQerQznuijhMNijFEFcHZIltfLdE,47
29
29
  verifiers/v1/cli/validate.py,sha256=K7mCz-ZI7sq69MQPg6QvreHOuEj-bgMln69a28kDTvA,17179
30
30
  verifiers/v1/cli/dashboard/__init__.py,sha256=v-baMxQuWxOCsbU7-p_jj2Q9BUnTN-TWi1q2hK6rU2s,198
31
31
  verifiers/v1/cli/dashboard/base.py,sha256=kUP93zJSIVLptSbnWX6MOy8kGg63fpeAzPqakCpPyDc,3547
32
- verifiers/v1/cli/dashboard/eval.py,sha256=D4iX69Ou8hHcv9_Bn2sPKF-9Zg89q00XLvNaLCajlNg,38369
32
+ verifiers/v1/cli/dashboard/eval.py,sha256=HEXPEegNXdgU9zAIuHzsWsoSIHyiOcDZh4tCGFNxKAk,38353
33
33
  verifiers/v1/cli/dashboard/replay.py,sha256=_X5up9MJsRbd_sWe4LgNTPNT8k1ip4xNpo50hxI3Ljk,2697
34
34
  verifiers/v1/cli/dashboard/validate.py,sha256=xrpK3Y90JsoDCQYLLvvsnJ4CPRMvSSJIghfHK62E6FQ,3687
35
35
  verifiers/v1/cli/eval/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -149,7 +149,7 @@ verifiers/v1/runtimes/docker/__init__.py,sha256=2YJtjOVSA4OgxXgeIlFW3Ps01KEfLNT_
149
149
  verifiers/v1/runtimes/docker/egress.py,sha256=iFH_1XotlEM-OCaW7GNu3TWVEq1sqesKYweyVBX8g90,14360
150
150
  verifiers/v1/serve/__init__.py,sha256=wOKuwfugzmDT4yIniwzCXlf4G6tv6Cg8Kc--WMa38Bs,553
151
151
  verifiers/v1/serve/client.py,sha256=E2y2x4qqYveWRWC9VZYQEu19aMEryPWTdXnYzbq5uTA,9829
152
- verifiers/v1/serve/delta.py,sha256=UnDhGqXdJPeRgRJ26j8xkHqU_HtBfk8TdzAvNezaWKA,11525
152
+ verifiers/v1/serve/delta.py,sha256=qhOUOYEt1wVzeaJ9IhjgU6ks5BkYOEtcFfGnuYxFEEs,13501
153
153
  verifiers/v1/serve/encoding.py,sha256=hBZFucAZK9riXOV3DaHcskq9zHTT8gVGkoFVOPfnr30,2499
154
154
  verifiers/v1/serve/pool.py,sha256=bT-FOlIuOiBtOasuPB-p9887tkpEqvQUJBgn1Q45ph0,15912
155
155
  verifiers/v1/serve/server.py,sha256=i6XrY_PMAapkrP54tYX8-K6iGmOmrR7BbQ-3Qhn3w4s,9885
@@ -185,13 +185,13 @@ verifiers/v1/utils/loaders.py,sha256=2TrgZK3MzKub1GnfaTVIQhlwF6q4qATXZCjicH6nT9c
185
185
  verifiers/v1/utils/logging.py,sha256=-zgaM-HZsgxumZ4wYNlRMZepp6JanCSjeL2wSVulwJM,2296
186
186
  verifiers/v1/utils/memory.py,sha256=ZkIvGk6uITAH5sKon65LifKPbvZr8mJ__PVc23FZpOQ,1835
187
187
  verifiers/v1/utils/paths.py,sha256=it_4JWf_8bPZe4TRcyvL7_KJ4fsbEsxhhIY_xA8Ikus,308
188
- verifiers/v1/utils/platform.py,sha256=F4qMxWJY5MwtJ7ozASwBrpcU8u3lXvHIc5rg-rviDOQ,7181
188
+ verifiers/v1/utils/platform.py,sha256=YwTHVA1Onn74lG6S3sdHus9OlP-rAbwkk9Po7h-BjpE,7159
189
189
  verifiers/v1/utils/prime.py,sha256=UTYRjp9cbjNb6CVmBHda-1wWZAIIfxNOmTyNuT7_wL4,970
190
190
  verifiers/v1/utils/retries.py,sha256=Y2ZgrAjn-qNkRKZP_RVNL_7EK0iaRcZeCa404lpGYi4,5417
191
191
  verifiers/v1/utils/score.py,sha256=493yJVMw8teCu9JxapxMFPFzI0hNUqdo0Y2nGW4kckk,6200
192
192
  verifiers/v1/utils/version.py,sha256=-obEo_-l9-D8FLef4hYxncOe-uJpxrM1g2Hig_37Sgs,1607
193
- verifiers-0.3.2.dev102.dist-info/METADATA,sha256=bgoqfsVCE7mh66RzwnfvlX0Jcxbi05QJO_JMjrSPUpI,4238
194
- verifiers-0.3.2.dev102.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
195
- verifiers-0.3.2.dev102.dist-info/entry_points.txt,sha256=iugElcdWPKbQM7uFF0lZ8iUpHsNr17-BwEAAjJWxV3U,259
196
- verifiers-0.3.2.dev102.dist-info/licenses/LICENSE,sha256=v0RrUsdV3IDoZhrRce297IXS3xMHNJ-_LdLpFAUWb9k,1072
197
- verifiers-0.3.2.dev102.dist-info/RECORD,,
193
+ verifiers-0.3.2.dev105.dist-info/METADATA,sha256=VP57HoS62DnWGpDZUu3u0quWYfjoEmFTCFrwrGgPjfE,4238
194
+ verifiers-0.3.2.dev105.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
195
+ verifiers-0.3.2.dev105.dist-info/entry_points.txt,sha256=iugElcdWPKbQM7uFF0lZ8iUpHsNr17-BwEAAjJWxV3U,259
196
+ verifiers-0.3.2.dev105.dist-info/licenses/LICENSE,sha256=v0RrUsdV3IDoZhrRce297IXS3xMHNJ-_LdLpFAUWb9k,1072
197
+ verifiers-0.3.2.dev105.dist-info/RECORD,,