xrtm-train 0.2.2__tar.gz → 0.2.4__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 (39) hide show
  1. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/PKG-INFO +3 -3
  2. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/pyproject.toml +3 -8
  3. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/cli/__init__.py +42 -19
  4. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/version.py +1 -1
  5. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/PKG-INFO +3 -3
  6. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/requires.txt +2 -2
  7. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_cli.py +45 -1
  8. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/LICENSE +0 -0
  9. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/README.md +0 -0
  10. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/setup.cfg +0 -0
  11. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/__init__.py +0 -0
  12. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/core/__init__.py +0 -0
  13. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/core/eval/__init__.py +0 -0
  14. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/core/eval/calibration.py +0 -0
  15. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/__init__.py +0 -0
  16. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/builders/__init__.py +0 -0
  17. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/memory/__init__.py +0 -0
  18. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/memory/learner.py +0 -0
  19. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/optimization/__init__.py +0 -0
  20. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/optimization/compiler.py +0 -0
  21. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/projectors/__init__.py +0 -0
  22. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/kit/trainers/__init__.py +0 -0
  23. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/metrics.py +0 -0
  24. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/providers/__init__.py +0 -0
  25. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/real_e2e.py +0 -0
  26. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/simulation/backtester.py +0 -0
  27. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/simulation/replayer.py +0 -0
  28. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm/train/simulation/runner.py +0 -0
  29. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/SOURCES.txt +0 -0
  30. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/dependency_links.txt +0 -0
  31. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/entry_points.txt +0 -0
  32. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/src/xrtm_train.egg-info/top_level.txt +0 -0
  33. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_backtester.py +0 -0
  34. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_real_benchmark_script.py +0 -0
  35. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_real_e2e.py +0 -0
  36. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_replayer.py +0 -0
  37. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_runner.py +0 -0
  38. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_sample_builder.py +0 -0
  39. {xrtm_train-0.2.2 → xrtm_train-0.2.4}/tests/test_single_node_trainer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xrtm-train
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: The Learning/Optimization layer for XRTM.
5
5
  Author-email: XRTM Team <moy@xrtm.org>
6
6
  License-Expression: Apache-2.0
@@ -14,8 +14,8 @@ Requires-Dist: click>=8.0.0
14
14
  Requires-Dist: rich>=13.0.0
15
15
  Requires-Dist: pyyaml>=6.0.0
16
16
  Requires-Dist: xrtm-data>=0.2.2
17
- Requires-Dist: xrtm-eval>=0.2.2
18
- Requires-Dist: xrtm-forecast>=0.6.2
17
+ Requires-Dist: xrtm-eval>=0.2.3
18
+ Requires-Dist: xrtm-forecast>=0.6.3
19
19
  Provides-Extra: dev
20
20
  Requires-Dist: pytest>=7.0.0; extra == "dev"
21
21
  Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xrtm-train"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  description = "The Learning/Optimization layer for XRTM."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -20,8 +20,8 @@ dependencies = [
20
20
  "rich>=13.0.0",
21
21
  "pyyaml>=6.0.0",
22
22
  "xrtm-data>=0.2.2",
23
- "xrtm-eval>=0.2.2",
24
- "xrtm-forecast>=0.6.2",
23
+ "xrtm-eval>=0.2.3",
24
+ "xrtm-forecast>=0.6.3",
25
25
  ]
26
26
 
27
27
  [project.optional-dependencies]
@@ -46,11 +46,6 @@ xrtm-train = "xrtm.train.cli:main"
46
46
  package-dir = {"" = "src"}
47
47
  packages = {find = {where = ["src"], include = ["xrtm*"], namespaces = true}}
48
48
 
49
- [tool.uv.sources]
50
- xrtm-data = { workspace = true }
51
- xrtm-eval = { workspace = true }
52
- xrtm-forecast = { workspace = true }
53
-
54
49
  [tool.pytest.ini_options]
55
50
  testpaths = ["tests"]
56
51
  asyncio_mode = "strict"
