Conceptos básicos de economía de tokens
9 ejemplos para empezar con la economía de tokens: 6 básicos y 3 intermedios.
Prerrequisitos
- Instala el SDK:
pip install anthropic - Configura tu clave API en el entorno:
export ANTHROPIC_API_KEY=sk-ant-... - Todos los ejemplos siguientes usan
anthropic.Anthropic(), que lee esa variable de entorno automáticamente.
Ejemplos básicos
1. Cuenta tokens antes de enviar una solicitud
Obtén un recuento exacto de tokens para una solicitud sin pagar por una respuesta.
import anthropic
client = anthropic.Anthropic()
count = client.messages.count_tokens(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)
print(count.input_tokens)count_tokensreplica la firma demessages.create, por lo que pasas el mismosystem,toolsymessagesque enviarías en una solicitud real.- Devuelve solo
input_tokens, ya que la longitud de la salida no se conoce hasta que ocurre la generación. - Esta llamada en sí es gratuita, no ejecuta el modelo ni genera una respuesta.
- Úsala como una prueba en seco antes de cualquier solicitud cuyo tamaño sea impredecible, como documentos proporcionados por el usuario.
Relacionado: Cómo funciona realmente el precio de los tokens de Claude - por qué la entrada y la salida se valoran de forma diferente.
2. Estima el coste a partir de un recuento de tokens
Convierte un recuento de tokens en una estimación en dólares utilizando la tarifa publicada de un modelo.
SONNET_INPUT_PER_MTOK = 2.00 # precio introductorio, hasta el 2026-08-31
count = client.messages.count_tokens(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)
estimated_input_cost = (count.input_tokens / 1_000_000) * SONNET_INPUT_PER_MTOK
print(f"${estimated_input_cost:.6f}")- Dividir por
1_000_000convierte un recuento de tokens en bruto en millones de tokens, coincidiendo con cómo se cotiza el precio por millón de tokens (MTok). - Esto solo estima el lado de entrada; el coste de salida es desconocido hasta que el modelo responde realmente.
- Mantén la constante de tarifa en un solo lugar, no dispersa en línea, para que una actualización de precios sea un cambio de una sola línea.
- Para un límite superior aproximado, multiplica
max_tokenspor la tarifa de salida y súmala a esta estimación.
3. Lee el uso real de una respuesta completada
Obtén recuentos exactos de tokens facturados después de una llamada real.
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)
print(response.usage.input_tokens, response.usage.output_tokens)response.usagees la fuente de verdad; refleja por lo que se te factura realmente.count_tokensantes de la llamada yusagedespués de la llamada deberían informar los mismosinput_tokenspara una solicitud idéntica.output_tokenssolo está disponible aquí, nunca en una estimación previa a la llamada.- Registra esto en cada llamada si estás creando algún tipo de panel de costes.
4. Calcula el coste real en dólares de una respuesta
Combina el uso de entrada y salida con las tarifas por modelo para obtener un coste exacto.
RATES = {
"claude-sonnet-5": {"input": 2.00, "output": 10.00},
"claude-haiku-4-5": {"input": 1.00, "output": 5.00},
}
def cost_of(response, model: str) -> float:
rate = RATES[model]
usage = response.usage
return (
(usage.input_tokens / 1_000_000) * rate["input"]
+ (usage.output_tokens / 1_000_000) * rate["output"]
)
print(f"${cost_of(response, 'claude-sonnet-5'):.6f}")- Mantener las tarifas en un diccionario con el nombre del modelo como clave hace que sea trivial añadir Opus o Fable más tarde.
- Esta función es el bloque de construcción para cualquier registro de costes por solicitud que añadas aguas abajo.
- Ignora los tokens de caché por ahora; consulta el ejemplo 6 para ver la versión que tiene en cuenta el caché.
- Redondea para mostrar, pero almacena el flotante sin redondear si estás agregando costes de muchas llamadas.
Relacionado: Creación de una calculadora de costes previa a la solicitud con la API de conteo de tokens - integración de esto en una puerta de enlace de canalización.
5. Cuenta tokens para una solicitud que incluye herramientas
Confirma que las definiciones de herramientas cuentan para el total de entrada.
tools = [
{
"name": "get_weather",
"description": "Obtiene el tiempo actual de una ciudad.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
]
count = client.messages.count_tokens(
model="claude-sonnet-5",
tools=tools,
messages=[{"role": "user", "content": "¿Qué tiempo hace en Austin?"}],
)
print(count.input_tokens)- Los esquemas de herramientas forman parte del prefijo de entrada y se facturan como cualquier otro token de entrada.
- Un gran catálogo de herramientas con muchas herramientas y descripciones largas puede dominar el recuento de tokens de un pequeño mensaje de usuario.
- Comparar este recuento con el del ejemplo 1 muestra exactamente cuántos tokens añaden las definiciones de herramientas.
- Este es el número que importa al decidir si un catálogo de herramientas merece ser almacenado en caché.
6. Cuenta tokens para una conversación de varios turnos
Observa cómo crece el recuento de tokens a medida que se acumula el historial de la conversación.
conversation = [
{"role": "user", "content": "¿Cuál es nuestra política de devoluciones?"},
{"role": "assistant", "content": "Se aceptan devoluciones dentro de los 30 días posteriores a la compra."},
{"role": "user", "content": "¿Se aplica eso a los artículos abiertos?"},
]
count = client.messages.count_tokens(
model="claude-sonnet-5",
messages=conversation,
)
print(count.input_tokens)- Cada turno anterior, tanto del usuario como del asistente, se reenvía como entrada en cada nueva llamada; así es como el modelo tiene memoria.
- El recuento de tokens para una conversación crece aproximadamente de forma lineal con el número de turnos, por lo que los chats de larga duración se vuelven progresivamente más caros por turno.
- Este es el mecanismo exacto que el caché de prompts está diseñado para compensar en las partes estables de una conversación.
- Comprobar este recuento periódicamente en un chat largo ayuda a detectar el crecimiento descontrolado del contexto antes de que se convierta en una sorpresa de costes.
Ejemplos intermedios
7. Crea una puerta de enlace de costes previa al envío
Rechaza enviar una solicitud si su coste estimado supera un presupuesto.
def send_if_affordable(client, max_cost_usd: float, **kwargs):
count = client.messages.count_tokens(
model=kwargs["model"],
messages=kwargs["messages"],
system=kwargs.get("system"),
tools=kwargs.get("tools"),
)
rate = RATES[kwargs["model"]]
input_cost = (count.input_tokens / 1_000_000) * rate["input"]
# Peor caso: asume que se utiliza todo el presupuesto de max_tokens como salida.
worst_case_output_cost = (kwargs.get("max_tokens", 0) / 1_000_000) * rate["output"]
if input_cost + worst_case_output_cost > max_cost_usd:
raise ValueError(
f"El coste estimado ${input_cost + worst_case_output_cost:.4f} supera el presupuesto ${max_cost_usd}"
)
return client.messages.create(**kwargs)
response = send_if_affordable(
client,
max_cost_usd=0.05,
model="claude-sonnet-5",
max_tokens=300,
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)- La estimación del peor caso de salida utiliza
max_tokenscomo límite superior, ya que la longitud real de la salida es desconocida antes de la llamada. - Este patrón es la semilla de una protección de presupuesto por inquilino o por función en una aplicación multiusuario.
- Lanzar una excepción antes de la llamada significa que nunca pagas por una solicitud que de todos modos habrías rechazado.
- Ajusta la suposición del peor caso si tus completaciones típicas se ejecutan muy por debajo de
max_tokens; un límite fijo puede ser demasiado conservador.
8. Rastrea el gasto en curso en un lote de llamadas
Acumula el coste en muchas solicitudes en un bucle.
def process_documents(client, documents: list[str], model: str) -> float:
total_cost = 0.0
for doc in documents:
response = client.messages.create(
model=model,
max_tokens=200,
messages=[{"role": "user", "content": f"Extrae las entidades clave de:\n{doc}"}],
)
total_cost += cost_of(response, model)
return total_cost
total = process_documents(client, ["texto del doc uno...", "texto del doc dos..."], "claude-haiku-4-5")
print(f"Coste total de ejecución: ${total:.4f}")- Acumular
cost_of(...)por llamada convierte un trabajo por lotes en un trabajo con un coste total conocido y auditable. - Ejecutar esto primero contra Haiku para una comprobación de cordura barata antes de cambiar a un modelo más potente es un patrón común.
- Este mismo bucle es lo que instrumentarías con registro o un emisor de métricas en producción.
- Compara el promedio por documento con tu presupuesto por documento, no solo con el total del lote, para detectar valores atípicos de costes.
Relacionado: Niveles de modelos: Enrutamiento de tareas simples a Haiku, tareas complejas a Opus - elección del modelo que llama este bucle.
9. Compara el coste estimado frente al real para detectar desviaciones
Verifica que tu estimación previa a la llamada coincide con lo que realmente se te facturó.
count = client.messages.count_tokens(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)
estimated_input_tokens = count.input_tokens
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=300,
messages=[{"role": "user", "content": "Resume el informe del tercer trimestre en tres puntos."}],
)
actual_input_tokens = response.usage.input_tokens
assert estimated_input_tokens == actual_input_tokens, "La estimación y el uso real han divergido"- Para una solicitud idéntica, la entrada de
count_tokensyusage.input_tokenssiempre deberían coincidir exactamente. - Una discrepancia generalmente significa que la solicitud cambió entre la estimación y la llamada real, no un error de precios.
- Integrar esta aserción en un conjunto de pruebas detecta la deriva accidental del prompt entre un estimador de costes y la ruta de código en vivo.
- Esta comprobación no tiene ninguna relación con los tokens de salida, que solo existen después de la generación.
Versiones de la pila: Escrito contra la línea de modelos de Claude actual a partir de ~junio de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado) y Claude Haiku 4.5 - y el SDK oficial de Python
anthropic(última versión 0.x). Los nombres de los modelos, los precios y las versiones del SDK cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.