tuieval 0.2.0.dev55__py3-none-any.whl → 0.2.0.dev56__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.
tuieval/_version.py CHANGED
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0.dev55'
22
- __version_tuple__ = version_tuple = (0, 2, 0, 'dev55')
21
+ __version__ = version = '0.2.0.dev56'
22
+ __version_tuple__ = version_tuple = (0, 2, 0, 'dev56')
23
23
 
24
24
  __commit_id__ = commit_id = None
tuieval/engine.py CHANGED
@@ -987,16 +987,16 @@ class Engine:
987
987
  del per_pack[name]
988
988
  return {l: p for l, p in out.items() if p}
989
989
 
990
- def estimate_seconds(self, jobs):
991
- """(seconds, notes): expected run time for the waiting jobs, estimated per pack.
990
+ def seconds_per_answer(self, jobs, waiting_only=True):
991
+ """({job key: expected seconds per answer}, borrowed, guessed, thin) for the waiting jobs.
992
992
  A pack the model has answered uses its own median time there. Otherwise the median of
993
993
  other models' times on that pack, scaled by how much slower or faster this model is than
994
- them on packs both have answered. notes lists what made the estimate rough ([] = solid)."""
994
+ them on packs both have answered. The sets say which estimates are rough (see estimate_seconds)."""
995
995
  times = self.answer_times()
996
996
  med = {l: {p: statistics.median(ts) for p, ts in pp.items()} for l, pp in times.items()}
997
- total, borrowed, guessed, thin = 0.0, set(), set(), set()
997
+ spr_of, borrowed, guessed, thin = {}, set(), set(), set()
998
998
  for j in jobs:
999
- if j.status != "waiting":
999
+ if j.status in ("done", "skipped", "failed") or (waiting_only and j.status != "waiting"):
1000
1000
  continue
1001
1001
  own = med.get(j.label, {})
1002
1002
  ref = {p: statistics.median(v[p] for l, v in med.items() if p in v and l != j.label)
@@ -1013,8 +1013,18 @@ class Engine:
1013
1013
  else:
1014
1014
  spr = statistics.median(own.values()) if own else DEFAULT_SECONDS_PER_REQUEST
1015
1015
  guessed.add((j.key, bool(own)))
1016
- done = len(self._done_keys(j)) if j.merge else 0
1017
- total += max(0, j.total - done) * spr
1016
+ spr_of[j.key] = spr
1017
+ return spr_of, borrowed, guessed, thin
1018
+
1019
+ def estimate_seconds(self, jobs):
1020
+ """(seconds, notes): expected run time for the waiting jobs, estimated per pack
1021
+ (seconds_per_answer). notes lists what made the estimate rough ([] = solid)."""
1022
+ spr_of, borrowed, guessed, thin = self.seconds_per_answer(jobs)
1023
+ total = 0.0
1024
+ for j in jobs:
1025
+ if j.key in spr_of:
1026
+ done = len(self._done_keys(j)) if j.merge else 0
1027
+ total += max(0, j.total - done) * spr_of[j.key]
1018
1028
  notes = []
1019
1029
  if borrowed:
1020
1030
  factors = sorted({f for _, f, _ in borrowed if f is not None})
tuieval/tui.py CHANGED
@@ -1855,6 +1855,8 @@ class RunScreen(Screen):
1855
1855
  self.current = ""
1856
1856
  self.req_first = None
1857
1857
  self.stats = []
1858
+ self.spr, self.rough = None, set() # job key -> expected seconds per answer (ETA), rough ones
1859
+ self.live = {} # job key -> seconds per answer in this session
1858
1860
  self.mem = {}
1859
1861
  self.outcome = "" # "Finished" or "Cancelled" once the queue is done
1860
1862
  self.ended = None
@@ -2037,6 +2039,8 @@ class RunScreen(Screen):
2037
2039
  + (f" [red]copy of repeat {r['identical_to_repeat'] + 1}[/red]"
2038
2040
  if r.get("identical_to_repeat") is not None else ""))
2039
2041
  self.stats.append(r)
2042
+ if r.get("total_s"):
2043
+ self.live.setdefault(job.key, []).append(r["total_s"])
2040
2044
  self.recent_entries[row_key] = {"model": job.label, "pack": job.pack.name, "record": r,
2041
2045
  "pack_fp": job.pack.fingerprint}
2042
2046
  if recent.row_count > 500:
@@ -2187,6 +2191,34 @@ class RunScreen(Screen):
2187
2191
  ("note", short_note(j.note))):
2188
2192
  q.update_cell(j.key, col, value, update_width=True)
2189
2193
 
