Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
| Ambos lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
| pres:gerti:servico_de_desenvolvimento_de_sistemas_de_informacao:projetos:iago-dataflow [27/05/2025 14:44] – [Extração de Dados] mfaquino | pres:gerti:servico_de_desenvolvimento_de_sistemas_de_informacao:projetos:iago-dataflow [09/09/2025 22:51] (atual) – mfaquino | ||
|---|---|---|---|
| Linha 6: | Linha 6: | ||
| O primeiro passo da pipeline é monitorar quando um documento deve ser indexado, para isso, diáriamente a pipeline monitora as tabelas do Oracle (TCE_GO.**PRO_SUMARIO**, | O primeiro passo da pipeline é monitorar quando um documento deve ser indexado, para isso, diáriamente a pipeline monitora as tabelas do Oracle (TCE_GO.**PRO_SUMARIO**, | ||
| - | < | + | < |
| + | SELECT | ||
| PS.PROSUM_ID AS ID, | PS.PROSUM_ID AS ID, | ||
| PS.PROAUTU_ID AS PROAUTU_ID, | PS.PROAUTU_ID AS PROAUTU_ID, | ||
| Linha 25: | Linha 26: | ||
| AND CONTROL.DESC_STATUS = ' | AND CONTROL.DESC_STATUS = ' | ||
| WHERE CONTROL.ID_PROCEDIMENTO IS NULL | WHERE CONTROL.ID_PROCEDIMENTO IS NULL | ||
| - | ORDER BY PS.DATA_CRIACAO_D DESC; | + | ORDER BY PS.DATA_CRIACAO_D DESC |
| + | OFFSET 0 ROWS FETCH NEXT 10000 ROWS ONLY; | ||
| </ | </ | ||
| - | |||
| ==== Processamento de Dados ==== | ==== Processamento de Dados ==== | ||
| - | Uma vez identificado quais documentos devem ser indexados, os mesmo devem ser enviados para processamento, | + | Uma vez identificado quais documentos devem ser indexados, os mesmo devem ser enviados para processamento, |
| - Extração de Metadados | - Extração de Metadados | ||
| - Extração do Documento/ | - Extração do Documento/ | ||
| - Geração de Embeddings com o Texto do Documento | - Geração de Embeddings com o Texto do Documento | ||
| + | - Cálculo de Tokens do Documento | ||
| + | - Geração de Resumo do Documento | ||
| + | - Geração de Resumo do Processo | ||
| **Processamento de Metadados** | **Processamento de Metadados** | ||
| - | O processamento dos metadados é feito chamando a API do ETCE: [[https:// | + | O processamento dos metadados é feito chamando a API do ETCE: [[https:// |
| < | < | ||
| Linha 93: | Linha 97: | ||
| **Processamento de Texto e OCR** | **Processamento de Texto e OCR** | ||
| - | O processamento e extração do documento PDF do texto do documento é realizado pela API do ETCE: [[https:// | + | O processamento e extração do documento PDF do texto do documento é realizado pela API do ETCE: \\ \\ [[https:// |
| + | [[https:// | ||
| < | < | ||
| Linha 111: | Linha 116: | ||
| Com o documento PDF recuperado, o mesmo é submetido a OCR pela API do Docling: [[http:// | Com o documento PDF recuperado, o mesmo é submetido a OCR pela API do Docling: [[http:// | ||
| + | |||
| + | **OBS: Antes de indexar o texto no elasticsearch, | ||
| **Processamento de Embeddings** | **Processamento de Embeddings** | ||
| Com o texto extraido do OCR, os embeddings são gerados em chunks pelo mesmo modelo com finetunnig usado no legis **arturmatos/ | Com o texto extraido do OCR, os embeddings são gerados em chunks pelo mesmo modelo com finetunnig usado no legis **arturmatos/ | ||
| + | < | ||
| + | |||
| + | import torch | ||
| + | from transformers import AutoTokenizer, | ||
| + | |||
| + | # Detecta GPU, se disponível | ||
| + | device = torch.device(" | ||
| + | |||
| + | # Carrega modelo e tokenizer | ||
| + | model_name = " | ||
| + | tokenizer = AutoTokenizer.from_pretrained(model_name) | ||
| + | model = AutoModel.from_pretrained(model_name) | ||
| + | model.to(device) | ||
| + | model.eval() | ||
| + | |||
| + | def get_cuda_embedding(texto: | ||
| + | start = time.time() | ||
| + | # Tokenização + envio para GPU | ||
| + | inputs = tokenizer(texto, | ||
| + | |||
| + | with torch.no_grad(): | ||
| + | outputs = model(**inputs) | ||
| + | |||
| + | # Assume-se que os embeddings são extraídos da saída da última camada (hidden_states) | ||
| + | # Aqui usamos o embedding do CLS token (posição 0) | ||
| + | embeddings = outputs.last_hidden_state[:, | ||
| + | |||
| + | # Opcional: normaliza o vetor | ||
| + | embeddings = torch.nn.functional.normalize(embeddings, | ||
| + | |||
| + | # Move para CPU e converte para numpy array | ||
| + | return embeddings.squeeze().tolist() | ||
| + | |||
| + | </ | ||
| + | |||
| + | **Cálculo de Tokens** | ||
| + | |||
| + | Com o texto extraido do documento e OCR, é realizado o cálculo da quantidade de tokens presentes no texto usando o script a seguir e salvos no campo do elasticsearch **metainfo.tokens**: | ||
| + | |||
| + | < | ||
| + | class DocUtils: | ||
| + | |||
| + | @staticmethod | ||
| + | def count_tokens(text: | ||
| + | try: | ||
| + | codificador = tiktoken.encoding_for_model(model) | ||
| + | except KeyError: | ||
| + | codificador = tiktoken.get_encoding(" | ||
| + | tokens = codificador.encode(text) | ||
| + | return len(tokens) | ||
| + | |||
| + | </ | ||
| + | |||
| + | **Geração de Resumo do Documento** | ||
| + | |||
| + | Com o texto extraido do documento e OCR, é realizado a geração de um resumo do documento e salvo no campo do elasticsearch **summary, **o resumo é feito utilizando uma LLM \\ \\ - GPT-4.1-mini atráves do serviço da [[: | ||
| + | - llama3.3 atráves do [[https:// | ||
| + | |||
| + | O seguinte prompt é utilizado para gerar o resumo: | ||
| + | < | ||
| + | |||
| + | Você é um assistente especializado em análise documental no contexto de Tribunais de Contas. A seguir, será apresentado o conteúdo de um documento integrante de um processo. | ||
| + | |||
| + | Sua tarefa é gerar um resumo claro, conciso e informativo, | ||
| + | |||
| + | Identifique o documento e tipo | ||
| + | |||
| + | Destaque o assunto principal ou objeto da análise | ||
| + | |||
| + | Informe, se houver, qualquer conclusão, recomendação ou decisão relevante constante no documento | ||
| + | |||
| + | Use linguagem objetiva e formal. Não copie trechos literais — reescreva com clareza e concisão. | ||
| + | |||
| + | Importante: Retorne apenas o texto do resumo. Não inclua nenhuma frase introdutória, | ||
| + | |||
| + | {document} | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== ==== | ||
| + | |||
| + | **Geração de Resumo do Processo** | ||
| + | |||
| + | Após realizado o resumo dos documentos de um processo, é realizado a geração do resumo do processo usando os resumos de documentos, o resultado é salvo em cada registro de documento no campo do elasticsearch **process_summary, | ||
| + | - llama3.3 atráves do [[https:// | ||
| + | < | ||
| + | |||
| + | O seguinte prompt é utilizado para gerar o resumo: | ||
| + | |||
| + | Você é um assistente especializado em síntese de processos administrativos e de controle externo no contexto de Tribunais de Contas. | ||
| + | |||
| + | A seguir, serão apresentados resumos de documentos que compõem um único processo. Cada resumo já contém informações estruturadas sobre tipo de documento, assunto e conclusões. | ||
| + | |||
| + | Sua tarefa é gerar um resumo geral e coeso do processo, com no máximo 6 frases, que: | ||
| + | |||
| + | Apresente o objetivo central do processo | ||
| + | |||
| + | Destaque os principais temas tratados ao longo dos documentos | ||
| + | |||
| + | Aponte as partes envolvidas, valores ou objetos auditados, se disponíveis | ||
| + | |||
| + | Mencione conclusões, | ||
| + | |||
| + | Regras obrigatórias: | ||
| + | |||
| + | O texto gerado deve ser direto e coeso, com linguagem técnica, formal e objetiva | ||
| + | |||
| + | Retorne apenas o texto do resumo. Não inclua frases introdutórias como " | ||
| + | |||
| + | Não repita literalmente os resumos individuais dos documentos. Faça uma síntese integrada e fluida | ||
| + | |||
| + | {documents} | ||
| + | |||
| + | </ | ||
| ==== Carga de Dados ==== | ==== Carga de Dados ==== | ||
| Linha 120: | Linha 241: | ||
| Ao final o resultado do processamento é carregado no elasticsearch, | Ao final o resultado do processamento é carregado no elasticsearch, | ||
| - | {{https:// | + | {{https:// |
| ==== Pipeline no Airflow ==== | ==== Pipeline no Airflow ==== | ||
| - | Essa pipeline é orquestrada e executada periodicamente pelo Airflow, o link de acesso é: [[https:// | + | Essa pipeline é orquestrada e executada periodicamente pelo Airflow, o link de acesso é: |
| + | |||
| + | Pipeline de Dados: [[https:// | ||
| + | Pipeline de Resumos: [[https:// | ||
| + | |||
| + | {{https:// | ||
| + | |||
| + | ==== Processos Sigilosos ==== | ||
| + | |||
| + | Diariamente é executado a pipeline de verificação de documentos sigilosos: [[https:// | ||
| + | A verificação é realizada executando a seguinte query no Oracle, que retorna todos os processos que atualmente são sigilosos: | ||
| + | < | ||
| + | |||
| + | SELECT | ||
| + | | ||
| + | | ||
| + | FROM TCE_GO.PRO_AUTUACAO | ||
| + | WHERE INDR_BLOQUEIODOC_A IS NOT NULL | ||
| + | ORDER BY PROAUTU_ID DESC | ||
| + | |||
| + | </ | ||
| + | |||
| + | Caso seja encontrado algum desses processos no elasticsearch, | ||
| - | {{https:// | + | Os logs dos processos removidos são registrados no próprio Airflow, sendo possível acompanhar periodicamente os documentos processados pelos administradores da ferramenta, ou usuários apenas leitores: \\ A seguir um exemplo de log de um processo que foi removido por se tornar sigiloso: **202500047003283** |
| + | {{https:// | ||
| ==== Tabela de Controle ==== | ==== Tabela de Controle ==== | ||