Costo y latencia: presupuesto, caché, un modelo más pequeño
En resumen: El costo de un modelo de lenguaje es tokens × precio, por separado para la entrada y para la salida; un presupuesto de tokens, una caché de respuestas y un modelo más pequeño bajan la cuenta, y la caché y el modelo más pequeño también reducen el tiempo de respuesta.
Problema
La cuenta a fin de mes
El asistente de soporte lleva un mes funcionando. Responde bien, y el conjunto de pruebas de la lección sobre la evaluación pasa. Entonces llegan dos quejas: la cuenta del modelo es más alta de lo esperado, y los clientes esperan cerca de un segundo por una respuesta.
Aquí está una llamada tal como la hace el asistente. Los precios de los tokens son ejemplos, en euros por millón de tokens:
question = "¿Cuánto cuesta el envío?"r = CLIENT.create(model=LARGE, max_tokens=1024, system=PROMPT + " " + ALL_DOCS, messages=[{"role": "user", "content": question}])m = MODELS[LARGE]euro = cost(m, r.usage)input_euro = r.usage.input_tokens * m.in_price / 1_000_000print(f"entrada: {r.usage.input_tokens} tokens, salida: {r.usage.output_tokens} tokens")print(f"costo: {euro:.5f} € (la entrada es {100 * input_euro / euro:.0f}%)")print(f"tiempo de ejemplo: {latency(m, r.usage)} ms")entrada: 386 tokens, salida: 40 tokenscosto: 0.00218 € (la entrada es 71%)tiempo de ejemplo: 1238 msLa pregunta «¿Cuánto cuesta el envío?» tiene 8 tokens, y la entrada tiene 386. Una parte de la cuenta es la respuesta, y la parte mayor es la entrada: el prompt de sistema y todos los documentos de la tienda viajan con cada pregunta. Y en el registro la mitad de las preguntas son iguales: cuánto cuesta el envío, cuándo atiende soporte.
La idea
A dónde van el dinero y el tiempo
Un modelo se paga por tokens (la lección sobre los tokens), por separado la entrada y la salida:
- la entrada es todo lo que envías: el prompt de sistema, los documentos, el historial de la conversación, la pregunta. La API no tiene memoria, así que todo eso se envía cada vez (la lección sobre el contexto);
- la salida es la respuesta. Un token de salida suele costar varias veces más que uno de entrada, aquí 4 veces.
Con el tiempo pasa algo parecido, con otro equilibrio. El modelo lee la entrada rápido y escribe la respuesta token a token. Así que una respuesta larga es lenta, y una entrada larga sobre todo es cara.
De ahí salen las tres soluciones que la lección mide con un programa:
- un presupuesto de tokens: menos entrada (solo lo necesario) y un tope para la salida;
- una caché: la misma pregunta no llega al modelo;
- un modelo más pequeño para las preguntas fáciles: un token más barato y más rápido.
Un presupuesto de tokens es un límite superior de tokens para una llamada, planeado de antemano, igual que planeas la memoria o el tiempo de respuesta de una petición.
Míralo
El asistente en código
El cliente falso es el mismo que en la lección sobre la evaluación: la forma de la API real, respuestas grabadas y tokens aproximados (cada palabra son 2 tokens). Las respuestas se graban según una palabra de la pregunta:
# un cliente falso: la forma de la API real, las respuestas están grabadas@dataclass(frozen=True)class Usage: input_tokens: int output_tokens: int
@dataclass(frozen=True)class Response: text: str stop_reason: str usage: Usage
# una respuesta grabada: modelo ("" = cualquiera), una palabra de la pregunta, texto que necesita el prompt@dataclass(frozen=True)class Recorded: model: str keyword: str needs: str text: str
# a grandes rasgos: cada palabra son 2 tokensdef tokens(text): return 2 * len(text.split())
# max_tokens corta la respuestadef reply(text, max_tokens, input_tokens): words = text.split(" ") if 2 * len(words) <= max_tokens: return Response(text, "end_turn", Usage(input_tokens, 2 * len(words))) kept = max_tokens // 2 return Response(" ".join(words[:kept]), "max_tokens", Usage(input_tokens, 2 * kept))
class FakeLlm: def __init__(self, recorded): self.recorded = recorded
def create(self, model, max_tokens, system, messages): question = messages[-1]["content"] input_tokens = tokens(system) + sum(tokens(m["content"]) for m in messages) for r in self.recorded: if r.model in ("", model) and r.keyword in question and r.needs in system: return reply(r.text, max_tokens, input_tokens) return reply("(no hay respuesta grabada)", max_tokens, input_tokens)RECORDED = [ Recorded("", "cuesta", "", "El envío a domicilio cuesta 4,90 €, a una oficina 3,50 €, y a partir de 50 € es gratis."), Recorded("", "reembolso", "", "Sí, se puede pagar contra reembolso. La comisión es de 1,50 €."), Recorded("", "devolver", "", "Puedes devolver la mercancía hasta 14 días después de la entrega si está sin usar y con la etiqueta."), Recorded("", "atiende", "", "Soporte atiende de lunes a viernes, de 9 a 18 h."), Recorded("", "1042", "", "El pedido 1042 ya salió y llega el jueves."), Recorded("", "1077", "", "El pedido 1077 se está preparando y sale mañana."), Recorded("", "dañado", "", "¡Lo siento! Hazle una foto al paquete y a la etiqueta y escríbenos con el número del pedido. Te enviaremos uno nuevo o te devolveremos el dinero en un plazo de 5 días hábiles."), Recorded("", "días", "", "Los paquetes llegan en 2 a 4 días hábiles."), Recorded("", "por mayor", "", "No lo sé, te paso con un compañero."), Recorded("", "Mastercard", "", "Sí, aceptamos Visa y Mastercard."),]Los documentos de la tienda son cinco secciones. Cada una tiene palabras que la identifican:
# una sección de los documentos y las palabras que la identifican@dataclass(frozen=True)class Doc: triggers: list text: str
PROMPT = "Eres el asistente de soporte de una tienda en línea. Responde con brevedad y solo a partir de los documentos. Si la respuesta no está, di: «No lo sé, te paso con un compañero.»"DOCS = [ Doc(["envío", "paquete"], "Envío: los paquetes llegan en 2 a 4 días hábiles. El envío a domicilio cuesta 4,90 €, a una oficina de mensajería 3,50 €, y a partir de 50 € es gratis. Un paquete se sigue por su número."), Doc(["devol", "dañado"], "Devoluciones: la mercancía se puede devolver hasta 14 días después de la entrega si está sin usar y con la etiqueta. Un paquete dañado se fotografía y se avisa a soporte. El dinero vuelve a la tarjeta en un plazo de 5 días hábiles."), Doc(["pag", "tarjeta", "mastercard"], "Pago: aceptamos Visa y Mastercard. El pago contra reembolso tiene una comisión de 1,50 €. El pago con tarjeta está protegido y el importe se cobra cuando se confirma el pedido."), Doc(["pedido"], "Pedidos: el estado de un pedido se ve en el perfil. Soporte revisa un pedido solo por su número y nunca pide los datos de la tarjeta."), Doc(["atiende", "horario"], "Soporte: trabajamos de lunes a viernes, de 9 a 18 h. Escríbenos a help@shop.example."),]ALL_DOCS = " ".join(doc.text for doc in DOCS)Los modelos, los precios y los tiempos. Todos los números de aquí son ejemplos, y el tiempo sale de una fórmula, no está medido:
# precios de ejemplo en € por 1 000 000 de tokens y tiempo de ejemplo (no medidos)@dataclass(frozen=True)class ModelInfo: in_price: float out_price: float base_ms: int input_per_ms: int ms_per_token: int
LARGE, SMALL = "model-large", "model-small"MODELS = { LARGE: ModelInfo(4.00, 16.00, 400, 10, 20), SMALL: ModelInfo(0.40, 1.60, 150, 40, 5),}CACHE_MS = 5# el costo de una llamada en €def cost(m, u): return (u.input_tokens * m.in_price + u.output_tokens * m.out_price) / 1_000_000
# tiempo de ejemplo en ms: inicio + leer la entrada + generardef latency(m, u): return m.base_ms + u.input_tokens // m.input_per_ms + u.output_tokens * m.ms_per_tokenLa respuesta para el pedido 1042 está grabada. En el asistente real el estado viene de una herramienta (la lección sobre las herramientas).
1_000_000 es lo mismo que 1000000. // es la división entera, como / entre enteros en Java y C#.Pruébalo
Completa
El costo es los tokens de entrada por el precio de entrada más los tokens de salida por…
return (u.input_tokens * m.in_price + u.output_tokens * ) / 1_000_000La salida tiene su propio precio, aquí 16 € por millón frente a 4 € de la entrada. Si calculas la salida al precio de la entrada, la cuenta de las respuestas sale cuatro veces más baja, y son la parte más cara por token.
Míralo
Un día
Un día en soporte es una muestra de 20 preguntas. Algunas se repiten, a veces en minúsculas o con un espacio de más. Tres son sobre un pedido concreto:
questions = [ "¿Cuánto cuesta el envío?", "¿Cuándo atiende soporte?", "¿Dónde está el pedido 1042?", "¿cuánto cuesta el envío?", "¿Puedo pagar contra reembolso?", "¿Hasta cuándo puedo devolver la mercancía?", "¿Cuánto cuesta el envío?", "Mi paquete llegó dañado, ¿qué hago?", "¿Cuándo atiende soporte?", "¿Dónde está el pedido 1077?", "¿Aceptan Mastercard?", "¿Cuánto cuesta el envío? ", "¿Cuántos días tarda un paquete a Monterrey?", "¿Puedo pagar contra reembolso?", "¿Venden al por mayor?", "¿Hasta cuándo puedo devolver la mercancía?", "¿Dónde está el pedido 1042?", "¿Cuándo atiende soporte?", "¿Cuánto cuesta el envío a una oficina?", "¿Cómo puedo devolver la mercancía?",]day recorre las preguntas y suma el costo y el tiempo. Las tres banderas activan las tres soluciones, y por ahora están apagadas:
def day(questions, budget, cache, route): answers = {} euro, ms, hits, on_small = 0.0, 0, 0, 0 for question in questions: k = key(question) # acierto: sin modelo if cache and k in answers: hits += 1 ms += CACHE_MS continue model = pick_model(question) if route else LARGE docs = relevant(question) if budget else ALL_DOCS max_tokens = 200 if budget else 1024 msg = {"role": "user", "content": question} r = CLIENT.create(model=model, max_tokens=max_tokens, system=PROMPT + " " + docs, messages=[msg]) m = MODELS[model] euro += cost(m, r.usage) ms += latency(m, r.usage) if model == SMALL: on_small += 1 # un pedido es de un cliente: sin caché if cache and "pedido" not in k: answers[k] = r.text return Totals(euro, ms, hits, on_small)def row(name, t, n): print(f"{name}: {t.euro / n * 1000:.2f} € por 1000 preguntas, {t.ms // n} ms de media")
def month(t, n): print(f"mes con 3000 preguntas al día: {t.euro / n * 3000 * 30:.2f} €")all = day(questions, False, False, False)row("modelo grande, todos los documentos", all, len(questions))month(all, len(questions))modelo grande, todos los documentos: 2.02 € por 1000 preguntas, 1032 ms de mediames con 3000 preguntas al día: 182.12 €El costo por 1000 preguntas ronda los 2 €. Con 3000 preguntas al día el mes sale en unos 182 €, y una pregunta espera de media cerca de un segundo.
La idea
Un presupuesto de tokens
La primera solución es la entrada. La pregunta sobre el envío solo necesita la sección del envío. relevant toma las secciones cuyas palabras están en la pregunta, y si no hay ninguna, las envía todas (la pregunta sobre la venta al por mayor tiene que verlo todo para decir «No lo sé»):
# presupuesto: solo las secciones cuyas palabras están en la preguntadef relevant(question): low = question.lower() parts = [doc.text for doc in DOCS if any(word in low for word in doc.triggers)] return " ".join(parts) if parts else ALL_DOCSEl segundo tope es max_tokens: como máximo 200 tokens por respuesta. No hace las respuestas más cortas. Dice cuánto puede costar como máximo una llamada.
all = day(questions, False, False, False)row("modelo grande, todos los documentos", all, len(questions))budget = day(questions, True, False, False)row("+ presupuesto de tokens", budget, len(questions))modelo grande, todos los documentos: 2.02 € por 1000 preguntas, 1032 ms de media+ presupuesto de tokens: 1.11 € por 1000 preguntas, 1009 ms de mediaEl costo baja casi a la mitad. El tiempo apenas se mueve: la entrada se lee rápido, y la respuesta es la misma.
Aquí las secciones se eligen por palabras. Cómo elegirlas por significado, con vectores, está en el módulo sobre la búsqueda semántica (RAG).
any(word in low for word in doc.triggers) es verdadero si al menos una palabra de la sección está en la pregunta.Pruébalo
Predice la salida
max_tokens es 10, y la pregunta es sobre un paquete dañado. ¿Qué imprimirá?
r = CLIENT.create(model=LARGE, max_tokens=10, system=PROMPT, messages=[{"role": "user", "content": "Mi paquete llegó dañado, ¿qué hago?"}])print(r.text)print(f"{r.stop_reason}, {r.usage.output_tokens}")El tope detiene la respuesta en 10 tokens, aquí 5 palabras, a mitad de una frase. stop_reason es max_tokens, no end_turn. El tope protege la cuenta, pero un tope demasiado bajo da media respuesta. El programa tiene que revisar stop_reason antes de mostrarle la respuesta al cliente.
La idea
Una caché de respuestas
La segunda solución es la repetición. Si la misma pregunta se hizo hace un momento, la respuesta es la misma: no hace falta preguntarle de nuevo al modelo. Es cache-aside de la lección «Caché»: miras en la caché, y si no está, le preguntas al modelo y guardas una copia.
La clave es la pregunta en minúsculas con un solo espacio entre palabras, así que «¿cuánto cuesta el envío? » es lo mismo que «¿Cuánto cuesta el envío?»:
# la clave de la caché: minúsculas, un espacio cada unodef key(question): return " ".join(question.lower().split())En day son las líneas con answers: un acierto devuelve la respuesta guardada en 5 ms y gratis. Una pregunta sobre un pedido no se guarda en la caché. La respuesta es de un solo cliente, y el estado cambia.
all = day(questions, False, False, False)row("modelo grande, todos los documentos", all, len(questions))budget = day(questions, True, False, False)row("+ presupuesto de tokens", budget, len(questions))cached = day(questions, True, True, False)row("+ caché", cached, len(questions))print(f"desde la caché: {cached.hits} de {len(questions)}")modelo grande, todos los documentos: 2.02 € por 1000 preguntas, 1032 ms de media+ presupuesto de tokens: 1.11 € por 1000 preguntas, 1009 ms de media+ caché: 0.74 € por 1000 preguntas, 640 ms de mediadesde la caché: 7 de 207 de 20 preguntas salen de la caché. Ahora también baja el tiempo, porque un acierto no espera al modelo.
Pruébalo
Encuentra el error
Un compañero simplifica la caché. Las pruebas de costo pasan, y un día después un cliente se queja de que el asistente le dijo el estado del pedido de otra persona. ¿Qué línea tiene el error?
Elige la línea con el error.
La caché guarda todas las respuestas, también las de los pedidos. En el asistente real la pregunta «¿Dónde está mi pedido?» es igual para todos los clientes, y la respuesta es del primero que preguntó. El siguiente cliente recibe el estado de otro, y el primero recibe uno viejo un día después. Una respuesta sobre un pedido no se guarda en la caché: esa es la comprobación que quitó el compañero.
La idea
Un modelo más pequeño para lo fácil
La tercera solución es el modelo. El modelo pequeño es 10 veces más barato por token y escribe más rápido. En la lección sobre la evaluación el conjunto de pruebas mostró dónde se defiende bien: el precio del envío, el pago, las devoluciones. Y dónde no: el plazo de entrega y la pregunta fuera de los documentos. Así que recibe solo los temas aprobados:
# los temas fáciles: el conjunto de pruebas mostró que el modelo pequeño los resuelveEASY = ["cuesta", "reembolso", "devolver", "Mastercard"]
def pick_model(question): return SMALL if any(word in question for word in EASY) else LARGEall = day(questions, False, False, False)row("modelo grande, todos los documentos", all, len(questions))budget = day(questions, True, False, False)row("+ presupuesto de tokens", budget, len(questions))cached = day(questions, True, True, False)row("+ caché", cached, len(questions))routed = day(questions, True, True, True)row("+ modelo pequeño para lo fácil", routed, len(questions))print(f"en el modelo pequeño: {routed.on_small} de {len(questions)}")month(all, len(questions))month(routed, len(questions))modelo grande, todos los documentos: 2.02 € por 1000 preguntas, 1032 ms de media+ presupuesto de tokens: 1.11 € por 1000 preguntas, 1009 ms de media+ caché: 0.74 € por 1000 preguntas, 640 ms de media+ modelo pequeño para lo fácil: 0.43 € por 1000 preguntas, 419 ms de mediaen el modelo pequeño: 6 de 20mes con 3000 preguntas al día: 182.12 €mes con 3000 preguntas al día: 39.06 €El mes baja de unos 182 € a unos 39 €, y el tiempo medio de 1032 a 419 ms. Los números salen de precios de ejemplo y de una fórmula de ejemplo, pero el orden de las soluciones es real.
Míralo
La cuenta, solución por solución
def day(questions, budget, cache, route): answers = {} euro, ms, hits, on_small = 0.0, 0, 0, 0 for question in questions: k = key(question) # acierto: sin modelo if cache and k in answers: hits += 1 ms += CACHE_MS continue model = pick_model(question) if route else LARGE docs = relevant(question) if budget else ALL_DOCS max_tokens = 200 if budget else 1024 msg = {"role": "user", "content": question} r = CLIENT.create(model=model, max_tokens=max_tokens, system=PROMPT + " " + docs, messages=[msg]) m = MODELS[model] euro += cost(m, r.usage) ms += latency(m, r.usage) if model == SMALL: on_small += 1 # un pedido es de un cliente: sin caché if cache and "pedido" not in k: answers[k] = r.text return Totals(euro, ms, hits, on_small)Paso a paso, en palabras
- Una llamada: entran el prompt, todos los documentos y la pregunta (386 tokens) y sale la respuesta (40). Los documentos son la mayor parte de la cuenta: 0,00218 €.
- El presupuesto de tokens: solo la sección que busca la pregunta y un tope para la respuesta. 154 tokens de entrada, 0,00126 € por la misma respuesta.
- Un día de 20 preguntas, por 1000 preguntas: 2,02 € con todos los documentos, 1,11 € con el presupuesto. El tiempo casi no cambia: es sobre todo la respuesta.
- La caché: 7 de 20 preguntas son repetidas y no llegan al modelo. Las preguntas sobre un pedido nunca se guardan en la caché.
- El modelo pequeño se encarga de los temas fáciles que aprobó el conjunto de pruebas: 6 de 20 preguntas. Es más barato y más rápido.
- De 2,02 € a 0,43 € por 1000 preguntas (79 % menos) y de 1032 a 419 ms. Los precios y los tiempos son ejemplos.
La idea
Ejecútalo en tu computadora
La respuesta real dice cuántos tokens usó. Aquí está la petición con el presupuesto para la pregunta sobre el envío, y la respuesta. El texto y los números vienen del cliente falso:
{ "model": "<nombre del modelo>", "max_tokens": 200, "system": "<el prompt de sistema>", "messages": [ { "role": "user", "content": "¿Cuánto cuesta el envío?" } ]}{ "content": [ { "type": "text", "text": "El envío a domicilio cuesta 4,90 €, a una oficina 3,50 €, y a partir de 50 € es gratis." } ], "stop_reason": "end_turn", "usage": { "input_tokens": 154, "output_tokens": 40 }}Los campos son usage.input_tokens y usage.output_tokens, y stop_reason dice si la respuesta está completa (end_turn) o si el tope la cortó (max_tokens). Con ellos el programa calcula la misma cuenta que aquí, solo que con números reales.
Los proveedores publican SDK oficiales para Java, C#, Python y JavaScript con la misma forma: mensajes, roles, tokens, herramientas. Los nombres exactos de las clases y los métodos están en la documentación del proveedor. Aquí la petición va por el cliente HTTP estándar del lenguaje, sin SDK. La dirección y el modelo son marcadores:
import jsonimport osimport urllib.request
# solo para mostrar: la dirección y la cabecera de la clave están en la documentación del proveedorENDPOINT = "https://<proveedor>/..."
def ask(system, question): body = { "model": "<nombre del modelo>", "max_tokens": 200, "system": system, "messages": [{"role": "user", "content": question}], } request = urllib.request.Request( ENDPOINT, data=json.dumps(body).encode("utf-8"), headers={ "content-type": "application/json", "authorization": "Bearer " + os.environ["LLM_API_KEY"], }, ) with urllib.request.urlopen(request) as response: return json.load(response) # JSON: content, stop_reason, usage
reply = ask(PROMPT + " " + relevant(question), question)usage = reply["usage"]print(reply["stop_reason"], usage["input_tokens"], usage["output_tokens"])Este código no se ejecuta en la comprobación de código del sitio. La clave está en la variable de entorno LLM_API_KEY, no en el código (la lección «Secretos en el código y en git»), necesitas una cuenta con un proveedor, y cada ejecución cuesta dinero.
urllib.request y json están en la biblioteca estándar, y json.dumps convierte el diccionario en JSON.La idea
Cuando duele
- Un presupuesto que recorta lo necesario. Si
relevantno encuentra la sección con la respuesta, el modelo dice «No lo sé» o, peor, inventa. Unmax_tokensdemasiado bajo da media respuesta. Todo cambio del presupuesto pasa por el conjunto de pruebas. - Una caché que miente. El precio del envío cambia, y la caché da el viejo. Una caché tiene caducidad (TTL) y se vacía cuando cambian los documentos. Las respuestas que dependen del cliente o del momento no entran.
- Un modelo pequeño sin conjunto de pruebas. «Parece sencillo» no es un argumento. El modelo pequeño toma un tema solo después de que el conjunto de pruebas lo pasó, y el conjunto se ejecuta de nuevo con cada cambio.
- Un ahorro que no vale la pena. Si el asistente recibe 50 preguntas al día, la cuenta son unos pocos euros al mes. La complejidad de la caché y del enrutador puede costar más que eso. Primero mide.
Más precisamente, para curiosos
Guardar el inicio del prompt. Muchos proveedores guardan el inicio repetido del prompt (el prompt de sistema y los documentos) y cobran menos por volver a leerlo. Es otra caché: el modelo igual responde, pero la entrada sale más barata. Funciona si el inicio es idéntico hasta el último carácter, por eso las partes que cambian (la pregunta, el nombre del cliente) van al final.
Una caché por significado. «¿Cómo puedo devolver la mercancía?» y «¿Hasta cuándo puedo devolver la mercancía?» son claves distintas. Una caché con vectores (la lección sobre los vectores) las trata como una sola pregunta. Encuentra más aciertos, y también falsos: «¿Puedo devolver unos zapatos?» y «¿Puedo devolver un regalo?» están cerca, y las respuestas pueden diferir.
Una respuesta en flujo. La respuesta puede llegar palabra a palabra (streaming). El tiempo total es el mismo, pero el cliente ve las primeras palabras a los cien ms en lugar de al segundo. Es rapidez para la persona, no para la cuenta.
Lotes. El trabajo que ningún cliente espera (resumir 10 000 reseñas de noche) puede pasar por un modo por lotes: más lento y más barato.
El tiempo en producción. El promedio esconde la cola: el 95 % de las respuestas pueden tardar menos de un segundo y el 5 % más de 5 segundos. Mide percentiles, como en la lección «Requisitos no funcionales que puedes medir» de «Ingeniería de software». Vigilar el costo y el tiempo en producción forma parte de MLOps y se enseña en ZeroToOps.
" ".join(question.lower().split()) separa por cualquier espacio en blanco y une con un solo espacio.Ejercicio
Qué solución ahorra más
Resuélvelo en tu editor.
El programa aplica las soluciones de forma acumulativa, así que no ves cuánto da cada una por sí sola. Ejecuta day tres veces, cada vez con una sola bandera, e imprime las filas junto a la que no tiene soluciones:
modelo grande, todos los documentos: 2.02 € por 1000 preguntas, 1032 ms de mediasolo presupuesto: 1.11 € por 1000 preguntas, 1009 ms de mediasolo caché: 1.30 € por 1000 preguntas, 654 ms de mediasolo modelo pequeño: 0.99 € por 1000 preguntas, 599 ms de mediaPor sí solo, el modelo pequeño es el más barato, y el presupuesto se le acerca. El presupuesto casi no ahorra tiempo, y la caché y el modelo pequeño lo reducen más, porque no esperan a que escriba el modelo grande. Las tres ahorran en sitios distintos, por eso juntas dan más.
Más tareas
- Un tema fácil más. Añade «atiende» a los temas fáciles. ¿Cuánto baja el costo? ¿Qué tienes que hacer antes de ponerlo en producción? (Pista: la lección sobre la evaluación.)
- Un tope para el día. Deja de preguntarle al modelo grande cuando el costo del día pase de 0,01 €, y responde «Te paso con un compañero». ¿A cuántas preguntas se queda sin respuesta del modelo?
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: El texto en trozos: tokens · La ventana de contexto · Llamar a un modelo a través de una API · Evaluación: un conjunto de pruebas para el asistente
- Continúa en: Dividir documentos en fragmentos (chunking) · RAG: respuestas a partir de los documentos · Evaluar RAG: ¿encuentra el fragmento y la respuesta se apoya en él? · El bucle del agente: plan, acción, observación
- Ejercicios sobre el tema: Aplicaciones con LLM