2194
+ LIVE_ANSWERS = 5 # a pack's own times this session take over from its history after this many
2195
+
2196
+ def eta_seconds(self):
2197
+ """(seconds, rough): time left, pack by pack: answers left × seconds per answer. A pack's own
2198
+ average this session once it has LIVE_ANSWERS of them, before that its history (Engine.
2199
+ seconds_per_answer: this model's past times there, or other models' scaled). Divided by the
2200
+ models running side by side. rough: some packs have no history of their own yet."""
2201
+ new = [j for j in self.jobs if self.spr is None or (j.key not in self.spr and j.status not in
2202
+ ("done", "skipped", "failed"))]
2203
+ if new: # at the start, and for evals added to the run
2204
+ spr, borrowed, guessed, _ = self.app.engine.seconds_per_answer(new, waiting_only=False)
2205
+ self.spr = {**(self.spr or {}), **spr}
2206
+ self.rough |= {k for k, *_ in borrowed} | {k for k, _ in guessed}
2207
+ left, rough, models = 0.0, False, set()
2208
+ for j in self.jobs:
2209
+ if j.status in ("done", "skipped", "failed") or j.done >= j.total:
2210
+ continue
2211
+ live = self.live.get(j.key, [])
2212
+ if len(live) >= self.LIVE_ANSWERS:
2213
+ spr = sum(live) / len(live)
2214
+ else:
2215
+ spr = self.spr.get(j.key, engine.DEFAULT_SECONDS_PER_REQUEST)
2216
+ rough |= j.key in self.rough
2217
+ left += (j.total - j.done) * spr
2218
+ models.add(j.label)
2219
+ lanes = max(1, min(self.parallel or self.app.engine.parallel_models(), len(models)))
2220
+ return left / lanes, rough
2221
+
2190
2222
  def update_overall(self):
2191
2223
  done = sum(j.done for j in self.jobs)
2192
2224
  passed = sum(j.passed for j in self.jobs)
@@ -2194,9 +2226,9 @@ class RunScreen(Screen):
2194
2226
  self.query_one("#bar", ProgressBar).update(progress=done)
2195
2227
  elapsed = time.time() - self.started
2196
2228
  eta = ""
2197
- done_now = sum(j.done - j.resumed for j in self.jobs if j.started) # answers from earlier sittings
2198
- if self.running and done_now > 0 and self.total > done: # took no time in this one
2199
- eta = f" · ETA {fmt_secs(elapsed / done_now * (self.total - done))}"
2229
+ if self.running and self.total > done:
2230
+ left, rough = self.eta_seconds()
2231
+ eta = f" · ETA {'~' if rough else ''}{fmt_secs(left)}"
2200
2232
  pct = f"{100 * passed / (passed + failed):.0f}%" if passed + failed else "-"
2201
2233
  recent = self.stats[-50:]
2202
2234
  tps = [r["gen_tps"] for r in recent if r.get("gen_tps")]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tuieval
3
- Version: 0.2.0.dev55
3
+ Version: 0.2.0.dev56
4
4
  Summary: Evaluate local and frontier LLMs on your own questions: accuracy, speed, tokens and PASS/FAIL verdicts, in the terminal.
5
5
  Project-URL: Homepage, https://github.com/ashe-wb/tuieval
6
6
  Project-URL: Issues, https://github.com/ashe-wb/tuieval/issues
@@ -1,12 +1,12 @@
1
1
  tuieval/__init__.py,sha256=myVXVX7htbwezW6k3x_FuKgn1RSZ2WcTaDEMByGn6Wg,312
2
2
  tuieval/__main__.py,sha256=E6Gls0DNz8GQK2K-kOUIx8cYhgANW_CH54VKrfCfs14,52
3
- tuieval/_version.py,sha256=1ZPMt5NERZZN86PFadmP7kAdrSCtNEk8dYfg9p2vGXg,535
3
+ tuieval/_version.py,sha256=w3V6noQtCnYcwkOc0Hi3EmCrxSS1deuXpcG9aisclJI,535
4
4
  tuieval/builtin.toml,sha256=Kxw22RZCJhURUyu5Wz8tj5Y1nM85A8hFVRbA4ocoPUg,4293
5
5
  tuieval/cli.py,sha256=gzGBzhqvR0WKJQQNHB8CudpgViIeIyawrNWa54whmoI,4502
6
6
  tuieval/client.py,sha256=kpsyLEZKfxCsvIGBHBbBy83TpI97CvnGCDq-4AbJS4Y,9986
7
7
  tuieval/compare.py,sha256=SHN_o_nlppFcHMBqBZRITIkeQDPaR_JxhUZItQLMBwo,26270
