自然语言处理

概述

参考:

Natural Language Processing(自然语言处理,简称 NLP) 是语言学、计算机科学和人工智能的跨学科领域,主要关注计算机与人类语言之间的交互,特别是如何编写程序来处理和分析大量的自然语言数据。目标是让计算机能够“理解”文档的内容,包括其中的语言上下文细微差别。技术可以准确提取文档中包含的信息和见解,以及对文档本身进行分类和组织。

语言模型

参考:

Language model(语言模型) 是单词序列的概率分布。

通过语言模型,才可以实现自然语言处理。NLP 程序都会使用语言模型,我们将自然语言作为输入,传递给语言模型,语言模型将会预测其将要输出的每一个单词的出现概率,然后逐一输出这些单词。

想要训练出来一个良好的语言模型,通常会需要类似 Transformers 这种机器学习模型。

Large language model

Large language model(大语言模型,简称 LLM) 是由具有许多参数(通常为数十亿或更多权重)的神经网络组成的语言模型,使用自我监督学习对大量未标记文本进行训练。LLM 在 2018 年左右出现,并在各种任务中表现出色。这已经将自然语言处理研究的重点从之前为特定任务训练专门的监督模型的范式转移了。

我们经常看到 LLM 实现的模型后面有 XB 的样式,其中 B 表示 Billions(十亿),这个 XB 指的就是参数的数量。比如 6B 表示 60 亿参数。

常见模型

参考:

我们常见的语言模型在现阶段(2023.5)可以简单分为如下几大类

  • BERT 系
    • 类似完形填空,联系上下文直接给出空中的内容
  • GPT 系
    • 一字一字推测的自回归模型。有 a 推测 b,然后根据 ab 推测 c,根据 abc 推测 d,以此类推
  • 其他系

Bidirectional Encoder Representations from Transformers(来自 Transformers 的双向编码器表示,简称 BERT)

Generative Pre-trained Transformer(生成式预训练 Transformer,简称 GPT)

General Language Model(通用语言模型,简称 GLM) # 清华开源

Large Language Model Meta AI(简称 LLaMA)

MOSS # 复旦开源,已停止更新

模型的架构

一个可以提供 NLP 能力的 Model service(模型服务),通常由下面几部分组成:

  • 权重文件 # 这就是 Model,也可以称为”模型文件“。通常名为 model.safetensors 或 pytorch_model.bin。那些动辄几个 G 的文件就是这个权重文件
  • 配置文件 # 加载 分词器、权重 时的依据。是一组文件
  • 处理代码 # 处理用户输入,处理模型输出。总结一下:所有除了 ”模型“ 本身这个黑箱计算之外的工作,都需要代码。

700

[!Note] 我们在 Hugging Face 的模型仓库中,通常可以看到除了代码之外的其他所有文件。至于代码,其实就是 transformers 依赖库。

还有人用 Model Packeage, Model Artifact, Model Repository, etc. 称呼这一整套完整的内容。

关联文件与配置

下面是这些文件的一般作用:

权重相关文件

  • model-safetensors # 模型的权重文件。也有可能名为 pytorch_model.bin。那些动辄几个 G 的文件就是这个权重文件
  • config.json # 模型结构配置。例如层数、隐藏层大小、注意力头数及 Transformers API 的调用关系等,用于加载、配置和使用预训练模型。
    • configuration_chatglm.py # 是 config.json 文件的类表现形式,模型配置的 Python 类代码文件,定义了用于配置模型的 ChatGLMConfig 类。
  • generation_config.json # 模型参数的默认值

分词器相关文件

  • vocab.json # 词表文件。包含了 TokenID 到 Token字符串 的映射关系,以及其他与 token 相关的信息。
  • merges.txt # 词表文件。包含了 Token 合并的规则,用于将子 Token 合并成一个 Token。
  • Tips: merges.txt 决定"怎么切",vocab.json 决定"切完之后每个 Token 叫什么 ID"。
  • tokenizer.json # 可以理解为 vocab.json + merges.txt + 其他数据的合并版。把 词表、合并规则、特殊 Token、etc. 所有数据打包在一起。
  • tokenizer_config.json # 分词器的"行为配置文件",不存数据,存的是"怎么用这个分词器"的元信息。e.g. 是否添加特殊 Token、是否小写、etc. 。

消息数据结构

发送给模型的消息通常包含两部分

  • conversation # 对话,i.e. 人们日常交流以及代码里常用 messages
  • tools # 工具。LLM 会根据工具信息,以及 conversation 中的内容判断是否需要使用工具。

这几部分由分词器进行处理

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
conversation=[{"role": "user", "content": prompt}]
tools=
# 其他代码
text = tokenizer.apply_chat_template(
    conversation,
    tools=tools,
    # 其他参数
)

Conversation

常见的 messages。每一次对话都是一个元素。下面是一个只有用户输入 ”你好“ 的 messages

[
    {"role": "user", "content": "北京今天的天气如何"},
]

如果有 图片、音视频、etc. 甚至 工具的调用结果、etc. ,还可以使用其他 role,并指定路径,由分词器读取后,转换为张量

Tools

参考:

一个工具的典型结构示例如下:

tools := [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,例如:北京",
                    }
                },
                "required": ["city"],
            },
        },
    }
]

[!Attention] 模型本身无法直接调用工具

模型会响应结构化的信息,由 tool_call 包裹,就像这样: <tool_call>格式化的工具调用参数</tool_call>

我们需要编写程序处理这些信息,由程序去执行具体的工具。

通常,程序应该工具调用应该放在 "role":"assistant" 的 messages 中,使用 tool_calls

{
  "role": "assistant",
  "content": "获取天气",
  "tool_calls": [
    {
      "id": "call_00_tO9WlaA7bYyLG89jjiVV4rwe",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{\"name\": \"get_weather\", \"arguments\": {\"city\": \"北京\"}}"
      }
    }
  ]
}

工具的执行结果应该放在 "role":"tool"。之后,程序将这些 messages 交给模型进行分析。继续执行后续任务