We extend the context length of Llama-3-8B-Instruct to 80K using QLoRA and 3.5K long-context training data synthesized from GPT-4. The entire training cycle is super efficient, which takes 8 hours on a 8xA800 (80G) machine. Yet, the resulted model achieves remarkable performance on a series of downstream long-context evaluation benchmarks.
All the following evaluation results can be reproduced following instructions
here.
We evaluate the model on the Needle-In-A-HayStack task using the official setting. The blue vertical line indicates the training context length, i.e. 80K.
We evaluate the model on
LongBench using 32K context length and the official prompt template. For
meta-llama/Meta-Llama-3-8B-Instruct, we use 8K context length.
We evaluate the model on
InfiniteBench using 80K context length and the official prompt template. The results of GPT-4 is copied from the
paper. For
meta-llama/Meta-Llama-3-8B-Instruct, we use 8K context length.
We evaluate the model's zero-shot performance on MMLU benchmark as a reflection of its short-context capability.
1torch==2.2.2
2flash_attn==2.5.6
3transformers==4.39.3
4peft==0.10.0
1import json
2import torch
3from transformers import AutoModelForCausalLM, AutoTokenizer
4from peft import PeftModel
5
6model_id = "meta-llama/Meta-Llama-3-8B-Instruct"
7peft_id = "namespace-Pt/Llama-3-8B-Instruct-80K-QLoRA"
8
9torch_dtype = torch.bfloat16
10# place the model on GPU
11device_map = {"": "cuda"}
12
13tokenizer = AutoTokenizer.from_pretrained(model_id)
14
15base_model = AutoModelForCausalLM.from_pretrained(
16 model_id,
17 torch_dtype=torch.bfloat16,
18 device_map=device_map,
19 attn_implementation="flash_attention_2",
20
21 # NOTE: expand rope base
22 rope_theta=200e6,
23)
24
25model = PeftModel.from_pretrained(
26 base_model,
27 peft_id,
28 torch_dtype=torch.bfloat16,
29 device_map=device_map,
30)
31# NOTE: merge LoRA weights
32model = model.merge_and_unload().eval()
33
34with torch.no_grad():
35 # short context
36 messages = [{"role": "user", "content": "Tell me about yourself."}]
37 inputs = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt", return_dict=True).to("cuda")
38 outputs = model.generate(**inputs, max_new_tokens=50)[:, inputs["input_ids"].shape[1]:]
39 print(f"Input Length: {inputs['input_ids'].shape[1]}")
40 print(f"Output: {tokenizer.decode(outputs[0])}")
41
42 # long context
43 with open("data/narrativeqa.json", encoding="utf-8") as f:
44 example = json.load(f)
45 messages = [{"role": "user", "content": example["context"]}]
46 inputs = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt", return_dict=True).to("cuda")
47 outputs = model.generate(**inputs, do_sample=False, top_p=1, temperature=1, max_new_tokens=20)[:, inputs["input_ids"].shape[1]:]
48 print("*"*20)
49 print(f"Input Length: {inputs['input_ids'].shape[1]}")
50 print(f"Answers: {example['answer']}")
51 print(f"Prediction: {tokenizer.decode(outputs[0])}")