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.
- hud/__init__.py +27 -7
- hud/agents/__init__.py +11 -5
- hud/agents/base.py +220 -500
- hud/agents/claude.py +200 -240
- hud/agents/gemini.py +275 -0
- hud/agents/gemini_cua.py +335 -0
- hud/agents/grounded_openai.py +98 -100
- hud/agents/misc/integration_test_agent.py +51 -20
- hud/agents/misc/response_agent.py +41 -36
- hud/agents/openai.py +291 -292
- hud/agents/{openai_chat_generic.py → openai_chat.py} +80 -34
- hud/agents/operator.py +211 -0
- hud/agents/tests/conftest.py +133 -0
- hud/agents/tests/test_base.py +300 -622
- hud/agents/tests/test_base_runtime.py +233 -0
- hud/agents/tests/test_claude.py +379 -210
- hud/agents/tests/test_client.py +9 -10
- hud/agents/tests/test_gemini.py +369 -0
- hud/agents/tests/test_grounded_openai_agent.py +65 -50
- hud/agents/tests/test_openai.py +376 -140
- hud/agents/tests/test_operator.py +362 -0
- hud/agents/tests/test_run_eval.py +179 -0
- hud/cli/__init__.py +461 -545
- hud/cli/analyze.py +43 -5
- hud/cli/build.py +664 -110
- hud/cli/debug.py +8 -5
- hud/cli/dev.py +882 -734
- hud/cli/eval.py +782 -668
- hud/cli/flows/dev.py +167 -0
- hud/cli/flows/init.py +191 -0
- hud/cli/flows/tasks.py +153 -56
- hud/cli/flows/templates.py +151 -0
- hud/cli/flows/tests/__init__.py +1 -0
- hud/cli/flows/tests/test_dev.py +126 -0
- hud/cli/init.py +60 -58
- hud/cli/push.py +29 -11
- hud/cli/rft.py +311 -0
- hud/cli/rft_status.py +145 -0
- hud/cli/tests/test_analyze.py +5 -5
- hud/cli/tests/test_analyze_metadata.py +3 -2
- hud/cli/tests/test_analyze_module.py +120 -0
- hud/cli/tests/test_build.py +108 -6
- hud/cli/tests/test_build_failure.py +41 -0
- hud/cli/tests/test_build_module.py +50 -0
- hud/cli/tests/test_cli_init.py +6 -1
- hud/cli/tests/test_cli_more_wrappers.py +30 -0
- hud/cli/tests/test_cli_root.py +140 -0
- hud/cli/tests/test_convert.py +361 -0
- hud/cli/tests/test_debug.py +12 -10
- hud/cli/tests/test_dev.py +197 -0
- hud/cli/tests/test_eval.py +251 -0
- hud/cli/tests/test_eval_bedrock.py +51 -0
- hud/cli/tests/test_init.py +124 -0
- hud/cli/tests/test_main_module.py +11 -5
- hud/cli/tests/test_mcp_server.py +12 -100
- hud/cli/tests/test_push_happy.py +74 -0
- hud/cli/tests/test_push_wrapper.py +23 -0
- hud/cli/tests/test_registry.py +1 -1
- hud/cli/tests/test_utils.py +1 -1
- hud/cli/{rl → utils}/celebrate.py +14 -12
- hud/cli/utils/config.py +18 -1
- hud/cli/utils/docker.py +130 -4
- hud/cli/utils/env_check.py +9 -9
- hud/cli/utils/git.py +136 -0
- hud/cli/utils/interactive.py +39 -5
- hud/cli/utils/metadata.py +69 -0
- hud/cli/utils/runner.py +1 -1
- hud/cli/utils/server.py +2 -2
- hud/cli/utils/source_hash.py +3 -3
- hud/cli/utils/tasks.py +4 -1
- hud/cli/utils/tests/__init__.py +0 -0
- hud/cli/utils/tests/test_config.py +58 -0
- hud/cli/utils/tests/test_docker.py +93 -0
- hud/cli/utils/tests/test_docker_hints.py +71 -0
- hud/cli/utils/tests/test_env_check.py +74 -0
- hud/cli/utils/tests/test_environment.py +42 -0
- hud/cli/utils/tests/test_git.py +142 -0
- hud/cli/utils/tests/test_interactive_module.py +60 -0
- hud/cli/utils/tests/test_local_runner.py +50 -0
- hud/cli/utils/tests/test_logging_utils.py +23 -0
- hud/cli/utils/tests/test_metadata.py +49 -0
- hud/cli/utils/tests/test_package_runner.py +35 -0
- hud/cli/utils/tests/test_registry_utils.py +49 -0
- hud/cli/utils/tests/test_remote_runner.py +25 -0
- hud/cli/utils/tests/test_runner_modules.py +52 -0
- hud/cli/utils/tests/test_source_hash.py +36 -0
- hud/cli/utils/tests/test_tasks.py +80 -0
- hud/cli/utils/version_check.py +258 -0
- hud/cli/{rl → utils}/viewer.py +2 -2
- hud/clients/README.md +12 -11
- hud/clients/__init__.py +4 -3
- hud/clients/base.py +166 -26
- hud/clients/environment.py +51 -0
- hud/clients/fastmcp.py +13 -6
- hud/clients/mcp_use.py +40 -15
- hud/clients/tests/test_analyze_scenarios.py +206 -0
- hud/clients/tests/test_protocol.py +9 -3
- hud/datasets/__init__.py +23 -20
- hud/datasets/loader.py +327 -0
- hud/datasets/runner.py +192 -105
- hud/datasets/tests/__init__.py +0 -0
- hud/datasets/tests/test_loader.py +221 -0
- hud/datasets/tests/test_utils.py +315 -0
- hud/datasets/utils.py +270 -90
- hud/environment/__init__.py +50 -0
- hud/environment/connection.py +206 -0
- hud/environment/connectors/__init__.py +33 -0
- hud/environment/connectors/base.py +68 -0
- hud/environment/connectors/local.py +177 -0
- hud/environment/connectors/mcp_config.py +109 -0
- hud/environment/connectors/openai.py +101 -0
- hud/environment/connectors/remote.py +172 -0
- hud/environment/environment.py +694 -0
- hud/environment/integrations/__init__.py +45 -0
- hud/environment/integrations/adk.py +67 -0
- hud/environment/integrations/anthropic.py +196 -0
- hud/environment/integrations/gemini.py +92 -0
- hud/environment/integrations/langchain.py +82 -0
- hud/environment/integrations/llamaindex.py +68 -0
- hud/environment/integrations/openai.py +238 -0
- hud/environment/mock.py +306 -0
- hud/environment/router.py +112 -0
- hud/environment/scenarios.py +493 -0
- hud/environment/tests/__init__.py +1 -0
- hud/environment/tests/test_connection.py +317 -0
- hud/environment/tests/test_connectors.py +218 -0
- hud/environment/tests/test_environment.py +161 -0
- hud/environment/tests/test_integrations.py +257 -0
- hud/environment/tests/test_local_connectors.py +201 -0
- hud/environment/tests/test_scenarios.py +280 -0
- hud/environment/tests/test_tools.py +208 -0
- hud/environment/types.py +23 -0
- hud/environment/utils/__init__.py +35 -0
- hud/environment/utils/formats.py +215 -0
- hud/environment/utils/schema.py +171 -0
- hud/environment/utils/tool_wrappers.py +113 -0
- hud/eval/__init__.py +67 -0
- hud/eval/context.py +674 -0
- hud/eval/display.py +299 -0
- hud/eval/instrument.py +185 -0
- hud/eval/manager.py +466 -0
- hud/eval/parallel.py +268 -0
- hud/eval/task.py +340 -0
- hud/eval/tests/__init__.py +1 -0
- hud/eval/tests/test_context.py +178 -0
- hud/eval/tests/test_eval.py +210 -0
- hud/eval/tests/test_manager.py +152 -0
- hud/eval/tests/test_parallel.py +168 -0
- hud/eval/tests/test_task.py +145 -0
- hud/eval/types.py +63 -0
- hud/eval/utils.py +183 -0
- hud/patches/__init__.py +19 -0
- hud/patches/mcp_patches.py +151 -0
- hud/patches/warnings.py +54 -0
- hud/samples/browser.py +4 -4
- hud/server/__init__.py +2 -1
- hud/server/low_level.py +2 -1
- hud/server/router.py +164 -0
- hud/server/server.py +567 -80
- hud/server/tests/test_mcp_server_integration.py +11 -11
- hud/server/tests/test_mcp_server_more.py +1 -1
- hud/server/tests/test_server_extra.py +2 -0
- hud/settings.py +45 -3
- hud/shared/exceptions.py +36 -10
- hud/shared/hints.py +26 -1
- hud/shared/requests.py +15 -3
- hud/shared/tests/test_exceptions.py +40 -31
- hud/shared/tests/test_hints.py +167 -0
- hud/telemetry/__init__.py +20 -19
- hud/telemetry/exporter.py +201 -0
- hud/telemetry/instrument.py +158 -253
- hud/telemetry/tests/test_eval_telemetry.py +356 -0
- hud/telemetry/tests/test_exporter.py +258 -0
- hud/telemetry/tests/test_instrument.py +401 -0
- hud/tools/__init__.py +16 -2
- hud/tools/apply_patch.py +639 -0
- hud/tools/base.py +54 -4
- hud/tools/bash.py +2 -2
- hud/tools/computer/__init__.py +4 -0
- hud/tools/computer/anthropic.py +2 -2
- hud/tools/computer/gemini.py +385 -0
- hud/tools/computer/hud.py +23 -6
- hud/tools/computer/openai.py +20 -21
- hud/tools/computer/qwen.py +434 -0
- hud/tools/computer/settings.py +37 -0
- hud/tools/edit.py +3 -7
- hud/tools/executors/base.py +4 -2
- hud/tools/executors/pyautogui.py +1 -1
- hud/tools/grounding/grounded_tool.py +13 -18
- hud/tools/grounding/grounder.py +10 -31
- hud/tools/grounding/tests/test_grounded_tool.py +26 -44
- hud/tools/jupyter.py +330 -0
- hud/tools/playwright.py +18 -3
- hud/tools/shell.py +308 -0
- hud/tools/tests/test_apply_patch.py +718 -0
- hud/tools/tests/test_computer.py +4 -9
- hud/tools/tests/test_computer_actions.py +24 -2
- hud/tools/tests/test_jupyter_tool.py +181 -0
- hud/tools/tests/test_shell.py +596 -0
- hud/tools/tests/test_submit.py +85 -0
- hud/tools/tests/test_types.py +193 -0
- hud/tools/types.py +21 -1
- hud/types.py +167 -57
- hud/utils/__init__.py +2 -0
- hud/utils/env.py +67 -0
- hud/utils/hud_console.py +61 -3
- hud/utils/mcp.py +15 -58
- hud/utils/strict_schema.py +162 -0
- hud/utils/tests/test_init.py +1 -2
- hud/utils/tests/test_mcp.py +1 -28
- hud/utils/tests/test_pretty_errors.py +186 -0
- hud/utils/tests/test_tool_shorthand.py +154 -0
- hud/utils/tests/test_version.py +1 -1
- hud/utils/types.py +20 -0
- hud/version.py +1 -1
- hud_python-0.5.1.dist-info/METADATA +264 -0
- hud_python-0.5.1.dist-info/RECORD +299 -0
- {hud_python-0.4.45.dist-info → hud_python-0.5.1.dist-info}/WHEEL +1 -1
- hud/agents/langchain.py +0 -261
- hud/agents/lite_llm.py +0 -72
- hud/cli/rl/__init__.py +0 -180
- hud/cli/rl/config.py +0 -101
- hud/cli/rl/display.py +0 -133
- hud/cli/rl/gpu.py +0 -63
- hud/cli/rl/gpu_utils.py +0 -321
- hud/cli/rl/local_runner.py +0 -595
- hud/cli/rl/presets.py +0 -96
- hud/cli/rl/remote_runner.py +0 -463
- hud/cli/rl/rl_api.py +0 -150
- hud/cli/rl/vllm.py +0 -177
- hud/cli/rl/wait_utils.py +0 -89
- hud/datasets/parallel.py +0 -687
- hud/misc/__init__.py +0 -1
- hud/misc/claude_plays_pokemon.py +0 -292
- hud/otel/__init__.py +0 -35
- hud/otel/collector.py +0 -142
- hud/otel/config.py +0 -181
- hud/otel/context.py +0 -570
- hud/otel/exporters.py +0 -369
- hud/otel/instrumentation.py +0 -135
- hud/otel/processors.py +0 -121
- hud/otel/tests/__init__.py +0 -1
- hud/otel/tests/test_processors.py +0 -197
- hud/rl/README.md +0 -30
- hud/rl/__init__.py +0 -1
- hud/rl/actor.py +0 -176
- hud/rl/buffer.py +0 -405
- hud/rl/chat_template.jinja +0 -101
- hud/rl/config.py +0 -192
- hud/rl/distributed.py +0 -132
- hud/rl/learner.py +0 -637
- hud/rl/tests/__init__.py +0 -1
- hud/rl/tests/test_learner.py +0 -186
- hud/rl/train.py +0 -382
- hud/rl/types.py +0 -101
- hud/rl/utils/start_vllm_server.sh +0 -30
- hud/rl/utils.py +0 -524
- hud/rl/vllm_adapter.py +0 -143
- hud/telemetry/job.py +0 -352
- hud/telemetry/replay.py +0 -74
- hud/telemetry/tests/test_replay.py +0 -40
- hud/telemetry/tests/test_trace.py +0 -63
- hud/telemetry/trace.py +0 -158
- hud/utils/agent_factories.py +0 -86
- hud/utils/async_utils.py +0 -65
- hud/utils/group_eval.py +0 -223
- hud/utils/progress.py +0 -149
- hud/utils/tasks.py +0 -127
- hud/utils/tests/test_async_utils.py +0 -173
- hud/utils/tests/test_progress.py +0 -261
- hud_python-0.4.45.dist-info/METADATA +0 -552
- hud_python-0.4.45.dist-info/RECORD +0 -228
- {hud_python-0.4.45.dist-info → hud_python-0.5.1.dist-info}/entry_points.txt +0 -0
- {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
|