Skip to content

Commit d72180a

Browse files
authored
✨ clarifai inference provider (#1781)
Adds Clarifai as a new inference provider for conversational tasks
1 parent 676466b commit d72180a

File tree

6 files changed

+107
-0
lines changed

6 files changed

+107
-0
lines changed

packages/inference/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Currently, we support the following providers:
6060
- [Replicate](https://replicate.com)
6161
- [Sambanova](https://sambanova.ai)
6262
- [Scaleway](https://www.scaleway.com/en/generative-apis/)
63+
- [Clarifai](http://clarifai.com)
6364
- [Together](https://together.xyz)
6465
- [Baseten](https://baseten.co)
6566
- [Blackforestlabs](https://blackforestlabs.ai)
@@ -99,6 +100,7 @@ Only a subset of models are supported when requesting third-party providers. You
99100
- [Scaleway supported models](https://huggingface.co/api/partners/scaleway/models)
100101
- [Together supported models](https://huggingface.co/api/partners/together/models)
101102
- [Baseten supported models](https://huggingface.co/api/partners/baseten/models)
103+
- [Clarifai supported models](https://huggingface.co/api/partners/clarifai/models)
102104
- [Cohere supported models](https://huggingface.co/api/partners/cohere/models)
103105
- [Cerebras supported models](https://huggingface.co/api/partners/cerebras/models)
104106
- [Groq supported models](https://console.groq.com/docs/models)

packages/inference/src/lib/getProviderHelper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as Baseten from "../providers/baseten.js";
2+
import * as Clarifai from "../providers/clarifai.js";
23
import * as BlackForestLabs from "../providers/black-forest-labs.js";
34
import * as Cerebras from "../providers/cerebras.js";
45
import * as Cohere from "../providers/cohere.js";
@@ -65,6 +66,9 @@ export const PROVIDERS: Record<InferenceProvider, Partial<Record<InferenceTask,
6566
cerebras: {
6667
conversational: new Cerebras.CerebrasConversationalTask(),
6768
},
69+
clarifai: {
70+
conversational: new Clarifai.ClarifaiConversationalTask(),
71+
},
6872
cohere: {
6973
conversational: new Cohere.CohereConversationalTask(),
7074
},
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* See the registered mapping of HF model ID => Clarifai model ID here:
3+
*
4+
* https://huggingface.co/api/partners/clarifai/models
5+
*
6+
* This is a publicly available mapping.
7+
*
8+
* If you want to try to run inference for a new model locally before it's registered on huggingface.co,
9+
* you can add it to the dictionary "HARDCODED_MODEL_ID_MAPPING" in consts.ts, for dev purposes.
10+
*
11+
* - If you work at Clarifai and want to update this mapping, please use the model mapping API we provide on huggingface.co
12+
* - 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
13+
* and we will tag Clarifai team members.
14+
*
15+
* Thanks!
16+
*/
17+
import { BaseConversationalTask } from "./providerHelper.js";
18+
import type { HeaderParams } from "../types.js";
19+
20+
const CLARIFAI_API_BASE_URL = "https://api.clarifai.com";
21+
22+
export class ClarifaiConversationalTask extends BaseConversationalTask {
23+
constructor() {
24+
super("clarifai", CLARIFAI_API_BASE_URL);
25+
}
26+
27+
override makeRoute(): string {
28+
return "/v2/ext/openai/v1/chat/completions";
29+
}
30+
31+
override prepareHeaders(params: HeaderParams, isBinary: boolean): Record<string, string> {
32+
const headers: Record<string, string> = {
33+
Authorization:
34+
params.authMethod !== "provider-key" ? `Bearer ${params.accessToken}` : `Key ${params.accessToken}`,
35+
};
36+
if (!isBinary) {
37+
headers["Content-Type"] = "application/json";
38+
}
39+
return headers;
40+
}
41+
}

packages/inference/src/providers/consts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const HARDCODED_MODEL_INFERENCE_MAPPING: Record<
2121
baseten: {},
2222
"black-forest-labs": {},
2323
cerebras: {},
24+
clarifai: {},
2425
cohere: {},
2526
"fal-ai": {},
2627
"featherless-ai": {},

packages/inference/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const INFERENCE_PROVIDERS = [
4848
"baseten",
4949
"black-forest-labs",
5050
"cerebras",
51+
"clarifai",
5152
"cohere",
5253
"fal-ai",
5354
"featherless-ai",

packages/inference/test/InferenceClient.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,4 +2401,62 @@ describe.skip("InferenceClient", () => {
24012401
},
24022402
TIMEOUT
24032403
);
2404+
2405+
describe.concurrent(
2406+
"clarifai",
2407+
() => {
2408+
const client = new InferenceClient(env.HF_CLARIFAI_KEY ?? "dummy");
2409+
2410+
HARDCODED_MODEL_INFERENCE_MAPPING["clarifai"] = {
2411+
"deepseek-ai/DeepSeek-V3.1": {
2412+
provider: "clarifai",
2413+
hfModelId: "deepseek-ai/DeepSeek-V3.1",
2414+
providerId: "deepseek-ai/deepseek-chat/models/DeepSeek-V3_1",
2415+
status: "live",
2416+
task: "conversational",
2417+
},
2418+
};
2419+
2420+
it("chatCompletion - DeepSeek-V3_1", async () => {
2421+
const res = await client.chatCompletion({
2422+
model: "deepseek-ai/DeepSeek-V3.1",
2423+
provider: "clarifai",
2424+
messages: [{ role: "user", content: "What is 5 + 3?" }],
2425+
max_tokens: 20,
2426+
});
2427+
if (res.choices && res.choices.length > 0) {
2428+
const completion = res.choices[0].message?.content;
2429+
expect(completion).toBeDefined();
2430+
expect(typeof completion).toBe("string");
2431+
expect(completion).toMatch(/(eight|8)/i);
2432+
}
2433+
});
2434+
2435+
it("chatCompletion stream - DeepSeek-V3_1", async () => {
2436+
const stream = client.chatCompletionStream({
2437+
model: "deepseek-ai/DeepSeek-V3.1",
2438+
provider: "clarifai",
2439+
messages: [{ role: "user", content: "Count from 1 to 3" }],
2440+
stream: true,
2441+
max_tokens: 20,
2442+
}) as AsyncGenerator<ChatCompletionStreamOutput>;
2443+
2444+
let fullResponse = "";
2445+
for await (const chunk of stream) {
2446+
if (chunk.choices && chunk.choices.length > 0) {
2447+
const content = chunk.choices[0].delta?.content;
2448+
if (content) {
2449+
fullResponse += content;
2450+
}
2451+
}
2452+
}
2453+
2454+
// Verify we got a meaningful response
2455+
expect(fullResponse).toBeTruthy();
2456+
expect(fullResponse.length).toBeGreaterThan(0);
2457+
expect(fullResponse).toMatch(/1.*2.*3/);
2458+
});
2459+
},
2460+
TIMEOUT
2461+
);
24042462
});

0 commit comments

Comments
 (0)