tenseleyflow/documentlanguagemodel / 20cfe6f

Browse files

Enable more slow integration tests

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
20cfe6f88862ac844cae71b785f168831e8a643d
Parents
510e78c
Tree
eb852e9

6 changed files

StatusFile+-
M tests/integration/train/multi_adapter/test_prompt_and_export_named.py 6 13
M tests/integration/train/multi_adapter/test_two_adapters.py 2 7
M tests/integration/train/multi_adapter/test_weighted_merge.py 2 7
M tests/integration/train/preference/test_dpo_tinymodel.py 7 7
M tests/integration/train/preference/test_orpo_tinymodel.py 7 7
M tests/integration/watch/test_watch_retrain.py 13 8
tests/integration/train/multi_adapter/test_prompt_and_export_named.pymodified
@@ -57,17 +57,12 @@ def _skip_if_tiny_model_unavailable() -> None:
5757
 
5858
 def _train_two(tmp_path_factory: pytest.TempPathFactory) -> Path:
5959
     """Train knowledge + tone on a prose doc; return the .dlm path."""
60
-    from dlm.base_models import resolve as resolve_base_model
6160
     from dlm.doc.parser import parse_file
62
-    from dlm.hardware import doctor
6361
     from dlm.store.manifest import Manifest, save_manifest
6462
     from dlm.store.paths import for_dlm
6563
     from dlm.train.multi_adapter.trainer import run_all
6664
     from tests.fixtures.dlm_factory import make_dlm, prose
67
-
68
-    plan = doctor().plan
69
-    if plan is None:
70
-        pytest.skip("doctor() returned no viable training plan on this host")
65
+    from tests.fixtures.planning import resolve_spec_and_plan
7166
 
7267
     for key in ("HF_HUB_OFFLINE", "TRANSFORMERS_OFFLINE", "HF_DATASETS_OFFLINE"):
7368
         os.environ.pop(key, None)
@@ -96,7 +91,7 @@ def _train_two(tmp_path_factory: pytest.TempPathFactory) -> Path:
9691
     doc.write_text(raw[:fm_end] + "\n" + _PROSE, encoding="utf-8")
9792
 
9893
     parsed = parse_file(doc)
99
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
94
+    spec, plan, _caps = resolve_spec_and_plan(parsed, accept_license=True)
10095
     store = for_dlm(parsed.frontmatter.dlm_id)
10196
     store.ensure_layout()
