AI第二课堂实践:大语言模型入门
大语言模型
概念
大模型通常指的是具有大规模参数和复杂架构的机器学习模型,尤其是在自然语言处理和计算机视觉等领域。
-
大模型特点
- 参数数量巨大:可能包含数十亿甚至数万亿个参数,这使得它们能够学习到极其丰富和细致的模式和特征。
- 强大的表示能力:能够对复杂的数据进行有效的表示和理解,捕捉到数据中的细微差别和复杂关系。
- 泛化能力强:经过在大规模数据上的训练,可以对新的、未见过的数据做出较为准确的预测和处理。
-
大模型的挑战和问题
- 计算资源需求高:训练和运行这样的模型需要大量的计算能力和内存,成本高昂。
- 数据需求大:需要海量的高质量数据来进行有效的训练。
- 可解释性差:其内部的决策过程和输出结果往往难以清晰地解释和理解。
分类
- 自然语言处理模型
能够理解和生成人类语言,用于对话、文本生成、问答系统、机器翻译等任务。例如,在智能客服中,能够快速准确地回答用户的问题,提供帮助和解决方案。
-
计算机视觉模型
用于图像识别、目标检测、图像分类、图像生成等任务。
-
语音处理模型
包括语音识别模型和语音合成模型。语音识别模型能够将人类的语音转化为文字,语音合成模型则可以将文字转换为自然流畅的语音。常见的应用如语音助手、语音导航等。
-
多模态模型
可以同时处理多种类型的数据,如图像和文本、音频和文本等。
-
强化学习模型
常用于游戏、机器人控制、自动驾驶等需要通过与环境交互来学习最优策略的场景。
-
推荐系统模型
根据用户的历史行为和偏好,为用户推荐相关的产品、内容等。预测分析模型
-
预测分析模型
基于历史数据进行预测,如预测股票价格、天气情况、销售趋势等。
LLM
发展历程
- 早期语言模型
采用统计学习预测词汇,受限于理解复杂语言规则。 - 深度学习的引入
Bengio在2003年将深度学习应用于语言模型,增强理解语言的能力 - Transformer架构优势
2018年左右,Transformer模型出现,通过大量文本训练理解语言规
则。 - 大型语言模型时代
随着模型规模扩大,LM展现出惊人能力,开启新纪元。
能力
- 涌现能力简介
- 基座模型的多元应用能力
- 支持对话统一入口
主要机制
-
**分词:**将文本分解成词汇单元,如单词、子词或字符等,常用的分词工具有 nltk、spacy(英文)和 jieba 库(中文)等。其中n-gram模型是一种基于分词的语言建模方法,它假设一个词出现的概率仅依赖于它前面的 n-1 个词,可以是 unigram(每个单词独立)、bigram(每个单词的概率取决于前一个单词)或 trigram(每个单词的概率取决于前两个单词)等形式,但 n-gram 模型存在忽略较长范围依赖关系和无法处理未见过词汇的局限性。
-
**词向量:**将词语转换成对应的数值向量表达形式,便于计算机读取和运算。常用方法包括独热编码和表示学习。独热编码将每个词汇表示为一个高维稀疏向量,其中只有一个元素为 1,其余为 0,但无法捕捉单词间的相似性和语义关系,且向量维度与词汇表大小相关,会导致向量十分稀疏。而表示学习则将词汇表中的每个单词映射到一个固定长度的低维向量空间中,相似的词汇具有相似的表示,从而捕获语义信息,它具有从高维到低维、能捕获语义信息、构建向量空间以及减小维度等特点。
-
**神经概率语言模型:**为解决词向量模式的局限性而引入神经网络,其具有强大的表达学习能力,词向量通过神经网络参数产生联系。例如 Transformer 模型,它由输入层、隐藏层和输出层构成。输入层接受上下文窗口内的词汇作为输入并表示为词向量;隐藏层通过学习权重捕获词汇之间的复杂关系,具备非线性建模能力;输出层使用 softmax 函数生成概率分布,表示词汇表中每个词汇作为下一个词的概率。
-
**自注意力机制:**Transformer 中使用的一种特殊机制,它通过对输入序列进行线性变换,得到一个注意力权重分布,然后根据这个分布加权输入序列中的每个元素,得到最终的输出。其作用是让模型能够像人在阅读长文章时依靠注意力选择重点词进行关联从而更好地理解文章一样,对海量文本进行并行处理,提高处理速率。计算注意力权重的过程可以通过一套复杂的公式实现,简单来说,可以类比数学课本上关于向量的知识,当两个向量的方向趋于一致时,它们的点积数值越大,代表两个词的关联程度大;数值为 0 则表示两个向量垂直,即词之间没有关联;数值为负数则表示两个向量相反,即两个词不但没关联,还差距过大。在实际应用中,还需要经过多次重复和复杂计算以获取更准确的信息,确定每个词符合上下文语境的含义。
代码
- chat_cil.py:实现了使用指定的预训练语言模型Qwen2-0.5B-Instruct,根据给定的提示"你是谁?"以及包含系统和用户角色的消息,生成一段新的文本,并最终打印输出。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Thread
device = "cuda" # 设备,可以是 "cuda" 或 "cpu"
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)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
# {"role": "user", "content": prompt}
]
def stream_generate(prompt, model, tokenizer, device):
# 准备初始输入
# messages = [
# {"role": "system", "content": "You are a helpful assistant."},
# {"role": "user", "content": prompt}
# ]
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(
model_inputs,
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_ids = model.generate(
# model_inputs.input_ids,
# max_new_tokens=512,
# do_sample=True,
# top_k=50,
# temperature=0.7,
# pad_token_id=tokenizer.eos_token_id
# )
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})
# for output_id in generated_ids[0][model_inputs.input_ids.shape[-1]:]:
# token = tokenizer.decode(output_id, skip_special_tokens=True)
# generated_text += token
# print(token, end="", flush=True)
# print() # 打印新行以结束当前响应
# 多轮对话
while True:
user_input = input("User: ")
if user_input.lower() == 'exit':
print("Exiting...")
break
# 生成回复并流式输出
print("Assistant: ", end="")
stream_generate(user_input, model, tokenizer, device)
-
ont_chat.py:构建了一个基于streamlit的 Web 应用
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)
-
test.py:与第一段代码类似,也是使用指定的预训练模型和提示,生成一段文本,不过在生成新的标记 ID 后,对其进行了特定的处理,以得到最终的输出并打印。
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(response)
prompt
在大语言模型(LLM)中,prompt(提示词或提示信息)是指用户向模型提供的输入文本或指令,用于引导模型生成特定类型的响应。它就像是给模型的一个引导或指示,帮助模型理解用户的需求并按照期望生成输出。
prompt 的内容和结构可以有多种形式。它可以是一个简单的问题,如“地球的半径是多少?”;也可以是一段描述,如“描述一下春天的美丽景色”;还可以是一项具体的任务要求,如“为一款新的智能手机编写产品说明书”;甚至可以包含对话历史记录等信息。
通过不断优化和调整 prompt,用户可以引导模型生成更准确、高质量、符合特定需求的文本内容。不同的 LLM 对 prompt 的响应方式可能会有所差异,因此在使用时可能需要根据具体的模型进行一定的尝试和调整。
总之,prompt 在与 LLM 的交互中起着关键作用,它是用户与模型之间沟通的桥梁,能够帮助用户更好地利用 LLM 的能力来解决各种问题和完成各种任务。
流式输出
流式输出是一种数据处理方式,它将数据以流的形式进行传输和处理。在这种方式中,数据不再集中存储在某个地方,而是以分散的方式存储在各个节点上,并不断流动。数据流的处理是在流动过程中实时完成的,这减少了数据处理的延迟,提高了数据处理效率。
在自然语言处理等领域,实现流式输出可以让模型实时地、连续地输出文本内容,而不是等待整个回答完全生成后再一次性输出,使用户体验更加流畅。例如,在与聊天机器人对话时,能够实时看到机器人逐字逐句地生成回答。
在 Python 中,可以通过生成器Generator
来实现流式输出。生成器是可以逐个产生值的函数,它可以在迭代过程中逐个产生数据。在处理大规模数据时,Python 的流式输出能够显著提高程序的性能和效率。
stable diffusion
概念
一种强大的图像生成模型
特点:
- 高画质生成:能够生成细节丰富、逼真清晰的图像。例如,可以生成极具艺术感的风景图像,其中的光影效果、色彩层次和物体纹理都十分细腻。
- 高度灵活的定制性:用户可以通过输入各种提示词,包括主题、风格、色彩、构图等方面的描述,来精准控制生成图像的特征。比如,您可以要求生成一幅“赛博朋克风格的城市夜景,以蓝色和紫色为主色调,有飞行的汽车和摩天大楼”的图像。
- 快速生成:相比一些传统的图像生成方法,Stable Diffusion 能够在相对较短的时间内生成图像,提高了创作效率。
- 多种应用场景:被广泛应用于艺术创作、设计、影视制作、游戏开发等领域。比如,在游戏开发中为角色设计独特的外观,或者为影视作品创建概念艺术图。