@@ -33,6 +33,7 @@ Example:
33
33
  """
34
34
 
35
35
  import json
36
+ from copy import deepcopy
36
37
  from datetime import datetime, timedelta, timezone
37
38
  from pathlib import Path
38
39
  from typing import Any, Dict, Optional
@@ -86,22 +87,29 @@ DEFAULT_CONFIG = {
86
87
 
87
88
  def load_config(config_path: Optional[str]) -> Dict[str, Any]:
88
89
  r"""Load configuration from YAML file, merged with defaults."""
89
- config: Dict[str, Any] = DEFAULT_CONFIG.copy()
90
+ config: Dict[str, Any] = deepcopy(DEFAULT_CONFIG)
90
91
 
91
92
  if config_path:
92
93
  with open(config_path) as f:
93
- user_config = yaml.safe_load(f)
94
+ user_config = yaml.safe_load(f) or {}
95
+ if not isinstance(user_config, dict):
96
+ raise ValueError("Training config must be a YAML mapping")
94
97
 
95
- # Deep merge
96
- for key, value in user_config.items():
97
- if isinstance(value, dict) and key in config and isinstance(config[key], dict):
98
- config[key].update(value)
99
- else:
100
- config[key] = value
98
+ _deep_merge(config, user_config)
101
99
 
102
100
  return config
103
101
 
104
102
 
103
+ def _deep_merge(base: Dict[str, Any], overrides: Dict[str, Any]) -> Dict[str, Any]:
104
+ r"""Recursively merge overrides into base."""
105
+ for key, value in overrides.items():
106
+ if isinstance(value, dict) and isinstance(base.get(key), dict):
107
+ _deep_merge(base[key], value)
108
+ else:
109
+ base[key] = value
110
+ return base
111
+
112
+
105
113
  # =============================================================================
106
114
  # CLI Group
107
115
  # =============================================================================
@@ -228,6 +236,7 @@ def prepare(
228
236
  @click.option("--epochs", type=int, default=None, help="Number of epochs (overrides config)")
229
237
  @click.option("--batch-size", type=int, default=None, help="Batch size (overrides config)")
230
238
  @click.option("--dry-run", is_flag=True, help="Validate config without training")
239
+ @click.option("--allow-mock", is_flag=True, help="Run the legacy mock training loop for demos only.")
231
240
  def train(
232
241
  config: Optional[str],
233
242
  data_dir: str,
@@ -238,16 +247,16 @@ def train(
238
247
  epochs: Optional[int],
239
248
  batch_size: Optional[int],
240
249
  dry_run: bool,
250
+ allow_mock: bool,
241
251
  ):
242
252
  r"""
243
- Train a forecasting model with prior injection.
253
+ Validate training configuration for prior-injected models.
244
254
 
245
- Supports full fine-tuning and LoRA. Uses Qwen 3 family by default.
246
- Progress and checkpoints are saved automatically.
255
+ Full model training is not wired into the product path yet. Use --dry-run
256
+ to validate configuration or --allow-mock for the legacy demo loop.
247
257
 
248
258
  Example:
249
- xrtm-train train -c config.yaml -d samples/ -o models/
250
- xrtm-train train -d samples/ -m Qwen/Qwen2.5-1.5B --epochs 3
259
+ xrtm-train train -c config.yaml -d samples/ --dry-run
251
260
  """
252
261
  # Load and merge config
253
262
  cfg = load_config(config)
@@ -290,6 +299,12 @@ def train(
290
299
  console.print("\n[yellow]Dry run complete. No training performed.[/yellow]")
291
300
  return
292
301
 
302
+ if not allow_mock:
303
+ raise click.ClickException(
304
+ "Real model training is not implemented in this CLI yet. Use --dry-run to validate config, "
305
+ "or pass --allow-mock to run the legacy demo loop intentionally."
306
+ )
307
+
293
308
  # Check for GPU dependencies
294
309
  try:
295
310
  import torch
@@ -393,14 +408,16 @@ def _run_training(cfg: dict, data_dir: str, output: str, resume: Optional[str])
393
408
  @click.option("--model", "-m", required=True, type=click.Path(exists=True), help="Model directory")
394
409
  @click.option("--data", "-d", "data_path", required=True, type=click.Path(exists=True), help="Test data file")
395
410
  @click.option("--output", "-o", type=click.Path(), help="Output file for results (.json)")
396
- def eval(model: str, data_path: str, output: Optional[str]):
411
+ @click.option("--allow-mock", is_flag=True, help="Emit the legacy mock metrics for demos only.")
412
+ def eval(model: str, data_path: str, output: Optional[str], allow_mock: bool):
397
413
  r"""
398
- Evaluate a trained model on test data.
414
+ Validate evaluation inputs for a trained model.
399
415
 
400
- Computes calibration metrics, Brier scores, and generates evaluation report.
416
+ Full model evaluation is not wired into the product path yet. Use --allow-mock
417
+ only when intentionally exercising the legacy demo metrics.
401
418
 
402
419
  Example:
403
- xrtm-train eval -m models/final -d samples/test.jsonl
420
+ xrtm-train eval -m models/final -d samples/test.jsonl --allow-mock
404
421
  """
405
422
  console.print(Panel(
406
423
  f"[bold blue]Evaluating Model[/bold blue]\n"
@@ -423,8 +440,14 @@ def eval(model: str, data_path: str, output: Optional[str]):
423
440
  test_samples = _load_jsonl(Path(data_path))
424
441
  console.print(f"\nLoaded {len(test_samples)} test samples")
425
442
 
443
+ if not allow_mock:
444
+ raise click.ClickException(
445
+ "Real model evaluation is not implemented in this CLI yet. Pass --allow-mock to emit "
446
+ "the legacy demo metrics intentionally."
447
+ )
448
+
426
449
  # Mock evaluation
427
- console.print("\n[yellow]⚠ Full evaluation pending. Using mock metrics.[/yellow]")
450
+ console.print("\n[yellow]⚠ Using legacy mock metrics because --allow-mock was provided.[/yellow]")
428
451
 
429
452
  metrics = {
430
453
  "brier_score": 0.15,
@@ -469,7 +492,7 @@ def init_config(output: str, model: str, strategy: str):
469
492
  Example:
470
493
  xrtm-train init-config -o config.yaml -m Qwen/Qwen2.5-7B
471
494
  """
