Files
ChatBot/ChatBot/Services/ModelService.cs
2025-10-15 20:36:55 +03:00

189 lines
6.1 KiB
C#

using ChatBot.Models.Configuration;
using Microsoft.Extensions.Options;
using ServiceStack;
namespace ChatBot.Services
{
public class ModelService
{
private readonly ILogger<ModelService> _logger;
private readonly OpenRouterSettings _openRouterSettings;
private readonly JsonApiClient _client;
private List<string> _availableModels = new();
private int _currentModelIndex = 0;
public ModelService(
ILogger<ModelService> logger,
IOptions<OpenRouterSettings> openRouterSettings
)
{
_logger = logger;
_openRouterSettings = openRouterSettings.Value;
_client = new JsonApiClient(_openRouterSettings.Url)
{
BearerToken = _openRouterSettings.Token,
};
}
public async Task InitializeAsync()
{
try
{
var models = await LoadModelsFromApiAsync();
_availableModels = models.Any()
? models
: _openRouterSettings.AvailableModels.ToList();
SetDefaultModel();
_logger.LogInformation("Current model: {Model}", GetCurrentModel());
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to initialize models, using configuration fallback");
_availableModels = _openRouterSettings.AvailableModels.ToList();
_currentModelIndex = 0;
}
}
private async Task<List<string>> LoadModelsFromApiAsync()
{
var response = await _client.GetAsync<dynamic>("/v1/models");
if (response == null)
{
_logger.LogInformation(
"Using {Count} models from configuration (API unavailable)",
_openRouterSettings.AvailableModels.Count
);
return new List<string>();
}
var models = ParseModelsFromResponse(response);
if (models.Any())
{
_logger.LogInformation(
"Loaded {Count} models from OpenRouter API",
(int)models.Count
);
return models;
}
_logger.LogInformation(
"Using {Count} models from configuration",
_openRouterSettings.AvailableModels.Count
);
return new List<string>();
}
private static List<string> ParseModelsFromResponse(dynamic response)
{
var models = new List<string>();
if (response is not System.Text.Json.JsonElement jsonElement)
return models;
if (
!jsonElement.TryGetProperty("data", out var dataElement)
|| dataElement.ValueKind != System.Text.Json.JsonValueKind.Array
)
return models;
foreach (var modelElement in dataElement.EnumerateArray())
{
if (modelElement.TryGetProperty("id", out var idElement))
{
var modelId = idElement.GetString();
if (!string.IsNullOrEmpty(modelId))
{
models.Add(modelId);
}
}
}
return models;
}
private void SetDefaultModel()
{
if (
string.IsNullOrEmpty(_openRouterSettings.DefaultModel)
|| !_availableModels.Contains(_openRouterSettings.DefaultModel)
)
{
_currentModelIndex = 0;
return;
}
_currentModelIndex = _availableModels.IndexOf(_openRouterSettings.DefaultModel);
}
public string GetCurrentModel()
{
return _availableModels.Count > 0 ? _availableModels[_currentModelIndex] : string.Empty;
}
/// <summary>
/// Получает настройки для текущей модели
/// </summary>
/// <returns>Настройки модели или настройки по умолчанию</returns>
public ModelSettings GetCurrentModelSettings()
{
var currentModel = GetCurrentModel();
if (string.IsNullOrEmpty(currentModel))
{
return GetDefaultModelSettings();
}
// Ищем настройки для текущей модели
var modelConfig = _openRouterSettings.ModelConfigurations.FirstOrDefault(m =>
m.Name.Equals(currentModel, StringComparison.OrdinalIgnoreCase)
);
if (modelConfig != null)
{
return modelConfig;
}
// Если настройки не найдены, возвращаем настройки по умолчанию
return GetDefaultModelSettings();
}
/// <summary>
/// Получает настройки по умолчанию
/// </summary>
/// <returns>Настройки по умолчанию</returns>
private ModelSettings GetDefaultModelSettings()
{
return new ModelSettings
{
Name = GetCurrentModel(),
MaxTokens = _openRouterSettings.MaxTokens,
Temperature = _openRouterSettings.Temperature,
IsEnabled = true,
};
}
public bool TrySwitchToNextModel()
{
if (_availableModels.Count <= 1)
{
_logger.LogWarning("No alternative models available for switching");
return false;
}
_currentModelIndex = (_currentModelIndex + 1) % _availableModels.Count;
_logger.LogInformation("Switched to model: {Model}", GetCurrentModel());
return true;
}
public List<string> GetAvailableModels()
{
return _availableModels.ToList();
}
public bool HasAlternativeModels()
{
return _availableModels.Count > 1;
}
}
}