Repository: modelscope/Trinity-RFT
Pull request #42: Move `algorithm_type` from `trainer` to `global_config`
Author: login: chenyushuo
Created: 2025-05-20T07:34:14Z | Merged: 2025-05-20T08:36:52Z

## Description

As title says.


## Checklist

Please check the following items before code is ready to be reviewed.

- [x]  Code has passed all tests
- [x]  Docstrings have been added/updated in Google Style
- [x]  Documentation has been updated
- [x]  Code is ready for review



Diff:
diff --git a/docs/sphinx_doc/source/tutorial/example_dpo.md b/docs/sphinx_doc/source/tutorial/example_dpo.md
index 5d274fbb476..8bbf3d91997 100644
--- a/docs/sphinx_doc/source/tutorial/example_dpo.md
+++ b/docs/sphinx_doc/source/tutorial/example_dpo.md
@@ -56,7 +56,7 @@ buffer:
       prompt_key: <prompt_key>
       chosen_key: <chosen_key>
       rejected_key: <rejected_key>
-trainer:
+global_config:
   algorithm_type: dpo
 
 # In train_dpo.yaml
diff --git a/docs/sphinx_doc/source/tutorial/trinity_configs.md b/docs/sphinx_doc/source/tutorial/trinity_configs.md
index 430f8724899..ec9372cc343 100644
--- a/docs/sphinx_doc/source/tutorial/trinity_configs.md
+++ b/docs/sphinx_doc/source/tutorial/trinity_configs.md
@@ -7,6 +7,7 @@ The following is the main config file for Trinity-RFT. Take `countdown.yaml` as
 ```yaml
 mode: both
 global_config:
+  algorithm_type: ppo
   total_epochs: 1
   batch_size: 96
   eval_interval: 1000
@@ -14,6 +15,7 @@ global_config:
 ```
 
 - `mode`: The mode of the experiment, chosen from `both`, `train`, `explore` or `bench`. `both` means both trainer and explorer are launched; `train` means only trainer is launched; `explore` means only explorer is launched; `bench` conducts benchmark evaluation. Default is `both`.
+- `global_config.algorithm_type`: The type of the algorithm, Support `ppo`, `grpo`, `opmd` and `dpo`.
 - `global_config.total_epochs`: The total number of epochs. It should be checked manually.
 - `global_config.batch_size`: The batch size used for training. It should be checked manually.
 - `global_config.eval_interval`: The interval steps between two evaluations. Default is `1000`.
@@ -192,7 +194,6 @@ Support `nccl` and `checkpoint`, `nccl` represents that model weights in `explor
 ```yaml
 trainer:
   trainer_type: 'verl'
-  algorithm_type: ppo
   trainer_config_path: 'examples/ppo_countdown/train_countdown.yaml'
   sft_warmup_steps: 0
   eval_interval: 1000
