diff --git a/packages/inference/README.md b/packages/inference/README.md index b2910ed186..db3f64b35f 100644 --- a/packages/inference/README.md +++ b/packages/inference/README.md @@ -60,6 +60,7 @@ Currently, we support the following providers: - [Replicate](https://replicate.com) - [Sambanova](https://sambanova.ai) - [Scaleway](https://www.scaleway.com/en/generative-apis/) +- [Clarifai](http://clarifai.com) - [Together](https://together.xyz) - [Baseten](https://baseten.co) - [Blackforestlabs](https://blackforestlabs.ai) @@ -99,6 +100,7 @@ Only a subset of models are supported when requesting third-party providers. You - [Scaleway supported models](https://huggingface.co/api/partners/scaleway/models) - [Together supported models](https://huggingface.co/api/partners/together/models) - [Baseten supported models](https://huggingface.co/api/partners/baseten/models) +- [Clarifai supported models](https://huggingface.co/api/partners/clarifai/models) - [Cohere supported models](https://huggingface.co/api/partners/cohere/models) - [Cerebras supported models](https://huggingface.co/api/partners/cerebras/models) - [Groq supported models](https://console.groq.com/docs/models) diff --git a/packages/inference/src/lib/getProviderHelper.ts b/packages/inference/src/lib/getProviderHelper.ts index c41f929cab..ee39f50342 100644 --- a/packages/inference/src/lib/getProviderHelper.ts +++ b/packages/inference/src/lib/getProviderHelper.ts @@ -1,4 +1,5 @@ import * as Baseten from "../providers/baseten.js"; +import * as Clarifai from "../providers/clarifai.js"; import * as BlackForestLabs from "../providers/black-forest-labs.js"; import * as Cerebras from "../providers/cerebras.js"; import * as Cohere from "../providers/cohere.js"; @@ -65,6 +66,9 @@ export const PROVIDERS: Record Clarifai model ID here: + * + * https://huggingface.co/api/partners/clarifai/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 Clarifai 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 Clarifai, please open an issue on the present repo + * and we will tag Clarifai team members. + * + * Thanks! + */ +import { BaseConversationalTask } from "./providerHelper.js"; +import type { HeaderParams } from "../types.js"; + +const CLARIFAI_API_BASE_URL = "https://api.clarifai.com"; + +export class ClarifaiConversationalTask extends BaseConversationalTask { + constructor() { + super("clarifai", CLARIFAI_API_BASE_URL); + } + + override makeRoute(): string { + return "/v2/ext/openai/v1/chat/completions"; + } + + override prepareHeaders(params: HeaderParams, isBinary: boolean): Record { + const headers: Record = { + Authorization: + params.authMethod !== "provider-key" ? `Bearer ${params.accessToken}` : `Key ${params.accessToken}`, + }; + if (!isBinary) { + headers["Content-Type"] = "application/json"; + } + return headers; + } +} diff --git a/packages/inference/src/providers/consts.ts b/packages/inference/src/providers/consts.ts index 1dfa656736..f93d890535 100644 --- a/packages/inference/src/providers/consts.ts +++ b/packages/inference/src/providers/consts.ts @@ -21,6 +21,7 @@ export const HARDCODED_MODEL_INFERENCE_MAPPING: Record< baseten: {}, "black-forest-labs": {}, cerebras: {}, + clarifai: {}, cohere: {}, "fal-ai": {}, "featherless-ai": {}, diff --git a/packages/inference/src/types.ts b/packages/inference/src/types.ts index b5d4815b5a..215252efda 100644 --- a/packages/inference/src/types.ts +++ b/packages/inference/src/types.ts @@ -48,6 +48,7 @@ export const INFERENCE_PROVIDERS = [ "baseten", "black-forest-labs", "cerebras", + "clarifai", "cohere", "fal-ai", "featherless-ai", diff --git a/packages/inference/test/InferenceClient.spec.ts b/packages/inference/test/InferenceClient.spec.ts index 4520c389a1..3ea6b55241 100644 --- a/packages/inference/test/InferenceClient.spec.ts +++ b/packages/inference/test/InferenceClient.spec.ts @@ -2401,4 +2401,62 @@ describe.skip("InferenceClient", () => { }, TIMEOUT ); + + describe.concurrent( + "clarifai", + () => { + const client = new InferenceClient(env.HF_CLARIFAI_KEY ?? "dummy"); + + HARDCODED_MODEL_INFERENCE_MAPPING["clarifai"] = { + "deepseek-ai/DeepSeek-V3.1": { + provider: "clarifai", + hfModelId: "deepseek-ai/DeepSeek-V3.1", + providerId: "deepseek-ai/deepseek-chat/models/DeepSeek-V3_1", + status: "live", + task: "conversational", + }, + }; + + it("chatCompletion - DeepSeek-V3_1", async () => { + const res = await client.chatCompletion({ + model: "deepseek-ai/DeepSeek-V3.1", + provider: "clarifai", + messages: [{ role: "user", content: "What is 5 + 3?" }], + max_tokens: 20, + }); + if (res.choices && res.choices.length > 0) { + const completion = res.choices[0].message?.content; + expect(completion).toBeDefined(); + expect(typeof completion).toBe("string"); + expect(completion).toMatch(/(eight|8)/i); + } + }); + + it("chatCompletion stream - DeepSeek-V3_1", async () => { + const stream = client.chatCompletionStream({ + model: "deepseek-ai/DeepSeek-V3.1", + provider: "clarifai", + messages: [{ role: "user", content: "Count from 1 to 3" }], + stream: true, + max_tokens: 20, + }) as AsyncGenerator; + + 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; + } + } + } + + // Verify we got a meaningful response + expect(fullResponse).toBeTruthy(); + expect(fullResponse.length).toBeGreaterThan(0); + expect(fullResponse).toMatch(/1.*2.*3/); + }); + }, + TIMEOUT + ); });