0


AI实践学习笔记(四)------大语言模型入门

第四节课程简介

讲师:赵文恺

日期:2024.8.1

简介:大语言模型入门

基本概念

大语言模型(LLM)

   ** 大语言模型(Large Language Model,LLM)是一种基于深度学习技术的人工智能模型,专门用于处理和生成自然语言。它们通常由大量的文本数据训练而成,能够理解和生成与人类语言相关的内容。GPT-4(即我所基于的模型)就是一种大语言模型,能够回答问题、生成文本、进行对话等。**

** 这些模型的基本构建块是神经网络,尤其是变换器(Transformer)架构。它们通过对大量语言数据的学习,掌握了语言的语法、词汇和常识,从而能够生成流畅且符合语境的文本。**

千问2(qwen2)

千问2是阿里云推出的新一代大语言模型,包含多个尺寸的预训练和指令微调模型,如Qwen2-0.5B、Qwen2-1.5B、Qwen2-7B、Qwen2-57B-A14B和Qwen2-72B。这些模型使用了GQA(分组查询注意力)机制,以优化推理速度和显存占用。

Qwen-2 的特点包括:

  1. 多模态能力:有些版本具备处理文本和图像的能力,能够更好地理解和生成多种形式的信息。
  2. 开源:Qwen-2 的部分模型和代码可能是开源的,这使得其他开发者和研究人员能够使用和改进这些工具。
  3. 大规模训练:它通常使用大量的文本数据进行训练,使其在多个语言理解和生成任务中表现良好。

** 本节课我们学习对千问2大语言模型的部署与测试。**

Stable Diffusion图像生成

** Stable Diffusion 是一种强大的图像生成模型,结合了扩散模型的理论和高效的潜在空间操作,使得能够生成高质量和有条件的图像。它在艺术创作、广告、游戏开发等多个领域具有广泛的应用潜力。**

千问2(qwen2)模型

环境准备

我们在趋动云算力平台上进行模型的部署:

注册云算力平台:https://growthdata.virtaicloud.com/t/NA

** 创建项目,选择B1.medium规格服务器**

** 选择CUDA12.1 PyTorch2.1.1的镜像**

** 在模型中搜索Qwen2-0.5B-Instruct**

点击启动后,进入环境。

在/gemini/code中存放代码,/gemini/pretrain中是我们刚刚挂载的模型。

我们在本地解压大模型应用.zip,得到5个文件,进入/gemini/code目录,将文件拖入窗口完成上传。

我们需要安装一些必要的库,确保我们的环境支持模型训练和推理所需的计算负载。

在 Python 环境中更新或安装

transformers

库,

transformers

库是由 Hugging Face 提供的,用于处理和使用各种预训练的深度学习模型,如 BERT、GPT 和其他变换器模型。

!pip install transformers==4.37.0 -U

在 Python 环境中安装 Streamlit 库,Streamlit 是一个用于创建和共享数据应用的开源框架,特别适合快速构建数据科学和机器学习应用的交互式用户界面。

!pip install streamlit

至此,我们完成了前期的环境准备。

test

这段代码的目的是加载一个预训练的因果语言模型,并使用它生成对话回应。

from transformers import AutoModelForCausalLM, AutoTokenizer
device = "cuda" # the device to load the model onto