@@ -200,7 +201,6 @@ trainer:
 ```
 
 - `trainer.trainer_type`: The backend of the trainer, Only `verl` is supported.
-- `trainer.algorithm_type`: The type of the algorithm, Support `ppo`, `grpo`, `opmd` and `dpo`.
 - `trainer.trainer_config_path`: The path to the trainer configuration file. It must be set manually.
 - `trainer.sft_warmup_steps`: The number of steps to warm up the model. Default is `0`.
 - `trainer.eval_interval`: The interval steps between two evaluations. Default is `1000`.
diff --git a/examples/async_gsm8k/explorer.yaml b/examples/async_gsm8k/explorer.yaml
index 673da76a59a..8402e4ced23 100644
--- a/examples/async_gsm8k/explorer.yaml
+++ b/examples/async_gsm8k/explorer.yaml
@@ -3,6 +3,7 @@ global_config:
   total_epochs: 20
   batch_size: 96
   eval_interval: 10
+  algorithm_type: grpo
 model:
   model_path: /PATH/TO/MODEL/
   max_prompt_tokens: 256
@@ -51,7 +52,6 @@ synchronizer:
   sync_iteration_interval: 10
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: examples/async_gsm8k/verl_config.yaml
   sft_warmup_steps: 0 # Set to integer to enable sft warmup
 monitor:
diff --git a/examples/async_gsm8k/trainer.yaml b/examples/async_gsm8k/trainer.yaml
index df193c3f374..79a50337d20 100644
--- a/examples/async_gsm8k/trainer.yaml
+++ b/examples/async_gsm8k/trainer.yaml
@@ -3,6 +3,7 @@ global_config:
   total_epochs: 20
   batch_size: 96
   eval_interval: 10
+  algorithm_type: grpo
 model:
   model_path: /PATH/TO/MODEL/
   max_prompt_tokens: 256
@@ -50,7 +51,6 @@ synchronizer:
   sync_iteration_interval: 10
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: examples/async_gsm8k/verl_config.yaml
   sft_warmup_steps: 0 # Set to integer to enable sft warmup
 monitor:
diff --git a/examples/dpo_humanlike/dpo.yaml b/examples/dpo_humanlike/dpo.yaml
index de459f92306..825788a7929 100644
--- a/examples/dpo_humanlike/dpo.yaml
+++ b/examples/dpo_humanlike/dpo.yaml
@@ -2,6 +2,7 @@ mode: train
 global_config:
   total_epochs: 20
   batch_size: 32 # NOTE
+  algorithm_type: dpo
 model:
   model_path: '/PATH/TO/MODEL/CHECKPOINT/' # NOTE
   max_prompt_tokens: 1792
@@ -29,7 +30,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: dpo
   trainer_config_path: 'examples/dpo_humanlike/train_dpo.yaml'
   save_interval: 30
 monitor:
diff --git a/examples/grpo_alfworld/alfworld.yaml b/examples/grpo_alfworld/alfworld.yaml
index 18dc2595e66..08a9fd8e42b 100644
--- a/examples/grpo_alfworld/alfworld.yaml
+++ b/examples/grpo_alfworld/alfworld.yaml
@@ -1,6 +1,7 @@
 global_config:
   total_epochs: 20
   batch_size: 4
+  algorithm_type: grpo
 model:
   model_path: '/PATH/TO/MODEL/CHECKPOINT/'
   max_prompt_tokens: 4096
@@ -50,7 +51,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: 'examples/grpo_alfworld/train_alfworld.yaml'
   save_interval: 10
 monitor:
diff --git a/examples/grpo_gsm8k/gsm8k.yaml b/examples/grpo_gsm8k/gsm8k.yaml
index 748a5ac0e58..71630adaac0 100644
--- a/examples/grpo_gsm8k/gsm8k.yaml
+++ b/examples/grpo_gsm8k/gsm8k.yaml
@@ -15,6 +15,7 @@ global_config:
   total_epochs: 1
   batch_size: 96
   eval_interval: 50
+  algorithm_type: grpo
 model:
   model_path: '/PATH/TO/MODEL/'
   max_prompt_tokens: 256
@@ -80,7 +81,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: 'examples/grpo_gsm8k/train_gsm8k.yaml'
   sft_warmup_steps: 0 # Set to integer to enable sft warmup
   save_interval: 100
diff --git a/examples/grpo_math/math.yaml b/examples/grpo_math/math.yaml
index b22291b09ad..a1527d9255e 100644
--- a/examples/grpo_math/math.yaml
+++ b/examples/grpo_math/math.yaml
@@ -2,6 +2,7 @@ global_config:
   total_epochs: 20
   batch_size: 288
   eval_interval: 10
+  algorithm_type: grpo
 model:
   model_path: /PATH/TO/MODEL/
   max_prompt_tokens: 1024
@@ -50,7 +51,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: 'examples/grpo_math/train_math.yaml'
   sft_warmup_steps: 0 # Set to integer to enable sft warmup
   save_interval: 100
diff --git a/examples/grpo_sciworld/sciworld.yaml b/examples/grpo_sciworld/sciworld.yaml
index 6ba88d51e22..350b37ba80e 100644
--- a/examples/grpo_sciworld/sciworld.yaml
+++ b/examples/grpo_sciworld/sciworld.yaml
@@ -1,6 +1,7 @@
 global_config:
   total_epochs: 20
   batch_size: 4
+  algorithm_type: grpo
 model:
   model_path: '/PATH/TO/MODEL/CHECKPOINT/'
   max_prompt_tokens: 4096
@@ -50,7 +51,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: 'examples/grpo_sciworld/train_sciworld.yaml'
   save_interval: 10
 monitor:
diff --git a/examples/grpo_webshop/webshop.yaml b/examples/grpo_webshop/webshop.yaml
index d5b59d67b05..0ae7563db25 100644
--- a/examples/grpo_webshop/webshop.yaml
+++ b/examples/grpo_webshop/webshop.yaml
@@ -1,6 +1,7 @@
 global_config:
   total_epochs: 20
   batch_size: 4
+  algorithm_type: grpo
 model:
   model_path: '/PATH/TO/MODEL/CHECKPOINT/'
   max_prompt_tokens: 4096
@@ -50,7 +51,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: grpo
   trainer_config_path: 'examples/grpo_webshop/train_webshop.yaml'
   save_interval: 10
 monitor:
diff --git a/examples/opmd_gsm8k/opmd_gsm8k.yaml b/examples/opmd_gsm8k/opmd_gsm8k.yaml
index 4739400f1a6..7cc502eff2f 100644
--- a/examples/opmd_gsm8k/opmd_gsm8k.yaml
+++ b/examples/opmd_gsm8k/opmd_gsm8k.yaml
@@ -1,6 +1,7 @@
 global_config:
   total_epochs: 1
   batch_size: 96
+  algorithm_type: opmd
 model:
   model_path: '{path to models}/Qwen2.5-1.5B-Inst'
   max_prompt_tokens: 256
@@ -49,7 +50,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: opmd
   trainer_config_path: 'examples/opmd_gsm8k/train_opmd_gsm8k.yaml'
   sft_warmup_steps: 0
   save_interval: 100
diff --git a/examples/ppo_countdown/countdown.yaml b/examples/ppo_countdown/countdown.yaml
index f7ad9c4362c..c428a167b47 100644
--- a/examples/ppo_countdown/countdown.yaml
+++ b/examples/ppo_countdown/countdown.yaml
@@ -2,6 +2,7 @@ global_config:
   total_epochs: 20
   batch_size: 96
   eval_interval: 1000
+  algorithm_type: ppo
 model:
   model_path: '/PATH/TO/MODEL/CHECKPOINT/'
   max_prompt_tokens: 256
@@ -51,7 +52,6 @@ synchronizer:
   sync_timeout: 1200
 trainer:
   trainer_type: 'verl'
-  algorithm_type: ppo
   trainer_config_path: 'examples/ppo_countdown/train_countdown.yaml'
   sft_warmup_steps: 0
   save_interval: 100
diff --git a/trinity/cli/launcher.py b/trinity/cli/launcher.py
index 5dbf53abb47..ce36299e84f 100644
--- a/trinity/cli/launcher.py
+++ b/trinity/cli/launcher.py
@@ -56,7 +56,7 @@ def train(config: Config) -> None:
                 logger.info("SFT warmup finished.")
                 break
 
-    algo_type = config.trainer.algorithm_type
+    algo_type = config.global_config.algorithm_type
     try:
         ray.get(trainer.train.remote(algo_type))
         logger.info("Train finished.")
@@ -100,7 +100,7 @@ def both(config: Config) -> None:
                 break
         ray.get([explorer.sync_weight.remote(), trainer.sync_weight.remote()])
 
-    algo_type = config.trainer.algorithm_type
+    algo_type = config.global_config.algorithm_type
     while True:
         try:
             ref_explore = explorer.explore_one_period.remote()
diff --git a/trinity/common/config.py b/trinity/common/config.py
index 2e8e8300079..2508081cfbc 100644
--- a/trinity/common/config.py
+++ b/trinity/common/config.py
@@ -120,6 +120,7 @@ class GlobalConfig:
     batch_size: int = 1
     eval_interval: int = 100
     eval_on_latest_ckp: bool = True
+    algorithm_type: AlgorithmType = AlgorithmType.PPO
 
 
 @dataclass
@@ -227,7 +228,6 @@ class TrainerConfig:
     trainer_config: Any = field(default_factory=dict)
 
     # train algorithm
-    algorithm_type: AlgorithmType = AlgorithmType.PPO
     get_exp_strategy: Optional[str] = None
 
     # warmup config
@@ -309,7 +309,7 @@ def _check_interval(self) -> None:
         # check eval_interval
         if (
             self.mode != "bench"
-            and self.trainer.algorithm_type != AlgorithmType.DPO
+            and self.global_config.algorithm_type != AlgorithmType.DPO
             and self.global_config.eval_interval % self.synchronizer.sync_interval != 0
         ):
             self.global_config.eval_interval = (
@@ -322,12 +322,12 @@ def _check_interval(self) -> None:
         # check save_interval
         if (
             self.mode != "bench"
-            and self.trainer.algorithm_type != AlgorithmType.DPO
+            and self.global_config.algorithm_type != AlgorithmType.DPO
             and self.synchronizer.sync_method == SyncMethod.CHECKPOINT
         ):
             if self.trainer.save_interval != self.synchronizer.sync_interval:
                 logger.warning(
-                    f"When `trainer.algorithm_type` != `DPO` and `synchronizer.sync_method` == `checkpoint`, "
+                    f"When `global_config.algorithm_type` != `DPO` and `synchronizer.sync_method` == `checkpoint`, "
                     f"`trainer.save_interval` will be set to "
                     f"`synchronizer.sync_interval = {self.synchronizer.sync_interval}`."
                 )
@@ -390,20 +390,24 @@ def _check_buffer(self) -> None:  # noqa: C901
                     f"Auto set `buffer.trainer_input.experience_buffer` to {self.buffer.trainer_input.experience_buffer}"
                 )
         elif self.mode == "train":  # TODO: to be check
-            if self.trainer.algorithm_type.is_dpo():
+            if self.global_config.algorithm_type.is_dpo():
                 if (
                     self.buffer.trainer_input.experience_buffer is None
                     or not self.buffer.trainer_input.experience_buffer.path
                 ):
                     raise ValueError(
-                        "`buffer.trainer_input.experience_buffer.path` is required when `trainer.algorithm_type == AlgorithmType.DPO`"
+                        "`buffer.trainer_input.experience_buffer.path` is required when `global_config.algorithm_type == AlgorithmType.DPO`"
                     )
-        if self.mode in ["both", "train"]:
-            self.buffer.trainer_input.experience_buffer.algorithm_type = self.trainer.algorithm_type
+        if self.buffer.trainer_input.experience_buffer is not None:
+            self.buffer.trainer_input.experience_buffer.algorithm_type = (
+                self.global_config.algorithm_type
+            )
 
         # set buffer.explorer_output
         if self.buffer.explorer_output is None:
             self.buffer.explorer_output = self.buffer.trainer_input.experience_buffer
+        else:
+            self.buffer.explorer_output.algorithm_type = self.global_config.algorithm_type
 
         # check trainer_input.sft_warmup_dataset
         if (
@@ -440,7 +444,7 @@ def check_and_update(self) -> None:  # noqa: C901
         # check mode
         if self.mode not in ["explore", "train", "both", "bench"]:
             raise ValueError(f"Invalid mode: {self.mode}")
-        if self.trainer.algorithm_type == AlgorithmType.DPO and self.mode == "both":
+        if self.global_config.algorithm_type == AlgorithmType.DPO and self.mode == "both":
             raise ValueError("DPO does not support `both` mode")
 
         # check model path
@@ -454,21 +458,22 @@ def check_and_update(self) -> None:  # noqa: C901
             self.explorer.engine_num * self.explorer.tensor_parallel_size
         )
         self.synchronizer.backend = self.explorer.backend
-        if self.mode == "bench" and self.synchronizer.sync_method != SyncMethod.CHECKPOINT:
+        if (
+            self.mode in ["train", "explore", "bench"]
+            and self.synchronizer.sync_method != SyncMethod.CHECKPOINT
+        ):
             self.synchronizer.sync_method = SyncMethod.CHECKPOINT
             logger.warning(
-                "Bench mode only supports checkpoint synchronization, set `synchronizer.sync_method` to `checkpoint`."
+                f"`{self.mode}` mode only supports checkpoint synchronization, set `synchronizer.sync_method` to `checkpoint`."
             )
         if (
-            self.trainer.algorithm_type == AlgorithmType.DPO
+            self.global_config.algorithm_type == AlgorithmType.DPO
             and self.synchronizer.sync_method != SyncMethod.CHECKPOINT
         ):
             self.synchronizer.sync_method = SyncMethod.CHECKPOINT
             logger.warning(
                 "DPO only supports checkpoint synchronization, set `synchronizer.sync_method` to `checkpoint`."
             )
-        if self.synchronizer.sync_method == SyncMethod.NCCL and self.mode != "both":
-            raise ValueError("`nccl` synchronization is only supported in both mode.")
 
         self._check_interval()
 
diff --git a/trinity/common/verl_config.py b/trinity/common/verl_config.py
index 944037ac2e1..f0f323918b3 100644
--- a/trinity/common/verl_config.py
+++ b/trinity/common/verl_config.py
@@ -310,11 +310,11 @@ def synchronize_config(self, config: Config) -> None:
         self.critic.ppo_mini_batch_size = config.global_config.batch_size
         self.critic.rollout_n = self.actor_rollout_ref.rollout.n
 
-        self.actor_rollout_ref.actor.algorithm_type = config.trainer.algorithm_type
-        if config.trainer.algorithm_type == AlgorithmType.PPO:
+        self.actor_rollout_ref.actor.algorithm_type = config.global_config.algorithm_type
+        if config.global_config.algorithm_type == AlgorithmType.PPO:
             logger.info("Using GAE `adv_estimator` for PPO")
             self.algorithm.adv_estimator = AdvantageEstimator.GAE.value
-        elif config.trainer.algorithm_type == AlgorithmType.GRPO:
+        elif config.global_config.algorithm_type == AlgorithmType.GRPO:
             logger.info("Using GRPO `adv_estimator` for GRPO")
             self.algorithm.adv_estimator = AdvantageEstimator.GRPO.value
 
diff --git a/trinity/manager/config_manager.py b/trinity/manager/config_manager.py
index 1f1e48d61bb..f56b8eb3634 100644
--- a/trinity/manager/config_manager.py
+++ b/trinity/manager/config_manager.py
@@ -66,6 +66,7 @@ def _init_default_config(self):
             "_train_batch_size_per_gpu": 16,
             "train_batch_size": 96,
             "eval_interval": 1000,
+            "algorithm_type": AlgorithmType.PPO.value,
             # Taskset Configs
             "taskset_path": "",
             "taskset_subset_name": None,
@@ -131,7 +132,6 @@ def _init_default_config(self):
             "sync_timeout": 1200,
             # Trainer Configs
             "trainer_type": "verl",
-            "algorithm_type": AlgorithmType.PPO.value,
             "sft_warmup_steps": 0,
             "_nccl_save_interval": 100,
             "save_interval": 100,
@@ -1600,20 +1600,7 @@ def generate_config(self):
         else:
             trainer_n_gpus_per_node = st.session_state["gpu_per_node"]
 
-        critic_model_path = (
-            st.session_state["critic_model_path"].strip()
-            if st.session_state["critic_model_path"].strip()
-            else st.session_state["model_path"]
-        )
-
-        if st.session_state["algorithm_type"] == AlgorithmType.DPO.value:
-            pass
-            # experience_buffer_path = (
-            #     st.session_state["experience_buffer_path"].strip()
-            #     if st.session_state["experience_buffer_path"].strip()
-            #     else st.session_state["dataset_path"].strip()
-            # )
-        else:  # not dpo algorithms
+        if st.session_state["algorithm_type"] != AlgorithmType.DPO.value:
             experience_buffer_path = st.session_state["experience_buffer_path"].strip()
             if (
                 not experience_buffer_path
@@ -1657,10 +1644,10 @@ def generate_config(self):
                     "total_epochs": st.session_state["total_epochs"],
                     "batch_size": st.session_state["train_batch_size"],
                     "eval_interval": st.session_state["eval_interval"],
+                    "algorithm_type": st.session_state["algorithm_type"],
                 },
                 "model": {
                     "model_path": st.session_state["model_path"],
-                    "critic_model_path": critic_model_path,
                     "max_prompt_tokens": st.session_state["max_prompt_tokens"],
                     "max_response_tokens": st.session_state["max_response_tokens"],
                     "checkpoint_path": st.session_state["checkpoint_path"],
@@ -1732,7 +1719,6 @@ def generate_config(self):
                 },
                 "trainer": {
                     "trainer_type": st.session_state["trainer_type"],
-                    "algorithm_type": st.session_state["algorithm_type"],
                     "trainer_config": trainer_config,
                     "sft_warmup_steps": st.session_state["sft_warmup_steps"],
                     "save_interval": st.session_state["save_interval"],
@@ -1744,6 +1730,13 @@ def generate_config(self):
                 },
             }
 
+            if st.session_state["adv_estimator"] == AdvantageEstimator.GAE.value:
+                config["model"]["critic_model_path"] = (
+                    st.session_state["critic_model_path"].strip()
+                    if st.session_state["critic_model_path"].strip()
+                    else st.session_state["model_path"]
+                )
+
             for idx in range(st.session_state["_eval_tasksets_num"]):
                 if st.session_state[f"eval_taskset_{idx}_path"].strip():
                     config["buffer"]["explorer_input"]["eval_tasksets"].append(


Reviews:
user: login: hiyuchang
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-20T08:00:47Z
user: login: pan-x-c
body: Please see the inline comments, others LGTM
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T08:28:31Z
user: login: pan-x-c
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-20T08:33:50Z

Review comments:
diff_hunk: @@ -11,13 +11,15 @@ global_config:
   batch_size: 96
   eval_interval: 1000
   eval_on_latest_ckp: true
+  algorithm_type: ppo
path: docs/sphinx_doc/source/tutorial/trinity_configs.md
user: login: pan-x-c
body: move to above `total_epochs`
created_at: 2025-05-20T08:25:06Z
author_association: COLLABORATOR
diff_hunk: @@ -11,13 +11,15 @@ global_config:
   batch_size: 96
   eval_interval: 1000
   eval_on_latest_ckp: true
+  algorithm_type: ppo
 ```
 
 - `mode`: The mode of the experiment, chosen from `both`, `train`, `explore` or `bench`. `both` means both trainer and explorer are launched; `train` means only trainer is launched; `explore` means only explorer is launched; `bench` conducts benchmark evaluation. Default is `both`.
 - `global_config.total_epochs`: The total number of epochs. It should be checked manually.
 - `global_config.batch_size`: The batch size used for training. It should be checked manually.
 - `global_config.eval_interval`: The interval steps between two evaluations. Default is `1000`.
 - `global_config.eval_on_latest_ckp`: Whether to evaluate on only the latest checkpoint or all the checkpoints in the path. Only valid in `bench` mode. Default is `true`.
