Course EN
← back to chapter

Medidor de costo

Corre un prompt y ve los tokens de input/output, los dólares (pricing ilustrativo) y la latencia junto a la respuesta. Leer `response.usage` es el hábito que evita que la cuenta te sorprenda.

Showcase — Medidor de costo

Corre un prompt y ve los tokens de input/output, los dólares (pricing ilustrativo) y la latencia junto a la respuesta. Leer response.usage es el hábito que evita que la cuenta te sorprenda.

Córrelo

bash bootstrap-secrets.sh              # reads ../../../../.env, writes secrets/
docker compose up --build              # default: PROVIDER=openai

Abre http://localhost:3000. Gemini: PROVIDER=gemini docker compose up --build.

Qué hay aquí

  • backend/ai_openai.py / backend/ai_gemini.py — una llamada más un reporte de token/costo/latencia.
  • frontend/app/page.tsx — caja de prompt, respuesta + métricas.

Detenlo

docker compose down

Ejecútalo en tu máquina

Descarga el proyecto como ZIP y córrelo con Docker. Levanta un backend FastAPI y un frontend Next.js en localhost:3000.

Descargar cost-meter.zip

unzip cost-meter.zip
cd cost-meter
bash bootstrap-secrets.sh   # one-time: pulls API keys into ./secrets
docker compose up --build   # default provider: openai
# or:  PROVIDER=gemini docker compose up --build

Escribe algo, elige un proveedor y ejecuta el mismo código de Código contra la API real. Requiere iniciar sesión.


  

Los mismos módulos que ejecuta el botón Run. El proyecto completo (frontend, Dockerfile, compose) está en el ZIP, pestaña README.

backend/ai_openai.py

"""Showcase 1 (OpenAI): meter every call.

Run a prompt and see what it actually cost — input tokens, output tokens, dollars
(illustrative pricing), and wall-clock latency, right next to the answer. The
habit this builds is the point: read response.usage and the bill stops surprising
you.
"""
import time

from openai import OpenAI

_client = OpenAI()

_MODEL = "gpt-5.4-nano"
_PRICES = {"gpt-5.4-nano": (0.05, 0.40)}  # USD per 1M (in, out) — illustrative


def run(prompt: str) -> str:
    p = prompt.strip()
    if not p:
        return "Enter a prompt to meter."
    start = time.time()
    response = _client.responses.create(model=_MODEL, input=[{"role": "user", "content": p}])
    seconds = time.time() - start
    u = response.usage
    p_in, p_out = _PRICES[_MODEL]
    cost = (u.input_tokens * p_in + u.output_tokens * p_out) / 1_000_000
    return (f"{response.output_text}\n\n"
            f"--- metrics ---\n"
            f"input tokens:  {u.input_tokens}\n"
            f"output tokens: {u.output_tokens}\n"
            f"cost:          ${cost:.6f}  (illustrative pricing)\n"
            f"latency:       {seconds:.2f}s")

backend/ai_gemini.py

"""Showcase 1 (Gemini): meter every call.

Same metrics, read from response.usage_metadata.
"""
import os
import time

from google import genai
from google.genai import types

_client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

_MODEL = "gemini-3.1-flash-lite"
_PRICES = {"gemini-3.1-flash-lite": (0.05, 0.30)}  # USD per 1M (in, out) — illustrative


def run(prompt: str) -> str:
    p = prompt.strip()
    if not p:
        return "Enter a prompt to meter."
    start = time.time()
    response = _client.models.generate_content(
        model=_MODEL,
        contents=[types.Content(role="user", parts=[types.Part(text=p)])],
    )
    seconds = time.time() - start
    u = response.usage_metadata
    out = u.candidates_token_count or 0
    p_in, p_out = _PRICES[_MODEL]
    cost = (u.prompt_token_count * p_in + out * p_out) / 1_000_000
    return (f"{response.text or ''}\n\n"
            f"--- metrics ---\n"
            f"input tokens:  {u.prompt_token_count}\n"
            f"output tokens: {out}\n"
            f"cost:          ${cost:.6f}  (illustrative pricing)\n"
            f"latency:       {seconds:.2f}s")

Archivos del proyecto

  • .gitignore
  • README.es.md
  • README.md
  • backend/Dockerfile
  • backend/ai_gemini.py
  • backend/ai_openai.py
  • backend/main.py
  • backend/requirements.txt
  • bootstrap-secrets.sh
  • docker-compose.yml
  • frontend/Dockerfile
  • frontend/app/layout.tsx
  • frontend/app/page.tsx
  • frontend/next.config.ts
  • frontend/package.json
  • frontend/tsconfig.json