model = AutoModelForCausalLM.from_pretrained(
    "/gemini/pretrain/Qwen2-0.5B-Instruct",
    torch_dtype="auto",
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("/gemini/pretrain/Qwen2-0.5B-Instruct")

prompt = "你是谁?"
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)
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(respons

我们逐行分析这段代码,解释每行的功能和作用:

from transformers import AutoModelForCausalLM, AutoTokenizer
  • 作用:从 transformers 库中导入 AutoModelForCausalLMAutoTokenizer。 - AutoModelForCausalLM 是 Hugging Face 的 transformers 库中的一个类,用于自动加载适用于因果语言建模(causal language modeling)的预训练模型。因果语言模型主要用于文本生成任务,比如 GPT(Generative Pre-trained Transformer)系列模型。- AutoTokenizer 是 Hugging Face 的 transformers 库中的一个类,用于自动加载和管理与特定预训练模型兼容的 tokenizer。Tokenizers 是将文本数据转换为模型可以处理的格式的工具,包括将文本转换为 tokens(即模型的输入格式)。
device = "cuda" # the device to load the model onto
  • 作用:指定将模型加载到 GPU 上。"cuda" 表示使用 GPU(CUDA 兼容的设备)来加速计算。如果没有 GPU,可将其更改为 "cpu"
model = AutoModelForCausalLM.from_pretrained(
    "/gemini/pretrain/Qwen2-0.5B-Instruct",
    torch_dtype="auto",
    device_map="auto"
)
  • 作用:加载一个预训练的因果语言模型。 - "/gemini/pretrain/Qwen2-0.5B-Instruct" 是模型的存储路径(可以是本地路径或模型名称)。- torch_dtype="auto" 使得 PyTorch 自动选择适当的数据类型(例如,float32float16)。- device_map="auto" 使得模型自动映射到指定的设备(例如 GPU)。
tokenizer = AutoTokenizer.from_pretrained("/gemini/pretrain/Qwen2-0.5B-Instruct")
  • 作用:加载与模型兼容的 tokenizer。tokenizer 用于将文本转换为模型可以处理的格式。
prompt = "你是谁?"
  • 作用:定义输入给模型的提示(prompt)。
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt}
]
  • 作用:创建一个包含对话上下文的消息列表。 - "role": "system" 指定系统消息,通常用于设置对话的上下文或系统行为。- "role": "user" 指定用户消息,表示用户输入的内容(在这里是 prompt)。
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)
  • 作用:使用 tokenizer 的 apply_chat_template 方法将消息列表转换为模型输入格式。 - tokenize=False 表示不对模板进行 tokenization。- add_generation_prompt=True 表示添加生成提示符,以帮助模型生成更好的回复。
model_inputs = tokenizer([text], return_tensors="pt").to(device)
  • 作用:将转换后的文本编码为模型的输入张量,并将其移动到指定的设备(GPU)。
generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512
)
  • 作用:使用模型生成文本。 - model_inputs.input_ids 是输入张量。- max_new_tokens=512 限制生成的最大新 token 数量为 512。
generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
  • 作用:从生成的 IDs 中删除输入部分,只保留模型生成的部分。 - zip(model_inputs.input_ids, generated_ids) 将输入 IDs 和生成的 IDs 配对。- output_ids[len(input_ids):] 表示从生成的 IDs 中删除与输入相同的部分,只保留生成的新部分。
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
  • 作用:将生成的 token IDs 解码为人类可读的文本。 - skip_special_tokens=True 表示跳过特殊 token(如填充和结束标记)。- [0] 取出第一个解码的结果(在处理多个输入时,batch_decode 返回一个列表)。
print(response)
  • 作用:打印生成的响应。

流式输出

** 接下来在test的基础上使用

transformers

库中的模型进行流式文本生成,并处理多轮对话。通过使用线程,模型生成过程不会阻塞主线程,允许实时输出生成的文本。**

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Thread

device = "cuda"

model_name = "/gemini/pretrain/Qwen2-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
tokenizer = AutoTokenizer.from_pretrained(model_name)
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
]
/root/miniconda3/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
In [2]:
def stream_generate(prompt, model, tokenizer, device):
    messages.append({"role": "user", "content": prompt})
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    model_inputs = tokenizer([text], return_tensors="pt").to(device)
    generate_params = dict(
        inputs=model_inputs.input_ids,
        max_new_tokens=512,
        do_sample=True,
        top_k=50,
        temperature=0.7,
        pad_token_id=tokenizer.eos_token_id,
        streamer=streamer
    )
    
    thread = Thread(target=model.generate, kwargs=generate_params)
    thread.start()

    generated_text = ""
    for new_text in streamer:
        generated_text += new_text
        print(new_text, end='', flush=True)
    print()
    # generated_text
    messages.append({"role": "user", "content": generated_text})
