beriond's picture
Update app.py
9fb64d0 verified
Raw History Blame Contribute Delete
4.66 kB
import gradio as gr
from transformers import pipeline
from langchain_community.llms import HuggingFacePipeline
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import PyMuPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
import os
from huggingface_hub import login
# --- Configurações Iniciais ---
DOC_PATH = "meu-documento.pdf"
MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.3"
# 🔑 Autenticação no Hugging Face Hub
huggingface_token = os.getenv("HUGGINGFACE_TOKEN")
if huggingface_token:
try:
print("Tentando fazer login no Hugging Face Hub...")
login(token=huggingface_token)
print("Login bem-sucedido.")
except Exception as e:
print(f"Erro no login do Hugging Face: {e}")
else:
print("Aviso: Variável de ambiente HUGGINGFACE_TOKEN não encontrada. O carregamento do modelo pode falhar.")
# 🔁 Carrega e processa o PDF
def carregar_documento_pdf(path):
if not os.path.exists(path):
print(f"Erro: O arquivo {path} não foi encontrado.")
return None
loader = PyMuPDFLoader(path)
documentos = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=256,
chunk_overlap=100,
separators=["\n\n", "\n", ".", " "]
)
documentos_divididos = splitter.split_documents(documentos)
embeddings = HuggingFaceEmbeddings(model_name="intfloat/e5-base-v2")
vectorstore = FAISS.from_documents(documentos_divididos, embeddings)
return vectorstore
# ⚙️ Configura o pipeline com o modelo Mistral
try:
pipe = pipeline(
"text-generation",
model=MODEL_NAME,
max_new_tokens=256,
temperature=0.7,
do_sample=True
)
llm = HuggingFacePipeline(pipeline=pipe)
except Exception as e:
print(f"Erro ao carregar o modelo HuggingFace: {e}")
llm = None
# 🧠 Memória da conversação
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True, k=3)
# 📄 Indexação do documento
vectorstore = carregar_documento_pdf(DOC_PATH)
# 🧾 Prompt otimizado para respostas claras
custom_prompt = PromptTemplate.from_template("""
Você é um assistente técnico que responde com base **apenas** no documento fornecido.
Sempre use o idioma Português do Brasil para responder.
Contexto:{context}
Pergunta: {question}
Resposta:""")
# 🔗 Cadeia RAG com memória e prompt
chat_chain = None
if llm and vectorstore:
chat_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
memory=memory,
combine_docs_chain_kwargs={"prompt": custom_prompt}
)
# 💬 Interface Gradio
with gr.Blocks() as demo:
gr.Markdown("## 🤖💼 CS Search Engine")
chatbot = gr.Chatbot(label="Assistente Técnico")
with gr.Row():
entrada = gr.Textbox(
placeholder="Pergunte sobre os projetos do documento...",
show_label=False,
container=False,
)
enviar_btn = gr.Button("Enviar")
def interagir(msg, history):
if not chat_chain:
history.append((msg, "Erro: A cadeia de chat não foi inicializada."))
return "", history
try:
resposta_completa = chat_chain.invoke({"question": msg})
resposta_texto_bruto = resposta_completa['answer']
# --- Correção para remover o prompt duplicado (Opção 1) ---
# Procura a string "Resposta:" para extrair apenas a parte desejada
partes = resposta_texto_bruto.split("Resposta:")
if len(partes) > 1:
# Pega a parte do texto após "Resposta:" e remove espaços em branco extras
resposta_texto = partes[1].strip()
else:
# Se não encontrar "Resposta:", usa a resposta bruta
resposta_texto = resposta_texto_bruto
# --- Fim da correção ---
except Exception as e:
resposta_texto = f"Erro ao gerar resposta: {e}"
history.append((msg, resposta_texto))
return "", history
entrada.submit(interagir, [entrada, chatbot], [entrada, chatbot])
enviar_btn.click(interagir, [entrada, chatbot], [entrada, chatbot])
demo.launch(server_name="0.0.0.0", server_port=7860, show_api=False)