推理提供商文档

如何在 Hub 上注册为推理服务提供商?

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

如何在 Hub 上注册为推理服务提供商?

-想在 Hugging Face Hub 上列出您的推理服务提供商?请与我们联系!

请在社交网络上或此处在 Hub 上联系我们。

本指南详细介绍了在 Hub 上注册为推理服务提供商的步骤,并提供了实施指导。

  1. 实施标准任务 API - 遵循我们的任务 API 架构以实现兼容性(请参阅先决条件)。
  2. 提交 JS 客户端集成 PR - 将您的提供商添加到huggingface.js(请参阅JS 客户端集成)。
  3. 注册模型映射 - 使用我们的模型映射 API 将您的模型链接到 Hub 模型(请参阅模型映射 API)。
  4. 实施计费端点 - 提供用于计费的 API(请参阅计费)。
  5. 提交 Python 客户端集成 PR - 将您的提供商添加到huggingface_hub(请参阅Python 客户端集成)。
  6. 在服务器端注册您的提供商并提供图标 - 联系我们以在服务器端添加您的提供商并提供您的 SVG 图标。
  7. 在您这边创建文档 - 添加文档并在您这边进行大量沟通。
  8. 添加文档页面 - 在此存储库 (huggingface/hub-docs) 中打开一个 Pull Request,以在文档中添加提供商特定的页面。
  9. 分享分享分享 多做宣传,让您的集成尽可能成功!

1. 先决条件

如果您的实现严格遵循 LLM 和 VLM 的 OpenAI API,您可能可以跳过本节大部分内容。在这种情况下,只需在huggingface.js上打开一个 PR 进行注册即可。

理解集成的第一步是查看位于huggingface.js仓库中的 JS 推理客户端。

这是驱动模型页面上推理小部件的客户端,也是下游(用于 Python SDK,用于生成代码片段等)的蓝图实现。

什么是任务

您将看到推理方法(`textToImage`、`chatCompletion`等)的名称与任务名称非常相似。任务,在 HF 生态系统中也称为 `pipeline_tag`,是模型的类型(基本上是模型具有的输入和输出类型),例如“text-generation”或“text-to-image”。它在模型页面上显眼地标示着,在这里:

所有可能任务的列表可以在https://huggingface.co/tasks找到,JS 方法名称列表则记录在https://github.com/huggingface/huggingface.js/tree/main/packages/inference的 README 中。

请注意,`chatCompletion` 是一个例外,因为它本身不是 `pipeline_tag`。相反,它包含 `pipeline_tag="text-generation"` 或 `pipeline_tag="image-text-to-text"` 并被标记为“对话型”的模型。

任务 API 架构

对于每种任务类型,我们强制执行 API 架构,以便最终用户更容易互换使用不同的模型。为了兼容,您的第三方 API 必须遵循我们期望 HF 模型页面上每种管道任务类型的“标准”API 形状。

对于 LLM 来说,这不是问题,因为大家都已经趋同于 OpenAI API,但对于“文本到图像”或“自动语音识别”等其他任务来说,可能更为棘手,因为没有标准的 API。

例如,您可以在此处找到文本转语音的预期架构:https://github.com/huggingface/huggingface.js/packages/src/tasks/text-to-speech/spec/input.json#L4,其他受支持的任务也类似。如果您的 API 在给定任务上与 HF 不同,这不是问题:您可以调整 `huggingface.js` 中的代码以能够调用您的模型,即提供某种参数名称和输出名称的“转换”。但是,API 规范不应是模型特定的,而应是任务特定的。运行 JS 代码并添加一些测试以确保它运行良好。我们可以帮助完成此步骤!

2. JS 客户端集成

在进行下一步之前,请确保您已实施必要的代码以与 JS 客户端集成并彻底测试您的实现。以下是需要遵循的步骤:

实现提供商帮助器 (JS)

在 `packages/inference/src/providers/{provider_name}.ts` 下创建一个新文件,并复制粘贴以下代码片段。

import { TaskProviderHelper } from "./providerHelper";

export class MyNewProviderTask extends TaskProviderHelper {

