Skip to content

vinhnamhai321/GenRT

Repository files navigation

GenRT: List-aware Reranking-Truncation Joint Model

Paper: List-aware Reranking-Truncation Joint Model for Search and Retrieval-augmented Generation
Authors: Shicheng Xu, Liang Pang, Jun Xu, Huawei Shen, Xueqi Cheng
Venue: WWW '24: Proceedings of the ACM Web Conference 2024

πŸ—‚οΈ Project Structure

GenRT/
β”œβ”€β”€ README.md                   # This file
β”œβ”€β”€ requirements.txt            # Python dependencies
β”œβ”€β”€ .gitignore                  # Git ignore rules
β”‚
β”œβ”€β”€ app.py                      # Flask web application (Phase 4)
β”œβ”€β”€ train_web10k.py             # Training script (Phase 2)
β”œβ”€β”€ test_inference.py           # Inference testing (Phase 3)
β”œβ”€β”€ test_gpu_fit.py             # GPU memory verification
β”‚
β”œβ”€β”€ app/                        # Web application assets
β”‚   β”œβ”€β”€ templates/
β”‚   β”‚   β”œβ”€β”€ index.html          # Search interface
β”‚   β”‚   └── result.html         # Results display
β”‚   └── static/
β”‚       └── style.css           # Styling
β”‚
β”œβ”€β”€ model/                      # GenRT model implementation
β”‚   β”œβ”€β”€ modeling_t5_add_pos_eof.py      # Main model (training)
β”‚   β”œβ”€β”€ modeling_t5_add_pos_eof_predict.py  # Model (inference)
β”‚   └── embedding_layer.py      # Feature embedding layers
β”‚
β”œβ”€β”€ services/                   # Inference service layer
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── inference_service.py    # GenRTInference class
β”‚
β”œβ”€β”€ setup/                      # Data preparation scripts
β”‚   β”œβ”€β”€ create_data_web10k.py   # Process LETOR β†’ pickle
β”‚   β”œβ”€β”€ merge_tables.py         # Merge feature tables
β”‚   β”œβ”€β”€ download_t5_clean.py    # Download T5-small
β”‚   β”œβ”€β”€ fix_t5_model.py         # Fix model format issues
β”‚   └── verify_data.py          # Verify processed data
β”‚
β”œβ”€β”€ data/                       # Raw dataset (LETOR format)
β”‚   └── MSLR-WEB10K/
β”‚       └── Fold1/
β”‚           β”œβ”€β”€ train.txt       # Training data
β”‚           β”œβ”€β”€ train.predict   # LambdaMART scores
β”‚           β”œβ”€β”€ test.txt        # Test data
β”‚           β”œβ”€β”€ test.predict    # LambdaMART scores
β”‚           β”œβ”€β”€ vali.txt        # Validation data
β”‚           └── my_model.txt    # Trained LambdaMART model
β”‚
β”œβ”€β”€ dataset/                    # Processed data (pickle files)
β”‚   └── MSLR-WEB10K/
β”‚       └── FOLD1/
β”‚           └── processed_data/
β”‚               β”œβ”€β”€ train_top40.pkl
β”‚               β”œβ”€β”€ train_top40_table.pkl
β”‚               β”œβ”€β”€ test_top40.pkl
β”‚               β”œβ”€β”€ test_top40_table.pkl
β”‚               └── feature_top40_table.pkl
β”‚
β”œβ”€β”€ checkpoints/                # Trained model weights
β”‚   β”œβ”€β”€ checkpoint_best.pth     # Best validation checkpoint
β”‚   └── checkpoint_latest.pth   # Latest checkpoint
β”‚
β”œβ”€β”€ T5-small/                   # T5-small base model
β”‚   β”œβ”€β”€ config.json
β”‚   β”œβ”€β”€ pytorch_model.bin
β”‚   └── spiece.model
β”‚
└── mytransformers_emb_sim/     # Modified HuggingFace Transformers
    └── src/transformers/
        └── models/t5/          # Custom T5 with GenRT modifications

πŸš€ Quick Start

Prerequisites

Requirement Version Notes
Python 3.8+ Tested on 3.10, 3.11
PyTorch 1.10+ CUDA support recommended
GPU 8GB+ VRAM RTX 4060 or better
Java JRE 8+ For RankLib

Installation

# 1. Navigate to project directory
cd GenRT

# 2. Create virtual environment (recommended)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# or: venv\Scripts\activate  # Windows

