Skip to content

Commit 93e43f1

Browse files
GnoaleWauplin
authored andcommitted
feat: add scaleway inference provider (#3356)
* feat: add scaleway inference provider * fix: alpha order
1 parent 84a92a9 commit 93e43f1

File tree

6 files changed

+107
-2
lines changed

6 files changed

+107
-2
lines changed

src/huggingface_hub/inference/_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class InferenceClient:
133133
Note: for better compatibility with OpenAI's client, `model` has been aliased as `base_url`. Those 2
134134
arguments are mutually exclusive. If a URL is passed as `model` or `base_url` for chat completion, the `(/v1)/chat/completions` suffix path will be appended to the URL.
135135
provider (`str`, *optional*):
136-
Name of the provider to use for inference. Can be `"black-forest-labs"`, `"cerebras"`, `"cohere"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"hyperbolic"`, `"nebius"`, `"novita"`, `"nscale"`, `"openai"`, `"replicate"`, "sambanova"` or `"together"`.
136+
Name of the provider to use for inference. Can be `"black-forest-labs"`, `"cerebras"`, `"cohere"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"hyperbolic"`, `"nebius"`, `"novita"`, `"nscale"`, `"openai"`, `"replicate"`, `"sambanova"`, `"scaleway"` or `"together"`.
137137
Defaults to "auto" i.e. the first of the providers available for the model, sorted by the user's order in https://hf.co/settings/inference-providers.
138138
If model is a URL or `base_url` is passed, then `provider` is not used.
139139
token (`str`, *optional*):

src/huggingface_hub/inference/_generated/_async_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class AsyncInferenceClient:
121121
Note: for better compatibility with OpenAI's client, `model` has been aliased as `base_url`. Those 2
122122
arguments are mutually exclusive. If a URL is passed as `model` or `base_url` for chat completion, the `(/v1)/chat/completions` suffix path will be appended to the URL.
123123
provider (`str`, *optional*):
124-
Name of the provider to use for inference. Can be `"black-forest-labs"`, `"cerebras"`, `"cohere"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"hyperbolic"`, `"nebius"`, `"novita"`, `"nscale"`, `"openai"`, `"replicate"`, "sambanova"` or `"together"`.
124+
Name of the provider to use for inference. Can be `"black-forest-labs"`, `"cerebras"`, `"cohere"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"hyperbolic"`, `"nebius"`, `"novita"`, `"nscale"`, `"openai"`, `"replicate"`, `"sambanova"`, `"scaleway"` or `"together"`.
125125
Defaults to "auto" i.e. the first of the providers available for the model, sorted by the user's order in https://hf.co/settings/inference-providers.
126126
If model is a URL or `base_url` is passed, then `provider` is not used.
127127
token (`str`, *optional*):

src/huggingface_hub/inference/_providers/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from .openai import OpenAIConversationalTask
3939
from .replicate import ReplicateImageToImageTask, ReplicateTask, ReplicateTextToImageTask, ReplicateTextToSpeechTask
4040
from .sambanova import SambanovaConversationalTask, SambanovaFeatureExtractionTask
41+
from .scaleway import ScalewayConversationalTask, ScalewayFeatureExtractionTask
4142
from .together import TogetherConversationalTask, TogetherTextGenerationTask, TogetherTextToImageTask
4243

4344

@@ -60,6 +61,7 @@
6061
"openai",
6162
"replicate",
6263
"sambanova",
64+
"scaleway",
6365
"together",
6466
]
6567

@@ -154,6 +156,10 @@
154156
"conversational": SambanovaConversationalTask(),
155157
"feature-extraction": SambanovaFeatureExtractionTask(),
156158
},
159+
"scaleway": {
160+
"conversational": ScalewayConversationalTask(),
161+
"feature-extraction": ScalewayFeatureExtractionTask(),
162+
},
157163
"together": {
158164
"text-to-image": TogetherTextToImageTask(),
159165
"conversational": TogetherConversationalTask(),

src/huggingface_hub/inference/_providers/_common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"nscale": {},
3434
"replicate": {},
3535
"sambanova": {},
36+
"scaleway": {},
3637
"together": {},
3738
}
3839

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from typing import Any, Dict, Optional, Union
2+
3+
from huggingface_hub.inference._common import RequestParameters, _as_dict
4+
5+
from ._common import BaseConversationalTask, InferenceProviderMapping, TaskProviderHelper, filter_none
6+
7+
8+
class ScalewayConversationalTask(BaseConversationalTask):
9+
def __init__(self):
10+
super().__init__(provider="scaleway", base_url="https://api.scaleway.ai")
11+
12+
13+
class ScalewayFeatureExtractionTask(TaskProviderHelper):
14+
def __init__(self):
15+
super().__init__(provider="scaleway", base_url="https://api.scaleway.ai", task="feature-extraction")
16+
17+
def _prepare_route(self, mapped_model: str, api_key: str) -> str:
18+
return "/v1/embeddings"
19+
20+
def _prepare_payload_as_dict(
21+
self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping
22+
) -> Optional[Dict]:
23+
parameters = filter_none(parameters)
24+
return {"input": inputs, "model": provider_mapping_info.provider_id, **parameters}
25+
26+
def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
27+
embeddings = _as_dict(response)["data"]
28+
return [embedding["embedding"] for embedding in embeddings]

