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框架构建即时问答系统。
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库中的几个类,分别是AutoModelForCausalLM
、AutoTokenizer
和TextIteratorStreamer
。
导入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=True
和skip_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生成内容的背后,作者和创作者的角色又如何界定?这些是我们在享受新技术带来便利的同时,必须认真考虑的问题。
总之,虽然这些技术还在不断的成长和完善之中,但它们无疑已经为我们打开了通往美好未来的一扇窗。作为一个学习者,我感到非常激动,同时也感到了责任重大。未来,我要继续努力学习,不断探索,希望能在这些领域贡献自己的力量,共同创造一个更加智能化、更加美好的世界。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。