大模型1-本地部署实现交互问答

任务

在本地部署大模型,调用大模型进行对话。

添加库:

1、Transformer

Transformers 是由 Hugging Face 开发的一个开源库,广泛应用于自然语言处理(NLP)任务。其主要功能是简化了对大型预训练语言模型的加载和使用。它提供了数百种预训练的模型,涵盖了多种 NLP 任务。Transformers 支持多种不同类型的 Transformer 模型架构,涵盖了近年来最先进的 NLP 模型。以下是一些知名模型架构:

  • BERT (Bidirectional Encoder Representations from Transformers):双向编码器,用于生成上下文的词向量。
  • GPT (Generative Pretrained Transformer):生成型预训练模型,擅长生成流畅的文本。
  • T5 (Text-To-Text Transfer Transformer):将所有任务转换为文本生成问题,支持多任务学习。
  • RoBERTa:BERT 的改进版本,通过更多的数据和计算资源训练,性能更好。
  • DistilBERT:BERT 的简化版,参数更少、速度更快,但仍能保持高性能。
  • XLNet:结合了自回归和自编码器的优点,擅长生成任务。
  • Bart:适合文本生成、摘要等任务,双向编码、左到右生成。

2、streamlit

Streamlit 是一个开源的 Python 库,专为快速构建和分享数据应用(data apps)而设计。通过 Streamlit,开发者可以使用非常简洁的 Python 代码将数据分析或机器学习模型可视化,并创建交互式的 Web 应用程序。Streamlit 的主要目标是降低开发和部署数据应用的复杂性,使得数据科学家和工程师可以专注于业务逻辑,而不需要深度了解前端开发。

简而言之就是提供了一个用户交互页面,不需要前端代码。

Streamlit 提供了许多用于构建用户界面的组件,使用户能够与数据进行交互。以下是一些常用的组件:

  • st.write(): 通用的输出函数,支持文字、数据框、图表等的输出。
  • st.title(): 用于创建应用的标题。
  • st.text()st.markdown(): 显示文本,支持 Markdown 格式。
  • st.image(): 显示图片。
  • st.button(): 创建一个按钮,用户点击后触发事件。
  • st.slider(): 滑块,允许用户选择数值范围。
  • st.selectbox(): 下拉选择框。
  • st.file_uploader(): 文件上传组件,支持用户上传文件。
  • st.form(): 用于处理表单输入,用户可以提交多个字段。

主要添加的库如下:

复制代码
from transformers import AutoTokenizer, AutoModelForCausalLM  # 大模型加载必要的函数
import torch
import streamlit as st
# 源大模型下载
from modelscope import snapshot_download  # 阿里的魔塔涵盖了很多大模型,下载速度超级快,而且qwen系列模型也挺好用的,算是国内数一数二的开源模型了

注意:

1、运行使用命令:streamlit run xxx.py

2、可能需要下载的包:einops、sentencepiece

3、使用魔塔modelscope下载模型,模型可以去魔塔社区寻找。

复制代码
from modelscope import snapshot_download
model_dir = snapshot_download('模型ID', cache_dir='您希望的下载路径', revision='版本号')

加载大模型

大模型加载最重要的就是tokenizer和model,

1. Tokenizer(分词器)

Tokenizer 是将自然语言文本转换为模型可理解的数字化表示的工具。它负责将输入的文本转化为词(或子词)ID,然后传递给模型。具体来说,Tokenizer 的作用包括:

  • 分词:将文本拆分成词或子词(这取决于模型的分词方式,比如 BERT 使用的 WordPiece,GPT 使用的 Byte-Pair Encoding (BPE))。
  • 编码:将分词后的文本转换为词汇表中的唯一标识(IDs)。
  • 填充与截断:确保输入的长度符合模型的要求(通常是固定长度),通过在短于要求的序列后添加填充(padding),或者截断超长的序列。
  • 特殊标记处理 :如开始标记 ([CLS])、结束标记 ([SEP]) 等,这些标记通常在处理输入序列时是必须的,尤其是在任务如分类和生成中。

示例

复制代码
from transformers import AutoTokenizer
# 加载 Tokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
# 将文本转换为输入 ID
inputs = tokenizer("Hello, how are you?", return_tensors="pt")

2. Model(模型)

Model 是预训练的大型神经网络模型,通常是 Transformer 架构,用于执行特定的任务(如语言建模、文本生成、问答、翻译等)。模型的任务可以包括:

  • 生成文本(如 GPT 模型)
  • 进行分类(如 BERT 在情感分析、分类任务中)
  • 生成摘要(如 T5 或 Bart 模型)
  • 回答问题(如 BERT 在问答系统中)

