tuieval 0.2.0.dev119__tar.gz → 0.2.0.dev121__tar.gz

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.
Files changed (80) hide show
  1. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/CHANGELOG.md +2 -0
  2. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/PKG-INFO +1 -1
  3. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/_version.py +2 -2
  4. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/tui.py +7 -5
  5. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/tests/test_tuieval.py +30 -1
  6. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/.gitignore +0 -0
  7. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/LICENSE +0 -0
  8. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/README.md +0 -0
  9. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/RELEASING.md +0 -0
  10. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/README.md +0 -0
  11. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/favicon.ico +0 -0
  12. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/readme-header.png +0 -0
  13. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/social-preview.png +0 -0
  14. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-1024.png +0 -0
  15. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-128.png +0 -0
  16. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-16.png +0 -0
  17. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-16.svg +0 -0
  18. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-256.png +0 -0
  19. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-32.png +0 -0
  20. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-48.png +0 -0
  21. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-512.png +0 -0
  22. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-64.png +0 -0
  23. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon-animated.svg +0 -0
  24. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/brand/tuieval-icon.svg +0 -0
  25. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/tui-answer-reasoning.png +0 -0
  26. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/tui-run-reasoning.png +0 -0
  27. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/images/tui-setup.png +0 -0
  28. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/models.md +0 -0
  29. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/docs/writing-packs.md +0 -0
  30. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/pyproject.toml +0 -0
  31. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/__init__.py +0 -0
  32. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/__main__.py +0 -0
  33. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/builtin.toml +0 -0
  34. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/cli.py +0 -0
  35. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/client.py +0 -0
  36. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/compare.py +0 -0
  37. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/dates.py +0 -0
  38. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/doctor.py +0 -0
  39. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/engine.py +0 -0
  40. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/export.py +0 -0
  41. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/__init__.py +0 -0
  42. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/answer.py +0 -0
  43. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/code.py +0 -0
  44. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/rag.py +0 -0
  45. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/reply.py +0 -0
  46. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/graders/tool_call.py +0 -0
  47. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/insights.py +0 -0
  48. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/logs.py +0 -0
  49. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/machines.py +0 -0
  50. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/onboard.py +0 -0
  51. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/packs.py +0 -0
  52. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/profiles.py +0 -0
  53. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/pta.py +0 -0
  54. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/remove.py +0 -0
  55. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/run_evals.py +0 -0
  56. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/scaffold.py +0 -0
  57. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/selftest.py +0 -0
  58. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/models.toml +0 -0
  59. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/answer/pack.toml +0 -0
  60. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/answer/system.txt +0 -0
  61. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/answer/tests.yaml +0 -0
  62. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/code/pack.toml +0 -0
  63. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/code/system.txt +0 -0
  64. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/code/tests.yaml +0 -0
  65. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/rag/pack.toml +0 -0
  66. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/rag/system.txt +0 -0
  67. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/rag/tests.yaml +0 -0
  68. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/reply/pack.toml +0 -0
  69. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/reply/system.txt +0 -0
  70. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/reply/tests.yaml +0 -0
  71. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/tool_call/pack.toml +0 -0
  72. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/tool_call/system.txt +0 -0
  73. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/tool_call/tests.yaml +0 -0
  74. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/templates/packs/tool_call/tools.yaml +0 -0
  75. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/tune.py +0 -0
  76. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/verdict.py +0 -0
  77. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/watch_proxy.py +0 -0
  78. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/workspace.py +0 -0
  79. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/src/tuieval/yamlout.py +0 -0
  80. {tuieval-0.2.0.dev119 → tuieval-0.2.0.dev121}/tests/mock_server.py +0 -0
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Fix: Results → Per question opened the answers of the model one column to the right of the cell picked, and crashed on the last model's column.
6
+ - Fix: `v` on the run screen switches to the last model still running when the stream shows one that has finished.
5
7
  - Setup opens with no models ticked: at launch, after New run, and after Back from a run or tune. Packs and options are still remembered.
6
8
  - Tuning: a server that refuses the `ignore_eos` request field is asked again without it, so strict servers can be tuned; the profile notes that workload answers may end early.
7
9
  - Fix: a server that crashes mid-request (the stream ends with no finish reason) was graded as an empty or cut-short answer; it's a server error now, never counted against the model.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tuieval
3
- Version: 0.2.0.dev119
3
+ Version: 0.2.0.dev121
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
@@ -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.dev119'
22
- __version_tuple__ = version_tuple = (0, 2, 0, 'dev119')
21
+ __version__ = version = '0.2.0.dev121'
22
+ __version_tuple__ = version_tuple = (0, 2, 0, 'dev121')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -2779,8 +2779,8 @@ class RunScreen(Screen):
2779
2779
  def action_watch_next(self):
2780
2780
  """Stream the next model running alongside (from its next answer)."""
2781
2781
  active = self.active()
2782
- if len(active) < 2:
2783
- self.notify("Only one model is running right now.")
2782
+ if not active or active == [self.watch]:
2783
+ self.notify("Only one model is running right now." if active else "No model is running right now.")
2784
2784
  return
2785
2785
  self.watch = active[(active.index(self.watch) + 1) % len(active)] if self.watch in active else active[0]
