Stay Hungry,Stay Foolish!

Transformers

Transformers

https://huggingface.co/docs/transformers/main/index

Transformers acts as the model-definition framework for state-of-the-art machine learning models in text, computer vision, audio, video, and multimodal model, for both inference and training.

It centralizes the model definition so that this definition is agreed upon across the ecosystem. transformers is the pivot across frameworks: if a model definition is supported, it will be compatible with the majority of training frameworks (Axolotl, Unsloth, DeepSpeed, FSDP, PyTorch-Lightning, …), inference engines (vLLM, SGLang, TGI, …), and adjacent modeling libraries (llama.cpp, mlx, …) which leverage the model definition from transformers.

We pledge to help support new state-of-the-art models and democratize their usage by having their model definition be simple, customizable, and efficient.

There are over 1M+ Transformers model checkpoints on the Hugging Face Hub you can use.

Explore the Hub today to find a model and use Transformers to help you get started right away.

Explore the Models Timeline to discover the latest text, vision, audio and multimodal model architectures in Transformers.

 

Features

Transformers provides everything you need for inference or training with state-of-the-art pretrained models. Some of the main features include:

  • Pipeline: Simple and optimized inference class for many machine learning tasks like text generation, image segmentation, automatic speech recognition, document question answering, and more.
  • Trainer: A comprehensive trainer that supports features such as mixed precision, torch.compile, and FlashAttention for training and distributed training for PyTorch models.
  • generate: Fast text generation with large language models (LLMs) and vision language models (VLMs), including support for streaming and multiple decoding strategies.

 

Design

Read our Philosophy to learn more about Transformers’ design principles.

Transformers is designed for developers and machine learning engineers and researchers. Its main design principles are:

  1. Fast and easy to use: Every model is implemented from only three main classes (configuration, model, and preprocessor) and can be quickly used for inference or training with Pipeline or Trainer.
  2. Pretrained models: Reduce your carbon footprint, compute cost and time by using a pretrained model instead of training an entirely new one. Each pretrained model is reproduced as closely as possible to the original model and offers state-of-the-art performance.
HuggingFace Expert Acceleration Program

 

Learn

If you’re new to Transformers or want to learn more about transformer models, we recommend starting with the LLM course. This comprehensive course covers everything from the fundamentals of how transformer models work to practical applications across various tasks. You’ll learn the complete workflow, from curating high-quality datasets to fine-tuning large language models and implementing reasoning capabilities. The course contains both theoretical and hands-on exercises to build a solid foundational knowledge of transformer models as you learn.

 

https://huggingface.co/docs/transformers/main/chat_templating

Using apply_chat_template

The input to apply_chat_template should be structured as a list of dictionaries with role and content keys. The role key specifies the speaker, and the content key contains the message. The common roles are:

  • user for messages from the user
  • assistant for messages from the model
  • system for directives on how the model should act (usually placed at the beginning of the chat)

apply_chat_template takes this list and returns a formatted sequence. Set tokenize=True if you want to tokenize the sequence.

 
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceH4/zephyr-7b-beta", device_map="auto", dtype=torch.bfloat16)

messages = [
    {"role": "system", "content": "You are a friendly chatbot who always responds in the style of a pirate",},
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
 ]
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt")
print(tokenizer.decode(tokenized_chat[0]))
 
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>

Pass the tokenized chat to generate() to generate a response.

 
outputs = model.generate(tokenized_chat, max_new_tokens=128) 
print(tokenizer.decode(outputs[0]))
 
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>
Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all.

 

 

https://github.com/fanqingsong/LLM_transformer_helloworld

对话模型推理

# -*- coding: utf-8 -*-
"""
仅此文件允许考生修改:
- 请在下列函数的函数体内完成实现。
- 不要改动函数名与参数签名。
- 你可以新增少量辅助函数。
"""

from typing import List
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM


# ============================================================
# 第一部分:Prompt 定义
# ============================================================
def build_system_prompt() -> str:
    """
    考生实现:定义 system prompt
    - 返回一个 system prompt,要求模型以"[Answer]: xxxx"的格式给出最终数值。
    
    System Prompt 的作用:
    1. 定义模型的身份和角色(数学助手)
    2. 指导模型的推理过程(逐步分析、解题思路)
    3. 规范模型的输出格式([Answer]: 数值)
    
    为什么要用 [Answer]: 格式?
    - 便于评测程序从模型输出中提取正确答案
    - 统一答案格式,避免模型输出过多解释性文字
    - 符合测试数据的标准格式要求
    """
    # ======== 考生实现区域(可修改) ========
    
    # System Prompt 定义:指导模型如何回答数学问题
    # 关键点:必须包含 [Answer]: 格式的要求,这是评测程序提取答案的标准
    system_prompt = """你是一个数学助手,擅长解决各种数学问题。请仔细分析问题,逐步推理,并最终以 [Answer]: 数值 的格式给出答案。

要求:
1. 仔细阅读题目,理解题意
2. 逐步分析解题思路
3. 进行必要的计算
4. 最终答案必须以 [Answer]: 数值 的格式给出

请开始解题。"""
    
    return system_prompt
    
    # ======== 考生实现区域(可修改) ========


