Files
Botexercito/Scripts/Classificador.ipynb
2026-03-22 18:07:19 +00:00

3741 lines
150 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "b33fe260",
"metadata": {},
"source": [
"<div align=\"center\">\n",
"\n",
"<span style=\"color:red\"><b>RESERVADO</b></span> \n",
"\n",
"<img src=\"Imagens/logo_presidencia_republica.jpg\" width=\"100\"/>\n",
"\n",
"**MINISTÉRIO DA DEFESA NACIONAL** \n",
"**EXÉRCITO PORTUGUÊS** \n",
"**DIREÇÃO DE COMUNICAÇÕES E INFORMAÇÃO** \n",
"**CENTRO DE DESENVOLVIMENTO APLICACIONAL E BI** \n",
"**PROJECTO LLM**\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"id": "749dc804",
"metadata": {},
"source": [
"# LLM Exercito\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "23364f12",
"metadata": {},
"outputs": [],
"source": [
"#!pip install pdfplumber pandas\n",
"#!pip install sentence-transformers faiss-cpu pandas numpy\n",
"#!pip install ocrmypdf"
]
},
{
"cell_type": "markdown",
"id": "505f7488",
"metadata": {},
"source": [
"## Bibliotecas Importadas"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "737d8189",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\garci\\AppData\\Local\\Python\\pythoncore-3.14-64\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
],
"source": [
"import os\n",
"import pdfplumber\n",
"import pandas as pd\n",
"import re\n",
"import unicodedata\n",
"import numpy as np\n",
"import shutil\n",
"from pathlib import Path\n",
"from collections import Counter\n",
"from tqdm import tqdm\n",
"from sentence_transformers import SentenceTransformer\n",
"import faiss\n",
"from IPython.display import display, Markdown"
]
},
{
"cell_type": "markdown",
"id": "f4dd76a3",
"metadata": {},
"source": [
"Pasta dos PDF sacados da intranet do exército\n",
"\n",
"Nesta fase e sem um repositório de documentos disponivel, utilizei um script denominado de [Sacarpdf.py](/Scripts/Sacarpdf.py) para savar todos os pdfs disponiveis na página do exército dentro deste diretório.\n",
"\n",
"*r\"\\\\intranet.exercito.local\\areas-sectoriais\"*\n",
"\n",
"Deu um conjunto de 11618 documentos.\n",
"\n",
"Aqui propunha tambem tirar-mos todos os documentos existentes no GESDOC para engrossar o nosso dataset, e melhorar a LLM naturalmente."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "611fc7a3",
"metadata": {},
"outputs": [],
"source": [
"pasta_pdfs = r\"D:\\Trabalhos\\Bot Exército\\pdfs\""
]
},
{
"cell_type": "markdown",
"id": "7fca8b1b",
"metadata": {},
"source": [
"## Funções"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "9a9e499d",
"metadata": {},
"outputs": [],
"source": [
"def normalizar_texto(txt):\n",
" if not isinstance(txt, str):\n",
" return \"\"\n",
" txt = txt.lower()\n",
" txt = ''.join(\n",
" c for c in unicodedata.normalize('NFD', txt)\n",
" if unicodedata.category(c) != 'Mn')\n",
" txt = re.sub(r\"[_\\-.\\\\/]+\", \" \", txt)\n",
" txt = re.sub(r\"\\s+\", \" \", txt).strip()\n",
" return txt"
]
},
{
"cell_type": "markdown",
"id": "e0fc74ed",
"metadata": {},
"source": [
"<a id=\"secao0\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "e8d06a54",
"metadata": {},
"outputs": [],
"source": [
"def classificar_documento(nome):\n",
" if not isinstance(nome, str):\n",
" return \"Desconhecido\"\n",
" categorias = {\n",
" \"NEP\": [\"nep\",\"normas de execucao permanente\",\"norma de execucao permanente\"],\n",
" \"LISTA\": [\"lista\",\"Lista de Verificacao\",\"Lista de Verificação\",\"LV\"],\n",
" \"Diretiva\": [\"diretiva\",\"dee\"],\n",
" \"Regulamentos e Leis\": [\"regulamento\",\"lei\",\"regulation\"],\n",
" \"Guia\": [\"guia\"],\n",
" \"manual\": [\"manual\",\"man\"],\n",
" \"Norma\": [\"norma\", \"normas\"],\n",
" \"NOTA\": [\"nota\"],\n",
" \"Folheto\": [\"folheto\",\"folhetos\",\"panfleto\",\"panfletos\"],\n",
" \"Referencial\": [\"referencial\", \"UC\"],\n",
" \"Publicação\": [\"pde\",\"publicacao doutrinaria do exercito\",\"pte\",\"pad\"],\n",
" \"Informçaões\": [ \"Informações propostas\",],\n",
" \"Plano\": [\"plano\",\"pme\",\"pa\"]\n",
" }\n",
" nome_normalizado = normalizar_texto(nome)\n",
" encontrados = []\n",
" for categoria, palavras in categorias.items():\n",
" for palavra in palavras:\n",
" palavra_norm = normalizar_texto(palavra)\n",
" padrao = r\"\\b\" + re.escape(palavra_norm) + r\"(\\d+)?\\b\"\n",
"\n",
" match = re.search(padrao, nome_normalizado)\n",
" if match:\n",
" encontrados.append((match.start(), categoria, palavra_norm))\n",
" if encontrados:\n",
" encontrados.sort(key=lambda x: x[0])\n",
" return encontrados[0][1]\n",
" return \"Outros\""
]
},
{
"cell_type": "markdown",
"id": "88a2be27",
"metadata": {},
"source": [
"As funções seguintes são as normais para um documento, contudo eu acho que faz sentido melhorarmos aqui o refinamento da remoção de algumas palavras e ou expressões/ paragrafos tipicos. Por exemplo temos documentos que normalmente são estruturados como se de uma Ordem de operações se tratasse com 1. Missão, 2.Situação etc... este tipo de formatação pdoerá ser eliminado para melhorar o chunck, outra coisa que pode ser feito é retirar assinaturas e nomes especificos (por exemplo as assinaturas dos documentos), assim como os destinatários das notas e remetentes por exemplo, este tipo de informação.\n",
"\n",
"- [Remover quebras excessivas e múltiplos espaços](#secao1)\n",
"- [Remover padrões tipo \"Página X de Y\"](#secao2)\n",
"- [Remover números de página isolados](#secao3)\n",
"- [Juntar linhas partidas](#secao4)\n",
"- [Remover headers e rodapés](#secao5)\n",
"- [Variável texto final](#secao6)\n",
"\n",
"<a id=\"secao1\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "2e7d3d54",
"metadata": {},
"outputs": [],
"source": [
"def normalizar_linha(linha):\n",
" if not linha:\n",
" return \"\"\n",
" linha = linha.strip().lower()\n",
" linha = re.sub(r\"\\s+\", \" \", linha)\n",
" linha = re.sub(r\"\\b\\d+\\b\", \"#\", linha)\n",
" return linha\n"
]
},
{
"cell_type": "markdown",
"id": "f009fa1a",
"metadata": {},
"source": [
"<a id=\"secao2\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "867e0baf",
"metadata": {},
"outputs": [],
"source": [
"def extrair_linhas_por_pagina(caminho_pdf):\n",
" paginas = []\n",
" with pdfplumber.open(caminho_pdf) as pdf:\n",
" for pagina in pdf.pages:\n",
" texto = pagina.extract_text() or \"\"\n",
" linhas = [l.strip() for l in texto.split(\"\\n\") if l.strip()]\n",
" paginas.append(linhas)\n",
" return paginas"
]
},
{
"cell_type": "markdown",
"id": "d956a898",
"metadata": {},
"source": [
"<a id=\"secao4\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "ad9c7e16",
"metadata": {},
"outputs": [],
"source": [
"def limpar_linhas_repetidas_pagina(linhas, headers, footers, top_n=5, bottom_n=5):\n",
" if not linhas:\n",
" return []\n",
" resultado = []\n",
" total = len(linhas)\n",
" for i, linha in enumerate(linhas):\n",
" linha_norm = normalizar_linha(linha)\n",
" if i < top_n and linha_norm in headers:\n",
" continue\n",
" if i >= max(0, total - bottom_n) and linha_norm in footers:\n",
" continue\n",
" resultado.append(linha)\n",
" return resultado"
]
},
{
"cell_type": "markdown",
"id": "03cde968",
"metadata": {},
"source": [
"<a id=\"secao5\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "202cdc98",
"metadata": {},
"outputs": [],
"source": [
"def detetar_headers_footers(paginas_linhas, top_n=3, bottom_n=3, min_ratio=0.6):\n",
" n_paginas = len(paginas_linhas)\n",
" if n_paginas == 0:\n",
" return set(), set()\n",
" min_count = max(2, int(n_paginas * min_ratio))\n",
" contador_topo = Counter()\n",
" contador_fundo = Counter()\n",
" for linhas in paginas_linhas:\n",
" topo = linhas[:top_n]\n",
" fundo = linhas[-bottom_n:] if len(linhas) >= bottom_n else linhas\n",
" topo_norm = set(normalizar_linha(l) for l in topo if normalizar_linha(l))\n",
" fundo_norm = set(normalizar_linha(l) for l in fundo if normalizar_linha(l))\n",
" contador_topo.update(topo_norm)\n",
" contador_fundo.update(fundo_norm)\n",
" headers = {linha for linha, c in contador_topo.items() if c >= min_count}\n",
" footers = {linha for linha, c in contador_fundo.items() if c >= min_count}\n",
" return headers, footers"
]
},
{
"cell_type": "markdown",
"id": "eeafe276",
"metadata": {},
"source": [
"<a id=\"secao6\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "def8fb0f",
"metadata": {},
"outputs": [],
"source": [
"def limpar_texto_final(texto):\n",
" if not texto:\n",
" return \"\"\n",
" texto = re.sub(r\"p[aá]gina\\s+\\d+\\s+de\\s+\\d+\", \"\", texto, flags=re.IGNORECASE)\n",
" texto = re.sub(r\"(?m)^\\s*\\d+\\s*$\", \"\", texto)\n",
" texto = re.sub(r\"(?<!\\n)\\n(?!\\n)\", \" \", texto)\n",
" texto = re.sub(r\"[ \\t]+\", \" \", texto)\n",
" texto = re.sub(r\"\\n{3,}\", \"\\n\\n\", texto)\n",
" \n",
" return texto.strip()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "78fd0491",
"metadata": {},
"outputs": [],
"source": [
"def extrair_texto_sem_headers_footers(caminho_pdf, top_n=3, bottom_n=3, min_ratio=0.6):\n",
" paginas_linhas = extrair_linhas_por_pagina(caminho_pdf)\n",
" headers, footers = detetar_headers_footers(\n",
" paginas_linhas,\n",
" top_n=top_n,\n",
" bottom_n=bottom_n,\n",
" min_ratio=min_ratio\n",
" )\n",
" paginas_limpas = []\n",
" for linhas in paginas_linhas:\n",
" limpas = limpar_linhas_repetidas_pagina(\n",
" linhas,\n",
" headers=headers,\n",
" footers=footers,\n",
" top_n=max(top_n, 5),\n",
" bottom_n=max(bottom_n, 5)\n",
" )\n",
" paginas_limpas.append(\"\\n\".join(limpas))\n",
" texto_final = \"\\n\\n\".join(paginas_limpas)\n",
" texto_final = limpar_texto_final(texto_final)\n",
" return texto_final, headers, footers"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "8416ea37",
"metadata": {},
"outputs": [],
"source": [
"def processar_pasta_pdfs(pasta_base):\n",
" \n",
" resultados = []\n",
" \n",
" todos_pdfs = []\n",
" \n",
" for raiz, _, ficheiros in os.walk(pasta_base):\n",
" for ficheiro in ficheiros:\n",
" if ficheiro.lower().endswith(\".pdf\"):\n",
" todos_pdfs.append(os.path.join(raiz, ficheiro))\n",
" \n",
" for caminho_pdf in tqdm(todos_pdfs):\n",
" \n",
" ficheiro = os.path.basename(caminho_pdf)\n",
" \n",
" try:\n",
" texto_limpo, headers, footers = extrair_texto_sem_headers_footers(caminho_pdf)\n",
" \n",
" resultados.append({\n",
" \"nome_pdf\": ficheiro,\n",
" \"caminho\": caminho_pdf,\n",
" \"texto_limpo\": texto_limpo,\n",
" \"headers_detetados\": list(headers),\n",
" \"footers_detetados\": list(footers)\n",
" })\n",
" \n",
" except Exception as e:\n",
" resultados.append({\n",
" \"nome_pdf\": ficheiro,\n",
" \"caminho\": caminho_pdf,\n",
" \"texto_limpo\": \"\",\n",
" \"headers_detetados\": [],\n",
" \"footers_detetados\": [],\n",
" \"erro\": str(e)\n",
" })\n",
" \n",
" return pd.DataFrame(resultados)"
]
},
{
"cell_type": "markdown",
"id": "119de030",
"metadata": {},
"source": [
"Funções especificas para a parte do chunking e do FAISS\n",
"\n",
"- [Chunking por parágrafos com overlap](#secao7)\n",
"- [Embeddings com sentence-transformers](#secao8)\n",
"- [FAISS para indexação local](#secao9)\n",
"<a id=\"secao7\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "dd27162b",
"metadata": {},
"outputs": [],
"source": [
"def limpar_paragrafos_vazios(paragrafos):\n",
" return [p.strip() for p in paragrafos if isinstance(p, str) and p.strip()]"
]
},
{
"cell_type": "markdown",
"id": "7a2b8916",
"metadata": {},
"source": [
"<a id=\"secao8\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "50bba284",
"metadata": {},
"outputs": [],
"source": [
"def dividir_em_paragrafos(texto):\n",
" if not isinstance(texto, str) or not texto.strip():\n",
" return []\n",
" paragrafos = re.split(r\"\\n\\s*\\n\", texto)\n",
" paragrafos = limpar_paragrafos_vazios(paragrafos)\n",
" return paragrafos\n"
]
},
{
"cell_type": "markdown",
"id": "82bbe430",
"metadata": {},
"source": [
"<a id=\"secao9\"></a>"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "091c9994",
"metadata": {},
"outputs": [],
"source": [
"def chunk_texto_inteligente(texto, chunk_size=1200, overlap=200, min_chunk_size=200):\n",
" if not isinstance(texto, str) or not texto.strip():\n",
" return [] \n",
" paragrafos = dividir_em_paragrafos(texto) \n",
" if not paragrafos:\n",
" return [] \n",
" chunks = []\n",
" chunk_atual = \"\" \n",
" for paragrafo in paragrafos:\n",
" paragrafo = paragrafo.strip()\n",
" if not paragrafo:\n",
" continue\n",
" if len(paragrafo) > chunk_size:\n",
" if chunk_atual.strip():\n",
" chunks.append(chunk_atual.strip())\n",
" chunk_atual = \"\" \n",
" inicio = 0\n",
" while inicio < len(paragrafo):\n",
" fim = inicio + chunk_size\n",
" subchunk = paragrafo[inicio:fim].strip()\n",
" if subchunk:\n",
" chunks.append(subchunk)\n",
" inicio += max(1, chunk_size - overlap)\n",
" continue \n",
" candidato = f\"{chunk_atual}\\n\\n{paragrafo}\".strip() if chunk_atual else paragrafo \n",
" if len(candidato) <= chunk_size:\n",
" chunk_atual = candidato\n",
" else:\n",
" if len(chunk_atual.strip()) >= min_chunk_size:\n",
" chunks.append(chunk_atual.strip())\n",
" if overlap > 0:\n",
" tail = chunk_atual.strip()[-overlap:]\n",
" chunk_atual = f\"{tail}\\n\\n{paragrafo}\".strip()\n",
" else:\n",
" chunk_atual = paragrafo\n",
" else:\n",
" chunk_atual = candidato\n",
" if chunk_atual.strip():\n",
" chunks.append(chunk_atual.strip())\n",
" return chunks"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "68060521",
"metadata": {},
"outputs": [],
"source": [
"def pesquisar_chunks(query, modelo_embeddings, index, dataset_chunks, top_k=5):\n",
" query_embedding = modelo_embeddings.encode([query], convert_to_numpy=True)\n",
" query_embedding = np.array(query_embedding, dtype=\"float32\")\n",
" \n",
" distancias, indices = index.search(query_embedding, top_k)\n",
" \n",
" resultados = dataset_chunks.iloc[indices[0]].copy()\n",
" resultados[\"score_distancia\"] = distancias[0]\n",
" \n",
" return resultados"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "eb6c2f90",
"metadata": {},
"outputs": [],
"source": [
"def criar_dataset_chunks(dataset):\n",
" registos = []\n",
" \n",
" for _, row in dataset.iterrows():\n",
" nome_pdf = row.get(\"nome_pdf\", \"\")\n",
" caminho = row.get(\"caminho\", \"\")\n",
" categoria = row.get(\"categoria\", \"Outros\")\n",
" chunks = row.get(\"chunks\", [])\n",
" \n",
" for i, chunk in enumerate(chunks):\n",
" registos.append({\n",
" \"nome_pdf\": nome_pdf,\n",
" \"caminho\": caminho,\n",
" \"categoria\": categoria,\n",
" \"chunk_id\": i,\n",
" \"texto_chunk\": chunk\n",
" })\n",
" \n",
" return pd.DataFrame(registos)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "b6919063",
"metadata": {},
"outputs": [],
"source": [
"def garantir_nome_unico(destino):\n",
" base, ext = os.path.splitext(destino)\n",
" contador = 1\n",
" \n",
" while os.path.exists(destino):\n",
" destino = f\"{base}_{contador}{ext}\"\n",
" contador += 1\n",
" \n",
" return destino"
]
},
{
"cell_type": "markdown",
"id": "a60d01ac",
"metadata": {},
"source": [
"RAG"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "f625f95f",
"metadata": {},
"outputs": [],
"source": [
"def construir_contexto_rag(query, resultados):\n",
" contexto = \"\\n\\n---\\n\\n\".join(\n",
" [\n",
" f\"[Documento: {row['nome_pdf']} | Categoria: {row['categoria']}]\\n{row['texto_chunk']}\"\n",
" for _, row in resultados.iterrows()\n",
" ]\n",
" )\n",
" \n",
" prompt = f\"\"\"\n",
"Responde à pergunta do utilizador com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"{query}\n",
"\n",
"Contexto:\n",
"{contexto}\n",
"\n",
"Instruções:\n",
"- Se a resposta não estiver claramente no contexto, diz que não encontraste informação suficiente.\n",
"- Resume de forma objetiva.\n",
"- Cita o nome do documento quando relevante.\n",
"\"\"\"\n",
" return prompt"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "8163c6f6",
"metadata": {},
"outputs": [],
"source": [
"def preparar_rag(query, modelo_embeddings, index, dataset_chunks, top_k=5):\n",
" resultados = pesquisar_chunks(\n",
" query=query,\n",
" modelo_embeddings=modelo_embeddings,\n",
" index=index,\n",
" dataset_chunks=dataset_chunks,\n",
" top_k=top_k\n",
" )\n",
" prompt = construir_contexto_rag(query, resultados)\n",
" return prompt, resultados"
]
},
{
"cell_type": "markdown",
"id": "348ffebd",
"metadata": {},
"source": [
"Função para teste de perguntas ao modelo"
]
},
{
"cell_type": "code",
"execution_count": 64,
"id": "b5019060",
"metadata": {},
"outputs": [],
"source": [
"def testar_perguntas(perguntas, modelo_embeddings, index, dataset_chunks, top_k=5):\n",
" \n",
" for pergunta in perguntas:\n",
" print(\"\\n\" + \"=\"*100)\n",
" print(\"🔎 PERGUNTA:\", pergunta)\n",
" print(\"=\"*100)\n",
" \n",
" resultados = pesquisar_chunks(\n",
" query=pergunta,\n",
" modelo_embeddings=modelo_embeddings,\n",
" index=index,\n",
" dataset_chunks=dataset_chunks,\n",
" top_k=top_k\n",
" )\n",
" \n",
" for i, row in resultados.iterrows():\n",
" print(f\"\\nResultado {i+1}\")\n",
" print(\"Documento:\", row[\"nome_pdf\"])\n",
" print(\"Categoria:\", row[\"categoria\"])\n",
" print(\"Score:\", row[\"score_distancia\"])\n",
" print(\"Texto:\")\n",
" print(row[\"texto_chunk\"][:400])\n",
" print(\"-\"*80)"
]
},
{
"cell_type": "markdown",
"id": "87006e08",
"metadata": {},
"source": [
"## Pré processamento do Corpus"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "05f406c4",
"metadata": {},
"outputs": [],
"source": [
"dados = []\n",
"for raiz, subpastas, ficheiros in os.walk(pasta_pdfs):\n",
" for ficheiro in ficheiros:\n",
" if ficheiro.lower().endswith(\".pdf\"): \n",
" caminho_pdf = os.path.join(raiz, ficheiro) \n",
" texto = \"\" \n",
" try:\n",
" with pdfplumber.open(caminho_pdf) as pdf:\n",
" for pagina in pdf.pages:\n",
" texto += pagina.extract_text() or \"\"\n",
" except:\n",
" texto = \"ERRO OCR??\" \n",
" dados.append({\n",
" \"nome_pdf\": ficheiro,\n",
" \"caminho\": caminho_pdf,\n",
" \"texto\": texto\n",
" })\n",
"dataset = pd.DataFrame(dados)\n",
"print(\"PDFs encontrados:\", len(dataset))\n",
"dataset.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "519ee39e",
"metadata": {},
"outputs": [],
"source": [
"dataset[\"categoria\"] = dataset[\"nome_pdf\"].apply(classificar_documento)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d0db03dd",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto</th>\n",
" <th>categoria</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR...</td>\n",
" <td>Guia</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR...</td>\n",
" <td>Guia</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU...</td>\n",
" <td>LISTA</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA...</td>\n",
" <td>LISTA</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Diretiva Ambiental do Exercito 2025-2027.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>Diretiva</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11613</th>\n",
" <td>Folheto_a verdade sobre o Crack.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>Folheto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11614</th>\n",
" <td>Folheto_a verdade sobre o ecstasy.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>Folheto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11615</th>\n",
" <td>Panfletos PIEDs.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td>MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ...</td>\n",
" <td>Folheto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11616</th>\n",
" <td>MAN 2016RHV03 - Processo Individual v1.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R...</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" <td>manual</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11617</th>\n",
" <td>MAN 2016RHV07 - Assiduidades v1.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R...</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" <td>manual</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>11618 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf \n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf \n",
"3 LISTA ADIDOS NACIONAIS.pdf \n",
"4 Diretiva Ambiental do Exercito 2025-2027.pdf \n",
"... ... \n",
"11613 Folheto_a verdade sobre o Crack.pdf \n",
"11614 Folheto_a verdade sobre o ecstasy.pdf \n",
"11615 Panfletos PIEDs.pdf \n",
"11616 MAN 2016RHV03 - Processo Individual v1.pdf \n",
"11617 MAN 2016RHV07 - Assiduidades v1.pdf \n",
"\n",
" caminho \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"... ... \n",
"11613 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11614 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11615 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11616 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R... \n",
"11617 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R... \n",
"\n",
" texto categoria \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR... Guia \n",
"1 NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR... Guia \n",
"2 LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU... LISTA \n",
"3 LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA... LISTA \n",
"4 Diretiva \n",
"... ... ... \n",
"11613 Folheto \n",
"11614 Folheto \n",
"11615 MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ... Folheto \n",
"11616 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... manual \n",
"11617 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... manual \n",
"\n",
"[11618 rows x 4 columns]"
]
},
"execution_count": 119,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset"
]
},
{
"cell_type": "markdown",
"id": "51c62227",
"metadata": {},
"source": [
"Gravei em [.csv](/pdfs/indexpdfs.csv) e [.json](/pdfs/indexpdfs.json) o dataset puro com o nome do indexpdfs e o que é para a construção da LLM gravei apenas como json em [dataset_llm](/pdfs/dataset_llm.json)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3bcc4a73",
"metadata": {},
"outputs": [],
"source": [
"dataset.to_csv(r\"D:\\Trabalhos\\Bot Exército\\pdfs\\indexpdfs.csv\", index=False)\n",
"dataset.to_json(r\"D:\\Trabalhos\\Bot Exército\\pdfs\\indexpdfs.json\", orient=\"records\", indent=2)\n",
"dataset[[\"nome_pdf\", \"categoria\", \"texto\"]].to_json(\n",
" \"dataset_llm.json\",\n",
" orient=\"records\",\n",
" force_ascii=False,\n",
" indent=2\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4ae3b00b",
"metadata": {},
"outputs": [],
"source": [
"dataset = pd.read_json(r\"D:\\Trabalhos\\Bot Exército\\pdfs\\dataset_llm.json\")"
]
},
{
"cell_type": "markdown",
"id": "3673b7aa",
"metadata": {},
"source": [
"Aqui para o refinamento dos metadados do nosso vetor seria interessante melhorar aqui os termos pada procura das funções de REGEX [aplicadas](#secao0), o dataset está muito desbalanceado, de qualquer forma isto serve apenas para fine tuning do modelo."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4810f6b1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"categoria\n",
"Outros 10829\n",
"NOTA 605\n",
"manual 50\n",
"NEP 27\n",
"Guia 25\n",
"LISTA 24\n",
"Plano 23\n",
"Diretiva 20\n",
"Folheto 13\n",
"Referencial 2\n",
"Name: count, dtype: int64"
]
},
"execution_count": 134,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[\"categoria\"].value_counts()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f1ed33c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>categoria</th>\n",
" <th>texto</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>Guia</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>Guia</td>\n",
" <td>NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>LISTA</td>\n",
" <td>LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>LISTA</td>\n",
" <td>LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Diretiva Ambiental do Exercito 2025-2027.pdf</td>\n",
" <td>Diretiva</td>\n",
" <td></td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11613</th>\n",
" <td>Folheto_a verdade sobre o Crack.pdf</td>\n",
" <td>Folheto</td>\n",
" <td></td>\n",
" </tr>\n",
" <tr>\n",
" <th>11614</th>\n",
" <td>Folheto_a verdade sobre o ecstasy.pdf</td>\n",
" <td>Folheto</td>\n",
" <td></td>\n",
" </tr>\n",
" <tr>\n",
" <th>11615</th>\n",
" <td>Panfletos PIEDs.pdf</td>\n",
" <td>Outros</td>\n",
" <td>MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11616</th>\n",
" <td>MAN 2016RHV03 - Processo Individual v1.pdf</td>\n",
" <td>Outros</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11617</th>\n",
" <td>MAN 2016RHV07 - Assiduidades v1.pdf</td>\n",
" <td>Outros</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>11618 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" nome_pdf categoria \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... Guia \n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf Guia \n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf LISTA \n",
"3 LISTA ADIDOS NACIONAIS.pdf LISTA \n",
"4 Diretiva Ambiental do Exercito 2025-2027.pdf Diretiva \n",
"... ... ... \n",
"11613 Folheto_a verdade sobre o Crack.pdf Folheto \n",
"11614 Folheto_a verdade sobre o ecstasy.pdf Folheto \n",
"11615 Panfletos PIEDs.pdf Outros \n",
"11616 MAN 2016RHV03 - Processo Individual v1.pdf Outros \n",
"11617 MAN 2016RHV07 - Assiduidades v1.pdf Outros \n",
"\n",
" texto \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR... \n",
"1 NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR... \n",
"2 LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU... \n",
"3 LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA... \n",
"4 \n",
"... ... \n",
"11613 \n",
"11614 \n",
"11615 MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ... \n",
"11616 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... \n",
"11617 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... \n",
"\n",
"[11618 rows x 3 columns]"
]
},
"execution_count": 135,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b74929bc",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n"
]
}
],
"source": [
"dataset = processar_pasta_pdfs(pasta_pdfs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eed83275",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto_limpo</th>\n",
" <th>headers_detetados</th>\n",
" <th>footers_detetados</th>\n",
" <th>erro</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO...</td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO...</td>\n",
" <td>[não classificado]</td>\n",
" <td>[não classificado]</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU...</td>\n",
" <td>[defesa]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA...</td>\n",
" <td>[]</td>\n",
" <td>[+#]</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Diretiva Ambiental do Exercito 2025-2027.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf \n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf \n",
"3 LISTA ADIDOS NACIONAIS.pdf \n",
"4 Diretiva Ambiental do Exercito 2025-2027.pdf \n",
"\n",
" caminho \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"\n",
" texto_limpo headers_detetados \\\n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO... [] \n",
"1 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO... [não classificado] \n",
"2 LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU... [defesa] \n",
"3 LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA... [] \n",
"4 [] \n",
"\n",
" footers_detetados erro \n",
"0 [] NaN \n",
"1 [não classificado] NaN \n",
"2 [] NaN \n",
"3 [+#] NaN \n",
"4 [] NaN "
]
},
"execution_count": 147,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset.head()"
]
},
{
"cell_type": "markdown",
"id": "12f721e2",
"metadata": {},
"source": [
"Havia 3 documentos que deram erro, na como não eram \"relevantes\" acabei por os eliminar"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b434bf29",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"erro\n",
"Invalid dictionary construct: [/'Registry', b'', /'Ordering', b'', /'Supplement'] 1\n",
"Unexpected EOF 1\n",
"No /Root object! - Is this really a PDF? 1\n",
"Name: count, dtype: int64"
]
},
"execution_count": 151,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[\"erro\"].value_counts()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bf9780a0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto_limpo</th>\n",
" <th>headers_detetados</th>\n",
" <th>footers_detetados</th>\n",
" <th>erro</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2711</th>\n",
" <td>849-D - 2120001806_signed.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\Financas\\pce\\pm...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>Invalid dictionary construct: [/'Registry', b'...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9814</th>\n",
" <td>LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\AdmRH\\g...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>Unexpected EOF</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11585</th>\n",
" <td>GSST_Relatorio anual-estatisticas2017+Despacho...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>No /Root object! - Is this really a PDF?</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"2711 849-D - 2120001806_signed.pdf \n",
"9814 LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf \n",
"11585 GSST_Relatorio anual-estatisticas2017+Despacho... \n",
"\n",
" caminho texto_limpo \\\n",
"2711 D:\\Trabalhos\\Bot Exército\\pdfs\\Financas\\pce\\pm... \n",
"9814 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\AdmRH\\g... \n",
"11585 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"\n",
" headers_detetados footers_detetados \\\n",
"2711 [] [] \n",
"9814 [] [] \n",
"11585 [] [] \n",
"\n",
" erro \n",
"2711 Invalid dictionary construct: [/'Registry', b'... \n",
"9814 Unexpected EOF \n",
"11585 No /Root object! - Is this really a PDF? "
]
},
"execution_count": 150,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[dataset[\"erro\"].notna()]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3d80c15",
"metadata": {},
"outputs": [],
"source": [
"dataset = dataset[dataset[\"erro\"].isna()]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0f8022eb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Series([], Name: count, dtype: int64)"
]
},
"execution_count": 153,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[\"erro\"].value_counts()"
]
},
{
"cell_type": "markdown",
"id": "7c441a45",
"metadata": {},
"source": [
"### Criação dos Chunks para análise (não finais)\n",
"\n",
"Aqui o afinar dos parametros dos chunks pode tambem ser algo a ser considerado para melhorar o modelo"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "efb4217e",
"metadata": {},
"outputs": [],
"source": [
"dataset[\"chunks\"] = dataset[\"texto_limpo\"].apply(lambda x: chunk_texto_inteligente(x, chunk_size=1200, overlap=200))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "08dc12c2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>chunks</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>[ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTR...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"\n",
" chunks \n",
"0 [ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTR... "
]
},
"execution_count": 158,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[[\"nome_pdf\", \"chunks\"]].head(1)"
]
},
{
"cell_type": "markdown",
"id": "1659a5bf",
"metadata": {},
"source": [
"### Divisão em chunks e OCR\n",
"\n",
"Chunks por documento, aqui reparei que havia documentos com num_chunks de 0 o que já era previsto porque havia documentos que eram digitalizados então paralelamente existe um script que faz o OCR desses documentos o conjunto de comandos seguintes identificaram quais os documentos sem chunks e com 1 ou 2 chunks e foram passados por OCR pelo script denominado de OCR.ipynb.\n",
"\n",
"Apliquei tambem um critério na questão do texto limpo ser menor de 200 caracteres porque muitas das vezes temos documentos que tem a folha de rosto, por exemplo, em pdf e o resto do corpo está digitalizado, assim cobre tambem esta possibilidade.\n",
"\n",
"A solução passou por identificar quais eram os documentos que necessitavam de OCR tendo em conta os critérios establecidos anteriormente e por estes documentos todos numa pasta aparte e aplicar OCR (script) sobre os mesmo.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34a93306",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>num_chunks</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>112</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>237</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Diretiva Ambiental do Exercito 2025-2027.pdf</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf num_chunks\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... 112\n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf 237\n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf 9\n",
"3 LISTA ADIDOS NACIONAIS.pdf 2\n",
"4 Diretiva Ambiental do Exercito 2025-2027.pdf 0"
]
},
"execution_count": 159,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[\"num_chunks\"] = dataset[\"chunks\"].apply(len)\n",
"dataset[[\"nome_pdf\", \"num_chunks\"]].head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "421a7795",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto_limpo</th>\n",
" <th>headers_detetados</th>\n",
" <th>footers_detetados</th>\n",
" <th>erro</th>\n",
" <th>chunks</th>\n",
" <th>num_chunks</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Diretiva Ambiental do Exercito 2025-2027.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>Politica Ambiental Exercito_2025_Capa.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>d</td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[d]</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>FND2017.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>FND2018.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50</th>\n",
" <td>Teste 2paginas.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td></td>\n",
" <td>[teste1]</td>\n",
" <td>[teste1]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11610</th>\n",
" <td>Folheto_ a verdade sobre o LSD.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11611</th>\n",
" <td>Folheto_a verdade sobre a Metanfetamina.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11612</th>\n",
" <td>Folheto_a verdade sobre as drogas.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11613</th>\n",
" <td>Folheto_a verdade sobre o Crack.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11614</th>\n",
" <td>Folheto_a verdade sobre o ecstasy.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td></td>\n",
" <td>[]</td>\n",
" <td>[]</td>\n",
" <td>NaN</td>\n",
" <td>[]</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>1234 rows × 8 columns</p>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"4 Diretiva Ambiental do Exercito 2025-2027.pdf \n",
"18 Politica Ambiental Exercito_2025_Capa.pdf \n",
"24 FND2017.pdf \n",
"25 FND2018.pdf \n",
"50 Teste 2paginas.pdf \n",
"... ... \n",
"11610 Folheto_ a verdade sobre o LSD.pdf \n",
"11611 Folheto_a verdade sobre a Metanfetamina.pdf \n",
"11612 Folheto_a verdade sobre as drogas.pdf \n",
"11613 Folheto_a verdade sobre o Crack.pdf \n",
"11614 Folheto_a verdade sobre o ecstasy.pdf \n",
"\n",
" caminho texto_limpo \\\n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"18 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... d \n",
"24 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"25 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"50 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"... ... ... \n",
"11610 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11611 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11612 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11613 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11614 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"\n",
" headers_detetados footers_detetados erro chunks num_chunks \n",
"4 [] [] NaN [] 0 \n",
"18 [] [] NaN [d] 1 \n",
"24 [] [] NaN [] 0 \n",
"25 [] [] NaN [] 0 \n",
"50 [teste1] [teste1] NaN [] 0 \n",
"... ... ... ... ... ... \n",
"11610 [] [] NaN [] 0 \n",
"11611 [] [] NaN [] 0 \n",
"11612 [] [] NaN [] 0 \n",
"11613 [] [] NaN [] 0 \n",
"11614 [] [] NaN [] 0 \n",
"\n",
"[1234 rows x 8 columns]"
]
},
"execution_count": 176,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[(dataset[\"num_chunks\"] == 0) |(dataset[\"texto_limpo\"].str.len() < 200)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "26dd7bc4",
"metadata": {},
"outputs": [],
"source": [
"pasta_ocr = r\"D:\\Trabalhos\\Bot Exército\\OCR\"\n",
"os.makedirs(pasta_ocr, exist_ok=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "06d4ee05",
"metadata": {},
"outputs": [],
"source": [
"docs_ocr = dataset[(dataset[\"num_chunks\"] == 0)|\n",
" (dataset[\"texto_limpo\"].str.len() < 200)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a15220e",
"metadata": {},
"outputs": [],
"source": [
"for _, row in docs_ocr.iterrows():\n",
" origem = row[\"caminho\"]\n",
" nome = row[\"nome_pdf\"]\n",
" destino = os.path.join(pasta_ocr, nome)\n",
" destino = garantir_nome_unico(destino)\n",
" try:\n",
" shutil.move(origem, destino)\n",
" except Exception as e:\n",
" print(f\"Erro ao copiar {nome}: {e}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e04a167",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>categoria</th>\n",
" <th>chunk_id</th>\n",
" <th>texto_chunk</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>0</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>1</td>\n",
" <td>janeiro de 2018, que deverá ser destruído. CHE...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>2</td>\n",
" <td>DAS REGISTO DE ALTERACÔES J Identificação ou c...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>3</td>\n",
" <td>DOS 25 1. Visitas Organizadas 25 2. Plano Anua...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>4</td>\n",
" <td>a A-1 ANEXO B Ficha de Dados Biográficos B-1 A...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"2 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"3 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"4 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"\n",
" caminho categoria chunk_id \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 0 \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 1 \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 2 \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 3 \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 4 \n",
"\n",
" texto_chunk \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO... \n",
"1 janeiro de 2018, que deverá ser destruído. CHE... \n",
"2 DAS REGISTO DE ALTERACÔES J Identificação ou c... \n",
"3 DOS 25 1. Visitas Organizadas 25 2. Plano Anua... \n",
"4 a A-1 ANEXO B Ficha de Dados Biográficos B-1 A... "
]
},
"execution_count": 161,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_chunks = criar_dataset_chunks(dataset)\n",
"dataset_chunks.head()"
]
},
{
"cell_type": "markdown",
"id": "68ad43dc",
"metadata": {},
"source": [
"Embeddings utilizei [este](https://huggingface.co/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2) mas agora é uma questão de testar com outros especificos por exemplo para a lingua portuguesa só usei este porque há documentos com várias linguas.\n",
"\n",
"Aqui é necessário uma decisão importante, que tem a ver com custo beneficio, e para alem de termos muitas das vezes documentos, ou podermos vir a ter por exemplo manuais, que não estão escritos em portugues neste caso temos que ir buscar um emmbeding multilingua. Eu por limitações da máquina que tenho em casa usei o anterior que é pequeno mas propunha a subistutição ou para o:\n",
"\n",
"- [Multilingual-E5-large](https://huggingface.co/intfloat/multilingual-e5-large) - multilinguas - se virmos este tem condições especificas como 'query' ou 'passage'.\n",
"- [BGE-M3](https://huggingface.co/BAAI/bge-m3) - multilinguas - Tem git disponivel [aqui](https://github.com/FlagOpen/FlagEmbedding).\n",
"- [Legal BERTimbau (adaptado)](https://huggingface.co/stjiris/bert-large-portuguese-cased-legal-mlm-nli-sts-v1) - focado em PT, construido sobre um corpus de referencias legais, o que pode ser adequado no nosso caso pela forma de construção de texto em artigos e nós em pontos do genero de ordem de operações."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bf52274f",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n",
"c:\\Users\\garci\\AppData\\Local\\Python\\pythoncore-3.14-64\\Lib\\site-packages\\huggingface_hub\\file_download.py:129: UserWarning: `huggingface_hub` cache-system uses symlinks by default to efficiently store duplicated files but your machine does not support them in C:\\Users\\garci\\.cache\\huggingface\\hub\\models--sentence-transformers--paraphrase-multilingual-MiniLM-L12-v2. Caching files will still work but in a degraded version that might require more space on your disk. This warning can be disabled by setting the `HF_HUB_DISABLE_SYMLINKS_WARNING` environment variable. For more details, see https://huggingface.co/docs/huggingface_hub/how-to-cache#limitations.\n",
"To support symlinks on Windows, you either need to activate Developer Mode or to run Python as an administrator. In order to activate developer mode, see this article: https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development\n",
" warnings.warn(message)\n",
"Loading weights: 100%|██████████| 199/199 [00:00<00:00, 18943.00it/s]\n",
"\u001b[1mBertModel LOAD REPORT\u001b[0m from: sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2\n",
"Key | Status | | \n",
"------------------------+------------+--+-\n",
"embeddings.position_ids | UNEXPECTED | | \n",
"\n",
"\u001b[3mNotes:\n",
"- UNEXPECTED\u001b[3m\t:can be ignored when loading from different task/architecture; not ok if you expect identical arch.\u001b[0m\n"
]
}
],
"source": [
"modelo_embeddings = SentenceTransformer(\"sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a92e9507",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Batches: 100%|██████████| 6699/6699 [38:41<00:00, 2.89it/s]\n"
]
}
],
"source": [
"embeddings = modelo_embeddings.encode(\n",
" dataset_chunks[\"texto_chunk\"].tolist(),\n",
" show_progress_bar=True,\n",
" convert_to_numpy=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7ef5b64b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Número de chunks indexados: 214360\n"
]
}
],
"source": [
"dimensao = embeddings.shape[1]\n",
"\n",
"index = faiss.IndexFlatL2(dimensao)\n",
"index.add(np.array(embeddings, dtype=\"float32\"))\n",
"\n",
"print(\"Número de chunks indexados:\", index.ntotal)"
]
},
{
"cell_type": "markdown",
"id": "04e049f8",
"metadata": {},
"source": [
"# Criação dos metadados/dataset\n",
"\n",
"Vamos então voltar a repetir o processo todo agora com os PDF's que foram alvos de OCR já integrados no dataset"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "a50d8a03",
"metadata": {},
"outputs": [],
"source": [
"pasta_pdfs = r\"D:\\Trabalhos\\Bot Exército\\pdfs\""
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "ddbd06d6",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
"Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"PDFs encontrados: 11616\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Politica Ambiental Exercito 2025.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>dPOLÍTICA AMBIENTAL DO EXÉRCITO\\nExército Port...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf \n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf \n",
"3 LISTA ADIDOS NACIONAIS.pdf \n",
"4 Politica Ambiental Exercito 2025.pdf \n",
"\n",
" caminho \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"\n",
" texto \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR... \n",
"1 NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR... \n",
"2 LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU... \n",
"3 LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA... \n",
"4 dPOLÍTICA AMBIENTAL DO EXÉRCITO\\nExército Port... "
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dados = []\n",
"for raiz, subpastas, ficheiros in os.walk(pasta_pdfs):\n",
" for ficheiro in ficheiros:\n",
" if ficheiro.lower().endswith(\".pdf\"): \n",
" caminho_pdf = os.path.join(raiz, ficheiro) \n",
" texto = \"\" \n",
" try:\n",
" with pdfplumber.open(caminho_pdf) as pdf:\n",
" for pagina in pdf.pages:\n",
" texto += pagina.extract_text() or \"\"\n",
" except:\n",
" texto = \"ERRO OCR??\" \n",
" dados.append({\n",
" \"nome_pdf\": ficheiro,\n",
" \"caminho\": caminho_pdf,\n",
" \"texto\": texto\n",
" })\n",
"dataset = pd.DataFrame(dados)\n",
"print(\"PDFs encontrados:\", len(dataset))\n",
"dataset.head()"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "1e418e7c",
"metadata": {},
"outputs": [],
"source": [
"dataset[\"categoria\"] = dataset[\"nome_pdf\"].apply(classificar_documento)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "0efe7fd0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>texto</th>\n",
" <th>categoria</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR...</td>\n",
" <td>Guia</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR...</td>\n",
" <td>Guia</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>LISTA DE ADIDOS ESTRANGEIROS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU...</td>\n",
" <td>LISTA</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>LISTA ADIDOS NACIONAIS.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA...</td>\n",
" <td>LISTA</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Politica Ambiental Exercito 2025.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>dPOLÍTICA AMBIENTAL DO EXÉRCITO\\nExército Port...</td>\n",
" <td>Outros</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11611</th>\n",
" <td>Prevenir_as_Perturbacoes_Musculo-Esqueleticas.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td>F A C T S\\n4\\nA g ê n c i a E u r o p e i a p ...</td>\n",
" <td>Outros</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11612</th>\n",
" <td>Seguranca Higiene Saude - Sector Florestal.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td>Índice Geral\\n1. Preâmbulo.......................</td>\n",
" <td>Outros</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11613</th>\n",
" <td>Panfletos PIEDs.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" <td>MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ...</td>\n",
" <td>Folheto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11614</th>\n",
" <td>MAN 2016RHV03 - Processo Individual v1.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R...</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" <td>manual</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11615</th>\n",
" <td>MAN 2016RHV07 - Assiduidades v1.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R...</td>\n",
" <td>MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera...</td>\n",
" <td>manual</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>11616 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf \n",
"2 LISTA DE ADIDOS ESTRANGEIROS.pdf \n",
"3 LISTA ADIDOS NACIONAIS.pdf \n",
"4 Politica Ambiental Exercito 2025.pdf \n",
"... ... \n",
"11611 Prevenir_as_Perturbacoes_Musculo-Esqueleticas.pdf \n",
"11612 Seguranca Higiene Saude - Sector Florestal.pdf \n",
"11613 Panfletos PIEDs.pdf \n",
"11614 MAN 2016RHV03 - Processo Individual v1.pdf \n",
"11615 MAN 2016RHV07 - Assiduidades v1.pdf \n",
"\n",
" caminho \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... \n",
"... ... \n",
"11611 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11612 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11613 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... \n",
"11614 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R... \n",
"11615 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SIGDN_R... \n",
"\n",
" texto categoria \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS\\nCENTR... Guia \n",
"1 NÃO CLASSIFICADO\\nESTADO-MAIOR-GENERAL DAS FOR... Guia \n",
"2 LISTA DE ADIDOS MILITARES ACREDITADOS EM PORTU... LISTA \n",
"3 LISTA DE ADIDOS MILITARES PORTUGUESES ACREDITA... LISTA \n",
"4 dPOLÍTICA AMBIENTAL DO EXÉRCITO\\nExército Port... Outros \n",
"... ... ... \n",
"11611 F A C T S\\n4\\nA g ê n c i a E u r o p e i a p ... Outros \n",
"11612 Índice Geral\\n1. Preâmbulo....................... Outros \n",
"11613 MISTURAR SUBSTÂNCIAS AUMENTA EXPONENCIALMENTE ... Folheto \n",
"11614 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... manual \n",
"11615 MINISTÉRIO DA DEFESA NACIONAL\\nSecretaria-Gera... manual \n",
"\n",
"[11616 rows x 4 columns]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset"
]
},
{
"cell_type": "markdown",
"id": "6d2635bb",
"metadata": {},
"source": [
"Aqui a semelhança do que fiz no pré processamento gravei em [.csv](/pdfs/indexpdfs_final.csv) e [.json](/pdfs/indexpdfs_final.json) o dataset puro com o nome do indexpdfs_final e o que é para a construção da LLM gravei apenas como json em [dataset_llm_final](/pdfs/dataset_llm_final.json).\n",
"\n",
"Aqui uma solução mais robusta seria colocar o nosso dataset num BD, tipo o weviate ou outro."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d4c6ebc",
"metadata": {},
"outputs": [],
"source": [
"dataset.to_csv(r\"D:\\Trabalhos\\Bot Exército\\pdfs\\indexpdfs_final.csv\", index=False)\n",
"dataset.to_json(r\"D:\\Trabalhos\\Bot Exército\\pdfs\\indexpdfs_final.json\", orient=\"records\", indent=2)\n",
"dataset[[\"nome_pdf\", \"categoria\", \"texto\"]].to_json(\n",
" \"dataset_llm_final.json\",\n",
" orient=\"records\",\n",
" force_ascii=False,\n",
" indent=2\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "757b0ab2",
"metadata": {},
"outputs": [],
"source": [
"dataset = pd.read_json(r\"dataset_llm_final.json\")"
]
},
{
"cell_type": "markdown",
"id": "1e4388dc",
"metadata": {},
"source": [
"O dataset está desiquilibrado\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "cc124042",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"categoria\n",
"Outros 10587\n",
"NOTA 607\n",
"Referencial 96\n",
"Plano 56\n",
"manual 51\n",
"Regulamentos e Leis 46\n",
"Publicação 36\n",
"NEP 27\n",
"LISTA 26\n",
"Guia 25\n",
"Norma 23\n",
"Diretiva 21\n",
"Folheto 15\n",
"Name: count, dtype: int64"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset[\"categoria\"].value_counts()"
]
},
{
"cell_type": "markdown",
"id": "bba88d27",
"metadata": {},
"source": [
"## Criação dos chunks finais"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "64320a4b",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" 78%|███████▊ | 9046/11616 [47:47<34:40, 1.24it/s] Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
" 97%|█████████▋| 11297/11616 [1:27:35<08:01, 1.51s/it] Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
" 97%|█████████▋| 11301/11616 [1:27:44<13:24, 2.55s/it]Could not get FontBBox from font descriptor because None cannot be parsed as 4 floats\n",
"100%|██████████| 11616/11616 [1:48:22<00:00, 1.79it/s] \n"
]
}
],
"source": [
"dataset = processar_pasta_pdfs(pasta_pdfs)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "4ab816fc",
"metadata": {},
"outputs": [],
"source": [
"dataset[\"chunks\"] = dataset[\"texto_limpo\"].apply(lambda x: chunk_texto_inteligente(x, chunk_size=1200, overlap=200))"
]
},
{
"cell_type": "markdown",
"id": "603a1e52",
"metadata": {},
"source": [
"Ora voltamos a ver quantos pdfs temos com chunks=0, e vemos que ainda assim haviam 141 que mesmo depois do OCR ficaram m\n",
"\n",
"tam_texto = 0 → OCR/extract falhou mesmo\n",
"\n",
"tam_texto > 0 mas num_chunks = 0 → o problema pode estar no chunking ou na limpeza"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "7deee1e2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2101</th>\n",
" <td>849-D - 2120001806_signed.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\Financas\\pce\\pm...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7987</th>\n",
" <td>12_1_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\12_1_ocr.pdf</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8031</th>\n",
" <td>2019 Lei 36_2019 - revoga DLs 1975 a 1980_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\2019 Lei 36...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8045</th>\n",
" <td>2120012050_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\2120012050_...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8402</th>\n",
" <td>4206_Mapa Incumprimentos_ABR2023_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\4206_Mapa I...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8760</th>\n",
" <td>Anexo D (Folha de Caixa)_ABR23_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Anexo D (Fo...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8926</th>\n",
" <td>Flyer_sinais de CAD internet e videojogos_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Flyer_sinai...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9000</th>\n",
" <td>NIF Exercito_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\NIF Exercit...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9034</th>\n",
" <td>OfertaFormativa - ISG_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\OfertaForma...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9080</th>\n",
" <td>Protocolo - Portinsurance_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Protocolo -...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9108</th>\n",
" <td>Saldos Conta SIG Dez24_1110040013_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9109</th>\n",
" <td>Saldos Conta SIG Dez24_1110040013_signed_signe...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9110</th>\n",
" <td>Saldos Conta SIG Dez24_1110044306_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9111</th>\n",
" <td>Saldos Conta SIG Dez24_1110044306_signed_signe...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9112</th>\n",
" <td>Saldos Conta SIG Dez24_1210040335_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9113</th>\n",
" <td>Saldos Conta SIG Dez24_1210040335_signed_signe...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9115</th>\n",
" <td>Teste 2paginas_ocr.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Teste 2pagi...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9990</th>\n",
" <td>LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\AdmRH\\g...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11597</th>\n",
" <td>GSST_Relatorio anual-estatisticas2017+Despacho...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"2101 849-D - 2120001806_signed.pdf \n",
"7987 12_1_ocr.pdf \n",
"8031 2019 Lei 36_2019 - revoga DLs 1975 a 1980_ocr.pdf \n",
"8045 2120012050_ocr.pdf \n",
"8402 4206_Mapa Incumprimentos_ABR2023_ocr.pdf \n",
"8760 Anexo D (Folha de Caixa)_ABR23_ocr.pdf \n",
"8926 Flyer_sinais de CAD internet e videojogos_ocr.pdf \n",
"9000 NIF Exercito_ocr.pdf \n",
"9034 OfertaFormativa - ISG_ocr.pdf \n",
"9080 Protocolo - Portinsurance_ocr.pdf \n",
"9108 Saldos Conta SIG Dez24_1110040013_ocr.pdf \n",
"9109 Saldos Conta SIG Dez24_1110040013_signed_signe... \n",
"9110 Saldos Conta SIG Dez24_1110044306_ocr.pdf \n",
"9111 Saldos Conta SIG Dez24_1110044306_signed_signe... \n",
"9112 Saldos Conta SIG Dez24_1210040335_ocr.pdf \n",
"9113 Saldos Conta SIG Dez24_1210040335_signed_signe... \n",
"9115 Teste 2paginas_ocr.pdf \n",
"9990 LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf \n",
"11597 GSST_Relatorio anual-estatisticas2017+Despacho... \n",
"\n",
" caminho \n",
"2101 D:\\Trabalhos\\Bot Exército\\pdfs\\Financas\\pce\\pm... \n",
"7987 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\12_1_ocr.pdf \n",
"8031 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\2019 Lei 36... \n",
"8045 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\2120012050_... \n",
"8402 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\4206_Mapa I... \n",
"8760 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Anexo D (Fo... \n",
"8926 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Flyer_sinai... \n",
"9000 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\NIF Exercit... \n",
"9034 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\OfertaForma... \n",
"9080 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Protocolo -... \n",
"9108 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9109 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9110 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9111 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9112 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9113 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Saldos Cont... \n",
"9115 D:\\Trabalhos\\Bot Exército\\pdfs\\OCR\\Teste 2pagi... \n",
"9990 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\AdmRH\\g... \n",
"11597 D:\\Trabalhos\\Bot Exército\\pdfs\\pessoal\\SegSaud... "
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"docs_restantes = dataset[dataset[\"num_chunks\"] == 0].copy()\n",
"docs_restantes[[\"nome_pdf\", \"caminho\"]].head(20)"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "e7dfcc23",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>tam_texto</th>\n",
" <th>num_chunks</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2101</th>\n",
" <td>849-D - 2120001806_signed.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7987</th>\n",
" <td>12_1_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8031</th>\n",
" <td>2019 Lei 36_2019 - revoga DLs 1975 a 1980_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8045</th>\n",
" <td>2120012050_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8402</th>\n",
" <td>4206_Mapa Incumprimentos_ABR2023_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8760</th>\n",
" <td>Anexo D (Folha de Caixa)_ABR23_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8926</th>\n",
" <td>Flyer_sinais de CAD internet e videojogos_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9000</th>\n",
" <td>NIF Exercito_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9034</th>\n",
" <td>OfertaFormativa - ISG_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9080</th>\n",
" <td>Protocolo - Portinsurance_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9108</th>\n",
" <td>Saldos Conta SIG Dez24_1110040013_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9109</th>\n",
" <td>Saldos Conta SIG Dez24_1110040013_signed_signe...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9110</th>\n",
" <td>Saldos Conta SIG Dez24_1110044306_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9111</th>\n",
" <td>Saldos Conta SIG Dez24_1110044306_signed_signe...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9112</th>\n",
" <td>Saldos Conta SIG Dez24_1210040335_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9113</th>\n",
" <td>Saldos Conta SIG Dez24_1210040335_signed_signe...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9115</th>\n",
" <td>Teste 2paginas_ocr.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9990</th>\n",
" <td>LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11597</th>\n",
" <td>GSST_Relatorio anual-estatisticas2017+Despacho...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf tam_texto \\\n",
"2101 849-D - 2120001806_signed.pdf 0 \n",
"7987 12_1_ocr.pdf 0 \n",
"8031 2019 Lei 36_2019 - revoga DLs 1975 a 1980_ocr.pdf 0 \n",
"8045 2120012050_ocr.pdf 0 \n",
"8402 4206_Mapa Incumprimentos_ABR2023_ocr.pdf 0 \n",
"8760 Anexo D (Folha de Caixa)_ABR23_ocr.pdf 0 \n",
"8926 Flyer_sinais de CAD internet e videojogos_ocr.pdf 0 \n",
"9000 NIF Exercito_ocr.pdf 0 \n",
"9034 OfertaFormativa - ISG_ocr.pdf 0 \n",
"9080 Protocolo - Portinsurance_ocr.pdf 0 \n",
"9108 Saldos Conta SIG Dez24_1110040013_ocr.pdf 0 \n",
"9109 Saldos Conta SIG Dez24_1110040013_signed_signe... 0 \n",
"9110 Saldos Conta SIG Dez24_1110044306_ocr.pdf 0 \n",
"9111 Saldos Conta SIG Dez24_1110044306_signed_signe... 0 \n",
"9112 Saldos Conta SIG Dez24_1210040335_ocr.pdf 0 \n",
"9113 Saldos Conta SIG Dez24_1210040335_signed_signe... 0 \n",
"9115 Teste 2paginas_ocr.pdf 0 \n",
"9990 LISTAS DE ANTIGUIDADE DE 1963 Oficiais.pdf 0 \n",
"11597 GSST_Relatorio anual-estatisticas2017+Despacho... 0 \n",
"\n",
" num_chunks \n",
"2101 0 \n",
"7987 0 \n",
"8031 0 \n",
"8045 0 \n",
"8402 0 \n",
"8760 0 \n",
"8926 0 \n",
"9000 0 \n",
"9034 0 \n",
"9080 0 \n",
"9108 0 \n",
"9109 0 \n",
"9110 0 \n",
"9111 0 \n",
"9112 0 \n",
"9113 0 \n",
"9115 0 \n",
"9990 0 \n",
"11597 0 "
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"docs_restantes[\"tam_texto\"] = docs_restantes[\"texto_limpo\"].fillna(\"\").str.len()\n",
"docs_restantes[[\"nome_pdf\", \"tam_texto\", \"num_chunks\"]].sort_values(\"tam_texto\").head(30)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "4f812fd3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"np.int64(0)"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset = dataset[dataset[\"num_chunks\"] > 0].reset_index(drop=True)\n",
"(dataset[\"num_chunks\"] == 0).sum()"
]
},
{
"cell_type": "markdown",
"id": "b62b8ec0",
"metadata": {},
"source": [
"### Aqui um exemplo para ver se a query está a procura dos documentos certos"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "d6d48621",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>caminho</th>\n",
" <th>categoria</th>\n",
" <th>chunk_id</th>\n",
" <th>texto_chunk</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>0</td>\n",
" <td>ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>1</td>\n",
" <td>janeiro de 2018, que deverá ser destruído. CHE...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>2</td>\n",
" <td>DAS REGISTO DE ALTERACÔES J Identificação ou c...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>3</td>\n",
" <td>DOS 25 1. Visitas Organizadas 25 2. Plano Anua...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA...</td>\n",
" <td>D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM...</td>\n",
" <td>Outros</td>\n",
" <td>4</td>\n",
" <td>a A-1 ANEXO B Ficha de Dados Biográficos B-1 A...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf \\\n",
"0 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"1 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"2 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"3 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"4 GUIA DOS ADIDOS DE DEFESA E MILITARES ACREDITA... \n",
"\n",
" caminho categoria chunk_id \\\n",
"0 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 0 \n",
"1 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 1 \n",
"2 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 2 \n",
"3 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 3 \n",
"4 D:\\Trabalhos\\Bot Exército\\pdfs\\comando-EstadoM... Outros 4 \n",
"\n",
" texto_chunk \n",
"0 ESTADO-MAIOR-GENERAL DAS FORÇAS ARMADAS CENTRO... \n",
"1 janeiro de 2018, que deverá ser destruído. CHE... \n",
"2 DAS REGISTO DE ALTERACÔES J Identificação ou c... \n",
"3 DOS 25 1. Visitas Organizadas 25 2. Plano Anua... \n",
"4 a A-1 ANEXO B Ficha de Dados Biográficos B-1 A... "
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_chunks = criar_dataset_chunks(dataset)\n",
"dataset_chunks.head()"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "65a8b094",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Loading weights: 100%|██████████| 199/199 [00:00<00:00, 15670.66it/s]\n",
"\u001b[1mBertModel LOAD REPORT\u001b[0m from: sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2\n",
"Key | Status | | \n",
"------------------------+------------+--+-\n",
"embeddings.position_ids | UNEXPECTED | | \n",
"\n",
"\u001b[3mNotes:\n",
"- UNEXPECTED\u001b[3m\t:can be ignored when loading from different task/architecture; not ok if you expect identical arch.\u001b[0m\n"
]
}
],
"source": [
"modelo_embeddings = SentenceTransformer(\"sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2\")"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "ea04809e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Batches: 100%|██████████| 7352/7352 [42:05<00:00, 2.91it/s]\n"
]
}
],
"source": [
"embeddings = modelo_embeddings.encode(\n",
" dataset_chunks[\"texto_chunk\"].tolist(),\n",
" show_progress_bar=True,\n",
" convert_to_numpy=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "dec2a18e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Número de chunks indexados: 235262\n"
]
}
],
"source": [
"dimensao = embeddings.shape[1]\n",
"\n",
"index = faiss.IndexFlatL2(dimensao)\n",
"index.add(np.array(embeddings, dtype=\"float32\"))\n",
"\n",
"print(\"Número de chunks indexados:\", index.ntotal)"
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "07f4854a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>nome_pdf</th>\n",
" <th>categoria</th>\n",
" <th>texto_chunk</th>\n",
" <th>score_distancia</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>36816</th>\n",
" <td>PAD 230-01 RGSUEOE SET22.pdf</td>\n",
" <td>Outros</td>\n",
" <td>ança do Pessoal; (3) Segurança física; (4) Seg...</td>\n",
" <td>7.508637</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36818</th>\n",
" <td>PAD 230-01 RGSUEOE SET22.pdf</td>\n",
" <td>Outros</td>\n",
" <td>o e do acesso à Informação classificada, em es...</td>\n",
" <td>9.730995</td>\n",
" </tr>\n",
" <tr>\n",
" <th>204497</th>\n",
" <td>Protocolo - Biwatt Green.pdf</td>\n",
" <td>Outros</td>\n",
" <td>a, classificada pela entidade emissora de conf...</td>\n",
" <td>9.759338</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39543</th>\n",
" <td>Regulamento (UE) 2016_679 do PE e do Conselho,...</td>\n",
" <td>Outros</td>\n",
" <td>porcionada para assegurar a segurança da rede ...</td>\n",
" <td>10.058803</td>\n",
" </tr>\n",
" <tr>\n",
" <th>204600</th>\n",
" <td>Protocolo - CRIAP 2023.pdf</td>\n",
" <td>Outros</td>\n",
" <td>cia trocada, classificada pela entidade emisso...</td>\n",
" <td>10.598384</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" nome_pdf categoria \\\n",
"36816 PAD 230-01 RGSUEOE SET22.pdf Outros \n",
"36818 PAD 230-01 RGSUEOE SET22.pdf Outros \n",
"204497 Protocolo - Biwatt Green.pdf Outros \n",
"39543 Regulamento (UE) 2016_679 do PE e do Conselho,... Outros \n",
"204600 Protocolo - CRIAP 2023.pdf Outros \n",
"\n",
" texto_chunk score_distancia \n",
"36816 ança do Pessoal; (3) Segurança física; (4) Seg... 7.508637 \n",
"36818 o e do acesso à Informação classificada, em es... 9.730995 \n",
"204497 a, classificada pela entidade emissora de conf... 9.759338 \n",
"39543 porcionada para assegurar a segurança da rede ... 10.058803 \n",
"204600 cia trocada, classificada pela entidade emisso... 10.598384 "
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"resultados = pesquisar_chunks(\n",
" query=\"Quais são as normas sobre segurança da informação?\",\n",
" modelo_embeddings=modelo_embeddings,\n",
" index=index,\n",
" dataset_chunks=dataset_chunks,\n",
" top_k=5\n",
")\n",
"\n",
"resultados[[\"nome_pdf\", \"categoria\", \"texto_chunk\", \"score_distancia\"]]"
]
},
{
"cell_type": "markdown",
"id": "5a918f91",
"metadata": {},
"source": [
"Qwen"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "0d48fbe5",
"metadata": {},
"outputs": [],
"source": [
"query = \"Quais são os procedimentos previstos na NEP para segurança documental?\"\n",
"resultados = pesquisar_chunks(query, modelo_embeddings, index, dataset_chunks, top_k=5)\n",
"prompt_final = construir_contexto_rag(query, resultados)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "debafbd9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Responde à pergunta do utilizador com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"Quais são os procedimentos previstos na NEP para segurança documental?\n",
"\n",
"Contexto:\n",
"[Documento: E0199A1P_Esp 012 - Sapador de Engenharia.pdf | Categoria: Outros]\n",
"as graves de procedimentos de segurança.\n",
"\n",
"---\n",
"\n",
"[Documento: DIRECTIVA31MAR08.pdf | Categoria: Outros]\n",
"rementar a utilização da aplicação de gestão documental de modo a tirar melhor partido das suas capacidades; (b) Propor acções com vista à motivação pessoal, para o cumprimento dos objectivos da DFin;\n",
"\n",
"(c) Efectuar o controlo da assiduidade do pessoal civil tirando partido das capacidades da aplicação de “controlo de ponto”. g. Oficial de Segurança (1) Quanto à segurança das informações (a) Adoptar todas as medidas relativas à protecção das matérias classificadas e conduzir as investigações de segurança que forem necessárias; (b) Aconselhar o Director sobre assuntos relativos à segurança e protecção das matérias classificadas; (c) Montar a segurança das matérias classificadas; (d) Propor a correcção de erros de atribuição da classificação de segurança; (e) Organizar programas de destruição de rotina de documentos desactualizados e sem interesse histórico, por forma a evitar a sobrecarga inútil dos arquivos; (f) Supervisionar a destruição de rascunhos, minutas, papeis químicos, cópias excedentárias e demais desperdícios, por forma a assegurar que através deles não ocorram quebras de segurança; (g) Planear a destruição de emergência de todas as matérias classificadas; (h) Efectuar inspecções de segurança com vista a verificar se são cumpridas as normas de segurança em vigor.\n",
"\n",
"---\n",
"\n",
"[Documento: Diretiva 2008 - 31Mar08.pdf | Categoria: Outros]\n",
"rementar a utilização da aplicação de gestão documental de modo a tirar melhor partido das suas capacidades; (b) Propor acções com vista à motivação pessoal, para o cumprimento dos objectivos da DFin;\n",
"\n",
"(c) Efectuar o controlo da assiduidade do pessoal civil tirando partido das capacidades da aplicação de “controlo de ponto”. g. Oficial de Segurança (1) Quanto à segurança das informações (a) Adoptar todas as medidas relativas à protecção das matérias classificadas e conduzir as investigações de segurança que forem necessárias; (b) Aconselhar o Director sobre assuntos relativos à segurança e protecção das matérias classificadas; (c) Montar a segurança das matérias classificadas; (d) Propor a correcção de erros de atribuição da classificação de segurança; (e) Organizar programas de destruição de rotina de documentos desactualizados e sem interesse histórico, por forma a evitar a sobrecarga inútil dos arquivos; (f) Supervisionar a destruição de rascunhos, minutas, papeis químicos, cópias excedentárias e demais desperdícios, por forma a assegurar que através deles não ocorram quebras de segurança; (g) Planear a destruição de emergência de todas as matérias classificadas; (h) Efectuar inspecções de segurança com vista a verificar se são cumpridas as normas de segurança em vigor.\n",
"\n",
"---\n",
"\n",
"[Documento: PDE 4-46-00.pdf | Categoria: Outros]\n",
"ma casuística e não integrada, Diretivas Técnicas e Normas de Execução Permanente (NEP), como forma de dar resposta aos problemas e desafios específicos que vão surgindo, de que tem resultado a instituição de procedimentos ajustados e facilitadores do cumprimento da missão do CmdLog. XI\n",
"\n",
"---\n",
"\n",
"[Documento: PASSTPA-2024_BrigInt_ocr.pdf | Categoria: Outros]\n",
"ensibilização dos executantes para a sua finalidade face aos perigos/riscos, de acordo com o método preconizado na PAD 123-01. i. Requlamentos, Manuais e Normas de Segurança (1) Promover a divulgação das NEP da Briglnt; (2) Promover a revisão dos PEI e sua difusão. j. Relato, investigação e registo de Incidentes / Acidentes (1) Manter atualizada, em Ordem de Serviço das Unidades, a relação dos elementos que constituem as Comissões de Investigação de Acidentes, quanto aos Fatores Humanos, Materiais e Ambientais. Por norma, o Presidente é o Comandante da Unidade, o Oficial Coordenador é o Oficial de Segurança e Saúde no Trabalho e o\n",
"\n",
"Instruções:\n",
"- Se a resposta não estiver claramente no contexto, diz que não encontraste informação suficiente.\n",
"- Resume de forma objetiva.\n",
"- Cita o nome do documento quando relevante.\n",
"\n"
]
}
],
"source": [
"print(prompt_final)"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "00364e41",
"metadata": {},
"outputs": [],
"source": [
"perguntas_teste = [\n",
" \"Quais são as normas sobre segurança da informação?\",\n",
" \"O que é uma NEP?\",\n",
" \"Que documento fala sobre redes sociais?\",\n",
" \"Quais são os procedimentos do interrogatório?\",\n",
" \"Que regras existem sobre administração de rede local?\"\n",
"]"
]
},
{
"cell_type": "markdown",
"id": "b1ad50fe",
"metadata": {},
"source": [
"Gualdar o modelo de embeddins"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "330f5a6f",
"metadata": {},
"outputs": [],
"source": [
"np.save(\"embeddings.npy\", embeddings)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "82b4c175",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"====================================================================================================\n",
"🔎 PERGUNTA: Quais são as normas sobre segurança da informação?\n",
"====================================================================================================\n",
"\n",
"Resultado 36817\n",
"Documento: PAD 230-01 RGSUEOE SET22.pdf\n",
"Categoria: Outros\n",
"Score: 7.508636951446533\n",
"Texto:\n",
"ança do Pessoal; (3) Segurança física; (4) Segurança das CSI. d. As medidas da segurança da informação situam-se no âmbito da segurança da informação classificada, no tratamento e manuseamento das mesmas e englobam: (1) Credenciação adequada à função e válida; (2) Classificação de segurança da informação; (3) Classificação do documento; (4) Preparação do documento classificado; (5) Reclassificação\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 36819\n",
"Documento: PAD 230-01 RGSUEOE SET22.pdf\n",
"Categoria: Outros\n",
"Score: 9.730995178222656\n",
"Texto:\n",
"o e do acesso à Informação classificada, em estrita observância do princípio da “necessidade de conhecer”. i. A segurança física deve ser implementada segundo o princípio da defesa em profundidade, recorrendo a um conjunto de medidas complementares nas restantes áreas da segurança. j. Para além da implementação dos conceitos prescritos adaptados às condições específicas da U/E/O e do meio onde se \n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 204498\n",
"Documento: Protocolo - Biwatt Green.pdf\n",
"Categoria: Outros\n",
"Score: 9.75933837890625\n",
"Texto:\n",
"a, classificada pela entidade emissora de confidencial, na mais estrita confidencialidade, bem como a observar o regime legal da proteção de dados pessoais. 2. Ao abrigo do disposto no númeroanterior, os OUTORGANTES obrigam-se, designadamente:\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 39544\n",
"Documento: Regulamento (UE) 2016_679 do PE e do Conselho, de 27 de abril de 2016, RGPD.pdf\n",
"Categoria: Outros\n",
"Score: 10.058802604675293\n",
"Texto:\n",
"porcionada para assegurar a segurança da rede e das informações, ou seja, a capacidade de uma rede ou de um sistema informático de resistir, com um dado nível de confiança, a eventos acidentais ou a ações maliciosas ou ilícitas que comprometam a disponibi­ lidade, a autenticidade, a integridade e a confidencialidade dos dados pessoais conservados ou transmitidos, bem como a segurança dos serviços \n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 204601\n",
"Documento: Protocolo - CRIAP 2023.pdf\n",
"Categoria: Outros\n",
"Score: 10.598383903503418\n",
"Texto:\n",
"cia trocada, classificada pela entidade emissora de confidencial, na mais estrita confidencialidade, bem como a observar o regime legal da proteção de dados pessoais. 2. Ao abrigo do disposto no númeroanterior, os OUTORGANTES obrigam-se, designadamente:\n",
"--------------------------------------------------------------------------------\n",
"\n",
"====================================================================================================\n",
"🔎 PERGUNTA: O que é uma NEP?\n",
"====================================================================================================\n",
"\n",
"Resultado 11402\n",
"Documento: RA2012.pdf\n",
"Categoria: Outros\n",
"Score: 13.04309368133545\n",
"Texto:\n",
"nto;\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 65681\n",
"Documento: NEP AGE.122_ocr.pdf\n",
"Categoria: Outros\n",
"Score: 15.137784004211426\n",
"Texto:\n",
".o 231/2009, de 15 setembro, que estabelece que o Comando de Pessoal é Orgão Central de Administração e Direção (OCAD), cabendo-lhe assegurar a superintendência e a execução em áreas ou atividades específicas essenciais. b. A presente NEP aplica-se a todos os trabalhadores da área da saúde, vinculados em regime de trabalho em funções públicas e integrados nas respetivas carreiras, que pretendam a \n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 43805\n",
"Documento: PDE 4-46-00.pdf\n",
"Categoria: Outros\n",
"Score: 15.832741737365723\n",
"Texto:\n",
"ma casuística e não integrada, Diretivas Técnicas e Normas de Execução Permanente (NEP), como forma de dar resposta aos problemas e desafios específicos que vão surgindo, de que tem resultado a instituição de procedimentos ajustados e facilitadores do cumprimento da missão do CmdLog. XI\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 1828\n",
"Documento: PDE 0-19-00_SINAIS CONVENCIONAIS MILITARES.pdf\n",
"Categoria: Outros\n",
"Score: 16.162994384765625\n",
"Texto:\n",
"Outros Símbolos e Gráficos TAREFA A/E GRÁFICO NOTAS Neutralizar (Neutralize) (É uma tarefa táctica que se traduz na N incapacidade do pessoal ou material In poder interferir com determinada operação das forças amigas. O comandante deve especificar qual a E Ver: N unidade ou material a neutralizar e a Suprimir (Supress); duração da neutralização. Desorganizar (Disrupt); No apoio de fogos representa\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 65696\n",
"Documento: NEP AGE.123_ocr.pdf\n",
"Categoria: Outros\n",
"Score: 16.30051040649414\n",
"Texto:\n",
"AGE.123 SUPLEMENTOS REMUNERATÓRIOS — TRABALHO EXTRAORDINÁRIO PAG. 2 despendidos com este suplemento; b. Assim, com a presente NEP, pretende-se compilar e difundir informação legislativa no âmbito da prestação de trabalho extraordinário, dispersa por vários normativos e, em simultâneo, regulamentar e implementar formalidade/procedimentos que permitam ao comando do Pessoal cumprir com o desidrato re\n",
"--------------------------------------------------------------------------------\n",
"\n",
"====================================================================================================\n",
"🔎 PERGUNTA: Que documento fala sobre redes sociais?\n",
"====================================================================================================\n",
"\n",
"Resultado 204\n",
"Documento: PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf\n",
"Categoria: Outros\n",
"Score: 10.005367279052734\n",
"Texto:\n",
"PEMGFA/GER 006 CAPÍTULO 12 COMUNICAÇÃO INSTITUCIONAL 1201. REDES SOCIAIS Atualmente as redes sociais fazem parte do dia-a-dia das pessoas e das organizações em todo o planeta. Com o crescimento do Facebook, Instagram, Twitter, etc permitindo acessos por computadores e também por tecnologias móveis como telefones, tablets, IPhones, etc é pois uma incontornável realidade. Para que possamos capitaliz\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 232228\n",
"Documento: Livro_VDS2018_definitivo_RCAN.pdf\n",
"Categoria: Outros\n",
"Score: 10.095380783081055\n",
"Texto:\n",
"Moqbel, 2012). Segundo Ellisson & Boyd (2007), as redes sociais são numa ferramenta pertencente à Internet que permite aos utilizadores estabelecer relações, construir um perfil público e criar e desenvolver conexões com outros utilizadores. Assim, as redes sociais como Facebook, Instagram, WhatsApp e LinkedIn fazem hoje parte do quotidiano de grande parte da população, transformando-se em platafo\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 13432\n",
"Documento: RA2022.pdf\n",
"Categoria: Outros\n",
"Score: 11.656988143920898\n",
"Texto:\n",
" Seguidores das Redes Sociais do Recrutamento do Exército, que tiveram igualmente um crescimento contínuo do número de seguidores ao longo de todo o ano. Figura 31 - Evolução mensal do número de “seguidores” das redes sociais do recrutamento do Exército, em 2022  Peças jornalísticas sobre o Exército nos Órgãos de Comunicação Social, no âmbito do incremento da relevância do Exército no ambiente m\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 232229\n",
"Documento: Livro_VDS2018_definitivo_RCAN.pdf\n",
"Categoria: Outros\n",
"Score: 12.249822616577148\n",
"Texto:\n",
"cooperativa com os clientes. As Organizações passaram a recorrer às mesmas como forma de promover os seus produtos e serviços (Drury, 2008). A utilização das redes sociais em contexto organizacional proporciona diversos benefícios para as Organizações, nomeadamente o facto de facilitar a interação e troca de informações com clientes e potenciais clientes (Ozuem, Howell & Lancaster, 2008), bem como\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 8738\n",
"Documento: PA2023.pdf\n",
"Categoria: Outros\n",
"Score: 12.47812557220459\n",
"Texto:\n",
"a divulgação do Serviço Militar em Regime de Voluntariado e Regime de Contrato (RV/RC) em Televisão, Cinemas, outdoors e revistas on-line. Comando do Pessoal Reforçar a mensagem transmitida pelo Recrutamento do Exército nas Redes Sociais através da criação de diversas campanhas no Facebook. Figura 15 Publicidade institucional\n",
"--------------------------------------------------------------------------------\n",
"\n",
"====================================================================================================\n",
"🔎 PERGUNTA: Quais são os procedimentos do interrogatório?\n",
"====================================================================================================\n",
"\n",
"Resultado 220461\n",
"Documento: E0202A1P_Esp 028 - I Armas Pesadas Morteiros CFS.pdf\n",
"Categoria: Outros\n",
"Score: 10.34010124206543\n",
"Texto:\n",
"o dos procedimentos - Supervisão\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 210171\n",
"Documento: MD 240-03_Modelo de Referencial de Curso.pdf\n",
"Categoria: Outros\n",
"Score: 10.960897445678711\n",
"Texto:\n",
"de recolha e análise de dados. (a) O procedimento metodológico, explica os passos inerentes aos processos de avaliação descrevendo quando e como se vai realizar a avaliação. A metodologia e instrumentos de recolha da informação nas fontes acima indicadas podem ser: 1 Testes. 2 Circuitos de Avaliação. 3 Observação direta. 4 Questionários. 5 Relatórios. 6-3\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 225621\n",
"Documento: PTE 005 01 Auditoria de Abonos e Descontos.pdf\n",
"Categoria: Outros\n",
"Score: 11.076339721679688\n",
"Texto:\n",
"CAPÍTULO 3 O PROCESSO DE AUDITORIA 301. Fases do processo de auditoria O Processo de auditoria contempla as quatro fases a seguir apresentadas. FASES DA AUDITORIA Compreensão dos processos, das entidades intervenientes e do meio Planeamento envolvente através do desenvolvimento do Estudo Preliminar. Avaliação do risco e elaboração do Programa de Auditoria. Avaliação do controlo interno e dos pro\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 226501\n",
"Documento: PTE 005 01 Auditoria de Abonos e Descontos.pdf\n",
"Categoria: Outros\n",
"Score: 11.076339721679688\n",
"Texto:\n",
"CAPÍTULO 3 O PROCESSO DE AUDITORIA 301. Fases do processo de auditoria O Processo de auditoria contempla as quatro fases a seguir apresentadas. FASES DA AUDITORIA Compreensão dos processos, das entidades intervenientes e do meio Planeamento envolvente através do desenvolvimento do Estudo Preliminar. Avaliação do risco e elaboração do Programa de Auditoria. Avaliação do controlo interno e dos pro\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 220893\n",
"Documento: E0215A1P_Esp 299 - C Morteiros CFO.pdf\n",
"Categoria: Outros\n",
"Score: 11.142557144165039\n",
"Texto:\n",
"cedimento O procedimento metodológico descreve quando e como se realiza a avaliação do curso e decorre em 2 fases: (1) Avaliação formativa, a fim de ajustar o desenvolvimento da formação às necessidades dos formandos; (2) Avaliação sumativa, a fim de aferir o resultado final da formação. b. Técnicas (1) Avaliação formativa: questões objetivas, registo de observação, revisão após ação;\n",
"--------------------------------------------------------------------------------\n",
"\n",
"====================================================================================================\n",
"🔎 PERGUNTA: Que regras existem sobre administração de rede local?\n",
"====================================================================================================\n",
"\n",
"Resultado 36778\n",
"Documento: PAD 230-01 RGSUEOE SET22.pdf\n",
"Categoria: Outros\n",
"Score: 10.024639129638672\n",
"Texto:\n",
"tação das NAT nesta área, emanadas pela respetiva entidade competente. 356. Competências do administrador de Rede local a. A tarefa principal do administrador de Rede local é gerir os sistemas informáticos locais, de acordo com as Normas em vigor no Exército e em estreita coordenação com a entidade competente do Exército para esta matéria. b. É dever do administrador de Rede local cumprir e divulg\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 45914\n",
"Documento: (REVOGADA) NAT 02.03.04 - Normas Tecnicas e procedimentos do Admin da Rede Local das UEO14JAN2014_ocr.pdf\n",
"Categoria: Outros\n",
"Score: 10.039144515991211\n",
"Texto:\n",
"istentes na U/E/O e fornece-lo ao CTE, sempre que solicitado ou em caso de alterações; (c) No processo de implementação de pontos de acesso wireless, regulamentados em Norma Técnica própria (NEP/NAT 02.03.06), é responsabilidade do Administrador Local: 1. Solicitar autorização e parecer técnico à DCSI; 2. Se autorizada, garantir que se cumprem as normas de implementação e exploração de pontos de a\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 36779\n",
"Documento: PAD 230-01 RGSUEOE SET22.pdf\n",
"Categoria: Outros\n",
"Score: 10.354473114013672\n",
"Texto:\n",
"Serviço nas U/E/O de relato de incidentes. c. No âmbito da infraestrutura da Rede, constituem responsabilidades do administrador da Rede local acompanhar o planeamento e a execução de trabalhos de expansão/melhoramento da Rede local, manter um cadastro atualizado das ligações físicas e lógicas de todos os equipamentos de Rede existentes na U/E/O e colaborar com a entidade técnica gestora da Rede d\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 45908\n",
"Documento: (REVOGADA) NAT 02.03.04 - Normas Tecnicas e procedimentos do Admin da Rede Local das UEO14JAN2014_ocr.pdf\n",
"Categoria: Outros\n",
"Score: 10.440067291259766\n",
"Texto:\n",
"Z LL DCSI NAT 02.03.04 | Pág. .2de58Pág. | ÂMBITO A presente norma destina-se a ser do conhecimento de todos os Administradores de Rede Local e outros elementos que, por força da necessidade ou por nomeação superior, tenham necessidade de executar tarefas e aceder, quer de forma física quer lógica, às redes e sistemas do SIC-Op, presentes na sua U/E/O, SITUAÇÃO a. O alto nível de informatização do\n",
"--------------------------------------------------------------------------------\n",
"\n",
"Resultado 45912\n",
"Documento: (REVOGADA) NAT 02.03.04 - Normas Tecnicas e procedimentos do Admin da Rede Local das UEO14JAN2014_ocr.pdf\n",
"Categoria: Outros\n",
"Score: 10.764945983886719\n",
"Texto:\n",
"Local (1) É da responsabilidade do Comandante/Diretor/Chefe da U/E/O a nomeação do Administrador de Rede Local e, eventualmente, um adjunto; (2) A nomeação deverá recair sobre graduados, sempre que possível do QP, habilitados com conhecimentos técnicos de administração e segurança de redes, por forma a\n",
"--------------------------------------------------------------------------------\n"
]
}
],
"source": [
"testar_perguntas(\n",
" perguntas_teste,\n",
" modelo_embeddings,\n",
" index,\n",
" dataset_chunks,\n",
" top_k=5\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "cf65854e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"====================================================================================================\n",
"PERGUNTA: Quais são as normas sobre segurança da informação?\n",
"\n",
"--- PROMPT PARA O QWEN ---\n",
"\n",
"\n",
"Responde à pergunta com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"Quais são as normas sobre segurança da informação?\n",
"\n",
"Contexto:\n",
"[Documento: PAD 230-01 RGSUEOE SET22.pdf | Categoria: Outros]\n",
"ança do Pessoal; (3) Segurança física; (4) Segurança das CSI. d. As medidas da segurança da informação situam-se no âmbito da segurança da informação classificada, no tratamento e manuseamento das mesmas e englobam: (1) Credenciação adequada à função e válida; (2) Classificação de segurança da informação; (3) Classificação do documento; (4) Preparação do documento classificado; (5) Reclassificação e desclassificação do documento; (6) Reprodução do documento classificado; (7) Transferência da informação classificada; (8) Registo e controlo de segurança da informação classificada; (9) Destruição e evacuação da informação classificada. e. A segurança do Pessoal traduz-se, de acordo com as ISM, no acesso regular e no acesso excecional a informação classificada, nomeadamente: (1) Na credenciação do Pessoal nas várias Marcas e Graus; (2) No acompanhamento de alterações de atitude ou comportamentos suspeitos que ponham em causa a idoneidade do Pessoal;\n",
"\n",
"---\n",
"\n",
"[Documento: PAD 230-01 RGSUEOE SET22.pdf | Categoria: Outros]\n",
"o e do acesso à Informação classificada, em estrita observância do princípio da “necessidade de conhecer”. i. A segurança física deve ser implementada segundo o princípio da defesa em profundidade, recorrendo a um conjunto de medidas complementares nas restantes áreas da segur\n",
"\n",
"====================================================================================================\n",
"PERGUNTA: O que é uma NEP?\n",
"\n",
"--- PROMPT PARA O QWEN ---\n",
"\n",
"\n",
"Responde à pergunta com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"O que é uma NEP?\n",
"\n",
"Contexto:\n",
"[Documento: RA2012.pdf | Categoria: Outros]\n",
"nto;\n",
"\n",
"---\n",
"\n",
"[Documento: NEP AGE.122_ocr.pdf | Categoria: Outros]\n",
".o 231/2009, de 15 setembro, que estabelece que o Comando de Pessoal é Orgão Central de Administração e Direção (OCAD), cabendo-lhe assegurar a superintendência e a execução em áreas ou atividades específicas essenciais. b. A presente NEP aplica-se a todos os trabalhadores da área da saúde, vinculados em regime de trabalho em funções públicas e integrados nas respetivas carreiras, que pretendam a sua actualização ou aperfeiçoamento profissional. 3. INTRODUÇÃO a. É facultado aos trabalhadores da área de saúde a frequência de ações de formação complementar específica da respetiva área profissional. Essas formações podem incluir participações em Cursos, Congressos, Seminários, Encontros, Estágios, Jornadas, Simpósios e outras atividades similares. b. Tais eventos encontram cobertura legal nos seguintes diplomas: (1) Decreto-Lei no 177/2009 de 04Ago, estabelece o regime da carreira especial médica, aplicável aos médicos cuja relação jurídica de emprego público seja constituída por contrato de trabalho em funções públicas, no no 3 do Art.o 25o, permite a frequência de cursos de formação complementar ou de actualização profissional, com vista ao aperfeiçoamento, que pode ser autorizado m\n",
"\n",
"---\n",
"\n",
"[Documento: PDE 4-46-00.pdf | Categoria: Outros]\n",
"ma casuística e não integrada, Direti\n",
"\n",
"====================================================================================================\n",
"PERGUNTA: Que documento fala sobre redes sociais?\n",
"\n",
"--- PROMPT PARA O QWEN ---\n",
"\n",
"\n",
"Responde à pergunta com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"Que documento fala sobre redes sociais?\n",
"\n",
"Contexto:\n",
"[Documento: PEMGFA_GER_006_GUIA DO ADIDO DE DEFESA.pdf | Categoria: Outros]\n",
"PEMGFA/GER 006 CAPÍTULO 12 COMUNICAÇÃO INSTITUCIONAL 1201. REDES SOCIAIS Atualmente as redes sociais fazem parte do dia-a-dia das pessoas e das organizações em todo o planeta. Com o crescimento do Facebook, Instagram, Twitter, etc permitindo acessos por computadores e também por tecnologias móveis como telefones, tablets, IPhones, etc é pois uma incontornável realidade. Para que possamos capitalizar no uso das redes sociais, no que se refere às atividades dos militares das Forças Armadas Portuguesas nas mais diversas missões, os Adidos de Defesa devem enviar ao GLADM propostas de publicações, desejavelmente com fotografias, sempre que as circunstâncias forem consideradas relevantes, oportunas ou convenientes, designadamente, artigos alusivos às atividades protocolares, seminários, visitas de altas entidades nacionais e estrangeiras. 1202. USO DO CORREIO ELETRÓNICO a. Nota introdutória A melhor forma de comunicar com alguém é presencialmente. Mais de 70% da mensagem que pretendemos transmitir advém da nossa linguagem não-verbal. Os restantes 30% são naturalmente provenientes da nossa expressão oral (tom, intensidade e volume). Contudo, a comunicação escrita, em detrimento de um enco\n",
"\n",
"---\n",
"\n",
"[Documento: Livro_VDS2018_definitivo_RCAN.pdf | Categoria: Outros]\n",
"Moqbel, 2012). Segundo Ellis\n",
"\n",
"====================================================================================================\n",
"PERGUNTA: Quais são os procedimentos do interrogatório?\n",
"\n",
"--- PROMPT PARA O QWEN ---\n",
"\n",
"\n",
"Responde à pergunta com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"Quais são os procedimentos do interrogatório?\n",
"\n",
"Contexto:\n",
"[Documento: E0202A1P_Esp 028 - I Armas Pesadas Morteiros CFS.pdf | Categoria: Outros]\n",
"o dos procedimentos - Supervisão\n",
"\n",
"---\n",
"\n",
"[Documento: MD 240-03_Modelo de Referencial de Curso.pdf | Categoria: Outros]\n",
"de recolha e análise de dados. (a) O procedimento metodológico, explica os passos inerentes aos processos de avaliação descrevendo quando e como se vai realizar a avaliação. A metodologia e instrumentos de recolha da informação nas fontes acima indicadas podem ser: 1 Testes. 2 Circuitos de Avaliação. 3 Observação direta. 4 Questionários. 5 Relatórios. 6-3\n",
"\n",
"---\n",
"\n",
"[Documento: PTE 005 01 Auditoria de Abonos e Descontos.pdf | Categoria: Outros]\n",
"CAPÍTULO 3 O PROCESSO DE AUDITORIA 301. Fases do processo de auditoria O Processo de auditoria contempla as quatro fases a seguir apresentadas. FASES DA AUDITORIA Compreensão dos processos, das entidades intervenientes e do meio Planeamento envolvente através do desenvolvimento do Estudo Preliminar. Avaliação do risco e elaboração do Programa de Auditoria. Avaliação do controlo interno e dos procedimentos, obtenção e Execução avaliação das evidências de auditoria e estabelecimento das Observações e Conclusões Preliminares. Escrituração das observações e opiniões, formulação de Relato recomendações e elaboração do Relatório de Auditoria. Acompanhamento do acolhimento das recomendações e Seguimento eventualmente a r\n",
"\n",
"====================================================================================================\n",
"PERGUNTA: Que regras existem sobre administração de rede local?\n",
"\n",
"--- PROMPT PARA O QWEN ---\n",
"\n",
"\n",
"Responde à pergunta com base apenas no contexto fornecido.\n",
"\n",
"Pergunta:\n",
"Que regras existem sobre administração de rede local?\n",
"\n",
"Contexto:\n",
"[Documento: PAD 230-01 RGSUEOE SET22.pdf | Categoria: Outros]\n",
"tação das NAT nesta área, emanadas pela respetiva entidade competente. 356. Competências do administrador de Rede local a. A tarefa principal do administrador de Rede local é gerir os sistemas informáticos locais, de acordo com as Normas em vigor no Exército e em estreita coordenação com a entidade competente do Exército para esta matéria. b. É dever do administrador de Rede local cumprir e divulgar as Normas técnicas bem como sensibilizar de forma permanente os utilizadores para os aspetos de segurança da informação e de operação dos meios e sistemas de informação: cuidados com o equipamento, manuseamento de matérias classificadas, políticas de segurança, sistema\n",
"\n",
"---\n",
"\n",
"[Documento: (REVOGADA) NAT 02.03.04 - Normas Tecnicas e procedimentos do Admin da Rede Local das UEO14JAN2014_ocr.pdf | Categoria: Outros]\n",
"istentes na U/E/O e fornece-lo ao CTE, sempre que solicitado ou em caso de alterações; (c) No processo de implementação de pontos de acesso wireless, regulamentados em Norma Técnica própria (NEP/NAT 02.03.06), é responsabilidade do Administrador Local: 1. Solicitar autorização e parecer técnico à DCSI; 2. Se autorizada, garantir que se cumprem as normas de implementação e exploração de pontos de acesso wireless, (3) No âmbito da configuração de equipamentos ligados ao domínio exe\n"
]
}
],
"source": [
"for pergunta in perguntas_teste:\n",
" print(\"\\n\" + \"=\"*100)\n",
" print(\"PERGUNTA:\", pergunta)\n",
" \n",
" prompt, resultados = preparar_rag(\n",
" query=pergunta,\n",
" modelo_embeddings=modelo_embeddings,\n",
" index=index,\n",
" dataset_chunks=dataset_chunks,\n",
" top_k=5\n",
" )\n",
" \n",
" print(\"\\n--- PROMPT PARA O QWEN ---\\n\")\n",
" print(prompt[:1500])"
]
},
{
"cell_type": "markdown",
"id": "b1c79d02",
"metadata": {},
"source": [
"Meter meter os ficheiros na indice_documentos.faiss dataset_chunks.json mesma pasta do app.py (que vai funcionar como backend do nosso \"Chat\"), no meu caso eu crei um pasta denominada [Modelos_bot_exercito](D:\\Trabalhos\\Modelos_bot_exercito) mas o idela é estar na mesma pasta"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.14.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}