8. Configuración de Temperatura y Tokens en Modelos LLM

This entry is parte 8 de 25 in the series Introducción a Microsoft Semantic Kernel

Introducción a Microsoft Semantic Kernel

1. Introducción a Semantic Kernel con C#: Construyendo tu Primera Aplicación de IA

2.Creando Plugins Personalizados en Semantic Kernel

3. Clasificación de Intenciones con LLMs en .NET

4. Servicios de Chat Completion con Azure OpenAI y Semantic Kernel

5. Vector Embeddings y Búsqueda Semántica con .NET

6. Prompt Engineering: Mejores Prácticas para LLMs

7. Integración de Azure OpenAI en Aplicaciones .NET

8. Configuración de Temperatura y Tokens en Modelos LLM

9. Estrategias de Caché para Servicios de IA

10. Manejo de Errores en Aplicaciones de IA con .NET

11. Salida JSON Estructurada con LLMs

12. Testing de Servicios de IA en .NET

13. Inyección de Dependencias con Semantic Kernel

14. Comprensión de Consultas con Lenguaje Natural

15. Sistemas de Búsqueda Semántica en Producción

16. Configuración de HttpClient para Servicios de IA

17. Guardrails y Validación en Sistemas de IA

18. Workflows Multi-Paso con IA

19. Optimización de Costos en Aplicaciones de IA

20. Monitoreo y Observabilidad de Servicios de IA

21. Arquitectura de Microservicios con IA

22. Seguridad en Aplicaciones de IA

23. Implementación de Routers Conversacionales Inteligentes

24. Filtrado por Relevancia Semántica en Búsquedas

25. Normalización y Preprocesamiento de Datos para IA

Introducción

Los parámetros de configuración de LLMs como temperatura, max_tokens, top_p controlan el comportamiento y la calidad de las respuestas. En este tutorial aprenderás a configurar estos parámetros para diferentes casos de uso.

Parámetros Principales

Temperature (0.0 – 2.0)

Controla la aleatoriedad de las respuestas:

// Determinístico (misma respuesta siempre)
var settingsDeterminista = new OpenAIPromptExecutionSettings
{
    Temperature = 0.0  
};

// Balanceado
var settingsBalanceado = new OpenAIPromptExecutionSettings
{
    Temperature = 0.7
};

// Muy creativo
var settingsCreativo = new OpenAIPromptExecutionSettings
{
    Temperature = 1.5
};

Casos de uso:
0.0-0.3: Clasificación, extracción de datos, respuestas precisas
0.4-0.7: Conversaciones naturales, asistentes
0.8-1.2: Contenido creativo, brainstorming
1.3-2.0: Muy experimental (raramente usado)

Max Tokens

Limita la longitud de la respuesta:

var settings = new OpenAIPromptExecutionSettings
{
    MaxTokens = 150  // Aproximadamente 100-120 palabras
};

// Reglas generales:
// - 1 token ≈ 0.75 palabras en inglés
// - 1 token ≈ 0.6 palabras en español
// - GPT-4: max 8,192 tokens (entrada + salida)
// - GPT-4-32k: max 32,768 tokens

Top P (Nucleus Sampling)

Controla la diversidad considerando probabilidad acumulativa:

var settings = new OpenAIPromptExecutionSettings
{
    TopP = 0.9  // Considera tokens que suman hasta 90% de probabilidad
};

// Valores típicos:
// - 0.1: Muy conservador
// - 0.9: Estándar (recomendado)
// - 1.0: Considera todas las opciones

Nota: Generalmente se usa temperature O top_p, no ambos.

Frequency Penalty y Presence Penalty

var settings = new OpenAIPromptExecutionSettings
{
    FrequencyPenalty = 0.5f,  // Reduce repetición de tokens frecuentes (-2.0 a 2.0)
    PresencePenalty = 0.5f    // Fomenta temas nuevos (-2.0 a 2.0)
};

// Frequency Penalty: Penaliza por frecuencia de uso
// Presence Penalty: Penaliza por presencia (sí/no), sin importar frecuencia

Configuraciones por Caso de Uso

1. Clasificación/Categorización

var classificationSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.1,       // Muy baja para consistencia
    MaxTokens = 50,          // Respuestas cortas
    TopP = 0.1,              // Muy conservador
    FrequencyPenalty = 0,
    PresencePenalty = 0
};

var prompt = """
Clasifica el siguiente texto en una de estas categorías: deportes, tecnología, política.

Texto: {{$text}}

Categoría:
""";

2. Chat Conversacional

var chatSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.7,       // Balance entre creatividad y coherencia
    MaxTokens = 500,         // Respuestas medianas
    TopP = 0.9,
    FrequencyPenalty = 0.3f, // Evitar repetición moderada
    PresencePenalty = 0.3f   // Fomentar variedad
};

3. Generación Creativa

var creativeSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.9,       // Alta creatividad
    MaxTokens = 1000,        // Respuestas largas
    TopP = 0.95,
    FrequencyPenalty = 0.5f,
    PresencePenalty = 0.5f
};

4. Extracción de Información

var extractionSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.0,       // Determinístico
    MaxTokens = 200,
    ResponseFormat = "json_object", // Formato estructurado
    FrequencyPenalty = 0,
    PresencePenalty = 0
};

5. Resumen de Texto

var summarySettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.3,       // Baja, pero permite algo de variación
    MaxTokens = 300,
    TopP = 0.8,
    FrequencyPenalty = 0.2f,
    PresencePenalty = 0.2f
};

6. Código/Programación

var codeSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.2,       // Preciso pero con algo de flexibilidad
    MaxTokens = 1500,
    TopP = 0.9,
    FrequencyPenalty = 0,
    PresencePenalty = 0
};

Servicio de Configuración Dinámica

public class LLMConfigurationService
{
    public enum TaskType
    {
        Classification,
        Conversation,
        Creative,
        Extraction,
        Summary,
        Code,
        Translation
    }

    public OpenAIPromptExecutionSettings GetSettingsForTask(TaskType taskType)
    {
        return taskType switch
        {
            TaskType.Classification => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.1f,
                MaxTokens = 50,
                TopP = 0.1f,
                FrequencyPenalty = 0,
                PresencePenalty = 0
            },

            TaskType.Conversation => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.7f,
                MaxTokens = 500,
                TopP = 0.9f,
                FrequencyPenalty = 0.3f,
                PresencePenalty = 0.3f
            },

            TaskType.Creative => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.9f,
                MaxTokens = 1000,
                TopP = 0.95f,
                FrequencyPenalty = 0.5f,
                PresencePenalty = 0.5f
            },

            TaskType.Extraction => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.0f,
                MaxTokens = 200,
                ResponseFormat = "json_object",
                FrequencyPenalty = 0,
                PresencePenalty = 0
            },

            TaskType.Summary => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.3f,
                MaxTokens = 300,
                TopP = 0.8f,
                FrequencyPenalty = 0.2f,
                PresencePenalty = 0.2f
            },

            TaskType.Code => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.2f,
                MaxTokens = 1500,
                TopP = 0.9f,
                FrequencyPenalty = 0,
                PresencePenalty = 0
            },

            TaskType.Translation => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.3f,
                MaxTokens = 1000,
                TopP = 0.9f,
                FrequencyPenalty = 0,
                PresencePenalty = 0
            },

            _ => new OpenAIPromptExecutionSettings
            {
                Temperature = 0.7f,
                MaxTokens = 500
            }
        };
    }
}

Estimación de Tokens

public class TokenEstimator
{
    // Estimación aproximada (no exacta)
    public int EstimateTokens(string text)
    {
        // Regla simple: ~1.3 caracteres por token en español
        return (int)Math.Ceiling(text.Length / 1.3);
    }

    public bool WillFitInContext(string prompt, string response, int maxContextTokens = 8192)
    {
        var promptTokens = EstimateTokens(prompt);
        var responseTokens = EstimateTokens(response);

        return (promptTokens + responseTokens) < maxContextTokens;
    }

    public int CalculateMaxResponseTokens(string prompt, int maxContextTokens = 8192, int safetyMargin = 100)
    {
        var promptTokens = EstimateTokens(prompt);
        return Math.Max(0, maxContextTokens - promptTokens - safetyMargin);
    }
}

Optimización de Costos

public class CostOptimizedLLMService
{
    private readonly Kernel _kernel;
    private readonly TokenEstimator _tokenEstimator;

    public async Task<string> GenerateWithCostLimitAsync(
        string prompt,
        int maxCostTokens = 1000)
    {
        var estimatedPromptTokens = _tokenEstimator.EstimateTokens(prompt);
        var remainingTokens = maxCostTokens - estimatedPromptTokens;

        if (remainingTokens <= 0)
        {
            throw new InvalidOperationException("Prompt excede límite de costo");
        }

        var settings = new OpenAIPromptExecutionSettings
        {
            Temperature = 0.7f,
            MaxTokens = Math.Min(remainingTokens, 500) // Limitar respuesta
        };

        var function = _kernel.CreateFunctionFromPrompt(prompt, settings);
        var result = await _kernel.InvokeAsync(function);

        return result.GetValue<string>() ?? string.Empty;
    }
}

Testing de Configuraciones

public class SettingsTester
{
    private readonly Kernel _kernel;

