内容目录

前言

在上一章【课程总结】day21(下):大模型的三大架构及T5体验中,我们体验了Encoder-Decoder架构的T5模型。本章内容,我们将以Decoder-Only架构的Qwen模型入手,了解Qwen模型结构、聊天模板的概念以及通过大模型进行翻译、信息抽取等任务的尝试。

模型选择

访问ModelScope官网,在模型库搜索Qwen2

补充说明:

Qwen模型简介

Qwen2是Qwen大型语言模型的新系列,基于LLaMA架构,由Qwen团队进行训练。

  • 参数规模:Qwen2系列模型的参数范围从0.5亿到72亿,Qwen2-7B对应是70亿参数规模。
  • 上下文长度:Qwen2-7B-Instruct支持最长达131,072个标记的上下文长度,能够处理大量输入。
  • 应用场景:Qwen2模型可应用于多种自然语言处理任务,包括语言理解、语言生成、多语言能力、编码、数学推理等。
  • 开源情况:Qwen2模型是开源的,Github地址:https://github.com/QwenLM/Qwen2
  • 技术博客https://qwenlm.github.io/blog/qwen2/
  • 技术文档https://qwen.readthedocs.io/en/latest/

模型下载

第一步:启动ModelScope平台的PAI-DSW的GPU环境

第二步:在终端中,输入以下命令进行模型下载:

git clone https://www.modelscope.cn/qwen/qwen2-7b-instruct.git

Qwen2模型目录简介

qwen2-7b-instruct/
│
├── .gitattributes                     # Git属性文件,用于配置Git的行为。
│
├── config.json                        # 模型配置文件,包含模型的基本参数和设置。
│
├── configuration.json                 # 系统初始化配置文件,定义系统启动时的配置。
│
├── generation_config.json             # 生成配置文件,包含文本生成时的参数设置。
│
├── LICENSE                            # 许可证文件,说明模型的使用条款和条件。
│
├── merges.txt                         # 词汇合并文件,通常用于处理子词分割。
│
├── model-00001-of-00004.safetensors   # 模型权重文件(第1部分),使用Safetensors格式存储。
├── model-00002-of-00004.safetensors   # 模型权重文件(第2部分),使用Safetensors格式存储。
├── model-00003-of-00004.safetensors   # 模型权重文件(第3部分),使用Safetensors格式存储。
├── model-00004-of-00004.safetensors   # 模型权重文件(第4部分),使用Safetensors格式存储。
│
├── model.safetensors.index.json       # 模型索引文件,包含模型权重的索引信息。
│
├── README.md                          # 项目说明文件,提供模型的使用说明和相关信息。
│
├── tokenizer.json                     # 分词器配置文件,定义分词器的参数和设置。
│
├── tokenizer_config.json              # 分词器初始化配置文件,包含分词器的启动配置。
│
└── vocab.json                         # 词汇表文件,列出模型可识别的所有词汇。

模型使用

第一步:创建Jupyter Notebook文件

在与qwen2-7b-instruct同一目录下,新建Jupyter Notebook文件,命名为qwen2测试.ipynb

workspace/
├── qwen2-7b-instruct/  
├── qwen2测试.ipynb  

第二步:运行测试代码
在qwen2测试.ipynb中,输入以下代码:

# 导入依赖组件
from modelscope import AutoModelForCausalLM
from modelscope import AutoTokenizer

# 判断设备
device = "cuda" # the device to load the model onto

# 模型ID,对应git clone的模型文件夹名称
model_id = "qwen2-7b-instruct"

# 加载模型
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype="auto",
    device_map="auto"
)

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_id)

# 准备提示词
messages = [
    {"role": "system", "content": """
            You are a helpful assistant.
            """},
    {"role": "user", "content": """
            中华人民共和国的首都是哪里?
    """}
]

# 应用聊天模板
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)

# 输入内容转ID
model_inputs = tokenizer([text], return_tensors="pt").to(device)

# 模型预测
generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512
)

# 删除问句信息
generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]

# 翻译答案
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

# 输出结果
print(response)

运行结果:

代码理解

导入依赖及初始化部分

# 导入依赖组件
from modelscope import AutoModelForCausalLM
from modelscope import AutoTokenizer

# 判断设备
device = "cuda" # the device to load the model onto