# 3. Install dependencies
pip install -r requirements.txt

# 4. Verify GPU
python test_gpu_fit.py

πŸ“Š Complete Pipeline

Phase 1: Data Preparation

Step 1.1: Download MSLR-WEB10K Dataset

  1. Visit Microsoft Learning to Rank Datasets
  2. Download MSLR-WEB10K.zip (~1GB)
  3. Extract to data/MSLR-WEB10K/

Expected structure:

data/MSLR-WEB10K/
β”œβ”€β”€ Fold1/
β”‚   β”œβ”€β”€ train.txt    # ~235MB, 723K lines
β”‚   β”œβ”€β”€ test.txt     # ~78MB, 241K lines
β”‚   └── vali.txt     # ~78MB, 241K lines
β”œβ”€β”€ Fold2/
β”‚   └── ...
└── Fold5/

Step 1.2: Generate LambdaMART Predictions

Download RankLib-2.18.jar and place in data/MSLR-WEB10K/Fold1/.

cd data/MSLR-WEB10K/Fold1

# Train LambdaMART model (takes ~10-30 minutes)
java -Xmx8g -jar RankLib.jar \
    -train train.txt \
    -ranker 6 \
    -metric2t NDCG@10 \
    -tree 1000 \
    -leaf 20 \
    -save my_model.txt

# Generate prediction scores for each split
java -jar RankLib.jar -load my_model.txt -rank train.txt -score train.predict
java -jar RankLib.jar -load my_model.txt -rank test.txt -score test.predict
java -jar RankLib.jar -load my_model.txt -rank vali.txt -score vali.predict

Step 1.3: Download T5-small Model

cd setup
python download_t5_clean.py

If you encounter safetensors issues:

python fix_t5_model.py

Step 1.4: Process Data to Pickle Format

cd setup

# Convert LETOR format to pickle (creates train/test/vali pkl files)
python create_data_web10k.py

# Merge all feature tables into one
python merge_tables.py

# Verify everything is ready
python verify_data.py

Phase 2: Training

πŸ’‘ Pre-trained Checkpoints Available!
You can skip training by downloading our pre-trained checkpoints:
πŸ“₯ Download Checkpoints from Google Drive
Extract and place the files in the checkpoints/ directory.

# From project root
python train_web10k.py

Training Options

# Custom hyperparameters
python train_web10k.py --batch_size 32 --epochs 15 --lr 5e-5

# Resume from checkpoint
python train_web10k.py --resume latest --epochs 20

# Reduced memory usage
python train_web10k.py --batch_size 8 --grad_accum 2

Command Line Arguments

Argument Default Description
--batch_size 16 Training batch size
--eval_batch_size 32 Evaluation batch size
--epochs 10 Number of training epochs
--lr 1e-4 Learning rate
--weight_decay 0.0005 Weight decay
--lr_decay 0.95 LR decay per epoch
--resume None 'latest', 'best', or checkpoint path
--no_amp False Disable mixed precision
--grad_accum 1 Gradient accumulation steps
--early_stop 5 Early stopping patience

Expected Output

πŸš€ GenRT Trainer Initialization
========================================
βœ… GPU: NVIDIA GeForce RTX 4060
   Memory: 8.0 GB

πŸ“‚ Loading data...
   βœ… Train: 10,000 queries
   βœ… Test: 3,000 queries

πŸ€– Initializing model...
   βœ… Model parameters: 12.5M

πŸ“ˆ Training Progress:
Epoch 1/10: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 625/625 [05:32<00:00]
   Train Loss: 2.3456
   Test NDCG@10: 0.4521
   βœ… Best model saved!

Phase 3: Inference Testing

python test_inference.py

Expected output:

πŸ§ͺ Testing GenRT Inference Service
========================================
πŸ”§ Initializing inference service...
   βœ… Loaded 3000 queries

πŸ“‹ Available sample QIDs: [1, 2, 3, ...]

πŸ” Testing prediction for QID: 1
βœ… Prediction successful!

πŸ“Š Results:
   NDCG@10 Baseline: 0.4231
   NDCG@10 GenRT:    0.4687
   Improvement:      +0.0456

Phase 4: Web Application

python app.py

Open browser: http://localhost:5000

Features

  • Enter Query ID to see reranking results
  • Side-by-side comparison: Baseline vs GenRT
  • Visual indicators for promoted/demoted documents
  • NDCG metrics display
  • Truncation point visualization

