//Receita

Recuperar a estrutura de um texto cru

O texto chegou com as linhas quebradas no meio da frase e sem marcador nenhum. Recuperar a estrutura é decisão, não redação.

Um memorando chega por e-mail em texto puro. As linhas foram quebradas no meio das frases, os títulos perderam a marcação, as duas listas perderam os marcadores e um aviso importante ficou indistinguível de um parágrafo comum. Você precisa daquilo como markdown, para publicar na base de conhecimento.

O conteúdo está todo lá. O que se perdeu foi a estrutura.

Por que a solução ingênua falha

Pedir a um modelo generativo que “reescreva isto em markdown” resolve na aparência e cria um risco que só aparece depois: a reescrita pode mudar palavras. Em memorando interno isso é irritante; em norma, contrato ou bula, é inaceitável — e a alteração é difícil de detectar justamente porque o texto sai bom.

A segunda tentativa é heurística pura: linha curta é título, linha que começa com verbo no infinitivo é item de lista. Funciona no documento que você usou para escrever as regras e quebra no próximo.

E existe uma terceira armadilha, mais sutil, que o cookbook documenta: perguntar a coisa errada ao modelo. Voltamos a ela adiante, porque é a lição mais transferível desta receita.

O desenho das perguntas

Duas requisições, e uma divisão clara de trabalho: o código lê a evidência direta, o modelo julga o que sobra, o código renderiza.

