当前位置: 首页 > news >正文

TransformersInternLM源码阅读

目录

    • 前言
    • 1. 环境配置
    • 2. 模型下载
    • 3. demo运行
    • 4. AutoTokenizer.from_pretrained
    • 5. AutoModelForCausalLM.from_pretrained
    • 6. tokenizer
    • 7. model.generate
    • 结语
    • 下载链接
    • 参考

前言

学习 UP 主 比飞鸟贵重的多_HKL 的 Transformers&InternLM源码阅读 视频,简单了解利用 Hugging Face Transformers 推理的整体流程,模型选用商汤的书生·浦语2.5(InternLM2.5-1.8B),记录下个人学习笔记,仅供自己参考😄

refer1:【大模型碎碎念】Transformers&InternLM源码阅读

refer2:https://github.com/InternLM/InternLM

refer3:https://chatgpt.com/

1. 环境配置

官方的环境要求如下:

在这里插入图片描述

安装指令如下:

git clone https://github.com/InternLM/InternLM.git
cd InternLM
conda create -n internlm python=3.10
conda activate internlm
pip install -r requirements.txt
pip install einops
pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 --index-url https://download.pytorch.org/whl/cu118

Note:torch 的安装大家按照自己实际情况来进行

2. 模型下载

官方提供了多种模型下载的方式,如下图所示:

在这里插入图片描述

大部分 LLM 模型的权重都会放到 Hugging Face 和 ModelScope 上,所以这里我们主要讲解如何从这两个平台上下载模型

首先来看如何从 Hugging Face 上 download,点击 InterLM2.5-1.8B 模型的 Transformers(HF) 链接 🤗internlm2_5-1_8b

Note:由于博主硬件资源有限,这边选用的是 1.5B 的模型,大家有条件的可以选用更大的模型,不过作为学习 LLM 推理的整体流程来说已经足够了

进去之后点击 Files 就可以看到官方提供的所有文件了,包括模型权重、配置文件等等

在这里插入图片描述

下面是这些文件的简要说明:

  • .gitattributes:Git 使用的属性文件,指定 Git 对仓库中不同文件的处理方式,如大文件(LFS)
  • README.md:模型仓库的说明文档,包括模型用途、安装、使用方式等基本信息
  • added_tokens.json:用户新增的一些 token 信息,一般为空或只有少量内容
  • config.json:大语言模型的核心配置文件,包含模型架构、参数、embedding 大小、层数、注意力机制等信息
  • configuration_internlm2.py:模型配置的 python 源文件,定义模型架构参数如何被 python 代码读取和处理,是加载模型配置的重要代码
  • generation_config.json:指定文本生成时的默认生成参数,例如温度(temperature)、最大序列长度、top-k、top-p 等
  • modeling_internlm2.py:模型定义的 python 源文件,包含模型架构代码
  • pytorch_model.bin:pytorch 训练后的模型权重文件
  • special_tokens_map.json:特殊 token(如 <bos><eos><pad>unk 等)和对应映射信息
  • tokenization_internlm2.py:tokenizer 的标准版本源码,用于文本分词和编码过程
  • tokenization_internlm2_fast.py:tokenizer 的快速版本源码
  • tokenizer.json:tokenizer 的 json 格式文件,内含词表和 token 的具体映射关系,用于快速加载 tokenizer
  • tokenizer.model:通常为 sentencepiece 格式的 tokenizer 模型文件,用于将文本切分为模型可以理解的 token 序列
  • tokenizer_config.json:tokenizer 配置文件,记录 tokenizer 的参数设置,包括预处理规则、截断和填充方式等

官方提供的这些文件是不是都要下载呢?不一定,有时官方会提供不同的权重,我们按需下载即可

另外,一个个手动下载属实有点慢,有没有快速一点的方法呢?在 如何优雅的下载huggingface-transformers模型 这篇文章中有提供从 Hugging Face 上 download 的多种方式,大家感兴趣的可以看看

博主这边为了学习,将官方提供的所有文件都给 download 下来了,使用的是 Git LFS 的方案,指令如下:

git lfs install
git clone https://huggingface.co/internlm/internlm2_5-1_8b

如下图所示:

在这里插入图片描述