# 模型ID,对应git clone的模型文件夹名称
model_id = "qwen2-7b-instruct"

上述的model_id对应本地下载的模型文件夹名称,特别注意文件名及大小写保持一致。

模型结构

在Jupyter Notebook中打印model的模型结构,得到如下内容:

Qwen2ForCausalLM(
  (model): Qwen2Model(
    (embed_tokens): Embedding(152064, 3584)
    (layers): ModuleList(
      (0-27): 28 x Qwen2DecoderLayer(
        (self_attn): Qwen2SdpaAttention(
          (q_proj): Linear(in_features=3584, out_features=3584, bias=True)
          (k_proj): Linear(in_features=3584, out_features=512, bias=True)
          (v_proj): Linear(in_features=3584, out_features=512, bias=True)
          (o_proj): Linear(in_features=3584, out_features=3584, bias=False)
          (rotary_emb): Qwen2RotaryEmbedding()
        )
        (mlp): Qwen2MLP(
          (gate_proj): Linear(in_features=3584, out_features=18944, bias=False)
          (up_proj): Linear(in_features=3584, out_features=18944, bias=False)
          (down_proj): Linear(in_features=18944, out_features=3584, bias=False)
          (act_fn): SiLU()
        )
        (input_layernorm): Qwen2RMSNorm()
        (post_attention_layernorm): Qwen2RMSNorm()
      )
    )
    (norm): Qwen2RMSNorm()
  )
  (lm_head): Linear(in_features=3584, out_features=152064, bias=False)
)
  • Qwen2ForCausalLM 是一个Decoder-Only结构模型。
  • embed_tokens 对应输出层的上文处理外挂部分。
  • layers 对应Decoder部分,由28个Qwen2DecoderLayer构成。
    • self_attn 对应mask自注意力机制部分。由于Decoder-Only结构,所以该模型没有融合注意力机制部分。
    • mlp:多层感知机结构
  • lm_head:对应全链接输出层,负责将模型的输出映射到词汇表的维度。

分词器tokenizer

在Jupyter Notebook中打印model的模型结构,得到如下内容:

Qwen2TokenizerFast(name_or_path='qwen2-7b-instruct', vocab_size=151643, 
        model_max_length=131072, is_fast=True, 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),
}
  • vocab_size:词汇表包含151,643个词汇。
  • model_max_length:支持的最大输入长度为131,072个token。
  • 特殊标记有:
    • <|im_start|>: 表示开始一个对话。
    • <|im_end|>: 表示结束一个对话。
    • |endoftext|: 表示文本结束。

查看参数量

total_params = sum(p.numel() for p in model.parameters())
print(f"模型参数总量: {total_params}")

# 运行结果:
# 模型参数总量: 7615616512

使用上述测试可以查看模型的参数量,对应为76亿。

message

messages = [
    {"role": "system", "content": """
            You are a helpful assistant.
            """},
    {"role": "user", "content": """
            中华人民共和国的首都是哪里?
    """}
]
  • messages 是一个包含对话信息的列表。
  • 每个消息都有一个 role 字段,表示消息的发送者角色。常见的角色有:
    • "system":系统角色,用于设置助手的行为或提供上下文信息。
    • "user":用户角色,表示提问或请求的内容。
  • 每个消息都有一个 content 字段,包含具体的文本内容。这个字段存储了角色所传达的信息。

聊天模板

在Jupyter Notebook中打印text,得到如下内容:

'<|im_start|>system\n\n   
You are a helpful assistant.\n   
<|im_end|>\n<|im_start|>user\n\n   
中华人民共和国的首都是哪里?\n    
<|im_end|>\n<|im_start|>assistant\n'

模型输出

在Jupyter Notebook中,使用以下测试代码,可以看到模型输出的原始内容。

# 模型预测
generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512
)

# 删除问句信息
# generated_ids = [
#     output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
# ]

# 翻译答案
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=False)[0]

# 输出结果
print(response)

输出结果:

<|im_start|>system

            You are a helpful assistant.
            <|im_end|>
<|im_start|>user

            中华人民共和国的首都是哪里?
    <|im_end|>
<|im_start|>assistant
中华人民共和国的首都是北京。<|im_end|>
  • skip_special_tokens 设置为False,可以输出完整的对话内容。如果改为True,则输出内容会去掉im_start等特殊字符。

