tuieval 0.2.0.dev103__tar.gz → 0.2.0.dev105__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 (79) hide show
  1. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/CHANGELOG.md +1 -0
  2. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/PKG-INFO +1 -1
  3. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/_version.py +2 -2
  4. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/__init__.py +3 -2
  5. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/code.py +18 -2
  6. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/tests/test_tuieval.py +15 -0
  7. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/.gitignore +0 -0
  8. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/LICENSE +0 -0
  9. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/README.md +0 -0
  10. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/RELEASING.md +0 -0
  11. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/README.md +0 -0
  12. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/favicon.ico +0 -0
  13. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/readme-header.png +0 -0
  14. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/social-preview.png +0 -0
  15. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-1024.png +0 -0
  16. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-128.png +0 -0
  17. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-16.png +0 -0
  18. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-16.svg +0 -0
  19. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-256.png +0 -0
  20. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-32.png +0 -0
  21. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-48.png +0 -0
  22. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-512.png +0 -0
  23. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-64.png +0 -0
  24. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon-animated.svg +0 -0
  25. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/brand/tuieval-icon.svg +0 -0
  26. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/tui-answer-reasoning.png +0 -0
  27. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/tui-run-reasoning.png +0 -0
  28. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/images/tui-setup.png +0 -0
  29. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/models.md +0 -0
  30. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/docs/writing-packs.md +0 -0
  31. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/pyproject.toml +0 -0
  32. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/__init__.py +0 -0
  33. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/__main__.py +0 -0
  34. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/builtin.toml +0 -0
  35. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/cli.py +0 -0
  36. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/client.py +0 -0
  37. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/compare.py +0 -0
  38. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/doctor.py +0 -0
  39. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/engine.py +0 -0
  40. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/export.py +0 -0
  41. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/answer.py +0 -0
  42. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/rag.py +0 -0
  43. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/reply.py +0 -0
  44. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/graders/tool_call.py +0 -0
  45. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/insights.py +0 -0
  46. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/logs.py +0 -0
  47. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/machines.py +0 -0
  48. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/onboard.py +0 -0
  49. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/packs.py +0 -0
  50. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/profiles.py +0 -0
  51. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/pta.py +0 -0
  52. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/remove.py +0 -0
  53. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/run_evals.py +0 -0
  54. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/scaffold.py +0 -0
  55. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/selftest.py +0 -0
  56. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/models.toml +0 -0
  57. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/answer/pack.toml +0 -0
  58. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/answer/system.txt +0 -0
  59. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/answer/tests.yaml +0 -0
  60. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/code/pack.toml +0 -0
  61. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/code/system.txt +0 -0
  62. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/code/tests.yaml +0 -0
  63. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/rag/pack.toml +0 -0
  64. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/rag/system.txt +0 -0
  65. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/rag/tests.yaml +0 -0
  66. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/reply/pack.toml +0 -0
  67. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/reply/system.txt +0 -0
  68. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/reply/tests.yaml +0 -0
  69. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/tool_call/pack.toml +0 -0
  70. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/tool_call/system.txt +0 -0
  71. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/tool_call/tests.yaml +0 -0
  72. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/templates/packs/tool_call/tools.yaml +0 -0
  73. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/tui.py +0 -0
  74. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/tune.py +0 -0
  75. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/verdict.py +0 -0
  76. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/watch_proxy.py +0 -0
  77. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/workspace.py +0 -0
  78. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/src/tuieval/yamlout.py +0 -0
  79. {tuieval-0.2.0.dev103 → tuieval-0.2.0.dev105}/tests/mock_server.py +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Fix: an answer followed by a stray `</think>` (or a stray code fence after it) was graded as empty; the answer before the tag is graded now. The code grader also reads a doubled ```` ```python ```` fence as one.
5
6
  - Run screen: `x` removes the highlighted pack from the run going if it hasn't started (the reverse of adding it); a model left with nothing isn't started.
6
7
  - `k` (skip model) asks first, naming the model. Yes/no dialogs start on No; `y` answers yes, `n` or Esc no.
7
8
  - Fix: hosted models no longer count as running alongside local ones (they don't share the machine), so a one-model-at-a-time setup no longer gets the "ran alongside other models" note. Older results are read the same way.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tuieval
3
- Version: 0.2.0.dev103
3
+ Version: 0.2.0.dev105
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.dev103'
22
- __version_tuple__ = version_tuple = (0, 2, 0, 'dev103')
21
+ __version__ = version = '0.2.0.dev105'
22
+ __version_tuple__ = version_tuple = (0, 2, 0, 'dev105')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -123,8 +123,9 @@ def strip_thinking(text):
123
123
  """Safety net for servers that leave <think> blocks in the answer."""
124
124
  text = THINK_RE.sub("", text or "")
125
125
  if "</think>" in text:
126
- text = text.split("</think>")[-1]
127
- return text.strip()
126
+ before, after = text.rsplit("</think>", 1)
127
+ text = after if after.strip(" \t\r\n`") else before # a stray closing tag (or fence) after the answer
128
+ return text.replace("<think>", "").replace("</think>", "").strip()
128
129
 