不过这个下载没有进度条显示,你也不知道下载到哪呢,当然文章中还提供了许多其它的方式,例如使用 Hugging Face Hub 下载,大家根据自己的需求选择即可

下载完成后是一个名为 internlm2.5-1_8b 的文件夹,文件夹下的文件也就是我们前面在 Hugging Face 上看到的:

在这里插入图片描述

Note:大家如果不想自己下载,也可以点击 here 下载博主准备好的模型文件

由于访问 Hugging Face 需要外网,大家如果没有一些科学上网工具,也可以从 ModelScope 上下载

ModelScope 是阿里推出的一个模型即服务的共享平台,与 Hugging Face Hub 类似,网址是:https://modelscope.cn/

下面我们就来看看如何从 ModelScope 上 download,点击 InterLM2.5-1.8B 模型的 ModelScope(HF) 链接 internlm2_5-1_8b

点击模型文件,接着点击右上角的下载模型即可 download:

在这里插入图片描述

ModelScope 也提供了多种下载方式,包括命令行下载、SDK 下载、Git 下载等,大家自己选择一种方式即可,这边博主就不再赘述了

在这里插入图片描述

博主对耳边经常听到的 Hugging Face、Hugging Face Hub、Hugging Face Transformers 不太了解,下面我们简要的解释下

Hugging Face 是一家知名的人工智能技术公司,总部位于美国纽约,成立于 2016 年。其最初以自然语言处理(NLP)为主要研究领域,现已发展成为全面的开源 AI 社区和平台,其标志是一个 🤗 笑脸符号

在这里插入图片描述

Huggin Face Hub 是由 Hugging Face 提供的一个集中式的模型和数据共享平台(托管仓库),可以看作 AI 社区的 “GitHub”,用户可以在此上传、下载、分享预训练模型、数据集等,网址是:https://huggingface.co/

在这里插入图片描述

Hugging Face Transformers 是 Hugging Face 公司开发的一个开源的 Python 库,用于便捷地使用和部署 Transformer 模型。它是当前最流行的 NLP 库之一,广泛应用于自然语言处理、计算机视觉、多模态领域

在这里插入图片描述

一句话总结三者关系:Hugging Face 是一家 AI 公司,提供 Hugging Face Hub 作为 AI 模型、数据的共享平台,并开发了 Hugging Face Transformers 库用于更便捷地使用和微调模型

3. demo运行

环境配置完、模型也下载之后我们就来执行推理

InternLM 的源码较少,大部分都是一些 README 说明文档,这是因为它支持在 Hugging Face 上直接调用,我们直接看它 Hugging Face 上提供的一段推理代码即可