	constructor() {
		super("your-provider-name", "your-api-base-url", "task-name");
	}

    override prepareHeaders(params: HeaderParams, binary: boolean): Record<string, string> {
        // Override the headers to use for the request.
        return super.prepareHeaders(params, binary);
    }

	makeRoute(params: UrlParams): string {
        // Return the route to use for the request. e.g. /v1/chat/completions route is commonly use for chat completion.
		throw new Error("Needs to be implemented");
	}

	preparePayload(params: BodyParams): Record<string, unknown> {
        // Return the payload to use for the request, as a dict.
		throw new Error("Needs to be implemented");
	}

	getResponse(response: unknown, outputType?: "url" | "blob"): string | Promise<Blob>{
		// Return the response in the expected format.
        throw new Error("Needs to be implemented");
    }
}

实现需要自定义处理的方法。查看基础实现以检查默认行为。如果您不需要覆盖某个方法,只需将其删除即可。您必须至少定义 `makeRoute`、`preparePayload` 和 `getResponse`。

如果提供商支持需要不同实现方式的多个任务,请为每个任务创建专门的子类,遵循现有提供商实现中使用的模式,例如Together AI 提供商实现

对于文本生成和对话任务,您可以分别继承 `BaseTextGenerationTask` 和 `BaseConversationalTask`(在providerHelper.ts中定义),并在需要时覆盖这些方法。示例可以在CerebrasFireworks提供商实现中找到。

注册提供商

前往packages/inference/src/lib/getProviderHelper.ts并将您的提供商添加到 `PROVIDERS`。您还需要将您的提供商添加到packages/inference/src/types.ts中的 `INFERENCE_PROVIDERS` 列表。请尽量遵循字母顺序。

更新 `packages/inference` 目录中的README.md,将您的提供商包含在支持的提供商列表和支持的模型链接列表中。

3. 模型映射 API

恭喜!您现在拥有一个 JS 实现,可以成功地在您的基础设施上进行推理调用!是时候与 Hub 集成了!

第一步是使用模型映射 API 注册支持的 HF 模型。

要继续此步骤,我们必须在服务器端启用您的帐户。请确保您的公司在 Hub 上有一个组织,并将其升级为团队或企业计划。

注册映射项

POST /api/partners/{provider}/models

创建一个新的映射项,其内容(JSON 编码)如下:

{
    "task": "WidgetType", // required
    "hfModel": "string", // required: the name of the model on HF: namespace/model-name
    "providerModel": "string", // required: the partner's "model id" i.e. id on your side
    "status": "live" | "staging" // Optional: defaults to "staging". "staging" models are only available to members of the partner's org, then you switch them to "live" when they're ready to go live
}
  • `task`,在 HF 生态系统中也称为 `pipeline_tag`,是模型类型/API 类型(示例:“text-to-image”、“text-generation”,但对于聊天模型,您应该使用“conversational”)
  • `hfModel` 是 Hub 端的模型 ID。
  • `providerModel` 是您这边的模型 ID(可以相同也可以不同。通常,我们鼓励您也使用 HF 模型 ID,但这取决于您)。

此路由的输出是一个映射 ID,您以后可以使用它来更新映射的状态或删除它。

身份验证