2786
2786
  with self.buf_lock:
@@ -3296,7 +3296,7 @@ class ResultsScreen(Screen):
3296
3296
  here = self.app.engine.machine().id
3297
3297
  table = self.query_one("#per-question", DataTable)
3298
3298
  table.clear(columns=True)
3299
- table.add_columns("Test", "Pack", "Level", "Added", "×tokens", *models)
3299
+ table.add_columns(*self.PQ_FIXED, *models)
3300
3300
  self.pq_tests, self.pq_models = {}, models
3301
3301
  for t in tests:
3302
3302
  cells = []
@@ -3415,11 +3415,13 @@ class ResultsScreen(Screen):
3415
3415
  return (f"{mark} {tok_s} {secs}" + (" [red]cut[/red]" if c["truncated"] else "")
3416
3416
  + (" [cyan]◐[/cyan]" if c["partial"] else ""))
3417
3417
 
3418
+ PQ_FIXED = ("Test", "Pack", "Level", "Added", "×tokens") # Per question's columns before the models
3419
+
3418
3420
  @on(DataTable.CellSelected, "#per-question")
3419
3421
  def per_question_selected(self, event):
3420
- col = event.coordinate.column - 4
3422
+ col = event.coordinate.column - len(self.PQ_FIXED)
3421
3423
  t = self.pq_tests.get(event.cell_key.row_key.value)
3422
- if not t or col < 0:
3424
+ if not t or not 0 <= col < len(self.pq_models):
3423
3425
  self.notify("Pick a model's cell to open its answers.")
3424
3426
  return
3425
3427
  c = t["cells"].get(self.pq_models[col])
@@ -847,6 +847,17 @@ class Parallel(unittest.TestCase):
847
847
  self.assertEqual({out["first"], out["switched"]}, {"a", "b"}) # v streams the other model
848
848
  self.assertTrue(any(r.get("ran_alongside") for r in self.results("a")["results"]))
849
849
 
850
+ def test_watch_next_moves_to_the_last_model_running(self):
851
+ from tuieval.tui import RunScreen
852
+ run = unittest.mock.MagicMock(watch="a", buf={"reasoning": [], "answer": []}, buf_lock=threading.Lock())
853
+ run.active.return_value = ["b"] # a finished; only b is still running
854
+ RunScreen.action_watch_next(run)
855
+ self.assertEqual(run.watch, "b")
856
+ run.active.return_value = ["b"]
857
+ RunScreen.action_watch_next(run) # already watching the only one
858
+ self.assertEqual(run.watch, "b")
859
+ run.notify.assert_called_with("Only one model is running right now.")
860
+
850
861
  def test_skip_one_model_keeps_the_other(self):
851
862
  e, events = self.engine()
852
863
  jobs = e.plan(["a", "b"], ["apps"], None, "certify", False, {})
@@ -1750,7 +1761,23 @@ class PTAIndex(unittest.TestCase):
1750
1761
  await pilot.pause(0.3)
1751
1762
  s = app.screen
1752
1763
  sorts["opened"] = s.entries[s.index]["record"]["test"]
1753
- print(json.dumps({"rows": rows, "bars": "P parsimony" in tri, "disagree": [both, alone],
1764
+ s.dismiss()
1765
+ await pilot.pause(0.2)
1766
+ app.pq_models = set()
1767
+ app.screen.query_one("#pq-disagree").value = False
1768
+ app.screen.query_one(TabbedContent).active = "tab-per-question"
1769
+ app.screen.fill_per_question()
1770
+ await pilot.pause(0.3)
1771
+ opened = {}
1772
+ pq.focus()
1773
+ for col in range(5, len(pq.columns)): # each model's cell opens its own answers
1774
+ pq.move_cursor(row=0, column=col)
1775
+ await pilot.press("enter")
1776
+ await pilot.pause(0.3)
1777
+ opened[str(pq.ordered_columns[col].label.plain)] = app.screen.entries[0]["model"]
1778
+ app.screen.dismiss()
1779
+ await pilot.pause(0.2)
1780
+ print(json.dumps({"rows": rows, "bars": "P parsimony" in tri, "disagree": [both, alone], "opened": opened,
1754
1781
  "tab": tab, "sorts": sorts, "fails": fails}))
1755
1782
  asyncio.run(go())
1756
1783
  """)
@@ -1760,6 +1787,8 @@ class PTAIndex(unittest.TestCase):
1760
1787
  self.assertIsInstance(got, dict, got)
1761
1788
  self.assertTrue(got["bars"])
1762
1789
  self.assertEqual(got["disagree"], [4, 0])
1790
+ self.assertGreaterEqual(len(got["opened"]), 2)
1791
+ self.assertEqual(got["opened"], {m: m for m in got["opened"]}) # a cell opens its column's model
1763
1792
  self.assertEqual(got["tab"], "tab-pta") # Results opens on the PTA index
1764
1793
  self.assertEqual([(r[0], r[3]) for r in got["rows"]][0], ("good", "4/4"))
1765
1794
  s = got["sorts"] # a click on a column name sorts by it, a second click reverses
File without changes
File without changes