hud-python 0.4.45__py3-none-any.whl → 0.5.1__py3-none-any.whl

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 (274) hide show
  1. hud/__init__.py +27 -7
  2. hud/agents/__init__.py +11 -5
  3. hud/agents/base.py +220 -500
  4. hud/agents/claude.py +200 -240
  5. hud/agents/gemini.py +275 -0
  6. hud/agents/gemini_cua.py +335 -0
  7. hud/agents/grounded_openai.py +98 -100
  8. hud/agents/misc/integration_test_agent.py +51 -20
  9. hud/agents/misc/response_agent.py +41 -36
  10. hud/agents/openai.py +291 -292
  11. hud/agents/{openai_chat_generic.py → openai_chat.py} +80 -34
  12. hud/agents/operator.py +211 -0
  13. hud/agents/tests/conftest.py +133 -0
  14. hud/agents/tests/test_base.py +300 -622
  15. hud/agents/tests/test_base_runtime.py +233 -0
  16. hud/agents/tests/test_claude.py +379 -210
  17. hud/agents/tests/test_client.py +9 -10
  18. hud/agents/tests/test_gemini.py +369 -0
  19. hud/agents/tests/test_grounded_openai_agent.py +65 -50
  20. hud/agents/tests/test_openai.py +376 -140
  21. hud/agents/tests/test_operator.py +362 -0
  22. hud/agents/tests/test_run_eval.py +179 -0
  23. hud/cli/__init__.py +461 -545
  24. hud/cli/analyze.py +43 -5
  25. hud/cli/build.py +664 -110
  26. hud/cli/debug.py +8 -5
  27. hud/cli/dev.py +882 -734
  28. hud/cli/eval.py +782 -668
  29. hud/cli/flows/dev.py +167 -0
  30. hud/cli/flows/init.py +191 -0
  31. hud/cli/flows/tasks.py +153 -56
  32. hud/cli/flows/templates.py +151 -0
  33. hud/cli/flows/tests/__init__.py +1 -0
  34. hud/cli/flows/tests/test_dev.py +126 -0
  35. hud/cli/init.py +60 -58
  36. hud/cli/push.py +29 -11
  37. hud/cli/rft.py +311 -0
  38. hud/cli/rft_status.py +145 -0
  39. hud/cli/tests/test_analyze.py +5 -5
  40. hud/cli/tests/test_analyze_metadata.py +3 -2
  41. hud/cli/tests/test_analyze_module.py +120 -0
  42. hud/cli/tests/test_build.py +108 -6
  43. hud/cli/tests/test_build_failure.py +41 -0
  44. hud/cli/tests/test_build_module.py +50 -0
  45. hud/cli/tests/test_cli_init.py +6 -1
  46. hud/cli/tests/test_cli_more_wrappers.py +30 -0
  47. hud/cli/tests/test_cli_root.py +140 -0
  48. hud/cli/tests/test_convert.py +361 -0
  49. hud/cli/tests/test_debug.py +12 -10
  50. hud/cli/tests/test_dev.py +197 -0
  51. hud/cli/tests/test_eval.py +251 -0
  52. hud/cli/tests/test_eval_bedrock.py +51 -0
  53. hud/cli/tests/test_init.py +124 -0
  54. hud/cli/tests/test_main_module.py +11 -5
  55. hud/cli/tests/test_mcp_server.py +12 -100
  56. hud/cli/tests/test_push_happy.py +74 -0
  57. hud/cli/tests/test_push_wrapper.py +23 -0
  58. hud/cli/tests/test_registry.py +1 -1
  59. hud/cli/tests/test_utils.py +1 -1
  60. hud/cli/{rl → utils}/celebrate.py +14 -12
  61. hud/cli/utils/config.py +18 -1
  62. hud/cli/utils/docker.py +130 -4
  63. hud/cli/utils/env_check.py +9 -9
  64. hud/cli/utils/git.py +136 -0
  65. hud/cli/utils/interactive.py +39 -5
  66. hud/cli/utils/metadata.py +69 -0
  67. hud/cli/utils/runner.py +1 -1
  68. hud/cli/utils/server.py +2 -2
  69. hud/cli/utils/source_hash.py +3 -3
  70. hud/cli/utils/tasks.py +4 -1
  71. hud/cli/utils/tests/__init__.py +0 -0
  72. hud/cli/utils/tests/test_config.py +58 -0
  73. hud/cli/utils/tests/test_docker.py +93 -0
  74. hud/cli/utils/tests/test_docker_hints.py +71 -0
  75. hud/cli/utils/tests/test_env_check.py +74 -0
  76. hud/cli/utils/tests/test_environment.py +42 -0
  77. hud/cli/utils/tests/test_git.py +142 -0
  78. hud/cli/utils/tests/test_interactive_module.py +60 -0
  79. hud/cli/utils/tests/test_local_runner.py +50 -0
  80. hud/cli/utils/tests/test_logging_utils.py +23 -0
  81. hud/cli/utils/tests/test_metadata.py +49 -0
  82. hud/cli/utils/tests/test_package_runner.py +35 -0
  83. hud/cli/utils/tests/test_registry_utils.py +49 -0
  84. hud/cli/utils/tests/test_remote_runner.py +25 -0
  85. hud/cli/utils/tests/test_runner_modules.py +52 -0
  86. hud/cli/utils/tests/test_source_hash.py +36 -0
  87. hud/cli/utils/tests/test_tasks.py +80 -0
  88. hud/cli/utils/version_check.py +258 -0
  89. hud/cli/{rl → utils}/viewer.py +2 -2
  90. hud/clients/README.md +12 -11
  91. hud/clients/__init__.py +4 -3
  92. hud/clients/base.py +166 -26
  93. hud/clients/environment.py +51 -0
  94. hud/clients/fastmcp.py +13 -6
  95. hud/clients/mcp_use.py +40 -15
  96. hud/clients/tests/test_analyze_scenarios.py +206 -0
  97. hud/clients/tests/test_protocol.py +9 -3
  98. hud/datasets/__init__.py +23 -20
  99. hud/datasets/loader.py +327 -0
  100. hud/datasets/runner.py +192 -105
  101. hud/datasets/tests/__init__.py +0 -0
  102. hud/datasets/tests/test_loader.py +221 -0
  103. hud/datasets/tests/test_utils.py +315 -0
  104. hud/datasets/utils.py +270 -90
  105. hud/environment/__init__.py +50 -0
  106. hud/environment/connection.py +206 -0
  107. hud/environment/connectors/__init__.py +33 -0
  108. hud/environment/connectors/base.py +68 -0
  109. hud/environment/connectors/local.py +177 -0
  110. hud/environment/connectors/mcp_config.py +109 -0
  111. hud/environment/connectors/openai.py +101 -0
  112. hud/environment/connectors/remote.py +172 -0
  113. hud/environment/environment.py +694 -0
  114. hud/environment/integrations/__init__.py +45 -0
  115. hud/environment/integrations/adk.py +67 -0
  116. hud/environment/integrations/anthropic.py +196 -0
  117. hud/environment/integrations/gemini.py +92 -0
  118. hud/environment/integrations/langchain.py +82 -0
  119. hud/environment/integrations/llamaindex.py +68 -0
  120. hud/environment/integrations/openai.py +238 -0
  121. hud/environment/mock.py +306 -0
  122. hud/environment/router.py +112 -0
  123. hud/environment/scenarios.py +493 -0
  124. hud/environment/tests/__init__.py +1 -0
  125. hud/environment/tests/test_connection.py +317 -0
  126. hud/environment/tests/test_connectors.py +218 -0
  127. hud/environment/tests/test_environment.py +161 -0
  128. hud/environment/tests/test_integrations.py +257 -0
  129. hud/environment/tests/test_local_connectors.py +201 -0
  130. hud/environment/tests/test_scenarios.py +280 -0
  131. hud/environment/tests/test_tools.py +208 -0
  132. hud/environment/types.py +23 -0
  133. hud/environment/utils/__init__.py +35 -0
  134. hud/environment/utils/formats.py +215 -0
  135. hud/environment/utils/schema.py +171 -0
  136. hud/environment/utils/tool_wrappers.py +113 -0
  137. hud/eval/__init__.py +67 -0
  138. hud/eval/context.py +674 -0
  139. hud/eval/display.py +299 -0
  140. hud/eval/instrument.py +185 -0
  141. hud/eval/manager.py +466 -0
  142. hud/eval/parallel.py +268 -0
  143. hud/eval/task.py +340 -0
  144. hud/eval/tests/__init__.py +1 -0
  145. hud/eval/tests/test_context.py +178 -0
  146. hud/eval/tests/test_eval.py +210 -0
  147. hud/eval/tests/test_manager.py +152 -0
  148. hud/eval/tests/test_parallel.py +168 -0
  149. hud/eval/tests/test_task.py +145 -0
  150. hud/eval/types.py +63 -0
  151. hud/eval/utils.py +183 -0
  152. hud/patches/__init__.py +19 -0
  153. hud/patches/mcp_patches.py +151 -0
  154. hud/patches/warnings.py +54 -0
  155. hud/samples/browser.py +4 -4
  156. hud/server/__init__.py +2 -1
  157. hud/server/low_level.py +2 -1
  158. hud/server/router.py +164 -0
  159. hud/server/server.py +567 -80
  160. hud/server/tests/test_mcp_server_integration.py +11 -11
  161. hud/server/tests/test_mcp_server_more.py +1 -1
  162. hud/server/tests/test_server_extra.py +2 -0
  163. hud/settings.py +45 -3
  164. hud/shared/exceptions.py +36 -10
  165. hud/shared/hints.py +26 -1
  166. hud/shared/requests.py +15 -3
  167. hud/shared/tests/test_exceptions.py +40 -31
  168. hud/shared/tests/test_hints.py +167 -0
  169. hud/telemetry/__init__.py +20 -19
  170. hud/telemetry/exporter.py +201 -0
  171. hud/telemetry/instrument.py +158 -253
  172. hud/telemetry/tests/test_eval_telemetry.py +356 -0
  173. hud/telemetry/tests/test_exporter.py +258 -0
  174. hud/telemetry/tests/test_instrument.py +401 -0
  175. hud/tools/__init__.py +16 -2
  176. hud/tools/apply_patch.py +639 -0
  177. hud/tools/base.py +54 -4
  178. hud/tools/bash.py +2 -2
  179. hud/tools/computer/__init__.py +4 -0
  180. hud/tools/computer/anthropic.py +2 -2
  181. hud/tools/computer/gemini.py +385 -0
  182. hud/tools/computer/hud.py +23 -6
  183. hud/tools/computer/openai.py +20 -21
  184. hud/tools/computer/qwen.py +434 -0
  185. hud/tools/computer/settings.py +37 -0
  186. hud/tools/edit.py +3 -7
  187. hud/tools/executors/base.py +4 -2
  188. hud/tools/executors/pyautogui.py +1 -1
  189. hud/tools/grounding/grounded_tool.py +13 -18
  190. hud/tools/grounding/grounder.py +10 -31
  191. hud/tools/grounding/tests/test_grounded_tool.py +26 -44
  192. hud/tools/jupyter.py +330 -0
  193. hud/tools/playwright.py +18 -3
  194. hud/tools/shell.py +308 -0
  195. hud/tools/tests/test_apply_patch.py +718 -0
  196. hud/tools/tests/test_computer.py +4 -9
  197. hud/tools/tests/test_computer_actions.py +24 -2
  198. hud/tools/tests/test_jupyter_tool.py +181 -0
  199. hud/tools/tests/test_shell.py +596 -0
  200. hud/tools/tests/test_submit.py +85 -0
  201. hud/tools/tests/test_types.py +193 -0
  202. hud/tools/types.py +21 -1
  203. hud/types.py +167 -57
  204. hud/utils/__init__.py +2 -0
  205. hud/utils/env.py +67 -0
  206. hud/utils/hud_console.py +61 -3
  207. hud/utils/mcp.py +15 -58
  208. hud/utils/strict_schema.py +162 -0
  209. hud/utils/tests/test_init.py +1 -2
  210. hud/utils/tests/test_mcp.py +1 -28
  211. hud/utils/tests/test_pretty_errors.py +186 -0
  212. hud/utils/tests/test_tool_shorthand.py +154 -0
  213. hud/utils/tests/test_version.py +1 -1
  214. hud/utils/types.py +20 -0
  215. hud/version.py +1 -1
  216. hud_python-0.5.1.dist-info/METADATA +264 -0
  217. hud_python-0.5.1.dist-info/RECORD +299 -0
  218. {hud_python-0.4.45.dist-info → hud_python-0.5.1.dist-info}/WHEEL +1 -1
  219. hud/agents/langchain.py +0 -261
  220. hud/agents/lite_llm.py +0 -72
  221. hud/cli/rl/__init__.py +0 -180
  222. hud/cli/rl/config.py +0 -101
  223. hud/cli/rl/display.py +0 -133
  224. hud/cli/rl/gpu.py +0 -63
  225. hud/cli/rl/gpu_utils.py +0 -321
  226. hud/cli/rl/local_runner.py +0 -595
  227. hud/cli/rl/presets.py +0 -96
  228. hud/cli/rl/remote_runner.py +0 -463
  229. hud/cli/rl/rl_api.py +0 -150
  230. hud/cli/rl/vllm.py +0 -177
  231. hud/cli/rl/wait_utils.py +0 -89
  232. hud/datasets/parallel.py +0 -687
  233. hud/misc/__init__.py +0 -1
  234. hud/misc/claude_plays_pokemon.py +0 -292
  235. hud/otel/__init__.py +0 -35
  236. hud/otel/collector.py +0 -142
  237. hud/otel/config.py +0 -181
  238. hud/otel/context.py +0 -570
  239. hud/otel/exporters.py +0 -369
  240. hud/otel/instrumentation.py +0 -135
  241. hud/otel/processors.py +0 -121
  242. hud/otel/tests/__init__.py +0 -1
  243. hud/otel/tests/test_processors.py +0 -197
  244. hud/rl/README.md +0 -30
  245. hud/rl/__init__.py +0 -1
  246. hud/rl/actor.py +0 -176
  247. hud/rl/buffer.py +0 -405
  248. hud/rl/chat_template.jinja +0 -101
  249. hud/rl/config.py +0 -192
  250. hud/rl/distributed.py +0 -132
  251. hud/rl/learner.py +0 -637
  252. hud/rl/tests/__init__.py +0 -1
  253. hud/rl/tests/test_learner.py +0 -186
  254. hud/rl/train.py +0 -382
  255. hud/rl/types.py +0 -101
  256. hud/rl/utils/start_vllm_server.sh +0 -30
  257. hud/rl/utils.py +0 -524
  258. hud/rl/vllm_adapter.py +0 -143
  259. hud/telemetry/job.py +0 -352
  260. hud/telemetry/replay.py +0 -74
  261. hud/telemetry/tests/test_replay.py +0 -40
  262. hud/telemetry/tests/test_trace.py +0 -63
  263. hud/telemetry/trace.py +0 -158
  264. hud/utils/agent_factories.py +0 -86
  265. hud/utils/async_utils.py +0 -65
  266. hud/utils/group_eval.py +0 -223
  267. hud/utils/progress.py +0 -149
  268. hud/utils/tasks.py +0 -127
  269. hud/utils/tests/test_async_utils.py +0 -173
  270. hud/utils/tests/test_progress.py +0 -261
  271. hud_python-0.4.45.dist-info/METADATA +0 -552
  272. hud_python-0.4.45.dist-info/RECORD +0 -228
  273. {hud_python-0.4.45.dist-info → hud_python-0.5.1.dist-info}/entry_points.txt +0 -0
  274. {hud_python-0.4.45.dist-info → hud_python-0.5.1.dist-info}/licenses/LICENSE +0 -0