您需要拥有*提供商* Hub 组织(例如 TogetherAI 的https://huggingface.co/togethercomputer)的**写入**权限才能访问此端点。

验证

该端点验证:

  • `hfModel` 确实是 `pipeline_tag == task` 或者 `task` 是“对话式”且模型兼容(即 `pipeline_tag` 是“text-generation”或“image-text-to-text”并且模型被标记为“对话式”)。
  • 映射创建后(异步),我们会自动测试合作伙伴 API 是否正确处理了针对相关任务的 huggingface.js/inference 调用,确保 API 规范有效。请参阅下面的自动验证部分。

使用标签过滤器将多个 HF 模型映射到单个推理端点

我们还支持根据 HF 模型的 `tags` 进行映射。使用标签过滤器,您可以自动将多个 HF 模型映射到您这边的单个推理端点。例如,任何同时标记有 `lora` 和 `base_model:adapter:black-forest-labs/FLUX.1-dev` 的模型都可以映射到您的 Flux-dev LoRA 推理端点。

重要提示:确保 JS 客户端库可以处理您提供商的 LoRA 权重。请查看fal 的实现以获取更多详细信息。

API 如下:

POST /api/partners/{provider}/models

创建一个新的映射项,其内容(JSON 编码)如下:

{
    "type": "tag-filter", // required
    "task": "WidgetType", // required
    "tags": ["string"], // required: any HF model with all of those tags will be mapped to providerModel
    "providerModel": "string", // required: the partner's "model id" i.e. id on your side
    "adapterType": "lora", // required: only "lora" is supported at the moment
    "status": "live" | "staging" // Optional: defaults to "staging". "staging" models are only available to members of the partner's org, then you switch them to "live" when they're ready to go live
}
  • `task`,在 HF 生态系统中也称为 `pipeline_tag`,是模型类型/API 类型(示例:“text-to-image”、“text-generation”,但对于聊天模型,您应该使用“conversational”)
  • `tags` 是要匹配的模型标签集。例如,要匹配 Flux 的所有 LoRA,您可以使用:`["lora", "base_model:adapter:black-forest-labs/FLUX.1-dev"]`
  • `providerModel` 是您这边的模型 ID(可以与 HF 模型 ID 相同或不同)。
  • `adapterType` 是一个文字值,帮助客户端库解释如何调用您的 API。目前唯一支持的值是 `“lora”`。

此路由的输出是一个映射 ID,您以后可以使用它来更新映射的状态或删除它。

删除映射项

DELETE /api/partners/{provider}/models/{mapping ID}

其中 `mapping ID` 是创建时获得的映射的 `_id` 字段。您也可以从列出整个映射 API 端点检索它。

更新映射项的状态

调用此 HTTP PUT 端点

PUT /api/partners/{provider}/models/{mapping ID}/status

包含以下正文(JSON 编码)

{
    "status": "live" | "staging" // The new status, one of "staging" or "live"
}   

其中 `mapping ID` 是创建时获得的映射的 `_id` 字段。您也可以从列出整个映射 API 端点检索它。

列出整个映射

GET /api/partners/{provider}/models?status=staging|live

这会从数据库中获取所有映射项。为了清晰起见,输出按任务分组。

这是公开可访问的。默认情况下保持透明很有用,它有助于调试客户端 SDK 等。

以下是响应示例:

{
    "text-to-image": {
        "black-forest-labs/FLUX.1-Canny-dev": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "providerId": "black-forest-labs/FLUX.1-canny",
            "status": "live"
        },
        "black-forest-labs/FLUX.1-Depth-dev": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "providerId": "black-forest-labs/FLUX.1-depth",
            "status": "live"
        },
        "tag-filter=base_model:adapter:stabilityai/stable-diffusion-xl-base-1.0,lora": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "status": "live",
            "providerId": "sdxl-lora-mutualized",
            "adapterType": "lora",
            "tags": [
                "base_model:adapter:stabilityai/stable-diffusion-xl-base-1.0",
                "lora"
            ]
        }
    },
    "conversational": {
        "deepseek-ai/DeepSeek-R1": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "providerId": "deepseek-ai/DeepSeek-R1",
            "status": "live"
        }
    },
    "text-generation": {
        "meta-llama/Llama-2-70b-hf": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "providerId": "meta-llama/Llama-2-70b-hf",
            "status": "live"
        },
        "mistralai/Mixtral-8x7B-v0.1": {
            "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
            "providerId": "mistralai/Mixtral-8x7B-v0.1",
            "status": "live"
        }
    }
}

自动验证

一旦通过 API 创建了映射,Hugging Face 会执行定期自动化测试,以确保映射的端点正常运行。

每个模型每 6 小时通过对您的服务进行 API 调用来测试。如果测试成功,模型将保持活动状态并继续定期测试。但是,如果测试失败(例如,您的服务在推理请求期间返回 HTTP 错误状态),提供商将暂时从活动提供商列表中删除。