πŸ”§ API Reference

Python API

from services.inference_service import GenRTInference

# Initialize service (loads model once)
inference = GenRTInference(
    checkpoint_path="./checkpoints/checkpoint_best.pth",
    device="cuda"  # or "cpu"
)

# Get available query IDs
all_qids = inference.get_available_qids()
sample_qids = inference.get_sample_qids(n=10)

# Predict for a single query
result = inference.predict(qid=12345)

# Result structure
{
    'qid': 12345,
    'baseline_ranking': [
        {'doc_id': 0, 'lambdamart_score': 1.234, 'relevance_label': 2},
        ...
    ],
    'genrt_ranking': [
        {'doc_id': 5, 'lambdamart_score': 0.987, 'relevance_label': 3, 'original_rank': 6},
        ...
    ],
    'truncation_point': 15,
    'metrics': {
        'ndcg@5_baseline': 0.412,
        'ndcg@5_genrt': 0.456,
        'ndcg@10_baseline': 0.423,
        'ndcg@10_genrt': 0.468,
        'improvement': 0.045
    },
    'num_docs_baseline': 40,
    'num_docs_genrt': 15
}

# Batch prediction
results = inference.predict_batch(qids=[1, 2, 3, 4, 5])

REST API Endpoints

Endpoint Method Description
/ GET Home page with search interface
/search POST Submit query and get results
/api/predict/<qid> GET Get prediction JSON for QID
/api/qids GET Get list of available QIDs
# Get prediction for QID
curl http://localhost:5000/api/predict/12345

# Get available QIDs (optional: ?n=100)
curl http://localhost:5000/api/qids?n=50

πŸ“ˆ Model Architecture

Overview

Input: [Query Features] + [Doc1 Features] + [Doc2 Features] + ... + [DocN Features]
                                    ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Global Dependency Encoder   β”‚
                    β”‚   (Multi-Head Self-Attention) β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  Sequential Dependency Decoder β”‚
                    β”‚   (Step-by-step Generation)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    ↓
Output: Reranked List + Truncation Point

Global Dependency Encoder

  • Input Embedding: 136 LETOR features + 1 LambdaMART score = 137-dim vector
  • Transfer Layer: MLP with Swish activation β†’ hidden size
  • Context Modeling: Multi-Head Self-Attention captures list-level dependencies
  • Residual Connection: Preserves original features while adding context

Sequential Dependency Decoder

  • Step-by-step Generation: Outputs one document per step
  • Truncation Decision: Binary classification at each step
  • Cross-Attention: Attends to encoder output for document selection
  • Position Encoding: Relative position encoding for order awareness

Loss Functions

  1. Reranking Loss ($\mathcal{L}_R$):

    • Step-adaptive attention loss (weights top positions more)
    • Step-by-step lambda loss (pairwise ranking)
  2. Truncation Loss ($\mathcal{L}_T$):

    • Binary classification with TDCG-based soft labels
    • Reward Augmented Maximum Likelihood (RAML)

πŸ“š Citation

If you use this code, please cite the original paper:

@inproceedings{xu2024genrt,
  title={List-aware Reranking-Truncation Joint Model for Search and Retrieval-augmented Generation},
  author={Xu, Shicheng and Pang, Liang and Xu, Jun and Shen, Huawei and Cheng, Xueqi},
  booktitle={Proceedings of the ACM Web Conference 2024},
  pages={1028--1037},
  year={2024},
  organization={ACM}
}

πŸ› Troubleshooting

Common Issues

Issue Solution
CUDA out of memory Reduce --batch_size to 8 or 4; Use --grad_accum 2
T5 model loading error Run python setup/fix_t5_model.py; Ensure pytorch_model.bin exists
Missing .predict files Follow Step 1.2 to generate with RankLib
Feature table not found Run python setup/merge_tables.py
Web app fails to start Check checkpoint and processed data exist
Java not found Install JRE 8+; Add to PATH
Import errors Ensure virtual environment is activated

Verification Commands

# Check GPU
python -c "import torch; print(torch.cuda.is_available())"

# Check data files
python setup/verify_data.py

# Check model loads
python test_gpu_fit.py

πŸ“ License

This project is for educational and research purposes only.


πŸ™ Acknowledgments

  • Original GenRT paper authors
  • Microsoft Research for MSLR datasets
  • HuggingFace for Transformers library
  • RankLib for LambdaMART implementation

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors