Pipelines 进阶
pipeline加载本地模型推理¶
In [2]:
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "/models/Llama3-8B-Chinese-Chat" # 替换为你的模型路径,并不是所有模型都可以用glm4就不行
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True)
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████| 4/4 [00:08<00:00, 2.14s/it]
In [17]:
from transformers import pipeline
prompt = "今天去了冰雪大世界"
generator = pipeline(task="text-generation", model=model, tokenizer=tokenizer, device=0)
generator(prompt)
Out[17]:
[{'generated_text': '今天去了冰雪大世界,感觉非常不错,孩子们都很开心。"'}]
设置文本生成返回条数¶
In [18]:
prompt = "今天去了冰雪大世界"
generator = pipeline(task="text-generation", model=model, tokenizer=tokenizer, num_return_sequences=2, return_full_text=False, device=0)
#生成多序列需要加do_sample默认只能生成一条
generator(prompt,do_sample=True)
Out[18]:
[{'generated_text': ',体验了很多刺激的冰雪活动。" 这'},
{'generated_text': ',享受了各种刺激和美好的景色。这里'}]
设置文本生成最大长度¶
In [23]:
prompt = "今天去了冰雪大世界"
generator = pipeline(task="text-generation", model=model, tokenizer=tokenizer, return_full_text=False, device=0)
generator(prompt, max_length=20)
Out[23]:
[{'generated_text': ',感觉非常不错,孩子们都很开心。"'}]
In [25]:
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "/models/bert-base-chinese" # 替换为你的模型路径,并不是所有模型都可以用glm4就不行
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True)
If you want to use `BertLMHeadModel` as a standalone, add `is_decoder=True.`
In [26]:
fill_mask = pipeline(task="fill-mask", model=model, tokenizer=tokenizer, device=0)
In [27]:
text = "中国[MASK]足球"
fill_mask(text, top_k=1)
Out[27]:
[{'score': 0.17308571934700012,
'token': 7339,
'token_str': '队',
'sequence': '中 国 队 足 球'}]
设置文本补全的条数¶
In [33]:
text = "我在天安门[MASK]升旗"
fill_mask(text, top_k=1)
Out[33]:
[{'score': 0.534364640712738,
'token': 677,
'token_str': '上',
'sequence': '我 在 天 安 门 上 升 旗'}]
In [35]:
text = "巴黎是[MASK]国的首都。"
fill_mask(text, top_k=2)
Out[35]:
[{'score': 0.9911912083625793,
'token': 3791,
'token_str': '法',
'sequence': '巴 黎 是 法 国 的 首 都 。'},
{'score': 0.002847259631380439,
'token': 2548,
'token_str': '德',
'sequence': '巴 黎 是 德 国 的 首 都 。'}]
In [37]:
text = "哈尔滨好玩的地方有[MASK][MASK][MASK]"
fill_mask(text, top_k=1)
You seem to be using the pipelines sequentially on GPU. In order to maximize efficiency please use a dataset
Out[37]:
[[{'score': 0.9840582013130188,
'token': 1525,
'token_str': '哪',
'sequence': '[CLS] 哈 尔 滨 好 玩 的 地 方 有 哪 [MASK] [MASK] [SEP]'}],
[{'score': 0.9702103137969971,
'token': 763,
'token_str': '些',
'sequence': '[CLS] 哈 尔 滨 好 玩 的 地 方 有 [MASK] 些 [MASK] [SEP]'}],
[{'score': 0.990031361579895,
'token': 8043,
'token_str': '?',
'sequence': '[CLS] 哈 尔 滨 好 玩 的 地 方 有 [MASK] [MASK] ? [SEP]'}]]
使用 Tokenizer 和 Model¶
In [15]:
from transformers import AutoTokenizer, AutoModel
model_name = "/models/bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
使用 BERT Tokenizer 编码文本¶
编码 (Encoding) 过程包含两个步骤:
- 分词:使用分词器按某种策略将文本切分为 tokens;
- 映射:将 tokens 转化为对应的 token IDs。
In [38]:
# 第一步:分词
sequence = "哈尔滨冬天很冷"
tokens = tokenizer.tokenize(sequence)
print(tokens)
['哈', '尔', '滨', '冬', '天', '很', '冷']
In [39]:
# 第二步:映射
token_ids = tokenizer.convert_tokens_to_ids(tokens)
In [40]:
print(token_ids)
[1506, 2209, 4012, 1100, 1921, 2523, 1107]
使用 Tokenizer.encode 方法端到端处理¶
In [41]:
token_ids_e2e = tokenizer.encode(sequence)
In [43]:
#结果中会增加101和102
token_ids_e2e
Out[43]:
[101, 1506, 2209, 4012, 1100, 1921, 2523, 1107, 102]
In [44]:
tokenizer.decode(token_ids)
Out[44]:
'哈 尔 滨 冬 天 很 冷'
In [45]:
tokenizer.decode(token_ids_e2e)
Out[45]:
'[CLS] 哈 尔 滨 冬 天 很 冷 [SEP]'
编解码多段文本¶
In [46]:
sequence_batch = ["冰雪大世界很好玩", "中国的首都是北京"]
In [47]:
token_ids_batch = tokenizer.encode(sequence_batch)
In [48]:
tokenizer.decode(token_ids_batch)
Out[48]:
'[CLS] 冰 雪 大 世 界 很 好 玩 [SEP] 中 国 的 首 都 是 北 京 [SEP]'

