推理供应商文档

如何在 Hub 上注册成为推理供应商?

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

如何在 Hub 上注册成为推理供应商?

想在 Hugging Face Hub 上被列为推理供应商吗?请在社交网络上或在 Hub 上联系我们。

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

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

1. 先决条件

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

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

这个客户端为我们模型页面上的推理小部件提供支持,并且是下游的蓝图实现(用于 Python SDK、生成代码片段等)。

什么是任务

您会看到推理方法(textToImagechatCompletion 等)的名称与任务名称非常相似。 任务,在 HF 生态系统中也称为 pipeline_tag,是模型类型(基本上是模型具有的输入和输出类型),例如“文本生成”或“文本到图像”。 它在模型页面上突出显示,此处

所有可能的任务列表可以在 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 模型页面上为每种 pipeline 任务类型期望的“标准”形状 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");
    }
}

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

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

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

注册供应商

转到 packages/inference/src/lib/getProviderHelper.ts 并将您的供应商添加到 PROVIDERS。 请尽量遵守字母顺序。

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 类型(示例:“文本到图像”、“文本生成”,但对于聊天模型,您应该使用“对话式”)
  • hfModel 是 Hub 端的模型 ID。
  • providerModel 是您这边的模型 ID(可以相同或不同)。

将来,我们将添加对新参数的支持(如果现在对您很重要,请联系我们)

{
    "hfFilter": ["string"]
    // ^Power user move: register a "tag" slice of HF in one go.
    // Example: tag == "base_model:adapter:black-forest-labs/FLUX.1-dev" for all Flux-dev LoRAs
}

身份验证

您需要位于具有写入权限的供应商 Hub 组织中(例如,TogetherAI 的 https://huggingface.co/togethercomputer)才能访问此端点。

验证

端点验证

  • hfModel 确实是 pipeline_tag == task,或者 task 是“对话式”且模型兼容(即 pipeline_tag 是“文本生成”或“图像文本到文本”并且模型标记为“对话式”)。
  • (将来)我们将自动测试合作伙伴的 API 是否成功响应了相应任务的 huggingface.js/inference 调用,即 API 规范是否有效。

删除映射项

DELETE /api/partners/{provider}/models?hfModel=namespace/model-name

更新映射项的状态

调用此 HTTP PUT 端点

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

正文如下(JSON 编码)

{
    "hfModel": "namespace/model-name", // The name of the model on HF
    "status": "live" | "staging" // The new status, one of "staging" or "live"
}   

列出所有映射

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

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

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

这是一个响应示例

{
    "text-to-image": {
        "black-forest-labs/FLUX.1-Canny-dev": {
            "providerId": "black-forest-labs/FLUX.1-canny",
            "status": "live"
        },
        "black-forest-labs/FLUX.1-Depth-dev": {
            "providerId": "black-forest-labs/FLUX.1-depth",
            "status": "live"
        }
    },
    "conversational": {
        "deepseek-ai/DeepSeek-R1": {
            "providerId": "deepseek-ai/DeepSeek-R1",
            "status": "live"
        }
    },
    "text-generation": {
        "meta-llama/Llama-2-70b-hf": {
            "providerId": "meta-llama/Llama-2-70b-hf",
            "status": "live"
        },
        "mistralai/Mixtral-8x7B-v0.1": {
            "providerId": "mistralai/Mixtral-8x7B-v0.1",
            "status": "live"
        }
    }
}

4. 计费

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

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

HTTP API 规范

我们要求您公开一个支持 HTTP POST 请求的 API。 请求的正文是一个 JSON 编码的对象,其中包含我们请求成本的请求 ID 列表。

POST {your URL here}
Content-Type: application/json

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

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

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 库中的支持是第二步。

实施 provider helper (Python)

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

实施需要自定义处理的方法。查看基本实现以检查默认行为。如果您不需要覆盖某个方法,只需删除它。 _prepare_payload_as_dict_prepare_payload_as_bytes 中至少有一个必须被覆盖。

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

对于 text-generation 和 conversational 任务,可以直接从 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)

注册 Provider

添加测试

FAQ

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

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

< > 在 GitHub 上更新