Um dia com um modelo de 1.5B: o que o Qwen2.5-Coder consegue (e não consegue) fazer
Um relato prático de colocar o Qwen2.5-Coder-1.5B para trabalhar como motor de um pipeline de dados real, com os números que comprovam isso.
Há muito entusiasmo de marketing em torno dos modelos pequenos locais, e menos registros cuidadosos do que acontece quando você coloca um para trabalhar em um pipeline real, sem supervisão, por horas. Este é esse registro, para o Qwen2.5-Coder-1.5B-Instruct — uma quantização Q4_K_M GGUF rodando localmente via llama.cpp — usado como gerador de primeira rodada em um pipeline cujo objetivo final é um dataset específico de Drupal preciso o suficiente para ajudar engenheiros a migrar sites Drupal 7 mais rápido.
O papel que demos a ele
O trabalho do modelo: ler um documento-fonte (uma página de referência de API, ou um par de pergunta-resposta de um fórum técnico) e produzir um objeto JSON instruction/response estruturado e ancorado nessa fonte — sem copiá-la literalmente, e sem inventar fatos que não estejam nela. É uma tarefa exigente para um modelo de 1.5B, e cada melhoria ao longo do caminho precisou ser conquistada contra dados medidos reais, não contra um exemplo escolhido a dedo.
Descoberta 1: ele tem instintos fortes — às vezes fortes demais
O comportamento mais interessante que encontramos: quando o contexto de entrada era longo ou ruidoso, o modelo às vezes recorria a uma resposta confiante e plausível vinda de seus dados de treinamento em vez do texto- fonte específico à sua frente. Capturamos a mesma resposta memorizada e bem formada aparecendo em páginas de documentação sobre classes completamente diferentes — um sinal claro de que o modelo tinha uma forte tendência prévia sobre "a resposta de sempre" e precisava de um empurrão em direção ao texto específico em questão.
A correção foi direta: em vez de uma instrução genérica de "não invente coisas", nomeamos explicitamente o conteúdo recorrente exato e dissemos claramente ao modelo para não recorrer a ele a menos que a fonte realmente tratasse disso. Isso funcionou de imediato e de forma duradoura — uma instrução precisa e específica superou em muito uma genérica.
Descoberta 2: ele leva seu exemplo trabalhado muito ao pé da letra
Incluímos um exemplo trabalhado (few-shot) no prompt para demonstrar o formato de saída esperado — prática padrão e bem respaldada. Em volume, os nomes fictícios do exemplo reapareciam ocasionalmente em respostas reais, um padrão sério o suficiente para exigir uma correção dedicada (a taxa exata de vazamento medida, e como a resolvemos, está em um artigo à parte sobre prompting few-shot). Resumindo: assim que entendemos por que isso acontecia (um exemplo com nomes plausíveis é difícil de distinguir do conteúdo real para um modelo pequeno), a correção foi direta — trocar o exemplo por algo deliberadamente inconfundível, e nomear explicitamente o vazamento como proibido. Isso coincide com pesquisas publicadas sobre "regurgitação de demonstrações" em modelos pequenos, o que foi uma boa checagem de sanidade de que havíamos diagnosticado o mecanismo real, e não apenas remendado um sintoma.
Descoberta 3: dê a ele uma checklist, não só uma instrução
Quando exigimos que a saída contivesse tanto uma assinatura copiada exata quanto uma explicação em linguagem simples do comportamento, o modelo às vezes devolvia só a assinatura. Em vez de brigar com isso em prosa, movemos a explicação para seu próprio campo obrigatório em um JSON Schema, forçado por decodificação restrita por gramática na camada de inferência. Isso resolveu o problema completamente, porque, nesse caso, o modelo já sabia como era uma boa explicação; só precisava de um empurrão estrutural para sempre incluí-la.
Descoberta 4: uma ideia razoável para testar — e a disciplina de reverter
Testamos mais uma ideia: em vez de deixar o modelo procurar e copiar uma assinatura de método do código-fonte, demos a ele uma lista numerada e pré-verificada de opções válidas e pedimos que escolhesse uma — eliminando até a possibilidade de copiar uma assinatura inexistente. É uma hipótese razoável, e vale a pena testá-la. Neste caso, medido ao vivo em vez de em uma amostra pequena revisada manualmente, a taxa de aceitação de primeira rodada daquele pipeline caiu de aproximadamente 40% para 21,4%, porque o modelo escolhia um item válido e depois descrevia um item diferente, memorizado, em seu lugar.
Revertemos, mantivemos a lista numerada como referência para o modelo em vez de um mecanismo rígido, e seguimos em frente dentro da mesma sessão de trabalho. Essa disposição de testar uma ideia, medi-la com honestidade contra tráfego ao vivo em vez de uma amostra favorável, e reverter quando os dados dizem não, foi o que tornou confiável o restante do progresso do dia.
O que realmente fez diferença
Em uma comparação controlada, mesmo verificador, mesma amostra fixa de 8 documentos reais:
Base (temperatura 0.2)
1/8 aceitos
Self-consistency (3 amostras, voto majoritário)
0/8
Best-of-3 com pontuação heurística
0/8
Temperatura 0 (decodificação greedy total)
2/8 — melhor resultado
Sem exemplo few-shot
0/8
Alternando entre 3 exemplos few-shot
0/8
Seleção de símbolo tipo múltipla escolha
0/8
A decodificação greedy deu o melhor resultado nessa comparação — indo de 1/8 para 2/8. Vale a pena ser preciso sobre o que isso é: uma amostra de 8 é pequena o suficiente para que "dobrou" seja um sinal preliminar, não um resultado consolidado. Foi consistente com uma observação separada e em escala maior em uma execução posterior sem supervisão (abaixo), o que nos deu confiança suficiente para mantê-lo como padrão de produção — mas a comparação de 8 itens sozinha não deveria ser lida como estatisticamente conclusiva.
O resultado final, em números
Ao longo de uma execução de produção de 7 horas sem supervisão, o modelo alcançou uma taxa de aceitação de primeira rodada de 46,0% na tarefa de geração de documentação (176 pares verificados escritos) e de 26,4% na tarefa mais difícil e menos estruturada de perguntas e respostas da comunidade (53 pares verificados) — subindo de um ponto de partida de 0% nessa segunda tarefa, mais cedo no projeto, depois de uma correção separada e não relacionada a um filtro anterior excessivamente rígido. O número de 46,0% iguala a melhor taxa que esse pipeline já registrou, historicamente, com uma mistura notavelmente mais saudável de casos-limite restantes.
Nada disso torna um modelo de 1.5B um substituto de um maior. O que isso mostra é que um modelo pequeno, projetado em torno de suas falhas específicas e bastante previsíveis, pode carregar a maior parte de uma carga de trabalho de geração de alto volume a custo marginal essencialmente zero — o que importa diretamente para o objetivo de fundo: produzir um dataset de Drupal grande e preciso o suficiente para ser genuinamente útil em trabalho de migração, sem o custo de passar cada geração individual por um modelo caro.