赞
踩
下面对glm-4-9b-chat模型进行测试,使用transformers 进行推理,测试输入和输出的的流程,以及对一些参数的解释。
import torch from transformers import AutoModelForCausalLM, AutoTokenizer device = "cuda" tokenizer = AutoTokenizer.from_pretrained("/data/model/ZhipuAI/glm-4-9b-chat",trust_remote_code=True) query = "你能做什么" # 转换成词汇表编码 inputs = tokenizer.apply_chat_template([ {"role": "system", "content": "你是一个乐于助人的助手"},\ {"role": "user", "content": "你是谁"}, {"role" : "assistant", "content": "我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持" }, {"role": "user", "content": query} ], add_generation_prompt=True, tokenize=True, return_tensors="pt", return_dict=True ) inputs = inputs.to(device) model = AutoModelForCausalLM.from_pretrained( "/data/model/ZhipuAI/glm-4-9b-chat", torch_dtype=torch.bfloat16, low_cpu_mem_usage=True, trust_remote_code=True ).to(device).eval() gen_kwargs = {"max_length": 25000, "do_sample": True, "top_k": 1} with torch.no_grad(): outputs = model.generate(**inputs, **gen_kwargs) new = outputs outputs = outputs[:, inputs['input_ids'].shape[1]:] print(tokenizer.decode(outputs[0], skip_special_tokens=True))
输入的数据首先需要转换成词汇表中的编码信息。
tokenizer.apply_chat_template方法:将输入内容转换成词汇表编码
[ { "role": "system", "content": "你是一个乐于助人的助手" }, { "role": "user", "content": "你是谁" }, { "role": "assistant", "content": "我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持" }, { "role": "user", "content": "你能做什么" } ]
经过分词器后会对模型进行编码,转换成词汇表编码形式,同时添加了一些特殊的标记,下面是解码后的输入信息
'[gMASK] <sop> <|system|> \n你是一个乐于助人的助手
<|user|> \n你是谁
<|assistant|> \n我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持
<|user|> \n你能做什么
<|assistant|>'
下面就是转换后对应的词汇表编码信息
tensor([151331, 151333, 151335, 198, 98406, 99950, 113336, 98869, 98942,
113255, 151336, 198, 103408, 99668, 151337, 198, 122786, 104668,
113255, 3837, 103092, 12847, 3825, 44, 3837, 117220, 108332,
730, 9372, 41244, 252, 98752, 99071, 98327, 99126, 100789,
15223, 100734, 98354, 220, 115937, 19, 101622, 99947, 100597,
109331, 100484, 110230, 1773, 99198, 126744, 100293, 99833, 100000,
121189, 99089, 108419, 113574, 111426, 151336, 198, 106779, 105520,
151337], device='cuda:0')
可以将某个字符转换成原文,如下
#将token ID转换为token字符串
tokenizer.convert_ids_to_tokens(99668).decode('utf-8')
# 输出: '谁'
下面是分词器的结构,其中显示词汇表有151329个词汇token,这些词汇包含了特殊标记和预留的词汇token
ChatGLM4Tokenizer(name_or_path='/data/model/ZhipuAI/glm-4-9b-chat', vocab_size=151329, model_max_length=128000, is_fast=False, padding_side='left', truncation_side='right', special_tokens={'eos_token': '<|endoftext|>', 'pad_token': '<|endoftext|>', 'additional_special_tokens': ['<|endoftext|>', '[MASK]', '[gMASK]', '[sMASK]', '<sop>', '<eop>', '<|system|>', '<|user|>', '<|assistant|>', '<|observation|>', '<|begin_of_image|>', '<|end_of_image|>', '<|begin_of_video|>', '<|end_of_video|>']}, clean_up_tokenization_spaces=False), added_tokens_decoder={ 151329: AddedToken("<|endoftext|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151330: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151331: AddedToken("[gMASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151332: AddedToken("[sMASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151333: AddedToken("<sop>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151334: AddedToken("<eop>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151335: AddedToken("<|system|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151336: AddedToken("<|user|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151337: AddedToken("<|assistant|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151338: AddedToken("<|observation|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151339: AddedToken("<|begin_of_image|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151340: AddedToken("<|end_of_image|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151341: AddedToken("<|begin_of_video|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), 151342: AddedToken("<|end_of_video|>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), }
输入首先经过的是embedding层,它会将词汇表编码转换成向量形式。其中的每个token都转换成4096维的向量。
Embedding(151552, 4096)可以这样理解:Embedding中151552表示能处理的最大令牌,它将 151552 个可能的单词或令牌映射到 4096 维的向量
Embedding在处理的最大token数量和tokenizer在最大的词汇表是不一定相同的,tokenizer中的词汇表可能有冗余未使用的部分
下面是模型的结构,
ChatGLMForConditionalGeneration( (transformer): ChatGLMModel( (embedding): Embedding( (word_embeddings): Embedding(151552, 4096) ) (rotary_pos_emb): RotaryEmbedding() (encoder): GLMTransformer( (layers): ModuleList( (0-39): 40 x GLMBlock( (input_layernorm): RMSNorm() (self_attention): SelfAttention( (query_key_value): Linear(in_features=4096, out_features=4608, bias=True) (core_attention): SdpaAttention( (attention_dropout): Dropout(p=0.0, inplace=False) ) (dense): Linear(in_features=4096, out_features=4096, bias=False) ) (post_attention_layernorm): RMSNorm() (mlp): MLP( (dense_h_to_4h): Linear(in_features=4096, out_features=27392, bias=False) (dense_4h_to_h): Linear(in_features=13696, out_features=4096, bias=False) ) ) ) (final_layernorm): RMSNorm() ) (output_layer): Linear(in_features=4096, out_features=151552, bias=False) ) )
模型的原始输出解码后如下,其中包含了输入部分和当前模型的输出部分
[gMASK] <sop> <|system|> \n你是一个乐于助人的助手
<|user|> \n你是谁
<|assistant|> \n我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持
<|user|> \n你能做什么
<|assistant|> \n作为一个人工智能助手,我可以做以下几件事情:\n\n1. **信息查询**:提供各种领域的知识,包括科学、历史、文化、技术等。\n\n2. **解答问题**:帮助解答各种问题,从简单的计算到复杂的学术问题。\n\n3. **语言翻译**:提供多种语言之间的翻译服务。\n\n4. **写作辅助**:帮助撰写文章、报告、邮件等,包括语法检查、文本润色等。\n\n5. **编程帮助**:提供编程相关的建议、代码示例和调试帮助。\n\n6. **学习辅导**:辅助学习,提供学习资源、解释概念和解答学习中的难题。\n\n7. **生活建议**:提供健康、饮食、运动等方面的建议。\n\n8. **娱乐互动**:进行简单的对话、讲笑话、提供谜语等娱乐内容。\n\n9. **技术支持**:解答关于软件、硬件和互联网使用的问题。\n\n10. **日程管理**:帮助规划日程、设置提醒和闹钟。\n\n请注意,我的能力受限于我的训练数据和算法,我无法进行物理交互或处理需要人类直觉和判断的任务。 <|user|>'
输出会进行截断处理,最终展示的内容就是本轮推理的真实结果(其中的25000参数表示模型的最大输出长度)
gen_kwargs = {"max_length": 25000, "do_sample": True, "top_k": 1}
with torch.no_grad():
outputs = model.generate(**inputs, **gen_kwargs)
new = outputs
# 获得本轮有效的输出内容
outputs = outputs[:, inputs['input_ids'].shape[1]:]
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
有效的输出内容如下:
作为一个人工智能助手,我可以做以下几件事情:
1. **信息查询**:提供各种领域的知识,包括科学、历史、文化、技术等。
2. **解答问题**:帮助解答各种问题,从简单的计算到复杂的学术问题。
3. **语言翻译**:提供多种语言之间的翻译服务。
4. **写作辅助**:帮助撰写文章、报告、邮件等,包括语法检查、文本润色等。
5. **编程帮助**:提供编程相关的建议、代码示例和调试帮助。
6. **学习辅导**:辅助学习,提供学习资源、解释概念和解答学习中的难题。
7. **生活建议**:提供健康、饮食、运动等方面的建议。
8. **娱乐互动**:进行简单的对话、讲笑话、提供谜语等娱乐内容。
9. **技术支持**:解答关于软件、硬件和互联网使用的问题。
10. **日程管理**:帮助规划日程、设置提醒和闹钟。
请注意,我的能力受限于我的训练数据和算法,我无法进行物理交互或处理需要人类直觉和判断的任务。
下面是各个数据的长度,原始输出是295,本轮有效的输出231个token,输入64个token
glm4-9b模型的最大上下文长度是128k,在推理时也可以手动限制,transformers库有max_length和max_new_tokens两个参数控制
max_length表示模型的最大输出长度,假如我们设置为64,也就是和输入token一样长,会发生什么?
会报错,显示max_length应该大于输入token长度
Input length of input_ids is 64, but `max_length` is set to 64. This can lead to unexpected behavior. You should consider increasing `max_length` or, better yet, setting `max_new_tokens`.
input_ids的输入长度为64,但' max_length '被设置为64。这可能导致意想不到的行为。你应该考虑增加' max_length ',或者更好的是,设置' max_new_tokens '。
如果吧max_length设置为100,由于模型输出中带上了输入,所以真实的输出应该会被截断
'[gMASK] <sop> <|system|> \n你是一个乐于助人的助手
<|user|> \n你是谁
<|assistant|> \n我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持
<|user|> \n你能做什么
<|assistant|> \n作为一个人工智能助手,我可以做以下几件事情:\n\n1. **信息查询**:我可以帮助你查找各种信息,包括新闻、历史数据、科学知识、技术'
之前的报错提示我们设置max_new_tokens ,如果我们这样采用下面的参数
gen_kwargs = {"max_length": 100,"max_new_tokens" :1000 , "do_sample": True, "top_k": 1}
模型可以输出完整的内容
'[gMASK] <sop> <|system|> \n你是一个乐于助人的助手 <|user|> \n你是谁 <|assistant|> \n我是一个人工智能助手,名为 ChatGLM,是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持 <|user|> \n你能做什么 <|assistant|> \n作为一个人工智能助手,我可以做以下几件事情:\n\n1. **信息查询**:我可以帮助你查找各种信息,包括新闻、历史数据、科学知识、技术信息等。\n\n2. **语言翻译**:我可以提供多种语言之间的翻译服务。\n\n3. **写作辅助**:我可以帮助你撰写文章、报告、邮件等,包括语法纠正、内容润色等。\n\n4. **学习辅导**:我可以提供学习资源、解释复杂概念、帮助解答学习中的问题。\n\n5. **生活建议**:我可以提供一些建议,比如健康饮食、锻炼计划、时间管理等。\n\n6. **技术支持**:我可以帮助解决一些基本的技术问题,比如软件使用、设备故障等。\n\n7. **娱乐互动**:我可以参与简单的对话,提供笑话、谜语、游戏等娱乐内容。\n\n8. **数据分析**:我可以处理和分析数据,提供统计信息或趋势预测。\n\n9. **编程帮助**:我可以提供编程语言的解释、代码示例和调试建议。\n\n10. **心理咨询**:虽然我不是专业的心理咨询师,但我可以提供一些基本的情绪支持和心理健康的建议。\n\n请注意,我的能力有限,特别是在需要深度专业知识或个人化服务的情况下,我可能无法提供与人类专家同等水平的帮助。 <|user|>'
但是会有警告,提示我们两个参数都设置了,优先考虑max_new_tokens
Both `max_new_tokens` (=1000) and `max_length`(=100) seem to have been set. `max_new_tokens` will take precedence. Please refer to the documentation for more information.
huggingface上的解释:
可以这样理解两个控制模型输出的参数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。