472
- config: Dict[str, Any] = DEFAULT_CONFIG.copy()
495
+ config: Dict[str, Any] = deepcopy(DEFAULT_CONFIG)
473
496
  config["model"]["name"] = model # type: ignore[index]
474
497
  config["model"]["strategy"] = strategy # type: ignore[index]
475
498
 
@@ -21,7 +21,7 @@ This module provides the single source of truth for the package version.
21
21
 
22
22
  __all__ = ["__version__", "__author__", "__contact__", "__license__", "__copyright__"]
23
23
 
24
- __version__ = "0.2.2"
24
+ __version__ = "0.2.4"
25
25
  __author__ = "XRTM Team"
26
26
  __contact__ = "moy@xrtm.org"
27
27
  __license__ = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xrtm-train
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: The Learning/Optimization layer for XRTM.
5
5
  Author-email: XRTM Team <moy@xrtm.org>
6
6
  License-Expression: Apache-2.0
@@ -14,8 +14,8 @@ Requires-Dist: click>=8.0.0
14
14
  Requires-Dist: rich>=13.0.0
15
15
  Requires-Dist: pyyaml>=6.0.0
16
16
  Requires-Dist: xrtm-data>=0.2.2
17
- Requires-Dist: xrtm-eval>=0.2.2
18
- Requires-Dist: xrtm-forecast>=0.6.2
17
+ Requires-Dist: xrtm-eval>=0.2.3
18
+ Requires-Dist: xrtm-forecast>=0.6.3
19
19
  Provides-Extra: dev
20
20
  Requires-Dist: pytest>=7.0.0; extra == "dev"
21
21
  Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
@@ -5,8 +5,8 @@ click>=8.0.0
5
5
  rich>=13.0.0
6
6
  pyyaml>=6.0.0
7
7
  xrtm-data>=0.2.2
8
- xrtm-eval>=0.2.2
9
- xrtm-forecast>=0.6.2
8
+ xrtm-eval>=0.2.3
9
+ xrtm-forecast>=0.6.3
10
10
 
11
11
  [dev]
12
12
  pytest>=7.0.0
@@ -18,7 +18,7 @@ from pathlib import Path
18
18
 
19
19
  from click.testing import CliRunner
20
20
 
21
- from xrtm.train.cli import main
21
+ from xrtm.train.cli import DEFAULT_CONFIG, load_config, main
22
22
 
23
23
 
24
24
  def test_data_prepare_builds_jsonl_samples() -> None:
@@ -102,3 +102,47 @@ def test_data_prepare_can_derive_news_and_priors_from_trade_records() -> None:
102
102
  assert rows[0]["current_news"] == "Market probability update: 0.400"
103
103
  assert rows[0]["prior_alpha"] == 4.0
104
104
  assert rows[0]["target_alpha"] == 6.0
105
+
106
+
107
+ def test_load_config_deep_merge_does_not_mutate_defaults() -> None:
108
+ runner = CliRunner()
109
+
110
+ with runner.isolated_filesystem():
111
+ config_path = Path("config.yaml")
112
+ config_path.write_text("model:\n name: custom-model\n")
113
+
114
+ config = load_config(str(config_path))
115
+
116
+ assert config["model"]["name"] == "custom-model"
117
+ assert config["model"]["family"] == DEFAULT_CONFIG["model"]["family"]
118
+ assert DEFAULT_CONFIG["model"]["name"] == "Qwen/Qwen2.5-0.5B"
119
+
120
+
121
+ def test_train_command_does_not_run_mock_training_by_default() -> None:
122
+ runner = CliRunner()
123
+
124
+ with runner.isolated_filesystem():
125
+ samples = Path("samples")
126
+ samples.mkdir()
127
+ (samples / "train.jsonl").write_text("{}\n")
128
+ (samples / "val.jsonl").write_text("{}\n")
129
+
130
+ result = runner.invoke(main, ["train", "--data", str(samples)])
131
+
132
+ assert result.exit_code != 0
133
+ assert "Real model training is not implemented" in result.output
134
+
135
+
136
+ def test_eval_command_does_not_emit_mock_metrics_by_default() -> None:
137
+ runner = CliRunner()
138
+
139
+ with runner.isolated_filesystem():
140
+ model = Path("model")
141
+ model.mkdir()
142
+ data = Path("test.jsonl")
143
+ data.write_text("{}\n")
144
+
145
+ result = runner.invoke(main, ["eval", "--model", str(model), "--data", str(data)])
146
+
147
+ assert result.exit_code != 0
148
+ assert "Real model evaluation is not implemented" in result.output
File without changes
File without changes
File without changes