TOKEN操作¶
返回参数:
- input_ids: token_ids
- token_type_ids: token_id 归属的句子编号
- attention_mask: 指示哪些token需要被关注(注意力机制)
In [51]:
embedding_batch = tokenizer("天天想你", "中国的首都是北京")
print(embedding_batch)
{'input_ids': [101, 1921, 1921, 2682, 872, 102, 704, 1744, 4638, 7674, 6963, 3221, 1266, 776, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
In [52]:
# 优化下输出结构
for key, value in embedding_batch.items():
print(f"{key}: {value}\n")
input_ids: [101, 1921, 1921, 2682, 872, 102, 704, 1744, 4638, 7674, 6963, 3221, 1266, 776, 102] token_type_ids: [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1] attention_mask: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
添加新 Token¶
当出现了词表或嵌入空间中不存在的新Token,需要使用 Tokenizer 将其添加到词表中。 Transformers 库提供了两种不同方法:
- add_tokens: 添加常规的正文文本 Token,以追加(append)的方式添加到词表末尾。
- add_special_tokens: 添加特殊用途的 Token,优先在已有特殊词表中选择(
bos_token, eos_token, unk_token, sep_token, pad_token, cls_token, mask_token)。如果预定义均不满足,则都添加到additional_special_tokens。
添加常规 Token¶
先查看已有词表,确保新添加的 Token 不在词表中:
In [53]:
len(tokenizer.vocab.keys())
Out[53]:
21128
In [54]:
from itertools import islice
# 使用 islice 查看词表部分内容
for key, value in islice(tokenizer.vocab.items(), 10):
print(f"{key}: {value}")
吋: 1397 ##茨: 18811 ##绸: 18396 奕: 1945 殊: 3654 ##卫: 14367 ##nce: 9056 ##糠: 18194 処: 1129 蕉: 5933
In [55]:
new_tokens = ["气象", "哈尔滨"]
In [56]:
# 将集合作差结果添加到词表中
new_tokens = set(new_tokens) - set(tokenizer.vocab.keys())
In [57]:
new_tokens
Out[57]:
{'哈尔滨', '气象'}
In [58]:
tokenizer.add_tokens(list(new_tokens))
Out[58]:
2
In [59]:
# 新增加了2个Token,词表总数由 21128 增加到 21130
len(tokenizer.vocab.keys())
Out[59]:
21130
添加特殊Token(审慎操作)¶
In [60]:
new_special_token = {"sep_token": "NEW_SPECIAL_TOKEN"}
In [61]:
tokenizer.add_special_tokens(new_special_token)
Out[61]:
1
In [62]:
# 新增加了1个特殊Token,词表总数由 21128 增加到 21131
len(tokenizer.vocab.keys())
Out[62]:
21131
使用 save_pretrained 方法保存指定 Model 和 Tokenizer¶
借助 AutoClass 的设计理念,保存 Model 和 Tokenizer 的方法也相当高效便捷。
假设我们对bert-base-chinese模型以及对应的 tokenizer 做了修改,并更名为new-bert-base-chinese,方法如下:
tokenizer.save_pretrained("./models/new-bert-base-chinese")
model.save_pretrained("./models/new-bert-base-chinese")
保存 Tokenizer 会在指定路径下创建以下文件:
- tokenizer.json: Tokenizer 元数据文件;
- special_tokens_map.json: 特殊字符映射关系配置文件;
- tokenizer_config.json: Tokenizer 基础配置文件,存储构建 Tokenizer 需要的参数;
- vocab.txt: 词表文件;
- added_tokens.json: 单独存放新增 Tokens 的配置文件。
保存 Model 会在指定路径下创建以下文件:
- config.json:模型配置文件,存储模型结构参数,例如 Transformer 层数、特征空间维度等;
- pytorch_model.bin:又称为 state dictionary,存储模型的权重。
In [63]:
tokenizer.save_pretrained("./models/new-bert-base-chinese")
Out[63]:
('./models/new-bert-base-chinese/tokenizer_config.json',
'./models/new-bert-base-chinese/special_tokens_map.json',
'./models/new-bert-base-chinese/vocab.txt',
'./models/new-bert-base-chinese/added_tokens.json',
'./models/new-bert-base-chinese/tokenizer.json')
In [64]:
model.save_pretrained("./models/new-bert-base-chinese")

浙公网安备 33010602011771号