Passo 3 · Módulo 1 · Fundamentos·Substrato de inferência — o que o Alembic delega
Curso de Harness Engineering · Visual Course
Substrato de inferência: o que o Alembic deliberadamente delega
Quando a sua unidade de trabalho cruza a cintura estreita — o ModelAdapter → cliproxyapi → fetch — tudo o que acontece abaixo do fio (KV cache, batching, paged attention, prefill/decode, quantização) NÃO é código do Alembic. É do gateway e dos modelos MLX locais. Ao fim desta lição você entende cada uma dessas peças, o tradeoff de cada uma, e por que delegá-las é a decisão certa — não um buraco.
O mapa cita linha a linha: o adapter default é um proxy HTTP OpenAI-compatible puro — ModelRunInput → fetch → ModelRunResult, sem cache de token, sem scheduler de batch, sem kernel de atenção. Leitura conceitual de apoio que o founder indicou: walkinglabs · learn-harness-engineering (PT-BR) e ai-engineering-from-scratch — para os mecanismos de baixo nível que vivem do outro lado da cintura.
Leia a versão simples, ou abra a camada técnica em qualquer seção.
1
A grande ideia
O que assumimos de você (pouquíssimo)
Você sabe que um LLM "gera texto token a token". Só isso.
Você não precisa ter escrito um kernel de GPU, nem saber o que é VRAM.
Você lembra da lição 0002: toda chamada de modelo passa pela cintura estreita (o ModelAdapter + Result). Aqui a gente desce abaixo dessa cintura.
Pense no Alembic como um servidor de aplicação. Ele decide o que fazer, em que ordem, com que regras — mas não gerencia a memória física da máquina. Isso é trabalho do sistema operacional. Da mesma forma: o Alembic orquestra a unidade de trabalho (roteamento, gates, custo, observabilidade), mas a inferência de baixo nível — como os tokens são realmente computados na GPU — ele empurra para baixo da sua cintura.
Ao fim desta lição você consegue
Explicar o que é o KV cache, por que ele cresce, e o que "eviction / memory-pressure" significa.
Distinguir continuous batching de paged attention — e por que ambos são truques de throughput do servidor.
Dizer por que prefill é compute-bound e decode é memory-bandwidth-bound — e o que isso muda.
Ler uma tabela de quantização (INT8 / INT4 / FP8 / AWQ / GPTQ) e saber quando ela machuca a qualidade.
Comparar speculative decoding × quantização × destilação como três caminhos para cortar custo/latência.
Justificar a decisão do Alembic de delegar tudo isso — e apontar onde, no código, essa decisão aparece (ou some).
Existem três palavras que o curso inteiro usa para classificar cada peça de um harness: owned (o Alembic implementa), delegated (o Alembic empurra para baixo da cintura — o gateway cliproxyapi ou os modelos MLX locais) e gap (ainda não existe; vira roadmap). Esta lição é quase inteira sobre a coluna delegated. E delegar bem é uma virtude de engenharia, não uma omissão.
Pense como… a tomada da parede. Você liga o seu notebook sem saber (nem se importar com) como a usina gera os 127 V. A "interface" é o plugue. O Alembic faz o mesmo: a interface é a chamada OpenAI-compatible; a "usina" (KV cache, batching, quantização) fica do outro lado, e isso é de propósito. Onde a analogia quebra: você não escolhe a usina; o Alembic escolhe qual modelo/tier — só não gerencia os elétrons.
A cintura, em uma frase de código
O adapter default (cliproxyapi.ts:47-58) reduz toda a inferência a: callOpenAiCompatible({ baseUrl: 'http://127.0.0.1:8317', … }, input, Date.now()). Não há, em nenhum lugar dessa camada TypeScript, um cache de chave/valor, um agendador de lotes ou um kernel de atenção. Essa única escolha arquitetural é o que transforma ~7 dos 23 princípios do mapa em delegated em vez de gap: o Alembic não está "faltando" gerência de KV cache — ele a empurrou conscientemente para baixo do fio, do mesmo jeito que um servidor de aplicação empurra a gerência de page-cache para o kernel.
Por que isso é uma lição inteira
Porque a honestidade é o valor do curso. Um material desonesto fingiria que o Alembic "faz tudo". Este aqui diz: estas peças são reais, importantes, têm tradeoffs sérios — e o Alembic de propósito não as possui. Saber a fronteira é o que separa quem desenha um harness de quem só usa um.
A clean cross-section of a two-floor building used as a teaching metaphor for software layers. The top floor i
2
A fronteira: o que fica acima e abaixo do fio
A imagem-moldura do curso é a dos "Self-Learning Agents": três camadas. Model (os pesos — o Alembic delega), Harness (o loop/gates/routing — o Alembic possui) e Context (memória/skills — o Alembic compõe). Tudo nesta lição mora na camada Model, abaixo da cintura. Leia o diagrama de cima (sua unidade de trabalho) para baixo (os elétrons).
De cima (sua unidade de trabalho, código do Alembic) para baixo (a inferência real). A linha clay é A CINTURA: tudo embaixo é delegado — o Alembic não tem uma única linha disso.
Antes de continuar — adivinhe
Você abre cliproxyapi.ts inteiro (≈78 linhas). Quantas dessas peças da camada de baixo (KV cache, batching, paged attention, quantização) você espera encontrar implementadas ali?
Zero. O arquivo inteiro reduz a inferência a um fetch. O que ele tem é: o id do adapter, as capabilities (streaming/toolUse/vision), um healthCheck que dá um GET em /v1/models, e o run guardado. Nada de baixo nível. Essa "vacância" é a fronteira inteira da lição.
3
KV cache: a memória que cresce a cada token
Para gerar o próximo token, o modelo precisa "olhar para trás" para todos os tokens anteriores (isso é a atenção). Recalcular esse olhar do zero a cada token seria absurdamente caro. Então o servidor guarda os resultados intermediários de cada token — duas matrizes por token, chamadas Key e Value. Esse armazenamento é o KV cache. Ele transforma a geração de "O(n²) toda vez" em "O(n) incremental".
Pense como… escrever uma redação sem reler o texto inteiro a cada palavra nova — você mantém um resumo na cabeça (o KV cache) e só acrescenta. Onde quebra: o seu "resumo mental" não cresce sem parar; o KV cache cresce linearmente com o tamanho do contexto e mora na memória da GPU (VRAM), que é finita.
O KV cache é o "olhar para trás" pré-computado: t5 reaproveita K e V de t1..t4.O KV cache troca o custo quadrático (recalcular tudo) pelo incremental (só o token novo).
Cada token gerado acrescenta uma coluna ao KV cache. Ao bater no teto de VRAM, o servidor precisa de uma política: descartar (evict) ou paginar blocos — nunca o Alembic decide isso.
O elo com a sua unidade de trabalho: quando a Iris (a employee do exemplo do curso-produto) recebe um prompt longo — o "soul" dela + skills + memória composta + a petição da C.D — esse prompt vira muitos tokens, e cada um ocupa espaço no KV cache do servidor. Se o contexto for grande demais, é o gateway que sofre a pressão de memória e decide evict/paginar. O Alembic só viu um Result voltar (ou um erro, se o servidor estourar).
Dica O KV cache é por requisição e por token. Dobrar o tamanho do contexto ≈ dobrar a memória de KV. É por isso que "janela de 1M tokens" é caro de servir, não só de treinar.
Cuidado "Eviction" não é grátis: descartar KV de uma conversa ativa força recomputar. Por isso servidores preferem paginar (mover blocos) a descartar. Detalhe do servidor — não do harness.
Onde isso vive (e onde NÃO vive)
No HARNESS-MAP.md (princípio #4): "Where Alembic does it: Nowhere in the TS layer — and correctly so. This lives in the inference server behind cliproxyapi (and in the local MLX runtime for LOCAL/offline models)." Status: delegated. Não é owned, não é gap — fora de escopo por design.
No setup local do founder (memória local-models-macbook): o KV cache de modelos como o DeepSeek-V4-Flash q2 (81 GB de pesos mmap'd, janela de até 1M tokens) ou o Qwen3-VL-30B-A3B é gerenciado pelo runtime MLX no M5 Max de 128 GB — o Alembic enxerga só a porta OpenAI-compat em :8000/:8317. [a verificar: os detalhes finos da política de eviction de cada runtime MLX/DS4 não foram inspecionados linha a linha — o que está verificado é apenas que o Alembic não tem código de KV cache.]
4
Continuous batching & paged attention
Duas ideias diferentes que vivem juntas no servidor:
Continuous batching — em vez de esperar um lote de requisições terminar para começar o próximo, o servidor intercala os passos de geração de várias requisições ao mesmo tempo. Assim que uma termina, outra entra no lugar imediatamente, sem deixar a GPU ociosa. É throughput: mais requisições por segundo no mesmo hardware.
Paged attention — gerencia o KV cache como a memória virtual de um sistema operacional: divide-o em "páginas" de tamanho fixo, em vez de exigir um bloco contíguo gigante por requisição. Isso elimina o desperdício (fragmentação) e deixa o servidor empacotar muito mais requisições na mesma VRAM.
Pense como… um restaurante. Continuous batching = assim que uma mesa termina, a próxima senta na hora (nunca deixa a mesa vazia). Paged attention = mesas modulares que você junta/separa conforme o grupo, em vez de reservar o salão inteiro para cada cliente. Onde quebra: num restaurante o garçom é o gargalo; aqui o gargalo é a largura de banda da memória da GPU.
Em cima: lotes estáticos desperdiçam a GPU enquanto a requisição mais lenta não acaba. Embaixo: o continuous batching preenche cada vaga assim que abre. Ambos são decisões do servidor de inferência.Sem paginação, cada requisição tranca um bloco grande contíguo e desperdiça o que sobra (fragmentação). Com paged attention, o KV vira páginas de tamanho fixo que se intercalam e preenchem os buracos — densidade de memória, decisão do servidor.
Não confunda com o "batching" do Alembic
O Alembic tem uma forma de "batching", mas é uma coisa completamente diferente: concorrência em nível de requisição no swarm (swarm/src/lead-dispatcher.ts · maxConcurrency, default 1, com rampa opcional). Isso é fan-out de orquestração — "rodar 3 unidades de trabalho em paralelo" — e não tem nada a ver com intercalar passos de decodificação de tokens dentro do servidor. Dois conceitos, dois andares. O HARNESS-MAP marca o cap de concorrência do swarm como owned, e o continuous batching como delegated.
Guarde istoContinuous batching = throughput (mais reqs/s). Paged attention = densidade de memória (mais reqs na mesma VRAM). Os dois são do servidor; o "batching" que você vê no código do Alembic é orquestração, outro andar.
A teaching illustration of a busy restaurant used as an analogy for server-side request scheduling. On the lef
5
Prefill vs decode: duas físicas diferentes
Gerar uma resposta tem duas fases, e elas têm naturezas opostas:
Prefill (processar o prompt inteiro de uma vez) é compute-bound: todos os tokens do prompt são processados em paralelo, então a GPU fica saturada de cálculo. É o que determina o time-to-first-token (quanto demora até a primeira palavra aparecer).
Decode (gerar os tokens de saída, um a um) é memory-bandwidth-bound: cada novo token precisa ler o KV cache inteiro da memória, e isso é serial (um token de cada vez). O gargalo não é o cálculo — é a velocidade de ler memória. É o que determina o inter-token-latency (a cadência da digitação).
Pense como… ler um livro e depois resumir em voz alta. Ler (prefill) você faz rápido com os olhos varrendo a página inteira; falar o resumo (decode) sai palavra por palavra, no ritmo da sua boca. Onde quebra: a "boca" aqui é a largura de banda da VRAM, e ela não acelera juntando mais núcleos de cálculo.
Prefill é um passo paralelo "gordo" (limitado por cálculo); decode é uma sequência de passos finos (limitada por leitura de memória). Otimizam de formas diferentes — e o Alembic mede só o tempo total das duas somadas.O decode lê os pesos inteiros a cada token através de uma banda de memória estreita; os núcleos de cálculo ficam ociosos esperando. Por isso reduzir os bits (quantização) ajuda o decode mais do que comprar poder de cálculo — é a ponte para a próxima seção.
Demo: o orçamento de latência de uma resposta
Mexa nos controles e veja como o tamanho do prompt empurra o prefill (a espera até o 1º token) e o tamanho da saída empurra o decode (o tempo de digitação). Os ritmos (tok/s) usam os números reais medidos no M5 Max do founder como ponto de partida.
prefill ≈ 49 ms (até o 1º token)decode ≈ 11.8 stotal ≈ 11.8 sgargalo: decode
Com prompt curto e saída longa, o decode domina — e decode é memory-bandwidth-bound, então comprar uma GPU "mais rápida em cálculo" quase não ajuda. É por isso que quantizar (que reduz a memória lida por token) costuma acelerar mais o decode do que aumentar o poder de cálculo.
Modelo simplificado p/ ensino: prefill ~ entrada ÷ 40.500 tok/s; decode ~ saída ÷ 33,9 tok/s (ritmos reais do DeepSeek-V4-Flash q2). É didático, não um benchmark do seu hardware.
O que o Alembic enxerga (só o total)
O HARNESS-MAP #5 é explícito: "Not modeled in the TS layer. Alembic measures end-to-end latency only — the OTEL span's start_time/end_time are the event's own timestamp (harness/src/otel.ts:53-64); the funnel records wall-clock durationMs." Confirmado na leitura: em toOtelSpan, start_time e end_time são ambos event.at — o evento é um ponto no tempo, não tem fase de prefill vs decode.
Status: delegated (o split é do servidor). Vira gap só se o Alembic algum dia quisesse routing ciente de prefill/decode — ele não tem hoje nenhuma quebra de TTFT vs inter-token-latency.
6
Quantização: trocar precisão por memória e velocidade
Os pesos de um modelo são números. Por padrão eles são armazenados em alta precisão (16 bits cada). Quantização é guardar esses mesmos números com menos bits — 8, 4, até menos. Menos bits = o modelo ocupa menos memória e cada token lê menos dados (lembre: decode é memory-bandwidth-bound, então isso acelera de verdade). O preço: cada peso fica menos preciso, e em algum ponto a qualidade do raciocínio começa a degradar.
Pense como… salvar uma foto em JPEG com mais compressão. Arquivo menor, abre mais rápido — mas exagere e aparecem "artefatos". Quantizar demais um modelo é o "JPEG estourado" do raciocínio: ele começa a errar contas, perder o fio em contextos longos, alucinar mais. Onde quebra: diferente do JPEG, dá para ser esperto sobre QUAIS pesos comprimir (é o que AWQ e GPTQ fazem) e preservar quase toda a qualidade.
o vocabulário, em uma olhada
Esquema
O que é
Quando brilha
FP16 / BF16
16 bits, ponto flutuante — a precisão "cheia" de referência.
Baseline de qualidade; o que você compara contra.
FP8
8 bits em ponto flutuante (mantém faixa dinâmica).
Hardware novo (ex.: H100); ótimo equilíbrio qualidade/velocidade.
INT8
8 bits inteiros. ~½ da memória do FP16.
Quase sem perda perceptível; o "padrão seguro".
INT4
4 bits inteiros. ~¼ da memória.
Couber-na-VRAM agressivo; aqui a qualidade começa a doer.
GPTQ
Método que quantiza pós-treino minimizando o erro camada a camada.
INT4/INT3 com perda muito menor que o corte ingênuo.
AWQ
"Activation-aware": protege os ~1% de pesos mais importantes.
INT4 preservando qualidade; popular por isso.
Demo: o tradeoff tamanho × qualidade × velocidade
Escolha um esquema de quantização para um modelo de referência (≈30 B de pesos, partindo de 60 GB em FP16) e veja os três eixos se moverem ao mesmo tempo. Note como AWQ/GPTQ entregam o tamanho do INT4 com muito mais qualidade que o INT4 ingênuo.
Memória (pesos)
60 GB
Velocidade de decode
1.0×
Qualidade retida
100%
FP16: a referência. Qualidade máxima, mas é o que mais pesa na VRAM e o decode mais lento por token. Tudo abaixo troca um pouco de qualidade por memória/velocidade.
Valores ilustrativos para ensinar o formato do tradeoff (não medições de um modelo específico). A lição real: a curva qualidade×tamanho não é reta — GPTQ/AWQ dobram a curva a seu favor.
De 16→8 bits a qualidade quase não cai. Abaixo de 4 bits, o corte ingênuo (linha rust) despenca; métodos espertos (AWQ/GPTQ, linha olive) seguram a qualidade pesando o mesmo. "Quando a quantização machuca" = a parte íngreme da curva.
Prova viva no setup do founder: o melhor VLM local medido foi o Qwen3-VL-30B-A3B em 4 bits (110–117 tok/s, ~19,5 GB) — e ele venceu em acurácia um modelo 72B denso muito maior. Já o DeepSeek-V4-Flash usa um truque fino: quantização assimétrica 2/8 bits — comprime agressivo onde dá, mas mantém 8 bits onde precisa para não perder o tool-use. Esse é exatamente o "seja esperto sobre quais pesos comprimir" da curva acima.
Por baixo "Activation-aware" (o AW de AWQ): nem todo peso importa igual. Uma fração pequena tem impacto desproporcional na saída. AWQ identifica e preserva esses, quantizando agressivamente o resto.
Quando dói A degradação não é uniforme: aparece primeiro em raciocínio em múltiplos passos, contexto longo e tool-use — justo o que um agente mais usa. Por isso quantização agressiva é arriscada para um harness sério.
O Alembic NÃO modela precisão — e isso aparece no schema
Esta é a evidência mais limpa da lição. O HARNESS-MAP #8 diz: "Model selection is by tier + price, not by quant level. The registry has maxOutputTokens and noImageSupport flags but no precision/quant metadata." Confirmado lendo contracts/src/registry.ts:8-30: o modelRegistryEntrySchema tem modelId, adapterId, tier, costPer1kInputUsd/OutputUsd, capabilities, e os opcionais provider/baseUrl/maxOutputTokens/noImageSupport — e o comentário do próprio código diz que esses quatro "feed the offline doctor --client-stack smoke check… never routing or pricing". Não existe campo de precisão. O Alembic trata cada modelId como uma tupla opaca capability+preço.
Status: delegated para quem serve os pesos. Vira gap só se um dia se quisesse routing ciente de quant — aí o schema do registry precisaria de um campo precision.
A teaching illustration contrasting image compression with model quantization. A single portrait photograph sh
7
Três caminhos para cortar custo/latência
Quantização não é a única alavanca. Há três técnicas clássicas para deixar a inferência mais barata/rápida — e elas atacam ângulos diferentes. Duas são puramente do servidor; uma é treino. O Alembic delega todas as três — mas vale entender o que cada uma faz.
caminho 1 · clique p/ virar
Speculative decoding
o que é? como acelera?
Um modelo rascunho (pequeno/rápido) "chuta" vários tokens à frente; o modelo grande verifica todos de uma vez. Os aceitos passam de graça. Acelera o decode sem mudar a qualidade (a saída é idêntica à do modelo grande sozinho).
caminho 2 · clique p/ virar
Quantização
o que troca?
Menos bits por peso → menos memória, decode mais rápido. Pode custar qualidade (a curva da seção 6). Não muda a arquitetura nem precisa de treino novo; é pós-processamento dos pesos.
caminho 3 · clique p/ virar
Destilação
por que é diferente?
Treinar um modelo aluno pequeno para imitar um professor grande. Resultado: um modelo menor e mais barato permanentemente — mas exige treino (caro, offline) e é um modelo novo, não o mesmo comprimido.
a pegadinha do Alembic · vire
"Destilação" no Alembic
cuidado com a palavra
O alembic distill destila um corpus de conhecimento (T0→T3 → LEARNINGS/SIGNALS), não um modelo. A palavra é a mesma; a técnica de ML não. No mapa: model-distillation = gap.
O rascunho aposta vários tokens à frente; o modelo grande os verifica todos num passo paralelo e aceita os que baterem. Acelera o decode sem mexer na qualidade — diferente da quantização. Tudo no servidor.Comparativo dos três caminhos. Speculative não toca a qualidade; quantização pode tocá-la; destilação produz um modelo novo via treino. No Alembic: speculative + quant = delegated; model-distillation = gap (a palavra "distill" no repo é outra coisa).
Exemplo guiado — escolhendo a alavanca para a fábrica da Iris
1
Sintoma: as respostas da Iris para a C.D demoram a "começar a digitar" (o 1º token tarda). Qual fase está lenta?
2
Diagnóstico: "tardar a começar" = prefill (time-to-first-token). O prompt da Iris é enorme (soul + skills + memória + petição). Prefill é compute-bound.
3
Alavanca certa: reduzir o tamanho do prompt (isso é context engineering, lição 0006 — owned pelo Alembic) ataca o prefill direto. Quantizar ajuda mais o decode, não tanto o prefill.
4
Onde mora a decisão: a escolha de modelo/tier é do Alembic (owned); a execução de prefill/quant é do gateway (delegated). O harness escolhe a estratégia; o substrato a executa.
5 · agora você
Tente: se o problema fosse "a Iris digita devagar depois de começar", qual fase? qual alavanca? (decode · quantização ou speculative decoding)
Resumo de bolso: speculative = mais rápido sem perder qualidade (mas precisa de um modelo rascunho); quantização = menor e mais rápido, com risco de qualidade; destilação = um modelo novo, menor de vez, mas custa um treino. O Alembic não faz nenhum dos três — ele escolhe qual modelo chamar, e o gateway faz o resto.
O HARNESS-MAP #7 separa: speculative decoding + weight quantization → inteiramente a camada gateway/MLX (delegated). Model distillation = gap (não feito). E alerta para o overload do termo: a "distillation funnel" (@alembic/etl, alembic distill) destila um corpus em LEARNINGS+SIGNALS, não pesos. Confundir os dois é o erro clássico ao ler o repo.
8
Por que delegar é a decisão certa
Tudo nesta lição é a coluna delegated. A pergunta honesta é: isso não é uma falha? Não. É a mesma disciplina de um servidor de aplicação que não reescreve o kernel: você possui a sua camada de valor com excelência e confia na camada de baixo no contrato dela. O Alembic possui a cintura (o contrato) e o comportamento de falha no fio (Result, breaker, retry). O que está embaixo, ele não toca.
É literalmente um fetch. Olhe o coração do adapter default:
packages/adapters/src/cliproxyapi.ts:47-58
// O adapter default reduz TODA a inferência a uma chamada HTTP.const attempt = (input: ModelRunInput): Promise<ModelRunResult> =>
callOpenAiCompatible(
{
adapterId: CLIPROXYAPI_ID,
baseUrl, /* http://127.0.0.1:8317 */
apiKey: options.apiKey,
headers: options.headers,
fetchImpl,
},
input,
Date.now(),
);
// As capabilities que ele anuncia — repare no que NÃO está aqui:const CAPABILITIES: ModelCapabilities = {
streaming: true, toolUse: true, vision: true,
// sem precisão. sem quant. sem KV. sem batch. Tudo isso é do outro lado do fio.
};
O substrato em três colunas. O grosso é delegated (correto, por design). Os "gaps" aqui são condicionais — só viram roadmap se o Alembic decidir rotear por precisão/fase, o que hoje ele deliberadamente não faz.
O único fato em que toda a lição se apoia
"That single architectural choice is what makes ~7 of the 23 principles below delegated rather than gap: Alembic isn't missing KV-cache management — it consciously pushed it below its waist, the same way an application server pushes page-cache management to the kernel." — HARNESS-MAP.md, "The one fact the whole map hinges on: the narrow waist".
O seam offline↔online é um único campo (adapterId), não dois caminhos de código. A complexidade de inferência inteira (KV, batch, quant) mora atrás do valor 'cliproxyapi' — invisível para a cintura.
Guarde isto A troca offline↔online no Alembic é um campo: adapterId: 'local' (o caminho $0 determinístico) vs 'cliproxyapi' (o gateway). Não são dois códigos diferentes — é a mesma cintura apontando para substratos diferentes. Toda a complexidade de inferência mora atrás desse campo.
A teaching illustration of a clear ownership boundary line. A horizontal divider splits the composition: above
9
Recapitulando
Passe pelos slides para fixar a fronteira inteira — de cima (a cintura) para baixo (os elétrons).
A fronteira
Abaixo do fio, não é código do Alembic
A cintura é um fetch para 127.0.0.1:8317. KV cache, batching, paged attention, prefill/decode, quantização: tudo delegated ao gateway + MLX.
1
KV cache
A memória que cresce a cada token
K e V guardados por token transformam O(n²) em O(n). Cresce linear com o contexto, enche a VRAM → o servidor faz eviction/paging. Nunca o Alembic.
2
Throughput do servidor
Batching ≠ paging ≠ swarm
Continuous batching = mais reqs/s. Paged attention = mais reqs na mesma VRAM. O "batching" do Alembic é concorrência de orquestração — outro andar.
3
Duas físicas
Prefill compute-bound, decode memory-bound
Prefill = 1 passo paralelo (time-to-first-token). Decode = passos seriais que leem o KV (tok/s). O Alembic mede só o total no span.
4
Quantização
Menos bits, com uma curva que não é reta
16→8 bits quase não dói; abaixo de 4 despenca. AWQ/GPTQ dobram a curva a favor protegendo os pesos certos. O registry não tem campo de precisão.
5
A decisão
Delegar é disciplina, não buraco
Speculative · quantização · destilação = três alavancas, todas delegated. O Alembic possui a cintura e a falha no fio; confia no substrato no contrato dele.
6
1 / 6setas ←→
As Dez verdades do substrato delegado
O adapter default do Alembic é um proxy HTTP puro — ModelRunInput → fetch → ModelRunResult.
KV cache guarda K e V por token; troca O(n²) por O(n) incremental.
O KV cache cresce linear com o contexto e mora na VRAM finita → daí eviction/paging.
Continuous batching mantém a GPU sempre cheia (throughput); é do servidor.
Paged attention gerencia o KV como memória virtual (densidade); também do servidor.
Prefill é compute-bound (1º token); decode é memory-bandwidth-bound (tok/s).
Quantizar reduz bits/peso → ajuda mais o decode; a curva qualidade×bits não é reta.
AWQ/GPTQ protegem os pesos importantes → INT4 com qualidade quase de INT8.
A degradação por quant aparece primeiro em raciocínio longo + tool-use — o que um agente mais usa.
No registry não há campo de precisão: cada modelId é tupla opaca capability+preço. Tudo isso = delegated, por design.
Verifique seu entendimento
Três perguntas. A pontuação corre sozinha embaixo.
1. Por que o Alembic não tem código de KV cache, e isso é classificado como o quê?
(b) A cintura é um fetch; KV cache é do gateway + MLX. Não é falha (gap) nem implementação própria (owned) — é uma delegação consciente, como um app server delega page-cache ao kernel.
2. A Iris demora a começar a responder (1º token tarda). Qual fase, e que natureza ela tem?
(c) "Tardar a começar" = time-to-first-token = prefill, que é compute-bound e cresce com o tamanho do prompt. Encolher o contexto (context engineering, lição 0006) é a alavanca; quantização ajuda mais o decode.
3. Qual afirmação sobre quantização está correta?
(a) A curva não é reta: AWQ/GPTQ dobram-na a favor preservando os pesos de maior impacto. (b) é falso — a queda é íngreme abaixo de 4 bits. (c) é falso — não existe campo precision no modelRegistryEntrySchema; quant é delegated.
Acertos: 0/3
Você é o professor agora: se o seu harness precisasse escolher entre um modelo INT4-AWQ barato e um FP8 caro para uma tarefa de raciocínio jurídico longo, que pergunta você faria primeiro? (Dica: pense em onde a quantização machuca.)
Na próxima lição (0004 · Saída estruturada & ferramentas) subimos de volta para cima da cintura: como o Alembic valida o JSON que o modelo cospe com Zod nos boundaries, o GAP de auto-repair, e por que a superfície MCP é read-only por design.