Módulo 1: Fundamentos de Prompt Engineering
4. Temperature y Parámetros de Generación
Descripción
Los parámetros de generación (temperature, top_p, max_tokens, frequency_penalty, presence_penalty) controlan cómo el modelo produce texto. Elegir mal estos valores puede hacer que un prompt "perfecto" falle en producción. En esta cápsula aprenderás qué hace cada parámetro, cuándo usar temperature 0 vs 1, y configuraciones recomendadas por caso de uso.
Por qué importa: Un clasificador con temperature=0.9 dará resultados inconsistentes aunque el prompt sea excelente. Un generador creativo con temperature=0 sonará robótico y repetitivo. Los parámetros son parte del diseño del prompt: no son secundarios.
Temperature
Qué hace: Controla la aleatoriedad en la selección del siguiente token. Modifica la distribución de probabilidad de los tokens candidatos antes de muestrear.
- temperature=0: El modelo elige siempre el token más probable. Determinístico.
- temperature=1: Muestrea según las probabilidades originales del modelo.
- temperature>1: Aplana la distribución (tokens menos probables tienen más chance). Más aleatorio.
Rango típico: 0.0 a 2.0 (OpenAI). 0.0 a 1.0 (Anthropic).
Cuándo usar cada valor
| Temperature | Casos de uso | Ejemplo de tarea |
|---|---|---|
| 0 | Clasificación, extracción, código, respuesta con una correcta | Clasificar sentimiento, extraer entidades, generar SQL |
| 0.1-0.3 | QA sobre documentos, resúmenes factuales | Responder preguntas sobre un PDF, resumir un informe |
| 0.3-0.5 | Balance: consistencia con algo de fluidez | Respuestas de soporte, análisis, traducción profesional |
| 0.7-0.9 | Creatividad, brainstorming, copy | Generar slogan, ideas de nombres, variaciones de texto |
| 1.0+ | Máxima creatividad / exploración | Arte generativo, juegos de rol, escritura experimental |
Ejemplo Práctico: Comparando Temperature
from openai import OpenAI
client = OpenAI()
prompt_clasificacion = "Clasifica el sentimiento: 'Me encantó el producto, lo recomiendo'"
prompt_creativo = "Escribe un eslogan de 5 palabras para una cafetería artesanal."
# Temperatura 0: mismo resultado siempre
print("=== Clasificación (temperature=0) ===")
for i in range(3):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Clasifica sentimiento. Solo: POSITIVO, NEGATIVO o NEUTRO."},
{"role": "user", "content": prompt_clasificacion}
],
temperature=0,
max_tokens=5
)
print(f" Intento {i+1}: {response.choices[0].message.content.strip()}")
# Output: POSITIVO / POSITIVO / POSITIVO (siempre igual)
# Temperatura 0.8: creatividad, variación
print("\n=== Creativo (temperature=0.8) ===")
for i in range(3):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt_creativo}],
temperature=0.8,
max_tokens=20
)
print(f" Intento {i+1}: {response.choices[0].message.content.strip()}")
# Output varía:
# Intento 1: "Tu café, tu momento perfecto."
# Intento 2: "Sabores que abrazan el alma."
# Intento 3: "Cada sorbo, una historia única."
top_p (Nucleus Sampling)
Qué hace: Limita el conjunto de tokens candidatos a los que acumulan el top_p de probabilidad. Ej: top_p=0.1 considera solo los tokens más probables hasta sumar 10% de probabilidad.
Relación con temperature: Ambos controlan aleatoriedad, pero de forma diferente:
temperatureescala la distribución enteratop_pcorta la distribución después de cierto umbral
Recomendación de OpenAI: Cambia solo temperature o top_p, no ambos simultáneamente.
# top_p bajo = más determinismo (diferente mecanismo al temperature)
response_low_p = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Dame una palabra que describa el océano"}],
temperature=1.0, # Sin restricción por temperature
top_p=0.1 # Pero solo tokens top 10% de probabilidad
)
# top_p alto = más variedad
response_high_p = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Dame una palabra que describa el océano"}],
temperature=1.0,
top_p=0.95 # Permite tokens menos probables
)
Valores típicos:
1.0: Sin filtro (todos los tokens considerados)0.9: Variedad con coherencia0.1-0.5: Más determinismo que con temperature pero sin llegar a 0
max_tokens
Qué hace: Límite máximo de tokens en la respuesta del modelo. No incluye los tokens del prompt.
Cuándo ajustar:
| Tipo de respuesta | max_tokens recomendado | Ejemplo |
|---|---|---|
| Clasificación simple | 5-20 | "POSITIVO", "Billing", "Error 404" |
| Extracción de datos | 50-200 | JSON con 3-5 campos |
| Resumen corto | 100-300 | 3 bullet points |
| Análisis moderado | 300-600 | Evaluación con criterios |
| Análisis extenso / código | 800-2000 | Función completa, análisis detallado |
# max_tokens bajo para clasificación
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Clasifica el ticket en: TECNICO, BILLING, CUENTA. Una sola palabra."},
{"role": "user", "content": "No puedo entrar a mi cuenta"}
],
temperature=0,
max_tokens=5 # "CUENTA" cabe en 1-2 tokens
)
print(response.choices[0].message.content) # CUENTA
# Verificar si la respuesta fue truncada
finish_reason = response.choices[0].finish_reason
print(f"Finish reason: {finish_reason}")
# "stop" = respuesta completa
# "length" = truncada por max_tokens
Importante: Si finish_reason == "length", la respuesta fue cortada. Aumenta max_tokens o pide una respuesta más concisa en el prompt.
frequency_penalty y presence_penalty
frequency_penalty
Qué hace: Penaliza tokens en proporción a cuántas veces ya aparecieron. Reduce repetición de las mismas palabras.
0: Sin penalización (default)0.5-1.0: Reduce repetición moderadamente2.0: Penalización máxima (puede degradar calidad)
presence_penalty
Qué hace: Penaliza tokens que ya aparecieron, independientemente de la frecuencia. Fomenta hablar de nuevos temas.
0: Sin penalización (default)0.3-0.6: Incentiva variedad de temas2.0: Penalización máxima
# Ejemplo: generación de lista sin repetición
prompt_lista = "Lista 10 adjetivos para describir un buen liderazgo:"
# Sin penalización: puede repetir conceptos
response_sin = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt_lista}],
temperature=0.7,
frequency_penalty=0,
presence_penalty=0,
max_tokens=150
)
# Con penalización: más diversidad
response_con = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt_lista}],
temperature=0.7,
frequency_penalty=0.5, # Reduce repetición de mismas palabras
presence_penalty=0.3, # Fomenta nuevos conceptos
max_tokens=150
)
Casos donde NO usar penalización:
- Código: términos técnicos deben repetirse (ej:
def,return, nombre de variables) - Extracción: si el mismo término aparece varias veces en el texto, debes incluirlo
- Respuestas técnicas donde la precisión del vocabulario importa
seed: Reproducibilidad en OpenAI
OpenAI ofrece el parámetro seed para reproducibilidad aproximada (no garantizada pero muy consistente):
# Con seed: mayor reproducibilidad
responses = []
for i in range(3):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Dame un nombre para una startup de IA"}],
temperature=0.9, # Alta temperatura
seed=42 # Pero con seed fijo
)
responses.append(response.choices[0].message.content)
print("Respuestas con seed=42:")
for r in responses:
print(f" - {r}")
# Las 3 respuestas serán muy similares o idénticas
Nota: seed es útil para reproducibilidad en testing y debugging, pero no es 100% garantizado entre versiones del modelo.
Configuraciones por Caso de Uso
from openai import OpenAI
from dataclasses import dataclass
client = OpenAI()
@dataclass
class ModelConfig:
temperature: float
max_tokens: int
frequency_penalty: float = 0.0
presence_penalty: float = 0.0
top_p: float = 1.0
# Configuraciones predefinidas
CONFIGS = {
"clasificacion": ModelConfig(
temperature=0,
max_tokens=20,
frequency_penalty=0
),
"extraccion": ModelConfig(
temperature=0,
max_tokens=200,
frequency_penalty=0
),
"resumen": ModelConfig(
temperature=0.3,
max_tokens=300,
frequency_penalty=0.3
),
"qa_documental": ModelConfig(
temperature=0.3,
max_tokens=500
),
"brainstorming": ModelConfig(
temperature=0.8,
max_tokens=400,
frequency_penalty=0.5,
presence_penalty=0.3
),
"copy_creativo": ModelConfig(
temperature=0.7,
max_tokens=200,
frequency_penalty=0.4
),
"codigo": ModelConfig(
temperature=0,
max_tokens=1500,
frequency_penalty=0
),
}
def call_with_config(system: str, user: str, config_name: str) -> str:
config = CONFIGS[config_name]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": user}
],
temperature=config.temperature,
max_tokens=config.max_tokens,
frequency_penalty=config.frequency_penalty,
presence_penalty=config.presence_penalty,
top_p=config.top_p
)
return response.choices[0].message.content
# Uso
result = call_with_config(
system="Clasifica el sentimiento. Solo: POSITIVO, NEGATIVO, NEUTRO.",
user="El producto llegó rápido pero la calidad es mediocre.",
config_name="clasificacion"
)
print(result) # NEGATIVO o NEUTRO
Tabla Resumen
| Caso de uso | temperature | max_tokens | freq_penalty | presence_penalty |
|---|---|---|---|---|
| Clasificación | 0 | 5-20 | 0 | 0 |
| Extracción (NER, JSON) | 0 | 50-200 | 0 | 0 |
| Resumen factual | 0.3 | 150-300 | 0.2 | 0 |
| QA sobre documentos | 0.3 | 200-500 | 0 | 0 |
| Análisis y evaluación | 0.4 | 300-600 | 0.2 | 0.1 |
| Generación de ideas | 0.8 | 200-400 | 0.5 | 0.3 |
| Copy creativo | 0.7 | 100-300 | 0.4 | 0.2 |
| Generación de código | 0 | 500-1500 | 0 | 0 |
| Traducción | 0.2 | igual al original | 0 | 0 |
Conexión con el Proyecto
En el Prompt Analyzer (cápsula 08) podrías detectar si un prompt usa parámetros apropiados:
- ¿Temperature 0 para tareas determinísticas (clasificación, extracción)?
- ¿max_tokens adecuado al tipo de respuesta esperada?
- ¿frequency_penalty activado para generaciones largas?
Troubleshooting
Problema 1: Respuestas truncadas
Síntoma: La respuesta se corta a mitad de una oración o antes del cierre del JSON.
Diagnóstico:
# Verificar el finish_reason
finish_reason = response.choices[0].finish_reason
print(f"Finish reason: {finish_reason}") # "length" = truncado
Solución:
- Aumentar
max_tokensgradualmente (usa+200hasta quefinish_reason == "stop") - O reducir la longitud esperada en el prompt: "Responde en máximo 50 palabras"
Problema 2: Respuestas inconsistentes en clasificación
Síntoma: El mismo texto clasifica como POSITIVO a veces y NEUTRO en otras.
Causa: temperature > 0 en tarea determinística.
Solución:
# ✅ Correcto para clasificación
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[...],
temperature=0 # Determinístico
)
# ❌ Problemático
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[...],
temperature=0.7 # Introduce variabilidad innecesaria
)
Problema 3: Respuestas muy repetitivas
Síntoma: El modelo repite las mismas frases o ideas.
Solución:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Describe 5 beneficios del ejercicio"}],
temperature=0.7,
frequency_penalty=0.8, # Penaliza repetición de palabras
presence_penalty=0.3, # Incentiva nuevos conceptos
max_tokens=300
)
Problema 4: Respuestas demasiado conservadoras o genéricas
Síntoma: Para brainstorming, el modelo da respuestas obvias y repetitivas.
Causa: Temperature demasiado baja para una tarea creativa.
Solución: Aumenta temperature a 0.7-0.9 para tareas creativas. Verifica que no tengas top_p bajo.
Ejercicios
Ejercicio 1: Elegir parámetros
Para cada tarea, elige temperature y max_tokens apropiados y justifica:
- (a) Extraer emails de un texto
- (b) Generar 10 ideas para nombres de producto
- (c) Responder preguntas sobre un documento técnico
- (d) Generar código Python para una función de ordenamiento
Ver solución
(a) Extraer emails:
temperature=0: Solo hay una respuesta correcta (los emails presentes)max_tokens=100-200: Lista de emails en JSON
(b) 10 ideas de nombres:
temperature=0.7-0.9: Necesitamos creatividad y variedadmax_tokens=150-300: 10 nombres con una palabra o frase cada unofrequency_penalty=0.5: Para que los nombres sean variados
(c) QA sobre documento:
temperature=0.2-0.3: Factual pero fluidomax_tokens=300-500: Respuesta explicativa
(d) Código Python:
temperature=0: Código debe ser correcto, no creativomax_tokens=500-1500: Dependiendo de la complejidadfrequency_penalty=0: El código repite palabras clave por necesidad
Ejercicio 2: Experimento con temperature
Ejecuta el mismo prompt 3 veces con temperature=0 y 3 veces con temperature=0.9. Compara variabilidad.
Ver solución
from openai import OpenAI
client = OpenAI()
prompt = "Dame una analogía para explicar qué es machine learning."
for temp in [0, 0.9]:
print(f"\n=== Temperature={temp} ===")
for i in range(3):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=temp,
max_tokens=80
)
print(f" {i+1}: {r.choices[0].message.content.strip()[:100]}...")
# Con temp=0: Las 3 respuestas serán muy similares o idénticas
# Con temp=0.9: Las 3 respuestas serán distintas (analogías diferentes)
Observación esperada: Con temperature=0 las respuestas son prácticamente idénticas. Con 0.9 cada intento produce una analogía distinta.
Ejercicio 3: Detectar respuesta truncada
Escribe código que: (1) haga una llamada con max_tokens=10, (2) detecte si fue truncada, (3) reintente con max_tokens más alto automáticamente.
Ver solución
from openai import OpenAI
client = OpenAI()
def call_with_retry(system: str, user: str, initial_max_tokens: int = 50) -> str:
"""
Llama al modelo y reintenta con más tokens si la respuesta fue truncada.
"""
max_tokens = initial_max_tokens
max_retries = 3
for attempt in range(max_retries):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": user}
],
temperature=0,
max_tokens=max_tokens
)
finish_reason = response.choices[0].finish_reason
content = response.choices[0].message.content
if finish_reason == "stop":
print(f"Completado en intento {attempt+1} con max_tokens={max_tokens}")
return content
elif finish_reason == "length":
print(f"Truncado con max_tokens={max_tokens}, reintentando con {max_tokens * 2}...")
max_tokens *= 2 # Doblar tokens y reintentar
else:
break
return content # Devolver lo que tenemos
# Test
result = call_with_retry(
system="Explica en detalle qué es un transformer en IA.",
user="Dame una explicación completa",
initial_max_tokens=10 # Muy bajo, se truncará
)
print(f"\nResultado final:\n{result[:200]}...")
Ejercicio 4 (Avanzado): Benchmark de temperature
Implementa un benchmark que prueba una tarea de clasificación con temperature 0, 0.3, 0.5, 0.7 y mide la consistencia (% de respuestas idénticas en 5 intentos).
Ver solución
from openai import OpenAI
from collections import Counter
client = OpenAI()
def benchmark_temperature(
system: str,
user: str,
temperatures: list[float],
n_tries: int = 5
) -> dict:
"""
Prueba diferentes temperaturas y mide consistencia.
"""
results = {}
for temp in temperatures:
responses = []
for _ in range(n_tries):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": user}
],
temperature=temp,
max_tokens=10
)
responses.append(r.choices[0].message.content.strip())
counts = Counter(responses)
most_common = counts.most_common(1)[0]
consistency = most_common[1] / n_tries * 100
results[temp] = {
"responses": responses,
"most_common": most_common[0],
"consistency_pct": consistency
}
return results
# Ejecutar benchmark
results = benchmark_temperature(
system="Clasifica el sentimiento. Una sola palabra: POSITIVO, NEGATIVO o NEUTRO.",
user="El producto llegó tarde pero estaba en perfectas condiciones.",
temperatures=[0, 0.3, 0.5, 0.7, 1.0],
n_tries=5
)
print("Temperature | Consistencia | Respuesta más común")
print("-" * 50)
for temp, data in results.items():
print(f" {temp:.1f} | {data['consistency_pct']:3.0f}% | {data['most_common']}")
# Output esperado (aproximado):
# Temperature | Consistencia | Respuesta más común
# --------------------------------------------------
# 0.0 | 100% | NEUTRO
# 0.3 | 80% | NEUTRO
# 0.5 | 60% | NEUTRO
# 0.7 | 60% | NEUTRO
# 1.0 | 40% | NEUTRO
Resumen
- temperature=0: Clasificación, extracción, código — cualquier tarea con respuesta correcta
- temperature 0.2-0.4: QA factual, resúmenes, análisis — balance de precisión y fluidez
- temperature 0.7-0.9: Creatividad, brainstorming, copy — variedad intencional
- max_tokens: Ajustar al tipo de respuesta. Verificar
finish_reasonpara detectar truncados. - top_p: Alternativa a temperature. No combinar ambos.
- frequency_penalty: Reducir repetición de palabras en generación larga.
- presence_penalty: Fomentar diversidad de conceptos.
- seed: Para reproducibilidad aproximada en testing (OpenAI).
Recursos adicionales
- OpenAI API Parameters — Documentación completa de todos los parámetros disponibles
- OpenAI Prompt Engineering - Temperature — Recomendaciones de OpenAI para cada parámetro
- Anthropic Generation Parameters — Parámetros disponibles en la API de Claude
- Temperature in LLMs (Explained) — Explicación técnica de cómo funciona temperature
- tiktoken — Para calcular tokens y dimensionar max_tokens correctamente antes de llamar