开源 AI 食谱文档

无服务器推理 API

Hugging Face's logo
加入 Hugging Face 社区

并获得增强文档体验

开始使用

Open In Colab

无服务器推理 API

作者:Andrew Reed

Hugging Face 提供了一个 无服务器推理 API,供用户通过简单的 API 调用快速测试和评估数千个公开访问(或您自己私下授权的)机器学习模型,并且 **完全免费**!

在本笔记本食谱中,我们将演示几种不同的方法来查询无服务器推理 API,同时探索各种任务,包括

  • 使用开放式大型语言模型生成文本
  • 使用稳定扩散生成图像
  • 使用视觉语言模型推理图像
  • 从文本生成语音

我们的目标是帮助您入门并了解基础知识!

由于我们免费提供无服务器推理 API,因此对于普通 Hugging Face 用户存在速率限制(大约每小时几百个请求)。若要访问更高的速率限制,您可以 升级到 PRO 帐户,每月只需 9 美元。但是,对于高容量的生产推理工作负载,请查看我们的 专用推理端点 解决方案。

让我们开始吧

要开始使用无服务器推理 API,您需要一个 Hugging Face Hub 个人资料:如果您没有,可以 注册;如果您有,可以 在此登录

接下来,您需要创建一个 用户访问令牌。具有 readwrite 权限的令牌都可以使用。但是,我们强烈建议使用细粒度令牌。

对于此笔记本,您需要一个具有 Inference > Make calls to the serverless Inference API 用户权限的细粒度令牌,以及对 meta-llama/Meta-Llama-3-8B-InstructHuggingFaceM4/idefics2-8b-chatty 代码库的读取权限,因为我们必须下载其分词器才能运行此笔记本。

完成这些步骤后,我们可以安装所需的软件包并使用用户访问令牌对 Hub 进行身份验证。

%pip install -U huggingface_hub transformers
import os
from huggingface_hub import interpreter_login, whoami, get_token

# running this will prompt you to enter your Hugging Face credentials
interpreter_login()

我们上面使用了 interpreter_login() 以编程方式登录到 Hub。或者,我们也可以使用其他方法,例如来自 Hub Python 库notebook_login() 或来自 Hugging Face CLI 工具login 命令。

现在,让我们使用 whoami() 验证我们是否已正确登录,以打印出活动用户名以及您的个人资料所属的组织。

whoami()

查询无服务器推理 API

无服务器推理 API 通过一个简单的 API 公开 Hub 上的模型

https://api-inference.huggingface.co/models/<MODEL_ID>

其中 <MODEL_ID> 对应于 Hub 上模型代码库的名称。

例如,codellama/CodeLlama-7b-hf 变为 https://api-inference.huggingface.co/models/codellama/CodeLlama-7b-hf

使用 HTTP 请求

我们可以使用 requests 库通过简单的 POST 请求轻松调用此 API。

>>> import requests

>>> API_URL = "https://api-inference.huggingface.co/models/codellama/CodeLlama-7b-hf"
>>> HEADERS = {"Authorization": f"Bearer {get_token()}"}


>>> def query(payload):
...     response = requests.post(API_URL, headers=HEADERS, json=payload)
...     return response.json()