    public async Task<SettingsTestResult> TestSettingsAsync(
        string prompt,
        List<OpenAIPromptExecutionSettings> settingsVariations,
        int iterations = 3)
    {
        var results = new List<TestIteration>();

        foreach (var settings in settingsVariations)
        {
            var responses = new List<string>();

            for (int i = 0; i < iterations; i++)
            {
                var function = _kernel.CreateFunctionFromPrompt(prompt, settings);
                var result = await _kernel.InvokeAsync(function);
                responses.Add(result.GetValue<string>() ?? "");
            }

            results.Add(new TestIteration
            {
                Settings = settings,
                Responses = responses,
                Consistency = CalculateConsistency(responses),
                AverageLength = responses.Average(r => r.Length)
            });
        }

        return new SettingsTestResult
        {
            Iterations = results,
            BestSettings = results.OrderByDescending(r => r.Consistency).First().Settings
        };
    }

    private double CalculateConsistency(List<string> responses)
    {
        // Implementación simplificada
        if (responses.Count < 2) return 1.0;

        var firstLength = responses[0].Length;
        var variance = responses.Average(r => Math.Abs(r.Length - firstLength));

        return 1.0 - (variance / firstLength);
    }
}

public class TestIteration
{
    public required OpenAIPromptExecutionSettings Settings { get; init; }
    public required List<string> Responses { get; init; }
    public double Consistency { get; init; }
    public double AverageLength { get; init; }
}

public class SettingsTestResult
{
    public required List<TestIteration> Iterations { get; init; }
    public required OpenAIPromptExecutionSettings BestSettings { get; init; }
}

Monitoreo de Configuraciones

public class SettingsMonitor
{
    private readonly Dictionary<string, SettingsMetrics> _metrics = new();

    public void TrackRequest(
        string configName,
        OpenAIPromptExecutionSettings settings,
        int promptTokens,
        int completionTokens,
        TimeSpan latency)
    {
        if (!_metrics.ContainsKey(configName))
        {
            _metrics[configName] = new SettingsMetrics { ConfigName = configName };
        }

        var metrics = _metrics[configName];
        metrics.TotalRequests++;
        metrics.TotalPromptTokens += promptTokens;
        metrics.TotalCompletionTokens += completionTokens;
        metrics.TotalLatencyMs += latency.TotalMilliseconds;
        metrics.LastUsed = DateTime.UtcNow;
    }

    public SettingsMetrics GetMetrics(string configName)
    {
        return _metrics.GetValueOrDefault(configName) ?? new SettingsMetrics { ConfigName = configName };
    }

    public List<SettingsMetrics> GetAllMetrics()
    {
        return _metrics.Values.OrderByDescending(m => m.TotalRequests).ToList();
    }
}

public class SettingsMetrics
{
    public required string ConfigName { get; init; }
    public long TotalRequests { get; set; }
    public long TotalPromptTokens { get; set; }
    public long TotalCompletionTokens { get; set; }
    public double TotalLatencyMs { get; set; }
    public DateTime? LastUsed { get; set; }

    public double AveragePromptTokens => TotalRequests > 0 ? (double)TotalPromptTokens / TotalRequests : 0;
    public double AverageCompletionTokens => TotalRequests > 0 ? (double)TotalCompletionTokens / TotalRequests : 0;
    public double AverageLatencyMs => TotalRequests > 0 ? TotalLatencyMs / TotalRequests : 0;
}

Mejores Prácticas

1. Comenzar Conservador

// ✅ Empezar con settings conservadores
var initialSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.5f,  // Medio
    MaxTokens = 300      // Moderado
};

// Ajustar basándose en resultados

2. Documentar Configuraciones

/// <summary>
/// Configuración para clasificación de tickets de soporte.
/// Temperature baja (0.1) para consistencia en categorías.
/// MaxTokens limitado (50) ya que solo necesitamos nombre de categoría.
/// </summary>
var ticketClassificationSettings = new OpenAIPromptExecutionSettings
{
    Temperature = 0.1f,
    MaxTokens = 50
};

3. A/B Testing

public async Task<string> ABTestSettingsAsync(string prompt)
{
    var settingsA = new OpenAIPromptExecutionSettings { Temperature = 0.5f };
    var settingsB = new OpenAIPromptExecutionSettings { Temperature = 0.7f };

    // Alternar entre configuraciones y medir resultados
    var useA = Random.Shared.Next(2) == 0;
    var settings = useA ? settingsA : settingsB;

    // Trackear qué configuración se usó
    TrackConfigUsage(useA ? "A" : "B");

    var function = _kernel.CreateFunctionFromPrompt(prompt, settings);
    return (await _kernel.InvokeAsync(function)).GetValue<string>() ?? "";
}

Conclusión

La configuración correcta de temperatura, tokens y otros parámetros es crucial para obtener resultados óptimos de LLMs. Cada caso de uso requiere un balance diferente entre creatividad, consistencia y costo. Experimenta con diferentes configuraciones, mide resultados, y ajusta basándote en datos reales.


Palabras clave: LLM configuration, temperature, tokens, top_p, GPT-4, prompt settings, OpenAI parameters

Share this content:

Introducción a Microsoft Semantic Kernel

7. Integración de Azure OpenAI en Aplicaciones .NET 9. Estrategias de Caché para Servicios de IA