Introducción
La IA generativa se ha convertido en una capacidad habitual dentro de aplicaciones empresariales: asistentes internos, generación de resúmenes, búsqueda conversacional, análisis de documentos, automatización de soporte y ayuda contextual para usuarios finales.
En el ecosistema .NET, C# permite integrar modelos de lenguaje de gran tamaño —LLMs— mediante servicios gestionados como Azure OpenAI Service y, cuando conviene desacoplar la aplicación del proveedor concreto, mediante abstracciones como Microsoft Extensions for AI. Además, herramientas como Semantic Kernel facilitan la orquestación de prompts, memoria, funciones y flujos más complejos.
Este artículo se centra en una implementación práctica y prudente: cómo llamar a un modelo desplegado en Azure OpenAI desde una aplicación .NET, qué decisiones arquitectónicas conviene tomar y qué riesgos técnicos deben gestionarse antes de llevar la solución a producción.
Conceptos clave antes de implementar
Antes de escribir código, es importante distinguir varios elementos que a menudo se mezclan:
- Modelo: familia o versión del LLM, por ejemplo un modelo GPT disponible en Azure OpenAI.
- Despliegue: nombre configurado dentro de Azure OpenAI para exponer un modelo concreto. En el código se suele invocar el nombre del despliegue, no necesariamente el nombre comercial del modelo.
- Prompt: instrucciones y contexto enviados al modelo.
- Tokens: unidades de texto procesadas por el modelo. Impactan en coste, latencia y límites de uso.
- Chat completion: patrón conversacional en el que se envían mensajes con roles como sistema, usuario y asistente.
- Grounding: técnica para aportar contexto externo, por ejemplo documentos internos, con el objetivo de reducir respuestas no verificadas.
- Orquestación: coordinación de prompts, herramientas, memoria, validaciones y llamadas a servicios externos.
La integración de un LLM no debe tratarse como una simple llamada HTTP más. En producción hay que considerar cuotas, latencia, seguridad, trazabilidad, privacidad de datos y comportamiento no determinista del modelo.
Preparativos iniciales
Para una implementación básica con Azure OpenAI y C# necesitaremos:
- Un proyecto .NET.
- Acceso a un recurso de Azure OpenAI Service.
- Un modelo desplegado dentro del recurso de Azure OpenAI.
- El endpoint del recurso.
- Una credencial válida, preferiblemente gestionada de forma segura.
- El nombre del despliegue que se invocará desde la aplicación.
Importante: en Azure OpenAI, el identificador usado por la aplicación suele ser el nombre del despliegue configurado en Azure, no simplemente
gpt-4,gpt-4ou otro nombre de familia de modelo.
Instalación de paquetes
Para una integración directa con Azure OpenAI desde .NET, puede utilizarse el paquete oficial del SDK de Azure:
dotnet add package Azure.AI.OpenAI
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
Estos paquetes permiten crear un cliente para Azure OpenAI y cargar configuración desde fuentes habituales en aplicaciones .NET.
En una aplicación real, evita almacenar secretos en archivos versionados. Para desarrollo local puedes usar variables de entorno o el mecanismo de secretos de usuario de .NET; para producción, considera Azure Key Vault o identidades administradas cuando el escenario lo permita.
Configuración de Azure OpenAI
En Azure, el flujo general es:
- Crear o usar un recurso existente de Azure OpenAI Service.
- Desplegar un modelo compatible con el caso de uso.
- Anotar:
- endpoint del recurso;
- nombre del despliegue;
- mecanismo de autenticación;
- límites de cuota y región.
Un ejemplo de configuración local podría ser:
{
"AzureOpenAI": {
"Endpoint": "https://<nombre-del-recurso>.openai.azure.com/",
"DeploymentName": "<nombre-del-despliegue>"
}
}
La clave de API no debería guardarse en este archivo si el repositorio se comparte o se despliega automáticamente. Para simplificar el ejemplo, la leeremos desde una variable de entorno.
Cliente básico en C#
El siguiente ejemplo muestra una implementación mínima para enviar una petición conversacional a un despliegue de Azure OpenAI.
using Azure;
using Azure.AI.OpenAI;
using Microsoft.Extensions.Configuration;
using OpenAI.Chat;
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddEnvironmentVariables()
.Build();
var endpoint = configuration["AzureOpenAI:Endpoint"];
var deploymentName = configuration["AzureOpenAI:DeploymentName"];
var apiKey = configuration["AZURE_OPENAI_API_KEY"];
if (string.IsNullOrWhiteSpace(endpoint))
{
throw new InvalidOperationException("Falta la configuración AzureOpenAI:Endpoint.");
}
if (string.IsNullOrWhiteSpace(deploymentName))
{
throw new InvalidOperationException("Falta la configuración AzureOpenAI:DeploymentName.");
}
if (string.IsNullOrWhiteSpace(apiKey))
{
throw new InvalidOperationException("Falta la variable de entorno AZURE_OPENAI_API_KEY.");
}
var azureClient = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey));
ChatClient chatClient = azureClient.GetChatClient(deploymentName);
ChatCompletion completion = await chatClient.CompleteChatAsync(
[
new SystemChatMessage("Eres un asistente técnico. Responde de forma precisa, breve y verificable."),
new UserChatMessage("Resume en tres puntos las ventajas de usar .NET para integrar IA generativa.")
]);
Console.WriteLine(completion.Content[0].Text);
Este ejemplo ilustra varios puntos importantes:
- Se usa
AzureOpenAIClientpara conectar con el recurso de Azure OpenAI. - Se obtiene un
ChatClientasociado al nombre del despliegue. - Se separa el mensaje de sistema del mensaje de usuario.
- La clave se carga desde una variable de entorno, no desde el archivo de configuración.
Encapsular el acceso al modelo
En una aplicación de producción conviene aislar la llamada al modelo detrás de un servicio propio. Esto facilita pruebas, control de errores, instrumentación y sustitución futura del proveedor o del modelo.
using Azure;
using Azure.AI.OpenAI;
using OpenAI.Chat;
public sealed class GenerativeAiService
{
private readonly ChatClient _chatClient;
public GenerativeAiService(string endpoint, string deploymentName, string apiKey)
{
var azureClient = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey));
_chatClient = azureClient.GetChatClient(deploymentName);
}
public async Task<string> GenerateSummaryAsync(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
throw new ArgumentException("El texto de entrada no puede estar vacío.", nameof(text));
}
ChatCompletion completion = await _chatClient.CompleteChatAsync(
[
new SystemChatMessage(
"Eres un asistente que resume documentación técnica. " +
"No añadas información que no esté presente en el texto original."),
new UserChatMessage($"""
Resume el siguiente texto en un máximo de cinco puntos:
{text}
""")
]);
return completion.Content.Count > 0
? completion.Content[0].Text
: string.Empty;
}
}
Uso del servicio:
var service = new GenerativeAiService(endpoint, deploymentName, apiKey);
var summary = await service.GenerateSummaryAsync("""
.NET permite construir aplicaciones cloud modernas con C#, integrarse con servicios de Azure
y aplicar patrones de arquitectura como inyección de dependencias, observabilidad y escalado horizontal.
""");
Console.WriteLine(summary);
Diseño de prompts: precisión antes que creatividad
El prompt es parte de la lógica de la aplicación. Debe versionarse, probarse y revisarse igual que cualquier otro componente crítico.
Buenas prácticas:
- Define un mensaje de sistema claro y estable.
- Indica restricciones explícitas: formato, idioma, longitud y criterios de aceptación.
- Pide al modelo que reconozca cuándo no tiene suficiente información.
- Evita mezclar instrucciones de negocio con texto no confiable del usuario.
- No incluyas secretos, tokens, claves, datos personales innecesarios ni información sensible.
- Valida la salida si se usará para tomar decisiones o alimentar otros sistemas.
Un ejemplo de instrucción más robusta:
Eres un asistente de soporte interno.
Responde solo con información incluida en el contexto proporcionado.
Si el contexto no contiene la respuesta, di: "No dispongo de información suficiente".
No inventes enlaces, políticas ni procedimientos.
Este tipo de instrucciones no elimina todos los riesgos, pero reduce respuestas especulativas y facilita la evaluación automatizada.
Arquitectura recomendada
Una arquitectura típica para integrar IA generativa en .NET puede dividirse en varias capas:
-
Capa de presentación
API REST, interfaz web, bot corporativo o aplicación de escritorio. -
Capa de aplicación
Casos de uso: resumir, clasificar, redactar, buscar, extraer entidades o responder preguntas. -
Servicio de IA
Encapsula el acceso a Azure OpenAI, controla prompts, parámetros, errores y telemetría. -
Capa de datos y contexto
Documentos, bases de datos, índices de búsqueda o sistemas internos usados para aportar contexto. -
Seguridad y gobierno
Autenticación, autorización, auditoría, límites de uso, protección de datos y revisión de outputs. -
Observabilidad
Métricas, trazas, logs controlados, latencia, consumo de tokens, tasa de errores y comportamiento por caso de uso.
Este enfoque evita acoplar toda la aplicación directamente al SDK y permite evolucionar prompts, modelos y proveedores con menor impacto.
Escalabilidad y rendimiento
Los LLMs introducen patrones de rendimiento distintos a los de una API tradicional. Las llamadas pueden ser más lentas, más costosas y estar sujetas a límites de cuota.
Recomendaciones prácticas:
- Controla el tamaño del prompt: enviar contexto excesivo aumenta coste y latencia.
- Limita la longitud de la respuesta cuando el caso de uso lo permita.
- Usa caché con cuidado para respuestas repetibles y no sensibles.
- Implementa timeouts y cancelación para evitar peticiones colgadas.
- Diseña reintentos con backoff respetando límites de cuota y errores transitorios.
- Aísla cargas pesadas mediante colas o procesamiento asíncrono.
- Mide tokens, latencia y errores por funcionalidad, no solo a nivel global.
- Evalúa streaming en interfaces conversacionales cuando mejore la experiencia de usuario.
No todas las aplicaciones necesitan la misma estrategia. Un asistente interactivo priorizará latencia percibida; un proceso batch de análisis documental priorizará coste, throughput y control de errores.
Seguridad y gestión de riesgos
La seguridad en aplicaciones con IA generativa no se limita a proteger la clave de API. También hay que considerar cómo se construyen los prompts, qué datos se envían al modelo y cómo se utiliza la respuesta.
Aspectos críticos:
- Gestión de secretos: usa Key Vault, variables de entorno o identidades administradas cuando sea posible.
- Autorización: no permitas que el usuario acceda indirectamente a datos o herramientas para los que no tiene permisos.
- Prompt injection: trata el contenido del usuario y los documentos externos como datos no confiables.
- Exfiltración de datos: evita enviar información sensible que no sea necesaria para el caso de uso.
- Validación de salida: no ejecutes comandos, consultas o acciones externas basadas en texto generado sin controles adicionales.
- Auditoría: registra eventos relevantes, pero evita guardar prompts o respuestas con datos sensibles sin una política clara.
- Aislamiento de herramientas: si el modelo puede invocar funciones, aplica listas permitidas, validación de parámetros y controles de negocio.
- Revisión humana: en procesos de alto impacto, mantén intervención humana antes de decisiones finales.
El modelo debe verse como un componente probabilístico. Puede producir respuestas incorrectas, incompletas o convincentes pero falsas. Por tanto, la aplicación debe diseñarse para contener esos fallos.
Uso de Semantic Kernel y abstracciones de IA
Para escenarios simples, una llamada directa al SDK puede ser suficiente. Sin embargo, cuando la aplicación crece, pueden aparecer necesidades adicionales:
- composición de prompts;
- invocación de funciones;
- memoria o contexto conversacional;
- integración con herramientas internas;
- separación entre lógica de negocio y proveedor de modelo;
- evaluación y pruebas de prompts.
En el ecosistema .NET, Microsoft ha impulsado dos líneas relevantes:
- Semantic Kernel: orientado a la orquestación de prompts, funciones y flujos de IA.
- Microsoft Extensions for AI: abstracciones para interactuar con modelos desde aplicaciones .NET de forma más homogénea.
La decisión de usarlas depende del tamaño del proyecto. Para un prototipo o una funcionalidad aislada, el SDK directo puede ser más simple. Para una plataforma interna con varios casos de uso y modelos, una capa de abstracción puede facilitar mantenibilidad y evolución.
Pruebas y evaluación
Las aplicaciones con LLMs requieren pruebas distintas a las tradicionales. No basta con verificar que la llamada devuelve HTTP 200.
Conviene definir un conjunto de evaluación con ejemplos reales o representativos:
- prompts esperados;
- respuestas aceptables;
- respuestas no aceptables;
- casos límite;
- entradas maliciosas;
- documentos incompletos;
- textos en varios idiomas;
- entradas excesivamente largas;
- preguntas fuera de dominio.
Algunas métricas útiles:
- tasa de respuestas correctas;
- tasa de respuestas inventadas;
- cumplimiento del formato solicitado;
- latencia media y percentiles;
- coste por operación;
- tasa de errores;
- satisfacción de usuarios;
- frecuencia de intervención humana.
La evaluación debe repetirse cuando cambien el modelo, el prompt, el contexto o la lógica de aplicación.
Errores habituales
Al implementar IA generativa en C# y Azure OpenAI, estos son problemas frecuentes:
- Usar el nombre del modelo en lugar del nombre del despliegue.
- Incluir claves de API en
appsettings.jsonversionado. - No controlar límites de tokens.
- No definir timeouts.
- No manejar errores transitorios o límites de cuota.
- Enviar demasiado contexto sin filtrado ni ranking.
- Confiar ciegamente en la respuesta del modelo.
- No registrar métricas de coste y latencia.
- Mezclar instrucciones del sistema con contenido no confiable del usuario.
- No tener una estrategia de evaluación antes de producción.
Evitar estos errores mejora la fiabilidad y reduce costes operativos.
Conclusión
Integrar IA generativa en aplicaciones .NET con C# es una opción viable y potente, especialmente cuando se combina con servicios gestionados como Azure OpenAI. Sin embargo, una implementación lista para producción requiere algo más que enviar un prompt y mostrar la respuesta.
Las claves son:
- separar el acceso al modelo en una capa propia;
- proteger credenciales y datos sensibles;
- diseñar prompts verificables;
- controlar coste, tokens y latencia;
- medir el comportamiento de la solución;
- validar respuestas antes de usarlas en procesos críticos;
- aplicar controles específicos frente a prompt injection y fuga de información.
Con una arquitectura bien diseñada, C# y .NET ofrecen una base sólida para construir soluciones de IA generativa mantenibles, observables y alineadas con los requisitos de seguridad de entornos cloud modernos.