Skip to content

Commit 38dee70

Browse files
HavenDVclaude
andcommitted
feat: Add Nvidia Cloud and Ollama Cloud as CustomProviders
Add two new OpenAI-compatible providers for cloud-hosted inference: - Nvidia NIM (build.nvidia.com) with chat, streaming, tools, and embeddings - Ollama Cloud (ollama.com) with chat, streaming, and embeddings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 99bd4fd commit 38dee70

7 files changed

Lines changed: 117 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ Each custom provider requires specific environment variables to run its integrat
124124
| **Nebius** | `NEBIUS_API_KEY` | `Qwen/Qwen2.5-72B-Instruct` | Chat, streaming, tools, embeddings (`BAAI/bge-en-icl`) |
125125
| **GitHub Models** | `TOKEN_FOR_GITHUB_MODELS` | `gpt-4o` | Chat, streaming, tools, embeddings (`text-embedding-3-small`) |
126126
| **Hyperbolic** | `HYPERBOLIC_API_KEY`, `HYPERBOLIC_CHAT_MODEL` (optional) | `meta-llama/Llama-3.3-70B-Instruct` | Chat, streaming |
127+
| **Nvidia** | `NVIDIA_API_KEY`, `NVIDIA_CHAT_MODEL` (optional) | `meta/llama-3.3-70b-instruct` | Chat, streaming, tools, embeddings (`nvidia/nv-embedqa-e5-v5`) |
128+
| **Ollama Cloud** | `OLLAMA_API_KEY`, `OLLAMA_CLOUD_CHAT_MODEL` (optional) | `llama3.2` | Chat, streaming, embeddings (`nomic-embed-text`) |
127129
| **Ollama** | *(local, no key)* | `llama3.2` | Chat, streaming (local only) |
128130
| **LM Studio** | *(local, no key)* | `lmstudio-community/Llama-3.2-3B-Instruct-GGUF` | Chat, streaming (local only) |
129131

src/libs/tryAGI.OpenAI/CustomProviders.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ public static class CustomProviders
9696
/// </summary>
9797
public const string NebiusBaseUrl = "https://api.studio.nebius.ai/v1/";
9898

99+
/// <summary>
100+
/// https://build.nvidia.com/
101+
/// </summary>
102+
public const string NvidiaBaseUrl = "https://integrate.api.nvidia.com/v1";
103+
104+
/// <summary>
105+
/// https://ollama.com/
106+
/// </summary>
107+
public const string OllamaCloudBaseUrl = "https://ollama.com/api/v1";
108+
99109
/// <summary>
100110
/// Creates an API to use for GitHub Models: https://github.com/marketplace/models
101111
/// </summary>
@@ -266,4 +276,22 @@ public static OpenAiClient Nebius(string apiKey)
266276
{
267277
return new OpenAiClient(apiKey, baseUri: new Uri(NebiusBaseUrl));
268278
}
279+
280+
/// <summary>
281+
/// Create an API to use for Nvidia NIM.
282+
/// </summary>
283+
/// <returns></returns>
284+
public static OpenAiClient Nvidia(string apiKey)
285+
{
286+
return new OpenAiClient(apiKey, baseUri: new Uri(NvidiaBaseUrl));
287+
}
288+
289+
/// <summary>
290+
/// Create an API to use for Ollama Cloud.
291+
/// </summary>
292+
/// <returns></returns>
293+
public static OpenAiClient OllamaCloud(string apiKey)
294+
{
295+
return new OpenAiClient(apiKey, baseUri: new Uri(OllamaCloudBaseUrl));
296+
}
269297
}

src/tests/OpenAI.IntegrationTests/CustomProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ public enum CustomProvider
2222
Cerebras,
2323
Cohere,
2424
Nebius,
25+
Nvidia,
26+
OllamaCloud,
2527
}

