AWS Trainium 和 Inferentia 文档

在 AWS Inferentia 上使用 Optimum Neuron 的 Sentence Transformers

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

在 AWS Inferentia 上使用 Optimum Neuron 的 Sentence Transformers

文本模型

该教程有一个 notebook 版本,请点击这里

本指南解释了如何在 AWS Inferentia2 上使用 Optimum Neuron 编译、加载和使用 Sentence Transformers (SBERT) 模型,从而实现高效的嵌入计算。Sentence Transformers 是用于生成句子嵌入的强大模型。您可以使用 Sentence Transformers 计算 100 多种语言的句子/文本嵌入。然后可以比较这些嵌入,例如使用余弦相似度来查找含义相似的句子。这对于语义文本相似度、语义搜索或释义挖掘非常有用。

将 Sentence Transformers 模型转换为 AWS Inferentia2

首先,您需要将您的 Sentence Transformers 模型转换为与 AWS Inferentia2 兼容的格式。您可以使用 optimum-cliNeuronModelForSentenceTransformers 类,通过 Optimum Neuron 编译 Sentence Transformers 模型。下面您将找到两种方法的示例。我们必须确保已安装 sentence-transformers。这仅在导出模型时需要。

pip install sentence-transformers

在这里,我们将使用 NeuronModelForSentenceTransformers,它可以用于将任何 Sentence Transformers 模型转换为与 AWS Inferentia2 兼容的格式,或加载已转换的模型。当使用 NeuronModelForSentenceTransformers 导出模型时,您需要设置 export=True 并定义输入形状和批次大小。输入形状由 sequence_length 定义,批次大小由 batch_size 定义。

from optimum.neuron import NeuronModelForSentenceTransformers

# Sentence Transformers model from HuggingFace
model_id = "BAAI/bge-small-en-v1.5"
input_shapes = {"batch_size": 1, "sequence_length": 384}  # mandatory shapes

# Load Transformers model and export it to AWS Inferentia2
model = NeuronModelForSentenceTransformers.from_pretrained(model_id, export=True, **input_shapes)

# Save model to disk
model.save_pretrained("bge_emb_inf2/")

在这里,我们将使用 optimum-cli 来转换模型。与 NeuronModelForSentenceTransformers 类似,我们需要定义输入形状和批次大小。输入形状由 sequence_length 定义,批次大小由 batch_size 定义。optimum-cli 将自动将模型转换为与 AWS Inferentia2 兼容的格式,并将其保存到指定的输出目录。

optimum-cli export neuron -m BAAI/bge-small-en-v1.5 --sequence_length 384 --batch_size 1 --task feature-extraction bge_emb_inf2/

加载已编译的 Sentence Transformers 模型并运行推理

一旦我们有了编译好的 Sentence Transformers 模型(我们自己导出或在 Hugging Face Hub 上可用),我们就可以加载它并运行推理。为了加载模型,我们可以使用 NeuronModelForSentenceTransformers 类,它是 SentenceTransformer 类的抽象层。`NeuronModelForSentenceTransformers` 类将自动将输入填充到指定的 `sequence_length` 并在 AWS Inferentia2 上运行推理。

from optimum.neuron import NeuronModelForSentenceTransformers
from transformers import AutoTokenizer

model_id_or_path = "bge_emb_inf2/"
tokenizer_id = "BAAI/bge-small-en-v1.5"

# Load model and tokenizer
model = NeuronModelForSentenceTransformers.from_pretrained(model_id_or_path)
tokenizer = AutoTokenizer.from_pretrained(tokenizer_id)

# Run inference
prompt = "I like to eat apples"
encoded_input = tokenizer(prompt, return_tensors='pt')
outputs = model(**encoded_input)

token_embeddings = outputs.token_embeddings
sentence_embedding = outputs.sentence_embedding

print(f"token embeddings: {token_embeddings.shape}") # torch.Size([1, 7, 384])
print(f"sentence_embedding: {sentence_embedding.shape}") # torch.Size([1, 384])

生产环境使用

为了在生产环境中部署这些模型,请参考 Amazon SageMaker 博客

CLIP

为 AWS Inferentia2 编译 CLIP

您可以使用 optimum-cliNeuronModelForSentenceTransformers 类,通过 Optimum Neuron 编译 CLIP 模型。选择您喜欢的一种方法

  • 使用 Optimum CLI
optimum-cli export neuron -m sentence-transformers/clip-ViT-B-32 --sequence_length 64 --text_batch_size 3 --image_batch_size 1 --num_channels 3 --height 224 --width 224 --task feature-extraction --subfolder 0_CLIPModel clip_emb/
  • 使用 NeuronModelForSentenceTransformers
from optimum.neuron import NeuronModelForSentenceTransformers

model_id = "sentence-transformers/clip-ViT-B-32"

# configs for compiling model
input_shapes = {
    "num_channels": 3,
    "height": 224,
    "width": 224,
    "text_batch_size": 3,
    "image_batch_size": 1,
    "sequence_length": 64,
}

emb_model = NeuronModelForSentenceTransformers.from_pretrained(
    model_id, subfolder="0_CLIPModel", export=True, library_name="sentence_transformers", dynamic_batch_size=False, **input_shapes
)

# Save locally or upload to the HuggingFace Hub
save_directory = "clip_emb/"
emb_model.save_pretrained(save_directory)

加载已编译的 Sentence Transformers 模型并运行推理

from PIL import Image
from sentence_transformers import util
from transformers import CLIPProcessor

from optimum.neuron import NeuronModelForSentenceTransformers

save_directory = "clip_emb"
emb_model = NeuronModelForSentenceTransformers.from_pretrained(save_directory)

processor = CLIPProcessor.from_pretrained(save_directory)
inputs = processor(
    text=["Two dogs in the snow", 'A cat on a table', 'A picture of London at night'], images=Image.open("two_dogs_in_snow.jpg"), return_tensors="pt", padding=True
)  

outputs = emb_model(**inputs)


# Compute cosine similarities
cos_scores = util.cos_sim(outputs.image_embeds, outputs.text_embeds)
print(cos_scores)

# tensor([[0.3072, 0.1016, 0.1095]])

注意事项

由于启用了动态批处理的已编译模型仅接受具有相同批次大小的输入张量,如果输入文本和图像具有不同的批次大小,我们无法设置 `dynamic_batch_size=True`。并且由于 `NeuronModelForSentenceTransformers` 类将输入填充到编译期间使用的批次大小(`text_batch_size` 和 `image_batch_size`),为了灵活性,您可以在编译期间使用相对较大的批次大小,但会牺牲计算量。

例如,如果您想编码 3 个、4 个或 5 个文本和 1 个图像,您可以在编译期间设置 `text_batch_size = 5 = max(3, 4, 5)` 和 `image_batch_size = 1`。