hud/cli/rl/__init__.py DELETED
@@ -1,180 +0,0 @@
1
- """RL training command for HUD CLI."""
2
-
3
- from __future__ import annotations
4
-
5
- import logging
6
- import os
7
- from typing import TYPE_CHECKING
8
-
9
- import typer
10
- from rich.console import Console
11
-
12
- from hud.cli.utils.tasks import find_tasks_file
13
- from hud.utils.hud_console import hud_console
14
-
15
- console = Console()
16
-
17
- if TYPE_CHECKING:
18
- from pathlib import Path
19
-
20
-
21
- def rl_command(
22
- tasks_file: str | None = typer.Argument(
23
- None,
24
- help="Path to tasks file (JSON/JSONL) or HuggingFace dataset name",
25
- ),
26
- model: str | None = typer.Argument(
27
- None,
28
- help="Model to train from https://hud.so/models (default: interactive selection)",
29
- ),
30
- config_file: Path | None = typer.Option( # noqa: B008
31
- None,
32
- "--config",
33
- "-c",
34
- help="Path to existing configuration file",
35
- ),
36
- output_dir: str = typer.Option(
37
- "/checkpoints",
38
- "--output-dir",
39
- "-o",
40
- help="Output directory for checkpoints",
41
- ),
42
- restart: bool = typer.Option(
43
- False,
44
- "--restart",
45
- help="Restart the vLLM server before training",
46
- ),
47
- verbose: bool = typer.Option(
48
- False,
49
- "--verbose",
50
- "-v",
51
- help="Enable verbose output",
52
- ),
53
- # DDP options
54
- no_ddp: bool = typer.Option(
55
- False,
56
- "--no-ddp",
57
- help="Disable DDP even with multiple GPUs",
58
- ),
59
- ddp_gpus: str | None = typer.Option(
60
- None,
61
- "--ddp-gpus",
62
- help="Specific GPUs for DDP (e.g., '0,1,2,3')",
63
- ),
64
- vllm_gpu: int | None = typer.Option(
65
- None,
66
- "--vllm-gpu",
67
- help="Specific GPU for vLLM server",
68
- ),
69
- # Execution mode options
70
- local: bool = typer.Option(
71
- False,
72
- "--local",
73
- help="Run training locally instead of using remote API server",
74
- ),
75
- yes: bool = typer.Option(
76
- False,
77
- "--yes",
78
- "-y",
79
- help="Auto-accept all prompts and use defaults (lazy mode)",
80
- ),
81
- vllm_gpu_count: int = typer.Option(
82
- None,
83
- "--vllm-gpu-count",
84
- help="Number of GPUs for vLLM server",
85
- ),
86
- skip_vllm_startup: bool = typer.Option(
87
- False,
88
- "--skip-vllm-startup",
89
- help="Skip local vLLM server startup (for internal use)",
90
- ),
91
- ) -> None:
92
- """Run GRPO reinforcement learning training on tasks."""
93
- # Configure logging based on verbose flag BEFORE any output
94
- if not verbose:
95
- os.environ["HUD_LOG_LEVEL"] = "WARNING"
96
- logging.basicConfig(level=logging.WARNING, force=True)
97
- root_logger = logging.getLogger()
98
- root_logger.setLevel(logging.WARNING)
99
-
100
- # Suppress INFO logs from various components
101
- for logger_name in [
102
- "httpx",
103
- "hud.agents",
104
- "hud.utils.design",
105
- "hud",
106
- "asyncio",
107
- "transformers",
108
- ]:
109
- logging.getLogger(logger_name).setLevel(logging.WARNING)
110
- logging.getLogger("hud.agents.base").setLevel(logging.WARNING)
111
- else:
112
- logging.basicConfig(level=logging.INFO)
113
-
114
- hud_console.header("HUD RL Training")
115
-
116
- # Determine execution mode
117
- use_remote = not local
118
-
119
- if not tasks_file:
120
- tasks_file = find_tasks_file(tasks_file)
121
- if not tasks_file:
122
- hud_console.warning("No tasks file found in current directory")
123
- hud_console.hint(
124
- "Download a HF dataset using `hud get <dataset_name>` (e.g., `hud get hud-evals/2048-basic`)" # noqa: E501
125
- )
126
- hud_console.hint("or create a tasks file manually.")
127
- raise typer.Exit(1)
128
-
129
- # If user ran bare `hud rl`, guide them through remote task conversion flow
130
- # before proceeding (remote only)
131
- if use_remote:
132
- try:
133
- from hud.cli.flows.tasks import convert_tasks_to_remote
134
-
135
- console.print("[cyan]Preparing remote training tasks...[/cyan]")
136
- tasks_file = convert_tasks_to_remote(tasks_file)
137
- except typer.Exit:
138
- raise
139
- except Exception as e:
140
- hud_console.warning(f"[red]Tasks file is not valid for remote training: {e!s}[/red]")
141
- hud_console.hint("Either ensure the tasks file has remote urls")
142
- hud_console.hint("Or rerun `hud rl` within an environment directory")
143
- raise typer.Exit(1) from e
144
-
145
- try:
146
- from .remote_runner import run_remote_training
147
-
148
- run_remote_training(
149
- tasks_file=tasks_file,
150
- model=model,
151
- config_file=config_file,
152
- output_dir=output_dir,
153
- vllm_gpu_count=vllm_gpu_count,
154
- yes=yes,
155
- )
156
- return
157
- except Exception as e:
158
- console.print(f"[red]❌ Remote training failed: {e!s}[/red]")
159
- raise typer.Exit(1) from e
160
-
161
- # Local execution flow delegated to local_runner (imports heavy deps lazily)
162
- from .local_runner import run_local_training
163
-
164
- run_local_training(
165
- tasks_file=tasks_file,
166
- model=model,
167
- config_file=config_file,
168
- output_dir=output_dir,
169
- yes=yes,
170
- restart=restart,
171
- verbose=verbose,
172
- no_ddp=no_ddp,
173
- ddp_gpus=ddp_gpus,
174
- vllm_gpu=vllm_gpu,
175
- skip_vllm_startup=skip_vllm_startup,
176
- )
177
-
178
-
179
- # Export the command function
180
- __all__ = ["rl_command"]
hud/cli/rl/config.py DELETED
@@ -1,101 +0,0 @@
1
- """Configuration generation and management for RL training."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- from typing import TYPE_CHECKING, Any
7
-
8
- from rich.console import Console
9
-
10
- from hud.rl.config import Config, validate_vl_model
11
- from hud.utils.hud_console import hud_console
12
-
13
- from .display import display_preset_table
14
- from .presets import estimate_memory_usage
15
-
16
- if TYPE_CHECKING:
17
- from pathlib import Path
18
- console = Console()
19
-
20
-
21
- def generate_config_interactive(
22
- model_name: str,
23
- presets: list[dict[str, Any]],
24
- yes: bool = False,
25
- ) -> tuple[Config, float]:
26
- """Generate RL training configuration interactively."""
27
- # Validate model is a VL model
28
- validate_vl_model(model_name)
29
-
30
- # Display preset options
31
- if not yes:
32
- display_preset_table(presets, 80.0) # Assuming A100 80GB
33
-
34
- # Let user select preset
35
- if yes:
36
- # Use default preset (Balanced if available, otherwise first)
37
- preset_choice = 1 if len(presets) > 1 else 0
38
- selected_preset = presets[preset_choice]
39
- hud_console.info(f"Auto-selecting preset: {selected_preset['name']} (--yes mode)")
40
- else:
41
- preset_choice = hud_console.select(
42
- "Select a training configuration preset:",
43
- choices=[{"name": p["name"], "value": i} for i, p in enumerate(presets)],
44
- default=1 if len(presets) > 1 else 0, # Default to "Balanced" if available
45
- )
46
- selected_preset = presets[preset_choice] # type: ignore
47
-
48
- # Use preset values directly
49
- max_steps_per_episode = selected_preset["max_steps_per_episode"]
50
-
51
- # Calculate memory estimate
52
- max_pixels = 256 * 28 * 28
53
- estimated_memory = estimate_memory_usage(
54
- selected_preset["mini_batch_size"],
55
- max_steps_per_episode,
56
- selected_preset["max_new_tokens"],
57
- max_pixels,
58
- )
59
-
60
- config_adds = {
61
- "actor": {
62
- "max_new_tokens": selected_preset["max_new_tokens"],
63
- "max_parallel_episodes": selected_preset["batch_size"],
64
- "max_steps_per_episode": selected_preset["max_steps_per_episode"],
65
- "force_tool_choice": True,
66
- },
67
- "training": {
68
- "mini_batch_size": selected_preset["mini_batch_size"],
69
- "group_size": selected_preset["group_size"],
70
- "batch_size": selected_preset["batch_size"],
71
- "lr": selected_preset["lr"],
72
- "epochs": selected_preset["epochs"],
73
- },
74
- "verbose": True,
75
- }
76
-
77
- # Create config
78
- config = Config.from_dict(config_adds)
79
-
80
- return config, estimated_memory
81
-
82
-
83
- def save_config(config: Config, path: Path) -> None:
84
- """Save configuration to a JSON file."""
85
- config_dict = config.to_dict()
86
-
87
- with open(path, "w", encoding="utf-8") as f:
88
- json.dump(config_dict, f, indent=2)
89
- f.write("\n") # Add newline at end of file
90
-
91
- if not path.name.startswith("."): # Don't show message for temp files
92
- console.print(f"[green]✅ Configuration saved to {path}[/green]")
93
-
94
-
95
- def load_config(path: Path) -> Config:
96
- """Load configuration from a JSON file."""
97
- with open(path, encoding="utf-8") as f:
98
- data = json.load(f)
99
-
100
- # Use Config.from_dict which handles missing fields gracefully
101
- return Config.from_dict(data)
hud/cli/rl/display.py DELETED
@@ -1,133 +0,0 @@
1
- """Display utilities for RL training configuration."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import TYPE_CHECKING, Any
6
-
7
- from rich.console import Console
8
- from rich.table import Table
9
-
10
- if TYPE_CHECKING:
11
- from hud.rl.config import Config
12
-
13
- console = Console()
14
-
15
-
16
- def display_gpu_info(gpu_info: dict[str, Any]) -> None:
17
- """Display GPU information in a table."""
18
- if not gpu_info["available"]:
19
- console.print(f"[red]❌ CUDA not available: {gpu_info.get('error', 'Unknown error')}[/red]")
20
- return
21
-
22
- gpu_table = Table(title="🖥️ Available GPUs", title_style="bold cyan")
23
- gpu_table.add_column("Index", style="yellow")
24
- gpu_table.add_column("Name", style="cyan")
25
- gpu_table.add_column("Memory", style="green")
26
-
27
- for device in gpu_info["devices"]:
28
- gpu_table.add_row(f"GPU {device['index']}", device["name"], f"{device['memory_gb']:.1f} GB")
29
-
30
- console.print(gpu_table)
31
-
32
-
33
- def display_preset_table(presets: list[dict[str, Any]], gpu_memory_gb: float) -> None:
34
- """Display training configuration presets in a table."""
35
- preset_table = Table(title="📊 Training Configuration Presets", title_style="bold cyan")
36
- preset_table.add_column("Option", style="yellow")
37
- preset_table.add_column("Steps", style="cyan")
38
- preset_table.add_column("Mini-batch", style="cyan")
39
- preset_table.add_column("Group", style="cyan")
40
- preset_table.add_column("Episodes/batch", style="cyan")
41
-
42
- # Add time columns for A100
43
- if gpu_memory_gb >= 40:
44
- preset_table.add_column("Tasks/hour", style="green")
45
- preset_table.add_column("Updates/hour", style="green")
46
-
47
- for i, preset in enumerate(presets):
48
- row = [
49
- f"{i + 1}. {preset['name']}",
50
- str(preset["max_steps_per_episode"]),
51
- str(preset["mini_batch_size"]),
52
- str(preset["group_size"]),
53
- str(preset["batch_size"]),
54
- ]
55
- if "tasks_per_hour" in preset:
56
- row.extend(
57
- [
58
- str(preset["tasks_per_hour"]),
59
- str(preset["steps_per_hour"]),
60
- ]
61
- )
62
- preset_table.add_row(*row)
63
-
64
- console.print("\n")
65
- console.print(preset_table)
66
- console.print("\n")
67
-
68
-
69
- def display_config_summary(
70
- config: Config, tasks_count: int, gpu_info: dict[str, Any], estimated_memory: float
71
- ) -> None:
72
- """Display comprehensive configuration summary for review."""
73
- console.print("\n[bold cyan]📋 RL Training Configuration Summary[/bold cyan]\n")
74
-
75
- # GPU Information
76
- if gpu_info["available"]:
77
- gpu_table = Table(title="🖥️ GPU Information", title_style="bold yellow")
78
- gpu_table.add_column("Property", style="cyan")
79
- gpu_table.add_column("Value", style="green")
80
-
81
- device = gpu_info["devices"][0] # Primary GPU
82
- gpu_table.add_row("GPU 0", device["name"])
83
- gpu_table.add_row("Memory", f"{device['memory_gb']:.1f} GB")
84
- gpu_table.add_row("Compute Capability", "8.0") # Assuming A100
85
-
86
- console.print(gpu_table)
87
-
88
- # Model Configuration
89
- model_table = Table(title="🤖 Model Configuration", title_style="bold yellow")
90
- model_table.add_column("Parameter", style="cyan")
91
- model_table.add_column("Value", style="green")
92
-
93
- model_table.add_row("Base Model", config.model.base_model)
94
- model_table.add_row("LoRA Rank (r)", str(config.model.lora_r))
95
- model_table.add_row("LoRA Alpha", str(config.model.lora_alpha))
96
- model_table.add_row("LoRA Dropout", str(config.model.lora_dropout))
97
-
98
- console.print(model_table)
99
-
100
- # Training Configuration
101
- training_table = Table(title="🎯 Training Configuration", title_style="bold yellow")
102
- training_table.add_column("Parameter", style="cyan")
103
- training_table.add_column("Value", style="green")
104
-
105
- training_table.add_row("Tasks Count", str(tasks_count))
106
- training_table.add_row("Learning Rate", f"{config.training.lr:.1e}")
107
- training_table.add_row("Epochs", str(config.training.epochs))
108
- training_table.add_row("Mini Batch Size", str(config.training.mini_batch_size))
109
- training_table.add_row("Batch Size", str(config.training.batch_size))
110
- training_table.add_row("Group Size", str(config.training.group_size))
111
- training_table.add_row("Training Steps", str(config.training.training_steps))
112
- training_table.add_row("Max Parallel Episodes", str(config.actor.max_parallel_episodes))
113
-
114
- console.print(training_table)
115
-
116
- # Memory Estimation
117
- memory_table = Table(title="💾 Memory Estimation", title_style="bold yellow")
118
- memory_table.add_column("Metric", style="cyan")
119
- memory_table.add_column("Value", style="green")
120
-
121
- memory_table.add_row("Estimated GPU Memory", f"{estimated_memory:.1f} GB")
122
- if gpu_info["available"]:
123
- available_memory = gpu_info["devices"][0]["memory_gb"]
124
- memory_table.add_row("Available GPU Memory", f"{available_memory:.1f} GB")
125
-
126
- if estimated_memory > available_memory:
127
- status = "[red]⚠️ May exceed available memory[/red]"
128
- else:
129
- status = "[green]✅ Within memory limits[/green]"
130
- memory_table.add_row("Status", status)
131
-
132
- console.print(memory_table)
133
- console.print("\n")
hud/cli/rl/gpu.py DELETED
@@ -1,63 +0,0 @@
1
- """GPU detection and validation utilities for RL training."""
2
-
3
- from __future__ import annotations
4
-
5
- import subprocess
6
- from typing import Any
7
-
8
-
9
- def detect_cuda_devices() -> dict[str, Any]:
10
- """Detect available CUDA devices and their properties."""
11
- try:
12
- # Check if CUDA is available
13
- result = subprocess.run(
14
- ["nvidia-smi", "--query-gpu=index,name,memory.total", "--format=csv,noheader,nounits"], # noqa: S607
15
- capture_output=True,
16
- text=True,
17
- check=True,
18
- )
19
-
20
- if result.returncode != 0:
21
- return {"available": False, "error": "nvidia-smi command failed"}
22
-
23
- devices = []
24
- for line in result.stdout.strip().split("\n"):
25
- parts = line.split(", ")
26
- if len(parts) >= 3:
27
- devices.append(
28
- {
29
- "index": int(parts[0]),
30
- "name": parts[1],
31
- "memory_gb": float(parts[2]) / 1024, # Convert MB to GB
32
- }
33
- )
34
-
35
- return {"available": True, "devices": devices}
36
-
37
- except FileNotFoundError:
38
- return {
39
- "available": False,
40
- "error": "nvidia-smi not found - CUDA drivers may not be installed",
41
- }
42
- except Exception as e:
43
- return {"available": False, "error": str(e)}
44
-
45
-
46
- def select_gpu_for_vllm(devices: list[dict[str, Any]]) -> int:
47
- """Select the best GPU for vLLM server (typically GPU 1 if available)."""
48
- if len(devices) > 1:
49
- # Prefer GPU 1 for vLLM to leave GPU 0 for other processes
50
- return 1
51
- return 0
52
-
53
-
54
- def validate_gpu_memory(gpu_memory_gb: float, model_size: str = "3B") -> bool:
55
- """Validate if GPU has sufficient memory for the model."""
56
- min_memory_requirements = {
57
- "3B": 12.0, # Minimum for Qwen 2.5 VL 3B
58
- "7B": 24.0,
59
- "14B": 40.0,
60
- }
61
-
62
- min_required = min_memory_requirements.get(model_size, 12.0)
63
- return gpu_memory_gb >= min_required