Added models listing endpoint

This commit is contained in:
2025-12-20 22:02:57 +01:00
parent e4a711fcbd
commit ae2b9e9f41
3 changed files with 126 additions and 0 deletions

View File

@@ -116,6 +116,79 @@ public class AIProvider
throw; throw;
} }
} }
public string[] GetModels()
{
var aIProviders = aIProvidersConfiguration.AiProviders;
List<string> results = [];
foreach (KeyValuePair<string, AIProviderConfiguration> aIProviderKV in aIProviders)
{
string aIProviderName = aIProviderKV.Key;
AIProviderConfiguration aIProvider = aIProviderKV.Value;
using var httpClient = new HttpClient();
string modelNameJsonPath = "";
Uri baseUri = new(aIProvider.BaseURL);
Uri requestUri;
string[][] requestHeaders = [];
switch (aIProvider.Handler)
{
case "ollama":
modelNameJsonPath = "$.models[*].name";
requestUri = new Uri(baseUri, "/api/tags");
break;
case "openai":
modelNameJsonPath = "$.data[*].id";
requestUri = new Uri(baseUri, "/v1/models");
if (aIProvider.ApiKey is not null)
{
requestHeaders = [
["Authorization", $"Bearer {aIProvider.ApiKey}"]
];
}
break;
default:
_logger.LogError("Unknown handler {aIProvider.Handler} in AiProvider {provider}.", [aIProvider.Handler, aIProvider]);
throw new ServerConfigurationException($"Unknown handler {aIProvider.Handler} in AiProvider {aIProvider}.");
}
var request = new HttpRequestMessage()
{
RequestUri = requestUri,
Method = HttpMethod.Post
};
foreach (var header in requestHeaders)
{
request.Headers.Add(header[0], header[1]);
}
HttpResponseMessage response = httpClient.GetAsync(requestUri).Result;
string responseContent = response.Content.ReadAsStringAsync().Result;
try
{
JObject responseContentJson = JObject.Parse(responseContent);
IEnumerable<JToken>? responseContentTokens = responseContentJson.SelectTokens(modelNameJsonPath);
if (responseContentTokens is null)
{
_logger.LogError("Unable to select tokens using JSONPath {modelNameJsonPath} for string: {responseContent}.", [modelNameJsonPath, responseContent]);
throw new JSONPathSelectionException(modelNameJsonPath, responseContent);
}
IEnumerable<string?> aIProviderResult = responseContentTokens.Values<string>();
foreach (string? result in aIProviderResult)
{
if (result is null) continue;
results.Add(aIProviderName + ":" + result);
}
}
catch (Exception ex)
{
_logger.LogError("Unable to parse the response to valid models. {ex.Message}", [ex.Message]);
throw;
}
}
return [.. results];
}
} }
public class AIProvidersConfiguration public class AIProvidersConfiguration

View File

@@ -0,0 +1,38 @@
namespace Server.Controllers;
using System.Text.Json;
using ElmahCore;
using Microsoft.AspNetCore.Mvc;
using Server.Exceptions;
using Server.Helper;
using Shared.Models;
[ApiController]
[Route("[controller]")]
public class ServerController : ControllerBase
{
private readonly ILogger<ServerController> _logger;
private readonly IConfiguration _config;
private AIProvider _aIProvider;
public ServerController(ILogger<ServerController> logger, IConfiguration config, AIProvider aIProvider)
{
_logger = logger;
_config = config;
_aIProvider = aIProvider;
}
[HttpGet("GetModels")]
public ActionResult<ServerGetModelsResult> GetModels()
{
try
{
string[] models = _aIProvider.GetModels();
return new ServerGetModelsResult() { Models = models, Success = true };
} catch (Exception ex)
{
_logger.LogError("Unable to get models due to exception {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]);
return new ServerGetModelsResult() { Success = false, Message = ex.Message};
}
}
}

View File

@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
namespace Shared.Models;
public class ServerGetModelsResult
{
[JsonPropertyName("Success")]
public required bool Success { get; set; }
[JsonPropertyName("Message")]
public string? Message { get; set; }
[JsonPropertyName("Models")]
public string[]? Models { get; set; }
}