Skip to content

Coluna da entrada com nome de campo ou de status levanta ValueError antes de qualquer chamada - #266

Open
bdcdo wants to merge 5 commits into
mainfrom
fix/coluna-do-usuario-protegida
Open

bdcdo wants to merge 5 commits into
mainfrom
fix/coluna-do-usuario-protegida

Conversation

@bdcdo

@bdcdo bdcdo commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Dois casos apagavam ou trocavam dados do usuário sem aviso. Medido na main em b48bd03, com a reprodução da issue e o provider simulado:

  • Coluna com o nome de um campo do modelo, sem coluna de status. Com resume=True, o padrão, e só parte das colunas do modelo presente, a resposta do LLM sobrescrevia a coluna: categoria = ["rotulo humano 1", "rotulo humano 2"] saía ["llm-a", "llm-b"], sem aviso, e o DataFrame de entrada mudava junto, porque a execução o altera in-place. Com todas as colunas do modelo presentes, a execução avisava e refazia todas as chamadas; com resume=False, avisava e devolvia a entrada.
  • status_column com o nome de outra coluna. status_column="categoria" tirava a coluna da saída, e a resposta paga se perdia. "texto" e "id" terminavam sem chamar o LLM, com a coluna de texto ou a id fora da saída e os campos None. "_error_details" e "_input_tokens" gravavam o status na mesma célula do detalhe de erro ou dos tokens de entrada.

O que muda

  • Sem a coluna de status, uma coluna da entrada com algum valor e com o nome de um campo do modelo levanta ValueError antes de qualquer chamada, com resume=True e com resume=False. A mensagem diz quais colunas seriam sobrescritas e oferece os caminhos: renomeá-las ou removê-las, ou passá-las em reprocess_columns para sobrescrevê-las de propósito, com a lista pronta, que soma as colunas já pedidas. Para a saída do dataframeit, que vem sem a coluna de status quando nenhuma linha falha, ela diz como devolver a coluna (df['_dataframeit_status'] = 'processed', ou o nome passado em status_column). Com a coluna de status presente, a execução retoma como antes.
  • status_column igual à coluna de texto, a um campo do modelo ou ao nome de outra coluna de controle do dataframeit (_error_details, tokens, _search_credits, trace) levanta ValueError. Uma coluna existente com o nome de status_column só é aceita quando traz apenas 'processed', 'error' ou vazio, que é o que a execução grava nela; com outro valor, a execução levanta, e a mensagem mostra o primeiro valor e a linha.
  • Sai o aviso de reexecução sobre a própria saída sem coluna de status, porque esse caso agora levanta.

A checagem das colunas do modelo fica depois da releitura do checkpoint e do retorno da entrada vazia, e antes de tocar no provider: o checkpoint desta execução traz a coluna de status, e a entrada vazia não tem linha a sobrescrever. A checagem de status_column fica com a validação das opções.

Decisões

  • A coluna que está em reprocess_columns não conta, porque sobrescrevê-la é o pedido. As demais colunas do modelo presentes contam: sem a coluna de status, toda linha é nova e recebe a resposta em todos os campos.
  • A coluna sem nenhum valor não conta, porque não tem o que perder. É o caso da coluna do modelo que a entrada polars traz toda nula para fixar o tipo.
  • Os nomes das colunas de controle ficam recusados mesmo com a opção que cria a coluna desligada (track_tokens=False, sem busca, sem trace), porque uma retomada com a opção ligada gravaria por cima do status, e track_tokens é ligado por padrão. As famílias vêm de _column_rank, em utils.py, que já ordena essas colunas na saída.
  • A checagem dos valores de status vale também para o nome padrão _dataframeit_status.

Testes alterados

Cinco testes afirmavam a sobrescrita, ou o aviso que a acompanhava, num caso que agora levanta ValueError:

  • tests/test_entrada_e_saida.py::test_reexecucao_sobre_a_propria_saida_avisa afirmava que reexecutar sobre a própria saída, sem a coluna de status, emitia o aviso de que todas as linhas seriam refeitas. Como test_reexecucao_sobre_a_propria_saida_levanta_e_diz_como_retomar, afirma o ValueError sem chamada ao LLM, com a mensagem que diz como devolver a coluna de status, com o nome padrão e com status_column.
  • tests/test_entrada_e_saida.py::test_reexecucao_avisa_mesmo_com_linha_toda_nula afirmava o mesmo aviso quando uma linha da saída é toda nula. Como test_reexecucao_levanta_mesmo_com_linha_toda_nula, afirma o ValueError no mesmo cenário.
  • tests/test_reprocess_columns.py::test_reprocess_columns_with_existing_columns_no_warning passava campo1 e campo2 com valor, sem a coluna de status e com reprocess_columns=["campo1"], e afirmava só a falta do aviso de conflito; a execução sobrescrevia também campo2, fora da lista. Agora a entrada traz a coluna de status, que é como se reprocessa uma saída, e o teste afirma, além da falta do aviso, que campo1 recebe a resposta e campo2 fica como estava.
  • tests/test_retomada_assinada.py::test_retomada_da_o_mesmo_resultado_que_a_execucao_sem_interrupcao rodava com reprocess_columns=None e com ["campo1", "campo2"] e afirmava, nos dois, que o "humano" da entrada perdia para a resposta paga. O caso None saiu: nele a primeira execução agora levanta, e a recusa com checkpoint_path, sem gravar o checkpoint, é coberta por test_coluna_com_nome_de_campo_e_checkpoint_levanta_sem_gravar. O teste segue com ["campo1", "campo2"], em que a sobrescrita é pedida.
  • tests/test_retomada_assinada.py::test_linha_com_erro_no_checkpoint_tambem_vem_dele rodava a primeira execução sobre campo1 = ["m1", "m2", "m3"] sem a coluna de status e afirmava que a linha com erro volta do checkpoint com "m2", e não com a correção à mão. A primeira execução agora passa reprocess_columns=["campo1"], que pede a sobrescrita, e a afirmação é a mesma.

tests/test_entrada_e_saida.py::test_entrada_polars_com_colunas_existentes_volta_igual ganha a coluna de status, que é o caso em que resume=False ainda avisa e devolve a entrada polars igual.

Itens da issue

  • Coluna com o nome de um campo do modelo: corrigido.
  • status_column com o nome de uma coluna existente, de campo, de texto ou do usuário: corrigido, e as colunas de controle entram na mesma recusa.

Closes #197

bdcdo and others added 5 commits October 21, 2026 22:07
…ntes do provider

Sem a coluna de status, a coluna da entrada com algum valor e com o nome
de um campo do modelo, fora de reprocess_columns, levanta ValueError com
resume=True e resume=False. status_column igual à coluna de texto, a um
campo, a outra coluna de controle ou a uma coluna com valores que não são
de status também levanta. O aviso de reexecução sobre a própria saída sai,
porque o caso agora levanta.
… mensagem indica reprocess_columns

A mensagem sugere reprocess_columns com as colunas que seriam
sobrescritas, somadas às já pedidas. A docstring de
_resume_from_checkpoint deixa de dizer que a execução sem interrupção
grava a resposta por cima da coluna da entrada.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coluna do usuário é sobrescrita ou apagada sem aviso

1 participant