streamlit调用模型

为了便于修改message的内容,接下来我们通过streamlit搭建一个简易的调用Qwen2的页面,来测试模型的不同任务胜任能力。

安装streamlit

pip install streamlit

下载模型

实测Qwen2-7B模型在魔搭社区GPU环境上运行会因为显存不足,导致无法有效运行,所以这里我们选择使用Qwen2-0.5B-Instruction模型。

git clone https://www.modelscope.cn/qwen/Qwen2-0.5B-Instruct.git

创建代码

创建app.py文件,代码内容如下:

import streamlit as st
from modelscope import AutoModelForCausalLM, AutoTokenizer
import torch

# 判断设备
device = "cuda" if torch.cuda.is_available() else "cpu"

# 模型ID
model_id = "Qwen2-0.5B-Instruct"

# 加载模型
model = AutoModelForCausalLM.from_pretrained(model_id).to(device)

tokenizer = AutoTokenizer.from_pretrained(model_id)

# Streamlit 页面标题
st.title("聊天助手")

# 输入系统内容
system_content = st.text_area("输入系统内容", "You are a helpful assistant.")

# 输入用户内容
user_content = st.text_area("输入用户内容", "中华人民共和国的首都是哪里?")

# 提交按钮
if st.button("获取回答"):
    # 准备提示词
    messages = [
        {"role": "system", "content": system_content},
        {"role": "user", "content": user_content}
    ]

    # 应用聊天模板
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )

    # 输入内容转ID
    model_inputs = tokenizer([text], return_tensors="pt").to(device)

    # 模型预测
    generated_ids = model.generate(
        model_inputs.input_ids,
        max_new_tokens=512
    )

    # 删除问句信息
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]

    # 翻译答案
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

    # 输出结果
    st.subheader("模型回答")
    st.write(response)

运行代码

在终端中运行以下命令

streamlit run app.py

启动后点击Local URL: http://localhost:8501 得到如下效果:

特别说明:
在使用streamlit启动页面前,请在终端命令行中使用 nvidia-smi 查看显存的释放情况;如果显存未释放,建议在Jupyter Notebook中Shutdown Kernel以便释放显存。

大模型能力

大模型有着非常强的能力,通过修改system和user中的内容,可以胜任不同的任务。

翻译任务

在streamlit页面中编辑框中输入对应内容:

  • 系统内容:

    你是一个翻译助手,请将输入的文本翻译成英文。
  • 用户内容:

    中国队在巴黎奥运会中取得了11金7银6铜的成绩,‌位列奖牌榜首位。‌

运行结果:

情感识别任务

  • 系统内容:
    你是一个情感识别机器人,请将用户的输入做情感分类。
    如果是正面的情感,请输出:正面
    如果是负面的情感,请输出:负面
    如果是中性的情感,请输出:中性
  • 用户内容:
    送餐快,态度也特别好,辛苦啦谢谢

运行结果:

说明:

信息提取任务

  • 系统内容:
    你是一个信息抽取机器人,请从用户的投诉中抽取核心信息,输出格式请参考:
    {
    'name' : '投诉人的姓名',
    ‘phone’ : '投诉人的电话号码',
    'reason' : '投诉原因',
    'appeal' : '投诉人期望的解决办法',
    },
    请注意:务必严格按照用户输入来抽取信息,切记随意捏造答案!如果没有相关的信息,请直接把该字段赋值为"不知道"。
  • 用户内容:
    我是楼下的小李子,家里快递丢了3天了,给你们打电话也打不通!赶紧处理!否则,我要给拨打市长热线了。

    运行结果:

