File size: 5,443 Bytes
c4d30ac |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
import ollama
import faiss
import gradio as gr
import numpy as np
import os
import glob
print("Inicializando...")
# Função para carregar e processar o conhecimento
def inicializar_rag():
"""Inicializa o modelo de embeddings, documentos e índice FAISS a partir dos arquivos de capítulo."""
# Diretório onde os arquivos de capítulo estão localizados
diretorio_rag = r".\RAG"
# Padrão para encontrar arquivos como b1.txt, b2.txt, ..., s1.txt, ..., d1.txt, ..., e1.txt, etc.
padrao_arquivos = os.path.join(diretorio_rag, "[bsde][1-9].txt")
caminhos_arquivos = glob.glob(padrao_arquivos)
documentos = []
# Carrega e processa cada arquivo de capítulo
for caminho in caminhos_arquivos:
if os.path.exists(caminho):
with open(caminho, "r", encoding="utf-8") as f:
# Divide em parágrafos (mantendo o separador original do código)
conteudo = f.read().split("\n\n")
documentos.extend(conteudo)
else:
print(f"Arquivo não encontrado: {caminho}")
if not documentos:
raise ValueError("Nenhum documento foi carregado. Verifique os caminhos dos arquivos.")
print(f"Trabalhando em {len(documentos)} documentos ...")
# Gera embeddings usando o Ollama
embeddings = []
for index, doc in enumerate(documentos):
if index % 200 == 0:
print(f"= = = {index} Embeddings... = = =")
# nomic-embed-text é um modelo para parágrafos mais longos
response = ollama.embed(model="nomic-embed-text", input=doc)
if index % 200 == 0:
print(f"Response: {response}")
embeddings.append(response["embeddings"][0]) # Acessa o embedding gerado
print(f"Trabalhando em {len(embeddings)} embeddings...")
embeddings = np.array(embeddings, dtype=np.float32) # Converte para numpy array
# Cria o índice FAISS
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(embeddings)
return documentos, index
# Função para buscar contexto relevante
def buscar_contexto(pergunta, documentos, index, k=5):
"""Busca os k documentos mais relevantes para a pergunta."""
# Gera embedding para a pergunta usando o Ollama
response = ollama.embed(model="nomic-embed-text", input=pergunta)
query_embedding = np.array([response["embeddings"][0]], dtype=np.float32)
# Busca no índice FAISS
D, I = index.search(query_embedding, k)
return [documentos[i] for i in I[0]]
# Função para gerar resposta com o Ollama
def gerar_resposta(frase_entrada, documentos, index):
"""Gera uma resposta baseada no contexto recuperado."""
contexto = buscar_contexto(frase_entrada, documentos, index)
contexto_str = "\n".join(contexto)
# Prompt com instruções detalhadas sobre CIF
prompt = f"""
1. Identifique o **conceito significativo** da frase "XXXXXX", ou seja, o propósito ou a ideia central que ela expressa, independentemente de ser uma pergunta ou uma afirmação.
2. Para determinar a vinculação de um termo específico com a Classificação Internacional de Funcionalidade (CIF), segundo Cieza et al., 2016, siga as diretrizes a seguir:
3. Identifique se o termo pertence ao universo da CIF, de acordo com o documento anexado:
- Se o termo é mencionado no arquivo anexado, anote isso.
- Se o termo não aparece no arquivo anexado, classifique como "Não coberto."
4. Verifique a relação do termo com os componentes da CIF:
- Funções Corporais: Se o termo se relaciona com códigos iniciados pela letra “b”
- Estruturas Corporais: Se o termo se relaciona com códigos iniciados pela letra “s”
- Atividades e Participação: Se o termo se relaciona com códigos iniciados pela letra “d”
- Fatores Ambientais: Se o termo se relaciona com códigos iniciados pela letra “e”
5. Classifique o termo: Se o termo for mencionado na CIF e tiver vínculo com um dos componentes acima, identifique qual categoria ele pertence.
Se o termo for mencionado na CIF, mas não tiver vínculo com nenhuma das categorias existentes, classifique como "Não Definido."
**RAG**:
{contexto_str}
**Frase**:
{frase_entrada}
**Formato da Resposta**:
- **Conceito**: [Descrição do conceito significativo]
- **Código CIF**: [Código CIF + nomeclatura]
- **Justificativa**: [Explicação baseada no RAG]
"""
resposta = ollama.generate(model="gemma3:1b", prompt=prompt)
return resposta["response"]
# Função principal para a interface Gradio
def interface_rag(frase_entrada):
"""Função chamada pela interface Gradio."""
resposta = gerar_resposta(frase_entrada, documentos, index)
return resposta
# Inicialização do RAG
print("Inicializando RAG...")
documentos, index = inicializar_rag()
# Configuração da interface Gradio
interface = gr.Interface(
fn=interface_rag,
inputs=gr.Textbox(label="Digite sua frase", placeholder="Ex.: O que é função puberal?"),
outputs=gr.Textbox(label="Resposta"),
title="Sistema RAG para CIF",
description="Pergunte algo sobre Funções Corporais, Estruturas Corporais, Atividades e Participação ou Fatores Ambientais com base na CIF.",
)
# Iniciar a interface
print("Gerando Interface...")
interface.launch()
|