新建 demo.py,其代码如下:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("internlm2_5-1_8b", trust_remote_code=True)
# `torch_dtype=torch.float16` 可以令模型以 float16 精度加载,否则 transformers 会将模型加载为 float32,有可能导致显存不足
model = AutoModelForCausalLM.from_pretrained("internlm2_5-1_8b", torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()
inputs = tokenizer(["来到美丽的大自然"], return_tensors="pt")
for k,v in inputs.items():
    inputs[k] = v.cuda()
gen_kwargs = {"max_length": 128, "top_p": 0.8, "temperature": 0.8, "do_sample": True, "repetition_penalty": 1.0}
output = model.generate(**inputs, **gen_kwargs)
output = tokenizer.decode(output[0].tolist(), skip_special_tokens=True)
print(output)

Note:demo.py 和前面下载的模型文件夹 internlm2_5-1_8b 应放在同一级目录下。此外源码博主有简单修改,将模型加载路径从 internlm/internlm2_5-1_8b 修改为了 internlm2_5-1_8b,直接从本地文件夹 internlm2_5-1_8b 加载模型,如果本地路径不存在它会从 Hugging Face 上 download 模型到 .cache 缓存文件中

执行后输出如下:

在这里插入图片描述

可以看到成功推理了,下面我们来逐行代码解释下这个脚本具体在做些什么:

1. 导入必要的库

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
  • torch:导入 pytorch 库,用于张量运算以及将模型和数据转移到 GPU 上
  • transformers:从 Hugging Face 的 Transformers 库中导入自动加载 Tokenizer 的模型的类
    • 这里我们使用 AutoTokenizerAutoModelForCausalLM 分别加载分词器和因果语言模型(适用于生成任务)

2. 加载分词器(Tokenizer)

tokenizer = AutoTokenizer.from_pretrained("internlm2_5-1_8b", trust_remote_code=True)
  • AutoTokenizer.from_pretrained:根据给定的模型名称 internlm2_5-1_8b 自动加载预训练的分词器
  • trust_remote_code=True:允许加载模型仓库中提供的自定义代码
    • 如果该模型使用了定制化的分词或其它逻辑,这个参数保证了代码能够被正确执行

3. 加载预训练模型

model = AutoModelForCausalLM.from_pretrained("internlm2_5-1_8b", torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()
  • AutoModelForCausalLM.from_pretrained:从 Hugging Face Hub 加载对应的预训练模型
    • 如果本地已经下载则会直接从本地加载,否则会自动从 Hugging Face Hub 下载到本地
  • torch_dtype=torch.float16:指定以 FP16 精度加载模型,能节省显存并加速推理
  • trust_remote_code=True:与加载分词器相同,允许加载模型仓库提供的自定义代码
  • .cuda():将模型放在 GPU 上以加速推理
  • model.eval():将模型设为评估模式,评估模式下会关闭 dropout 等训练期间的随机行为,确保推理结果稳定

4. 准备输入数据

inputs = tokenizer(["来到美丽的大自然"], return_tensors="pt")
for k,v in inputs.items():
    inputs[k] = v.cuda()
  • tokenizer(...):将字符串 来到美丽的大自然 进行分词并转换为模型接受的张量格式
    • 这里返回的是一个字典,包含键 input_idsattention_mask
  • 同时将所有输入张量放到 GPU 上

5. 设置生成参数

gen_kwargs = {"max_length": 128, "top_p": 0.8, "temperature": 0.8, "do_sample": True, "repetition_penalty": 1.0}
  • max_length:生成文本的最大长度(以 token 数计)
  • top_p:采用 nucleus sampling(核采样)策略,控制生成文本的多样性。这里设置 0.8 表示只考虑累积概率达到 80% 的 token
  • temperature:温度参数,用于调节生成文本时的随机性。较低的温度会使输出更确定,较高的温度会使输出更随机
  • do_sample:设为 True 表示采用采样方法生成文本,而非贪心搜索
  • repetition_penalty:重复惩罚因子,用于降低模型重复生成相同内容的概率。设置为 1.0 表示不施加额外的惩罚

6. 生成文本

output = model.generate(**inputs, **gen_kwargs)
  • model.generate:调用模型的生成方法,将输入和生成参数传入。模型根据输入提示(prompt)生成一个 token 序列

7. 解码生成的结果

output = tokenizer.decode(output[0].tolist(), skip_special_tokens=True)
  • tokenizer.decode:将生成的 token ID 序列转换回人类可读的文本字符串
  • skip_special_tokens=True:在解码过程中跳过特殊 token(例如:填充、起始或结束符号),使得输出更加干净

8. 输出生成结果

print(output)
  • 输出生成的文本

整个脚本的执行流程可以概况为以下几点:

  • 1. 加载必要的库和模型资源:加载 pytorch、分词器和预训练因果语言模型,并将其移至 GPU 运行
  • 2. 预处理输入:将输入文本转换为模型可以处理的张量,并确保数据与模型在同一设备上
  • 3. 设置生成参数并进行推理:利用模型的 generate 方法生成文本,其中参数控制生成的长度、多样性和采样策略
  • 4. 解码并输出生成的文本:将生成的 token 序列转换为可读文本,并输出结果

整体流程熟悉后下面我们来 debug 调试下看每步具体在做些什么

4. AutoTokenizer.from_pretrained

我们先 debug 调试下分词加载器函数

Note:由于逐行代码调试展示篇幅占用太大,因此博主这边重点展示核心部分,关于更多的细节大家可以跟随 UP 主的视频一步步调试

博主在利用 vscode 进行代码调试过程中发现无法进入调试安装的 python 第三方库源码,这边参考【已解决】vscode如何调试python第三方库 解决了这个问题,解决方式如下:

步骤 1:打开 vscode 配置,搜索 Debug Just My Code,将 “调试时,仅单步执行用户编写的代码,禁用此选项可允许单步执行库代码” 的 √ 取消

在这里插入图片描述

步骤 2:点击 Debug Just My Code 左边的设置(小齿轮),选择将设置应用于所有配置文件

在这里插入图片描述

接下来我们就可以愉快的调试了

首先,我们进入到 AutoTokenizer.from_pretrained 函数中:

在这里插入图片描述

这里我们主要是处理 from_pretrained 方法中用户传入的参数,包括 configuse_fasttokenizer_typetrust_remote_code 等,通过这一系列的参数处理,后续的分词器加载逻辑可以依赖这些参数进行正确的初始化和配置。由于 tokenizer_type 为 None,因此我们直接往下走,看到 get_tokenizer_config 函数的调用:

在这里插入图片描述

get_tokenizer_config 函数实现如下:

在这里插入图片描述

get_tokenizer_config 通过 cache_file 函数定位分词器配置文件,并处理相关下载参数与异常选项,若配置文件存在,则将其作为 JSON 文件读取并解析为 python 字典,否则返回空

在这里插入图片描述

我们可以看到它读取了本地目录下的 internlm2_5-1_8b\\tokenizer_config.json JSON 文件,并返回了加载结果,也就是说这个函数其实就是加载了分词器的 json 配置文件并返回

tokenizer_config.json 内容如下:

{
  "add_bos_token": true,
  "add_eos_token": false,
  "added_tokens_decoder": {
    "0": {
      "content": "<unk>",
      "lstrip": false,
      "normalized": false,
      "rstrip": false,
      "single_word": false,
      "special": true
    },
    "1": {
      "content": "<s>",
      "lstrip": false,
      "normalized": false,
      "rstrip": false,
      "single_word": false,
      "special": true
    },
    "2": {
      "content": "</s>",
      "lstrip": false,
      "normalized": false,
      "rstrip": false,
      "single_word": false,
      "special": true
    }
  },
  "additional_special_tokens": [],
  "auto_map": {
    "AutoTokenizer": [
      "tokenization_internlm2.InternLM2Tokenizer",
      "tokenization_internlm2_fast.InternLM2TokenizerFast"
    ]
  },
  "bos_token": "<s>",
  "clean_up_tokenization_spaces": false,
  "decode_with_prefix_space": false,
  "eos_token": "</s>",
  "model_max_length": 1000000000000000019884624838656,
  "pad_token": "</s>",
  "sp_model_kwargs": null,
  "tokenizer_class": "InternLM2Tokenizer",
  "unk_token": "<unk>"
}

下面是对该配置文件中各个字段的简要解释:

  • add_bos_token:默认 true,表示在分词时自动添加起始标记(bos, beginning of sequence)
  • add_eos_token:默认 false,表示不会再分词时自动添加结束标记(eos, end of sequence)
  • added_tokens_decoder:定义了添加到词表中的特殊标记及其属性,具体包括:
    • "0": "<unk>":未知标记,用于表示模型未识别的词汇,属性中设置了不去除左右空格、不过归一化、也不限制为单词,同时标记为特殊符号
    • "1": "<s>":起始标记,与 add_bos_token 配合使用,属性同上
    • "2": "<s>":结束标记,属性同上
  • additional_special_tokens:默认 [],表示当前没有额外定义的其它特殊标记
  • auto_map:提供自动映射信息,当使用 AutoTokenizer 加载时,将依次尝试以下两个分词器类:
    • tokenization_internlm2.InternLM2Tokenizer
    • tokenization_internlm2_fast.InternLM2TokenizerFast
  • bos_token:默认 "<s>",指向了实际的起始标记,通常与 add_bos_token 配合使用
  • clean_up_tokenization_spaces:默认 false,表示分词过程中不会额外清理空格
  • decode_with_prefix_space:默认 false,指定解码时不会自动在前面添加空格
  • eos_token:默认 "<s>",指定了结束标记,用于标记序列结束
  • model_max_length:模型最大输入序列长度,配置文件中给了一个极大的数值,表示不对模型输入长度做实际限制,防止自动截断文本
  • pad_token:默认 "<s>",表示使用结束标记作为填充符号
  • sp_model_kwargs:默认 null,表示没有为 sentencepiece 模型提供额外参数
  • tokenizer_class:默认 InternLM2Tokenizer,指向了实际使用的分词类名称,表明这是 InternLM2 的分词器实现
  • unk_token:默认 "<unk>",指定了未知标记,用于处理未识别的输入字符或词汇

这个配置文件为模型加载和分词提供了详细信息,确保在编码和解码过程中特殊标记能被正确处理

我们接着看 tokenizer_config.json 配置文件加载后的处理:

在这里插入图片描述

这里我们从分词器配置文件中提取分词器类信息和自动映射信息,如果配置文件中未提供,则转而使用模型的配置对象获取这些信息,根据这些信息判断是否可以使用本地代码实现,或者需要加载远程代码,并最终确定是否信任远程代码

我们可以看到 has_remote_codetrust_remote_code 变量都为 True,因此我们来看这个分支下执行的内容:

在这里插入图片描述

可以看到分支中调用了 get_class_from_dynamic_module 函数,该函数实现如下:

在这里插入图片描述

这个函数首先解析了一些参数,然后通过 get_cached_module_file 函数下载并缓存远程的 python 模块文件,接着从下载的模块中动态查找并加载目标类,最终返回这个类对象供后续使用,实际上它调用的是 get_class_in_module 函数,其实现如下:

在这里插入图片描述

通过一系列的转换,模块路径会被转换为 "transformers_modules.internlm2_5-1_8b.tokenization_internlm2_fast",接着从本地缓存目录下的对应文件加载模块,最终返回模块中名为 InternLM2TokenizerFast 的类:

在这里插入图片描述

通过这一系列的操作最终我们拿到了 InternLM2TokenizerFast 类,拿到这个类后利用该类的 from_pretrained 方法加载并实例化了分词器,从而完成分词器的初始化过程:

在这里插入图片描述

那现在我们就要来分析 tokenizer_class 类的 from_pretrained 方法,看它具体是如何做的:

在这里插入图片描述

这里是一些前置处理工作,包括从 kwargs 中获取并移除一些辅助参数,构建 user_agent 字典等,接着往下面看:

在这里插入图片描述

这里我们又重新获取加载了 tokenizer_config.json 配置文件来查看是否有特定版本的 tokenizer 文件(例如 fast 版本)需要处理,并更新 vocab_filestokenizer_file 的对应值

我们继续往下面看:

在这里插入图片描述

这里我们根据传入的 vocab_file 字典解析为本地文件路径来加载相应的资源,保证分词器配置与词汇文件都是最新且正确的,我们继续往下走:

在这里插入图片描述

在解析完 vocab_file 字典后,我们会记录未解析的文件并通过日志进行提示,最后我们将所有解析结果和配置文件传递给 _from_pretrained 方法,由其构造出最终的分词器实例

所有我们的最终任务是来分析 _from_pretrained 方法,在这个方法中才真正返回了 tokenizer 分词器的实例,它其实就是不断的套娃:

在这里插入图片描述

这段代码首先判断了是否需要加载慢速分词器,接着读取已保存的初始化配置信息,加载 tokenizer_config.json 文件获取保存的初始化参数,并将其与当前传入的参数进行整合

我们继续往下走:

在这里插入图片描述

这里我们处理了特殊 token 的反序列化,保证所有已保存的 AddedToken 信息都被正确恢复为 AddedToken 实例

在这里插入图片描述

接着会调用类方法 convert_added_tokensinit_kwargs 进行进一步转换,确保所有关于 added_tokens 的字段都被转换为期望的格式(AddedToken 对象),而不是原始的 JSON 字符串或字典

转换前后的 init_kwargs 对比如下所示:

在这里插入图片描述

接着我们就可以利用准备好的初始化参数来创建一个分词器实例了,代码如下:

在这里插入图片描述

这里我们最终会跳转到 InternLM 模型本身自定义的分词器类 InternLM2TokenizerFast 如下所示:

在这里插入图片描述

最终我们拿到的就是通过 tokenizer_config.json 配置文件实例化的 InternLM2TokenizerFast 分词类:

在这里插入图片描述

至此,我们完成了分词器加载的整体流程

说实话,博主也没有理清楚,反正就是通过 transformers 中的一系列方法获取到了创建 tokenizer 实例的参数,然后调用了 InternLM2 的分词器类 InternLM2TokenizerFast 进行了实例化

5. AutoModelForCausalLM.from_pretrained

和分词器加载类似,首先我们通过 AutoConfig.from_pretrained 方法拿到模型的配置参数:

在这里插入图片描述

具体的 AutoConfig.from_pretrained 方法实现我们这边就不分析了,返回的模型参数如下:

在这里插入图片描述

这里就有 internlm2_5-1_8b 模型的各种参数,例如隐藏层 hidden_size 大小为 2048,num_attention_heads 注意力头数为 16 等等

接着调用 model_class.from_pretrained 方法加载并实例化模型:

在这里插入图片描述

from_pretrained 方法中,我们可以看到通过 load_state_dict 加载了 InternLM 模型的权重:

在这里插入图片描述

加载完权重后我们实例化了模型,它是 InternLM2ForCausalLM 类:

在这里插入图片描述

实例化模型完成后通过 _load_pretrained_model 方法加载预训练权重到 model 中:

在这里插入图片描述

最后将 model 返回就完成了模型整个的初始化工作

6. tokenizer

下面我们来看如何利用初始化的 tokenizer 进行分词

在这里插入图片描述

可以看到我们最终调用的是 _call_one 方法,text 是我们的输入 token 即 来到美丽的大自然

_call_one 方法中最终返回的是 self.batch_encode_plus 的结果:

在这里插入图片描述

self.batch_encode_plus 中调用了 self._batch_encode_plus 方法,又是套娃:

在这里插入图片描述

self._batch_encode_plus 方法中我们通过 encode_batch 方法我们将输入的序列转换为了 token:

在这里插入图片描述

不过由于这部分被 Transformers 给封装了,我们看不到内部的实现,不过我们从 encodings 中可以看到输入文本序列被转换为了五个 token,分别是 <s>来到美丽的大自然,其中 <s> 是前面说的特殊标记 token,用来表示开始

Note:这里每个 token 对应的 id 我们其实可以从 InternLM 官方提供的 tokenizer.json 配置文件找到,例如 美丽 这个 token 对应的 id 是 69732

在这里插入图片描述

接着经过一系列的转换处理,最终我们返回的是一个 BatchEncoding 的实例对象:

在这里插入图片描述

在 demo.py 中会将分词转换后的 tensor 放在 GPU 上:

在这里插入图片描述

这就是 tokenizer 的整个过程,不过核心的部分具体是怎么做分词的我们并没有看

7. model.generate

最后我们来看下模型的 forward 过程

在 generate 函数中有相关注释标注了整体的流程步骤:

  • 1. Handle generation_config and kwargs that might update it, and validate the .generate() call
  • 2. Set generation parameters if not already defined
  • 3. Define model inputs
  • 4. Define other model kwargs
  • 5. Prepare input_ids which will be used for auto-regressive generation
  • 6. Prepare max_length depending on other stopping criteria.
  • 7. Prepare the cache.
  • 8. determine generation mode
  • 9. prepare logits processors and stopping criteria
  • 10. go into different generation modes
  • 11. expand input_ids with num_return_sequences additional sequences per batch
  • 12. run sample

前面都是一些参数解析和数据的准备,我们重点来看下步骤 12:

在这里插入图片描述

_sample 方法中,我们将输入准备好后就可以塞到模型中进行推理生成下一个 token,由于 InternLM 是自回归的语言模型,因此是一个 token 接着一个 token 生成的,我们在 _sample 方法中很容易找到模型的 forward 部分:

在这里插入图片描述

接着我们会调用 InternLM 官方的 forward 方法:

在这里插入图片描述

这里其实还没到具体的 forward,我们接着往下走,具体的 forward 过程在 InternLM2Model 类中:

在这里插入图片描述

首先我们对输入的 token 进行了 embedding,将每个 token 转换为了向量,转换完后输入的 inputs_embeds 维度是 1x5x2048,其中 1 代表 batch 维度,5 代表输入的 5 个 token,2048 代表每个 token 用 2048 维的向量表示

接着拿到我们的 mask 矩阵:

在这里插入图片描述

矩阵右上角的元素是一个非常大的负数(-65504),在做 softmax 后这些位置都会变为 0,也就意味着被 mask 掉了

然后就开始遍历模型的 24 层 layers:

在这里插入图片描述

遍历完之后就完成的 24 层 decoder layers 的前向推理,拿到的输出向量维度依旧是 1x5x2048:

在这里插入图片描述

Note:这里的 next_cache 其实就是我们所了解的 KV Cache

OK,拿到推理结果后我们就开始返回到上一层:

在这里插入图片描述

接着会调用 self.output 方法直接用 nn.Linear 做前向计算,从 hidden_size(2048)映射到 vocab_size(92544),形状变成 [1, 5, vocab_size],每个 token 得到一个大小为 vocab_size 的 logits 分布

接着再返回上一层,由于在生成时,我们只关心最后一个预测,因此这里我们只需要拿到模型预测的最后一个位置的 logits 来生成下一个 token 即可:

在这里插入图片描述

所以这里的 next_token_logits 维度是 1x1x92544,经过 logits_processor 函数对原始 logits 处理之后就可以拿到下一个 token 的 score:

在这里插入图片描述

然后,通过采样的方式生成下一个 token,将 logitis 转为概率(softmax),用多项式分布采样一个 token:

在这里插入图片描述

这样,我们就真正的拿到了下一个 token(,),接着将这个 token 拼接到输入序列上重新输入到模型中进行下一次前向推理得到下一个 token:

在这里插入图片描述

如此循环,直到满足生成结束的条件(例如遇到 eos_token 或者达到设置的 max_len 等)

接着将生成的一个个 token 序列返回:

在这里插入图片描述

最后通过 tokenizer 的 decode 函数将 token 转换为文本序列输出:

在这里插入图片描述

这就是 InternLM 推理的大致流程

结语

这篇文章主要分享了如何下载 LLM 的权重以及如何利用 Hugging Face Transformers 进行简单的推理

此外,我们还简单分享了 LLM 在推理时的大致流程,先初始化 tokenizer 分词器和 model 模型,接着将输入的文本序列通过 tokenizer 变为一个个 token,接着就可以送入模型中生成下一个 token,将新生成的 token 与输入的 token 拼接后继续送入模型中生成,如此循环,直到达到结束条件

大家感兴趣的可以看看 UP 的视频讲解,还是非常不错的🤗

下载链接

  • 🤗internlm2_5-1_8b【提取码:1234】

参考

  • 【大模型碎碎念】Transformers&InternLM源码阅读
  • https://github.com/InternLM/InternLM
  • https://chatgpt.com/
  • 如何优雅的下载huggingface-transformers模型
  • 【已解决】vscode如何调试python第三方库

相关文章:

  • 括弧匹配检验(信息学奥赛一本通-1354)
  • Cherry Studio搭建本地知识库,结合DeepSeek实现RAG
  • AM32-MultiRotor-ESC项目固件编译和烧录方法介绍
  • 【Spring】Spring框架介绍
  • C/C++蓝桥杯算法真题打卡(Day7)
  • 生物化学笔记:医学免疫学原理03 超抗原+丝裂原+疫苗佐剂
  • BLE 4.0开发技术全景解析
  • [自动化] 【八爪鱼】使用八爪鱼实现CSDN文章自动阅读脚本
  • (自用)在派上设置自启动时的问题
  • 0323-哈夫曼数、哈夫曼编码
  • proteus仿真stm32f103c8程序运行不起来的问题分析与解决
  • Jboss漏洞再现
  • C51知识点
  • 代码随想录算法训练营第十五天|右旋字符串
  • Linux的文件上传下载的lrzsz库的安装与使用
  • 《当人工智能遇上广域网:跨越地理距离的通信变革》
  • 08_双向循环神经网络
  • React 中useMemo和useCallback Hook 的作用,在什么场景下使用它们?
  • 图书管理系统系统-Java、SpringBoot、Vue和MySQL开发的图书馆管理系统
  • 文心快码 使用体验与介绍
  • 葡萄牙、西班牙突发大范围停电,交通和通信服务受到严重影响
  • 国家市场监管总局:民生无小事,严打民生领域侵权假冒违法行为
  • 中信证券:“国家队”未曾减持ETF,应充分相信国家维稳决心
  • 时隔七年,上合组织国家电影节再度在中国举办
  • 北大学者:过度依赖技术工具可能会削弱人类主动思考的能力
  • 第四届全民阅读大会·阅读权益保障论坛举办