O que fica no código. Linhas em branco e marcadores explícitos (-, 1., #) são fatos do texto: o código os lê e nunca os manda ao modelo para reconsiderar. No memorando do experimento, as linhas em branco sobreviveram e todos os marcadores se perderam — então o modelo recebe só o que o código não consegue decidir.

Requisição 1, costurar. Uma pergunta Noul por par de linhas vizinhas, todas juntas:

from typesafe_sdk import Noul, NoulCriteria

def pergunta_de_juncao(i: int) -> Noul:
    return Noul(
        instructions=(
            f"A linha L{i:03d} começa no meio de uma frase, continuando uma frase "
            f"deixada incompleta no fim da linha L{i - 1:03d}?"
        ),
        criteria=NoulCriteria(
            true="A linha começa no meio de uma frase iniciada na linha anterior: a quebra rasgou a frase",
            false="A linha começa uma frase, um item, um título ou um pensamento próprio",
        ),
    )

O limiar de junção depende de um fato que o código sabe ler: como a linha anterior termina. Depois de uma linha sem pontuação final, 0,2 já basta para juntar; depois de ponto, dois-pontos ou ponto e vírgula, o corte sobe para 0,5. Um corte único não serve para os dois casos — e essa é uma decisão que o código toma olhando a pontuação, não o modelo.

Requisição 2, classificar. Um Choice por bloco costurado, entre título, parágrafo, item de lista, citação, código e destaque. Junto vão perguntas acompanhantes — nível do título, se a ordem dos itens importa, que tipo de destaque é — lidas apenas quando o tipo do bloco as torna relevantes. Elas vão na mesma requisição porque os tipos ainda não são conhecidos, e esperar por eles custaria uma terceira ida e volta; a pergunta extra custa pouco, já que o state é a maior parte dos tokens e vai uma vez só.

O que o experimento oficial mediu

O documento é um memorando sobre migração de build, em inglês, no estado descrito acima. Números publicados pela TypeSafe, com o jev-1.12:

EtapaPerguntasTempo
Costura (passo 1)160,32 s
Classificação (passo 2)62 sobre 17 blocos0,51 s
Total0,8 s, 10.211 tokens

As 28 linhas viraram 17 blocos, com 11 quebras de linha costuradas. A classificação acertou a estrutura: o comando de shell solto virou bloco de código, as três linhas de time viraram lista com marcador (perguntas de ordem entre 0,12 e 0,16), as três tarefas antes de segunda viraram lista numerada (ordem entre 0,86 e 0,90) e o aviso sem marcação nenhuma foi classificado como destaque do tipo “warning”.

Sobre o custo em dólar, o cookbook se contradiz: o código imprime US$ 0,0003 para essa execução e o texto afirma US$ 0,0015 em dois lugares. Registramos as duas coisas e citamos o número que o código imprime.

E o bloco mais incerto é instrutivo: a frase que apresenta a lista ficou com confiança 0,43, dividida entre parágrafo 0,53, item de lista 0,24 e destaque 0,19. É ambiguidade real — a frase nomeia o que vem depois (cara de título), é uma frase completa (cara de parágrafo) e está onde um destaque costuma estar. O cookbook sugere o uso óbvio: sublinhar para revisão qualquer bloco cuja confiança de tipo fique abaixo de 0,55.

A lição que vale para toda receita

A parte mais transferível deste cookbook não é a estrutura: é a experiência sobre redação da pergunta.

A primeira versão perguntava o que parecia natural: “estas duas linhas são do mesmo parágrafo?”. O resultado foi ruim de um jeito específico. Um punhado de linhas curtas sob um título — uma lista digitada sem marcadores — é um parágrafo no sentido frouxo: as linhas estão juntas e falam do mesmo assunto. Com essa redação, todos os itens de lista pontuaram acima de 0,75 e as listas colapsaram em blocos corridos: 12 blocos em vez de 17.

Mesmo documento, mesma forma de requisição, só a redação mudou:

Linha“continua a frase”“mesmo parágrafo”
“The platform team”0,220,77
“The web client team”0,110,81
“Delete the old build cache directory”0,080,88
“Run the doctor script and fix anything it flags”0,050,91

A regra que sai daí: quando um julgamento alimenta um limiar, pergunte o fato mais estreito que decide aquele limiar. “Mesmo parágrafo” pede ao modelo que julgue se o assunto continua, e entre itens de lista ele continua. “Continua a frase” pergunta sobre o texto em si. É a diferença entre 17 blocos e 12 — e é a mesma disciplina descrita em critérios que separam.

O que muda em português

A mecânica não depende de idioma, e a costura tem uma vantagem em português: nossas frases são mais longas, então a quebra no meio da frase é mais frequente e a pergunta tem mais evidência para trabalhar.

Dois ajustes locais. A detecção de pontuação final precisa incluir o travessão de diálogo e as reticências, comuns em texto brasileiro. E documento oficial em PDF costuma trazer hifenização de fim de linha (“estabele-” / “cimento”): isso é remendo de código, feito antes da costura, não pergunta.

Como a TypeSafe declara que o inglês é a língua principal de treino, teste os dois limiares de junção nos seus documentos antes de rodar em lote.

Onde isso quebra

  • Tabela. Texto que perdeu a formatação de tabela não volta com esta receita: as colunas viraram espaços e reconstruí-las é outro problema.
  • Documento longo. O documento inteiro entra no state das duas requisições, e documento grande derruba acurácia, conforme os limites do jev-1.13. Fatie por seção.
  • Contagem e numeração. “Renumere os itens de 1 a 7” é conta, e conta é código. A receita decide se a lista é ordenada; o código escreve os números.
  • Geração. Se o objetivo é reescrever ou resumir, esta não é a ferramenta: o jev-1.13 não é treinado para gerar texto.

O índice das receitas está em receitas.

Perguntas frequentes

Por que não pedir a um LLM que reescreva em markdown?

Porque reescrever pode mudar as palavras. Nesta receita o modelo nunca gera texto: ele responde perguntas estreitas sobre o documento e o código faz a renderização, então cada caractere da saída vem da entrada.

Quais são as duas requisições?

A primeira faz uma pergunta Noul por par de linhas vizinhas: esta linha continua uma frase interrompida na anterior? A segunda, depois de costurar os blocos, faz uma pergunta Choice por bloco: que tipo de conteúdo é este?

Por que duas e não uma?

Porque os blocos só existem depois que a primeira respondeu. É um dos casos em que a documentação considera legítimo fazer uma segunda requisição: o código não consegue montar a segunda pergunta antes de ter a primeira resposta.

A redação da pergunta muda o resultado?

Muito. Com a pergunta 'as duas linhas são do mesmo parágrafo', todos os itens de lista sem marcador passaram de 0,75 e as listas colapsaram, resultando em 12 blocos. Com 'esta linha continua a frase', os mesmos itens ficaram entre 0,05 e 0,22 e a estrutura saiu certa, com 17 blocos.

Quanto custou o experimento?

10.211 tokens e 0,8 segundo em duas idas e voltas. Sobre o custo em dólar o cookbook se contradiz: o código imprime US$ 0,0003 e o texto afirma US$ 0,0015 em dois lugares. Citamos o valor que o código imprime.

Quer dominar decisões com IA em português? O curso da comunidade está em pré-venda.

Garantir pré-venda por R$ 499,00

Pré-venda: R$ 499,00 · Após o lançamento: R$ 799,00