Skip to content

Commit 7d91fe7

Browse files
jolow99SBrandeis
andauthored
Add the Public AI Inference Utility as an inference provider (#1743)
This PR adds Public AI as a new inference provider for conversational tasks. Base URL: https://api.publicai.co Developer Docs: https://platform.publicai.co Route: /v1/chat/completions (OpenAI compatible) --------- Co-authored-by: Simon Brandeis <[email protected]>
1 parent 0bfa42f commit 7d91fe7

File tree

6 files changed

+67
-0
lines changed

6 files changed

+67
-0
lines changed

packages/inference/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Currently, we support the following providers:
5656
- [Novita](https://novita.ai)
5757
- [Nscale](https://nscale.com)
5858
- [OVHcloud](https://endpoints.ai.cloud.ovh.net/)
59+
- [Public AI](https://publicai.co)
5960
- [Replicate](https://replicate.com)
6061
- [Sambanova](https://sambanova.ai)
6162
- [Scaleway](https://www.scaleway.com/en/generative-apis/)

packages/inference/src/lib/getProviderHelper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as Novita from "../providers/novita.js";
1212
import * as Nscale from "../providers/nscale.js";
1313
import * as OpenAI from "../providers/openai.js";
1414
import * as OvhCloud from "../providers/ovhcloud.js";
15+
import * as PublicAI from "../providers/publicai.js";
1516
import type {
1617
AudioClassificationTaskHelper,
1718
AudioToAudioTaskHelper,
@@ -139,6 +140,9 @@ export const PROVIDERS: Record<InferenceProvider, Partial<Record<InferenceTask,
139140
conversational: new OvhCloud.OvhCloudConversationalTask(),
140141
"text-generation": new OvhCloud.OvhCloudTextGenerationTask(),
141142
},
143+
publicai: {
144+
conversational: new PublicAI.PublicAIConversationalTask(),
145+
},
142146
replicate: {
143147
"text-to-image": new Replicate.ReplicateTextToImageTask(),
144148
"text-to-speech": new Replicate.ReplicateTextToSpeechTask(),

packages/inference/src/providers/consts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const HARDCODED_MODEL_INFERENCE_MAPPING: Record<
3131
novita: {},
3232
nscale: {},
3333
openai: {},
34+
publicai: {},
3435
ovhcloud: {},
3536
replicate: {},
3637
sambanova: {},
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { BaseConversationalTask } from "./providerHelper.js";
2+
3+
export class PublicAIConversationalTask extends BaseConversationalTask {
4+
constructor() {
5+
super("publicai", "https://api.publicai.co");
6+
}
7+
}

packages/inference/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const INFERENCE_PROVIDERS = [
5959
"nscale",
6060
"openai",
6161
"ovhcloud",
62+
"publicai",
6263
"replicate",
6364
"sambanova",
6465
"scaleway",

packages/inference/test/InferenceClient.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,4 +2238,57 @@ describe.skip("InferenceClient", () => {
22382238
},
22392239
TIMEOUT
22402240
);
2241+
2242+
describe.concurrent(
2243+
"PublicAI",
2244+
() => {
2245+
const client = new InferenceClient(env.HF_PUBLICAI_KEY ?? "dummy");
2246+
2247+
HARDCODED_MODEL_INFERENCE_MAPPING["publicai"] = {
2248+
"swiss-ai/Apertus-8B-Instruct-2509": {
2249+
provider: "publicai",
2250+
hfModelId: "swiss-ai/Apertus-8B-Instruct-2509",
2251+
providerId: "swiss-ai/apertus-8b-instruct",
2252+
status: "live",
2253+
task: "conversational",
2254+
},
2255+
};
2256+
2257+
it("chatCompletion", async () => {
2258+
const res = await client.chatCompletion({
2259+
model: "swiss-ai/Apertus-8B-Instruct-2509",
2260+
provider: "publicai",
2261+
messages: [{ role: "user", content: "Complete this sentence with words, one plus one is equal " }],
2262+
});
2263+
if (res.choices && res.choices.length > 0) {
2264+
const completion = res.choices[0].message?.content;
2265+
expect(completion).toContain("two");
2266+
}
2267+
});
2268+
2269+
it("chatCompletion stream", async () => {
2270+
const stream = client.chatCompletionStream({
2271+
model: "swiss-ai/Apertus-8B-Instruct-2509",
2272+
provider: "publicai",
2273+
messages: [{ role: "user", content: "Say 'this is a test'" }],
2274+
stream: true,
2275+
}) as AsyncGenerator<ChatCompletionStreamOutput>;
2276+
2277+
let fullResponse = "";
2278+
for await (const chunk of stream) {
2279+
if (chunk.choices && chunk.choices.length > 0) {
2280+
const content = chunk.choices[0].delta?.content;
2281+
if (content) {
2282+
fullResponse += content;
2283+
}
2284+
}
2285+
}
2286+
2287+
// Verify we got a meaningful response
2288+
expect(fullResponse).toBeTruthy();
2289+
expect(fullResponse.length).toBeGreaterThan(0);
2290+
});
2291+
},
2292+
TIMEOUT
2293+
);
22412294
});

0 commit comments

Comments
 (0)