tuieval 0.2.0.dev125__tar.gz → 0.2.0.dev127__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.
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/CHANGELOG.md +1 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/PKG-INFO +1 -1
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/_version.py +2 -2
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/client.py +1 -1
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/compare.py +2 -1
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/tests/mock_server.py +6 -1
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/tests/test_tuieval.py +8 -3
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/.gitignore +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/LICENSE +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/README.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/RELEASING.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/agent-packs.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/README.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/favicon.ico +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/readme-header.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/social-preview.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-1024.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-128.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-16.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-16.svg +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-256.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-32.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-48.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-512.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-64.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon-animated.svg +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/brand/tuieval-icon.svg +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/tui-answer-reasoning.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/tui-run-reasoning.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/images/tui-setup.png +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/models.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/docs/writing-packs.md +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/pyproject.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/__init__.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/__main__.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/agents.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/builtin.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/cli.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/dates.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/doctor.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/engine.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/export.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/__init__.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/answer.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/code.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/rag.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/reply.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/graders/tool_call.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/insights.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/logs.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/machines.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/onboard.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/packs.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/profiles.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/pta.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/remove.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/run_evals.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/scaffold.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/selftest.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/models.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/answer/pack.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/answer/system.txt +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/answer/tests.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/code/pack.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/code/system.txt +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/code/tests.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/rag/pack.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/rag/system.txt +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/rag/tests.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/reply/pack.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/reply/system.txt +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/reply/tests.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/pack.toml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/system.txt +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/tests.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/tools.yaml +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/tui.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/tune.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/verdict.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/watch_proxy.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/workspace.py +0 -0
- {tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/yamlout.py +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Fix: a request that runs out of time says `time limit: timed out after N s`, not `connection error`, and `tuieval compare` counts it against the model like the run does (it was left out as an error).
|
|
5
6
|
- Agent packs (`kind = "agent"`): each test is a small project with a task, worked on by a command-line agent you define in `[agents]`, using the model tuieval serves, and graded by the task's visible and hidden tests. Results show the agent's stats, diff and transcript; `tuieval compare` adds an Agent tasks table; `tuieval selftest` checks each task's reference and wrong fixes. See docs/agent-packs.md.
|
|
6
7
|
- Answers that used more tokens than the `max_tokens` sent (a provider that didn't stop them) are marked over budget: `(n over budget)` in the PTA index, an **over budget** column, `over` in Per question and a note in the answer view. `[defaults] over_budget = "fail"` fails them instead. Works on stored results.
|
|
7
8
|
- 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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tuieval
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev127
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2, 0, '
|
|
21
|
+
__version__ = version = '0.2.0.dev127'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 0, 'dev127')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -153,7 +153,7 @@ def stream_chat(base_url, body, on_delta=None, timeout=1800, stream=None, header
|
|
|
153
153
|
for raw in r:
|
|
154
154
|
now = time.time()
|
|
155
155
|
if now - start > timeout:
|
|
156
|
-
out["error"] = f"
|
|
156
|
+
out["error"] = f"time limit: timed out after {timeout:.0f} s in all"
|
|
157
157
|
break
|
|
158
158
|
if stall_s and out["ttft_s"] is not None and now - last > stall_s:
|
|
159
159
|
out["error"] = _stalled(stall_s)
|
|
@@ -49,7 +49,8 @@ def _load_native(data):
|
|
|
49
49
|
"model": m["label"], "suite": pack["name"], "test": f"{pack['name']}: {r['test']}",
|
|
50
50
|
"name": f"{pack['name']}: {r['description']}",
|
|
51
51
|
"ok": bool(r["pass"]), "score": float(r["score"]), "reason": r["reason"],
|
|
52
|
-
|
|
52
|
+
# a timeout is the model too slow (client.is_server_error), not an error; older results called it one
|
|
53
|
+
"error": r["reason"].startswith(("server returned", "connection error")) and "timed out" not in r["reason"],
|
|
53
54
|
"truncated": r.get("finish") == "length", "output": r.get("answer") or "",
|
|
54
55
|
# tokens past the max_tokens sent, which the provider didn't stop (client.mark_over_budget)
|
|
55
56
|
"over_budget": r.get("over_budget"),
|
|
@@ -56,6 +56,7 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
56
56
|
answers, mode, model, delay, max_output = {}, "oracle", "mock", 0.0, None
|
|
57
57
|
stall, stall_before, silent = 0.0, 0.0, False
|
|
58
58
|
die_after = None
|
|
59
|
+
hold, answered = None, 0 # while the hold file exists, answers after the first wait (a run that stays going)
|
|
59
60
|
|
|
60
61
|
def log_message(self, *a):
|
|
61
62
|
pass
|
|
@@ -120,6 +121,8 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
120
121
|
self.wfile.flush()
|
|
121
122
|
time.sleep(0.2)
|
|
122
123
|
|
|
124
|
+
while self.hold and Handler.answered and os.path.exists(self.hold):
|
|
125
|
+
wait(0.2)
|
|
123
126
|
wait(self.stall_before)
|
|
124
127
|
send({"choices": [{"delta": {"reasoning_content": "Thinking it over. "}}]})
|
|
125
128
|
wait(self.stall)
|
|
@@ -136,6 +139,7 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
136
139
|
"prompt_per_second": 500.0, "cache_n": 0}})
|
|
137
140
|
die_if_due()
|
|
138
141
|
self.wfile.write(b"data: [DONE]\n\n")
|
|
142
|
+
Handler.answered += 1
|
|
139
143
|
|
|
140
144
|
|
|
141
145
|
class Server(ThreadingHTTPServer):
|
|
@@ -157,11 +161,12 @@ def main(argv=None):
|
|
|
157
161
|
p.add_argument("--stall-before", type=float, default=0.0)
|
|
158
162
|
p.add_argument("--silent", action="store_true")
|
|
159
163
|
p.add_argument("--die-after", type=int)
|
|
164
|
+
p.add_argument("--hold", help="while this file exists, every answer after the first waits")
|
|
160
165
|
a, _ = p.parse_known_args(argv) # other flags (e.g. speed knobs under test) are accepted and ignored
|
|
161
166
|
Handler.answers, Handler.mode, Handler.model, Handler.delay = load_answers(a.packs), a.mode, a.model, a.delay
|
|
162
167
|
Handler.max_output = a.max_output
|
|
163
168
|
Handler.stall, Handler.stall_before, Handler.silent = a.stall, a.stall_before, a.silent
|
|
164
|
-
Handler.die_after = a.die_after
|
|
169
|
+
Handler.die_after, Handler.hold = a.die_after, a.hold
|
|
165
170
|
srv = Server(("127.0.0.1", a.port), Handler)
|
|
166
171
|
print(f"mock server on 127.0.0.1:{a.port} ({a.mode}, {len(Handler.answers)} known questions)", flush=True)
|
|
167
172
|
try:
|
|
@@ -1412,8 +1412,12 @@ class AddToRun(unittest.TestCase):
|
|
|
1412
1412
|
|
|
1413
1413
|
def test_tui_never_queues_the_same_thing_twice(self):
|
|
1414
1414
|
"""Start while a run is going never adds or queues a model and pack already running or queued."""
|
|
1415
|
+
hold = os.path.join(self.tmp.name, "hold") # the first run stays going until every pick is made
|
|
1416
|
+
write(hold, "")
|
|
1417
|
+
path = os.path.join(self.ws, "models.toml")
|
|
1418
|
+
write(path, read(path).replace('"--delay", "0.2"', f'"--delay", "0.2", "--hold", {json.dumps(hold)}'))
|
|
1415
1419
|
code = textwrap.dedent("""
|
|
1416
|
-
import asyncio, json, time
|
|
1420
|
+
import asyncio, json, os, time
|
|
1417
1421
|
from tuieval.tui import EvalsApp, RunScreen, SetupScreen, ChoiceScreen
|
|
1418
1422
|
from textual.widgets import SelectionList
|
|
1419
1423
|
async def pick(app, pilot, models, packs=("apps",)):
|
|
@@ -1459,6 +1463,7 @@ class AddToRun(unittest.TestCase):
|
|
|
1459
1463
|
if isinstance(s, ChoiceScreen):
|
|
1460
1464
|
s.dismiss("queue")
|
|
1461
1465
|
await pilot.pause()
|
|
1466
|
+
os.remove(os.environ["HOLD"])
|
|
1462
1467
|
deadline = time.time() + 300 # the queued runs start one after another: wait for all three
|
|
1463
1468
|
while time.time() < deadline:
|
|
1464
1469
|
await pilot.pause(0.2)
|
|
@@ -1469,7 +1474,7 @@ class AddToRun(unittest.TestCase):
|
|
|
1469
1474
|
asyncio.run(go())
|
|
1470
1475
|
""")
|
|
1471
1476
|
p = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True, timeout=600,
|
|
1472
|
-
env=dict(os.environ, TUIEVAL_HOME=self.ws, TUIEVAL_DETECT_PORTS=""))
|
|
1477
|
+
env=dict(os.environ, TUIEVAL_HOME=self.ws, TUIEVAL_DETECT_PORTS="", HOLD=hold))
|
|
1473
1478
|
out = json.loads(p.stdout.strip().splitlines()[-1]) if p.stdout.strip() else p.stderr
|
|
1474
1479
|
self.assertIsInstance(out, dict, out)
|
|
1475
1480
|
self.assertEqual(out["same"], [False, 0])
|
|
@@ -3005,7 +3010,7 @@ class StallGuard(unittest.TestCase):
|
|
|
3005
3010
|
def test_keepalives_dont_outlast_the_timeout(self):
|
|
3006
3011
|
from tuieval import client
|
|
3007
3012
|
res, took = self.ask("--stall-before", "5", timeout=1, stall_s=1)
|
|
3008
|
-
self.
|
|
3013
|
+
self.assertTrue(res["error"].startswith("time limit: timed out"), res["error"])
|
|
3009
3014
|
self.assertFalse(client.is_server_error(res["error"])) # slow, like any timeout: counts
|
|
3010
3015
|
self.assertLess(took, 4)
|
|
3011
3016
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/pack.toml
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/system.txt
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/tests.yaml
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev125 → tuieval-0.2.0.dev127}/src/tuieval/templates/packs/tool_call/tools.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|