10297
     save_manifest(
@@ -134,11 +129,10 @@ def test_load_for_inference_resolves_each_named_adapter(
134129
     _skip_if_deps_missing()
135130
     _skip_if_tiny_model_unavailable()
136131
 
137
-    from dlm.base_models import resolve as resolve_base_model
138132
     from dlm.doc.parser import parse_file
139
-    from dlm.hardware import doctor
140133
     from dlm.inference.loader import load_for_inference, resolve_adapter_path
141134
     from dlm.store.paths import for_dlm
135
+    from tests.fixtures.planning import resolve_spec_and_plan
142136
 
143137
     doc = _train_two(tmp_path_factory)
144138
     parsed = parse_file(doc)
@@ -151,8 +145,7 @@ def test_load_for_inference_resolves_each_named_adapter(
151145
     assert k_path.is_dir()
152146
     assert t_path.is_dir()
153147
 
154
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
155
-    caps = doctor().capabilities
148
+    spec, _plan, caps = resolve_spec_and_plan(parsed, accept_license=True)
156149
 
157150
     # Full load exercises the PEFT adapter-load path on both names.
158151
     loaded_k = load_for_inference(store, spec, caps, adapter_name="knowledge")
@@ -171,9 +164,9 @@ def test_export_named_adapter_records_adapter_name(
171164
     _skip_if_tiny_model_unavailable()
172165
 
173166
     try:
174
-        from dlm.export.vendoring import resolve_llama_cpp_paths
167
+        from dlm.export.vendoring import llama_quantize_bin
175168
 
176
-        resolve_llama_cpp_paths()  # probes the submodule; raises if missing
169
+        llama_quantize_bin()  # probes the vendored quantize binary; raises if missing
177170
     except Exception as exc:
178171
         pytest.skip(f"llama.cpp vendoring unavailable: {exc}")
179172
 
tests/integration/train/multi_adapter/test_two_adapters.pymodified
@@ -60,17 +60,12 @@ def test_two_adapters_each_get_their_own_version_history(
6060
     except Exception as exc:
6161
         pytest.skip(f"tiny-model fixture unavailable: {exc}")
6262
 
63
-    from dlm.base_models import resolve as resolve_base_model
6463
     from dlm.doc.parser import parse_file
65
-    from dlm.hardware import doctor
6664
     from dlm.store.manifest import Manifest, load_manifest, save_manifest
6765
     from dlm.store.paths import for_dlm
6866
     from dlm.train.multi_adapter.trainer import run_all
6967
     from tests.fixtures.dlm_factory import make_dlm, prose
70
-
71
-    plan = doctor().plan
72
-    if plan is None:
73
-        pytest.skip("doctor() returned no viable training plan on this host")
68
+    from tests.fixtures.planning import resolve_spec_and_plan
7469
 
7570
     # Unset offline env so weights can download on cold caches.
7671
     for key in ("HF_HUB_OFFLINE", "TRANSFORMERS_OFFLINE", "HF_DATASETS_OFFLINE"):
@@ -108,7 +103,7 @@ def test_two_adapters_each_get_their_own_version_history(
108103
     assert parsed.frontmatter.training.adapters is not None
109104
     assert set(parsed.frontmatter.training.adapters) == {"knowledge", "tone"}
110105
 
111
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
106
+    spec, plan, _caps = resolve_spec_and_plan(parsed, accept_license=True)
112107
     store = for_dlm(parsed.frontmatter.dlm_id)
113108
     store.ensure_layout()
114109
     save_manifest(
tests/integration/train/multi_adapter/test_weighted_merge.pymodified
@@ -56,17 +56,12 @@ def _train_two_adapters(
5656
     except Exception as exc:
5757
         pytest.skip(f"tiny-model fixture unavailable: {exc}")
5858
 
59
-    from dlm.base_models import resolve as resolve_base_model
6059
     from dlm.doc.parser import parse_file
61
-    from dlm.hardware import doctor
6260
     from dlm.store.manifest import Manifest, save_manifest
6361
     from dlm.store.paths import for_dlm
6462
     from dlm.train.multi_adapter.trainer import run_all
6563
     from tests.fixtures.dlm_factory import make_dlm, prose
66
-
67
-    plan = doctor().plan
68
-    if plan is None:
69
-        pytest.skip("doctor() returned no viable training plan on this host")
64
+    from tests.fixtures.planning import resolve_spec_and_plan
7065
 
7166
     for key in ("HF_HUB_OFFLINE", "TRANSFORMERS_OFFLINE", "HF_DATASETS_OFFLINE"):
7267
         os.environ.pop(key, None)
@@ -88,7 +83,7 @@ def _train_two_adapters(
8883
     doc.write_text(raw[:fm_end] + "\n" + _PROSE, encoding="utf-8")
8984
 
9085
     parsed = parse_file(doc)
91
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
86
+    spec, plan, _caps = resolve_spec_and_plan(parsed, accept_license=True)
9287
     store = for_dlm(parsed.frontmatter.dlm_id)
9388
     store.ensure_layout()
9489
     save_manifest(
tests/integration/train/preference/test_dpo_tinymodel.pymodified
@@ -24,11 +24,10 @@ pytestmark = pytest.mark.slow
2424
 
2525
 @pytest.mark.slow
2626
 def test_dpo_phase_writes_second_adapter_version(trained_store) -> None:  # type: ignore[no-untyped-def]
27
-    from dlm.base_models import resolve as resolve_base_model
2827
     from dlm.doc.parser import parse_file
29
-    from dlm.hardware import doctor
3028
     from dlm.store.manifest import load_manifest
3129
     from dlm.train.preference.phase_orchestrator import run_phases
30
+    from tests.fixtures.planning import resolve_spec_and_plan
3231
 
3332
     store = trained_store.store
3433
     dlm_path = trained_store.doc
@@ -37,10 +36,11 @@ def test_dpo_phase_writes_second_adapter_version(trained_store) -> None: # type
3736
     _append_preference_section(dlm_path, terse_preferences)
3837
 
3938
     parsed = parse_file(dlm_path)
40
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
41
-    plan = doctor().plan
42
-    if plan is None:
43
-        pytest.skip("no viable plan on this host — DPO body needs a real trainer")
39
+    spec, plan, capabilities = resolve_spec_and_plan(
40
+        parsed,
41
+        accept_license=True,
42
+        skip_reason="no viable plan on this host — DPO body needs a real trainer",
43
+    )
4444
 
4545
     prior_manifest = load_manifest(store.manifest)
4646
     assert prior_manifest.adapter_version == 1
@@ -51,7 +51,7 @@ def test_dpo_phase_writes_second_adapter_version(trained_store) -> None: # type
5151
         spec,
5252
         plan,
5353
         phase="preference",
54
-        capabilities=doctor().capabilities,
54
+        capabilities=capabilities,
5555
     )
5656
     assert [r.phase for r in results] == ["preference"]
5757
     dpo_result = results[0].result
tests/integration/train/preference/test_orpo_tinymodel.pymodified
@@ -17,12 +17,11 @@ pytestmark = pytest.mark.slow
1717
 
1818
 @pytest.mark.slow
1919
 def test_orpo_phase_writes_second_adapter_version(trained_store) -> None:  # type: ignore[no-untyped-def]
20
-    from dlm.base_models import resolve as resolve_base_model
2120
     from dlm.doc.parser import parse_file
2221
     from dlm.doc.serializer import serialize
23
-    from dlm.hardware import doctor
2422
     from dlm.store.manifest import load_manifest
2523
     from dlm.train.preference.phase_orchestrator import run_phases
24
+    from tests.fixtures.planning import resolve_spec_and_plan
2625
 
2726
     store = trained_store.store
2827
     dlm_path = trained_store.doc
@@ -45,10 +44,11 @@ def test_orpo_phase_writes_second_adapter_version(trained_store) -> None: # typ
4544
     parsed = parse_file(dlm_path)
4645
     assert parsed.frontmatter.training.preference.method == "orpo"
4746
 
48
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
49
-    plan = doctor().plan
50
-    if plan is None:
51
-        pytest.skip("no viable plan on this host — ORPO body needs a real trainer")
47
+    spec, plan, capabilities = resolve_spec_and_plan(
48
+        parsed,
49
+        accept_license=True,
50
+        skip_reason="no viable plan on this host — ORPO body needs a real trainer",
51
+    )
5252
 
5353
     prior_manifest = load_manifest(store.manifest)
5454
     prior_runs = len(prior_manifest.training_runs)
@@ -62,7 +62,7 @@ def test_orpo_phase_writes_second_adapter_version(trained_store) -> None: # typ
6262
         spec,
6363
         plan,
6464
         phase="preference",
65
-        capabilities=doctor().capabilities,
65
+        capabilities=capabilities,
6666
         lock_mode="ignore",
6767
     )
6868
     assert [r.phase for r in results] == ["preference"]
tests/integration/watch/test_watch_retrain.pymodified
@@ -36,13 +36,12 @@ def test_watch_cycle_detects_new_content_and_retrains( # pragma: no cover - slo
3636
     tmp_path: Path,
3737
 ) -> None:
3838
     """`do_one_cycle` on a doc with new content runs the trainer and bumps version."""
39
-    from dlm.base_models import resolve as resolve_base_model
4039
     from dlm.doc.parser import parse_file
41
-    from dlm.hardware import doctor
4240
     from dlm.train.trainer import run as trainer_run
4341
     from dlm.watch.loop import do_one_cycle
42
+    from tests.fixtures.planning import resolve_spec_and_plan
4443
 
45
-    doc_path = trained_store.doc_path
44
+    doc_path = trained_store.doc
4645
     store = trained_store.store
4746
     initial_adapter = store.resolve_current_adapter()
4847
     assert initial_adapter is not None
@@ -50,15 +49,21 @@ def test_watch_cycle_detects_new_content_and_retrains( # pragma: no cover - slo
5049
     # Append a new section to the doc so the ChangeSet sees `new`.
5150
     original = doc_path.read_text(encoding="utf-8")
5251
     doc_path.write_text(
53
-        original + "\n\n## Added by watch test\n\nThis is new content.\n",
52
+        original
53
+        + "\n\n::instruction::\n"
54
+        + "### Q\n"
55
+        + "What changed in the watch test?\n"
56
+        + "### A\n"
57
+        + "A new instruction section was appended.\n",
5458
         encoding="utf-8",
5559
     )
5660
 
5761
     parsed = parse_file(doc_path)
58
-    spec = resolve_base_model(parsed.frontmatter.base_model, accept_license=True)
59
-    plan = doctor(training_config=parsed.frontmatter.training).plan
60
-    if plan is None:
61
-        pytest.skip("no viable plan on this host — watch retrain needs a real trainer")
62
+    spec, plan, _caps = resolve_spec_and_plan(
63
+        parsed,
64
+        accept_license=True,
65
+        skip_reason="no viable plan on this host — watch retrain needs a real trainer",
66
+    )
6267
 
6368
     result = do_one_cycle(
6469
         doc_path=doc_path,