Files
paddlepaddle--paddlenlp/tests/llm/test_reinforce_plus_plus.py
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

116 lines
4.1 KiB
Python

# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import os
import signal
import subprocess
import sys
import time
import unittest
from parameterized import parameterized_class
from .testing_utils import LLMTest
@parameterized_class(
["model_dir"],
[["qwen"]],
)
class ReinforcePlusPlusTest(LLMTest, unittest.TestCase):
config_path: str = None
model_dir: str = None
def setUp(self) -> None:
LLMTest.setUp(self)
sys.path.insert(0, "./llm/alignment/rl")
sys.path.insert(0, self.model_dir)
def tearDown(self) -> None:
LLMTest.tearDown(self)
def test_reinforce_plus_plus(self):
# 设置必要的环境变量
env_vars = {
"PYTHONPATH": f"{os.path.abspath('./')}:{os.path.abspath('./llm')}:" + os.environ.get("PYTHONPATH", ""),
"FLAGS_set_to_1d": "False",
"NVIDIA_TF32_OVERRIDE": "0",
"FLAGS_dataloader_use_file_descriptor": "False",
"HF_DATASETS_DOWNLOAD_TIMEOUT": "1",
"FLAGS_gemm_use_half_precision_compute_type": "False",
"FLAGS_force_cublaslt_no_reduced_precision_reduction": "True",
"FLAGS_mla_use_tensorcore": "0",
"FLAGS_cascade_attention_max_partition_size": "2048",
}
case_env = os.environ.copy()
case_env.update(env_vars)
# 修改执行路径
repo_path = os.getcwd()
rl_dir = os.path.join(os.getcwd(), "./llm/alignment/rl")
os.chdir(rl_dir)
# 下载并解压数据
if not os.path.exists("ppo-kk.tgz"):
subprocess.run(
"wget -q https://paddlenlp.bj.bcebos.com/datasets/examples/ppo-kk.tgz && tar zxf ppo-kk.tgz",
shell=True,
check=True,
)
# 启动 reward server
reward_dir = os.path.join(os.getcwd(), "./reward")
reward_log = os.path.join(reward_dir, "reward_server.log")
reward_server_script = os.path.join(reward_dir, "reward_server.py")
with open(reward_log, "w") as log_file:
reward_proc = subprocess.Popen(
[sys.executable, reward_server_script],
cwd=reward_dir,
stdout=log_file,
stderr=subprocess.STDOUT,
preexec_fn=os.setsid, # 便于后续 kill 整个进程组
)
try:
# 等待 reward server 启动
time.sleep(30)
# 运行主逻辑
cmd = 'python -u -m paddle.distributed.launch \
--devices "$CUDA_VISIBLE_DEVICES" run_rl.py \
../../config/qwen/grpo_argument.yaml \
--rl_algorithm "reinforce_plus_plus" \
--actor_model_name_or_path "Qwen/Qwen2-1.5B" \
--max_dec_len 128 \
--max_steps 3 \
--kl_coeff 0.000 \
--kl_loss_coeff 0.000 \
--use_fused_rms_norm true '
pro = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = pro.communicate()
print(out)
pro.wait()
pro.returncode == 0
assert str(out).find("Error") == -1
assert str(err).find("Error") == -1
os.chdir(repo_path)
finally:
# main 执行完毕,关闭 reward server
if reward_proc.poll() is None: # 确保进程还在
os.killpg(os.getpgid(reward_proc.pid), signal.SIGTERM) # kill 整个进程组