tests/test_inference_providers.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
ReplicateTextToSpeechTask,
5151
)
5252
from huggingface_hub.inference._providers.sambanova import SambanovaConversationalTask, SambanovaFeatureExtractionTask
53+
from huggingface_hub.inference._providers.scaleway import ScalewayConversationalTask, ScalewayFeatureExtractionTask
5354
from huggingface_hub.inference._providers.together import TogetherTextToImageTask
5455

5556
from .testing_utils import assert_in_logs
@@ -1052,6 +1053,75 @@ def test_prepare_url_conversational(self):
10521053
assert url == "https://api.novita.ai/v3/openai/chat/completions"
10531054

10541055

1056+
class TestScalewayProvider:
1057+
def test_prepare_hf_url_conversational(self):
1058+
helper = ScalewayConversationalTask()
1059+
url = helper._prepare_url("hf_token", "username/repo_name")
1060+
assert url == "https://router.huggingface.co/scaleway/v1/chat/completions"
1061+
1062+
def test_prepare_url_conversational(self):
1063+
helper = ScalewayConversationalTask()
1064+
url = helper._prepare_url("scw_token", "username/repo_name")
1065+
assert url == "https://api.scaleway.ai/v1/chat/completions"
1066+
1067+
def test_prepare_payload_as_dict(self):
1068+
helper = ScalewayConversationalTask()
1069+
payload = helper._prepare_payload_as_dict(
1070+
[
1071+
{"role": "system", "content": "You are a helpful assistant"},
1072+
{"role": "user", "content": "Hello!"},
1073+
],
1074+
{
1075+
"max_tokens": 512,
1076+
"temperature": 0.15,
1077+
"top_p": 1,
1078+
"presence_penalty": 0,
1079+
"stream": True,
1080+
},
1081+
InferenceProviderMapping(
1082+
provider="scaleway",
1083+
hf_model_id="meta-llama/Llama-3.1-8B-Instruct",
1084+
providerId="meta-llama/llama-3.1-8B-Instruct",
1085+
task="conversational",
1086+
status="live",
1087+
),
1088+
)
1089+
assert payload == {
1090+
"max_tokens": 512,
1091+
"messages": [
1092+
{"content": "You are a helpful assistant", "role": "system"},
1093+
{"role": "user", "content": "Hello!"},
1094+
],
1095+
"model": "meta-llama/llama-3.1-8B-Instruct",
1096+
"presence_penalty": 0,
1097+
"stream": True,
1098+
"temperature": 0.15,
1099+
"top_p": 1,
1100+
}
1101+
1102+
def test_prepare_url_feature_extraction(self):
1103+
helper = ScalewayFeatureExtractionTask()
1104+
assert (
1105+
helper._prepare_url("hf_token", "username/repo_name")
1106+
== "https://router.huggingface.co/scaleway/v1/embeddings"
1107+
)
1108+
1109+
def test_prepare_payload_as_dict_feature_extraction(self):
1110+
helper = ScalewayFeatureExtractionTask()
1111+
payload = helper._prepare_payload_as_dict(
1112+
"Example text to embed",
1113+
{"truncate": True},
1114+
InferenceProviderMapping(
1115+
provider="scaleway",
1116+
hf_model_id="username/repo_name",
1117+
providerId="provider-id",
1118+
task="feature-extraction",
1119+
status="live",
1120+
),
1121+
)
1122+
assert payload == {"input": "Example text to embed", "model": "provider-id", "truncate": True}
1123+
1124+
10551125
class TestNscaleProvider:
10561126
def test_prepare_route_text_to_image(self):
10571127
helper = NscaleTextToImageTask()

0 commit comments

Comments
 (0)