From fd6a95847ce19c9efea01f8713202c3ea59a1425 Mon Sep 17 00:00:00 2001 From: Shenghang Tsai Date: Tue, 28 Oct 2025 14:51:03 +0800 Subject: [PATCH] new provider SiliconFlow --- packages/inference/README.md | 2 + .../inference/src/lib/getProviderHelper.ts | 4 + packages/inference/src/providers/consts.ts | 1 + .../inference/src/providers/siliconflow.ts | 16 ++++ packages/inference/src/types.ts | 2 + .../inference/test/InferenceClient.spec.ts | 95 +++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 packages/inference/src/providers/siliconflow.ts diff --git a/packages/inference/README.md b/packages/inference/README.md index 664c224583..ee675a3178 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/) +- [SiliconFlow](https://siliconflow.com) - [Clarifai](http://clarifai.com) - [Together](https://together.xyz) - [Baseten](https://baseten.co) @@ -99,6 +100,7 @@ Only a subset of models are supported when requesting third-party providers. You - [Replicate supported models](https://huggingface.co/api/partners/replicate/models) - [Sambanova supported models](https://huggingface.co/api/partners/sambanova/models) - [Scaleway supported models](https://huggingface.co/api/partners/scaleway/models) +- [SiliconFlow supported models](https://huggingface.co/api/partners/siliconflow/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) diff --git a/packages/inference/src/lib/getProviderHelper.ts b/packages/inference/src/lib/getProviderHelper.ts index 5f5f16b044..bbb3d190bc 100644 --- a/packages/inference/src/lib/getProviderHelper.ts +++ b/packages/inference/src/lib/getProviderHelper.ts @@ -15,6 +15,7 @@ import * as Nscale from "../providers/nscale.js"; import * as OpenAI from "../providers/openai.js"; import * as OvhCloud from "../providers/ovhcloud.js"; import * as PublicAI from "../providers/publicai.js"; +import * as SiliconFlow from "../providers/siliconflow.js"; import type { AudioClassificationTaskHelper, AudioToAudioTaskHelper, @@ -169,6 +170,9 @@ export const PROVIDERS: Record = { replicate: "replicate", sambanova: "sambanovasystems", scaleway: "scaleway", + siliconflow: "siliconflow", together: "togethercomputer", wavespeed: "wavespeed", "zai-org": "zai-org", diff --git a/packages/inference/test/InferenceClient.spec.ts b/packages/inference/test/InferenceClient.spec.ts index fcb6e55cb3..ca008c0d50 100644 --- a/packages/inference/test/InferenceClient.spec.ts +++ b/packages/inference/test/InferenceClient.spec.ts @@ -2572,4 +2572,99 @@ describe.skip("InferenceClient", () => { }, TIMEOUT ); + describe.concurrent( + "SiliconFlow", + () => { + const client = new InferenceClient(env.HF_SILICONFLOW_KEY ?? "dummy"); + + HARDCODED_MODEL_INFERENCE_MAPPING["siliconflow"] = { + "deepseek-ai/DeepSeek-R1": { + provider: "siliconflow", + hfModelId: "deepseek-ai/DeepSeek-R1", + providerId: "deepseek-ai/DeepSeek-R1", + status: "live", + task: "conversational", + }, + "deepseek-ai/DeepSeek-V3": { + provider: "siliconflow", + hfModelId: "deepseek-ai/DeepSeek-V3", + providerId: "deepseek-ai/DeepSeek-V3", + status: "live", + task: "conversational", + }, + }; + + it("chatCompletion - DeepSeek-R1", async () => { + const res = await client.chatCompletion({ + model: "deepseek-ai/DeepSeek-R1", + provider: "siliconflow", + messages: [{ role: "user", content: "What is the capital of France?" }], + 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(/Paris/i); + } + }); + + it("chatCompletion - DeepSeek-V3", async () => { + const res = await client.chatCompletion({ + model: "deepseek-ai/DeepSeek-V3", + provider: "siliconflow", + messages: [{ role: "user", content: "The weather today is" }], + max_tokens: 10, + }); + expect(res.choices).toBeDefined(); + expect(res.choices?.length).toBeGreaterThan(0); + expect(res.choices?.[0].message?.content).toBeDefined(); + expect(typeof res.choices?.[0].message?.content).toBe("string"); + expect(res.choices?.[0].message?.content?.length).toBeGreaterThan(0); + }); + + it("chatCompletion stream - DeepSeek-R1", async () => { + const stream = client.chatCompletionStream({ + model: "deepseek-ai/DeepSeek-R1", + provider: "siliconflow", + messages: [{ role: "user", content: "Say 'this is a test'" }], + stream: true, + }) 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; + } + } + } + expect(fullResponse).toBeTruthy(); + expect(fullResponse.length).toBeGreaterThan(0); + }); + + it("chatCompletion stream - DeepSeek-V3", async () => { + const stream = client.chatCompletionStream({ + model: "deepseek-ai/DeepSeek-V3", + provider: "siliconflow", + messages: [{ role: "user", content: "Say 'this is a test'" }], + stream: true, + }) 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; + } + } + } + expect(fullResponse).toBeTruthy(); + expect(fullResponse.length).toBeGreaterThan(0); + }); + }, + TIMEOUT + ); });