Integración de Inteligencia Artificial en Aplicaciones ASP.NET Core

Arquitectura para Aplicaciones Inteligentes con ASP.NET Core

La combinación de ASP.NET Core con tecnologías de inteligencia artificial permite crear aplicaciones web altamente inteligentes, escalables y mantenibles. Este enfoque facilita la incorporación de capacidades como aprendizaje automático, procesamiento del lenguaje natural y visión por computadora directamente en servicios web modernos.

Servicios de Aprendizaje Automático en .NET

ML.NET ofrece una inetgración nativa con ASP.NET Core, permitiendo cargar modelos preentrenados y realizar inferancias en tiempo real. La clave está en gestionar correctamente el ciclo de vida del modelo mediante inyección de deepndencias:

public interface IPrediccionService
{
    Task<ResultadoPrediccion> PredecirAsync(EntradaDatos datos);
}

public class ServicioPrediccion : IPrediccionService
{
    private readonly ILogger<ServicioPrediccion> _logger;
    private readonly PredictionEnginePool<EntradaDatos, ResultadoPrediccion> _motor;

    public ServicioPrediccion(
        PredictionEnginePool<EntradaDatos, ResultadoPrediccion> motor,
        ILogger<ServicioPrediccion> logger)
    {
        _motor = motor;
        _logger = logger;
    }

    public async Task<ResultadoPrediccion> PredecirAsync(EntradaDatos entrada)
    {
        try
        {
            var resultado = _motor.Predict("ModeloClasificacion", entrada);
            _logger.LogInformation("Predicción generada: {Etiqueta}", resultado.EtiquetaPredecida);
            return await Task.FromResult(resultado);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error durante la predicción");
            throw;
        }
    }
}

En Program.cs, se configura el pool de motores para reutilizar instancias y mejorar el rendimiento:

builder.Services.AddPredictionEnginePool<EntradaDatos, ResultadoPrediccion>()
    .FromFile("ModeloClasificacion", "modelos/clasificador.zip", watchForChanges: true);

Despliegue de Modelos ONNX

Para modelos entrenados en Python (TensorFlow/PyTorch), el formato ONNX permite su ejecución en entornos .NET mediante Microsoft.ML.OnnxRuntime:

public class MotorOnnx : IDisposable
{
    private readonly InferenceSession _sesion;
    private bool _disposed = false;

    public MotorOnnx(string rutaModelo)
    {
        _sesion = new InferenceSession(rutaModelo);
    }

    public float[] Inferir(float[,] datosEntrada)
    {
        var tensor = new DenseTensor<float>(datosEntrada, new int[] { 1, datosEntrada.GetLength(0), datosEntrada.GetLength(1) });
        var entrada = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("entrada", tensor) };

        using var salida = _sesion.Run(entrada);
        return salida.First().AsTensor<float>().ToArray();
    }

    public void Dispose()
    {
        if (!_disposed)
        {
            _sesion?.Dispose();
            _disposed = true;
        }
    }
}

Optimización del Rendimiento con Procesamiento por Lotes

Para escenarios con alta carga, agrupar múltiples solicitudes mejora significativamente la eficiencia del uso de recursos:

public class ProcesadorPorLotes
{
    private readonly Queue<SolicitudProcesada> _cola = new();
    private readonly Timer _temporizador;
    private readonly int _tamanoLote = 64;

    public ProcesadorPorLotes()
    {
        _temporizador = new Timer(EjecutarLote, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(50));
    }

    private void EjecutarLote(object state)
    {
        var lote = new List<SolicitudProcesada>();
        lock (_cola)
        {
            while (_cola.Count > 0 && lote.Count < _tamanoLote)
            {
                lote.Add(_cola.Dequeue());
            }
        }

        if (lote.Any())
        {
            var resultados = RealizarInferenciaEnLote(lote.Select(s => s.Datos).ToArray());
            AsignarResultados(lote, resultados);
        }
    }

