Cache Provider-Modelle in models_cache.json statt bei jedem Start von APIs zu laden

- LoadModelsAsync() prüft zuerst data/models_cache.json
- Bei Cache-Hit: kein API-Call, sofortiger Start
- RefreshModelsFromApis() lädt von APIs + speichert Cache
- POST /api/models/refresh Endpoint für manuellen Refresh
- dataDir an OpenAiService-Konstruktor übergeben
This commit is contained in:
Meleki committed 2026-03-12 08:57:47 +01:00
1 parent 145441fa7b
commit ed6e78de56
3 files changed
+62 -5

No files matched your search

+53 -4
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
@@ -151,12 +152,14 @@ public class OpenAiService
private List<ProviderModel> _nvidiaModels = new List<ProviderModel>();
private List<ProviderModel> _pollinationsModels = new List<ProviderModel>();
private List<ProviderModel> _geminiModels = new List<ProviderModel>();
private readonly string _cacheFile;
public OpenAiService(IHttpClientFactory httpFactory, DatabaseService db, ToolService toolService, Microsoft.Extensions.Configuration.IConfiguration configuration)
public OpenAiService(IHttpClientFactory httpFactory, DatabaseService db, ToolService toolService, Microsoft.Extensions.Configuration.IConfiguration configuration, string dataDir)
{
_httpFactory = httpFactory;
_db = db;
_toolService = toolService;
_cacheFile = Path.Combine(dataDir, "models_cache.json");
Providers = new Dictionary<string, (string BaseUrl, string ApiKey)>
{
["nvidia"] = ("https://g4f.space/api/nvidia/v1", ""),
@@ -166,19 +169,65 @@ public class OpenAiService
}
/// <summary>
/// Lädt verfügbare Modelle aller Provider beim Server-Start und cached sie.
/// Lädt verfügbare Modelle – aus lokalem Cache (models_cache.json) oder von den APIs.
/// </summary>
public async Task LoadModelsAsync()
public async Task LoadModelsAsync(bool forceRefresh = false)
{
if (!forceRefresh && File.Exists(_cacheFile))
{
try
{
var json = await File.ReadAllTextAsync(_cacheFile);
var cache = JsonSerializer.Deserialize<Dictionary<string, List<ProviderModel>>>(json);
if (cache != null)
{
_nvidiaModels = cache.ContainsKey("nvidia") ? cache["nvidia"] : new List<ProviderModel>();
_pollinationsModels = cache.ContainsKey("pollinations") ? cache["pollinations"] : new List<ProviderModel>();
_geminiModels = cache.ContainsKey("gemini") ? cache["gemini"] : new List<ProviderModel>();
Console.WriteLine($"[OpenAiService] Modelle aus Cache geladen: {_nvidiaModels.Count} Nvidia, {_pollinationsModels.Count} Pollinations, {_geminiModels.Count} Gemini");
return;
}
}
catch (Exception ex)
{
Console.WriteLine($"[OpenAiService] Cache-Datei fehlerhaft, lade von APIs: {ex.Message}");
}
}
await RefreshModelsFromApis();
}
/// <summary>
/// Lädt Modelle von allen Provider-APIs und speichert sie im Cache.
/// </summary>
public async Task RefreshModelsFromApis()
{
_nvidiaModels = await FetchModels("https://g4f.space/api/nvidia/models", "Nvidia");
_pollinationsModels = await FetchModels("https://text.pollinations.ai/models", "Pollinations");
// Gemini: dynamisch von der API laden (Bearer-Token erforderlich)
var geminiApiKey = Providers["gemini"].ApiKey;
if (!string.IsNullOrEmpty(geminiApiKey))
_geminiModels = await FetchModels("https://generativelanguage.googleapis.com/v1beta/openai/models", "Gemini", geminiApiKey);
else
Console.WriteLine("[OpenAiService] GeminiApiKey nicht konfiguriert – Gemini-Modelle nicht geladen.");
// Cache speichern
try
{
var cache = new Dictionary<string, List<ProviderModel>>
{
["nvidia"] = _nvidiaModels,
["pollinations"] = _pollinationsModels,
["gemini"] = _geminiModels
};
var json = JsonSerializer.Serialize(cache, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(_cacheFile, json);
Console.WriteLine($"[OpenAiService] Modelle-Cache gespeichert: {_cacheFile}");
}
catch (Exception ex)
{
Console.WriteLine($"[OpenAiService] Fehler beim Speichern des Modelle-Cache: {ex.Message}");
}
}
private async Task<List<ProviderModel>> FetchModels(string url, string providerName, string apiKey = "")