8
8
  tuieval/doctor.py,sha256=y1C_ggjd8oikXTrovgTBf26wjThP8EoVkfTVeO_n5dQ,6070
9
- tuieval/engine.py,sha256=w3KsgxzFAMcRyVzFGQXhTgN3d9qYRtAZZxNLXZOgnrQ,114222
9
+ tuieval/engine.py,sha256=0PuHFus1k02qAY8nlsI6z5iQo7IT82bMwmHDZT6fGtU,114784
10
10
  tuieval/export.py,sha256=dbHQgL_ubWtIPM1sLzAew_gETnrDJyd0zgqVA5vkpXM,9657
11
11
  tuieval/machines.py,sha256=tdRrn3WNOmCHwfcxcWz1NuAuOJdI7WnJFR1y6xgF89c,13512
12
12
  tuieval/onboard.py,sha256=IYETVDWCCo9vF0Dtj4_rr9VanYeCky8PwP3-2g5A_l0,6215
@@ -17,7 +17,7 @@ tuieval/remove.py,sha256=Vwh43nm9lVb9U9aN-h6CMYbkTwdR3UWfZObwweF72n0,5157
17
17
  tuieval/run_evals.py,sha256=5bQEqU533XYiLze9dYcl72c5GSIpohMj1eqJrePRwnc,46450
18
18
  tuieval/scaffold.py,sha256=YBOqniJpf_GtKKAFF3_OHxxMGbmTWdFjcClGcOnrrKE,12130
19
19
  tuieval/selftest.py,sha256=nExkrOidgymlmvkxImEBfrQG5iTUN5WuRMIKtqusCCs,9835
20
- tuieval/tui.py,sha256=21Re8fM5rf3zbHIKvK9laMV-mL2HjcGfMReoRg0DRLw,164268
20
+ tuieval/tui.py,sha256=xAQnR270m7x-rfTdK7LBPMM9MEQC37zndD1TOTq8EUU,166103
21
21
  tuieval/tune.py,sha256=jXwYuSjfdqbLCE3WonP2xaUHwk_FnhI67twB1BaHggI,38992
22
22
  tuieval/verdict.py,sha256=Muo1a05mCv781MlEJsXwDsGaKbRi0JS4Lv8HdvK_Aco,19054
23
23
  tuieval/watch_proxy.py,sha256=bnDO1i6n6yUs1hODoUWcMppJMGPavoQqs6aNYrIxpT8,11416
@@ -46,8 +46,8 @@ tuieval/templates/packs/tool_call/pack.toml,sha256=n4bx0lGJHSmW41uVqhfIXJ2BWZpmT
46
46
  tuieval/templates/packs/tool_call/system.txt,sha256=mKxu-lB-0YjLHXdgeFJa8x2C180OvcNz5cHv2N5Bg3U,254
47
47
  tuieval/templates/packs/tool_call/tests.yaml,sha256=Nv7c4syrzJ9cU8EBKSK_1ZSFx9V02aCjW4-2TBCPT7s,1859
48
48
  tuieval/templates/packs/tool_call/tools.yaml,sha256=HgxCkh0On2VwbHSsjAGM8tNCK7ZtKLGrs7lMCn3Fprs,1048
49
- tuieval-0.2.0.dev55.dist-info/METADATA,sha256=DGIO8VwyZC4CMfIgLwiY7gpg24S1xfuPDakBj_W90qo,13881
50
- tuieval-0.2.0.dev55.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
51
- tuieval-0.2.0.dev55.dist-info/entry_points.txt,sha256=7eIhi1GpFxBP2OLJV02Nn8LwsNuO512eKOGt1IBbj04,45
52
- tuieval-0.2.0.dev55.dist-info/licenses/LICENSE,sha256=7wfRgGtBGH1aXhZkIn47oUznqKC18kEPMvUVgol7Ffc,1077
53
- tuieval-0.2.0.dev55.dist-info/RECORD,,
49
+ tuieval-0.2.0.dev56.dist-info/METADATA,sha256=nUWInJiqgtyGg3hiyaYIUuGD-BYOzoyqi3kRoSloRPk,13881
50
+ tuieval-0.2.0.dev56.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
51
+ tuieval-0.2.0.dev56.dist-info/entry_points.txt,sha256=7eIhi1GpFxBP2OLJV02Nn8LwsNuO512eKOGt1IBbj04,45
52
+ tuieval-0.2.0.dev56.dist-info/licenses/LICENSE,sha256=7wfRgGtBGH1aXhZkIn47oUznqKC18kEPMvUVgol7Ffc,1077
53
+ tuieval-0.2.0.dev56.dist-info/RECORD,,