# ============================================================
# 第二部分:模板拼装
# ============================================================
def apply_chat_template_single(
    tokenizer: AutoTokenizer,
    system_prompt: str,
    problem: str,
) -> str:
    """
    考生实现:将单个问题转换为模型输入文本
    - 使用 tokenizer.apply_chat_template 构造对话
    - 返回拼装好的文本字符串
    
    参数说明:
        tokenizer: Qwen3 模型的 tokenizer,包含特殊 token 和模板定义
        system_prompt: 系统提示词,定义模型角色和输出格式
        problem: 用户问题(如 "12 + 35")
    
    返回值:
        完整格式化后的对话文本,包含 system、user、assistant 标记
    
    Chat Template 的作用:
        transformers 库的 tokenizer.apply_chat_template 会根据模型类型自动构造
        符合该模型预期的对话格式。对于 Qwen 模型,它会把 messages 列表转换为:
        <|system|>你是一个数学助手...<|user|>12 + 35<|assistant|>
        这样的格式。
    """
    # ======== 考生实现区域(可修改) ========
    
    # 构造消息列表:包含系统提示和用户问题
    # 消息格式:每个消息是一个字典,包含 role(角色)和 content(内容)
    # - "system": 定义模型行为
    # - "user": 用户输入的问题
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": problem},
    ]
    
    # 应用聊天模板,将消息列表转换为模型可理解的文本格式
    rendered = tokenizer.apply_chat_template(
        messages,                      # 消息列表
        tokenize=False,                # 不进行 tokenize,返回原始字符串而不是 token IDs
                                      # 这样可以在调试时看到完整的文本内容
        add_generation_prompt=True,    # 添加 <|assistant|> 标记,引导模型生成回复
                                      # 如果没有这个标记,模型不知道要在哪里开始生成
        enable_thinking=True,          # 启用思考标签支持
                                      # 允许模型输出 <think>...</think>
                                      # 模型会在 <> 标签内进行推理,评测程序会自动移除这部分内容
    )
    return rendered
    
    # ======== 考生实现区域(可修改) ========


# ============================================================
# 第三部分:核心推理实现
# ============================================================
def generate_single(
    model: AutoModelForCausalLM,
    tokenizer: AutoTokenizer,
    rendered_text: str,
    max_new_tokens: int,
    do_sample: bool,
) -> torch.Tensor:
    """
    考生实现:单条推理
    - 将文本 tokenize 后送入模型生成
    - 返回包含输入和输出的完整 token 序列
    
    参数说明:
        model: Qwen3 预训练模型,用于文本生成
        tokenizer: 用于将文本转换为 token IDs
        rendered_text: 已格式化的完整对话文本(包含 system、user、assistant 标记)
        max_new_tokens: 生成的最大新 token 数量(不包括输入长度)
        do_sample: 是否使用采样(True=随机采样,False=贪心解码)
    
    返回值:
        torch.Tensor,形状为 [1, seq_len],包含输入+新生成的完整序列
    
    注意事项:
        1. 返回的是包含输入的完整序列(evaluate.py 会提取新生成的部分)
        2. 使用 .to(model.device) 确保输入在正确的设备上(CPU/GPU/NPU)
        3. 使用 model.generate() 的默认参数,模型会自动处理特殊 token
    """
    # ======== 考生实现区域(可修改) ========
    
    # 步骤 1:将文本编码为 token IDs
    # - tokenizer.encode() 将字符串转换为整数列表
    # - return_tensors="pt" 返回 PyTorch 张量
    # - .to(model.device) 将张量移动到模型所在的设备(CPU/GPU/NPU)
    inputs = tokenizer.encode(rendered_text, return_tensors="pt").to(model.device)
    
    # 步骤 2:使用模型生成文本
    # - model.generate() 会自动生成新的 token
    # - 返回的 outputs 包含完整的序列:输入 + 新生成的 token
    # - 评测程序会从 outputs 中提取新生成的部分
    outputs = model.generate(
        inputs,                        # 输入 token IDs
        max_new_tokens=max_new_tokens, # 最多生成多少个新 token
        do_sample=do_sample,          # 采样模式:True=随机采样(更灵活),False=贪心(更确定)
    )
    return outputs
    # ======== 考生实现区域(可修改) ========