In [3]:
# 多轮对话
while True:
    user_input = input("User: ")
    if user_input.lower() == 'exit':
        print("Exiting...")
        break
    
    # 生成回复并流式输出
    print("Assistant: ", end="")
    stream_generate(user_input, model, tokenizer, device)
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Thread
  • import torch:导入 PyTorch 库,用于模型计算和设备管理。
  • from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer:从 transformers 库导入模型、tokenizer 和流式文本生成工具。
  • from threading import Thread:导入 Thread 类,用于创建线程,实现异步执行。设置设备和加载模型
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
  • TextIteratorStreamer 用于流式生成文本。skip_prompt=Trueskip_special_tokens=True 控制生成文本的输出格式。
def stream_generate(prompt, model, tokenizer, device):
  • 定义一个名为 stream_generate 的函数,用于生成模型回复并流式输出。
    messages.append({"role": "user", "content": prompt})
 将用户输入的消息添加到 
messages

列表中,以保持对话上下文。

    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
  • 使用 apply_chat_template 方法将 messages 列表转换为模型的输入格式,tokenize=False 表示不对文本进行分词,add_generation_prompt=True 表示添加生成提示符。
    model_inputs = tokenizer([text], return_tensors="pt").to(device)
  • 将生成的文本 text 转换为 PyTorch 张量,并将其移动到指定的设备(GPU)。
    generate_params = dict(
        inputs=model_inputs.input_ids,
        max_new_tokens=512,
        do_sample=True,
        top_k=50,
        temperature=0.7,
        pad_token_id=tokenizer.eos_token_id,
        streamer=streamer
    )
  • 定义生成参数字典: - inputs=model_inputs.input_ids:模型的输入 ID。- max_new_tokens=512:生成的最大新令牌数。- do_sample=True:启用采样,以产生更随机的输出。- top_k=50:使用前 50 个候选令牌进行采样。- temperature=0.7:控制生成文本的随机性,温度较低生成更确定的输出。- pad_token_id=tokenizer.eos_token_id:填充标记的 ID。- streamer=streamer:用于流式输出的 TextIteratorStreamer 对象。
    thread = Thread(target=model.generate, kwargs=generate_params)
    thread.start()
  • 创建并启动一个线程来执行模型的生成任务,以避免阻塞主线程。
    generated_text = ""
    for new_text in streamer:
        generated_text += new_text
        print(new_text, end='', flush=True)
    print()
  • streamer 获取生成的文本并逐步拼接到 generated_text 中,同时实时打印生成的文本。
    messages.append({"role": "user", "content": generated_text})
  • 将生成的文本作为用户消息添加到 messages 列表中,以更新对话上下文。
while True:
    user_input = input("User: ")
    if user_input.lower() == 'exit':
        print("Exiting...")
        break
  • 开启一个无限循环,读取用户输入。如果用户输入 exit,则退出循环并打印 "Exiting..."
    print("Assistant: ", end="")
    stream_generate(user_input, model, tokenizer, device)
  • 调用 stream_generate 函数生成回复并流式输出。print("Assistant: ", end="") 用于在生成的文本之前打印 "Assistant: " 提示符。

运行结果

one_chat.py

** 虽然有了流式输出,但是整个问答没有界面,观感差,接下来我们使用streamlit框架构建即时问答系统。**

import streamlit as st
from threading import Thread
import json
import time
from transformers import AutoTokenizer
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
import torch

st.title('Qwen2-0.5B-Instruct')

device = "cuda"
model_name = "/gemini/pretrain/Qwen2-0.5B-Instruct"

@st.cache_resource
def get_model():  
    model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    return model, tokenizer

model, tokenizer = get_model()
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

def generate_response(input_text):

    prompt = f'''
    你是一个智能问答助手,这是你需要回答的问题:
    <question>
    {input_text}
    </question>
    '''

    print(prompt)
    # 构建消息列表
    messages = [{"role": "user", "content": prompt}]

    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    model_inputs = tokenizer([text], return_tensors="pt").to(device)
    generate_params = dict(
        inputs=model_inputs.input_ids,
        max_new_tokens=512,
        do_sample=True,
        top_k=50,
        temperature=0.7,
        pad_token_id=tokenizer.eos_token_id,
        streamer=streamer
    )
    
    thread = Thread(target=model.generate, kwargs=generate_params)
    thread.start()

    return streamer