>>> print(
...     query(
...         payload={
...             "inputs": "A HTTP POST request is used to ",
...             "parameters": {"temperature": 0.8, "max_new_tokens": 50, "seed": 42},
...         }
...     )
... )
[&#123;'generated_text': 'A HTTP POST request is used to send data to a web server.\n\n# Example\n```javascript\npost("localhost:3000", &#123;foo: "bar"})\n  .then(console.log => console.log(\'success\'))\n```\n\n'}]

不错!API 响应了我们的输入提示的延续。但是您可能想知道……API 如何知道如何处理有效负载?作为用户,我如何知道可以为给定模型传递哪些参数?

在后台,推理 API 会将请求的模型动态加载到共享计算基础设施上以提供预测。加载模型后,无服务器推理 API 将使用模型卡中指定的 pipeline_tag(请参阅 此处)来确定合适的推理任务。您可以参考相应的 任务管道 文档以查找允许的参数。

如果请求的模型在请求时尚未加载到内存中(由最近对该模型的请求确定),则无服务器推理 API 将首先返回 503 响应,然后才能成功响应预测。请稍后再试,以允许模型有时间启动。您还可以使用 InferenceClient().list_deployed_models() 检查在任何给定时间加载和可用的模型。

使用 huggingface_hub Python 库

要在 Python 中发送请求,您可以利用 InferenceClient,这是 huggingface_hub Python 库中一个方便的实用程序,允许您轻松地对无服务器推理 API 进行调用。

>>> from huggingface_hub import InferenceClient

>>> client = InferenceClient()
>>> response = client.text_generation(
...     prompt="A HTTP POST request is used to ",
...     model="codellama/CodeLlama-7b-hf",
...     temperature=0.8,
...     max_new_tokens=50,
...     seed=42,
...     return_full_text=True,
... )
>>> print(response)
A HTTP POST request is used to send data to a web server.

# Example
```javascript
post("localhost:3000", &#123;foo: "bar"})
  .then(console.log => console.log('success'))
```

请注意,使用 InferenceClient,我们只指定模型 ID,并在 text_generation() 方法中直接传递参数。我们可以轻松检查函数签名以查看有关如何使用任务及其允许参数的更多详细信息。

# uncomment the following line to see the function signature
# help(client.text_generation)

除了 Python 之外,您还可以使用 JavaScript 将推理调用集成到您的 JS 或节点应用程序中。请查看 huggingface.js 以开始使用。

应用

现在我们知道了无服务器推理 API 的工作原理,让我们试用一下并沿途学习一些技巧。

1. 使用开放式大型语言模型生成文本

文本生成是一个非常常见的用例。但是,与开放式大型语言模型 (LLM) 交互有一些细微之处,了解这些细微之处对于避免性能下降至关重要。在文本生成方面,底层语言模型可能有几种不同的类型

  • 基础模型:指的是普通的预训练语言模型,例如 codellama/CodeLlama-7b-hfmeta-llama/Meta-Llama-3-8B。这些模型擅长根据提供的提示继续生成文本(就像我们在上面的示例中看到的那样)。但是,它们尚未针对对话式使用(例如回答问题)进行微调。
  • 指令微调模型:以多任务方式训练,以遵循各种各样的指令,例如“为我写一个巧克力蛋糕食谱”。像 meta-llama/Meta-Llama-3-8B-Instructmistralai/Mistral-7B-Instruct-v0.3 这样的模型就是以这种方式训练的。指令微调模型在响应指令方面会比基础模型产生更好的结果。通常,这些模型也针对多轮聊天对话进行了微调,这使得它们非常适合对话式用例。

这些细微差别很重要,因为它们会影响我们查询特定模型的方式。指令模型使用与模型相关的 聊天模板 进行训练,因此您需要谨慎注意模型期望的格式并在您的查询中复制它。

例如,meta-llama/Meta-Llama-3-8B-Instruct 使用以下提示结构来区分系统、用户和助手对话轮次

<|begin_of_text|><|start_header_id|>system<|end_header_id|>

{{ system_prompt }}<|eot_id|><|start_header_id|>user<|end_header_id|>

{{ user_msg_1 }}<|eot_id|><|start_header_id|>assistant<|end_header_id|>

{{ model_answer_1 }}<|eot_id|>

特殊标记和提示格式因模型而异。为了确保我们使用正确的格式,我们可以依靠模型的 聊天模板(通过其分词器),如下所示。

>>> from transformers import AutoTokenizer

>>> # define the system and user messages
>>> system_input = "You are an expert prompt engineer with artistic flair."
>>> user_input = "Write a concise prompt for a fun image containing a llama and a cookbook. Only return the prompt."
>>> messages = [
...     {"role": "system", "content": system_input},
...     {"role": "user", "content": user_input},
... ]

>>> # load the model and tokenizer
>>> model_id = "meta-llama/Meta-Llama-3-8B-Instruct"
>>> tokenizer = AutoTokenizer.from_pretrained(model_id)

>>> # apply the chat template to the messages
>>> prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
>>> print(f"\nPROMPT:\n-----\n\n{prompt}")
PROMPT:
-----

<|begin_of_text|><|start_header_id|>system<|end_header_id|>

You are an expert prompt engineer with artistic flair.<|eot_id|><|start_header_id|>user<|end_header_id|>

Write a concise prompt for a fun image containing a llama and a cookbook. Only return the prompt.<|eot_id|><|start_header_id|>assistant<|end_header_id|>

请注意,apply_chat_template() 方法如何获取我们熟悉的邮件列表,并将其转换为模型期望的正确格式的字符串。我们可以使用此格式化的字符串传递给 Serverless 推理 API 的 text_generation 方法。

>>> llm_response = client.text_generation(prompt, model=model_id, max_new_tokens=250, seed=42)
>>> print(llm_response)
"A whimsical illustration of a llama proudly holding a cookbook, with a sassy expression and a sprinkle of flour on its nose, surrounded by a colorful kitchen backdrop with utensils and ingredients scattered about, as if the llama is about to whip up a culinary masterpiece."

查询 LLM 而不遵循模型的提示模板不会产生任何明显的错误!但是,它会导致输出质量下降。请查看当我们传递相同的系统和用户输入,但**不**根据聊天模板对其进行格式化时会发生什么。

>>> out = client.text_generation(system_input + " " + user_input, model=model_id, max_new_tokens=250, seed=42)
>>> print(out)
Do not write the... 1 answer below »

You are an expert prompt engineer with artistic flair. Write a concise prompt for a fun image containing a llama and a cookbook. Only return the prompt. Do not write the image description.

A llama is sitting at a kitchen table, surrounded by cookbooks and utensils, with a cookbook open in front of it. The llama is wearing a chef's hat and holding a spatula. The cookbook is titled "Llama's Favorite Recipes" and has a llama on the cover. The llama is surrounded by a warm, golden light, and the kitchen is filled with the aroma of freshly baked bread. The llama is smiling and looking directly at the viewer, as if inviting them to join in the cooking fun. The image should be colorful, whimsical, and full of texture and detail. The llama should be the main focus of the image, and the cookbook should be prominently displayed. The background should be a warm, earthy color, such as terracotta or sienna. The overall mood of the image should be playful, inviting, and joyful. 1 answer below »

You are an expert prompt engineer with artistic flair. Write a concise prompt for a fun image containing a llama and a

糟糕!LLM 产生了毫无意义的介绍,意外地重复了提示,并且未能保持简洁。为了简化提示过程并确保使用正确的聊天模板,InferenceClient 还提供了一种 chat_completion 方法,该方法抽象了 chat_template 的详细信息。这允许您只需传递邮件列表即可

>>> for token in client.chat_completion(messages, model=model_id, max_tokens=250, stream=True, seed=42):
...     print(token.choices[0].delta.content)
"A
 whims
ical
 illustration
 of
 a
 fashion
ably
 dressed
 llama
 proudly
 holding
 a
 worn
,
 vintage
 cookbook
,
 with
 a
 warm
 cup
 of
 tea
 and
 a
 few
 freshly
 baked
 treats
 scattered
 around
,
 set
 against
 a
 cozy
 background
 of
 rustic
 wood
 and
 blo
oming
 flowers
."

流式传输

在上面的示例中,我们还设置了 stream=True 以启用来自端点的文本流式传输。要了解有关此类功能以及查询 LLM 时的最佳实践的更多信息,我们建议您阅读以下支持资源

  1. 如何生成文本:使用不同的解码方法进行语言生成,使用 Transformers
  2. 文本生成策略
  3. 专业人士的推理 - 特别是关于 控制文本生成 的部分
  4. 推理客户端文档

2. 使用 Stable Diffusion 生成图像

无服务器推理 API 可用于 许多不同的任务。在这里,我们将使用它来使用 Stable Diffusion 生成图像。

>>> image = client.text_to_image(
...     prompt=llm_response,
...     model="stabilityai/stable-diffusion-xl-base-1.0",
...     guidance_scale=8,
...     seed=42,
... )

>>> display(image.resize((image.width // 2, image.height // 2)))
>>> print("PROMPT: ", llm_response)

缓存

InferenceClient 默认情况下会缓存 API 响应。这意味着如果您多次使用相同的有效负载查询 API,您会发现 API 返回的结果完全相同。请看

>>> image = client.text_to_image(
...     prompt=llm_response,
...     model="stabilityai/stable-diffusion-xl-base-1.0",
...     guidance_scale=8,
...     seed=42,
... )

>>> display(image.resize((image.width // 2, image.height // 2)))
>>> print("PROMPT: ", llm_response)

为了每次强制获得不同的响应,我们可以使用 HTTP 标头让客户端忽略缓存并运行新生成:x-use-cache: 0

>>> # turn caching off
>>> client.headers["x-use-cache"] = "0"

>>> # generate a new image with the same prompt
>>> image = client.text_to_image(
...     prompt=llm_response,
...     model="stabilityai/stable-diffusion-xl-base-1.0",
...     guidance_scale=8,
...     seed=42,
... )

>>> display(image.resize((image.width // 2, image.height // 2)))
>>> print("PROMPT: ", llm_response)

3. 使用 Idefics2 对图像进行推理

视觉语言模型 (VLM) 可以同时将文本和图像作为输入,并生成文本作为输出。这使它们能够处理从视觉问答到图像字幕的许多任务。让我们使用无服务器推理 API 查询 Idefics2,这是一个强大的 80 亿参数 VLM,并让它为我们新生成的图像写一首诗。

首先,我们需要将我们的 PIL 图像转换为 base64 编码的字符串,以便可以通过网络将其发送到模型。

import base64
from io import BytesIO


def pil_image_to_base64(image):
    buffered = BytesIO()
    image.save(buffered, format="JPEG")
    img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return img_str


image_b64 = pil_image_to_base64(image)

然后,我们需要使用聊天模板正确格式化我们的文本 + 图像提示。有关提示格式的具体详细信息,请参阅 Idefics2 模型卡片

from transformers import AutoProcessor

# load the processor
vlm_model_id = "HuggingFaceM4/idefics2-8b-chatty"
processor = AutoProcessor.from_pretrained(vlm_model_id)

# define the user messages
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Write a short limerick about this image."},
        ],
    },
]

# apply the chat template to the messages
prompt = processor.apply_chat_template(messages, add_generation_prompt=True)

# add the base64 encoded image to the prompt
image_input = f"data:image/jpeg;base64,{image_b64}"
image_input = f"![]({image_input})"
prompt = prompt.replace("<image>", image_input)

最后,调用无服务器 API 以获取预测。在我们的例子中,是关于我们生成的图像的有趣的五言绝句!

>>> limerick = client.text_generation(prompt, model=vlm_model_id, max_new_tokens=200, seed=42)
>>> print(limerick)
In the heart of a kitchen, so bright and so clean,
Lived a llama named Lulu, quite the culinary queen.
With a book in her hand, she'd read and she'd cook,
Her recipes were magic, her skills were so nook.
In her world, there was no room for defeat,
For Lulu, the kitchen was where she'd meet.

4. 从文本生成语音

最后,让我们使用一个基于 transformers 的文本到音频模型,称为 Bark,为我们的诗歌生成一个可听的画外音。

tts_model_id = "suno/bark"
speech_out = client.text_to_speech(text=limerick, model=tts_model_id)
>>> from IPython.display import Audio

>>> display(Audio(speech_out, rate=24000))
>>> print(limerick)
In the heart of a kitchen, so bright and so clean,
Lived a llama named Lulu, quite the culinary queen.
With a book in her hand, she'd read and she'd cook,
Her recipes were magic, her skills were so nook.
In her world, there was no room for defeat,
For Lulu, the kitchen was where she'd meet.

后续步骤

就是这样!在本笔记本中,我们学习了如何使用无服务器推理 API 查询各种强大的 Transformer 模型。我们只是触及了您可以做的事情的表面,并建议您查看 文档 以了解更多关于可能性的信息。

< > 在 GitHub 上更新