Update README_zh.md
Browse files- README_zh.md +264 -0
README_zh.md
CHANGED
|
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div align="center">
|
| 2 |
+
<h1> Retrieval as Generation: A Unified Framework with Self-Triggered Information Planning </h1>
|
| 3 |
+
<p>
|
| 4 |
+
<a href="./README.md">English</a> | <strong>简体中文</strong>
|
| 5 |
+
</p>
|
| 6 |
+
|
| 7 |
+
<p>
|
| 8 |
+
<a href="https://github.com/WisdomShell/GRIP"><img alt="Website" src="https://img.shields.io/badge/🌐_Project-Website-A593C2?style=flat-square&labelColor=8A7AA8"></a>
|
| 9 |
+
<a href="https://huggingface.co/WisdomShell/LLaMa-3-8B-Base-GRIP"><img alt="Model Weights" src="https://img.shields.io/badge/🤗_HuggingFace-Model_Weights-D4A574?style=flat-square&labelColor=B8956A"></a>
|
| 10 |
+
<a href="https://arxiv.org/abs/2506.99999999"><img alt="Paper" src="https://img.shields.io/badge/📄_arXiv-Paper-C7969C?style=flat-square&labelColor=A8798A"></a>
|
| 11 |
+
</p>
|
| 12 |
+
<h2>[ACL 2026 主会场]</h2>
|
| 13 |
+
<a href="https://deepblue666.github.io/">Bo Li</a> 
|
| 14 |
+
<a>Mingda Wang</a> 
|
| 15 |
+
<a>GeXiang Fang</a> 
|
| 16 |
+
<a>Shikun Zhang</a> 
|
| 17 |
+
<a>Wei Ye</a> 
|
| 18 |
+
<div>
|
| 19 |
+
</div>
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
传统的 RAG(检索增强生成)系统将检索视为一种外部的、一次性的干预行为——在生成开始前僵硬地预取文档。这种方式在复杂推理过程中信息需求逐步涌现时往往表现不佳。即便是动态搜索方法,也高度依赖于孤立的外部控制器或启发式规则。
|
| 23 |
+
|
| 24 |
+
我们认为,正如人类的认知过程一样,检索应当是一种内在的、生成式的能力。大语言模型必须能够自主地评估自身知识状态、触发搜索,并根据不断演进的推理状态构建具有上下文关联的后续查询。
|
| 25 |
+
|
| 26 |
+
GRIP(Generation-guided Retrieval with Information Planning,生成引导的信息规划检索)正是这一新范式的具体体现。在"检索即生成"框架下,我们的模型通过特定控制词元(control tokens),将检索决策直接内化于词元级的解码过程中。这一方法将模型从依赖辅助性多阶段搜索模块中解放出来,在单一自回归轨迹内实现端到端、自触发的信息规划。
|
| 27 |
+
|
| 28 |
+
## 🌟 核心特性
|
| 29 |
+
|
| 30 |
+
- 🎯 **词元驱动控制**:通过显式控制词元(如 `[RETRIEVE]`、`[ANSWER]`、`[INTERMEDIARY]`),将检索行为直接嵌入模型的生成策略,无需外部分类器。
|
| 31 |
+
- 🔄 **自触发规划**:自主决定何时回退到内部知识、如何根据部分推理重新构建针对性查询,以及何时终止搜索。
|
| 32 |
+
- ⚖️ **自适应检索深度**:根据问题复杂度动态调整检索轮次,在成功避免冗余搜索的同时,还能突破严格的训练预算限制进行外推。
|
| 33 |
+
- 🚀 **最先进的性能**:在五个问答基准测试上,以更小的骨干模型(LLaMA3-8B)超越了强力的开源 RAG 基线(如 GainRAG、R1-Searcher),并达到了与 GPT-4o 相当的竞争性水平。
|
| 34 |
+
- 🧩 **统一解码轨迹**:将多步推理与即时证据整合紧密耦合于单一、连续的生成流程中。
|
| 35 |
+
- 🛠️ **优化的训练方案**:采用针对四种不同行为模式的结构化有监督微调(SFT),并通过基于规则的强化学习(DAPO)进一步精炼,以确保准确且均衡的检索控制。
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
## 🚀 快速开始
|
| 39 |
+
|
| 40 |
+
### 安装
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
git clone https://github.com/WisdomShell/GRIP
|
| 44 |
+
cd GRIP
|
| 45 |
+
conda create -n GRIP python=3.9
|
| 46 |
+
conda activate GRIP
|
| 47 |
+
cd GRIP/model/Train
|
| 48 |
+
pip install -e .
|
| 49 |
+
cd ../
|
| 50 |
+
pip install -r requirements.txt
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
## 准备工作
|
| 54 |
+
|
| 55 |
+
### 构建 Wikipedia 索引
|
| 56 |
+
|
| 57 |
+
下载 Wikipedia 数据转储文件。
|
| 58 |
+
|
| 59 |
+
```python
|
| 60 |
+
mkdir wiki_data
|
| 61 |
+
cd wiki_data
|
| 62 |
+
wget https://dl.fbaipublicfiles.com/dpr/wikipedia_split/psgs_w100.tsv.gz
|
| 63 |
+
gzip -d psgs_w100.tsv.gz
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
使用 Elasticsearch 对 Wikipedia 数据建立索引。
|
| 67 |
+
|
| 68 |
+
```python
|
| 69 |
+
mkdir ret
|
| 70 |
+
cd ret
|
| 71 |
+
wget -O elasticsearch-7.17.9.tar.gz https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.9-linux-x86_64.tar.gz
|
| 72 |
+
tar zxvf elasticsearch-7.17.9.tar.gz
|
| 73 |
+
rm elasticsearch-7.17.9.tar.gz
|
| 74 |
+
cd elasticsearch-7.17.9
|
| 75 |
+
nohup bin/elasticsearch
|
| 76 |
+
python data_generation/index.py --data_path path/to/your/psgs_w100.tsv --index_name wiki
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
## 检查点与数据集
|
| 80 |
+
|
| 81 |
+
以下是本工作中用于 SFT 和 RL 训练的数据集,以及已训练完成的 GRIP 模型权重。
|
| 82 |
+
|
| 83 |
+
| 数据集 | HF 数据集仓库 |
|
| 84 |
+
|------------------------------|-----------------------------------------------------------------------------------------------------------|
|
| 85 |
+
| GRIP_SFT_Train_Data | [WisdomShell/GRIP_SFT_Data](https://huggingface.co/datasets/WisdomShell/GRIP_SFT_Data) |
|
| 86 |
+
| GRIP_RL_Train_Data | [WisdomShell/GRIP_RL_Data](https://huggingface.co/datasets/WisdomShell/GRIP_RL_Data) |
|
| 87 |
+
|
| 88 |
+
| 模型 | HF 模型仓库 |
|
| 89 |
+
|------------------------------|-----------------------------------------------------------------------------------------------------------|
|
| 90 |
+
| Meta-LLaMa-3-8b-GRIP | [WisdomShell/LLaMa-3-8b-GRIP](https://huggingface.co/WisdomShell/GRIP-Llama-3-8B) |
|
| 91 |
+
|
| 92 |
+
## 生成 SFT 和 RL 训练数据
|
| 93 |
+
|
| 94 |
+
在此之前,您需要下载 `NaturalQuestion-open` 训练集、`WebQuestions` 训练集和 `TriviaQA` 训练集,提取其中的问题��答案,将它们合并为一个 jsonl 文件,并转换为以下格式:
|
| 95 |
+
|
| 96 |
+
```json
|
| 97 |
+
{
|
| 98 |
+
"question": "",
|
| 99 |
+
"answer":["Answer", ...]
|
| 100 |
+
}
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
使用 `Meta-LLaMa-3-8B-Instruct` 模型执行以下代码:
|
| 104 |
+
|
| 105 |
+
```python
|
| 106 |
+
bash data_generation/first.sh
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
将您的 *OpenAI token* 写入 `use_gpt_for_data.py` 文件,并配置 `C.jsonl` 文件路径。
|
| 110 |
+
生成完成后,将自动覆盖原始文件。
|
| 111 |
+
|
| 112 |
+
```
|
| 113 |
+
python generation_train_data/use_gpt_for_data.py
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
将 A、B、C、D 所在的目录写入 `merge_dataset.py` 文件。
|
| 117 |
+
输出路径将保存 SFT_Train_data 和 RL_Train_data。
|
| 118 |
+
|
| 119 |
+
```
|
| 120 |
+
python generation_train_data/merge_dataset.py
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
## 训练
|
| 124 |
+
|
| 125 |
+
### SFT
|
| 126 |
+
|
| 127 |
+
1. 数据处理
|
| 128 |
+
|
| 129 |
+
- 脚本:`Train/examples/data_preprocess/grip/sft.py`
|
| 130 |
+
- 您需要指定 `data_path` 参数,即 GRIP 合成数据的路径:
|
| 131 |
+
|
| 132 |
+
```python
|
| 133 |
+
parser.add_argument('--data_path', default='<PATH_TO_RAW_DATASET_ROOT>/SFT_data.jsonl')
|
| 134 |
+
```
|
| 135 |
+
- 您需要指定 `dataset` 的名称,以便在后续训练中使用:
|
| 136 |
+
|
| 137 |
+
```python
|
| 138 |
+
# 数据路径默认保存在 "datasets" 文件夹中
|
| 139 |
+
parser.add_argument('--save_dir', default='datasets/GRIPSFT')
|
| 140 |
+
```
|
| 141 |
+
2. 训练脚本
|
| 142 |
+
|
| 143 |
+
- 脚本:`Train/examples/sft/run_sft_llama.sh`
|
| 144 |
+
- 使用模型的 **Base 版本** 进行训练:
|
| 145 |
+
|
| 146 |
+
```bash
|
| 147 |
+
set -x
|
| 148 |
+
|
| 149 |
+
NAME=GRIPSFT # 在此指定上一步处理后的训练数据名称
|
| 150 |
+
torchrun --standalone --nnodes=1 --nproc_per_node=8 -m verl.trainer.fsdp_sft_trainer \
|
| 151 |
+
data.train_files=datasets/$NAME/train.parquet \
|
| 152 |
+
data.val_files=datasets/$NAME/test.parquet \
|
| 153 |
+
data.prompt_key=extra_info \
|
| 154 |
+
data.response_key=extra_info \
|
| 155 |
+
optim.lr=1e-6 \
|
| 156 |
+
data.prompt_dict_keys=['question'] \
|
| 157 |
+
+data.response_dict_keys=['answer'] \
|
| 158 |
+
data.micro_batch_size=4 \
|
| 159 |
+
model.partial_pretrain=meta-llama/Meta-Llama-3-8B-Base \ #使用 Base 版本训练
|
| 160 |
+
trainer.default_local_dir=/path/to/your/SFT_model \ # 微调模型保存路径
|
| 161 |
+
trainer.project_name=GRIPSFT \
|
| 162 |
+
trainer.experiment_name=$NAME \
|
| 163 |
+
trainer.logger=['console'] \ # 上报到 `console` 或 `wandb`
|
| 164 |
+
trainer.total_epochs=8 \ # 训练轮次
|
| 165 |
+
trainer.default_hdfs_dir=null $@ \
|
| 166 |
+
ulysses_sequence_parallel_size=2 \
|
| 167 |
+
use_remove_padding=true
|
| 168 |
+
```
|
| 169 |
+
|
| 170 |
+
### RL
|
| 171 |
+
|
| 172 |
+
1. 数据处理
|
| 173 |
+
|
| 174 |
+
- 脚本:`Train/examples/data_preprocess/grip/rl.py`
|
| 175 |
+
- 您需要指定 `data_path` 参数,即 GRIP 合成数据的路径:
|
| 176 |
+
|
| 177 |
+
```python
|
| 178 |
+
parser.add_argument('--data_path', default='<PATH_TO_RAW_DATASET_ROOT>/RL_data.jsonl')
|
| 179 |
+
```
|
| 180 |
+
- 您需要指定 `dataset` 的名称,以便在后续训练中使用:
|
| 181 |
+
|
| 182 |
+
```python
|
| 183 |
+
# 数据路径默认保存在 "datasets" 文件夹中
|
| 184 |
+
parser.add_argument('--save_dir', default='datasets/GRIPRL')
|
| 185 |
+
```
|
| 186 |
+
- 您需要指定 `data_source` 的名称,以便在后续训练中选择奖励模型:
|
| 187 |
+
|
| 188 |
+
```python
|
| 189 |
+
parser.add_argument('--data_source', default='GRIPRL') # 必填
|
| 190 |
+
```
|
| 191 |
+
2. 使用 `DAPO` 训练脚本
|
| 192 |
+
|
| 193 |
+
- 脚本:`Train/recipe/dapo/dapo_4w_continue_rl_ep3_llama.sh`
|
| 194 |
+
- 您需要修改以下参数以适配 RL 训练:
|
| 195 |
+
|
| 196 |
+
```bash
|
| 197 |
+
...
|
| 198 |
+
# 路径配置
|
| 199 |
+
MODEL_PATH=<PATH_TO_SAVE>/GRIPSFT_LLaMa/global_step_xxx # SFT 检查点
|
| 200 |
+
CKPTS_DIR=<PATH_TO_SAVE>/RL_model # RL 模型保存路径
|
| 201 |
+
TRAIN_FILE=datasets/GRIPRL/train.parquet # RL 数据集
|
| 202 |
+
TEST_FILE=datasets/GRIPRL/test.parquet # RL 数据集
|
| 203 |
+
...
|
| 204 |
+
```
|
| 205 |
+
3. 奖励模型的具体实现位于文件 `Train/verl/utils/reward_score/grip.py` 中。
|
| 206 |
+
4. 训练完成后,您需要通过脚本 `Train/scripts/merge.sh` 将模型保存的分片合并为 Hugging Face 格式。
|
| 207 |
+
|
| 208 |
+
### 使用 GRIP 进行本地推理
|
| 209 |
+
|
| 210 |
+
#### 测试数据格式对齐
|
| 211 |
+
|
| 212 |
+
```json
|
| 213 |
+
{
|
| 214 |
+
"question": "Test Query",
|
| 215 |
+
"answer": ["Answer List", ...]
|
| 216 |
+
}
|
| 217 |
+
```
|
| 218 |
+
|
| 219 |
+
#### 多轮 GRIP 推理
|
| 220 |
+
|
| 221 |
+
- 主脚本:`inference/inference.sh`
|
| 222 |
+
|
| 223 |
+
```python
|
| 224 |
+
# 模型保存路径
|
| 225 |
+
parser.add_argument('--model_path', type=str, default="/path/to/your/RL_model/step_xxx")
|
| 226 |
+
# 预测文件输出路径
|
| 227 |
+
parser.add_argument('--output_file', type=str, default="output/rl_step_xxx_hotpot.jsonl")
|
| 228 |
+
# 待预测文件
|
| 229 |
+
parser.add_argument('--input_file', type=str, default="test_data/hotpotQA.jsonl")
|
| 230 |
+
```
|
| 231 |
+
- 该脚本将按以下格式生成预测结果:
|
| 232 |
+
|
| 233 |
+
```json
|
| 234 |
+
{
|
| 235 |
+
"Question": "String",
|
| 236 |
+
"prediction": ["String",......]
|
| 237 |
+
}
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
## 评估
|
| 241 |
+
|
| 242 |
+
```python
|
| 243 |
+
python eval/eval.py \
|
| 244 |
+
--references_path test_dataset.jsonl \
|
| 245 |
+
--predictions_path prediction.jsonl
|
| 246 |
+
```
|
| 247 |
+
|
| 248 |
+
## 🤝 贡献
|
| 249 |
+
|
| 250 |
+
欢迎贡献!请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解相关指引。
|
| 251 |
+
|
| 252 |
+
## 📄 引用
|
| 253 |
+
如果您使用了本仓库,请引用该论文。
|
| 254 |
+
```bibtex
|
| 255 |
+
|
| 256 |
+
```
|
| 257 |
+
|
| 258 |
+
## 📝 许可证
|
| 259 |
+
|
| 260 |
+
本项目采用 Apache 2.0 许可证——详情请参阅 [LICENSE](LICENSE) 文件。
|
| 261 |
+
|
| 262 |
+
## 🙏 致谢
|
| 263 |
+
|
| 264 |
+
特别感谢开源社区及所有使本项目成为可能的贡献者。
|