with st.form('my_form'):
    text = st.text_area('Enter text:', 'What are the three key pieces of advice for learning how to code?')
    submitted = st.form_submit_button('Submit')
    if submitted:
        message_placeholder = st.empty()
        # 调用模型生成响应
        streamer = generate_response(text)
        response = ""
        for text in streamer:
            response += text
            message_placeholder.info(response + "▌")
    
        message_placeholder.info(response)
import streamlit as st
from threading import Thread
import json
import time
from transformers import AutoTokenizer
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
import torch
  • 导入streamlit库,这是一个用于创建和部署机器学习模型和数据应用程序的Python库。st 是streamlit的简写。

  • 导入Thread类,用于创建线程。

  • 导入json库,用于处理json格式的数据。

  • 导入time库,用于处理时间相关的功能。

  • 导入transformers库中的几个类,分别是AutoModelForCausalLMAutoTokenizerTextIteratorStreamer

  • 导入torch库,这是一个用于深度学习的研究和生产级别的Python库。

@st.cache_resource
def get_model():  
    model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    return model, tokenizer
  • 定义了一个函数get_model,用于加载和返回模型及tokenizer。使用了@st.cache_resource装饰器来缓存模型和tokenizer,以提高性能。
model, tokenizer = get_model()
  • 调用get_model函数,返回模型和tokenizer。
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
  • 创建一个TextIteratorStreamer对象,用于流式处理文本数据。skip_prompt=Trueskip_special_tokens=True这两个参数用于调整处理过程中的行为。
def generate_response(input_text):
  • 定义了一个函数generate_response,该函数接受一个输入文本input_text,并生成一个相应的响应。
    prompt = f'''
    你是一个智能问答助手,这是你需要回答的问题:
    <question>
    {input_text}
    </question>
    '''
  • 定义了一个模板字符串prompt,将输入的文本input_text嵌入一个结构化的上下文中。
    print(prompt)
  • prompt打印到控制台。
    # 构建消息列表
    messages = [{"role": "user", "content": prompt}]
  • 构建了一个消息列表messages,其中包含一个字典,表示用户发送的消息。
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
  • 使用tokenizer.apply_chat_template函数处理消息列表,并将结果赋给text变量。
    model_inputs = tokenizer([text], return_tensors="pt").to(device)
  • 使用tokenizer将处理过的文本转换为模型的输入格式,并将结果移动到指定的设备上。
    generate_params = dict(
        inputs=model_inputs.input_ids,
        max_new_tokens=512,
        do_sample=True,
        top_k=50,
        temperature=0.7,
        pad_token_id=tokenizer.eos_token_id,
        streamer=streamer
    )
  • 定义了生成参数generate_params字典,包含了模型的输入、生成最大新令牌数、是否进行采样等参数。
    thread = Thread(target=model.generate, kwargs=generate_params)
    thread.start()
  • 创建一个线程,用于异步执行模型的生成任务,并将生成的文本流式输出。
    return streamer
  • 返回streamer对象。
with st.form('my_form'):
    text = st.text_area('Enter text:', 'What are the three key pieces of advice for learning how to code?')
  • 使用streamlit的form组件创建了一个表单my_form,并提供了文本框供用户输入问题。
    submitted = st.form_submit_button('Submit')
  • 创建了一个按钮,用于提交表单。
    if submitted:
        message_placeholder = st.empty()
  • 如果表单被提交,则创建一个message_placeholder以显示输出。
        # 调用模型生成响应
        streamer = generate_response(text)
  • 调用generate_response生成响应。
        response = ""
  • 创建了一个空字符串response,用于存储生成的文本。
        for text in streamer:
            response += text
            message_placeholder.info(response + "▌")
  • 遍历streamer中的文本,将其追加到response中,并实时显示到message_placeholder中。
        message_placeholder.info(response)
  • 最后,将完整的响应显示到message_placeholder中。

运行结果

Stable Diffusion