失败的映射每小时重新测试一次。此外,更新模型映射的状态会触发即时验证测试。

验证过程检查以下内容:

  • 推理 API 可访问,并且 HTTP 调用成功。
  • 输出格式与 Hugging Face JavaScript 推理客户端兼容。
  • 满足延迟要求
    • 对于对话模型和文本模型:在 5 秒以内(流式模式下首次生成令牌的时间)。
    • 对于其他任务:在 30 秒以内。

对于大型语言模型(LLMs),还会进行额外的行为测试

  • 工具调用支持。
  • 结构化输出支持。

这些测试涉及向模型发送特定的推理请求并验证响应是否符合预期格式。

4. 计费

对于路由请求(见下图),即用户通过 HF 进行身份验证时,我们的意图是用户只需支付标准提供商 API 费率。我们不收取额外费用,直接将提供商成本传递给用户。有关定价结构的更多详细信息,请参阅定价页面

我们提供了一种更简单的方法来计算此成本并向我们的用户收费,即要求您通过您自己托管的 HTTP API 为每个请求提供成本。

HTTP API 规范

我们要求您公开一个支持 HTTP POST 请求的 API。请求正文是一个 JSON 编码的对象,其中包含我们请求成本的请求 ID 列表。身份验证系统应与您的推理服务相同;例如,一个 bearer token。

POST {your URL here}
Authorization: {authentication info - eg "Bearer token"}
Content-Type: application/json

{
    "requestIds": [
        "deadbeef0",
        "deadbeef1",
        "deadbeef2",
        "deadbeef3"
    ]
}

响应也是 JSON 编码的。响应包含一个对象数组,指定请求的 ID 及其以纳美元 (10^-9 USD) 为单位的成本。

HTTP/1.1 200 OK
Content-Type: application/json

{
    "requests": [
        { "requestId": "deadbeef0", "costNanoUsd": 100 },
        { "requestId": "deadbeef1", "costNanoUsd": 100 },
        { "requestId": "deadbeef2", "costNanoUsd": 100 },
        { "requestId": "deadbeef3", "costNanoUsd": 100 }
    ]
}

价格单位

我们要求价格是一个非负整数,单位是纳美元(10^-9 美元)。

如何定义请求 ID

对于您服务的每个请求/生成,您都应该定义一个唯一的请求(或响应)ID,并将其作为响应头提供。我们将使用此 ID 作为上述计费 API 的请求 ID。

作为这些要求的一部分,请告知我们您的标头名称。如果您还没有,我们建议使用 `Inference-Id` 名称,它应该包含一个 UUID 字符串。

示例:在推理响应中定义 `Inference-Id` 标头。

POST /v1/chat/completions
Content-Type: application/json
[request headers]
[request body]
------
HTTP/1.1 200 OK
Content-Type: application/json
[other request headers]
Inference-Id: unique-id-00131
[response body]

5. Python 客户端集成

在将新的提供商添加到 `huggingface_hub` Python 库之前,请确保所有之前的步骤都已完成并且 Hub 上的一切都正常运行。Python 库中的支持是第二步。

实现提供程序助手 (Python)

在 `src/huggingface_hub/inference/_providers/{provider_name}.py` 下创建一个新文件,并复制粘贴以下代码片段。

实现需要自定义处理的方法。检查基本实现以查看默认行为。如果您不需要覆盖某个方法,只需将其删除即可。至少必须覆盖 `_prepare_payload_as_dict` 或 `_prepare_payload_as_bytes` 中的一个。

如果提供商支持多个需要不同实现的任务,请为每个任务创建专门的子类,遵循 fal_ai.py 中所示的模式。

对于文本生成和对话任务,可以直接继承自 BaseTextGenerationTask 和 BaseConversationalTask(在 _common.py 中定义),并在需要时覆盖这些方法。示例可以在 fireworks_ai.py 和 together.py 中找到。

from typing import Any, Dict, Optional, Union

from ._common import TaskProviderHelper