129
130
 
130
131
  def grade(test, answer, meta=None):
@@ -15,8 +15,24 @@ from . import grader, result
15
15
 
16
16
 
17
17
  def _extract_code(text):
18
- blocks = re.findall(r"```(?:python|py)?[ \t]*\n(.*?)```", text, re.DOTALL)
19
- return blocks[-1] if blocks else text # last block = the final answer, not a draft
18
+ """The last python (or untagged) fenced block: the final answer, not a draft. A doubled
19
+ opening fence is one fence, and a stray fence after the last block is ignored."""
20
+ blocks, lang, cur = [], None, None
21
+ for line in text.splitlines(keepends=True):
22
+ fence = line.strip()
23
+ if not fence.startswith("```"):
24
+ if cur is not None:
25
+ cur.append(line)
26
+ elif cur is None:
27
+ lang, cur = fence[3:].strip().lower(), []
28
+ elif fence[3:].strip() and not "".join(cur).strip():
29
+ lang = fence[3:].strip().lower() # ```python twice
30
+ else:
31
+ if lang in ("", "python", "py", "python3"):
32
+ blocks.append("".join(cur))
33
+ cur = None
34
+ blocks = [b for b in blocks if b.strip()]
35
+ return blocks[-1] if blocks else text
20
36
 
21
37
 
22
38
  CHECK_RE = re.compile(r"^# (SETUP|CHECK: *(.+?)) *$")
@@ -248,6 +248,21 @@ class WorkspaceGraders(unittest.TestCase):
248
248
 
249
249
 
250
250
  class Units(unittest.TestCase):
251
+ def test_strip_thinking_keeps_answer_before_stray_close_tag(self):
252
+ from tuieval.graders import strip_thinking
253
+ self.assertEqual(strip_thinking("<think>hm</think>\n42"), "42")
254
+ self.assertEqual(strip_thinking("leaked thoughts</think>\n42"), "42")
255
+ self.assertEqual(strip_thinking("```python\nx = 1\n```\n</think>\n"), "```python\nx = 1\n```")
256
+ self.assertEqual(strip_thinking("</think>"), "")
257
+ self.assertEqual(strip_thinking("```python\nx = 1\n```\n</think>\n```"), "```python\nx = 1\n```")
258
+
259
+ def test_extract_code_tolerates_doubled_and_stray_fences(self):
260
+ from tuieval.graders.code import _extract_code
261
+ self.assertEqual(_extract_code("```python\n```python\nx = 1\n```\n```"), "x = 1\n")
262
+ self.assertEqual(_extract_code("```py\nold\n```\ntext\n```python\nnew\n```"), "new\n") # last block wins
263
+ self.assertEqual(_extract_code("```python\nx = 1\n```\n```bash\nrun it\n```"), "x = 1\n")
264
+ self.assertEqual(_extract_code("x = 1"), "x = 1")
265
+
251
266
  def test_settings_note_names_only_what_differs(self):
252
267
  from tuieval import compare
253
268
  infos = [{"label": m, "settings": {"temperature": 1.0, **extra}} for m, extra in
File without changes
File without changes