🧑‍🏫 Guide for Implementation

April 23, 2026 · View on GitHub

Paper License Python 3.9+

💡 Overview

Boundary-Aware Policy Optimization(BAPO) is a novel reinforcement learning-based framework for training reliable agentic search models. Beyond correctness rewards, BAPO incorporates boundary-aware rewards to encourage appropriate "I Don't Know" (IDK) responses. To tackle the tradeoff between exploration and exploitation during RL training, we introduce an adaptive reward modulator to prevent the model from being over-encouraged to admit ignorance.

🧑‍🏫 Guide for Implementation

1. Environment Setup

You can install the required packages by checking requirements.txt and following the steps below:

#create conda env
conda create -n bapo python==3.10
conda activate bapo

# install torch
pip3 install torch==2.4.0 --index-url https://download.pytorch.org/whl/cu124

# install flash-attn
wget https://github.com/Dao-AILab/flash-attention/releases/download/v2.7.3/flash_attn-2.7.3+cu12torch2.4cxx11abiFALSE-cp310-cp310-linux_x86_64.whl

pip install flash_attn-2.7.3+cu12torch2.4cxx11abiFALSE-cp310-cp310-linux_x86_64.whl

# install faiss gpu
# Due to the incompatibility when installing faiss using pip, it is necessary to use the following conda command for installation.
conda install -c pytorch -c nvidia faiss-gpu=1.8.0


# install RL basic env
cd RL_train
pip3 install -e .

# install verl
cd src/verl
pip install -e .

# install other requirements
pip install bs4==0.0.2 pdfplumber==0.11.6 chardet==5.2.0
pip install timeout_decorator Pebble==5.1.1

2. Model Download

Our default training is based on the Qwen series models, including the Qwen2.5-instruct series from 3B, 7B to 14B. You can download the corresponding checkpoints from Hugging Face:

3. Retriever Serving Deployment

In this section, we will deploy the retriever for performing search tasks on Wikipedia-based datasets. We provide a Wikipedia retriever service implemented using FlashRAG.

More details can be found in the FlashRAG documentation.

Configuration

The config file is located at evaluation/search/serving_config.yaml:

retrieval_method: "{your_path}/e5-base-v2"  # name or path of the retrieval model.
index_path: "{your_path}/e5_flat_inner.index" # path to the indexed file
faiss_gpu: True # whether use gpu to hold index
corpus_path: "{your_path}/wiki18_100w.jsonl"  # path to corpus in '.jsonl' format that store the documents

Required Downloads

You need to download the following components:

Corpus: wiki18_100w.jsonl

Retrieval Model: e5-base-v2

Index: wiki18_100w_e5_index.zip

Starting the Service

To start the retriever serving, first fill in evaluation/search/serving_config.yaml with the correct paths to the retrieval model, index, and corpus, as well as available GPU IDs. Then, run the following command:

cd evaluation/search
python host_wiki.py \
    --config serving_config.yaml \
    --num_retriever {num_retriever} \
    --port {port}

4. BAPO Training

Our training framework is based on verl. The training scripts can be found under scripts/train.

Dataset

The training dataset is located at dataset/train_qa.parquet and the test set is at dataset/test_qa.parquet. Our data consists of the QA part of the dataset released by Tool-Star, totaling 5k samples.

Original dataset links:

Training Command

export PYTHONPATH=/src/verl:$PYTHONPATH
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU

bash scripts/train/train.sh \
    --train_batch_size 64 \
    --ppo_mini_batch_size 16 \
    --rollout_n 8 \
    --apply_chat True \
    --prompt_template_name re_search_faith_template \
    --actor_model_path ${actor_model_path} \
    --project_name Tool-Star \
    --experiment_name ${experiment_name} \
    --nnodes 1 \
    --n_gpus_per_node 8 \
    --save_freq 10 \
    --test_freq 1 \
    --total_epochs 2 \
    --oversample_faith True \
    --idk_ratio 0.1 \
    --stage_level True \
    --sample_level True \
    --tensor_model_parallel_size 1 \
    --reward_manager re_search_faith \
    --wandb_api_key {wandb_key} \
    --save_path {your_output_path}/out/${experiment_name} \
    --train_files ./dataset/train_qa.parquet \
    --test_files ./dataset/test_qa.parquet \
    --search_url http://0.0.0.0:1243