示例

复制代码
from transformers import AutoTokenizer, AutoModelForCausalLM
# 加载 tokenizer 和 model
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2").cuda()
# 编码输入文本,将字符转为ID
inputs = tokenizer("Hello, how are you?", return_tensors="pt").to('cuda')
# 模型生成文本
outputs = model.generate(inputs['input_ids'], max_length=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

注意:

1、generate()transformers 库中用于文本生成的函数。它会根据输入的 token ID(即 inputs['input_ids'])生成一段新的文本。

2、inputs['input_ids']:这是模型输入的 token ID 序列,来自于上一步 tokenizer 处理后的结果。模型会根据这些 token 来生成下一个 token。

3、tokenizer.decode(outputs[0], skip_special_tokens=True)

  • outputs[0]outputs 是一个 batch,其中 outputs[0] 是我们关心的第一条生成结果。
  • tokenizer.decode():将模型生成的 token ID 序列转换回人类可读的文本字符串。
  • skip_special_tokens=True:告诉 tokenizer 在解码时忽略特殊的 token,比如 [CLS][SEP] 等。某些模型在处理过程中会加入这些特殊的 token,但它们通常不需要出现在最终的输出文本中。

4、AutoTokenizer负责加载预训练的分词器, AutoModelForCausalLM负责加载语言模型。AutoTokenizer.from_pretrained函数的相关参数可参考AutoTokenizer.from_pretrained参数说明,AutoModelForCausalLM.from_pretrained函数的相关参数可参考AutoModelForCausalLM.from_pretrained参数说明

示例

1、Yuan2-2B-Mars-hf模型

源2.0 是浪潮信息发布的新一代基础语言大模型。我们开源了全部的3个模型源2.0-102B,源2.0-51B和源2.0-2B。并且我们提供了预训练,微调,推理服务的相关脚本,以供研发人员做进一步的开发。源2.0是在源1.0的基础上,利用更多样的高质量预训练数据和指令微调数据集,令模型在语义、数学、推理、代码、知识等不同方面具备更强的理解能力。

python 复制代码
# 导入所需的库
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import streamlit as st

# 创建一个标题和一个副标题
st.title("AI助手")

# 源大模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('IEITYuan/Yuan2-2B-Mars-hf', cache_dir='./')

# 定义模型路径
path = './IEITYuan/Yuan2-2B-Mars-hf'

# 定义模型数据类型
torch_dtype = torch.bfloat16 # A10
# torch_dtype = torch.float16 # P100

# 定义一个函数,用于获取模型和tokenizer
@st.cache_resource
def get_model():
    print("Creat tokenizer...")
    tokenizer = AutoTokenizer.from_pretrained(path, add_eos_token=False, add_bos_token=False, eos_token='<eod>')
    tokenizer.add_tokens(['<sep>', '<pad>', '<mask>', '<predict>', '<FIM_SUFFIX>', '<FIM_PREFIX>', '<FIM_MIDDLE>','<commit_before>','<commit_msg>','<commit_after>','<jupyter_start>','<jupyter_text>','<jupyter_code>','<jupyter_output>','<empty_output>'], special_tokens=True)

    print("Creat model...")
    model = AutoModelForCausalLM.from_pretrained(path, torch_dtype=torch_dtype, trust_remote_code=True).cuda()

    print("Done.")
    return tokenizer, model

# 加载model和tokenizer
tokenizer, model = get_model()

# 初次运行时,session_state中没有"messages",需要创建一个空列表
if "messages" not in st.session_state:
    st.session_state["messages"] = []

# 每次对话时,都需要遍历session_state中的所有消息,并显示在聊天界面上
for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])

# 如果用户在聊天输入框中输入了内容,则执行以下操作
if prompt := st.chat_input():
    # 将用户的输入添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "user", "content": prompt})

    # 在聊天界面上显示用户的输入
    st.chat_message("user").write(prompt)

    # 调用模型
    prompt = "<n>".join(msg["content"] for msg in st.session_state.messages) + "<sep>" # 拼接对话历史
    inputs = tokenizer(prompt, return_tensors="pt")["input_ids"].cuda()
    outputs = model.generate(inputs, do_sample=False, max_length=1024) # 设置解码方式和最大生成长度
    output = tokenizer.decode(outputs[0])
    response = output.split("<sep>")[-1].replace("<eod>", '')

    # 将模型的输出添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "assistant", "content": response})

    # 在聊天界面上显示模型的输出
    st.chat_message("assistant").write(response)

运行结果:

