Skip to content

Integrate Nscale-cloud into HuggingFace inference #1260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
86d56bc
feat: Adding nscale as provider
nbarr07 Mar 5, 2025
490d231
chore: added tests
nbarr07 Mar 6, 2025
3e32bc4
update the tapes.ts, update textToImage.ts nscale response format
nbarr07 Mar 7, 2025
d6bf892
remove nscale test from package.json
nbarr07 Mar 7, 2025
b93d276
remove skip comment on tests
nbarr07 Mar 7, 2025
4c36014
Merge remote-tracking branch 'upstream/main'
nbarr07 Mar 7, 2025
83f8e2d
save custom changes for nscale
nbarr07 Apr 8, 2025
f9e360f
Update nscale-cloud provider
nbarr07 Apr 9, 2025
8cf1a86
update Nscale provider
nbarr07 Apr 9, 2025
42edde2
Delete package-lock.json
nbarr07 Apr 9, 2025
efca482
Update consts.ts
nbarr07 Apr 9, 2025
6a6d0bd
Update nscale-cloud.ts
nbarr07 Apr 9, 2025
5e6cb04
Update url in nscale-cloud.ts
nbarr07 Apr 9, 2025
815250c
Merge remote-tracking branch 'upstream/main'
nbarr07 Apr 9, 2025
bcc01c0
rename to nscale
nbarr07 Apr 9, 2025
bce9ec0
format code
SBrandeis Apr 14, 2025
95cc1f8
Merge remote-tracking branch 'origin/main' into pr/nbarr07/1260
SBrandeis Apr 14, 2025
b606d69
somehow some tapes were removed
SBrandeis Apr 14, 2025
7e499fc
Update namespace in the readme
nbarr07 Apr 15, 2025
30f161c
Update packages/inference/src/providers/nscale.ts
hanouticelina Apr 15, 2025
0e5a6c8
remove casting
hanouticelina Apr 15, 2025
827093f
Merge remote-tracking branch 'upstream/main'
hanouticelina Apr 22, 2025
ed1af1f
Merge branch 'main' into main
hanouticelina Apr 22, 2025
8826fc5
Merge remote-tracking branch 'upstream/main'
hanouticelina Apr 24, 2025
5f2e36c
Merge branch 'main' of github.com:nbarr07/huggingface.js
hanouticelina Apr 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/inference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Currently, we support the following providers:
- [Hyperbolic](https://hyperbolic.xyz)
- [Nebius](https://studio.nebius.ai)
- [Novita](https://novita.ai/?utm_source=github_huggingface&utm_medium=github_readme&utm_campaign=link)
- [Nscale](https://nscale.com)
- [Replicate](https://replicate.com)
- [Sambanova](https://sambanova.ai)
- [Together](https://together.xyz)
Expand Down Expand Up @@ -79,6 +80,7 @@ Only a subset of models are supported when requesting third-party providers. You
- [Fireworks AI supported models](https://huggingface.co/api/partners/fireworks-ai/models)
- [Hyperbolic supported models](https://huggingface.co/api/partners/hyperbolic/models)
- [Nebius supported models](https://huggingface.co/api/partners/nebius/models)
- [Nscale supported models](https://huggingface.co/api/partners/nscale/models)
- [Replicate supported models](https://huggingface.co/api/partners/replicate/models)
- [Sambanova supported models](https://huggingface.co/api/partners/sambanova/models)
- [Together supported models](https://huggingface.co/api/partners/together/models)
Expand Down
5 changes: 5 additions & 0 deletions packages/inference/src/lib/getProviderHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as HFInference from "../providers/hf-inference";
import * as Hyperbolic from "../providers/hyperbolic";
import * as Nebius from "../providers/nebius";
import * as Novita from "../providers/novita";
import * as Nscale from "../providers/nscale";
import * as OpenAI from "../providers/openai";
import type {
AudioClassificationTaskHelper,
Expand Down Expand Up @@ -109,6 +110,10 @@ export const PROVIDERS: Record<InferenceProvider, Partial<Record<InferenceTask,
conversational: new Novita.NovitaConversationalTask(),
"text-generation": new Novita.NovitaTextGenerationTask(),
},
nscale: {
"text-to-image": new Nscale.NscaleTextToImageTask(),
conversational: new Nscale.NscaleConversationalTask(),
},
openai: {
conversational: new OpenAI.OpenAIConversationalTask(),
},
Expand Down
1 change: 1 addition & 0 deletions packages/inference/src/providers/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const HARDCODED_MODEL_INFERENCE_MAPPING: Record<
hyperbolic: {},
nebius: {},
novita: {},
nscale: {},
openai: {},
replicate: {},
sambanova: {},
Expand Down
79 changes: 79 additions & 0 deletions packages/inference/src/providers/nscale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* See the registered mapping of HF model ID => Nscale model ID here:
*
* https://huggingface.co/api/partners/nscale-cloud/models
*
* This is a publicly available mapping.
*
* If you want to try to run inference for a new model locally before it's registered on huggingface.co,
* you can add it to the dictionary "HARDCODED_MODEL_ID_MAPPING" in consts.ts, for dev purposes.
*
* - If you work at Nscale and want to update this mapping, please use the model mapping API we provide on huggingface.co
* - If you're a community member and want to add a new supported HF model to Nscale, please open an issue on the present repo
* and we will tag Nscale team members.
*
* Thanks!
*/
import type { TextToImageInput } from "@huggingface/tasks";
import { InferenceOutputError } from "../lib/InferenceOutputError";
import type { BodyParams } from "../types";
import { omit } from "../utils/omit";
import { BaseConversationalTask, TaskProviderHelper, type TextToImageTaskHelper } from "./providerHelper";

const NSCALE_API_BASE_URL = "https://inference.api.nscale.com";

interface NscaleCloudBase64ImageGeneration {
data: Array<{
b64_json: string;
}>;
}

export class NscaleConversationalTask extends BaseConversationalTask {
constructor() {
super("nscale", NSCALE_API_BASE_URL);
}
}

export class NscaleTextToImageTask extends TaskProviderHelper implements TextToImageTaskHelper {
constructor() {
super("nscale", NSCALE_API_BASE_URL);
}

preparePayload(params: BodyParams<TextToImageInput>): Record<string, unknown> {
return {
...omit(params.args, ["inputs", "parameters"]),
...params.args.parameters,
response_format: "b64_json",
prompt: params.args.inputs,
model: params.model,
};
}

makeRoute(): string {
return "v1/images/generations";
}

async getResponse(
response: NscaleCloudBase64ImageGeneration,
url?: string,
headers?: HeadersInit,
outputType?: "url" | "blob"
): Promise<string | Blob> {
if (
typeof response === "object" &&
"data" in response &&
Array.isArray(response.data) &&
response.data.length > 0 &&
"b64_json" in response.data[0] &&
typeof response.data[0].b64_json === "string"
) {
const base64Data = response.data[0].b64_json;
if (outputType === "url") {
return `data:image/jpeg;base64,${base64Data}`;
}
return fetch(`data:image/jpeg;base64,${base64Data}`).then((res) => res.blob());
}

throw new InferenceOutputError("Expected Nscale text-to-image response format");
}
}
1 change: 1 addition & 0 deletions packages/inference/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const INFERENCE_PROVIDERS = [
"hyperbolic",
"nebius",
"novita",
"nscale",
"openai",
"replicate",
"sambanova",
Expand Down
61 changes: 61 additions & 0 deletions packages/inference/test/InferenceClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1690,4 +1690,65 @@ describe.skip("InferenceClient", () => {
},
TIMEOUT
);
describe.concurrent(
"Nscale",
() => {
const client = new InferenceClient(env.HF_NSCALE_KEY ?? "dummy");

HARDCODED_MODEL_INFERENCE_MAPPING["nscale"] = {
"meta-llama/Llama-3.1-8B-Instruct": {
hfModelId: "meta-llama/Llama-3.1-8B-Instruct",
providerId: "nscale",
status: "live",
task: "conversational",
},
"black-forest-labs/FLUX.1-schnell": {
hfModelId: "black-forest-labs/FLUX.1-schnell",
providerId: "flux-schnell",
status: "live",
task: "text-to-image",
},
};

it("chatCompletion", async () => {
const res = await client.chatCompletion({
model: "meta-llama/Llama-3.1-8B-Instruct",
provider: "nscale",
messages: [{ role: "user", content: "Complete this sentence with words, one plus one is equal " }],
});
if (res.choices && res.choices.length > 0) {
const completion = res.choices[0].message?.content;
expect(completion).toContain("two");
}
});
it("chatCompletion stream", async () => {
const stream = client.chatCompletionStream({
model: "meta-llama/Llama-3.1-8B-Instruct",
provider: "nscale",
messages: [{ role: "user", content: "Say 'this is a test'" }],
stream: true,
}) as AsyncGenerator<ChatCompletionStreamOutput>;
let fullResponse = "";
for await (const chunk of stream) {
if (chunk.choices && chunk.choices.length > 0) {
const content = chunk.choices[0].delta?.content;
if (content) {
fullResponse += content;
}
}
}
expect(fullResponse).toBeTruthy();
expect(fullResponse.length).toBeGreaterThan(0);
});
it("textToImage", async () => {
const res = await client.textToImage({
model: "black-forest-labs/FLUX.1-schnell",
provider: "nscale",
inputs: "An astronaut riding a horse",
});
expect(res).toBeInstanceOf(Blob);
});
},
TIMEOUT
);
});