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

siriusj19 2024-10-01 15:01:08 阅读 76

第四节课程简介

讲师:赵文恺

日期: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 的特点包括:

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

   本节课我们学习对千问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 环境中更新或安装 <code>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",code>

device_map="auto"code>

)

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)code>

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 库中导入 AutoModelForCausalLM 和 AutoTokenizer

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",code>

device_map="auto"code>

)

作用:加载一个预训练的因果语言模型。

"/gemini/pretrain/Qwen2-0.5B-Instruct" 是模型的存储路径(可以是本地路径或模型名称)。torch_dtype="auto"code> 使得 PyTorch 自动选择适当的数据类型(例如,float32 或 float16)。device_map="auto"code> 使得模型自动映射到指定的设备(例如 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)code>

作用:将转换后的文本编码为模型的输入张量,并将其移动到指定的设备(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)code>

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)code>

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="")code>

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=True 和 skip_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)code>

将生成的文本 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)code>

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="")code>

stream_generate(user_input, model, tokenizer, device)

调用 stream_generate 函数生成回复并流式输出。print("Assistant: ", end="")code> 用于在生成的文本之前打印 "Assistant: " 提示符。

运行结果

one_chat.py

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

<code>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)code>

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)code>

使用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

核心概念

扩散模型(Diffusion Models):

扩散模型是一类生成模型,通过逐步添加噪声到数据中,然后学习如何从噪声中恢复数据。Stable Diffusion 是这类模型的一个实例。

反向扩散过程(Reverse Diffusion Process):

在训练过程中,模型学习如何从噪声恢复图像。这涉及到从纯噪声开始,逐步去噪直到恢复出清晰的图像。

条件生成(Conditional Generation):

Stable Diffusion 可以根据用户提供的文本描述生成图像,这种条件生成使得模型可以根据指定的文本描述创建相关的图像。

潜在空间(Latent Space):

Stable Diffusion 在潜在空间中进行操作,这意味着它将图像映射到一个较低维度的空间进行处理,然后再映射回图像空间。这种方法提高了效率,并且生成的图像质量通常较高。

工作原理

数据准备和训练:

模型在大量图像和文本对的数据上进行训练。训练的目标是学会如何从图像中添加噪声,并从噪声中恢复出原始图像。

文本编码:

使用预训练的文本编码器(如 CLIP)将文本描述编码成潜在空间中的向量。这些向量提供了生成图像的条件信息。

生成过程:

从纯噪声开始,模型根据文本描述逐步去噪,生成图像。在每一步中,模型使用已学习的去噪网络来生成图像的细节,直到完成图像的生成。

图像解码:

在生成过程结束后,潜在空间中的图像被解码回图像空间,得到最终的图像结果。

环境准备

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

操作应用

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

<code>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生成内容的背后,作者和创作者的角色又如何界定?这些是我们在享受新技术带来便利的同时,必须认真考虑的问题。

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。