hud-python 0.4.45__py3-none-any.whl → 0.5.13__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 (282) hide show
  1. hud/__init__.py +27 -7
  2. hud/agents/__init__.py +70 -5
  3. hud/agents/base.py +238 -500
  4. hud/agents/claude.py +236 -247
  5. hud/agents/gateway.py +42 -0
  6. hud/agents/gemini.py +264 -0
  7. hud/agents/gemini_cua.py +324 -0
  8. hud/agents/grounded_openai.py +98 -100
  9. hud/agents/misc/integration_test_agent.py +51 -20
  10. hud/agents/misc/response_agent.py +48 -36
  11. hud/agents/openai.py +282 -296
  12. hud/agents/{openai_chat_generic.py → openai_chat.py} +63 -33
  13. hud/agents/operator.py +199 -0
  14. hud/agents/resolver.py +70 -0
  15. hud/agents/tests/conftest.py +133 -0
  16. hud/agents/tests/test_base.py +300 -622
  17. hud/agents/tests/test_base_runtime.py +233 -0
  18. hud/agents/tests/test_claude.py +381 -214
  19. hud/agents/tests/test_client.py +9 -10
  20. hud/agents/tests/test_gemini.py +369 -0
  21. hud/agents/tests/test_grounded_openai_agent.py +65 -50
  22. hud/agents/tests/test_openai.py +377 -140
  23. hud/agents/tests/test_operator.py +362 -0
  24. hud/agents/tests/test_resolver.py +192 -0
  25. hud/agents/tests/test_run_eval.py +179 -0
  26. hud/agents/types.py +148 -0
  27. hud/cli/__init__.py +493 -546
  28. hud/cli/analyze.py +43 -5
  29. hud/cli/build.py +699 -113
  30. hud/cli/debug.py +8 -5
  31. hud/cli/dev.py +889 -732
  32. hud/cli/eval.py +793 -667
  33. hud/cli/flows/dev.py +167 -0
  34. hud/cli/flows/init.py +191 -0
  35. hud/cli/flows/tasks.py +153 -56
  36. hud/cli/flows/templates.py +151 -0
  37. hud/cli/flows/tests/__init__.py +1 -0
  38. hud/cli/flows/tests/test_dev.py +126 -0
  39. hud/cli/init.py +60 -58
  40. hud/cli/pull.py +1 -1
  41. hud/cli/push.py +38 -13
  42. hud/cli/rft.py +311 -0
  43. hud/cli/rft_status.py +145 -0
  44. hud/cli/tests/test_analyze.py +5 -5
  45. hud/cli/tests/test_analyze_metadata.py +3 -2
  46. hud/cli/tests/test_analyze_module.py +120 -0
  47. hud/cli/tests/test_build.py +110 -8
  48. hud/cli/tests/test_build_failure.py +41 -0
  49. hud/cli/tests/test_build_module.py +50 -0
  50. hud/cli/tests/test_cli_init.py +6 -1
  51. hud/cli/tests/test_cli_more_wrappers.py +30 -0
  52. hud/cli/tests/test_cli_root.py +140 -0
  53. hud/cli/tests/test_convert.py +361 -0
  54. hud/cli/tests/test_debug.py +12 -10
  55. hud/cli/tests/test_dev.py +197 -0
  56. hud/cli/tests/test_eval.py +251 -0
  57. hud/cli/tests/test_eval_bedrock.py +51 -0
  58. hud/cli/tests/test_init.py +124 -0
  59. hud/cli/tests/test_main_module.py +11 -5
  60. hud/cli/tests/test_mcp_server.py +12 -100
  61. hud/cli/tests/test_push.py +1 -1
  62. hud/cli/tests/test_push_happy.py +74 -0
  63. hud/cli/tests/test_push_wrapper.py +23 -0
  64. hud/cli/tests/test_registry.py +1 -1
  65. hud/cli/tests/test_utils.py +1 -1
  66. hud/cli/{rl → utils}/celebrate.py +14 -12
  67. hud/cli/utils/config.py +18 -1
  68. hud/cli/utils/docker.py +130 -4
  69. hud/cli/utils/env_check.py +9 -9
  70. hud/cli/utils/git.py +136 -0
  71. hud/cli/utils/interactive.py +39 -5
  72. hud/cli/utils/metadata.py +70 -1
  73. hud/cli/utils/runner.py +1 -1
  74. hud/cli/utils/server.py +2 -2
  75. hud/cli/utils/source_hash.py +3 -3
  76. hud/cli/utils/tasks.py +4 -1
  77. hud/cli/utils/tests/__init__.py +0 -0
  78. hud/cli/utils/tests/test_config.py +58 -0
  79. hud/cli/utils/tests/test_docker.py +93 -0
  80. hud/cli/utils/tests/test_docker_hints.py +71 -0
  81. hud/cli/utils/tests/test_env_check.py +74 -0
  82. hud/cli/utils/tests/test_environment.py +42 -0
  83. hud/cli/utils/tests/test_git.py +142 -0
  84. hud/cli/utils/tests/test_interactive_module.py +60 -0
  85. hud/cli/utils/tests/test_local_runner.py +50 -0
  86. hud/cli/utils/tests/test_logging_utils.py +23 -0
  87. hud/cli/utils/tests/test_metadata.py +49 -0
  88. hud/cli/utils/tests/test_package_runner.py +35 -0
  89. hud/cli/utils/tests/test_registry_utils.py +49 -0
  90. hud/cli/utils/tests/test_remote_runner.py +25 -0
  91. hud/cli/utils/tests/test_runner_modules.py +52 -0
  92. hud/cli/utils/tests/test_source_hash.py +36 -0
  93. hud/cli/utils/tests/test_tasks.py +80 -0
  94. hud/cli/utils/version_check.py +258 -0
  95. hud/cli/{rl → utils}/viewer.py +2 -2
  96. hud/clients/README.md +12 -11
  97. hud/clients/__init__.py +4 -3
  98. hud/clients/base.py +166 -26
  99. hud/clients/environment.py +51 -0
  100. hud/clients/fastmcp.py +13 -6
  101. hud/clients/mcp_use.py +45 -15
  102. hud/clients/tests/test_analyze_scenarios.py +206 -0
  103. hud/clients/tests/test_protocol.py +9 -3
  104. hud/datasets/__init__.py +23 -20
  105. hud/datasets/loader.py +326 -0
  106. hud/datasets/runner.py +198 -105
  107. hud/datasets/tests/__init__.py +0 -0
  108. hud/datasets/tests/test_loader.py +221 -0
  109. hud/datasets/tests/test_utils.py +315 -0
  110. hud/datasets/utils.py +270 -90
  111. hud/environment/__init__.py +52 -0
  112. hud/environment/connection.py +258 -0
  113. hud/environment/connectors/__init__.py +33 -0
  114. hud/environment/connectors/base.py +68 -0
  115. hud/environment/connectors/local.py +177 -0
  116. hud/environment/connectors/mcp_config.py +137 -0
  117. hud/environment/connectors/openai.py +101 -0
  118. hud/environment/connectors/remote.py +172 -0
  119. hud/environment/environment.py +835 -0
  120. hud/environment/integrations/__init__.py +45 -0
  121. hud/environment/integrations/adk.py +67 -0
  122. hud/environment/integrations/anthropic.py +196 -0
  123. hud/environment/integrations/gemini.py +92 -0
  124. hud/environment/integrations/langchain.py +82 -0
  125. hud/environment/integrations/llamaindex.py +68 -0
  126. hud/environment/integrations/openai.py +238 -0
  127. hud/environment/mock.py +306 -0
  128. hud/environment/router.py +263 -0
  129. hud/environment/scenarios.py +620 -0
  130. hud/environment/tests/__init__.py +1 -0
  131. hud/environment/tests/test_connection.py +317 -0
  132. hud/environment/tests/test_connectors.py +205 -0
  133. hud/environment/tests/test_environment.py +593 -0
  134. hud/environment/tests/test_integrations.py +257 -0
  135. hud/environment/tests/test_local_connectors.py +242 -0
  136. hud/environment/tests/test_scenarios.py +1086 -0
  137. hud/environment/tests/test_tools.py +208 -0
  138. hud/environment/types.py +23 -0
  139. hud/environment/utils/__init__.py +35 -0
  140. hud/environment/utils/formats.py +215 -0
  141. hud/environment/utils/schema.py +171 -0
  142. hud/environment/utils/tool_wrappers.py +113 -0
  143. hud/eval/__init__.py +67 -0
  144. hud/eval/context.py +727 -0
  145. hud/eval/display.py +299 -0
  146. hud/eval/instrument.py +187 -0
  147. hud/eval/manager.py +533 -0
  148. hud/eval/parallel.py +268 -0
  149. hud/eval/task.py +372 -0
  150. hud/eval/tests/__init__.py +1 -0
  151. hud/eval/tests/test_context.py +178 -0
  152. hud/eval/tests/test_eval.py +210 -0
  153. hud/eval/tests/test_manager.py +152 -0
  154. hud/eval/tests/test_parallel.py +168 -0
  155. hud/eval/tests/test_task.py +291 -0
  156. hud/eval/types.py +65 -0
  157. hud/eval/utils.py +194 -0
  158. hud/patches/__init__.py +19 -0
  159. hud/patches/mcp_patches.py +308 -0
  160. hud/patches/warnings.py +54 -0
  161. hud/samples/browser.py +4 -4
  162. hud/server/__init__.py +2 -1
  163. hud/server/low_level.py +2 -1
  164. hud/server/router.py +164 -0
  165. hud/server/server.py +567 -80
  166. hud/server/tests/test_mcp_server_integration.py +11 -11
  167. hud/server/tests/test_mcp_server_more.py +1 -1
  168. hud/server/tests/test_server_extra.py +2 -0
  169. hud/settings.py +45 -3
  170. hud/shared/exceptions.py +36 -10
  171. hud/shared/hints.py +26 -1
  172. hud/shared/requests.py +15 -3
  173. hud/shared/tests/test_exceptions.py +40 -31
  174. hud/shared/tests/test_hints.py +167 -0
  175. hud/telemetry/__init__.py +20 -19
  176. hud/telemetry/exporter.py +201 -0
  177. hud/telemetry/instrument.py +165 -253
  178. hud/telemetry/tests/test_eval_telemetry.py +356 -0
  179. hud/telemetry/tests/test_exporter.py +258 -0
  180. hud/telemetry/tests/test_instrument.py +401 -0
  181. hud/tools/__init__.py +18 -2
  182. hud/tools/agent.py +223 -0
  183. hud/tools/apply_patch.py +639 -0
  184. hud/tools/base.py +54 -4
  185. hud/tools/bash.py +2 -2
  186. hud/tools/computer/__init__.py +36 -3
  187. hud/tools/computer/anthropic.py +2 -2
  188. hud/tools/computer/gemini.py +385 -0
  189. hud/tools/computer/hud.py +23 -6
  190. hud/tools/computer/openai.py +20 -21
  191. hud/tools/computer/qwen.py +434 -0
  192. hud/tools/computer/settings.py +37 -0
  193. hud/tools/edit.py +3 -7
  194. hud/tools/executors/base.py +4 -2
  195. hud/tools/executors/pyautogui.py +1 -1
  196. hud/tools/grounding/grounded_tool.py +13 -18
  197. hud/tools/grounding/grounder.py +10 -31
  198. hud/tools/grounding/tests/test_grounded_tool.py +26 -44
  199. hud/tools/jupyter.py +330 -0
  200. hud/tools/playwright.py +18 -3
  201. hud/tools/shell.py +308 -0
  202. hud/tools/tests/test_agent_tool.py +355 -0
  203. hud/tools/tests/test_apply_patch.py +718 -0
  204. hud/tools/tests/test_computer.py +4 -9
  205. hud/tools/tests/test_computer_actions.py +24 -2
  206. hud/tools/tests/test_jupyter_tool.py +181 -0
  207. hud/tools/tests/test_shell.py +596 -0
  208. hud/tools/tests/test_submit.py +85 -0
  209. hud/tools/tests/test_types.py +193 -0
  210. hud/tools/types.py +21 -1
  211. hud/types.py +194 -56
  212. hud/utils/__init__.py +2 -0
  213. hud/utils/env.py +67 -0
  214. hud/utils/hud_console.py +89 -18
  215. hud/utils/mcp.py +15 -58
  216. hud/utils/strict_schema.py +162 -0
  217. hud/utils/tests/test_init.py +1 -2
  218. hud/utils/tests/test_mcp.py +1 -28
  219. hud/utils/tests/test_pretty_errors.py +186 -0
  220. hud/utils/tests/test_tool_shorthand.py +154 -0
  221. hud/utils/tests/test_version.py +1 -1
  222. hud/utils/types.py +20 -0
  223. hud/version.py +1 -1
  224. hud_python-0.5.13.dist-info/METADATA +264 -0
  225. hud_python-0.5.13.dist-info/RECORD +305 -0
  226. {hud_python-0.4.45.dist-info → hud_python-0.5.13.dist-info}/WHEEL +1 -1
  227. hud/agents/langchain.py +0 -261
  228. hud/agents/lite_llm.py +0 -72
  229. hud/cli/rl/__init__.py +0 -180
  230. hud/cli/rl/config.py +0 -101
  231. hud/cli/rl/display.py +0 -133
  232. hud/cli/rl/gpu.py +0 -63
  233. hud/cli/rl/gpu_utils.py +0 -321
  234. hud/cli/rl/local_runner.py +0 -595
  235. hud/cli/rl/presets.py +0 -96
  236. hud/cli/rl/remote_runner.py +0 -463
  237. hud/cli/rl/rl_api.py +0 -150
  238. hud/cli/rl/vllm.py +0 -177
  239. hud/cli/rl/wait_utils.py +0 -89
  240. hud/datasets/parallel.py +0 -687
  241. hud/misc/__init__.py +0 -1
  242. hud/misc/claude_plays_pokemon.py +0 -292
  243. hud/otel/__init__.py +0 -35
  244. hud/otel/collector.py +0 -142
  245. hud/otel/config.py +0 -181
  246. hud/otel/context.py +0 -570
  247. hud/otel/exporters.py +0 -369
  248. hud/otel/instrumentation.py +0 -135
  249. hud/otel/processors.py +0 -121
  250. hud/otel/tests/__init__.py +0 -1
  251. hud/otel/tests/test_processors.py +0 -197
  252. hud/rl/README.md +0 -30
  253. hud/rl/__init__.py +0 -1
  254. hud/rl/actor.py +0 -176
  255. hud/rl/buffer.py +0 -405
  256. hud/rl/chat_template.jinja +0 -101
  257. hud/rl/config.py +0 -192
  258. hud/rl/distributed.py +0 -132
  259. hud/rl/learner.py +0 -637
  260. hud/rl/tests/__init__.py +0 -1
  261. hud/rl/tests/test_learner.py +0 -186
  262. hud/rl/train.py +0 -382
  263. hud/rl/types.py +0 -101
  264. hud/rl/utils/start_vllm_server.sh +0 -30
  265. hud/rl/utils.py +0 -524
  266. hud/rl/vllm_adapter.py +0 -143
  267. hud/telemetry/job.py +0 -352
  268. hud/telemetry/replay.py +0 -74
  269. hud/telemetry/tests/test_replay.py +0 -40
  270. hud/telemetry/tests/test_trace.py +0 -63
  271. hud/telemetry/trace.py +0 -158
  272. hud/utils/agent_factories.py +0 -86
  273. hud/utils/async_utils.py +0 -65
  274. hud/utils/group_eval.py +0 -223
  275. hud/utils/progress.py +0 -149
  276. hud/utils/tasks.py +0 -127
  277. hud/utils/tests/test_async_utils.py +0 -173
  278. hud/utils/tests/test_progress.py +0 -261
  279. hud_python-0.4.45.dist-info/METADATA +0 -552
  280. hud_python-0.4.45.dist-info/RECORD +0 -228
  281. {hud_python-0.4.45.dist-info → hud_python-0.5.13.dist-info}/entry_points.txt +0 -0
  282. {hud_python-0.4.45.dist-info → hud_python-0.5.13.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