src/tests/OpenAI.IntegrationTests/Tests.Chat.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public partial class Tests
1919
[DataRow(CustomProvider.Mistral)]
2020
[DataRow(CustomProvider.Codestral)]
2121
[DataRow(CustomProvider.Hyperbolic)]
22+
[DataRow(CustomProvider.Nvidia)]
23+
[DataRow(CustomProvider.OllamaCloud)]
2224
public async Task GenerateFiveRandomWords(CustomProvider customProvider)
2325
{
2426
var pair = GetAuthorizedChatApi(customProvider);
@@ -54,6 +56,8 @@ public async Task GenerateFiveRandomWords(CustomProvider customProvider)
5456
[DataRow(CustomProvider.Mistral)]
5557
//[DataRow(CustomProvider.Codestral)]
5658
[DataRow(CustomProvider.Hyperbolic)]
59+
[DataRow(CustomProvider.Nvidia)]
60+
[DataRow(CustomProvider.OllamaCloud)]
5761
public async Task GenerateFiveRandomWordsAsStream(CustomProvider customProvider)
5862
{
5963
var pair = GetAuthorizedChatApi(customProvider);
@@ -88,6 +92,8 @@ public async Task GenerateFiveRandomWordsAsStream(CustomProvider customProvider)
8892
[DataRow(CustomProvider.Groq)]
8993
//[DataRow(CustomProvider.XAi)]
9094
[DataRow(CustomProvider.Hyperbolic)]
95+
[DataRow(CustomProvider.Nvidia)]
96+
[DataRow(CustomProvider.OllamaCloud)]
9197
public async Task GenerateFiveRandomWordsAsJsonObject(CustomProvider customProvider)
9298
{
9399
var pair = GetAuthorizedChatApi(customProvider);

src/tests/OpenAI.IntegrationTests/Tests.ChatClient.CustomProviders.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,35 @@ public Task ChatClient_Nebius_Streaming() =>
341341
public Task ChatClient_Nebius_ToolCalling() =>
342342
ChatClient_CustomProvider_ToolCallingAsync(CustomProvider.Nebius);
343343

344+
// --- Nvidia ---
345+
346+
[TestMethod]
347+
[Retry(2)]
348+
public Task ChatClient_Nvidia_GetResponse() =>
349+
ChatClient_CustomProvider_GetResponseAsync(CustomProvider.Nvidia);
350+
351+
[TestMethod]
352+
[Retry(2)]
353+
public Task ChatClient_Nvidia_Streaming() =>
354+
ChatClient_CustomProvider_StreamingAsync(CustomProvider.Nvidia);
355+
356+
[TestMethod]
357+
[Retry(2)]
358+
public Task ChatClient_Nvidia_ToolCalling() =>
359+
ChatClient_CustomProvider_ToolCallingAsync(CustomProvider.Nvidia);
360+
361+
// --- Ollama Cloud ---
362+
363+
[TestMethod]
364+
[Retry(2)]
365+
public Task ChatClient_OllamaCloud_GetResponse() =>
366+
ChatClient_CustomProvider_GetResponseAsync(CustomProvider.OllamaCloud);
367+
368+
[TestMethod]
369+
[Retry(2)]
370+
public Task ChatClient_OllamaCloud_Streaming() =>
371+
ChatClient_CustomProvider_StreamingAsync(CustomProvider.OllamaCloud);
372+
344373
// --- GitHub Models ---
345374

346375
//[TestMethod]

src/tests/OpenAI.IntegrationTests/Tests.EmbeddingGenerator.CustomProviders.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,34 @@ public Task EmbeddingGenerator_Nebius_Batch() =>
129129
EmbeddingGenerator_CustomProvider_BatchAsync(
130130
CustomProvider.Nebius, "BAAI/bge-en-icl");
131131

132+
// --- Nvidia ---
133+
134+
[TestMethod]
135+
[Retry(2)]
136+
public Task EmbeddingGenerator_Nvidia_Generate() =>
137+
EmbeddingGenerator_CustomProvider_GenerateAsync(
138+
CustomProvider.Nvidia, "nvidia/nv-embedqa-e5-v5");
139+
140+
[TestMethod]
141+
[Retry(2)]
142+
public Task EmbeddingGenerator_Nvidia_Batch() =>
143+
EmbeddingGenerator_CustomProvider_BatchAsync(
144+
CustomProvider.Nvidia, "nvidia/nv-embedqa-e5-v5");
145+
146+
// --- Ollama Cloud ---
147+
148+
[TestMethod]
149+
[Retry(2)]
150+
public Task EmbeddingGenerator_OllamaCloud_Generate() =>
151+
EmbeddingGenerator_CustomProvider_GenerateAsync(
152+
CustomProvider.OllamaCloud, "nomic-embed-text");
153+
154+
[TestMethod]
155+
[Retry(2)]
156+
public Task EmbeddingGenerator_OllamaCloud_Batch() =>
157+
EmbeddingGenerator_CustomProvider_BatchAsync(
158+
CustomProvider.OllamaCloud, "nomic-embed-text");
159+
132160
// --- Azure ---
133161

134162
[TestMethod]

src/tests/OpenAI.IntegrationTests/Tests.Helpers.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,28 @@ internal static (OpenAiClient Api, string Model) GetAuthorizedChatApi(CustomProv
209209
: throw new AssertInconclusiveException("NEBIUS_API_KEY environment variable is not found.")),
210210
model ?? "Qwen/Qwen2.5-72B-Instruct");
211211
}
212+
if (customProvider == CustomProvider.Nvidia)
213+
{
214+
return (CustomProviders.Nvidia(apiKey:
215+
Environment.GetEnvironmentVariable("NVIDIA_API_KEY") is { Length: > 0 } nvidiaKeyValue
216+
? nvidiaKeyValue
217+
: throw new AssertInconclusiveException("NVIDIA_API_KEY environment variable is not found.")),
218+
model ??
219+
(Environment.GetEnvironmentVariable("NVIDIA_CHAT_MODEL") is { Length: > 0 } nvidiaModel
220+
? nvidiaModel
221+
: "meta/llama-3.3-70b-instruct"));
222+
}
223+
if (customProvider == CustomProvider.OllamaCloud)
224+
{
225+
return (CustomProviders.OllamaCloud(apiKey:
226+
Environment.GetEnvironmentVariable("OLLAMA_API_KEY") is { Length: > 0 } ollamaCloudKeyValue
227+
? ollamaCloudKeyValue
228+
: throw new AssertInconclusiveException("OLLAMA_API_KEY environment variable is not found.")),
229+
model ??
230+
(Environment.GetEnvironmentVariable("OLLAMA_CLOUD_CHAT_MODEL") is { Length: > 0 } ollamaCloudModel
231+
? ollamaCloudModel
232+
: "llama3.2"));
233+
}
212234

213235
var apiKey =
214236
Environment.GetEnvironmentVariable("OPENAI_API_KEY") is { Length: > 0 } openAiKeyValue

0 commit comments

Comments
 (0)