feat: Gemini als Provider hinzugefügt (Free-Tier-Modelle hardcodiert)

- OpenAiService: Gemini-Provider mit Base-URL generativelanguage.googleapis.com/v1beta/openai
- GeminiApiKey aus IConfiguration (appsettings.json / appsettings.Production.json)
- Gemini Free-Tier-Modelle hardcodiert: 2.5 Pro, 2.5 Flash, 2.5 Flash Lite
- ModelsEndpoint: /api/models/gemini Endpoint
- Frontend: geminiOptgroup dynamisch befüllt
- ProviderKeys als static HashSet (für ChatService.ResolveModelId)
This commit is contained in:
Meleki committed 2026-03-11 18:41:47 +01:00
1 parent 50e09bbc36
commit e87455ffe9
6 files changed
+45 -15

No files matched your search

+9
View File
@@ -12,6 +12,7 @@ public static class ModelsEndpoint
{
app.MapGet("/api/models/nvidia", HandleNvidiaModels);
app.MapGet("/api/models/pollinations", HandlePollinationsModels);
app.MapGet("/api/models/gemini", HandleGeminiModels);
}
private static IResult HandleNvidiaModels(OpenAiService openAiService)
@@ -29,4 +30,12 @@ public static class ModelsEndpoint
.ToList();
return Results.Json(new { models });
}
private static IResult HandleGeminiModels(OpenAiService openAiService)
{
var models = openAiService.GetGeminiModels()
.Select(m => new { id = m.Id, displayName = m.DisplayName })
.ToList();
return Results.Json(new { models });
}
}
+1 -1
View File
@@ -70,7 +70,7 @@ builder.Services.AddSingleton<AnthropicService>(sp =>
// OpenAI-kompatibler Service (Nvidia etc.)
builder.Services.AddSingleton<OpenAiService>(sp =>
new OpenAiService(sp.GetRequiredService<IHttpClientFactory>(), dbService, sp.GetRequiredService<ToolService>()));
new OpenAiService(sp.GetRequiredService<IHttpClientFactory>(), dbService, sp.GetRequiredService<ToolService>(), builder.Configuration));
// Telegram Bot (pro Session – Token aus Session-Config)
var maxIterations = builder.Configuration.GetValue<int>("MaxIterations", 100);
+27 -12
View File
@@ -22,12 +22,11 @@ public class OpenAiService
private readonly DatabaseService _db;
private readonly ToolService _toolService;
// Provider-Definitionen
private static readonly Dictionary<string, (string BaseUrl, string ApiKey)> Providers = new()
{
["nvidia"] = ("https://g4f.space/api/nvidia/v1", ""),
["pollinations"] = ("https://text.pollinations.ai/openai", "")
};
// Provider-Keys (statisch für ChatService.ResolveModelId)
public static readonly HashSet<string> ProviderKeys = new() { "nvidia", "pollinations", "gemini" };
// Provider-Definitionen (inkl. API-Keys, instanzgebunden)
private readonly Dictionary<string, (string BaseUrl, string ApiKey)> Providers;
// Tools die für OpenAI-kompatible Provider verfügbar sind
private static readonly List<object> OpenAiTools = new()
@@ -151,12 +150,19 @@ public class OpenAiService
private List<ProviderModel> _nvidiaModels = new List<ProviderModel>();
private List<ProviderModel> _pollinationsModels = new List<ProviderModel>();
private List<ProviderModel> _geminiModels = new List<ProviderModel>();
public OpenAiService(IHttpClientFactory httpFactory, DatabaseService db, ToolService toolService)
public OpenAiService(IHttpClientFactory httpFactory, DatabaseService db, ToolService toolService, Microsoft.Extensions.Configuration.IConfiguration configuration)
{
_httpFactory = httpFactory;
_db = db;
_toolService = toolService;
Providers = new Dictionary<string, (string BaseUrl, string ApiKey)>
{
["nvidia"] = ("https://g4f.space/api/nvidia/v1", ""),
["pollinations"] = ("https://text.pollinations.ai/openai", ""),
["gemini"] = ("https://generativelanguage.googleapis.com/v1beta/openai", configuration["GeminiApiKey"] ?? "")
};
}
/// <summary>
@@ -164,15 +170,23 @@ public class OpenAiService
/// </summary>
public async Task LoadModelsAsync()
{
_nvidiaModels = await FetchModels("https://g4f.space/api/nvidia/models", "Nvidia");
_nvidiaModels = await FetchModels("https://g4f.space/api/nvidia/models", "Nvidia");
_pollinationsModels = await FetchModels("https://text.pollinations.ai/models", "Pollinations");
// Gemini: nur kostenlose Free-Tier-Modelle (hardcodiert)
_geminiModels = new List<ProviderModel>
{
new ProviderModel("gemini-2.5-pro", "Gemini 2.5 Pro"),
new ProviderModel("gemini-2.5-flash", "Gemini 2.5 Flash"),
new ProviderModel("gemini-2.5-flash-lite", "Gemini 2.5 Flash Lite"),
};
}
private async Task<List<ProviderModel>> FetchModels(string url, string providerName)
private async Task<List<ProviderModel>> FetchModels(string url, string providerName, string apiKey = "")
{
try
{
var client = CreateClient("");
var client = CreateClient(apiKey);
var resp = await client.GetAsync(url);
if (!resp.IsSuccessStatusCode) return new List<ProviderModel>();
@@ -211,8 +225,9 @@ public class OpenAiService
}
}
public List<ProviderModel> GetNvidiaModels() => _nvidiaModels;
public List<ProviderModel> GetNvidiaModels() => _nvidiaModels;
public List<ProviderModel> GetPollinationsModels() => _pollinationsModels;
public List<ProviderModel> GetGeminiModels() => _geminiModels;
/// <summary>
/// Gibt den Provider und das eigentliche Modell-ID aus einem kombinierten Model-String zurück.
@@ -232,7 +247,7 @@ public class OpenAiService
public static bool IsOpenAiProvider(string model)
{
var (provider, _) = ParseModelString(model);
return Providers.ContainsKey(provider);
return ProviderKeys.Contains(provider);
}
public async Task StreamChat(
+2 -1
View File
@@ -14,5 +14,6 @@
"PayloadLogging": false,
"PayloadLoggingGzip": false,
"KreaToken": "",
"KreaApiKey": ""
"KreaApiKey": "",
"GeminiApiKey": ""
}
+3
View File
@@ -191,6 +191,9 @@
<option value="opus-4-5">opus-4-5</option>
<option value="opus-4-6" selected>opus-4-6</option>
<option value="haiku-4-5">haiku-4-5</option>
<optgroup label="Google Gemini" id="geminiOptgroup">
<option value="" disabled>Wird geladen...</option>
</optgroup>
<optgroup label="Pollinations" id="pollinationsOptgroup">
<option value="" disabled>Wird geladen...</option>
</optgroup>
+3 -1
View File
@@ -20,6 +20,7 @@ registerPage('agent', {
const modelEl = document.getElementById('agentModel');
const nvidiaOptgroup = document.getElementById('nvidiaOptgroup');
const pollinationsOptgroup = document.getElementById('pollinationsOptgroup');
const geminiOptgroup = document.getElementById('geminiOptgroup');
// Modelle dynamisch laden
const loadProviderModels = async (url, prefix, optgroup) => {
@@ -42,7 +43,8 @@ registerPage('agent', {
await Promise.all([
loadProviderModels('/api/models/nvidia', 'nvidia', nvidiaOptgroup),
loadProviderModels('/api/models/pollinations', 'pollinations', pollinationsOptgroup)
loadProviderModels('/api/models/pollinations', 'pollinations', pollinationsOptgroup),
loadProviderModels('/api/models/gemini', 'gemini', geminiOptgroup)
]);
const allowUserChoiceEl = document.getElementById('agentAllowUserChoice');
const autoCommitEl = document.getElementById('agentAutoCommit');