class MyNewProviderTaskProviderHelper(TaskProviderHelper):
    def __init__(self):
        """Define high-level parameters."""
        super().__init__(provider=..., base_url=..., task=...)

    def get_response(
        self,
        response: Union[bytes, Dict],
        request_params: Optional[RequestParameters] = None,
    ) -> Any:
        """
        Return the response in the expected format.

        Override this method in subclasses for customized response handling."""
        return super().get_response(response)

    def _prepare_headers(self, headers: Dict, api_key: str) -> Dict:
        """Return the headers to use for the request.

        Override this method in subclasses for customized headers.
        """
        return super()._prepare_headers(headers, api_key)

    def _prepare_route(self, mapped_model: str, api_key: str) -> str:
        """Return the route to use for the request.

        Override this method in subclasses for customized routes.
        """
        return super()._prepare_route(mapped_model)

    def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
        """Return the payload to use for the request, as a dict.

        Override this method in subclasses for customized payloads.
        Only one of `_prepare_payload_as_dict` and `_prepare_payload_as_bytes` should return a value.
        """
        return super()._prepare_payload_as_dict(inputs, parameters, mapped_model)

    def _prepare_payload_as_bytes(
        self, inputs: Any, parameters: Dict, mapped_model: str, extra_payload: Optional[Dict]
    ) -> Optional[bytes]:
        """Return the body to use for the request, as bytes.

        Override this method in subclasses for customized body data.
        Only one of `_prepare_payload_as_dict` and `_prepare_payload_as_bytes` should return a value.
        """
        return super()._prepare_payload_as_bytes(inputs, parameters, mapped_model, extra_payload)

注册提供商

添加测试

6. 添加提供商文档

在 Hugging Face 文档中为您的提供商创建一个专用文档页面。此页面应包含对您的提供商服务的简洁描述,突出用户的好处,设定对性能或功能的期望,并包含任何相关细节,例如定价模型或数据保留政策。实质上,提供对最终用户有价值的任何信息。

以下是添加文档页面的方法:

  • 提供您的徽标:您可以直接将您的徽标文件(单独的亮色和暗色模式版本)发送给我们。这通常是最简单的方法。或者,如果您愿意,您可以在huggingface/documentation-images存储库中打开一个 PR。如果您选择打开 PR:
    • 徽标必须是 `.png` 格式。
    • 将其命名为 `{provider-name}-light.png` 和 `{provider-name}-dark.png`。
    • 请在 PR 上标记 `Wauplin` 和 `celinah`。
  • 创建文档文件
    • 使用现有提供商页面作为模板。例如,请查看Fal AI的模板。
    • 该文件应位于 `scripts/inference-providers/templates/providers/{your-provider-name}.handlebars` 下。
  • 提交文档 PR
    • 添加您的新 `{provider-name}.handlebars` 文件。
    • 更新合作伙伴表格以包含您的公司或产品。
    • 更新 `docs/inference-providers/` 目录中的 `_toctree.yml` 文件,将您的新文档页面包含在“提供商”部分,并保持字母顺序。
    • 更新 `scripts/inference-providers/scripts/generate.ts` 文件,将您的提供商包含在 `PROVIDERS_HUB_ORGS` 和 `PROVIDERS_URLS` 常量中,并保持字母顺序。
    • 在 `scripts/inference-providers` 仓库的根目录下运行 `pnpm install`(如果您尚未安装)然后运行 `pnpm run generate` 以生成文档。
    • 提交所有更改,包括手动编辑的文件(提供商页面、`_toctree.yml`、合作伙伴表)和脚本生成的文件。
    • 当您打开 PR 时,请标记 @Wauplin、@SBrandeis、@julien-c 和 @hanouticelina 进行审查。如果您在这些步骤中需要任何帮助,请随时联系——我们随时为您提供帮助!

常见问题

问题:默认情况下,我们在设置页面中按什么顺序列出提供商?

答案:默认排序是按过去 7 天内 HF 路由的总请求数。此顺序决定了模型页面上的小部件将优先使用哪个提供商(但用户自定义的顺序优先)。

< > 在 GitHub 上更新