Note: train.sh is a training script template where you can pass several key hyperparameters to configure the training, while some fixed hyperparameters can be adjusted within the train.sh file itself.

Quick Start

We provide several example training scripts. You can run the following script to start training:

cd ./RL_train
bash scripts/train/run_bapo.sh

Important: If you encounter OOM (Out of Memory) issues (typically when training 14B models), we recommend increasing the tensor_model_parallel_size parameter (e.g., set it to 2).

Checkpoint Conversion

For the trained RL checkpoint, you can follow the code below to convert the weights to Hugging Face format:

# Merge RL weights and save in the same path.
python ./RL_train/model_merger.py \
    --local_dir {save_path}/global_step_156/actor \

5. Evaluation

For evaluation of our trained checkpoints, we include four QA datasets: HotpotQA, 2WikiMultiHopQA, Bamboogle, and MuSiQue.

Configuration Setup

First, replace the search URL in evaluation/utils.py with the configuration from 3. Retriever Serving Deployment:

def search(query: str):
    if query == '':
        return 'invalid query'

    url = f'your_search_api_url'  # Replace with your actual search API URL
    ...

def batch_search(query: Union[str, List[str]], top_n=5) -> List[str]:
    if len(query) == 0:
        return 'invalid query'

    url = f'your_search_api_url'  # Replace with your actual search API URL
    ...

Running Inference

Start the inference using the following command with recommended default parameters:

cd evaluation
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export TOKENIZERS_PARALLELISM=true
export PYTHONPATH=/path/to/your_path:$PYTHONPATH

python run.py \
    --model_path /path/to/your_model_path \
    --dataset_name HotpotQA \
    --task qa \
    --gpu_use 0.95 \
    --max_tokens 8192 \
    --max_input_len 8192 \
    --output_path /path/to/your_results/your_exp_result.json \
    --counts 200 \
    --batch_size 100

We have provided an inference script in run_qa.sh

Parameter Explanations

ParameterDescription
--model_pathPath to your trained model
--dataset_nameDataset name (supports: HotpotQA, 2WikiMultiHopQA, Bamboogle, MuSiQue)
--taskSet to qa for QA reasoning datasets
--gpu_useGPU memory utilization ratio
--max_tokensMaximum number of tokens the model can generate
--max_input_lenMaximum input tokens the model can accept
--output_pathPath to save the evaluation results
--countsNumber of samples to evaluate from the test set
--batch_sizeBatch size for parallel inference

6. Calculate Metrics

This section describes how to calculate evaluation metrics using the LLM-as-judge mechanism.

API Configuration

First, replace the API URL and API key with your own in evaluation/evaluate/scripts/evaluate.py:

async def llm_evaluate_equivalence_batch(
    questions: List[str],
    labeled_answers: List[str],
    pred_answers: List[str],
    api_base_url: str = "", #input your api base url
    model_name: str = "", # input the model name
    api_key: str = "", #input your api key
    concurrent_limit: int = 50,
    extract_answer: bool = False
) -> List[bool]:
    """
    Evaluate multiple answer pairs concurrently using LLM
    """
    ...

Running Evaluation

Execute the following command to calculate metrics:

cd evaluation
python evaluate/scripts/evaluate.py \
    --output_path /path/to/your_results/your_exp_result.json \
    --task qa \
    --dataset_name HotpotQA \
    --use_llm \
    --extract_answer

Parameter Explanations

ParameterDescription
--output_pathPath to the evaluation results file
--taskTask type: qa for QA reasoning
--dataset_nameDataset name for evaluation
--use_llmEnable LLM-as-judge evaluation mechanism
--extract_answerEnable exact matching

📚 Documentation

We have provided a comprehensive code implementation guide for BAPO to help users understand the codebase and facilitate replication and modification.


🙏 Acknowledgements

This work is implemented based on verl, ReCall and Tool-Star. We sincerely thank the authors of these projects for their valuable contributions to the open-source community.

📃 Citation

@article{liu2026bapo,
  title={BAPO: Boundary-Aware Policy Optimization for Reliable Agentic Search},
  author={Liu, Shiyu and Yin, Yongjing and Yan, Jianhao and Tang, Yunbo and Zhang, Qinggang and Li, Bei and Chen, Xin and Wang, Jingang and Cai, Xunliang and Su, Jinsong},
  journal={arXiv preprint arXiv:2601.11037},
  year={2026}
}