Módulo 2: OpenAI API - Introducción
Parameters Avanzados de OpenAI API
Descripción de la cápsula
Has visto el uso básico de OpenAI API. Ahora aprenderás a controlar las respuestas con parameters avanzados:
temperature(creatividad)max_tokens(longitud)top_p(sampling)frequency_penaltyypresence_penalty
Estos parameters te dan control fino sobre cómo GPT genera texto.
Tiempo: 25 minutos
Dificultad: Media
🎯 Objetivos
- ✅ Dominar
temperature(determinismo vs creatividad) - ✅ Controlar longitud con
max_tokens - ✅ Entender
top_p, penalties - ✅ Elegir parameters según use case
🌡️ Parameter 1: Temperature
¿Qué es?
Controla la aleatoriedad de las respuestas:
temperature=0: Determinista (siempre igual)temperature=1: Balanceado (default)temperature=2: Muy creativo (máximo)
Rango: 0.0 - 2.0
Ejemplo visual:
Prompt: "Dame un nombre para una startup de AI"
Temperature 0 (determinista):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=0,
messages=[{"role": "user", "content": "Dame un nombre para una startup de AI"}]
)
Output (siempre igual):
IntelliCore
Ejecuta 10 veces → Siempre "IntelliCore"
Temperature 1 (balanceado):
temperature=1
Output (varía):
Run 1: NeuralPath
Run 2: CogniSphere
Run 3: ThinkBot AI
Temperature 2 (muy creativo):
temperature=2
Output (muy variado, a veces extraño):
Run 1: QuantumMindGlow
Run 2: BrainyPixelForge
Run 3: ZephyrCogniVerse
Cuándo usar cada valor:
| Temperature | Use Case | Ejemplo |
|---|---|---|
| 0.0-0.3 | Respuestas consistentes, factual | FAQs, soporte técnico, clasificación |
| 0.7-1.0 | Balance creatividad/consistencia | Chatbots general, recomendaciones |
| 1.5-2.0 | Máxima creatividad | Escritura creativa, brainstorming |
Código de prueba:
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def test_temperature(temp: float):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=temp,
messages=[{"role": "user", "content": "Dame un nombre para una startup de AI"}]
)
return response.choices[0].message.content
# Test 3 temperaturas, 3 veces cada una
for temp in [0, 1, 2]:
print(f"\n=== TEMPERATURE {temp} ===")
for i in range(3):
result = test_temperature(temp)
print(f" Run {i+1}: {result}")
Ejecuta y observa diferencias.
🔢 Parameter 2: Max Tokens
¿Qué es?
Límite máximo de tokens en la respuesta generada.
Importante:
- 1 token ≈ 0.75 palabras (inglés)
- 1 token ≈ 0.5 palabras (español, más largo)
Ejemplo:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
max_tokens=50, # Máximo 50 tokens
messages=[{"role": "user", "content": "Explica qué es Python"}]
)
Output (truncado a ~50 tokens):
Python es un lenguaje de programación interpretado,
de alto nivel, conocido por su sintaxis clara y
legibilidad. Es ampliamente usado en...
Nota: Respuesta se corta si excede 50 tokens.
Sin max_tokens:
max_tokens=None # Default (sin límite explícito)
GPT decide cuándo parar (usualmente termina respuesta completa).
Cuándo usar:
| Valor | Use Case |
|---|---|
| 10-50 | Respuestas muy cortas (sí/no, clasificación) |
| 100-300 | Respuestas moderadas (FAQs) |
| 500-1000 | Respuestas largas (explicaciones) |
| None | Dejar que GPT decida |
⚠️ Costo vs Max Tokens:
Ejemplo:
- Prompt: 20 tokens
max_tokens=100→ GPT genera 80 tokens- Costo: (20 input + 80 output) × pricing
Si max_tokens=1000 pero GPT solo genera 80:
- Costo: (20 + 80) × pricing (mismo costo)
max_tokensNO afecta costo si GPT termina antes
Benefit: Previene respuestas infinitas por bug.
🎲 Parameter 3: Top-p (Nucleus Sampling)
¿Qué es?
Alternativa a temperature. Controla cuántas palabras GPT considera al generar texto.
top_p=0.1: Solo considera 10% palabras más probables (determinista)top_p=1.0: Considera todas las palabras (creativo)
Rango: 0.0 - 1.0
Temperature vs Top-p:
Regla: Usa UNO, no ambos.
# Opción 1: Solo temperature
temperature=0.7, top_p=1.0 # Default top_p
# Opción 2: Solo top_p
temperature=1.0, top_p=0.9 # Default temperature
Recomendación: Usa temperature (más intuitivo).
🚫 Parameters 4 y 5: Penalties
Frequency Penalty (penaliza repetición):
Reduce probabilidad de repetir palabras/frases ya usadas.
frequency_penalty=0: Sin penalización (default)frequency_penalty=1: Máxima penalizaciónfrequency_penalty=2: Muy agresivo (evita casi toda repetición)
Rango: -2.0 a 2.0
Ejemplo:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
frequency_penalty=1.5,
messages=[{"role": "user", "content": "Escribe 5 razones para aprender Python"}]
)
Sin penalty (repetitivo):
1. Python es fácil
2. Python es versátil
3. Python es popular
4. Python es poderoso
5. Python es útil
Con penalty (más variado):
1. Sintaxis clara y legible
2. Gran ecosistema de bibliotecas
3. Comunidad activa y soporte
4. Aplicable en múltiples dominios
5. Curva de aprendizaje suave
Presence Penalty (penaliza temas repetidos):
Incentiva a GPT a hablar de temas nuevos.
presence_penalty=0: Sin penalización (default)presence_penalty=1: Máxima penalización
Rango: -2.0 a 2.0
Ejemplo:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
presence_penalty=1.0,
messages=[{"role": "user", "content": "Háblame de Python"}]
)
Sin penalty: Habla solo de Python
Con penalty: Menciona Python pero también compara con otros lenguajes
Cuándo usar penalties:
| Penalty | Use Case |
|---|---|
| Frequency | Escritura creativa, evitar repeticiones |
| Presence | Brainstorming, explorar temas diversos |
| Ambos 0 | Respuestas factuales (default) |
🧪 Experimentos Combinados
Experimento 1: Chatbot determinista (FAQs):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=0,
max_tokens=100,
messages=[
{"role": "system", "content": "Eres un bot de soporte. Responde conciso y consistente."},
{"role": "user", "content": "¿Cómo reseteo mi contraseña?"}
]
)
Resultado: Siempre misma respuesta (predecible para usuarios).
Experimento 2: Escritura creativa:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=1.5,
max_tokens=500,
frequency_penalty=1.2,
presence_penalty=0.8,
messages=[
{"role": "system", "content": "Eres un escritor creativo."},
{"role": "user", "content": "Escribe inicio de cuento sci-fi"}
]
)
Resultado: Muy creativo, variado, sin repeticiones.
Experimento 3: Clasificación (sí/no):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=0,
max_tokens=1, # Solo "Sí" o "No"
messages=[
{"role": "system", "content": "Responde solo 'Sí' o 'No'."},
{"role": "user", "content": "¿Python es un lenguaje interpretado?"}
]
)
Resultado: "Sí" (determinista, mínimo costo).
📊 Tabla Resumen de Parameters
| Parameter | Default | Rango | Controla | Cuándo usar |
|---|---|---|---|---|
temperature | 1.0 | 0.0-2.0 | Aleatoriedad | Siempre (principal knob) |
max_tokens | None | 1-∞ | Longitud máxima | Limitar costo/longitud |
top_p | 1.0 | 0.0-1.0 | Sampling | Alternativa a temperature |
frequency_penalty | 0 | -2 a 2 | Repetición palabras | Escritura creativa |
presence_penalty | 0 | -2 a 2 | Repetición temas | Brainstorming |
🎯 Guía de Decisión: Qué Parameters Usar
Use Case 1: FAQ Bot / Soporte Técnico
temperature=0.0 # Determinista
max_tokens=150 # Respuestas cortas
frequency_penalty=0 # Default
presence_penalty=0 # Default
Por qué: Consistencia es crítica (misma respuesta siempre).
Use Case 2: Chatbot General
temperature=0.7 # Ligeramente creativo
max_tokens=None # GPT decide
frequency_penalty=0 # Default
presence_penalty=0 # Default
Por qué: Balance naturalidad/consistencia.
Use Case 3: Escritura Creativa
temperature=1.5 # Muy creativo
max_tokens=1000 # Respuestas largas
frequency_penalty=1.0 # Evita repeticiones
presence_penalty=0.8 # Explora temas diversos
Por qué: Maximiza creatividad y variedad.
Use Case 4: Clasificación (ML labeling)
temperature=0.0 # Determinista
max_tokens=5 # Solo label
frequency_penalty=0 # Default
presence_penalty=0 # Default
Por qué: Necesitas respuesta exacta y consistente.
🏭 Código Educativo vs Producción
Versión educativa (para aprender):
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Código simple para entender el concepto
def generate_response(prompt: str, temp: float = 0.7) -> str:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=temp,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
Explicación: Esta versión enfoca en entender cómo funcionan los parameters básicos sin distracciones.
Versión producción (para proyectos reales):
from openai import OpenAI
import os
import time
import logging
from typing import Optional, Dict, Any
from dotenv import load_dotenv
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def generate_response_production(
prompt: str,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
max_retries: int = 3,
timeout: int = 30
) -> Dict[str, Any]:
"""
Genera respuesta con OpenAI API con manejo robusto de errores.
Args:
prompt: Texto del prompt
temperature: Controla aleatoriedad (0-2)
max_tokens: Límite de tokens (None = sin límite)
max_retries: Intentos máximos si falla
timeout: Timeout en segundos
Returns:
Dict con response, metadata (tokens, cost, latency)
"""
# Validación de inputs
if not prompt or not isinstance(prompt, str):
raise ValueError("Prompt debe ser string no vacío")
if not 0 <= temperature <= 2:
raise ValueError("Temperature debe estar entre 0 y 2")
if max_tokens is not None and max_tokens < 1:
raise ValueError("max_tokens debe ser >= 1")
# Retry logic con exponential backoff
for attempt in range(max_retries):
try:
start_time = time.time()
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=temperature,
max_tokens=max_tokens,
messages=[{"role": "user", "content": prompt}],
timeout=timeout
)
latency = time.time() - start_time
# Validación de response
if not response.choices:
raise ValueError("API retornó respuesta vacía")
# Calcular costo (precios Febrero 2026)
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens
cost = (input_tokens * 0.0015 / 1000) + (output_tokens * 0.002 / 1000)
# Metadata completa
result = {
"content": response.choices[0].message.content,
"metadata": {
"model": response.model,
"tokens": {
"input": input_tokens,
"output": output_tokens,
"total": response.usage.total_tokens
},
"cost_usd": round(cost, 6),
"latency_seconds": round(latency, 2),
"finish_reason": response.choices[0].finish_reason,
"temperature": temperature
}
}
logger.info(
f"OpenAI request successful | "
f"tokens={response.usage.total_tokens} | "
f"latency={latency:.2f}s | "
f"cost=${cost:.6f}"
)
return result
except Exception as e:
logger.error(
f"Attempt {attempt + 1}/{max_retries} failed: {type(e).__name__}: {e}"
)
# Si es el último intento, propaga el error
if attempt == max_retries - 1:
raise RuntimeError(
f"Failed after {max_retries} attempts: {e}"
) from e
# Exponential backoff: 2^attempt segundos
wait_time = 2 ** attempt
logger.info(f"Retrying in {wait_time}s...")
time.sleep(wait_time)
# No debería llegar aquí
raise RuntimeError("Unexpected error in retry logic")
# Ejemplo de uso en producción
if __name__ == "__main__":
try:
result = generate_response_production(
prompt="Explica qué es FastAPI",
temperature=0.7,
max_tokens=300
)
print(f"Respuesta: {result['content']}\n")
print(f"Tokens usados: {result['metadata']['tokens']['total']}")
print(f"Costo: ${result['metadata']['cost_usd']}")
print(f"Latencia: {result['metadata']['latency_seconds']}s")
except Exception as e:
logger.error(f"Error fatal: {e}")
# Aquí podrías enviar alerta a Sentry, Datadog, etc.
Diferencias clave:
| Aspecto | Educativa | Producción |
|---|---|---|
| Validación | ❌ Ninguna | ✅ Inputs + outputs |
| Error handling | ❌ Sin retries | ✅ Retries con backoff |
| Logging | ❌ Sin logs | ✅ Logging estructurado |
| Timeout | ❌ Default (infinito) | ✅ 30s configurable |
| Metadata | ❌ Solo content | ✅ Tokens, cost, latency |
| Type hints | ⚠️ Básico | ✅ Completo + docstring |
| Cost tracking | ❌ No calcula | ✅ Cálculo preciso |
Cuándo usar cada una:
- Educativa: Para aprender el concepto, prototipos rápidos, scripts one-off
- Producción: Para APIs, aplicaciones con usuarios reales, sistemas críticos
Nota importante: En Módulos 7-8 usarás patterns de la versión producción para el proyecto final.
🏋️ Ejercicios Prácticos
Ejercicio 1: Temperature básico (Fácil)
Modifica el código para probar 3 temperaturas (0, 0.7, 1.5) con el prompt "Dame 3 nombres de productos tech".
Ver solución
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
for temp in [0, 0.7, 1.5]:
print(f"\n=== Temperature {temp} ===")
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=temp,
messages=[{"role": "user", "content": "Dame 3 nombres de productos tech"}]
)
print(response.choices[0].message.content)
Explicación: Con temp=0 verás consistencia, con 1.5 verás creatividad máxima.
Ejercicio 2: Max tokens (Fácil)
Crea función que retorne respuestas de exactamente 50 tokens.
Ver solución
def short_response(prompt: str) -> str:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
max_tokens=50, # Límite estricto
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# Test
result = short_response("Explica qué es Python")
print(result)
print(f"Tokens usados: {len(result.split())}") # Aproximado
Explicación: max_tokens=50 fuerza respuesta corta. Útil para resúmenes o clasificación.
Ejercicio 3: Penalties (Medio)
Crea función que genere 10 ideas únicas (sin repetir conceptos) usando penalties.
Ver solución
def generate_unique_ideas(topic: str, count: int = 10) -> list:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=1.2, # Creativo
frequency_penalty=1.5, # Evita repetir palabras
presence_penalty=1.0, # Explora temas diversos
messages=[{
"role": "user",
"content": f"Lista {count} ideas únicas sobre: {topic}"
}]
)
return response.choices[0].message.content
# Test
ideas = generate_unique_ideas("apps AI para productividad", 10)
print(ideas)
Explicación: Penalties altos evitan repetición de palabras y temas, generando ideas más diversas.
Ejercicio 4: Use case específico (Medio)
Configura parameters para chatbot de soporte técnico (respuestas consistentes, cortas, sin creatividad).
Ver solución
def support_bot(question: str) -> str:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=0.0, # Determinista
max_tokens=150, # Respuestas cortas
frequency_penalty=0, # Default
presence_penalty=0, # Default
messages=[
{"role": "system", "content": "Eres un bot de soporte técnico. Responde conciso y consistente."},
{"role": "user", "content": question}
]
)
return response.choices[0].message.content
# Test
print(support_bot("¿Cómo cambio mi contraseña?"))
print(support_bot("¿Cómo cambio mi contraseña?")) # Misma respuesta
Explicación: temperature=0 garantiza respuestas idénticas para mismas preguntas. Crítico para FAQs.
Ejercicio 5: Clasificación optimizada (Avanzado)
Crea clasificador de sentimiento (Positivo/Negativo/Neutral) optimizado para costo y velocidad.
Ver solución
def classify_sentiment(text: str) -> str:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=0.0, # Determinista
max_tokens=1, # Solo 1 palabra
messages=[
{
"role": "system",
"content": "Clasifica sentimiento. Responde solo: Positivo, Negativo o Neutral"
},
{
"role": "user",
"content": text
}
]
)
return response.choices[0].message.content
# Test
texts = [
"Me encanta este producto!",
"Pésimo servicio, no lo recomiendo",
"Es un producto normal"
]
for text in texts:
sentiment = classify_sentiment(text)
print(f"{text[:30]:30} → {sentiment}")
Explicación:
max_tokens=1= costo mínimo (1 token output)temperature=0= consistencia en clasificación- Total: ~$0.00001 por clasificación
Ejercicio 6: Comparación A/B (Avanzado)
Compara cost y quality entre 2 configuraciones: temp=0 vs temp=1.5.
Ver solución
import time
def compare_configs(prompt: str):
configs = [
{"name": "Determinista", "temperature": 0.0},
{"name": "Creativo", "temperature": 1.5}
]
results = []
for config in configs:
start = time.time()
response = client.chat.completions.create(
model="gpt-3.5-turbo",
temperature=config["temperature"],
messages=[{"role": "user", "content": prompt}]
)
latency = time.time() - start
tokens = response.usage.total_tokens
cost = (tokens * 0.002 / 1000) # Aproximado
results.append({
"config": config["name"],
"temperature": config["temperature"],
"response": response.choices[0].message.content[:100] + "...",
"tokens": tokens,
"cost": f"${cost:.6f}",
"latency": f"{latency:.2f}s"
})
# Print results
for r in results:
print(f"\n{'='*60}")
print(f"Config: {r['config']} (temp={r['temperature']})")
print(f"Response: {r['response']}")
print(f"Tokens: {r['tokens']} | Cost: {r['cost']} | Latency: {r['latency']}")
# Test
compare_configs("Escribe un eslogan para startup AI")
Explicación: Mismo prompt, diferentes configs. Observa diferencias en calidad, variabilidad y costo.
🔗 Recursos adicionales
- OpenAI API Parameters - Reference completo oficial
- Prompt Engineering Guide - Best practices OpenAI
- Temperature Playground - Test interactivo de parameters
- OpenAI Cookbook - Parameters - Ejemplos avanzados
- Rate Limits & Optimization - Guía oficial
- Cost Calculator - Calculadora de costos
- Error Handling Best Practices - Guía de errores
- Community Examples - Discusiones community
➡️ Próximo paso
Siguiente cápsula: 06-pricing-rate-limits.md
Ahora que dominas los parameters, aprenderás:
- Cómo calcular costos exactos
- Rate limits y quotas
- Optimización de costos
- Monitoreo de usage
Tiempo: 25 minutos
Tiempo estimado: 25 minutos
Siguiente: 06-pricing-rate-limits.md