Lo que vas a aprender
- Medir cuántos tokens consume cada petición y dónde se gastan
- Usar prompt caching para no pagar dos veces el contexto repetido
- Limitar el output con max_tokens y stop_sequences
- Comprimir el system prompt y elegir el modelo adecuado por tarea
Paso 1: Medir el consumo real de tokens
Antes de optimizar hay que medir. Cada respuesta de la API devuelve un objeto usage con input_tokens y output_tokens. En la facturación el output suele costar ~5x más que el input, así que controlar la salida es prioritario. Ejecuta una petición sencilla e imprime el usage para tener una línea base. Guarda esos números: los compararás al final. Consejo práctico: crea una función wrapper que loguee el usage de cada llamada durante desarrollo, así detectas de un vistazo qué prompts se disparan. En LATAM y España el ahorro es real en euros/pesos porque pagas por token, no por petición.
import anthropic
client = anthropic.Anthropic()
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Resume la fotosintesis en 2 frases."}],
)
print(resp.content[0].text)
print("input:", resp.usage.input_tokens)
print("output:", resp.usage.output_tokens)
Consejo: El output cuesta bastante mas que el input; recortar la salida es donde mas ahorras.
Error común: No confies en contar palabras: un token no es una palabra. Usa siempre resp.usage.
Paso 2: Limitar el output con max_tokens y stop_sequences
El error más común es dejar max_tokens en un valor alto 'por si acaso'. max_tokens es un techo, no una reserva, pero si no instruyes al modelo a ser breve generará texto de más y pagarás cada token. Combina dos técnicas: baja max_tokens a lo que realmente necesitas y pide explícitamente brevedad en el prompt. Además, stop_sequences corta la generación cuando aparece una cadena concreta, útil para respuestas estructuradas. Si esperas un JSON corto o una sola línea, 200-400 tokens sobran. Instruye el formato exacto: 'Responde solo con la palabra' o 'máximo 3 viñetas'.
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=150,
stop_sequences=["\n\n"],
messages=[{
"role": "user",
"content": "Clasifica este ticket como URGENTE o NORMAL. Responde solo la palabra.\n\nTicket: No puedo acceder a mi cuenta desde ayer."
}],
)
print(resp.content[0].text, resp.usage.output_tokens)
Consejo: Pedir el formato exacto en el prompt reduce el output mas que cualquier parametro.
Error común: Un max_tokens demasiado bajo trunca la respuesta a media frase; ajusta con margen.
Paso 3: Activar prompt caching para contexto repetido
Si envías el mismo contexto largo en cada petición (instrucciones, documentación, ejemplos), estás pagando esos tokens una y otra vez. Con prompt caching marcas bloques con cache_control y Anthropic los almacena ~5 minutos: las lecturas posteriores del bloque cacheado cuestan una fracción del precio normal. Es ideal para chatbots con system prompt grande, RAG con documentos fijos o few-shot con muchos ejemplos. Coloca lo estable al principio y marca el último bloque estable con cache_control. El primer request escribe la caché (coste ligeramente mayor); los siguientes leen barato.
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=300,
system=[{
"type": "text",
"text": "Eres asistente legal. Aqui la normativa completa: ...(texto largo)...",
"cache_control": {"type": "ephemeral"}
}],
messages=[{"role": "user", "content": "Puedo rescindir el contrato antes de 12 meses?"}],
)
print(resp.usage) # mira cache_creation y cache_read tokens
Consejo: Revisa cache_read_input_tokens en usage para confirmar que la cache funciona.
Error común: La cache expira a los ~5 min sin uso; no sirve para contexto que cambia en cada llamada.
Paso 4: Comprimir el system prompt y los mensajes
Muchos system prompts están inflados con cortesías, repeticiones y ejemplos redundantes. Cada palabra se paga en cada petición. Reescribe en estilo telegráfico: instrucciones directas, sin 'por favor', sin explicar lo obvio. Elimina ejemplos few-shot que no cambien el resultado (prueba quitándolos y midiendo calidad). En conversaciones largas, no reenvíes todo el historial: resume los turnos antiguos en un párrafo y mantén solo los últimos mensajes íntegros. Esta técnica de 'ventana deslizante + resumen' puede recortar el input a la mitad en chats largos.
# Antes (verboso) vs despues (comprimido)
system_verboso = """Por favor, actua como un asistente muy amable que
ayuda a los usuarios respondiendo sus preguntas de forma detallada..."""
system_comprimido = "Asistente de soporte. Responde conciso, en espanol, max 3 frases."
# Ventana deslizante: resume lo viejo, conserva lo reciente
def construir_mensajes(historial, resumen_previo):
recientes = historial[-4:]
return [{"role": "user", "content": f"Resumen previo: {resumen_previo}"}] + recientes
Consejo: Menos ejemplos few-shot no siempre baja la calidad: mide antes de asumir.
Error común: No resumas datos criticos (numeros, nombres) o el modelo perdera precision.
Paso 5: Elegir el modelo adecuado por tarea
No toda tarea necesita el modelo más potente. Para clasificación, extracción o respuestas simples, un modelo más ligero de la familia Claude cuesta mucho menos por token y responde más rápido. Reserva claude-opus-4-8 para razonamiento complejo, código difícil o análisis largos. Una arquitectura de enrutamiento sencilla clasifica primero la petición con un modelo barato y solo escala al potente cuando hace falta. Esto puede reducir la factura drásticamente sin que el usuario note diferencia en tareas rutinarias.
def elegir_modelo(tarea):
simples = {"clasificar", "extraer", "traducir", "formatear"}
return "claude-haiku-4" if tarea in simples else "claude-opus-4-8"
modelo = elegir_modelo("clasificar")
resp = client.messages.create(
model=modelo,
max_tokens=100,
messages=[{"role": "user", "content": "Idioma de: 'Bom dia, tudo bem?'"}],
)
print(modelo, resp.content[0].text)
Consejo: Enruta con un modelo barato y escala solo cuando la confianza sea baja.
Error común: Verifica los nombres de modelo disponibles en tu consola; cambian con cada release.
Paso 6: Medir el ahorro y automatizar el control
Cierra el ciclo comparando el consumo antes y después de optimizar. Crea un pequeño tracker que acumule input y output tokens por sesión y calcule un coste estimado. Con esto justificas las optimizaciones ante tu equipo y detectas regresiones cuando alguien vuelve a inflar un prompt. En producción, loguea el usage a tu observabilidad (Datadog, CloudWatch) y pon alertas si el promedio de tokens por petición sube. La disciplina de medir es lo que mantiene la factura bajo control a largo plazo.
class TokenTracker:
def __init__(self, precio_in=0.000003, precio_out=0.000015):
self.tin = self.tout = 0
self.pin, self.pout = precio_in, precio_out
def add(self, usage):
self.tin += usage.input_tokens
self.tout += usage.output_tokens
def coste(self):
return self.tin*self.pin + self.tout*self.pout
t = TokenTracker()
t.add(resp.usage)
print(f"Coste estimado: ${t.coste():.4f}")
Consejo: Ajusta los precios a los oficiales de tu plan; los del ejemplo son ilustrativos.
Error común: No hardcodees precios en produccion: cambian y falsearan tus reportes.
Resultado
Ahora sabes medir el consumo de tokens de Claude y aplicar cinco palancas de ahorro: limitar el output, activar prompt caching para contexto repetido, comprimir prompts, enrutar tareas simples a modelos más baratos y trackear el coste. Combinadas, estas técnicas pueden reducir tu factura entre un 40% y un 80% según el caso de uso, sin sacrificar calidad en las tareas que importan.