    public Task<RespuestaInferencia> EnviarSolicitudAsync(DatosEntrada datos)
    {
        var fuente = new TaskCompletionSource<RespuestaInferencia>();
        var solicitud = new SolicitudProcesada(datos, fuente);

        lock (_cola)
        {
            _cola.Enqueue(solicitud);
        }

        return fuente.Task;
    }
}

Gestión de Versiones y Pruebas A/B

Implementar múltiples versiones de modelos permite pruebas controladas y despliegues progresivos:

[ApiController]
[Route("api/[controller]")]
public class ClasificacionController : ControllerBase
{
    private readonly Dictionary<string, IPrediccionService> _servicios;

    public ClasificacionController(IEnumerable<IPrediccionService> servicios)
    {
        _servicios = servicios.ToDictionary(s => s.GetType().Name);
    }

    [HttpPost("clasificar")]
    public async Task<iactionresult> Clasificar([FromBody] EntradaUsuario entrada, [FromQuery] string version = "default")
    {
        var servicio = _servicios.ContainsKey(version) 
            ? _servicios[version] 
            : _servicios.Values.First();

        var resultado = await servicio.PredecirAsync(new EntradaDatos { Contenido = entrada.Texto });
        return Ok(new { Etiqueta = resultado.EtiquetaPredecida, Confianza = resultado.Puntuacion });
    }
}
</iactionresult>

Integración de APIs de Procesamiento del Lenguaje Natural

El uso de IHttpClientFactory junto con políticas de resiliencia asegura comunicaciones estables con servicios externos:

services.AddHttpClient("ApiLenguaje", cliente =>
{
    cliente.BaseAddress = new Uri(builder.Configuration["Apis:Lenguaje:Url"]);
    cliente.DefaultRequestHeaders.Authorization = 
        new AuthenticationHeaderValue("Bearer", builder.Configuration["Apis:Lenguaje:Token"]);
})
.AddPolicyHandler(ConfigurarReintento())
.AddPolicyHandler(ConfigurarCircuito());

Las políticas garantizan tolerancia a fallos transitorios:

static IAsyncPolicy<HttpResponseMessage> ConfigurarReintento()
{
    return Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                 .WaitAndRetryAsync(3, i => TimeSpan.FromMilliseconds(200 * Math.Pow(2, i)));
}

Visión por Computadora con OpenCVSharp

OpenCVSharp permite procesar imágenes en tiempo real dentro de servicios background:

public class ServicioDeteccionRostros : BackgroundService
{
    private readonly VideoCapture _camara;
    private readonly CascadeClassifier _detector;

    public ServicioDeteccionRostros()
    {
        _camara = new VideoCapture(0);
        _detector = new CascadeClassifier("modelos/rostro.xml");
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var frame = new Mat();
            _camara.Read(frame);

            if (frame.IsEmpty()) continue;

            var rostros = _detector.Detect(frame);
            foreach (var rect in rostros)
            {
                Cv2.Rectangle(frame, rect, Scalar.Red, 2);
            }

            // Publicar imagen procesada vía SignalR o guardar
            await Task.Delay(30, stoppingToken);
        }
    }
}

Monitoreo y Diagnóstico

Mediante middleware personalizado se puede rastrear el rendimiento de las inferencias:

app.Use(async (context, next) =>
{
    var inicio = DateTime.UtcNow;
    await next();
    var duracion = DateTime.UtcNow - inicio;

    if (context.Request.Path.StartsWithSegments("/api/prediccion"))
    {
        var logger = context.RequestServices.GetRequiredService<ILogger<MiddlewareRendimiento>>();
        logger.LogInformation("Inferencia completada en {ms} ms", duracion.TotalMilliseconds);
    }
});

Despliegue con Docker

Un archivo Dockerfile optimizado incluye los modelos y bibliotecas necesarias:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
COPY modelos/ ./modelos/
COPY modelos/rostro.xml ./modelos/
ENTRYPOINT ["dotnet", "AplicacionAI.dll"]

Esta arquitectura permite escalar horizontalmente servicios de IA mientras se mantiene la consistencia del entorno y la reproducibilidad del despliegue.

Etiquetas: ASP.NET Core ml.net ONNX OpenCVSharp IHttpClientFactory

Publicado el 9-27 09:23