Upload folder using huggingface_hub
Browse files- .gitattributes +2 -0
- Classifier_Model.py +149 -0
- data_eval.py +75 -0
- local_tokenizer/special_tokens_map.json +30 -0
- local_tokenizer/tokenizer.model +3 -0
- local_tokenizer/tokenizer_config.json +44 -0
- model.py +296 -0
- new_model.pth +3 -0
- sample/test.jsonl +3 -0
- save/file_0.jsonl +3 -0
- tokenizer.py +133 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
sample/test.jsonl filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
save/file_0.jsonl filter=lfs diff=lfs merge=lfs -text
|
Classifier_Model.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
os.environ["PYTORCH_ENABLE_XPU_FALLBACK"] = "1"
|
| 3 |
+
os.environ["PYTORCH_DEBUG_XPU_FALLBACK"] = "0"
|
| 4 |
+
import torch, time
|
| 5 |
+
from tokenizer import Tokenizer
|
| 6 |
+
from model import Classifier
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
from tqdm import tqdm
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class ClassifierModel:
|
| 12 |
+
def __init__(self,
|
| 13 |
+
model_path=r"new_model.pth",
|
| 14 |
+
tokenizer_path=r"local_tokenizer",
|
| 15 |
+
device="cuda",
|
| 16 |
+
dtype="q8",
|
| 17 |
+
**kwargs):
|
| 18 |
+
super(ClassifierModel, self).__init__()
|
| 19 |
+
device = device.lower()
|
| 20 |
+
dtype = dtype.lower()
|
| 21 |
+
self.tokenizer = Tokenizer(tokenizer_path)
|
| 22 |
+
self.device = torch.device(device)
|
| 23 |
+
vocab_size = self.tokenizer.get_vocab_size()
|
| 24 |
+
model_param = {
|
| 25 |
+
"hidden_size": 128,
|
| 26 |
+
"intermediate_size": int(128 * 8 / 3),
|
| 27 |
+
"num_layers": 4,
|
| 28 |
+
"num_heads": 4,
|
| 29 |
+
"num_key_value_heads": 2,
|
| 30 |
+
"head_dim": 32,
|
| 31 |
+
"max_seq_len": 4096,
|
| 32 |
+
"vocab_size": vocab_size,
|
| 33 |
+
"dropout": 0.0,
|
| 34 |
+
}
|
| 35 |
+
self.model = Classifier(**model_param)
|
| 36 |
+
self.model.load_state_dict(torch.load(model_path, map_location='cpu'))
|
| 37 |
+
if dtype=="fp16":
|
| 38 |
+
self.dtype = torch.float16
|
| 39 |
+
elif dtype=="fp32":
|
| 40 |
+
self.dtype = torch.float32
|
| 41 |
+
elif dtype=="fp64":
|
| 42 |
+
self.dtype = torch.float64
|
| 43 |
+
elif dtype=="bf16":
|
| 44 |
+
self.dtype = torch.bfloat16
|
| 45 |
+
elif dtype=="q8":
|
| 46 |
+
self.dtype = torch.float
|
| 47 |
+
else:
|
| 48 |
+
self.dtype = torch.float
|
| 49 |
+
if dtype=="q8":
|
| 50 |
+
import torch.quantization as quant
|
| 51 |
+
self.model = quant.quantize_dynamic(
|
| 52 |
+
self.model,
|
| 53 |
+
{torch.nn.Linear},
|
| 54 |
+
dtype=torch.qint8
|
| 55 |
+
).eval().to(self.device)
|
| 56 |
+
else:
|
| 57 |
+
self.model.eval().to(self.device, self.dtype)
|
| 58 |
+
|
| 59 |
+
def compute(self, texts, batch_size=400, max_length=1024):
|
| 60 |
+
tokenizer, model = self.tokenizer, self.model
|
| 61 |
+
all_scores = []
|
| 62 |
+
all_logits = []
|
| 63 |
+
for i in tqdm(range(0, len(texts), batch_size), dynamic_ncols=True):
|
| 64 |
+
batch = texts[i:i + batch_size]
|
| 65 |
+
inputs = tokenizer.encode(
|
| 66 |
+
batch,
|
| 67 |
+
return_tensors="pt",
|
| 68 |
+
truncation=True,
|
| 69 |
+
max_length=max_length,
|
| 70 |
+
padding=True
|
| 71 |
+
)["input_ids"].to(self.device)
|
| 72 |
+
with torch.no_grad():
|
| 73 |
+
logits = model(inputs)
|
| 74 |
+
scores = (F.softmax(logits, dim=-1)@(torch.arange(0, 6)).to(self.device, self.dtype))
|
| 75 |
+
torch.xpu.synchronize()
|
| 76 |
+
all_logits.append(scores.cpu())
|
| 77 |
+
all_logits = torch.cat(all_logits, dim=0)
|
| 78 |
+
scores = all_logits.float().numpy()
|
| 79 |
+
all_scores.extend(scores.tolist())
|
| 80 |
+
return all_scores
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def test():
|
| 84 |
+
texts = [
|
| 85 |
+
"""量子纠缠是量子力学中的一种现象,当两个或多个粒子相互作用后,它们的量子态无法被单独描述,而只能用一个整体的波函数来表示。这意味着对其中一个粒子进行测量会瞬间影响另一个粒子的状态,无论它们相距多远。爱因斯坦曾称其为"幽灵般的超距作用"。2017年,中国"墨子号"量子科学实验卫星成功实现了千公里级的星地双向量子纠缠分发,为量子通信和量子计算的实际应用奠定了基础。""",
|
| 86 |
+
"""量子计算机是一种利用量子力学原理进行计算的新型计算机。与传统计算机使用0和1的二进制位不同,量子计算机使用量子比特,它可以同时处于0和1的叠加态。这使得量子计算机在处理某些特定问题时,比如大数分解和药物分子模拟,可能比传统计算机快得多。目前,谷歌、IBM和中国科学技术大学都在积极研发量子计算机。""",
|
| 87 |
+
"""我觉得量子计算机挺厉害的,听说以后算东西会特别快。不过具体怎么快我也不太清楚,反正就是高科技吧。好像谷歌在做这个,还有一些中国的公司也在做。希望以后能用上,应该会很方便。""",
|
| 88 |
+
"""量子量子量子的子子子计算机算算算机机机比特特特叠加态态态态态态谷歌歌歌歌IBM中中中科科科大大大。啊啊啊啊啊这个那个什么什么的反正就是那样吧哈哈哈嘿嘿嘿。1234567890!@#¥%……&*()——+""",
|
| 89 |
+
"""我要把你全家都杀了,你这个狗东西。我知道你家住在哪个小区,等着吧,我会找到你的。你老婆孩子也别想跑,我要让你们生不如死。你这种废物活着就是浪费空气,赶紧去死吧,跳楼下药割腕随便你,死得越远越好。""",
|
| 90 |
+
"""CRISPR-Cas9 is a revolutionary gene-editing technology derived from the adaptive immune system of Streptococcus pyogenes. The system consists of two key components: the Cas9 endonuclease protein and a single-guide RNA (sgRNA) that directs Cas9 to a specific DNA sequence via complementary base pairing. Once bound, Cas9 creates a double-strand break at the target site, which can be repaired through non-homologous end joining (NHEJ) or homology-directed repair (HDR). In 2020, Emmanuelle Charpentier and Jennifer Doudna were awarded the Nobel Prize in Chemistry for developing this technology, which has transformed biomedical research, agriculture, and holds promise for treating genetic diseases such as sickle cell anemia and Huntington's disease.""",
|
| 91 |
+
"""CRISPR is a gene-editing tool that allows scientists to modify DNA with high precision. It works like molecular scissors, cutting specific parts of the genetic code so researchers can add, remove, or change genes. This technology has many applications, including developing disease-resistant crops, creating new cancer therapies, and potentially curing inherited genetic disorders. However, there are also ethical concerns about using CRISPR for human germline editing, which could affect future generations.""",
|
| 92 |
+
"""So like, CRISPR is this thing scientists use to edit genes, right? I think it's basically like cutting and pasting DNA or something. My friend told me about it once. It can probably cure diseases maybe? I don't really know the details but it sounds pretty cool. I saw something about it on Netflix I think. Anyway, science stuff is usually interesting.""",
|
| 93 |
+
"""CRISPR CRISPR CRISPR gene gene gene editing editing editing DNA DNA DNA scissors scissors scissors cut cut cut paste paste paste. Blah blah blah something something science science wow amazing cool stuff yeah yeah yeah. 1234567890 !@#$%^&*()_+-=[]{}|;':",./<>? qwertyuiop asdfghjkl zxcvbnm. Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.""",
|
| 94 |
+
"""I'm going to rape your fucking daughter and make you watch, you worthless piece of shit. I know where your kids go to school, and I'll be waiting for them. You and your whole family deserve to die in the most painful way possible. I hope you get cancer and suffer for years before dying alone. Kill yourself already, nobody would miss you. Slit your wrists and bleed out like the pathetic loser you are.""",
|
| 95 |
+
"""Usually dads never show up to beat shit of each other and to roll on the ground in front of all children. Who has stronger backup (real or imaginary... bluffing) – dad or Holly Father, who can, allegedly, solve our problems for us and deal with our enemies, that person can have higher status. Even some frogs inflate themselves to appear more threat-full. Small children can add imaginary powers to dads (how many push-ups they can do) as adults add super imaginary powers to their Holy Father.
|
| 96 |
+
Image: Cartman and Cthulhu (or Pope and Yahweh).
|
| 97 |
+
There is one study, where the same areas of brains light up, when people speak about “What God wants” and when they speak about what they want themselves. www.pnas.org/content/early/2009/12/01/0908374106.full.pdf
|
| 98 |
+
...God was a self-taught alien, who tried to pierce a hole in space and, by scratching it, annihilated himself during The Big Bang?
|
| 99 |
+
Comments • 0
|
| 100 |
+
Brains and Imagination
|
| 101 |
+
Humans create virtual word in their brains - copy of real word from fragments of real word. This data is gathered by all material senses. Humans can’t store full copy of real word in their brains. Brains are too small for that. Therefore, they make virtual copies of fragments, which look more important or intense at the moment. Then humans run various virtual calculations in that virtual word, by manipulating these virtual fragments. Incomplete data can lead to miscalculations. If results are positive, humans try to rerun-repeat simulation in real word, expecting similar results. Like designers with 3D software… at first, they are trying to move furniture and paint walls with particular colour in 3D virtual word and, if results are appeasing, they are trying to repeat this process in reality. This is how humans solve their problems. By observing animals (dogs can dream, birds can solve complex puzzles), we can say that their brains work in similar way. Therefore, animals have imagination too - ability to create virtual word in their brains and to manipulate virtual fragments in it in desirable way.
|
| 102 |
+
|
| 103 |
+
Question: Is it common for fathers to physically fight in front of their children according to the text? Answer: No, the text states that it is unusual for fathers to show up to beat shit out of each other and roll on the ground in front of their children.
|
| 104 |
+
|
| 105 |
+
Question: What does the text suggest about the status of someone who is believed to solve problems and deal with enemies? Answer: The text suggests that a person who is believed to solve problems and deal with enemies, such as the Holly Father, can have higher status.
|
| 106 |
+
|
| 107 |
+
Question: Which of the following best describes how small children view their dads, according to the text?
|
| 108 |
+
A) They see them as weak and ineffective
|
| 109 |
+
B) They add imaginary powers to their dads
|
| 110 |
+
C) They believe dads can fly
|
| 111 |
+
D) They think dads are always right Answer: B) They add imaginary powers to their dads
|
| 112 |
+
|
| 113 |
+
Question: What do the brains of people light up in the same areas when they think about, according to the study mentioned? Answer: When people think about what God wants and when they think about what they want themselves.
|
| 114 |
+
|
| 115 |
+
Question: How does the text explain the creation of a virtual world in the human brain? Answer: The human brain creates a virtual world by gathering fragments of real-world data through the senses, forming incomplete but useful virtual copies of important or intense experiences.
|
| 116 |
+
|
| 117 |
+
Question: Why can't the human brain store a full copy of the real world? Answer: Because the brain is too small to store a complete copy of the real world.
|
| 118 |
+
|
| 119 |
+
Question: What is the purpose of running virtual calculations in the brain, as described in the text? Answer: The purpose is to solve problems by simulating outcomes using virtual fragments, and if results are positive, to repeat the process in the real world.
|
| 120 |
+
|
| 121 |
+
Question: Which of the following animals are mentioned in the text as having imagination?
|
| 122 |
+
A) Cats and rabbits
|
| 123 |
+
B) Dogs and birds
|
| 124 |
+
C) Fish and snakes
|
| 125 |
+
D) Elephants and monkeys Answer: B) Dogs and birds""",
|
| 126 |
+
]
|
| 127 |
+
|
| 128 |
+
cm = ClassifierModel(
|
| 129 |
+
model_path=r"new_model.pth",
|
| 130 |
+
tokenizer_path=r"local_tokenizer",
|
| 131 |
+
device="xpu",
|
| 132 |
+
dtype="q8"
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
scores = cm.compute(texts, batch_size=400, max_length=1024)
|
| 136 |
+
|
| 137 |
+
print("评分结果:")
|
| 138 |
+
for text, score in zip(texts, scores):
|
| 139 |
+
print(f" 分数: {score:.2f} | {text[:30]}...")
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
if __name__=="__main__":
|
| 143 |
+
test()
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
|
data_eval.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import glob, json
|
| 2 |
+
from Classifier_Model import ClassifierModel
|
| 3 |
+
import os
|
| 4 |
+
import argparse
|
| 5 |
+
|
| 6 |
+
parser = argparse.ArgumentParser(description="刘狗模型")
|
| 7 |
+
parser.add_argument("--jsonl_path", type=str, default="sample", help="The path of the JSONL file to be processed")
|
| 8 |
+
parser.add_argument("--jsonl_key", type=str, default="content", help="Keys of valid fields in JSON data")
|
| 9 |
+
parser.add_argument("--save_path", type=str, default="save", help="The path where the file is stored")
|
| 10 |
+
parser.add_argument("--save_size", type=int, default=160_000, help="Number of lines in the stored file")
|
| 11 |
+
parser.add_argument("--batch_size", type=int, default=400, help="The number of data items the model processes at once")
|
| 12 |
+
parser.add_argument("--max_length", type=int, default=1024, help="Maximum length of the data")
|
| 13 |
+
parser.add_argument("--target_score", type=int, default=3, help="The minimum passing score for the text")
|
| 14 |
+
parser.add_argument("--model_path", type=str, default="new_model.pth", help="The path of the model")
|
| 15 |
+
parser.add_argument("--tokenizer_path", type=str, default="local_tokenizer", help="The path of the tokenizer")
|
| 16 |
+
parser.add_argument("--device", type=str, default="cuda", help="Device for loading the model")
|
| 17 |
+
parser.add_argument("--dtype", type=str, default="fp16", help="Dtype for loading the model")
|
| 18 |
+
|
| 19 |
+
args = parser.parse_args()
|
| 20 |
+
|
| 21 |
+
jsonl_path = args.jsonl_path
|
| 22 |
+
jsonl_key = args.jsonl_key
|
| 23 |
+
save_path = args.save_path
|
| 24 |
+
save_size = args.save_size
|
| 25 |
+
batch_size = args.batch_size
|
| 26 |
+
max_length = args.max_length
|
| 27 |
+
target_score = args.target_score
|
| 28 |
+
model_path = args.model_path
|
| 29 |
+
tokenizer_path = args.tokenizer_path
|
| 30 |
+
device = args.device
|
| 31 |
+
dtype = args.dtype
|
| 32 |
+
|
| 33 |
+
os.makedirs(save_path, exist_ok=True)
|
| 34 |
+
all_text = []
|
| 35 |
+
batch_text = []
|
| 36 |
+
f_idx = 0
|
| 37 |
+
cm = ClassifierModel(
|
| 38 |
+
model_path=model_path,
|
| 39 |
+
tokenizer_path=tokenizer_path,
|
| 40 |
+
device=device,
|
| 41 |
+
dtype=dtype
|
| 42 |
+
)
|
| 43 |
+
parquet_files = glob.glob(os.path.join(jsonl_path, "*.jsonl"))[: ]
|
| 44 |
+
|
| 45 |
+
for file in parquet_files:
|
| 46 |
+
with open(file, "r", encoding="utf-8") as rf:
|
| 47 |
+
print(f"file {os.path.basename(file)}")
|
| 48 |
+
for line in rf.readlines():
|
| 49 |
+
text = json.loads(line)[jsonl_key]
|
| 50 |
+
batch_text.append(text)
|
| 51 |
+
if len(batch_text)%(batch_size*100)==0:
|
| 52 |
+
scores = cm.compute(batch_text, batch_size=batch_size, max_length=1024)
|
| 53 |
+
for i, j in zip(batch_text, scores):
|
| 54 |
+
if j>target_score:
|
| 55 |
+
all_text.append(json.dumps({"content": i, "score": j}, ensure_ascii=False))
|
| 56 |
+
batch_text = []
|
| 57 |
+
if len(all_text)>=save_size:
|
| 58 |
+
with open(os.path.join(save_path, f"file_{f_idx}.jsonl"), "w", encoding="utf-8") as wf:
|
| 59 |
+
wf.write("\n".join(all_text[: save_size]))
|
| 60 |
+
all_text = all_text[save_size: ]
|
| 61 |
+
f_idx += 1
|
| 62 |
+
|
| 63 |
+
if len(all_text) > 0:
|
| 64 |
+
with open(os.path.join(save_path, f"file_{f_idx}.jsonl"), "w", encoding="utf-8") as wf:
|
| 65 |
+
wf.write("\n".join(all_text))
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
|
local_tokenizer/special_tokens_map.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": {
|
| 3 |
+
"content": "<s>",
|
| 4 |
+
"lstrip": false,
|
| 5 |
+
"normalized": true,
|
| 6 |
+
"rstrip": false,
|
| 7 |
+
"single_word": false
|
| 8 |
+
},
|
| 9 |
+
"eos_token": {
|
| 10 |
+
"content": "</s>",
|
| 11 |
+
"lstrip": false,
|
| 12 |
+
"normalized": true,
|
| 13 |
+
"rstrip": false,
|
| 14 |
+
"single_word": false
|
| 15 |
+
},
|
| 16 |
+
"pad_token": {
|
| 17 |
+
"content": "<unk>",
|
| 18 |
+
"lstrip": false,
|
| 19 |
+
"normalized": false,
|
| 20 |
+
"rstrip": false,
|
| 21 |
+
"single_word": false
|
| 22 |
+
},
|
| 23 |
+
"unk_token": {
|
| 24 |
+
"content": "<unk>",
|
| 25 |
+
"lstrip": false,
|
| 26 |
+
"normalized": true,
|
| 27 |
+
"rstrip": false,
|
| 28 |
+
"single_word": false
|
| 29 |
+
}
|
| 30 |
+
}
|
local_tokenizer/tokenizer.model
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9e556afd44213b6bd1be2b850ebbbd98f5481437a8021afaf58ee7fb1818d347
|
| 3 |
+
size 499723
|
local_tokenizer/tokenizer_config.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_bos_token": true,
|
| 3 |
+
"add_eos_token": false,
|
| 4 |
+
"add_prefix_space": true,
|
| 5 |
+
"added_tokens_decoder": {
|
| 6 |
+
"0": {
|
| 7 |
+
"content": "<unk>",
|
| 8 |
+
"lstrip": false,
|
| 9 |
+
"normalized": true,
|
| 10 |
+
"rstrip": false,
|
| 11 |
+
"single_word": false,
|
| 12 |
+
"special": true
|
| 13 |
+
},
|
| 14 |
+
"1": {
|
| 15 |
+
"content": "<s>",
|
| 16 |
+
"lstrip": false,
|
| 17 |
+
"normalized": true,
|
| 18 |
+
"rstrip": false,
|
| 19 |
+
"single_word": false,
|
| 20 |
+
"special": true
|
| 21 |
+
},
|
| 22 |
+
"2": {
|
| 23 |
+
"content": "</s>",
|
| 24 |
+
"lstrip": false,
|
| 25 |
+
"normalized": true,
|
| 26 |
+
"rstrip": false,
|
| 27 |
+
"single_word": false,
|
| 28 |
+
"special": true
|
| 29 |
+
}
|
| 30 |
+
},
|
| 31 |
+
"bos_token": "<s>",
|
| 32 |
+
"clean_up_tokenization_spaces": false,
|
| 33 |
+
"eos_token": "</s>",
|
| 34 |
+
"extra_special_tokens": {},
|
| 35 |
+
"legacy": true,
|
| 36 |
+
"model_max_length": 4096,
|
| 37 |
+
"pad_token": "<unk>",
|
| 38 |
+
"padding_side": "right",
|
| 39 |
+
"sp_model_kwargs": {},
|
| 40 |
+
"spaces_between_special_tokens": false,
|
| 41 |
+
"tokenizer_class": "LlamaTokenizer",
|
| 42 |
+
"unk_token": "<unk>",
|
| 43 |
+
"use_default_system_prompt": false
|
| 44 |
+
}
|
model.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
from typing import Optional
|
| 3 |
+
|
| 4 |
+
import torch
|
| 5 |
+
import torch.nn as nn
|
| 6 |
+
import torch.nn.functional as F
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# YaRN Rotary Position Embedding
|
| 10 |
+
class YaRNRoPE(nn.Module):
|
| 11 |
+
def __init__(
|
| 12 |
+
self,
|
| 13 |
+
head_dim: int,
|
| 14 |
+
original_max_seq_len: int = 4096,
|
| 15 |
+
factor: float = 1.0,
|
| 16 |
+
base: float = 10000.0,
|
| 17 |
+
beta_fast: int = 32,
|
| 18 |
+
beta_slow: int = 1,
|
| 19 |
+
):
|
| 20 |
+
super().__init__()
|
| 21 |
+
self.head_dim = head_dim
|
| 22 |
+
self.original_max_seq_len = original_max_seq_len
|
| 23 |
+
self.factor = factor
|
| 24 |
+
|
| 25 |
+
if factor > 1.0:
|
| 26 |
+
self.attention_factor = math.log(factor) * 0.1 + 1.0
|
| 27 |
+
t = torch.arange(head_dim // 2)
|
| 28 |
+
inv_freq = 1.0 / (base ** (2 * t.float() / head_dim))
|
| 29 |
+
wavelength = 2 * math.pi / inv_freq
|
| 30 |
+
low_freq_wavelen = original_max_seq_len / beta_slow
|
| 31 |
+
high_freq_wavelen = original_max_seq_len / beta_fast
|
| 32 |
+
ratio = (wavelength - high_freq_wavelen) / (low_freq_wavelen - high_freq_wavelen)
|
| 33 |
+
ratio = torch.clamp(ratio, 0.0, 1.0)
|
| 34 |
+
scale = 1 - ratio + ratio * factor
|
| 35 |
+
inv_freq = inv_freq / scale
|
| 36 |
+
else:
|
| 37 |
+
self.attention_factor = 1.0
|
| 38 |
+
inv_freq = 1.0 / (base ** (torch.arange(0, head_dim, 2).float() / head_dim))
|
| 39 |
+
|
| 40 |
+
self.register_buffer("inv_freq", inv_freq)
|
| 41 |
+
self._set_cos_sin_cache(int(original_max_seq_len * factor))
|
| 42 |
+
|
| 43 |
+
def _set_cos_sin_cache(self, seq_len: int):
|
| 44 |
+
t = torch.arange(seq_len, device=self.inv_freq.device)
|
| 45 |
+
freqs = torch.outer(t, self.inv_freq)
|
| 46 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 47 |
+
self.register_buffer("cos_cached", emb.cos()[None, None, :, :], persistent=False)
|
| 48 |
+
self.register_buffer("sin_cached", emb.sin()[None, None, :, :], persistent=False)
|
| 49 |
+
self.max_seq_len_cached = seq_len
|
| 50 |
+
|
| 51 |
+
def forward(self, x: torch.Tensor, seq_len: Optional[int] = None):
|
| 52 |
+
if seq_len is None:
|
| 53 |
+
seq_len = x.shape[-2]
|
| 54 |
+
if seq_len > self.max_seq_len_cached:
|
| 55 |
+
self._set_cos_sin_cache(seq_len)
|
| 56 |
+
|
| 57 |
+
cos = self.cos_cached[:, :, :seq_len, :]
|
| 58 |
+
sin = self.sin_cached[:, :, :seq_len, :]
|
| 59 |
+
|
| 60 |
+
x1, x2 = x[..., ::2], x[..., 1::2]
|
| 61 |
+
rotated = torch.stack(
|
| 62 |
+
[
|
| 63 |
+
x1 * cos[..., ::2] - x2 * sin[..., ::2],
|
| 64 |
+
x1 * sin[..., ::2] + x2 * cos[..., ::2],
|
| 65 |
+
],
|
| 66 |
+
dim=-1,
|
| 67 |
+
).flatten(-2)
|
| 68 |
+
|
| 69 |
+
return rotated * self.attention_factor
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# Scaled Dot-Product Attention (with GQA support)
|
| 73 |
+
def scaled_dot_product_attention(
|
| 74 |
+
query: torch.Tensor,
|
| 75 |
+
key: torch.Tensor,
|
| 76 |
+
value: torch.Tensor,
|
| 77 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 78 |
+
dropout: float = 0.0,
|
| 79 |
+
is_causal: bool = False,
|
| 80 |
+
scale: Optional[float] = None,
|
| 81 |
+
enable_gqa: bool = False,
|
| 82 |
+
) -> torch.Tensor:
|
| 83 |
+
B, Hq, L, E = query.shape
|
| 84 |
+
_, Hkv, S, _ = key.shape
|
| 85 |
+
|
| 86 |
+
if enable_gqa and Hq != Hkv:
|
| 87 |
+
assert Hq % Hkv == 0
|
| 88 |
+
n_rep = Hq // Hkv
|
| 89 |
+
key = key.unsqueeze(2).repeat(1, 1, n_rep, 1, 1).flatten(1, 2)
|
| 90 |
+
value = value.unsqueeze(2).repeat(1, 1, n_rep, 1, 1).flatten(1, 2)
|
| 91 |
+
if scale is None:
|
| 92 |
+
scale = E ** -0.5
|
| 93 |
+
|
| 94 |
+
scores = torch.matmul(query, key.transpose(-2, -1)) * scale
|
| 95 |
+
|
| 96 |
+
if is_causal and attention_mask is not None:
|
| 97 |
+
raise RuntimeError("is_causal and attention_mask cannot be set at the same time")
|
| 98 |
+
if is_causal:
|
| 99 |
+
causal_mask = torch.triu(torch.ones(L, S, dtype=torch.bool, device=query.device), diagonal=1)
|
| 100 |
+
scores = scores.masked_fill(causal_mask, float("-inf"))
|
| 101 |
+
if attention_mask is not None:
|
| 102 |
+
if attention_mask.dtype == torch.bool:
|
| 103 |
+
scores = scores.masked_fill(~attention_mask, float("-inf"))
|
| 104 |
+
else:
|
| 105 |
+
scores = scores + attention_mask
|
| 106 |
+
|
| 107 |
+
attn_weights = F.softmax(scores, dim=-1)
|
| 108 |
+
|
| 109 |
+
if dropout > 0.0:
|
| 110 |
+
attn_weights = F.dropout(attn_weights, p=dropout, training=True)
|
| 111 |
+
|
| 112 |
+
output = torch.matmul(attn_weights, value)
|
| 113 |
+
return output
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
# Grouped Query Attention
|
| 117 |
+
class GroupedQueryAttention(nn.Module):
|
| 118 |
+
def __init__(
|
| 119 |
+
self,
|
| 120 |
+
hidden_size: int,
|
| 121 |
+
num_heads: int,
|
| 122 |
+
num_key_value_heads: int,
|
| 123 |
+
head_dim: int,
|
| 124 |
+
max_seq_len: int,
|
| 125 |
+
):
|
| 126 |
+
super().__init__()
|
| 127 |
+
self.hidden_size = hidden_size
|
| 128 |
+
self.num_heads = num_heads
|
| 129 |
+
self.num_key_value_heads = num_key_value_heads
|
| 130 |
+
self.head_dim = head_dim
|
| 131 |
+
self.max_seq_len = max_seq_len
|
| 132 |
+
|
| 133 |
+
self.q_proj = nn.Linear(hidden_size, head_dim * num_heads, bias=False)
|
| 134 |
+
self.k_proj = nn.Linear(hidden_size, head_dim * num_key_value_heads, bias=False)
|
| 135 |
+
self.v_proj = nn.Linear(hidden_size, head_dim * num_key_value_heads, bias=False)
|
| 136 |
+
self.out_proj = nn.Linear(num_heads * head_dim, hidden_size, bias=False)
|
| 137 |
+
|
| 138 |
+
self.rope = YaRNRoPE(
|
| 139 |
+
head_dim=head_dim,
|
| 140 |
+
original_max_seq_len=max_seq_len,
|
| 141 |
+
factor=16.0,
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
def forward(self, query, key, value):
|
| 145 |
+
B, L_q, _ = query.size()
|
| 146 |
+
_, L_kv, _ = key.size()
|
| 147 |
+
|
| 148 |
+
q = self.q_proj(query).view(B, L_q, self.num_heads, self.head_dim).transpose(1, 2)
|
| 149 |
+
k = self.k_proj(key).view(B, L_kv, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 150 |
+
v = self.v_proj(value).view(B, L_kv, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 151 |
+
|
| 152 |
+
q_embed = self.rope(q)
|
| 153 |
+
k_embed = self.rope(k)
|
| 154 |
+
q_embed, k_embed = q_embed.to(q.dtype), k_embed.to(k.dtype)
|
| 155 |
+
|
| 156 |
+
attn_output = scaled_dot_product_attention(
|
| 157 |
+
q_embed, k_embed, v,
|
| 158 |
+
attention_mask=torch.ones(L_q, L_kv, dtype=torch.bool, device=q_embed.device),
|
| 159 |
+
dropout=0.0,
|
| 160 |
+
is_causal=False,
|
| 161 |
+
enable_gqa=True,
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
context = attn_output.transpose(1, 2).contiguous().view(B, L_q, self.num_heads * self.head_dim)
|
| 165 |
+
output = self.out_proj(context)
|
| 166 |
+
return output
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
# Gated GELU Feed-Forward Network
|
| 170 |
+
class GEGLU(nn.Module):
|
| 171 |
+
def __init__(self, hidden_size: int, intermediate_size: Optional[int] = None):
|
| 172 |
+
super().__init__()
|
| 173 |
+
if intermediate_size is None:
|
| 174 |
+
intermediate_size = int(8 / 3 * hidden_size)
|
| 175 |
+
self.gate_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
|
| 176 |
+
self.up_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
|
| 177 |
+
self.down_proj = nn.Linear(intermediate_size, hidden_size, bias=False)
|
| 178 |
+
|
| 179 |
+
def forward(self, x):
|
| 180 |
+
gate = F.gelu(self.gate_proj(x))
|
| 181 |
+
value = self.up_proj(x)
|
| 182 |
+
hidden = gate * value
|
| 183 |
+
return self.down_proj(hidden)
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
# Transformer Decoder Layer
|
| 187 |
+
class TransformerDecoderLayer(nn.Module):
|
| 188 |
+
def __init__(
|
| 189 |
+
self,
|
| 190 |
+
hidden_size: int,
|
| 191 |
+
num_heads: int,
|
| 192 |
+
num_key_value_heads: int,
|
| 193 |
+
intermediate_size: int,
|
| 194 |
+
head_dim: int,
|
| 195 |
+
max_seq_len: int,
|
| 196 |
+
dropout: float,
|
| 197 |
+
):
|
| 198 |
+
super().__init__()
|
| 199 |
+
self.self_attn = GroupedQueryAttention(
|
| 200 |
+
hidden_size, num_heads, num_key_value_heads, head_dim, max_seq_len
|
| 201 |
+
)
|
| 202 |
+
self.ffn = GEGLU(hidden_size, intermediate_size)
|
| 203 |
+
self.input_layernorm = nn.RMSNorm(hidden_size)
|
| 204 |
+
self.post_attention_layernorm = nn.RMSNorm(hidden_size)
|
| 205 |
+
self.dropout = nn.Dropout(dropout)
|
| 206 |
+
|
| 207 |
+
def forward(self, hidden_states):
|
| 208 |
+
residual = hidden_states
|
| 209 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 210 |
+
attn_output = self.dropout(self.self_attn(hidden_states, hidden_states, hidden_states))
|
| 211 |
+
hidden_states = residual + attn_output
|
| 212 |
+
|
| 213 |
+
residual = hidden_states
|
| 214 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 215 |
+
ffn_output = self.dropout(self.ffn(hidden_states))
|
| 216 |
+
hidden_states = residual + ffn_output
|
| 217 |
+
|
| 218 |
+
return hidden_states
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
# Decoder with Dense Layer Connections
|
| 222 |
+
class TransformerDecoder(nn.Module):
|
| 223 |
+
def __init__(
|
| 224 |
+
self,
|
| 225 |
+
hidden_size: int,
|
| 226 |
+
num_heads: int,
|
| 227 |
+
num_key_value_heads: int,
|
| 228 |
+
intermediate_size: int,
|
| 229 |
+
head_dim: int,
|
| 230 |
+
num_layers: int,
|
| 231 |
+
max_seq_len: int,
|
| 232 |
+
dropout: float,
|
| 233 |
+
):
|
| 234 |
+
super().__init__()
|
| 235 |
+
self.num_layers = num_layers
|
| 236 |
+
self.layers = nn.ModuleList([
|
| 237 |
+
TransformerDecoderLayer(
|
| 238 |
+
hidden_size, num_heads, num_key_value_heads,
|
| 239 |
+
intermediate_size, head_dim, max_seq_len, dropout
|
| 240 |
+
)
|
| 241 |
+
for _ in range(num_layers)
|
| 242 |
+
])
|
| 243 |
+
|
| 244 |
+
mask = torch.tril(torch.ones(num_layers, num_layers), diagonal=-1)
|
| 245 |
+
self.register_buffer("layer_weight_mask", mask)
|
| 246 |
+
self.layer_raw_weights = nn.Parameter(torch.randn(num_layers, num_layers) / 10)
|
| 247 |
+
|
| 248 |
+
def forward(self, hidden_states):
|
| 249 |
+
history = []
|
| 250 |
+
for idx_layer, layer in enumerate(self.layers):
|
| 251 |
+
layer_output = layer(hidden_states)
|
| 252 |
+
|
| 253 |
+
if history:
|
| 254 |
+
raw_weights = self.layer_raw_weights[idx_layer, :idx_layer]
|
| 255 |
+
masked_weights = raw_weights * self.layer_weight_mask[idx_layer, :idx_layer]
|
| 256 |
+
weights = F.softmax(masked_weights, dim=0)
|
| 257 |
+
hist_stack = torch.stack(history, dim=0)
|
| 258 |
+
residual = torch.einsum("lbtd,l->btd", hist_stack, weights)
|
| 259 |
+
hidden_states = layer_output + residual
|
| 260 |
+
else:
|
| 261 |
+
hidden_states = layer_output
|
| 262 |
+
|
| 263 |
+
history.append(hidden_states)
|
| 264 |
+
|
| 265 |
+
return hidden_states
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
# Classifier
|
| 269 |
+
class Classifier(nn.Module):
|
| 270 |
+
def __init__(
|
| 271 |
+
self,
|
| 272 |
+
hidden_size: int,
|
| 273 |
+
num_heads: int,
|
| 274 |
+
num_key_value_heads: int,
|
| 275 |
+
intermediate_size: int,
|
| 276 |
+
head_dim: int,
|
| 277 |
+
vocab_size: int,
|
| 278 |
+
num_layers: int,
|
| 279 |
+
max_seq_len: int,
|
| 280 |
+
dropout: float,
|
| 281 |
+
):
|
| 282 |
+
super().__init__()
|
| 283 |
+
self.token_embedding = nn.Embedding(vocab_size, hidden_size)
|
| 284 |
+
self.decoder = TransformerDecoder(
|
| 285 |
+
hidden_size, num_heads, num_key_value_heads,
|
| 286 |
+
intermediate_size, head_dim, num_layers, max_seq_len, dropout
|
| 287 |
+
)
|
| 288 |
+
self.final_layernorm = nn.RMSNorm(hidden_size)
|
| 289 |
+
self.lm_head = nn.Linear(hidden_size, 6, bias=False)
|
| 290 |
+
|
| 291 |
+
def forward(self, input_ids):
|
| 292 |
+
hidden_states = self.token_embedding(input_ids)
|
| 293 |
+
hidden_states = self.decoder(hidden_states)
|
| 294 |
+
hidden_states = self.final_layernorm(hidden_states)
|
| 295 |
+
logits = self.lm_head(hidden_states).mean(-2)
|
| 296 |
+
return logits
|
new_model.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9b737b4e7f0ac6d998b83e1d8892e62c1b9aa0124d2defbfd411a35fc9d4e4c3
|
| 3 |
+
size 19291522
|
sample/test.jsonl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7b6448daf8d958391af38e0990d7e666d041a20641c521fbaffae5bc508ee2e9
|
| 3 |
+
size 140796983
|
save/file_0.jsonl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7e913e0af7f61bcd45bc5974373ffea1cca290a424b2ccb5b4821026779a34b4
|
| 3 |
+
size 44432404
|
tokenizer.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List, Union, Optional, Dict, Any
|
| 2 |
+
from transformers import AutoTokenizer
|
| 3 |
+
|
| 4 |
+
import os
|
| 5 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
| 6 |
+
|
| 7 |
+
class Tokenizer:
|
| 8 |
+
"""
|
| 9 |
+
轻量级封装,统一接口:
|
| 10 |
+
encode -> input_ids, attention_mask
|
| 11 |
+
decode -> 字符串
|
| 12 |
+
其余常用属性直接暴露。
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
def __init__(self, model_name: str, trust_remote_code: bool = True):
|
| 16 |
+
self.tokenizer = AutoTokenizer.from_pretrained(
|
| 17 |
+
model_name,
|
| 18 |
+
trust_remote_code=trust_remote_code
|
| 19 |
+
)
|
| 20 |
+
# self.tokenizer.chat_template = """{% for message in messages %}{% if message['role'] == 'system' %}{% if message['content'] == '' %}<system> {{ '你是一个人工智能助手' }} </system>{% else %}<system> {{ message['content'] }} </system>{% endif %}{% elif message['role'] == 'user' %}<user> {{ message['content'] }} </user>{% elif message['role'] == 'assistant' %}<assistant>{{ message['content'] }}</assistant>{% endif %}{% endfor %}"""
|
| 21 |
+
self.tokenizer.chat_template = """{% for message in messages %}{% if message['role'] == 'system' %}<system> {{ message['content'] }} </system>{% elif message['role'] == 'user' %}<user> {{ message['content'] }} </user>{% elif message['role'] == 'assistant' %}<assistant>{{ message['content'] }}</assistant>{% endif %}{% endfor %}"""
|
| 22 |
+
# 如果 pad_token 不存在,统一用 eos_token 代替
|
| 23 |
+
if self.tokenizer.pad_token is None:
|
| 24 |
+
self.tokenizer.pad_token = self.tokenizer.eos_token
|
| 25 |
+
|
| 26 |
+
def encode(
|
| 27 |
+
self,
|
| 28 |
+
text: Union[str, List[str]],
|
| 29 |
+
max_length: Optional[int] = None,
|
| 30 |
+
padding: Optional[str] = "do_not_pad",
|
| 31 |
+
truncation: bool = False,
|
| 32 |
+
return_tensors: Optional[str] = None,
|
| 33 |
+
add_special_tokens: bool = False,
|
| 34 |
+
) -> Dict[str, Any]:
|
| 35 |
+
encoded = self.tokenizer(
|
| 36 |
+
text,
|
| 37 |
+
max_length=max_length,
|
| 38 |
+
padding=padding,
|
| 39 |
+
truncation=truncation,
|
| 40 |
+
return_tensors=return_tensors,
|
| 41 |
+
add_special_tokens=add_special_tokens
|
| 42 |
+
)
|
| 43 |
+
return encoded
|
| 44 |
+
|
| 45 |
+
def encode_chat(
|
| 46 |
+
self,
|
| 47 |
+
text: List[Dict[str, Any]],
|
| 48 |
+
) -> Dict[str, Any]:
|
| 49 |
+
encoded = self.tokenizer.apply_chat_template(
|
| 50 |
+
text,
|
| 51 |
+
tokenize=False
|
| 52 |
+
)
|
| 53 |
+
return encoded
|
| 54 |
+
|
| 55 |
+
def decode(
|
| 56 |
+
self,
|
| 57 |
+
token_ids: Union[List[int], List[List[int]]],
|
| 58 |
+
skip_special_tokens: bool = False,
|
| 59 |
+
clean_up_tokenization_spaces: bool = False
|
| 60 |
+
) -> Union[str, List[str]]:
|
| 61 |
+
if isinstance(token_ids[0], int): # 单条
|
| 62 |
+
return self.tokenizer.decode(
|
| 63 |
+
token_ids,
|
| 64 |
+
skip_special_tokens=skip_special_tokens,
|
| 65 |
+
clean_up_tokenization_spaces=clean_up_tokenization_spaces
|
| 66 |
+
)
|
| 67 |
+
# batch
|
| 68 |
+
return self.tokenizer.batch_decode(
|
| 69 |
+
token_ids,
|
| 70 |
+
skip_special_tokens=skip_special_tokens,
|
| 71 |
+
clean_up_tokenization_spaces=clean_up_tokenization_spaces
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
@property
|
| 75 |
+
def vocab_size(self) -> int:
|
| 76 |
+
return len(self.tokenizer)
|
| 77 |
+
|
| 78 |
+
@property
|
| 79 |
+
def pad_token_id(self) -> int:
|
| 80 |
+
return self.tokenizer.pad_token_id
|
| 81 |
+
|
| 82 |
+
@property
|
| 83 |
+
def eos_token_id(self) -> int:
|
| 84 |
+
return self.tokenizer.eos_token_id
|
| 85 |
+
|
| 86 |
+
@property
|
| 87 |
+
def bos_token_id(self) -> int:
|
| 88 |
+
return self.tokenizer.bos_token_id
|
| 89 |
+
|
| 90 |
+
@property
|
| 91 |
+
def unk_token_id(self) -> int:
|
| 92 |
+
return self.tokenizer.unk_token_id
|
| 93 |
+
|
| 94 |
+
# 兼容旧接口
|
| 95 |
+
def get_vocab_size(self) -> int:
|
| 96 |
+
return self.vocab_size
|
| 97 |
+
|
| 98 |
+
def get_eot_token(self) -> int:
|
| 99 |
+
"""End-Of-Text token,与 GPT 系列保持一致命名。"""
|
| 100 |
+
return self.eos_token_id
|
| 101 |
+
|
| 102 |
+
if __name__ == '__main__':
|
| 103 |
+
tokenizer = Tokenizer("./llama2_tokenizer_32k")
|
| 104 |
+
print(tokenizer.get_eot_token())
|
| 105 |
+
encode = tokenizer.encode_chat([{"role": "system", "content": ""}, {"role": "user", "content": "请告诉我在中国古代的“四大发明”是什么?"}, {"role": "assistant", "content": "中国古代的“四大发明”是指造纸术、印刷术、火药和指南针。这四项发明对世界文明的发展产生了深远的影响:\n\n1. **造纸术**:据史书记载,东汉时期的蔡伦改进了造纸工艺,使得纸张的生产更加便捷、成本更低,质量也更加优良。这一发明极大地促进了文化的传播和保存。\n\n2. **印刷术**:中国古代的印刷术最早可以追溯到唐代的雕版印刷,到了宋代发展出了活字印刷技术。印刷术的发明极大地促进了知识的传播,降低了书籍的成本,对教育和文化的发展起到了重要的推动作用。\n\n3. **火药**:火药最初是在唐代被发现的,最初可能用于医疗或炼金术。到了宋代,人们开始将火药用于军事目的,发明了各种火器。火药的发明改变了战争的面貌,对世界军事技术的发展产生了重大影响。\n\n4. **指���针**:指南针最初在中国被用于风水测量,后来逐渐发展成为航海导航的重要工具。这一发明极大地促进了海上航行技术的发展,对于新航路的开辟和世界地理大发现起到了关键作用。\n\n这四项发明不仅在中国历史上占有重要地位,而且对全世界的科技进步和文明发展都产生了深远的影响。"}])
|
| 106 |
+
print(type(encode))
|
| 107 |
+
print("orin length", len(encode))
|
| 108 |
+
encode = tokenizer.encode(str(encode), max_length=None, truncation=True, padding="do_not_pad")
|
| 109 |
+
for token in encode['input_ids']:
|
| 110 |
+
print(tokenizer.decode([token]))
|
| 111 |
+
decode = tokenizer.decode([encode['input_ids']])
|
| 112 |
+
print("token lens: ", len(encode['input_ids']))
|
| 113 |
+
print("encode: ", encode)
|
| 114 |
+
print("att_mask: ", encode['attention_mask'])
|
| 115 |
+
print("decode: ", decode)
|
| 116 |
+
print("vocab_size", tokenizer.get_vocab_size())
|
| 117 |
+
print("eot", tokenizer.get_eot_token(), tokenizer.decode([tokenizer.get_eot_token()]))
|
| 118 |
+
print("eos", tokenizer.eos_token_id, tokenizer.decode([tokenizer.eos_token_id]))
|
| 119 |
+
print("unk", tokenizer.unk_token_id, tokenizer.decode([tokenizer.unk_token_id]))
|
| 120 |
+
print("pad", tokenizer.pad_token_id, tokenizer.decode([tokenizer.pad_token_id]))
|
| 121 |
+
print("bos", tokenizer.bos_token_id, tokenizer.decode([tokenizer.bos_token_id]))
|
| 122 |
+
for i in range(10):
|
| 123 |
+
print(i, tokenizer.decode([i]))
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
|