Juntar el equipo
Un equipo de investigación de agentes es un orquestador, unos trabajadores, una comprobación de cada resultado y una regla para parar. Importa porque cada pieza vista hasta ahora tiene un coste, y un equipo sin límite no tiene final.
Esta lección une el módulo en un solo bucle con un presupuesto de tokens.
Al final de esta lección
Nota
Puedo ejecutar un orquestador y trabajadores con un presupuesto, una comprobación y una regla de parada.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Presupuesto | el máximo de tokens que puede gastar una ejecución entera |
| Regla de parada | una prueba que termina la ejecución antes de que se acaben los encargos |
| Aceptado | un resultado que pasó todas las comprobaciones |
| Rechazado | un resultado dejado fuera, con sus motivos |
| Gastado | los tokens usados hasta ahora, de resultados buenos y malos |
| Suficiente | el número de resultados aceptados que termina la ejecución |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un bucle, tres límites
El orquestador toma los encargos en orden. Antes de cada uno se hace dos preguntas. ¿Ya tengo suficiente? ¿Podría este encargo hacerme pasar del presupuesto?
Luego pregunta al trabajador y comprueba el resultado. Cada respuesta se paga, así que lo gastado cuenta las buenas y las malas.
Ejemplo resuelto: una vuelta del bucle
| Paso | Pregunta | Si es sí |
|---|---|---|
| 1 | ¿Hay suficientes resultados aceptados? | Para, motivo suficiente |
| 2 | ¿Gastado más el límite de este encargo pasa del presupuesto? | Para, motivo presupuesto |
| 3 | Pregunta al trabajador, suma sus tokens a lo gastado | Siempre, bueno o malo |
| 4 | ¿El resultado pasa la comprobación? | Se acepta, si no se rechaza con motivos |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Por qué el límite va antes
Comprobar el presupuesto después de una llamada es tarde: los tokens ya se han ido. Por eso el bucle reserva el peor caso. Usa el límite del propio encargo, y para si no cabría.
La misma idea protege el tiempo y el número de rondas. Un equipo siempre tiene una regla que lo termina.
Un error frecuente
Advertencia
Mucha gente solo cuenta los resultados buenos contra el presupuesto. Un trabajador que falla también lee y escribe tokens. Cuenta todo lo que la ejecución pidió, o la factura no coincidirá con el presupuesto.
Escribir el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el equipo de investigación, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const BRIEFS = [' ' { id: \"b1\", question: \"¿Cuántos visitantes quieren abrir los domingos?\", sources: [\"s1\"], max: 900 },' ' { id: \"b2\", question: \"¿Cuánto costaría un domingo en horas de personal?\", sources: [\"s2\"], max: 900 },' ' { id: \"b3\", question: \"¿Cuánta gente hay un día de fin de semana?\", sources: [\"s3\"], max: 900 },' '];' '// Las respuestas de tres trabajadores con guion, grabadas.' 'const RECORDED = {' ' b1: { answer: \"212 de 400 visitantes lo quieren\", sources: [\"s1\"], tokens: 700 },' ' b2: { answer: \"108 euros cada domingo\", sources: [\"s2\"], tokens: 850 },' ' b3: { answer: \"310 visitas un sábado\", sources: [\"s3\"], tokens: 1200 },' '};' > team.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el equipo de investigación, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function problems(b, r) {' ' const out = [];' ' if (r.answer.trim().length === 0) out.push(\"falta la respuesta\");' ' r.sources.forEach(function (s) { if (b.sources.includes(s) === false) out.push(\"fuente desconocida \" + s); });' ' if (r.tokens > b.max) out.push(\"pasa de su límite\");' ' return out;' '}' >> team.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el equipo de investigación, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function team(budget, enough) {' ' const out = { accepted: [], rejected: [], spent: 0, stopped: \"fin\" };' ' for (const b of BRIEFS) {' ' if (out.accepted.length >= enough) { out.stopped = \"suficiente\"; break; }' ' if (out.spent + b.max > budget) { out.stopped = \"presupuesto\"; break; }' ' const r = RECORDED[b.id];' ' out.spent += r.tokens;' ' const p = problems(b, r);' ' if (p.length > 0) out.rejected.push(b.id + \" (\" + p.join(\", \") + \")\");' ' else out.accepted.push(r.answer);' ' }' ' return out;' '}' >> team.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el equipo de investigación, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' let first = null;' ' for (const run of [[2500, 3], [1500, 3], [4000, 2]]) {' ' const o = team(run[0], run[1]);' ' first = first || o;' ' console.log(\"presupuesto \" + run[0] + \", suficiente \" + run[1] + \": aceptados \" + o.accepted.length + \", rechazados \" + o.rejected.length + \", gastado \" + o.spent + \", paró por \" + o.stopped);' ' if (o.rejected.length > 0) console.log(\" rechazados: \" + o.rejected.join(\"; \"));' ' }' ' const q = [{ role: \"user\", content: \"Escribe una frase con estos hallazgos: \" + first.accepted.join(\"; \") }];' ' const r = await ask(q, \"Los visitantes quieren abrir los domingos y cuesta 108 euros cada domingo.\", 40);' ' console.log(\"Resumen: \" + r.text.trim());' '}' 'main();' >> team.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecutar el equipo de investigación
docker exec -w /home/node/project agent node team.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Los trabajadores están grabados
Los tres trabajadores son respuestas grabadas, con su cuenta de tokens, para que cada estudiante vea los mismos totales. La única llamada en vivo redacta un resumen de lo aceptado.
Un equipo real enviaría cada encargo a un modelo, y el bucle de alrededor sigue igual.
Una salida posible
| Línea | Qué muestra |
|---|---|
| presupuesto 2500, suficiente 3: aceptados 2, rechazados 1, gastado 2750, paró por fin | Gastó 2750 de 2500: la tercera respuesta pasó de su límite de 900 y el bucle solo había reservado 900 |
| rechazados: b3 (pasa de su límite) | El motivo se guarda |
| presupuesto 1500, suficiente 3: aceptados 1, rechazados 0, gastado 700, paró por presupuesto | El segundo encargo podía no caber |
| presupuesto 4000, suficiente 2: aceptados 2, rechazados 0, gastado 1550, paró por suficiente | Dos buenos resultados bastaban |
| Resumen: … | Una frase que cambia en cada ejecución |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.