def generate_batch(
    model: AutoModelForCausalLM,
    tokenizer: AutoTokenizer,
    rendered_texts: List[str],
    max_new_tokens: int,
    do_sample: bool,
) -> List[torch.Tensor]:
    """
    考生实现:批量推理
    - 一次处理多个问题,提高效率
    - 返回所有批次的输出列表
    
    参数说明:
        model: Qwen3 预训练模型
        tokenizer: 用于编码文本
        rendered_texts: 多个已格式化的对话文本列表
        max_new_tokens: 生成的最大新 token 数量
        do_sample: 是否使用采样
    
    返回值:
        List[torch.Tensor],每个元素是一个批次的输出
        批次形状为 [batch_size, seq_len]
    
    批量处理的优势:
        1. 并行处理:GPU 可以同时处理多条数据
        2. 减少数据传输:一次 GPU 调用处理多条
        3. 提高吞吐量:相比逐条处理能获得 3+ 倍加速
    
    实现要点:
        1. 使用循环分批处理,避免一次性处理过多数据导致内存溢出
        2. 使用 padding=True 确保同一批次内序列长度一致
        3. 使用 attention_mask 告诉模型哪些 token 是 padding,哪些是真实内容
        4. 使用 torch.no_grad() 节省显存(推理时不需要梯度)
    """
    # ======== 考生实现区域(可修改) ========
    
    all_outputs = []  # 存储所有批次的输出
    batch_size: int = 4  # 批次大小:一次处理 4 条数据
                        # 可以调整:太小效率低,太大可能内存不足

    # 循环处理:每次处理一个批次
    # range(0, len(rendered_texts), batch_size) 生成:0, 4, 8, 12, ...
    for i in range(0, len(rendered_texts), batch_size):
        # 提取当前批次:rendered_texts[i:i+batch_size]
        # 例如:如果 i=0, batch_size=4,则提取第 0, 1, 2, 3 条
        batch_texts = rendered_texts[i:i + batch_size]
        
        # 步骤 1:对批次进行编码和填充
        # tokenizer() 可以将多条文本同时编码,并自动填充到相同长度
        # - batch_texts: 多条文本(列表)
        # - padding=True: 短序列会填充到和最长序列一样长
        # - truncation=True: 超长序列会被截断
        # - 返回的 inputs 包含 input_ids 和 attention_mask
        inputs = tokenizer(
            batch_texts,               # 多条文本(如 ["问题1", "问题2", "问题3", "问题4"])
            return_tensors="pt",        # 返回 PyTorch 张量
            padding=True,              # 自动填充到相同长度
            truncation=True            # 超长序列截断(防止溢出)
        ).to(model.device)             # 移动到模型设备
        
        # 步骤 2:批量生成文本
        # 使用 torch.no_grad() 禁用梯度计算,节省显存并提高速度
        with torch.no_grad():
            outputs = model.generate(
                inputs.input_ids,        # 编码后的 token IDs,形状 [batch_size, seq_len]
                attention_mask=inputs.attention_mask,  # 注意力掩码,标记哪些是真实内容(1),哪些是填充(0)
                max_new_tokens=max_new_tokens,  # 最多生成多少个新 token
                do_sample=do_sample,     # 采样模式
                pad_token_id=tokenizer.eos_token_id  # 指定填充 token 的 ID
                # 注意:这里没有使用 pad_token_id=tokenizer.pad_token_id
                # 因为 Qwen 模型可能没有 pad_token,使用 eos_token_id 作为替代
            )
        
        # 将当前批次的输出添加到总结果中
        all_outputs.append(outputs)

    # 返回所有批次的输出列表
    # 例如:如果 10 条数据分成 3 批,则返回 [batch1_output, batch2_output, batch3_output]
    # evaluate.py 会将这些批次的结果合并到一起
    return all_outputs
    
    # ======== 考生实现区域(可修改) ========

 

嵌入模型

# -*- coding: utf-8 -*-
"""
仅此文件允许考生修改:
- 请在下列函数的函数体内完成实现。
- 不要改动函数名与参数签名。
- 你可以新增少量辅助函数。
"""

import torch
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel


# ============================================================
# 相似度计算函数
# ============================================================
def student_compute_similarity(text1: str, text2: str, model: AutoModel, tokenizer: AutoTokenizer) -> float:
    """
    考生实现:计算两个文本之间的相似度
    
    参数:
        text1: 第一个文本字符串(如 "12 + 35")
        text2: 第二个文本字符串(如 "35 + 12")
        model: 预加载的 Qwen3-Embedding 模型(评测程序提供)
        tokenizer: 预加载的 tokenizer(评测程序提供)
    
    返回:
        相似度值(0.0 到 1.0 之间的浮点数)
        1.0 表示完全相同,0.0 表示完全不同
    
    要求:
        - 使用传入的 model 和 tokenizer,不要自己加载模型
        - 实现 last-token pooling(取最后一个 token 的隐藏状态作为句子表示)
        - 必须使用左侧 padding(padding_side="left")
        - L2 归一化(将向量标准化为单位向量)
        - 计算余弦相似度(归一化向量的点积)
        - 不得使用 sentence_transformers
    
    相似度计算原理:
        1. 将文本编码为向量(embedding)
        2. Last-token pooling:取最后一个 token 的隐藏状态作为句子表示
        3. L2 归一化:将向量标准化为单位向量
        4. 余弦相似度:计算两个归一化向量的点积(cos(θ) 的值域为 [-1, 1])
        
        为什么使用 last-token pooling?
        - Embedding 模型在训练时,最后一个 token 包含了整个句子的语义信息
        - 相比平均 pooling 或 CLS token,last-token 能更好地捕捉句子级语义
    """
    # ======== 考生实现区域(可修改) ========
    
    # 步骤 1:获取模型所在的设备(CPU/GPU/NPU)
    # next(model.parameters()) 获取模型的第一个参数,.device 获取其设备
    # 这样可以确保输入张量与模型在同一设备上
    device = next(model.parameters()).device
    
    # 步骤 2:准备输入文本列表
    # 将两个文本放入列表,以便批量处理
    texts = [text1, text2]
    
    # 步骤 3:使用 tokenizer 编码文本
    # padding=True: 将短序列填充到最长序列的长度
    # truncation=True: 超长序列截断到 max_length
    # max_length=512: 最大序列长度(典型的 BERT 等模型长度)
    # return_tensors="pt": 返回 PyTorch 张量
    # padding_side="left": 在左侧填充(重要!)
    #   为什么使用左侧 padding?
    #   - 因为使用 last-token pooling,我们需要保证最后一个 token 是真实的文本 token
    #   - 如果在右侧 padding,最后一个 token 会是填充 token,失去语义信息
    inputs = tokenizer(
        texts,                      # 文本列表:["12 + 35", "35 + 12"]
        padding=True,              # 自动填充到相同长度
        truncation=True,            # 超长序列截断
        max_length=512,            # 最大长度
        return_tensors="pt",        # 返回 PyTorch 张量
        padding_side="left"         # 关键:左侧填充
    ).to(device)                    # 移动到模型设备
    
    # 步骤 4:获取模型输出的嵌入向量
    # 使用 torch.no_grad() 禁用梯度计算,节省显存并提高速度
    with torch.no_grad():
        # 模型前向传播:输入 token IDs,输出隐藏状态
        # outputs.last_hidden_state 形状: [batch_size=2, seq_len, hidden_dim]
        outputs = model(**inputs)
        
        # Last-token pooling:取最后一个 token 的隐藏状态作为句子表示
        # last_hidden_state 形状: [2, seq_len, hidden_dim]
        # 例如:[[[token1], [token2], [token3]], [[token4], [token5], [token6]]]
        # [:, -1, :] 表示取每一行的最后一个 token
        # embeddings 形状: [2, hidden_dim]
        # 例如:[[token3], [token6]]
        last_hidden_state = outputs.last_hidden_state
        embeddings = last_hidden_state[:, -1, :]  # 索引 -1 表示最后一个元素
        
        # 步骤 5:L2 归一化
        # 将向量标准化为单位向量(长度为 1)
        # 公式:v_normalized = v / ||v||
        # F.normalize(..., p=2, dim=1):
        #   - p=2: 使用 L2 范数(欧氏距离)
        #   - dim=1: 在 hidden_dim 维度上归一化
        # 归一化后的向量满足:||v|| = 1
        # embeddings 形状保持不变: [2, hidden_dim]
        embeddings = F.normalize(embeddings, p=2, dim=1)
        
        # 步骤 6:计算余弦相似度
        # 对于归一化的向量 a, b,余弦相似度 = a · b(点积)
        # 如果 a 和 b 都是单位向量,则 cos(θ) = a · b
        # - 如果 a 和 b 完全相同:a · b = 1
        # - 如果 a 和 b 垂直:a · b = 0
        # - 如果 a 和 b 相反:a · b = -1
        # torch.dot(a, b) 计算向量点积
        # .item() 将标量张量转换为 Python float
        # embeddings[0] 是 text1 的嵌入,embeddings[1] 是 text2 的嵌入
        similarity = torch.dot(embeddings[0], embeddings[1]).item()
        # similarity 的范围:[0, 1],因为所有向量都是正方向(经过归一化后的嵌入向量)
    
    return similarity
    
    # ======== 考生实现区域(可修改) ========


def compute_similarity(text1: str, text2: str, model: AutoModel, tokenizer: AutoTokenizer) -> float:
    """
    评测程序调用的接口函数
    """
    return student_compute_similarity(text1, text2, model, tokenizer)

 

posted @ 2025-10-29 15:21  lightsong  阅读(13)  评论(0)    收藏  举报
千山鸟飞绝,万径人踪灭