+- `global_config.algorithm_type`: The type of the algorithm, Support `ppo`, `grpo`, `opmd` and `dpo`.
path: docs/sphinx_doc/source/tutorial/trinity_configs.md
user: login: pan-x-c
body: save as above
created_at: 2025-05-20T08:28:15Z
author_association: COLLABORATOR

PR comments:
user: login: hiyuchang
created_at: 2025-05-20T07:43:43Z
body: lgtm
author_association: COLLABORATOR
user: login: chenyushuo
created_at: 2025-05-20T07:45:21Z
body: /run-unittest
author_association: COLLABORATOR
user: login: github-actions[bot]
created_at: 2025-05-20T07:57:34Z
body: ### Summary

| **Tests 📝** | **Passed ✅** | **Failed ❌** | **Skipped ⏭️** | **Pending ⏳** | **Other ❓** | **Flaky 🍂** | **Duration ⏱️** |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 22 | 22 | 0 | 0 | 0 | 0 | 0 | 695ms |

### Failed Tests

<p>No failed tests ✨</p>




### Flaky Tests

<p>No flaky tests ✨</p>


### Skipped

<p>No skipped tests ✨</p>


### Tests

| **Test Name** | **Status** | **Flaky** | **Duration** |
| --- | --- | --- | --- |
| tests/buffer/queue_test.py::TestQueueBuffer::test_queue_buffer | ✅ |  | 4ms |
| tests/buffer/sql_test.py::TestSQLBuffer::test_create_sql_buffer | ✅ |  | 1ms |
| tests/common/config_test.py::TestConfig::test_all_examples_are_valid | ✅ |  | 1ms |
| tests/common/config_test.py::TestConfig::test_load_default_config | ✅ |  | 1ms |
| tests/common/experience_test.py::TestExperienceConversion::test_batch_conversion | ✅ |  | 1ms |
| tests/common/experience_test.py::TestExperienceConversion::test_experience_model_experience_conversion | ✅ |  | 1ms |
| tests/common/vllm_test.py::TestModelWrapperSyncV0::test_generate | ✅ |  | 46ms |
| tests/common/vllm_test.py::TestModelWrapperAsyncV0::test_generate | ✅ |  | 43ms |
| tests/common/vllm_test.py::TestModelWrapperAsyncTPV0::test_generate | ✅ |  | 53ms |
| tests/common/vllm_test.py::TestModelWrapperAsyncTPV1::test_generate | ✅ |  | 53ms |
| tests/common/vllm_test.py::TestModelWrapperAsyncV1::test_generate | ✅ |  | 39ms |
| tests/common/vllm_test.py::TestTokenizer::test_assistant_token_mask | ✅ |  | 1ms |
| tests/explorer/explorer_test.py::BaseExplorerCase::test_explorer | ✅ |  | 1ms |
| tests/explorer/explorer_test.py::TestExplorerCountdownEval::test_explorer | ✅ |  | 86ms |
| tests/explorer/explorer_test.py::TestExplorerCountdownNoEval::test_explorer | ✅ |  | 96ms |
| tests/explorer/runner_pool_test.py::RunnerPoolTest::test_runner_pool | ✅ |  | 18ms |
| tests/explorer/workflow_test.py::WorkflowTest::test_gsm8k_workflow | ✅ |  | 1ms |
| tests/explorer/workflow_test.py::WorkflowTest::test_math_complex_workflow | ✅ |  | 1ms |
| tests/explorer/workflow_test.py::WorkflowTest::test_math_fraction_workflow | ✅ |  | 1ms |
| tests/explorer/workflow_test.py::WorkflowTest::test_math_workflow | ✅ |  | 1ms |
| tests/trainer/trainer_test.py::BaseTrainerCase::test_trainer | ✅ |  | 1ms |
| tests/trainer/trainer_test.py::TestTrainerCountdown::test_trainer | ✅ |  | 247ms |


[Github Test Reporter](https://github.com/ctrf-io/github-test-reporter) by [CTRF](https://ctrf.io) 💚
<!-- CTRF PR COMMENT TAG: false -->
author_association: NONE