LLM的tokenizer方式解读

背景
在LLM处理中有很多关于tokenizer的方式,方便记忆理解,在此特意整理一下。
本次以为qwen/Qwen2-7B-Instruct模型的tokenizer为例。

bert-base-chinese模型略有不同,可以参考这里

transformers 版本 2.1.1

加载tokenizer

from transformers import AutoTokenizer

model_path = "qwen/Qwen2-7B-Instruct"
# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False, trust_remote_code=True)
tokenizer

# Qwen2Tokenizer(name_or_path='qwen/Qwen2-7B-Instruct', vocab_size=151643, model_max_length=131072, is_fast=False, padding_side='right', truncation_side='right', 
# special_tokens={'eos_token': '<|im_end|>', 'pad_token': '<|endoftext|>', 'additional_special_tokens': ['<|im_start|>', '<|im_end|>']}, 
# clean_up_tokenization_spaces=False),  added_tokens_decoder={
# 	151643: AddedToken("<|endoftext|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
# 	151644: AddedToken("<|im_start|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
# 	151645: AddedToken("<|im_end|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
# }

可以看到qwen/Qwen2-7B-Instruct分词器的一些基础信息,比如词表大小vocab_size=151643,还有3个特殊符号151643、151644和151645等信息。

最基础encode和decode,将文本转化为词表的id或者id序列转化为可阅读的文本字符串。

text = "This is a test"
text_encode = tokenizer.encode(text)
print(text_encode)
# [1986, 374, 264, 1273]

text_decode = tokenizer.decode(text_encode)
print(text_decode)
# This is a test

构造LLM模型可以识别的输入格式,直接调用tokenizer对象。

texts = ["This is a test", "Another test", "天气不错"]
tokenizer(texts)
# {'input_ids': [[1986, 374, 264, 1273], [14037, 1273], [104307, 100832]], 'attention_mask': [[1, 1, 1, 1], [1, 1], [1, 1]]}

# 一般来说会加上一些参数
# truncation=True时,超过max_length的文本会被截断
# padding=True时,文本会被填充到max_length,不足会填充0
# attention_mask 会根据input_ids生成 1表示真实有效,0表示填充字符
tokenizer(texts, truncation=True, padding=True, max_length=4)
# {'input_ids': [[1986, 374, 264, 1273], [14037, 1273, 151643, 151643], [104307, 100832, 151643, 151643]], 'attention_mask': [[1, 1, 1, 1], [1, 1, 0, 0], [1, 1, 0, 0]]}

apply_chat_template函数可以构造带有提示词模式的模型输入。
一般来说,LLM中可以设置两种 Prompt:一种是 System Prompt,该种 Prompt 内容会在整个会话过程中持久地影响模型的回复,且相比于普通 Prompt 具有更高的重要性;另一种是 User Prompt,这更偏向于我们平时提到的 Prompt,即需要模型做出回复的输入。

prompt = "帮我实现一个快排算法"
messages = [{"role": "system", "content": "现在你是一个pyhon代码高手"}, {"role": "user", "content": prompt}]
# 构造LLM prrompt,tokenize=False不立即执行 tokenizer
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, return_tensors="pt")
print(text)
# <|im_start|>system
# 现在你是一个pyhon代码高手<|im_end|>
# <|im_start|>user
# 帮我实现一个快排算法<|im_end|>
# <|im_start|>assistant

# 转为为LLM可识别的数据格式
model_inputs = tokenizer(text, truncation=True, padding=True, max_length=512, return_tensors="pt")

结果如下:

{'input_ids': tensor([[151644,   8948,    198,  99601,  56568, 101909,   3288,  81549,  46100,
         105862, 151645,    198, 151644,    872,    198, 108965, 101884,  46944,
          99234,  59956, 107018, 151645,    198, 151644,  77091,    198]]), 
 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1]])
 }

将model_inputs 结果重新转化为文本如下:

tokenizer.decode(model_inputs["input_ids"][0])
# '<|im_start|>system\n现在你是一个pyhon代码高手<|im_end|>\n<|im_start|>user\n帮我实现一个快排算法<|im_end|>\n<|im_start|>assistant\n'
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值