tuieval 0.2.0.dev116__tar.gz → 0.2.0.dev119__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.dev116 → tuieval-0.2.0.dev119}/CHANGELOG.md +2 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/PKG-INFO +1 -1
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/_version.py +2 -2
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/tui.py +16 -7
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/tune.py +33 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/tests/test_tuieval.py +57 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/.gitignore +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/LICENSE +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/README.md +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/RELEASING.md +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/README.md +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/favicon.ico +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/readme-header.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/social-preview.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-1024.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-128.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-16.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-16.svg +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-256.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-32.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-48.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-512.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-64.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon-animated.svg +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/brand/tuieval-icon.svg +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/tui-answer-reasoning.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/tui-run-reasoning.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/images/tui-setup.png +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/models.md +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/docs/writing-packs.md +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/pyproject.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/__init__.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/__main__.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/builtin.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/cli.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/client.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/compare.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/dates.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/doctor.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/engine.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/export.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/__init__.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/answer.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/code.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/rag.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/reply.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/graders/tool_call.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/insights.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/logs.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/machines.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/onboard.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/packs.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/profiles.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/pta.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/remove.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/run_evals.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/scaffold.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/selftest.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/models.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/answer/pack.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/answer/system.txt +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/answer/tests.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/code/pack.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/code/system.txt +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/code/tests.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/rag/pack.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/rag/system.txt +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/rag/tests.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/reply/pack.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/reply/system.txt +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/reply/tests.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/pack.toml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/system.txt +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/tests.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/tools.yaml +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/verdict.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/watch_proxy.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/workspace.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/yamlout.py +0 -0
- {tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/tests/mock_server.py +0 -0
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- 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
|
+
- 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.
|
|
5
7
|
- 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.
|
|
6
8
|
- Dates: answers record `answered_at` (older ones read it from their log name); tests get an added date (an `added` field, or the day tuieval first saw them, in `test-dates.json`). Shown in the answer view, Pick tests, Per question, Failures and Production readiness.
|
|
7
9
|
- Copy reasoning: `y` in the answer view copies its full reasoning, `a` the answer; `y` on the run screen copies the reasoning streamed so far. Uses pbcopy, wl-copy, xclip, xsel or clip, else the terminal (OSC 52).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tuieval
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev119
|
|
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.dev119'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 0, 'dev119')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -751,11 +751,17 @@ class SetupScreen(Screen):
|
|
|
751
751
|
self.refresh_packs()
|
|
752
752
|
self.refresh_models()
|
|
753
753
|
state = self.app.load_state()
|
|
754
|
-
|
|
755
|
-
|
|
754
|
+
if state: # packs and options carry over; models start unticked every time
|
|
755
|
+
self.apply_selection({k: v for k, v in state.items() if k != "models"}, quiet=True)
|
|
756
|
+
else:
|
|
756
757
|
self.first_time_defaults()
|
|
757
758
|
self.query_one("#suites", SelectionList).focus()
|
|
758
759
|
|
|
760
|
+
def clear_models(self):
|
|
761
|
+
"""Untick every model (Setup shown again after a run: each run picks its models afresh)."""
|
|
762
|
+
self.selected_models = set()
|
|
763
|
+
self.refresh_models()
|
|
764
|
+
|
|
759
765
|
def first_time_defaults(self):
|
|
760
766
|
"""With nothing chosen before: tick the only pack and the only local model, and start on
|
|
761
767
|
Smoke until something has run (a 3-question check of the setup)."""
|
|
@@ -1155,7 +1161,7 @@ class SetupScreen(Screen):
|
|
|
1155
1161
|
reasons = sorted({j.note for j in jobs if j.status == "skipped"})
|
|
1156
1162
|
self.notify(f"Nothing selected can run: {'; '.join(reasons)}", severity="warning")
|
|
1157
1163
|
return
|
|
1158
|
-
self.app.save_state(sel)
|
|
1164
|
+
self.app.save_state({k: v for k, v in sel.items() if k != "models"}) # models aren't remembered
|
|
1159
1165
|
# Packs whose earlier answers a start would set aside (Retest, everything already done, or
|
|
1160
1166
|
# other questions or settings): the user picks per pack before anything moves.
|
|
1161
1167
|
rows, rerun = retest_rows(e, labels, suites, repeat, tier, picks, force)
|
|
@@ -1349,7 +1355,7 @@ class TuneScreen(Screen):
|
|
|
1349
1355
|
def action_back(self):
|
|
1350
1356
|
if self.running:
|
|
1351
1357
|
self.notify("Tuning keeps going; the header shows its progress. Press w to come back.")
|
|
1352
|
-
self.app.back_to_setup()
|
|
1358
|
+
self.app.back_to_setup(clear_models=True)
|
|
1353
1359
|
|
|
1354
1360
|
|
|
1355
1361
|
# ------------------------------------------------------------------ add model
|
|
@@ -2825,7 +2831,7 @@ class RunScreen(Screen):
|
|
|
2825
2831
|
if self.running:
|
|
2826
2832
|
self.notify("Pick models and packs, then Start: add them to this run or queue them after it.",
|
|
2827
2833
|
timeout=8)
|
|
2828
|
-
self.app.back_to_setup() #
|
|
2834
|
+
self.app.back_to_setup(clear_models=True) # packs and options stay; models are picked afresh
|
|
2829
2835
|
self.app.screen.query_one("#models").focus()
|
|
2830
2836
|
|
|
2831
2837
|
@on(Button.Pressed, "#done-runs")
|
|
@@ -2835,7 +2841,7 @@ class RunScreen(Screen):
|
|
|
2835
2841
|
def action_back(self):
|
|
2836
2842
|
if self.running:
|
|
2837
2843
|
self.notify("The run keeps going; the header shows its progress. Press w to come back.")
|
|
2838
|
-
self.app.back_to_setup()
|
|
2844
|
+
self.app.back_to_setup(clear_models=True)
|
|
2839
2845
|
|
|
2840
2846
|
|
|
2841
2847
|
# ------------------------------------------------------------------ results
|
|
@@ -3789,9 +3795,12 @@ class EvalsApp(App):
|
|
|
3789
3795
|
return (f"\n\nThe {len(self.queue)} queued item(s) are dropped (the queue isn't kept after quitting): "
|
|
3790
3796
|
+ "; ".join(i.title for i in self.queue) + ".")
|
|
3791
3797
|
|
|
3792
|
-
def back_to_setup(self):
|
|
3798
|
+
def back_to_setup(self, clear_models=False):
|
|
3799
|
+
"""clear_models: Setup is being shown for a new pick (New run, Back), so no model stays ticked."""
|
|
3793
3800
|
while len(self.screen_stack) > 2 and not isinstance(self.screen, SetupScreen):
|
|
3794
3801
|
self.pop_screen()
|
|
3802
|
+
if clear_models and isinstance(self.screen, SetupScreen):
|
|
3803
|
+
self.screen.clear_models()
|
|
3795
3804
|
|
|
3796
3805
|
def show_session(self, screen):
|
|
3797
3806
|
if screen is None or screen is self.screen:
|
|
@@ -169,7 +169,37 @@ def _body(m, sampling, msgs, max_tokens=GEN_TOKENS, request=None):
|
|
|
169
169
|
**(request or {})}
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
def _rejects_ignore_eos(res):
|
|
173
|
+
"""True if the server refused the request because it doesn't accept the ignore_eos field."""
|
|
174
|
+
err = res.get("error") or ""
|
|
175
|
+
return err.startswith("server returned HTTP 4") and "ignore_eos" in err
|
|
176
|
+
|
|
177
|
+
|
|
172
178
|
def _request(eng, base_url, body, name, emit, limit):
|
|
179
|
+
"""One streamed request with live progress and a wall-clock limit. A server that refuses
|
|
180
|
+
ignore_eos is asked again without it, and later requests leave it out (see no_ignore_eos)."""
|
|
181
|
+
key = (base_url, body.get("model"))
|
|
182
|
+
rejected = no_ignore_eos(eng)
|
|
183
|
+
if key in rejected:
|
|
184
|
+
body = {k: v for k, v in body.items() if k != "ignore_eos"}
|
|
185
|
+
res = _stream_request(eng, base_url, body, name, emit, limit)
|
|
186
|
+
if body.get("ignore_eos") and _rejects_ignore_eos(res):
|
|
187
|
+
rejected.add(key)
|
|
188
|
+
emit("tune_step", message=" the server doesn't accept ignore_eos: answers may end early "
|
|
189
|
+
"(speeds are per token, so still comparable)")
|
|
190
|
+
res = _stream_request(eng, base_url, {k: v for k, v in body.items() if k != "ignore_eos"},
|
|
191
|
+
name, emit, limit)
|
|
192
|
+
return res
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def no_ignore_eos(eng):
|
|
196
|
+
"""(base_url, served model) pairs whose server refused ignore_eos in this tuning session."""
|
|
197
|
+
if not hasattr(eng, "_tune_no_ignore_eos"):
|
|
198
|
+
eng._tune_no_ignore_eos = set()
|
|
199
|
+
return eng._tune_no_ignore_eos
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _stream_request(eng, base_url, body, name, emit, limit):
|
|
173
203
|
"""One streamed request with live progress (every PROGRESS_EVERY_S: waiting for the first
|
|
174
204
|
token, or ~tokens so far and tok/s) and a wall-clock limit. Returns client.stream_chat's result."""
|
|
175
205
|
st, t0 = client.Stream(), time.time()
|
|
@@ -681,6 +711,9 @@ def tune(eng, label, emit=lambda *a, **k: None, max_starts=16, min_gain=0.03, us
|
|
|
681
711
|
if warm_info:
|
|
682
712
|
notes.insert(0, f"warm start from {warm_info['from']}: inherited "
|
|
683
713
|
f"{', '.join(warm_info['inherited']) or 'nothing'}")
|
|
714
|
+
if any(model == m["served_name"] for _, model in no_ignore_eos(eng)):
|
|
715
|
+
notes.insert(0, f"the server doesn't accept ignore_eos, so workload answers could end before "
|
|
716
|
+
f"{gen_tokens} tokens (speeds are per token)")
|
|
684
717
|
if best_r.facts.get("extra_swap_mb") and best_r is not base:
|
|
685
718
|
warnings.append(f"the chosen flags use more memory than the defaults: macOS swapped "
|
|
686
719
|
f"~{best_r.facts['extra_swap_mb']} MB more of other apps' memory; close apps during runs, "
|
|
@@ -2016,6 +2016,32 @@ class FirstRun(unittest.TestCase):
|
|
|
2016
2016
|
env=dict(os.environ, TUIEVAL_HOME=self.ws, TUIEVAL_DETECT_PORTS=""), timeout=60).stdout.strip()
|
|
2017
2017
|
self.assertEqual(out, "['first'] ['my-model'] smoke False") # tuning shows once something has run
|
|
2018
2018
|
|
|
2019
|
+
def test_setup_never_starts_with_models_ticked(self):
|
|
2020
|
+
tuieval(self.ws, "add", "my-model", "--server", "local")
|
|
2021
|
+
os.makedirs(os.path.join(self.ws, "logs"), exist_ok=True)
|
|
2022
|
+
write(os.path.join(self.ws, "logs", "tui_state.json"),
|
|
2023
|
+
json.dumps({"models": ["my-model"], "packs": ["first"], "tier": "certify", "repeat": 2}))
|
|
2024
|
+
code = textwrap.dedent("""
|
|
2025
|
+
import asyncio
|
|
2026
|
+
from tuieval.tui import EvalsApp
|
|
2027
|
+
from textual.widgets import SelectionList
|
|
2028
|
+
async def go():
|
|
2029
|
+
app = EvalsApp({})
|
|
2030
|
+
async with app.run_test(size=(140, 40)) as pilot:
|
|
2031
|
+
await pilot.pause()
|
|
2032
|
+
s = app.screen
|
|
2033
|
+
print(s.query_one("#suites", SelectionList).selected, sorted(s.selected_models), s.tier())
|
|
2034
|
+
s.selected_models = {"my-model"}
|
|
2035
|
+
s.refresh_models()
|
|
2036
|
+
app.back_to_setup(clear_models=True) # what New run and Back do
|
|
2037
|
+
await pilot.pause()
|
|
2038
|
+
print(s.query_one("#suites", SelectionList).selected, sorted(s.selected_models))
|
|
2039
|
+
asyncio.run(go())
|
|
2040
|
+
""")
|
|
2041
|
+
out = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True,
|
|
2042
|
+
env=dict(os.environ, TUIEVAL_HOME=self.ws, TUIEVAL_DETECT_PORTS=""), timeout=60).stdout
|
|
2043
|
+
self.assertEqual(out.strip().splitlines(), ["['first'] [] certify", "['first'] []"])
|
|
2044
|
+
|
|
2019
2045
|
def test_trimmed_names_keep_both_ends(self):
|
|
2020
2046
|
from tuieval.tui import fit_first_column, mid_trim, trim_names
|
|
2021
2047
|
name = "some-author--some-long-model-name-q4_k_m-vllm"
|
|
@@ -2512,6 +2538,37 @@ class WarmTune(unittest.TestCase):
|
|
|
2512
2538
|
self.assertEqual(out.score("projected"), 66.0)
|
|
2513
2539
|
self.assertEqual(out.score("total"), 10.0)
|
|
2514
2540
|
|
|
2541
|
+
def test_server_refusing_ignore_eos_is_asked_without_it(self):
|
|
2542
|
+
sent = []
|
|
2543
|
+
|
|
2544
|
+
def server(eng, base_url, body, *a): # refuses unknown fields, like a strict server
|
|
2545
|
+
sent.append(dict(body))
|
|
2546
|
+
if "ignore_eos" in body:
|
|
2547
|
+
return {"error": 'server returned HTTP 400: {"error":{"message":"unsupported request field: '
|
|
2548
|
+
'ignore_eos"}}', "answer": "", "reasoning": ""}
|
|
2549
|
+
return {"error": None, "answer": "ok", "reasoning": ""}
|
|
2550
|
+
orig = self.tune._stream_request
|
|
2551
|
+
self.tune._stream_request = server
|
|
2552
|
+
self.addCleanup(setattr, self.tune, "_stream_request", orig)
|
|
2553
|
+
body = {"model": "new", "messages": [], "ignore_eos": True}
|
|
2554
|
+
res = self.tune._request(self.eng, "http://x", body, "p", lambda *a, **k: None, 60)
|
|
2555
|
+
self.assertIsNone(res["error"])
|
|
2556
|
+
self.assertEqual(["ignore_eos" in b for b in sent], [True, False]) # retried without it
|
|
2557
|
+
self.tune._request(self.eng, "http://x", body, "p", lambda *a, **k: None, 60)
|
|
2558
|
+
self.assertEqual(len(sent), 3) # later requests leave it out at once
|
|
2559
|
+
self.assertNotIn("ignore_eos", sent[-1])
|
|
2560
|
+
self.assertIn(("http://x", "new"), self.tune.no_ignore_eos(self.eng))
|
|
2561
|
+
|
|
2562
|
+
def test_other_request_errors_are_not_retried(self):
|
|
2563
|
+
sent = []
|
|
2564
|
+
orig = self.tune._stream_request
|
|
2565
|
+
self.tune._stream_request = lambda eng, url, body, *a: sent.append(body) or {
|
|
2566
|
+
"error": "server returned HTTP 400: bad messages", "answer": "", "reasoning": ""}
|
|
2567
|
+
self.addCleanup(setattr, self.tune, "_stream_request", orig)
|
|
2568
|
+
res = self.tune._request(self.eng, "http://x", {"model": "new", "ignore_eos": True}, "p",
|
|
2569
|
+
lambda *a, **k: None, 60)
|
|
2570
|
+
self.assertEqual((len(sent), res["error"]), (1, "server returned HTTP 400: bad messages"))
|
|
2571
|
+
|
|
2515
2572
|
def test_family_ignores_the_mtp_layer(self):
|
|
2516
2573
|
# one GGUF lists KV heads per layer, none on the MTP (last) layer; the other gives one number
|
|
2517
2574
|
d = self.tmp.name
|
|
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.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/pack.toml
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/system.txt
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/src/tuieval/templates/packs/tool_call/tests.yaml
RENAMED
|
File without changes
|
{tuieval-0.2.0.dev116 → tuieval-0.2.0.dev119}/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
|