显存占用情况:

2、qwen2-1.5b-instruct模型

Qwen2 是 Qwen 大型语言模型系列的新篇章。对于 Qwen2,我们发布了从 0.5 到 720 亿参数不等的基础语言模型与指令调优语言模型,其中包括混合专家(Mixture-of-Experts)模型。本仓库包含了 1.5B 参数的 Qwen2 指令调优模型。

用原来的的代码运行会出问题,运行结果如下:

猜测是因为不同模型的运行规则有所不同,因此按照qwen文档说明修改代码:

python 复制代码
# 导入所需的库
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch            
import streamlit as st
# 源大模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('qwen/Qwen2-1.5B-Instruct', cache_dir='./')
# 创建一个标题和一个副标题
st.title("AI助手")

# 定义模型路径
path = './qwen/Qwen2-1___5B-Instruct'
# path = './IEITYuan/Yuan2-2B-Mars-hf'
# 定义一个函数,用于获取模型和tokenizer
@st.cache_resource
def get_model():
    print("Creat tokenizer...")
    tokenizer = AutoTokenizer.from_pretrained(path, add_eos_token=False, add_bos_token=False, eos_token='<eod>')
    tokenizer.add_tokens(['<sep>', '<pad>', '<mask>', '<predict>', '<FIM_SUFFIX>', '<FIM_PREFIX>', '<FIM_MIDDLE>','<commit_before>','<commit_msg>','<commit_after>','<jupyter_start>','<jupyter_text>','<jupyter_code>','<jupyter_output>','<empty_output>','<|im_end|>'], special_tokens=True)

    print("Creat model...")
    model = AutoModelForCausalLM.from_pretrained(path, torch_dtype=torch.bfloat16, trust_remote_code=True).cuda()

    print("Done.")
    return tokenizer, model

# 加载model和tokenizer
tokenizer, model = get_model()

# 初次运行时,session_state中没有"messages",需要创建一个空列表
if "messages" not in st.session_state:
    st.session_state["messages"] = []

# 每次对话时,都需要遍历session_state中的所有消息,并显示在聊天界面上
for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])

# 如果用户在聊天输入框中输入了内容,则执行以下操作
if prompt := st.chat_input():
    # 将用户的输入添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "user", "content": prompt})

    # 在聊天界面上显示用户的输入
    st.chat_message("user").write(prompt)

    # 调用模型
    messages = [
    {"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
    ]
    for msg in st.session_state.messages:
        messages.append(msg)
    print(messages)
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True,
        )
    inputs = tokenizer([text], return_tensors="pt").to(model.device)
    outputs = model.generate(**inputs, max_length=1024) # 设置解码方式和最大生成长度
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(inputs.input_ids, outputs)
    ]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

    # 将模型的输出添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "assistant", "content": response})

    # 在聊天界面上显示模型的输出
    st.chat_message("assistant").write(response)

输出结果如下:

这下没啥问题了,所以对不同模型,要根据对应文档编写使用程序。qwen2-1.5b-instruct显存占用如下:

参考文献:

1、Streamlit完全指南:交互式应用开发从入门到精通 - 知乎 (zhihu.com)

2、‍‌‌‍‌‬‬‍‍⁠‌‬‬‌‍‌‍‬‌Task3:源大模型RAG实战 - 飞书云文档 (feishu.cn)

相关推荐
星云ai1 分钟前
2025年的营销趋势-矩阵IP
大数据·人工智能
Y1nhl4 分钟前
搜广推校招面经八十二
人工智能·pytorch·深度学习·机器学习·推荐算法·搜索算法
蹦蹦跳跳真可爱5895 分钟前
Python----深度学习(基于DNN的PM2.5预测)
人工智能·pytorch·python·深度学习·线性回归·dnn
IT古董8 分钟前
【漫话机器学习系列】226.测试集、训练集、验证集(test,training,validation sets)
人工智能
十贝9 分钟前
大模型对话风格微调项目实战——部署上线篇
人工智能
掘金詹姆斯9 分钟前
LangChain4j—人工智能服务 AIService(三)
java·人工智能
星辰大海的精灵10 分钟前
AI编码陷阱防不胜防看看 Cursor使用技巧
人工智能·后端
掘金詹姆斯10 分钟前
LangChain4j—聊天记忆 Chat memory(四)
java·人工智能
小小毛桃19 分钟前
在分类任务中,显著性分析
人工智能·分类·数据挖掘
Black_Rock_br22 分钟前
智驭未来:NVIDIA自动驾驶安全白皮书与实验室创新实践深度解析
人工智能·安全·自动驾驶