--- license: apache-2.0 pipeline_tag: text-generation --- # Model Card for Qwen3-4B-ECHO-Sokoban-GRPO Building upon Qwen3-4B, we trained the model with the ECHO framework using GRPO on the Sokoban dataset. Specifically, because Qwen3-4B performs poorly on the more challenging Sokoban puzzles, we adopted a multi-round RL training regimen capped at four rounds, with a maximum of 25 candidate actions per round. The detailed environment configuration is as follows: ```python LargerSokoban6: env_type: sokoban max_actions_per_traj: 100 env_instruction: "You are solving the Sokoban puzzle. You are the player and you need to push all boxes to targets. When you are right next to a box, you can push it by moving in the same direction. You cannot push a box through a wall, and you cannot pull a box. The answer should be a sequence of actions, like Right || Right || Up" max_tokens: 300 env_config: dim_x: 6 dim_y: 6 num_boxes: 2 max_steps: 300 search_depth: 20 ``` Tabel 1: Model performance on Sokoban task | Model | Success Rate(%) | |----------------|----------------| | Qwen3-4B | 21.8 | | Qwen3-4B-Echo(GRPO) | 34.0 | | Qwen3-30B-A3B-Thinking-2507 | 72.75 | | Qwen3-30B-A3B-Thinking-2507-Echo(GRPO) | 82.80 | | Deepseek-R1 | 75.75 | | Qwen3-235B-A22B-Thinking-2507) | 79.68 | | gpt-oss-120b | 79.69 | # Quick start ```python from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "GradientResearch/Qwen3-4B-ECHO-Sokoban-GRPO" # load the tokenizer and the model tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype="auto", device_map="auto" ) # prepare the model input prompt = "sokoban" messages = [ {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True, enable_thinking=True # Switches between thinking and non-thinking modes. Default is True. ) model_inputs = tokenizer([text], return_tensors="pt").to(model.device) # conduct text completion generated_ids = model.generate( **model_inputs, max_new_tokens=32768 ) output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist() # parsing thinking content try: # rindex finding 151668 () index = len(output_ids) - output_ids[::-1].index(151668) except ValueError: index = 0 thinking_content = tokenizer.decode(output_ids[:index], skip_special_tokens=True).strip("\n") content = tokenizer.decode(output_ids[index:], skip_special_tokens=True).strip("\n") print("thinking content:", thinking_content) print("content:", content) ``` # Citation If you find our work helpful, feel free to give us a cite. ``` @misc{xiao2025echodecouplinginferencetraining, title={Echo: Decoupling Inference and Training for Large-Scale RL Alignment on Heterogeneous Swarms}, author={Jie Xiao and Changyuan Fan and Qingnan Ren and Alfred Long and Yuchen Zhang and Rymon Yu and Eric Yang and Lynn Ai and Shaoduo Gan}, year={2025}, eprint={2508.05387}, archivePrefix={arXiv}, primaryClass={cs.LG}, url={https://arxiv.org/abs/2508.05387}, } ```