核心概念

  1. 扩散模型(Diffusion Models): 扩散模型是一类生成模型,通过逐步添加噪声到数据中,然后学习如何从噪声中恢复数据。Stable Diffusion 是这类模型的一个实例。
  2. 反向扩散过程(Reverse Diffusion Process): 在训练过程中,模型学习如何从噪声恢复图像。这涉及到从纯噪声开始,逐步去噪直到恢复出清晰的图像。
  3. 条件生成(Conditional Generation): Stable Diffusion 可以根据用户提供的文本描述生成图像,这种条件生成使得模型可以根据指定的文本描述创建相关的图像。
  4. 潜在空间(Latent Space): Stable Diffusion 在潜在空间中进行操作,这意味着它将图像映射到一个较低维度的空间进行处理,然后再映射回图像空间。这种方法提高了效率,并且生成的图像质量通常较高。

工作原理

  1. 数据准备和训练: 模型在大量图像和文本对的数据上进行训练。训练的目标是学会如何从图像中添加噪声,并从噪声中恢复出原始图像。
  2. 文本编码: 使用预训练的文本编码器(如 CLIP)将文本描述编码成潜在空间中的向量。这些向量提供了生成图像的条件信息。
  3. 生成过程: 从纯噪声开始,模型根据文本描述逐步去噪,生成图像。在每一步中,模型使用已学习的去噪网络来生成图像的细节,直到完成图像的生成。
  4. 图像解码: 在生成过程结束后,潜在空间中的图像被解码回图像空间,得到最终的图像结果。

环境准备

与千问二环境准备操作类似。

操作应用

在进入环境后输入以下三行命令:

tar xf /gemini/data-1/stable-diffusion-webui.tar -C /gemini/code/

chmod +x /root/miniconda3/lib/python3.10/site-packages/gradio/frpc_linux_amd64_v0.2

cd /stable-diffusion-webui && python launch.py --deepdanbooru --share --xformers --listen

运行结果

总结感想

** 学习千问2.0大语言模型和Stable Diffusion,是一种梦幻般的体验,它不仅让我深入了解了当前AI领域的两大热点技术,也让我对人工智能的潜力和未来有了更深刻的认识。**

** 首先,千问2.0大语言模型给我留下了深刻的印象。这款先进的模型,不仅在自然语言处理方面的表现令人惊叹,而且它的应用范围之广、功能之强,都让人叹为观止。它不仅仅是一个信息检索工具,更是一个能够理解和生成自然语言的智能系统,它不仅能回答问题,还能进行创作、翻译、摘要等复杂任务。这让我深刻感受到了人工智能在学习和工作效率上的提升潜力,同时对于如何更好地与这种智能系统交互,也有了更多的思考。**

** 而Stable Diffusion,则以其惊人的图像生成能力,让我对这个由人类使用工具改造世界的传统观念产生了疑问。过去,媒介和技法是制作艺术作品的限制,而现在,这些门槛被AI技术所打破。它可以读懂你的文字描述,并将其转化为令人信服的视觉图像。这种技术力量的展现,不仅让艺术家们对创作有了新的思考,也让我们普通人感受到了创造力的解放。**

** 两者的结合,更是让人激动。当强大的语言模型与图像生成技术相结合,可以想象得到,未来无论是科技产品设计、游戏开发,还是影视制作、艺术创作,都将迎来一场前所未有的革命。我们已经见到了诸如文本到图像(Text-to-Image)生成的初步应用,这仅仅是冰山一角。随着技术的不断发展和应用,我们可以预见,未来可能会有更多的creative work,是由智能系统辅助甚至完全由智能系统独立完成的。**

** 但与此同时也带来了一些问题和挑战。比如在版权、伦理和技术偏见等方面。我们如何确保这些技术的发展和应用符合社会伦理和法律规范?在AI生成内容的背后,作者和创作者的角色又如何界定?这些是我们在享受新技术带来便利的同时,必须认真考虑的问题。**

** 总之,虽然这些技术还在不断的成长和完善之中,但它们无疑已经为我们打开了通往美好未来的一扇窗。作为一个学习者,我感到非常激动,同时也感到了责任重大。未来,我要继续努力学习,不断探索,希望能在这些领域贡献自己的力量,共同创造一个更加智能化、更加美好的世界。**


本文转载自: https://blog.csdn.net/siriusj19/article/details/140902058
版权归原作者 siriusj19 所有, 如有侵权,请联系我们删除。

“AI实践学习笔记(四)------大语言模型入门”的评论:

还没有评论