enunciados + leetcode
Enunciados como los de una entrevista real para resolver por tu cuenta, con el tiempo que te darían, y problemas de LeetCode recomendados para cada tecnología y seniority. Nada se corrige acá: resolvelo en tu editor, en voz alta, y marcá lo que ya practicaste.
Vas a implementar el loop de un agente sin usar ningún framework. El modelo es un mock model.next(messages) que devuelve o bien { type: "tool_call", id: string, name: string, args: object } o bien { type: "final", text: string }. Tenés dos tools: getWeather({ city }), que devuelve { tempC: number }, y convert({ celsius }), que devuelve { fahrenheit: number }.
Implementá runAgent(userMessage, { maxSteps }) que agregue el mensaje del usuario, pida el siguiente paso al modelo, ejecute la tool pedida, agregue el resultado al historial con el id de la llamada y repita hasta recibir final o llegar a maxSteps. Armá un mock que, ante "¿Qué temperatura hace en Córdoba en Fahrenheit?", pida getWeather, después convert y finalmente responda.
# requisitos
maxSteps, devolviendo el historial hasta ese punto.args de cada tool antes de ejecutarla y devolverle al modelo el error de validación como resultado de la tool en vez de romper.maxSteps.# si te sobra tiempo, te van a preguntar
Tenés un mock streamCompletion(prompt, signal) que devuelve un async iterable de eventos { type: "delta", text: string } emitidos cada 50 ms y que termina con { type: "done", usage: { outputTokens: number } }. El mock respeta un AbortSignal: si se aborta, deja de emitir y lanza un AbortError.
Implementá collectStream(prompt, { onDelta, timeoutMs, stopSequences }) que vaya llamando a onDelta con cada fragmento, acumule el texto completo y devuelva { text, finishReason }, donde finishReason es "done", "timeout", "stop_sequence" o "aborted". Si aparece una stop sequence, aunque quede partida entre dos deltas (por ejemplo "FI" y "N" con stop sequence "FIN"), hay que cortar el stream y no incluirla en el texto.
# requisitos
AbortController para cancelar el stream ante timeout o stop sequence.onDelta texto que luego habría que retirar.AbortSignal.# si te sobra tiempo, te van a preguntar
Tenés que armar el contexto que se manda al modelo a partir de un system prompt, el historial de conversación { role: "user" | "assistant", content: string }[] y una lista de documentos recuperados { id, text, score }[]. Contás con countTokens(text): number (para el ejercicio, aproximá con Math.ceil(text.length / 4)).
Implementá buildContext({ system, history, docs, budget, reserveForOutput }) que respete el presupuesto total. Las prioridades son: el system prompt y el último mensaje del usuario entran siempre; después, los documentos por score descendente; después, el historial del más reciente al más viejo. Si el system más el último mensaje ya superan el presupuesto, hay que lanzar un error.
# requisitos
budget - reserveForOutput como límite estricto.# si te sobra tiempo, te van a preguntar