Skip to content

Commit cd4dafe

Browse files
committed
feat: add NVIDIA NIM and Hugging Face as BYOK providers
- NVIDIA NIM: free 40 RPM, no daily cap, OpenAI-compatible Base: integrate.api.nvidia.com/v1 Default: meta/llama-3.1-405b-instruct - Hugging Face: free ~few hundred req/hr, OpenAI-compatible Base: router.huggingface.co/v1 Default: meta-llama/Llama-3.1-70B-Instruct - Both useful as overflow when Cloudflare 10K neurons/day limit hit - Added to resolveProviderDefaults, RECOMMENDED list, and validate
1 parent bd957d6 commit cd4dafe

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

backend/simpatico-ats.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ function resolveProviderDefaults(cfg) {
607607
} else if (p === "deepseek") {
608608
baseUrl = baseUrl || "https://api.deepseek.com/v1";
609609
model = model || "deepseek-chat";
610+
} else if (p === "nvidia") {
611+
baseUrl = baseUrl || "https://integrate.api.nvidia.com/v1";
612+
model = model || "meta/llama-3.1-405b-instruct";
613+
} else if (p === "huggingface") {
614+
baseUrl = baseUrl || "https://router.huggingface.co/v1";
615+
model = model || "meta-llama/Llama-3.1-70B-Instruct";
610616
}
611617
// custom / other: user must supply both
612618

@@ -7477,6 +7483,8 @@ async function handleBYOKValidate(request, env, ctx) {
74777483
anthropic: ["claude-sonnet-4-20250514", "claude-3-5-sonnet-20241022", "claude-3-haiku-20240307"],
74787484
deepseek: ["deepseek-chat", "deepseek-reasoner"],
74797485
kimi: ["kimi-k2-0520", "moonshot-v1-128k", "moonshot-v1-32k"],
7486+
nvidia: ["meta/llama-3.1-405b-instruct", "meta/llama-3.3-70b-instruct", "mistralai/mixtral-8x22b-instruct-v0.1"],
7487+
huggingface: ["meta-llama/Llama-3.1-70B-Instruct", "Qwen/Qwen2.5-72B-Instruct", "mistralai/Mistral-7B-Instruct-v0.3"],
74807488
};
74817489

74827490
try {
@@ -7601,6 +7609,44 @@ async function handleBYOKValidate(request, env, ctx) {
76017609
id: m.id, name: m.id, recommended: (RECOMMENDED.kimi || []).includes(m.id),
76027610
}));
76037611

7612+
} else if (provider === "nvidia") {
7613+
// NVIDIA NIM — OpenAI-compatible, free tier 40 RPM
7614+
const nimUrl = (base_url || "https://integrate.api.nvidia.com/v1") + "/models";
7615+
const res = await fetch(nimUrl, { headers: { Authorization: `Bearer ${api_key}` } });
7616+
if (!res.ok) {
7617+
const errText = await res.text().catch(() => "");
7618+
return apiResponse({
7619+
connected: false, provider: "nvidia",
7620+
error: res.status === 401 || res.status === 403 ? "Invalid API key — get one at build.nvidia.com" : `API error ${res.status}: ${errText.substring(0, 100)}`,
7621+
});
7622+
}
7623+
const data = await res.json();
7624+
models = (data.data || [])
7625+
.filter(m => m.id && (m.id.includes("llama") || m.id.includes("mistral") || m.id.includes("mixtral") || m.id.includes("qwen") || m.id.includes("gemma") || m.id.includes("deepseek")))
7626+
.map(m => ({ id: m.id, name: m.id, recommended: (RECOMMENDED.nvidia || []).includes(m.id) }))
7627+
.sort((a, b) => (b.recommended ? 1 : 0) - (a.recommended ? 1 : 0));
7628+
7629+
} else if (provider === "huggingface") {
7630+
// Hugging Face — OpenAI-compatible router, free tier ~few hundred req/hr
7631+
const hfUrl = (base_url || "https://router.huggingface.co/v1") + "/models";
7632+
const res = await fetch(hfUrl, { headers: { Authorization: `Bearer ${api_key}` } });
7633+
if (!res.ok) {
7634+
const errText = await res.text().catch(() => "");
7635+
return apiResponse({
7636+
connected: false, provider: "huggingface",
7637+
error: res.status === 401 ? "Invalid token — get one at huggingface.co/settings/tokens" : `API error ${res.status}: ${errText.substring(0, 100)}`,
7638+
});
7639+
}
7640+
const data = await res.json();
7641+
models = (data.data || [])
7642+
.filter(m => m.id)
7643+
.map(m => ({ id: m.id, name: m.id, recommended: (RECOMMENDED.huggingface || []).includes(m.id) }))
7644+
.sort((a, b) => (b.recommended ? 1 : 0) - (a.recommended ? 1 : 0));
7645+
// If model listing fails (HF may not support /models), provide curated list
7646+
if (models.length === 0) {
7647+
models = (RECOMMENDED.huggingface || []).map(id => ({ id, name: id, recommended: true }));
7648+
}
7649+
76047650
} else {
76057651
const customUrl = (base_url || "").replace(/\/$/, "") + "/models";
76067652
try {

0 commit comments

Comments
 (0)