Esta solução implementa uma arquitetura híbrida, de refinamento iterativo, projetada para balancear as quatro restrições conflitantes do desafio: Tempo (< 10s), Acurácia (> 80%), Custo (mínimo) e Adaptabilidade (acúmulo de conhecimento).
Testes iniciais (logs V16-V20) provaram que nenhuma abordagem simples atende a todas as restrições:
- O Problema do Tempo: Uma chamada síncrona direta ao
gpt-5-minié a única abordagem 100% precisa, mas nossos logs provaram que ela é muito volátil e estoura o limite de 10s (ex: 12.99s, 10.98s nos logs de teste). - O Problema da Acurácia: Uma heurística local (ex:
HeuristicExtractorV18.3) é extremamente rápida (< 0.1s), mas sua acurácia é muito baixa, pois falha em layouts posicionais ou retorna dados incorretos ("envenenados"). - O Problema do "Conhecimento": O
gpt-5-minié um extrator de dados excelente, mas um péssimo gerador de Regex e Regras. Nossos logs de09:37:22provaram que oParserGenerator(baseado em LLM) gerou Regex inválidas (ex:Padrão não possui grupo de captura ()) e que regras de validação fracas levaram aConfiança Alta (1.00)para dados 57% errados.
Para resolver esse "beco sem saída", a solução implementa uma arquitetura de "acúmulo de conhecimento" que usa o gpt-5-mini síncrono (para acurácia) apenas quando necessário, protegido por um "watchdog" de tempo cumulativo.
A lógica de orquestração (main.py) gerencia quatro caminhos distintos:
Quando um label é visto pela primeira vez, o foco é o Tempo e o Acúmulo de Conhecimento.
- Tarefa Síncrona (Heurística): O
HeuristicExtractor(V18.3) é executado. Ele é rápido (< 0.1s), mas "ingênuo" (retorna muitosnulls). - Validação Síncrona: O
main.pyvalida a taxa de falha (ex:failure_rate < HEURISTIC_FAILURE_THRESHOLD). - Decisão Síncrona (Watchdog):
- Se a heurística for boa: Retorna os dados (Tempo < 0.1s).
- Se a heurística for ruim: (ex: falha de 86%) O sistema aciona o
FallbackExtractor.extract_all(LLM de alta acurácia) em uma thread (_run_llm_in_thread), protegido por um watchdog de tempo cumulativo.
- Tarefa Assíncrona (Acúmulo de Conhecimento):
- Paralelamente, uma thread (
_run_parser_generation_task) é disparada para construir o "conhecimento" V1. - Chamada 1 (LLM):
FallbackExtractor.extract_allobtém o "gabarito" (dados perfeitos). - Chamada 2 (LLM):
ParserGeneratorV22.0 usa o gabarito para gerar Regex (corrigindo o bug do grupo de captura). - Chamada 3 (Local):
ValidationGeneratorV22.1 faz engenharia reversa do gabarito para gerar regras de validação fortes (corrigindo o bug deTypeErrore o bug deenum). - O pacote (
parser,validation_rules) é salvo noParserRepository.
- Paralelamente, uma thread (
Quando um label já conhecido é visto:
- O
ParserExecutor(local, < 0.1s) executa as Regex geradas. - O
ConfidenceCalculator(local) usa as Regras V22.1 (fortes) para validar os dados. - Se
confiança > 0.8, os dados são retornados. - Resultado: Custo $0, Tempo < 0.1s. (A acurácia depende do parser gerado pelo LLM).
Este é o núcleo da "criatividade" do projeto. O sistema aprende com seus próprios erros.
- O
ParserExecutorfalha (as Regex do LLM eram ruins). - O
ConfidenceCalculator(com as regras V22.1 fortes) detecta a falha (ex:Score: 0.62). - Tarefa Síncrona (Watchdog): O
FallbackExtractor.extract_missingé chamado para corrigir os campos faltantes, protegido pelo watchdog de tempo cumulativo. - Tarefa Assíncrona (Refinamento): O sistema dispara uma nova thread (
_run_parser_REFINEMENT_task) que usa esses dados corrigidos como um novo gabarito para gerar um pacote V2 (melhorado) deparserevalidation_rules, substituindo o conhecimento antigo.
A falha do Item 4 (12.99s) provou que o LLM pode estourar 10s. Nossa solução (main.py) usa um "orçamento de tempo" de lote.
- Limite do Lote: (Nº de Itens * 10s).
- Orçamento do Item: (Limite do Lote - Tempo Acumulado Gasto).
- Resultado: Itens rápidos (0.1s) "economizam" tempo, permitindo que os itens que precisam do LLM usem (ex:) 13.09s (como o Item 6), mantendo a média total do lote (40.41s / 6 = 6.73s) bem abaixo do limite.
- Clone o repositório.
- Instale as dependências:
pip install -r requirements.txt - Crie um arquivo
.envna raiz e adicione sua API key:OPENAI_API_KEY=sk-.... - (Opcional) Limpe o cache de conhecimento:
rm -rf parser_repository_cache/ - Adicione os PDFs de teste a uma pasta
/files(omain.pya utiliza). - Configure o
dataset.jsonpara apontar para os arquivos PDF. - Execute o processamento em lote:
python3 main.py
Como um diferencial, uma interface de usuário funcional foi prototipada utilizando a plataforma low-code lovable.dev.
Nota Importante: Devido à complexidade da arquitetura de processamento em lote (V22.1) e ao curto prazo de entrega, a UI ainda não foi integrada ao backend principal.
O código exportado do protótipo da UI está incluído na pasta /ui-prototype para demonstrar a intenção e a funcionalidade visual.