agilerl 2.8.0.dev0__tar.gz → 2.8.0.dev2__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.
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/.gitignore +4 -4
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/PKG-INFO +17 -7
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/README.md +16 -6
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/cispo.py +3 -6
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/base.py +85 -138
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/dpo.py +6 -21
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/grpo.py +6 -35
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/gspo.py +3 -6
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/matd3.py +1 -10
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/neural_ts_bandit.py +15 -4
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/neural_ucb_bandit.py +15 -4
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/ppo.py +5 -1
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/ppo_llm.py +6 -17
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/reinforce_llm.py +6 -17
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/sft.py +7 -11
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/hpo/mutation.py +13 -2
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/manifest.py +102 -2
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/networks.py +73 -14
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/cnn.py +1 -1
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/dummy.py +5 -1
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/train.py +2 -2
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/trainer.py +169 -2
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/algo_utils.py +68 -6
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/evolvable_networks.py +4 -4
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/llm_utils.py +4 -21
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/probe_envs_ma.py +0 -134
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/utils.py +3 -4
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/pyproject.toml +5 -11
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/LICENSE +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/bc_lm.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/llm_ops/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/llm_ops/fused_logprobs.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/llm_ops/fused_lora.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/llm_ops/fused_loss.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/llm_ops/vllm_colocate.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/optimizer_wrapper.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/core/registry.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/cqn.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/ddpg.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/dqn.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/dqn_rainbow.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/ilql.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/ippo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/maddpg.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/algorithms/td3.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/data.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/replay_buffer.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/rollout_buffer.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/sampler.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/components/segment_tree.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/data/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/data/language_environment.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/data/rl_data.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/data/tokenizer.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/data/torch_datasets.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/hpo/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/hpo/tournament.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/base.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/preference.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/reasoning.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/search.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/sft.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/sync_vec_env.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/llm_envs/token_observation.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/logger.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/metrics.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/cispo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/cqn.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/ddpg.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/dpo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/dqn.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/grpo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/gspo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/ippo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/llmppo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/llmreinforce.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/maddpg.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/matd3.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/neural_ts.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/neural_ucb.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/ppo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/rainbow_dqn.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/sft.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/algorithms/td3.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/env.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/hpo.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/models/training.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/base.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/bert.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/configs.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/custom_components.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/gpt.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/lstm.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/mlp.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/multi_input.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/resnet.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/modules/simba.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/actors.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/base.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/custom_modules.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/distributions.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/q_networks.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/networks/value_networks.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/population.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/protocols.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/rollouts/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/rollouts/on_policy.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_bandits.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_llm.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_multi_agent_off_policy.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_multi_agent_on_policy.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_off_policy.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_offline.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/training/train_on_policy.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/typing.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/cache.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/env_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/ilql_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/llm_packing.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/log_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/minari_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/population_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/ppo_value_head.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/probe_envs.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/probe_envs_llm.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/sampling_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/torch_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/utils/trainer_utils.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/vector/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/vector/dummy_vec_env.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/vector/pz_async_vec_env.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/vector/pz_vec_env.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/__init__.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/agent.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/learning.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/llm_envs.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/make_evolvable.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/pettingzoo_wrappers.py +0 -0
- {agilerl-2.8.0.dev0 → agilerl-2.8.0.dev2}/agilerl/wrappers/utils.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# Symlink for Pylance/Pyright type checking of namespace package
|
|
2
|
-
agilerl/arena
|
|
1
|
+
# Symlink for Pylance/Pyright type checking of namespace package (repo root only)
|
|
2
|
+
/agilerl/arena
|
|
3
3
|
|
|
4
4
|
# Byte-compiled / optimized / DLL files
|
|
5
5
|
__pycache__/
|
|
@@ -162,5 +162,5 @@ wandb/
|
|
|
162
162
|
CLAUDE.md
|
|
163
163
|
AGENTS.md
|
|
164
164
|
|
|
165
|
-
#
|
|
166
|
-
agilerl/arena/
|
|
165
|
+
# Symlink for type-checking (repo root only)
|
|
166
|
+
/agilerl/arena/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agilerl
|
|
3
|
-
Version: 2.8.0.
|
|
3
|
+
Version: 2.8.0.dev2
|
|
4
4
|
Summary: AgileRL is a deep reinforcement learning library focused on improving RL development through RLOps.
|
|
5
5
|
Author-email: Nick Ustaran-Anderegg <dev@agilerl.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -87,7 +87,7 @@ AgileRL is a Deep Reinforcement Learning library focused on improving developmen
|
|
|
87
87
|
|
|
88
88
|
This library is initially focused on reducing the time taken for training models and hyperparameter optimization (HPO) by pioneering [evolutionary HPO techniques](https://docs.agilerl.com/en/latest/evo_hyperparam_opt/index.html) for reinforcement learning.<br>
|
|
89
89
|
Evolutionary HPO has been shown to drastically reduce overall training times by automatically converging on optimal hyperparameters, without requiring numerous training runs.<br>
|
|
90
|
-
We are constantly adding more algorithms and features. AgileRL already includes state-of-the-art evolvable [on-policy](https://docs.agilerl.com/en/latest/on_policy/index.html), [off-policy](https://docs.agilerl.com/en/latest/off_policy/index.html), [offline](https://docs.agilerl.com/en/latest/offline_training/index.html), [multi-agent](https://docs.agilerl.com/en/latest/multi_agent_training/index.html) and [contextual multi-armed bandit](https://docs.agilerl.com/en/latest/bandits/index.html) reinforcement learning algorithms with [distributed training](https://docs.agilerl.com/en/latest/distributed_training/index.html).
|
|
90
|
+
We are constantly adding more algorithms and features. AgileRL already includes state-of-the-art evolvable [LLM fine-tuning](https://docs.agilerl.com/en/latest/llm_finetuning/index.html), [on-policy](https://docs.agilerl.com/en/latest/on_policy/index.html), [off-policy](https://docs.agilerl.com/en/latest/off_policy/index.html), [offline](https://docs.agilerl.com/en/latest/offline_training/index.html), [multi-agent](https://docs.agilerl.com/en/latest/multi_agent_training/index.html) and [contextual multi-armed bandit](https://docs.agilerl.com/en/latest/bandits/index.html) reinforcement learning algorithms with [distributed training](https://docs.agilerl.com/en/latest/distributed_training/index.html).
|
|
91
91
|
|
|
92
92
|
<p align="center">
|
|
93
93
|
<img src=https://user-images.githubusercontent.com/47857277/236407686-21363eb3-ffcf-419f-b019-0be4ddf1ed4a.gif width="100%" max-width="900">
|
|
@@ -105,6 +105,16 @@ We are constantly adding more algorithms and features. AgileRL already includes
|
|
|
105
105
|
|
|
106
106
|
## Benchmarks
|
|
107
107
|
|
|
108
|
+
### LLM Fine-tuning
|
|
109
|
+
|
|
110
|
+
AgileRL's multi-turn LLM training enables state-of-the-art performance on long-horizon tasks with small models. In the following example, AgileRL's CISPO was benchmarked against ART and TRL on the <a href="https://github.com/axon-rl/gem">GEM</a> Sudoku Hard task. This is a difficult multi-turn problem, which requires a context length of 32k tokens and up to 50 turns per rollout. The sync AgileRL run is a single agent using the AgileRL framework. The async and HPO runs were performed on <a href="https://arena.agilerl.com">Arena</a>, AgileRL's RLOps platform. All runs used the same starting hyperparameters. AgileRL runs were run on A100 40GB nodes, whereas ART and TRL required A100 80GB nodes due to a lack of optimizations. AgileRL runs significantly outperformed those using the ART and TRL frameworks.
|
|
111
|
+
|
|
112
|
+
<p align="center">
|
|
113
|
+
<img src="https://raw.githubusercontent.com/AgileRL/AgileRL/main/docs/_static/multi_turn_llm_benchmarks.png" min-width="100%" width="700">
|
|
114
|
+
</p>
|
|
115
|
+
|
|
116
|
+
### Classic RL
|
|
117
|
+
|
|
108
118
|
Reinforcement learning algorithms and libraries are usually benchmarked once the optimal hyperparameters for training are known, but it often takes hundreds or thousands of experiments to discover these. This is unrealistic and does not reflect the true, total time taken for training. What if we could remove the need to conduct all these prior experiments?
|
|
109
119
|
|
|
110
120
|
In the charts below, a single AgileRL run, which automatically tunes hyperparameters, is benchmarked against Optuna's multiple training runs traditionally required for hyperparameter optimization, demonstrating the real time savings possible. Global steps is the sum of every step taken by any agent in the environment, including across an entire population.
|
|
@@ -402,10 +412,10 @@ Use the `ArenaClient` to interact with Arena programmatically from scripts or no
|
|
|
402
412
|
from agilerl.arena import ArenaClient
|
|
403
413
|
|
|
404
414
|
client = ArenaClient()
|
|
405
|
-
client.login()
|
|
415
|
+
client.login() # OAuth2 device-flow authentication
|
|
406
416
|
|
|
407
|
-
#
|
|
408
|
-
client.validate_environment(source="path/to/my_env.py")
|
|
417
|
+
# Upload and validate a custom environment
|
|
418
|
+
client.validate_environment(name="my-custom-env", source="path/to/my_env.py")
|
|
409
419
|
|
|
410
420
|
# Train on validated custom environment
|
|
411
421
|
client.submit_experiment(
|
|
@@ -423,13 +433,13 @@ The same operations are available from the command line:
|
|
|
423
433
|
arena login
|
|
424
434
|
|
|
425
435
|
# Upload and validate
|
|
426
|
-
arena env validate --source path/to/my_env.py
|
|
436
|
+
arena env validate my-custom-env --source path/to/my_env.py
|
|
427
437
|
|
|
428
438
|
# Train on validated custom environment
|
|
429
439
|
arena experiments submit path/to/manifest.yaml --project my-project
|
|
430
440
|
```
|
|
431
441
|
|
|
432
|
-
For the full CLI and Python SDK reference
|
|
442
|
+
For the full CLI and Python SDK reference, including authentication, environment validation, experiments, and deployment, see the [Arena Client](https://docs.agilerl.com/en/latest/arena/index.html) documentation.
|
|
433
443
|
|
|
434
444
|
## Tutorials
|
|
435
445
|
|
|
@@ -23,7 +23,7 @@ AgileRL is a Deep Reinforcement Learning library focused on improving developmen
|
|
|
23
23
|
|
|
24
24
|
This library is initially focused on reducing the time taken for training models and hyperparameter optimization (HPO) by pioneering [evolutionary HPO techniques](https://docs.agilerl.com/en/latest/evo_hyperparam_opt/index.html) for reinforcement learning.<br>
|
|
25
25
|
Evolutionary HPO has been shown to drastically reduce overall training times by automatically converging on optimal hyperparameters, without requiring numerous training runs.<br>
|
|
26
|
-
We are constantly adding more algorithms and features. AgileRL already includes state-of-the-art evolvable [on-policy](https://docs.agilerl.com/en/latest/on_policy/index.html), [off-policy](https://docs.agilerl.com/en/latest/off_policy/index.html), [offline](https://docs.agilerl.com/en/latest/offline_training/index.html), [multi-agent](https://docs.agilerl.com/en/latest/multi_agent_training/index.html) and [contextual multi-armed bandit](https://docs.agilerl.com/en/latest/bandits/index.html) reinforcement learning algorithms with [distributed training](https://docs.agilerl.com/en/latest/distributed_training/index.html).
|
|
26
|
+
We are constantly adding more algorithms and features. AgileRL already includes state-of-the-art evolvable [LLM fine-tuning](https://docs.agilerl.com/en/latest/llm_finetuning/index.html), [on-policy](https://docs.agilerl.com/en/latest/on_policy/index.html), [off-policy](https://docs.agilerl.com/en/latest/off_policy/index.html), [offline](https://docs.agilerl.com/en/latest/offline_training/index.html), [multi-agent](https://docs.agilerl.com/en/latest/multi_agent_training/index.html) and [contextual multi-armed bandit](https://docs.agilerl.com/en/latest/bandits/index.html) reinforcement learning algorithms with [distributed training](https://docs.agilerl.com/en/latest/distributed_training/index.html).
|
|
27
27
|
|
|
28
28
|
<p align="center">
|
|
29
29
|
<img src=https://user-images.githubusercontent.com/47857277/236407686-21363eb3-ffcf-419f-b019-0be4ddf1ed4a.gif width="100%" max-width="900">
|
|
@@ -41,6 +41,16 @@ We are constantly adding more algorithms and features. AgileRL already includes
|
|
|
41
41
|
|
|
42
42
|
## Benchmarks
|
|
43
43
|
|
|
44
|
+
### LLM Fine-tuning
|
|
45
|
+
|
|
46
|
+
AgileRL's multi-turn LLM training enables state-of-the-art performance on long-horizon tasks with small models. In the following example, AgileRL's CISPO was benchmarked against ART and TRL on the <a href="https://github.com/axon-rl/gem">GEM</a> Sudoku Hard task. This is a difficult multi-turn problem, which requires a context length of 32k tokens and up to 50 turns per rollout. The sync AgileRL run is a single agent using the AgileRL framework. The async and HPO runs were performed on <a href="https://arena.agilerl.com">Arena</a>, AgileRL's RLOps platform. All runs used the same starting hyperparameters. AgileRL runs were run on A100 40GB nodes, whereas ART and TRL required A100 80GB nodes due to a lack of optimizations. AgileRL runs significantly outperformed those using the ART and TRL frameworks.
|
|
47
|
+
|
|
48
|
+
<p align="center">
|
|
49
|
+
<img src="https://raw.githubusercontent.com/AgileRL/AgileRL/main/docs/_static/multi_turn_llm_benchmarks.png" min-width="100%" width="700">
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
### Classic RL
|
|
53
|
+
|
|
44
54
|
Reinforcement learning algorithms and libraries are usually benchmarked once the optimal hyperparameters for training are known, but it often takes hundreds or thousands of experiments to discover these. This is unrealistic and does not reflect the true, total time taken for training. What if we could remove the need to conduct all these prior experiments?
|
|
45
55
|
|
|
46
56
|
In the charts below, a single AgileRL run, which automatically tunes hyperparameters, is benchmarked against Optuna's multiple training runs traditionally required for hyperparameter optimization, demonstrating the real time savings possible. Global steps is the sum of every step taken by any agent in the environment, including across an entire population.
|
|
@@ -338,10 +348,10 @@ Use the `ArenaClient` to interact with Arena programmatically from scripts or no
|
|
|
338
348
|
from agilerl.arena import ArenaClient
|
|
339
349
|
|
|
340
350
|
client = ArenaClient()
|
|
341
|
-
client.login()
|
|
351
|
+
client.login() # OAuth2 device-flow authentication
|
|
342
352
|
|
|
343
|
-
#
|
|
344
|
-
client.validate_environment(source="path/to/my_env.py")
|
|
353
|
+
# Upload and validate a custom environment
|
|
354
|
+
client.validate_environment(name="my-custom-env", source="path/to/my_env.py")
|
|
345
355
|
|
|
346
356
|
# Train on validated custom environment
|
|
347
357
|
client.submit_experiment(
|
|
@@ -359,13 +369,13 @@ The same operations are available from the command line:
|
|
|
359
369
|
arena login
|
|
360
370
|
|
|
361
371
|
# Upload and validate
|
|
362
|
-
arena env validate --source path/to/my_env.py
|
|
372
|
+
arena env validate my-custom-env --source path/to/my_env.py
|
|
363
373
|
|
|
364
374
|
# Train on validated custom environment
|
|
365
375
|
arena experiments submit path/to/manifest.yaml --project my-project
|
|
366
376
|
```
|
|
367
377
|
|
|
368
|
-
For the full CLI and Python SDK reference
|
|
378
|
+
For the full CLI and Python SDK reference, including authentication, environment validation, experiments, and deployment, see the [Arena Client](https://docs.agilerl.com/en/latest/arena/index.html) documentation.
|
|
369
379
|
|
|
370
380
|
## Tutorials
|
|
371
381
|
|
|
@@ -4,9 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from agilerl.algorithms.grpo import GRPO
|
|
7
|
+
from agilerl.algorithms.grpo import GRPO
|
|
8
|
+
from agilerl.utils.algo_utils import inherit_init_signature
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
@inherit_init_signature(GRPO, fixed={"loss_type"})
|
|
10
12
|
class CISPO(GRPO):
|
|
11
13
|
"""CISPO loss variant of :class:`agilerl.algorithms.grpo.GRPO`
|
|
12
14
|
|
|
@@ -16,8 +18,3 @@ class CISPO(GRPO):
|
|
|
16
18
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
17
19
|
"""Initialize a CISPO agent with fixed ``loss_type``."""
|
|
18
20
|
super().__init__(*args, loss_type="cispo", **kwargs)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
_CISPO_CLASS_SIG, _CISPO_INIT_SIG = _signatures_without_loss_type()
|
|
22
|
-
CISPO.__signature__ = _CISPO_CLASS_SIG
|
|
23
|
-
CISPO.__init__.__signature__ = _CISPO_INIT_SIG
|
|
@@ -149,7 +149,6 @@ if TYPE_CHECKING or HAS_LLM_DEPENDENCIES:
|
|
|
149
149
|
build_vllm_llm_init_kwargs,
|
|
150
150
|
build_vllm_rollout_lora_request,
|
|
151
151
|
create_model_from_name_or_path,
|
|
152
|
-
format_colocated_vllm_oom_hint,
|
|
153
152
|
gather_if_zero3,
|
|
154
153
|
get_model_name_or_path,
|
|
155
154
|
get_state_dict,
|
|
@@ -164,8 +163,12 @@ if TYPE_CHECKING or HAS_LLM_DEPENDENCIES:
|
|
|
164
163
|
if TYPE_CHECKING or HAS_DEEPSPEED:
|
|
165
164
|
from deepspeed.checkpoint.utils import clone_tensors_for_torch_save
|
|
166
165
|
|
|
167
|
-
if TYPE_CHECKING
|
|
166
|
+
if TYPE_CHECKING:
|
|
167
|
+
from vllm import LLM, CompletionOutput, SamplingParams
|
|
168
|
+
elif HAS_VLLM:
|
|
168
169
|
from vllm import LLM, CompletionOutput, SamplingParams
|
|
170
|
+
else:
|
|
171
|
+
LLM = CompletionOutput = SamplingParams = None
|
|
169
172
|
|
|
170
173
|
__all__ = ["ActionResult", "EvolvableAlgorithm", "MultiAgentRLAlgorithm", "RLAlgorithm"]
|
|
171
174
|
|
|
@@ -173,8 +176,6 @@ logger = logging.getLogger(__name__)
|
|
|
173
176
|
|
|
174
177
|
SelfAgentWrapper = TypeVar("SelfAgentWrapper", bound=AgentWrapperProtocol)
|
|
175
178
|
|
|
176
|
-
logger = logging.getLogger(__name__)
|
|
177
|
-
|
|
178
179
|
|
|
179
180
|
class _RegistryMeta(type):
|
|
180
181
|
"""Metaclass to wrap registry information after algorithm is done
|
|
@@ -2239,18 +2240,10 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
2239
2240
|
:param lora_target_scope: Optional PEFT LoRA path scope for multimodal models
|
|
2240
2241
|
(e.g. ``"language_model"``). Passed to :func:`adapt_lora_config_for_model`.
|
|
2241
2242
|
:type lora_target_scope: str | None, optional
|
|
2242
|
-
:param
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
(default) auto-tunes to a ~256 MB fp32 tile.
|
|
2247
|
-
:type fused_logprobs_chunk_rows: int | None, optional
|
|
2248
|
-
:param fused_loss_chunk_rows: Rows per ``(chunk_rows, vocab)`` logit tile in
|
|
2249
|
-
the token-level Liger fused policy loss. ``None`` (default) auto-tunes to
|
|
2250
|
-
a ~256 MB fp32 logit workspace — the same heuristic as
|
|
2251
|
-
``fused_logprobs_chunk_rows`` on the standard path; pass an int to
|
|
2252
|
-
override.
|
|
2253
|
-
:type fused_loss_chunk_rows: int | None, optional
|
|
2243
|
+
:param chunk_rows: Primary chunk-size knob for fused logit tiles used by
|
|
2244
|
+
both the standard fused-logprob path and the Liger fused-loss path.
|
|
2245
|
+
``None`` (default) preserves each path's auto-tuned behavior.
|
|
2246
|
+
:type chunk_rows: int | None, optional
|
|
2254
2247
|
:param vllm_importance_sampling_correction: When ``True`` (default) and
|
|
2255
2248
|
``use_vllm=True``, correct the rollout/trainer log-prob mismatch by
|
|
2256
2249
|
weighting each training token by ``clamp(exp(trainer - sampling),
|
|
@@ -2339,8 +2332,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
2339
2332
|
activation_offload: bool = False,
|
|
2340
2333
|
use_sequence_packing: bool = False,
|
|
2341
2334
|
lora_target_scope: str | None = None,
|
|
2342
|
-
|
|
2343
|
-
fused_loss_chunk_rows: int | None = None,
|
|
2335
|
+
chunk_rows: int | None = None,
|
|
2344
2336
|
vllm_importance_sampling_correction: bool = True,
|
|
2345
2337
|
vllm_importance_sampling_cap: float = 2.0,
|
|
2346
2338
|
) -> None:
|
|
@@ -2503,10 +2495,10 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
2503
2495
|
self.wrap = wrap
|
|
2504
2496
|
self.use_separate_reference_adapter = use_separate_reference_adapter
|
|
2505
2497
|
self.cast_logprobs_to_fp32 = cast_logprobs_to_fp32
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
self.
|
|
2498
|
+
if chunk_rows is not None and chunk_rows <= 0:
|
|
2499
|
+
msg = f"chunk_rows must be a positive int or None, got {chunk_rows}."
|
|
2500
|
+
raise ValueError(msg)
|
|
2501
|
+
self.chunk_rows = chunk_rows
|
|
2510
2502
|
# vLLM sampling-mismatch correction (truncated importance sampling).
|
|
2511
2503
|
# The rollout is drawn from vLLM but the loss treats the trainer's
|
|
2512
2504
|
# recomputed ``old_log_probs`` as the behaviour policy; the two differ
|
|
@@ -2522,13 +2514,6 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
2522
2514
|
# Kept on even when use_vllm=False: decoupled rollouts still sample
|
|
2523
2515
|
# from a separate vLLM engine.
|
|
2524
2516
|
self._is_correction_liger_warned = False
|
|
2525
|
-
if fused_loss_chunk_rows is not None and fused_loss_chunk_rows <= 0:
|
|
2526
|
-
msg = (
|
|
2527
|
-
f"fused_loss_chunk_rows must be a positive int or None, "
|
|
2528
|
-
f"got {fused_loss_chunk_rows}."
|
|
2529
|
-
)
|
|
2530
|
-
raise ValueError(msg)
|
|
2531
|
-
self.fused_loss_chunk_rows = fused_loss_chunk_rows
|
|
2532
2517
|
# Warn-once flag for the canonical Liger + non-token importance-sampling
|
|
2533
2518
|
# "not memory-bounded" warning (see :meth:`_warn_liger_non_token_is`).
|
|
2534
2519
|
self._liger_non_token_warned = False
|
|
@@ -2553,6 +2538,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
2553
2538
|
self._vllm_moved = False
|
|
2554
2539
|
self._vllm_lora_loaded = False
|
|
2555
2540
|
self._vllm_lora_staging_dir: Path | None = None
|
|
2541
|
+
self._vllm_lora_staging_dir_is_temp = True
|
|
2556
2542
|
self._vllm_rollout_lora_request: Any | None = None
|
|
2557
2543
|
# Colocated vLLM (use_vllm=True) runs the rollout engine and the HF
|
|
2558
2544
|
# trainer in one process. Each holds its OWN base: vLLM cycles its base
|
|
@@ -4201,7 +4187,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4201
4187
|
fused_ids[start:end, 1:],
|
|
4202
4188
|
temperature=self.temperature,
|
|
4203
4189
|
cast_to_fp32=self.cast_logprobs_to_fp32,
|
|
4204
|
-
|
|
4190
|
+
chunk_rows=self.chunk_rows,
|
|
4205
4191
|
)
|
|
4206
4192
|
del first
|
|
4207
4193
|
|
|
@@ -4376,7 +4362,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4376
4362
|
packed.input_ids[:, 1:],
|
|
4377
4363
|
temperature=self.temperature,
|
|
4378
4364
|
cast_to_fp32=self.cast_logprobs_to_fp32,
|
|
4379
|
-
|
|
4365
|
+
chunk_rows=self.chunk_rows,
|
|
4380
4366
|
)
|
|
4381
4367
|
log_probs = unpack_logprobs(packed_lp, packed)
|
|
4382
4368
|
|
|
@@ -4600,7 +4586,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4600
4586
|
packed.input_ids[:, 1:],
|
|
4601
4587
|
temperature=self.temperature,
|
|
4602
4588
|
cast_to_fp32=self.cast_logprobs_to_fp32,
|
|
4603
|
-
|
|
4589
|
+
chunk_rows=self.chunk_rows,
|
|
4604
4590
|
)
|
|
4605
4591
|
# Map back to the dense (mb, T-1) frame so the loss path is
|
|
4606
4592
|
# unchanged; cross-segment boundary predictions are dropped.
|
|
@@ -4614,7 +4600,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4614
4600
|
batch_ids[:, 1:],
|
|
4615
4601
|
temperature=self.temperature,
|
|
4616
4602
|
cast_to_fp32=self.cast_logprobs_to_fp32,
|
|
4617
|
-
|
|
4603
|
+
chunk_rows=self.chunk_rows,
|
|
4618
4604
|
)
|
|
4619
4605
|
|
|
4620
4606
|
first = None
|
|
@@ -4696,13 +4682,17 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4696
4682
|
def _ensure_vllm_lora_staging_dir(self) -> Path:
|
|
4697
4683
|
"""Resolve (once) the dir the rollout LoRA adapter is exported to.
|
|
4698
4684
|
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4685
|
+
The staging dir is always process-private: each rank exports its own
|
|
4686
|
+
adapter copy and reads it back locally, so ranks never race on shared
|
|
4687
|
+
files. Honours ``VLLMConfig.lora_staging_dir`` when set — e.g. a known
|
|
4688
|
+
path that orchestrated deployments expect the adapter under — staging
|
|
4689
|
+
in a ``rank_<process_index>`` subdirectory of that root when
|
|
4690
|
+
distributed. The dir is created (parents included) and marked
|
|
4691
|
+
non-temporary so ``clean_up`` never deletes it. Otherwise falls back
|
|
4692
|
+
to a process-private ``mkdtemp`` that ``clean_up`` removes.
|
|
4693
|
+
Idempotent: both the colocated init (``_configure_vllm``) and every
|
|
4694
|
+
adapter sync (``_move_lora_to_vllm``) call this, so the same directory
|
|
4695
|
+
is used throughout the agent's life.
|
|
4706
4696
|
|
|
4707
4697
|
:return: The resolved staging directory.
|
|
4708
4698
|
:rtype: pathlib.Path
|
|
@@ -4710,8 +4700,11 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4710
4700
|
if self._vllm_lora_staging_dir is None:
|
|
4711
4701
|
configured = getattr(self.vllm_config, "lora_staging_dir", None)
|
|
4712
4702
|
if configured is not None:
|
|
4713
|
-
|
|
4714
|
-
self.
|
|
4703
|
+
staging_dir = Path(configured)
|
|
4704
|
+
if self.accelerator is not None and self.accelerator.num_processes > 1:
|
|
4705
|
+
staging_dir = staging_dir / f"rank_{self.accelerator.process_index}"
|
|
4706
|
+
staging_dir.mkdir(parents=True, exist_ok=True)
|
|
4707
|
+
self._vllm_lora_staging_dir = staging_dir
|
|
4715
4708
|
self._vllm_lora_staging_dir_is_temp = False
|
|
4716
4709
|
else:
|
|
4717
4710
|
self._vllm_lora_staging_dir = Path(
|
|
@@ -4734,12 +4727,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4734
4727
|
peft_ref = self._get_peft_model_for_vllm_sync()
|
|
4735
4728
|
peft_ref.set_adapter(self._vllm_rollout_adapter)
|
|
4736
4729
|
|
|
4737
|
-
# Export to a fixed staging dir + id and refresh the resident rollout
|
|
4738
|
-
# slot in place: ``load_inplace`` (2nd sync onward) re-reads the updated
|
|
4739
|
-
# weights from disk, and the fixed id avoids per-sync CUDA-graph
|
|
4740
|
-
# accumulation that would grow GPU memory across iterations.
|
|
4741
4730
|
staging_dir = self._ensure_vllm_lora_staging_dir()
|
|
4742
|
-
is_main_process = self.accelerator is None or self.accelerator.is_main_process
|
|
4743
4731
|
with gather_if_zero3(self.zero_stage, list(peft_ref.parameters())):
|
|
4744
4732
|
if self.lora_config is None:
|
|
4745
4733
|
msg = "lora_config is required for vLLM LoRA adapter export."
|
|
@@ -4749,33 +4737,9 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4749
4737
|
staging_dir,
|
|
4750
4738
|
self._vllm_rollout_adapter,
|
|
4751
4739
|
target_modules=self.lora_config.target_modules,
|
|
4752
|
-
is_main_process=is_main_process,
|
|
4753
4740
|
)
|
|
4754
4741
|
if self.accelerator is not None:
|
|
4755
4742
|
self.accelerator.wait_for_everyone()
|
|
4756
|
-
if not adapter_path.is_dir():
|
|
4757
|
-
msg = (
|
|
4758
|
-
f"PEFT adapter export for {self._vllm_rollout_adapter!r} not found under "
|
|
4759
|
-
f"{staging_dir}. Expected {adapter_path} or adapter_config.json in "
|
|
4760
|
-
f"{staging_dir}."
|
|
4761
|
-
)
|
|
4762
|
-
raise FileNotFoundError(msg)
|
|
4763
|
-
|
|
4764
|
-
if is_main_process and logger.isEnabledFor(logging.DEBUG):
|
|
4765
|
-
# Sum of L2 norms of the trained-from-zero LoRA-B weights; a value
|
|
4766
|
-
# that changes across syncs confirms the trainer is exporting
|
|
4767
|
-
# updated weights into the rollout adapter. Gated on the standard
|
|
4768
|
-
# logging level (the norm reduction costs a GPU sync).
|
|
4769
|
-
lora_b_sq = sum(
|
|
4770
|
-
float(p.detach().float().pow(2).sum().item())
|
|
4771
|
-
for n, p in peft_ref.named_parameters()
|
|
4772
|
-
if "lora_B" in n and self._vllm_rollout_adapter in n
|
|
4773
|
-
)
|
|
4774
|
-
logger.debug(
|
|
4775
|
-
"lora-sync: actor lora_B L2=%.6f path=%s",
|
|
4776
|
-
lora_b_sq**0.5,
|
|
4777
|
-
adapter_path,
|
|
4778
|
-
)
|
|
4779
4743
|
|
|
4780
4744
|
# One-shot refresh of the resident slot. ``load_inplace`` forces vLLM to
|
|
4781
4745
|
# re-read the (updated) adapter weights from disk; required from the second
|
|
@@ -4784,11 +4748,19 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
4784
4748
|
adapter_path,
|
|
4785
4749
|
load_inplace=self._vllm_lora_loaded,
|
|
4786
4750
|
)
|
|
4787
|
-
|
|
4751
|
+
lora_device = torch.device(self.device)
|
|
4752
|
+
if lora_device.type == "cuda":
|
|
4753
|
+
# Pin the CUDA context to this agent's device: vLLM's LoRA copy
|
|
4754
|
+
# kernels otherwise launch on the process-default device.
|
|
4755
|
+
with torch.cuda.device(lora_device):
|
|
4756
|
+
loaded = self.llm.llm_engine.add_lora(refresh_request)
|
|
4757
|
+
else:
|
|
4758
|
+
loaded = self.llm.llm_engine.add_lora(refresh_request)
|
|
4788
4759
|
if not loaded:
|
|
4789
4760
|
msg = (
|
|
4790
|
-
|
|
4791
|
-
"Check max_lora_rank / target module
|
|
4761
|
+
"vLLM failed to load LoRA adapter from "
|
|
4762
|
+
f"{adapter_path}. Check max_lora_rank / target module "
|
|
4763
|
+
"names match the trainer."
|
|
4792
4764
|
)
|
|
4793
4765
|
raise RuntimeError(msg)
|
|
4794
4766
|
|
|
@@ -5077,13 +5049,13 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5077
5049
|
logits: torch.Tensor,
|
|
5078
5050
|
index: torch.Tensor,
|
|
5079
5051
|
cast_to_fp32: bool = True,
|
|
5080
|
-
|
|
5052
|
+
chunk_rows: int = 1,
|
|
5081
5053
|
) -> torch.Tensor:
|
|
5082
5054
|
"""Calculate log probabilities for previously generated token ids.
|
|
5083
5055
|
|
|
5084
|
-
Processes ``
|
|
5085
|
-
``(
|
|
5086
|
-
OOM on large-vocabulary models. Default ``
|
|
5056
|
+
Processes ``chunk_rows`` rows at a time so peak memory stays bounded to
|
|
5057
|
+
``(chunk_rows, seq_len, vocab_size)`` rather than the full batch, avoiding
|
|
5058
|
+
OOM on large-vocabulary models. Default ``chunk_rows=1`` minimizes the
|
|
5087
5059
|
fp32 workspace at the cost of more kernel launches; raise to amortize
|
|
5088
5060
|
launch overhead when memory headroom allows.
|
|
5089
5061
|
|
|
@@ -5120,12 +5092,12 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5120
5092
|
result = target - log_z
|
|
5121
5093
|
return result.to(orig_dtype) if cast_to_fp32 else result
|
|
5122
5094
|
|
|
5123
|
-
if B <=
|
|
5095
|
+
if B <= chunk_rows:
|
|
5124
5096
|
return _logprobs_chunk(logits, index)
|
|
5125
5097
|
|
|
5126
5098
|
per_token_logps = []
|
|
5127
|
-
for start in range(0, B,
|
|
5128
|
-
end = min(start +
|
|
5099
|
+
for start in range(0, B, chunk_rows):
|
|
5100
|
+
end = min(start + chunk_rows, B)
|
|
5129
5101
|
per_token_logps.append(
|
|
5130
5102
|
_logprobs_chunk(logits[start:end], index[start:end]),
|
|
5131
5103
|
)
|
|
@@ -5135,10 +5107,9 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5135
5107
|
def _resolve_fused_chunk_rows(vocab_size: int, explicit: int | None = None) -> int:
|
|
5136
5108
|
"""Rows per fused ``(chunk_rows, vocab)`` logit tile.
|
|
5137
5109
|
|
|
5138
|
-
Shared by the fused-linear-logprob (standard) path
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
workspace identically. A positive ``explicit`` overrides; ``None``
|
|
5110
|
+
Shared by the fused-linear-logprob (standard) path and the Liger
|
|
5111
|
+
fused-loss path so both bound their per-chunk logit workspace
|
|
5112
|
+
identically. A positive ``explicit`` overrides; ``None``
|
|
5142
5113
|
auto-tunes to a ~256 MB fp32 logit workspace (fewer rows at larger
|
|
5143
5114
|
vocab), clamped to ``[128, 4096]``.
|
|
5144
5115
|
|
|
@@ -5162,12 +5133,12 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5162
5133
|
target_ids: torch.Tensor,
|
|
5163
5134
|
temperature: float = 1.0,
|
|
5164
5135
|
cast_to_fp32: bool = True,
|
|
5165
|
-
|
|
5136
|
+
chunk_rows: int | None = None,
|
|
5166
5137
|
) -> torch.Tensor:
|
|
5167
5138
|
"""Per-token target logprobs without materializing the full ``(B, T, V)``
|
|
5168
5139
|
logits tensor.
|
|
5169
5140
|
|
|
5170
|
-
Tiles flat over ``(B*T)`` with workspace bounded to ``(
|
|
5141
|
+
Tiles flat over ``(B*T)`` with workspace bounded to ``(chunk_rows, V)``
|
|
5171
5142
|
per iteration. Counterpart of :meth:`_logprobs_from_logits` for
|
|
5172
5143
|
callers that hold hidden states and the lm_head separately. **No-grad
|
|
5173
5144
|
only** — gradients won't flow to ``lm_head_weight`` from this fn. The
|
|
@@ -5195,16 +5166,16 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5195
5166
|
in fp32 then cast back. Same semantics as
|
|
5196
5167
|
:meth:`_logprobs_from_logits`.
|
|
5197
5168
|
:type cast_to_fp32: bool, optional
|
|
5198
|
-
:param
|
|
5199
|
-
iteration; trades launch count vs ``
|
|
5169
|
+
:param chunk_rows: rows of the flattened ``(B*T)`` workspace per
|
|
5170
|
+
iteration; trades launch count vs ``chunk_rows * V`` peak. When
|
|
5200
5171
|
``None`` (default) it is resolved from the vocab size via
|
|
5201
5172
|
a ~256 MB fp32 workspace heuristic.
|
|
5202
|
-
:type
|
|
5173
|
+
:type chunk_rows: int | None, optional
|
|
5203
5174
|
:return: ``(B, T)`` per-token logprobs in ``hidden.dtype``.
|
|
5204
5175
|
:rtype: torch.Tensor
|
|
5205
5176
|
"""
|
|
5206
|
-
|
|
5207
|
-
lm_head_weight.shape[0],
|
|
5177
|
+
chunk_rows = LLMAlgorithm._resolve_fused_chunk_rows(
|
|
5178
|
+
lm_head_weight.shape[0], chunk_rows
|
|
5208
5179
|
)
|
|
5209
5180
|
return fused_linear_logprobs_chunked(
|
|
5210
5181
|
hidden,
|
|
@@ -5213,7 +5184,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5213
5184
|
target_ids,
|
|
5214
5185
|
temperature=temperature,
|
|
5215
5186
|
cast_to_fp32=cast_to_fp32,
|
|
5216
|
-
chunk_rows=
|
|
5187
|
+
chunk_rows=chunk_rows,
|
|
5217
5188
|
)
|
|
5218
5189
|
|
|
5219
5190
|
@staticmethod
|
|
@@ -5224,7 +5195,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5224
5195
|
target_ids: torch.Tensor,
|
|
5225
5196
|
temperature: float = 1.0,
|
|
5226
5197
|
cast_to_fp32: bool = True,
|
|
5227
|
-
|
|
5198
|
+
chunk_rows: int | None = None,
|
|
5228
5199
|
) -> torch.Tensor:
|
|
5229
5200
|
"""Gradient-aware version of :meth:`_logprobs_from_hidden_fused`.
|
|
5230
5201
|
|
|
@@ -5250,15 +5221,15 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5250
5221
|
:type temperature: float, optional
|
|
5251
5222
|
:param cast_to_fp32: run the per-chunk reduction in fp32.
|
|
5252
5223
|
:type cast_to_fp32: bool, optional
|
|
5253
|
-
:param
|
|
5224
|
+
:param chunk_rows: rows of the flattened ``(B*T)`` workspace per chunk.
|
|
5254
5225
|
When ``None`` (default) it is resolved from the vocab size via
|
|
5255
5226
|
a ~256 MB fp32 workspace heuristic.
|
|
5256
|
-
:type
|
|
5227
|
+
:type chunk_rows: int | None, optional
|
|
5257
5228
|
:return: ``(B, T)`` per-token logprobs in ``hidden.dtype``.
|
|
5258
5229
|
:rtype: torch.Tensor
|
|
5259
5230
|
"""
|
|
5260
|
-
|
|
5261
|
-
lm_head_weight.shape[0],
|
|
5231
|
+
chunk_rows = LLMAlgorithm._resolve_fused_chunk_rows(
|
|
5232
|
+
lm_head_weight.shape[0], chunk_rows
|
|
5262
5233
|
)
|
|
5263
5234
|
return FusedLinearLogProbsFunction.apply(
|
|
5264
5235
|
hidden,
|
|
@@ -5267,7 +5238,7 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5267
5238
|
target_ids,
|
|
5268
5239
|
temperature,
|
|
5269
5240
|
cast_to_fp32,
|
|
5270
|
-
|
|
5241
|
+
chunk_rows,
|
|
5271
5242
|
)
|
|
5272
5243
|
|
|
5273
5244
|
def _configure_batch_size_per_process(
|
|
@@ -5729,10 +5700,11 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5729
5700
|
def _sleep_vllm_after_init(self) -> None:
|
|
5730
5701
|
"""Put the colocated engine to sleep once after construction.
|
|
5731
5702
|
|
|
5732
|
-
Native ``sleep(level=
|
|
5733
|
-
the
|
|
5703
|
+
Native ``sleep(level=sleep_mode_level)``: vLLM cycles its allocator
|
|
5704
|
+
state based on the configured sleep level; ``wake_up()`` restores the
|
|
5705
|
+
engine allocations.
|
|
5734
5706
|
"""
|
|
5735
|
-
self.llm.sleep(level=
|
|
5707
|
+
self.llm.sleep(level=self.vllm_config.sleep_mode_level)
|
|
5736
5708
|
self._vllm_awake = False
|
|
5737
5709
|
if self.accelerator is None or self.accelerator.is_main_process:
|
|
5738
5710
|
log_cuda_memory_snapshot("vLLM sleep complete")
|
|
@@ -5745,8 +5717,6 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5745
5717
|
return
|
|
5746
5718
|
|
|
5747
5719
|
ds_plugin = getattr(self.accelerator.state, "deepspeed_plugin", None)
|
|
5748
|
-
if ds_plugin is None:
|
|
5749
|
-
return
|
|
5750
5720
|
|
|
5751
5721
|
ds_config = ds_plugin.deepspeed_config
|
|
5752
5722
|
if "gradient_clipping" not in ds_config:
|
|
@@ -5860,15 +5830,16 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5860
5830
|
|
|
5861
5831
|
def _prepare_vllm_for_training(self) -> None:
|
|
5862
5832
|
"""Prepare vLLM for learning."""
|
|
5863
|
-
if self.
|
|
5864
|
-
|
|
5865
|
-
)
|
|
5833
|
+
if not self.use_vllm:
|
|
5834
|
+
return
|
|
5835
|
+
# Every rank holds its own colocated engine (external_launcher), so
|
|
5836
|
+
# every rank must sleep it — not just the main process.
|
|
5837
|
+
if self.vllm_config.sleep_mode and self._vllm_awake:
|
|
5866
5838
|
torch.cuda.empty_cache()
|
|
5867
|
-
self.llm.sleep(level=
|
|
5839
|
+
self.llm.sleep(level=self.vllm_config.sleep_mode_level)
|
|
5868
5840
|
self._vllm_awake = False
|
|
5869
5841
|
|
|
5870
|
-
|
|
5871
|
-
self._vllm_moved = False
|
|
5842
|
+
self._vllm_moved = False
|
|
5872
5843
|
|
|
5873
5844
|
def _prepare_vllm_for_generation(self) -> None:
|
|
5874
5845
|
if self.use_memory_efficient_params:
|
|
@@ -5881,35 +5852,11 @@ class LLMAlgorithm(EvolvableAlgorithm, ABC):
|
|
|
5881
5852
|
log_cuda_memory_snapshot(
|
|
5882
5853
|
"trainer base offloaded to CPU (before vLLM wake)"
|
|
5883
5854
|
)
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5855
|
+
# Every rank holds its own colocated engine, and _sleep_vllm_after_init
|
|
5856
|
+
# slept them all; we wake them all here.
|
|
5857
|
+
if self.vllm_config.sleep_mode and not self._vllm_awake:
|
|
5887
5858
|
torch.cuda.empty_cache()
|
|
5888
|
-
|
|
5889
|
-
self.accelerator.local_process_index
|
|
5890
|
-
if self.accelerator is not None
|
|
5891
|
-
else 0
|
|
5892
|
-
)
|
|
5893
|
-
try:
|
|
5894
|
-
self.llm.wake_up()
|
|
5895
|
-
except RuntimeError as err: # pragma: no cover
|
|
5896
|
-
err_text = str(err).lower()
|
|
5897
|
-
if "out of memory" in err_text or "cuda error" in err_text:
|
|
5898
|
-
vcfg = self.vllm_config
|
|
5899
|
-
hint = format_colocated_vllm_oom_hint(
|
|
5900
|
-
device_index,
|
|
5901
|
-
kv_cache_memory_bytes=(
|
|
5902
|
-
vcfg.kv_cache_memory_bytes if vcfg is not None else None
|
|
5903
|
-
),
|
|
5904
|
-
gpu_memory_utilization=(
|
|
5905
|
-
vcfg.gpu_memory_utilization if vcfg is not None else None
|
|
5906
|
-
),
|
|
5907
|
-
max_model_len=getattr(self, "max_model_len", None),
|
|
5908
|
-
trainer_on_gpu=not self.use_memory_efficient_params,
|
|
5909
|
-
)
|
|
5910
|
-
msg = f"vLLM wake_up failed (GPU OOM).\n{hint}"
|
|
5911
|
-
raise RuntimeError(msg) from err
|
|
5912
|
-
raise
|
|
5859
|
+
self.llm.wake_up()
|
|
5913
5860
|
self._vllm_awake = True
|
|
5914
5861
|
if self.accelerator is None or self.accelerator.is_main_process:
|
|
5915
5862
|
log_cuda_memory_snapshot("vLLM base restored on GPU (after wake)")
|