Spaces:
Running
Running
"""Taken and modified from vllm: https://github.com/vllm-project/vllm/blob/93b38bea5dd03e1b140ca997dfaadef86f8f1855/benchmarks/benchmark_serving.py | |
Filter dataset to: | |
1. Remove entries that have too long prompts or completions | |
2. Only keep first human prompt for each conversation | |
""" | |
import json | |
import random | |
from typing import AsyncGenerator, List, Tuple | |
from transformers import ( | |
AutoTokenizer, | |
PreTrainedTokenizer, | |
PreTrainedTokenizerBase, | |
PreTrainedTokenizerFast, | |
) | |
def filter_dataset_to_size( | |
dataset_path: str, | |
size: int, | |
) -> List[Tuple[str, int, int]]: | |
# Load the dataset. | |
with open(dataset_path) as f: | |
dataset = json.load(f) | |
# randomly sample dataset | |
return random.sample(dataset, size) | |
def filter_dataset( | |
dataset_path: str, | |
tokenizer: PreTrainedTokenizerBase, | |
) -> List[Tuple[str, int, int]]: | |
# Load the dataset. | |
with open(dataset_path) as f: | |
dataset = json.load(f) | |
# Filter out the conversations with less than 2 turns. | |
dataset = [data for data in dataset if len(data["conversations"]) >= 2] | |
# Only keep the first two turns of each conversation, where the first turn is human. | |
dataset = [ | |
( | |
data["id"], | |
data["conversations"][0]["value"], | |
data["conversations"][1]["value"], | |
) | |
for data in dataset if data["conversations"][0]["from"] == "human" | |
] | |
# Tokenize the prompts and completions. | |
conversation_ids = [conv_id for conv_id, _, _ in dataset] | |
prompts = [prompt for _, prompt, _ in dataset] | |
prompt_token_ids = tokenizer(prompts).input_ids | |
completions = [completion for _, _, completion in dataset] | |
completion_token_ids = tokenizer(completions).input_ids | |
tokenized_dataset = [] | |
for i in range(len(dataset)): | |
output_len = len(completion_token_ids[i]) | |
tokenized_dataset.append( | |
(conversation_ids[i], prompts[i], prompt_token_ids[i], output_len) | |
) | |
# Filter out too long sequences. | |
filtered_dataset_json = [] | |
for conv_id, prompt, prompt_token_ids, output_len in tokenized_dataset: | |
prompt_len = len(prompt_token_ids) | |
if prompt_len < 4 or output_len < 4: | |
# Prune too short sequences. | |
# This is because TGI causes errors when the input or output length | |
# is too short. | |
continue | |
# making even shorter than 1024 to account for additional tokens introduced by chat completion wrapper | |
if prompt_len > 800 or output_len > 800: | |
# if prompt_len > 1024 or output_len > 1024: | |
# Prune too long sequences. | |
continue | |
filtered_dataset_json.append( | |
{ | |
"id": conv_id, | |
"conversations": [ | |
{ | |
"from": "human", | |
"value": prompt, | |
} | |
], | |
} | |
) | |
return filtered_dataset_json | |
def main(): | |
tokenizer = AutoTokenizer.from_pretrained("huggyllama/llama-7b") | |
# download: https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json | |
filtered_dataset = filter_dataset( | |
"ShareGPT_V3_unfiltered_cleaned_split.json", tokenizer | |
) | |
with open("ShareGPT_V3_filtered.json", "w") as f: | |
json.dump(filtered_dataset, f) | |
print(f'Created filtered benchmark of size: {len(filtered_dataset)}') | |
sampled_dataset = filter_dataset_to_size("ShareGPT_V3_filtered.json", 500) | |
with open("ShareGPT_V3_filtered_500.json", "w") as f: | |
json.dump(sampled_dataset, f) | |
print(f'Created sampled benchmark of size: {len(sampled_dataset)}') | |
if __name__ == "__main__": | |
main() | |