阅读理解任务

  • 系统内容:

    你是一个阅读理解机器人,请认真阅读用户的输入内容,严格根据文章的内容来回答用户的问题。
    注意:如果文章中没有出现相关问题的答案,请直接回答"不知道"。
  • 用户内容:

    诸葛亮(181年—234年10月8日),字孔明,号卧龙,琅琊阳都(今山东省沂南县)人 [126],三国时期蜀汉丞相,中国古代杰出的政治家、军事家、战略家 [256]、发明家、文学家。 [164]
    诸葛亮早年随叔父诸葛玄到荆州,诸葛玄死后,诸葛亮躬耕于南阳。 [1-4]刘备依附荆州刘表时三顾茅庐,诸葛亮向刘备提出占据荆州、益州,联合孙权共同对抗曹操的《隆中对》,刘备根据诸葛亮的策略,成功占领荆州、益州之地,与孙权、曹操形成三足鼎立之势。章武元年(221年),刘备称帝,任命诸葛亮为丞相。刘备伐吴于夷陵之战失败后,刘备于永安托孤于诸葛亮。刘禅继位后,封诸葛亮为武乡侯,领益州牧。诸葛亮勤勉谨慎,大小政事必亲自处理,赏罚严明;与东吴联盟,改善和西南各族的关系;实行屯田政策,加强战备。诸葛亮前后五次北伐中原,但未能实现兴复汉室的目标。终因积劳成疾,于建兴十二年(234年)病逝于五丈原(今陕西省宝鸡市岐山境内),享年五十四岁 [5]。后主刘禅追谥为忠武侯,后世常以“武侯”尊称。东晋桓温追封为“武兴王”。 [6]
    诸葛亮散文代表作有《出师表》《诫子书》等。曾发明木牛流马、孔明灯等,并改造连弩,叫作诸葛连弩,可一弩十矢俱发。 [162]诸葛亮一生“鞠躬尽瘁,死而后已”,是中国传统文化中“忠臣”与“智者”的代表人物。
    诸葛亮的注明著作是什么?

运行结果:

文本摘要任务

  • 系统内容:
    你是一个文本摘要机器人,请将用户输入的文章输出摘要,要求100字以内。
  • 用户内容:
    鲁迅(1881年9月25日—1936年10月19日),原名周樟寿,后改名周树人,字豫山,后改字豫才,浙江绍兴人。中国著名文学家、思想家、革命家、教育家、美术家、书法家、民主战士,新文化运动的重要参与者,中国现代文学的奠基人之一。 [181-185]
    他早年与厉绥之和钱均夫同赴日本公费留学,于日本仙台医科专门学校肄业。 [172] [180]“鲁迅”,是他在1918年发表《狂人日记》时所用的笔名,也是最为广泛的笔名。 [1-6]
    鲁迅一生在文学创作、文学批评、思想研究、文学史研究、翻译、美术理论引进、基础科学介绍和古籍校勘与研究等多个领域具有重大贡献。他对于五四运动以后的中国社会思想文化发展具有重大影响,蜚声世界文坛,尤其在韩国、日本思想文化领域有极其重要的地位和影响,被誉为“二十世纪东亚文化地图上占最大领土的作家”。

    运行结果:

回想2019年在搜狗时,参加了一年一度的《黑客马拉松大赛》,其中我们小组的主题就是进行文本摘要提取。当时只是使用word2vec词向量提取后进行机器学习,虽然创意较好,但是效果并不理想。如今对比大模型的效果,真是感慨技术进步之快。

少样本学习推理任务

  • 系统内容:
    请学习下面用户给定的样本,据此做出相关的推理:
    {'input':'北京', 'output':'北京烤鸭'}
    {'input':'山西', 'output':'肉夹馍'}
  • 用户内容:
    兰州

    运行结果:

内容小结

  • Qwen系列模型是Decoder-Only模型,其中Qwen2-7B-Instruct是经过监督微调SFT的模型,参数支持70亿。
  • Qwen模型可以支持多种任务,如:翻译任务、信息提取、情感识别、文本摘要、少样本学习推理任务等。

参考资料

暂无

欢迎关注公众号以获得最新的文章和新闻

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

分类文章

personal_logo
Dongming
自由职业者

推荐活动

推荐文章

【操作攻略】GPU云环境的使用介绍
【项目实战】通过LLaMaFactory+Qwen2-VL-2B微调一个多模态医疗大模型
【课程总结】day19(中):Transformer架构及注意力机制了解
【重拾数学知识】矢量的点乘和叉乘
【课程总结】Day11(上):手势图像识别实战(LeNet模型)
【课程总结】day34:多模态大模型之ViT模型、CLIP模型论文阅读理解
【目录】AI知识学习路线图
【课程总结】day33:文生图StableDiffusion模型初步了解以及部署体验
【课程总结】day32(下):Xinference部署向量化模型
【课程总结】day31:多模态大模型初步了解
内容目录
滚动至顶部