|
import os |
|
import yaml |
|
import gradio as gr |
|
from langchain_huggingface import ChatHuggingFace |
|
from langchain_huggingface.llms.huggingface_endpoint import HuggingFaceEndpoint |
|
from langchain_community.vectorstores import FAISS |
|
from langchain.chains import RetrievalQA |
|
from langchain_huggingface.embeddings import HuggingFaceEmbeddings |
|
from langchain.prompts import PromptTemplate |
|
from langchain_community.document_loaders import WebBaseLoader |
|
from langchain_text_splitters import CharacterTextSplitter |
|
from langchain_community.vectorstores import FAISS |
|
from langchain_huggingface import HuggingFaceEmbeddings |
|
from dotenv import load_dotenv |
|
import os |
|
import logging |
|
logging.getLogger("langchain.text_splitter").setLevel(logging.ERROR) |
|
import warnings |
|
warnings.filterwarnings("ignore") |
|
from langchain_community.document_loaders import RecursiveUrlLoader |
|
import yaml |
|
|
|
|
|
CACHE_FOLDER = "./model/" |
|
LOCAL_FOLDER = "./model/" |
|
VS_BASE = "./vector_store/vs_base" |
|
|
|
os.makedirs(CACHE_FOLDER, exist_ok=True) |
|
os.makedirs(LOCAL_FOLDER, exist_ok=True) |
|
os.makedirs(VS_BASE, exist_ok=True) |
|
|
|
|
|
|
|
LLM_MODEL = 'google/gemma-3-12b-it' |
|
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2" |
|
|
|
|
|
|
|
|
|
url_list = [ |
|
"https://www.infinitepay.io", |
|
"https://www.infinitepay.io/maquininha", |
|
"https://www.infinitepay.io/maquininha-celular", |
|
"https://www.infinitepay.io/tap-to-pay", |
|
"https://www.infinitepay.io/pdv", |
|
"https://www.infinitepay.io/receba-na-hora", |
|
"https://www.infinitepay.io/gestao-de-cobranca", |
|
"https://www.infinitepay.io/gestao-de-cobranca-2", |
|
"https://www.infinitepay.io/link-de-pagamento", |
|
"https://www.infinitepay.io/loja-online", |
|
"https://www.infinitepay.io/boleto", |
|
"https://www.infinitepay.io/conta-digital", |
|
"https://www.infinitepay.io/conta-pj", |
|
"https://www.infinitepay.io/pix", |
|
"https://www.infinitepay.io/pix-parcelado", |
|
"https://www.infinitepay.io/emprestimo", |
|
"https://www.infinitepay.io/cartao", |
|
"https://www.infinitepay.io/rendimento", |
|
'https://www.infinitepay.io/taxas', |
|
'https://www.cloudwalk.io/', |
|
'https://www.cloudwalk.io/#our-mission', |
|
'https://www.cloudwalk.io/#our-pillars', |
|
'https://www.cloudwalk.io/#our-products', |
|
] |
|
|
|
|
|
loader = WebBaseLoader(web_paths=url_list) |
|
docs = loader.load() |
|
|
|
|
|
text_splitter = CharacterTextSplitter(chunk_size=1500, chunk_overlap=100) |
|
split_docs = text_splitter.split_documents(docs) |
|
embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL) |
|
vector_store = FAISS.from_documents(split_docs, embeddings) |
|
os.makedirs(VS_BASE, exist_ok=True) |
|
vector_store.save_local(VS_BASE) |
|
print(f"vs_base salva em {VS_BASE}") |
|
|
|
|
|
HF_TOKEN = os.getenv("HF_TOKEN") |
|
if not HF_TOKEN: |
|
raise ValueError("HF_TOKEN não encontrado. Por favor, defina-o nos segredos do Hugging Face Space.") |
|
|
|
os.environ["HF_HUB_USER_AGENT"] = "CloudWalk_Chatbot" |
|
|
|
|
|
llm = HuggingFaceEndpoint( |
|
repo_id=LLM_MODEL, |
|
task="text-generation", |
|
max_new_tokens=1024, |
|
do_sample=False, |
|
repetition_penalty=1.03, |
|
huggingfacehub_api_token=HF_TOKEN, |
|
) |
|
|
|
chat_model = ChatHuggingFace(llm=llm) |
|
|
|
|
|
embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL) |
|
|
|
|
|
vector_store_path = './vector_store/vs_base/' |
|
try: |
|
faiss_store = FAISS.load_local(vector_store_path, embeddings, allow_dangerous_deserialization=True) |
|
except Exception as e: |
|
print(f"Erro ao carregar a vector store FAISS: {e}") |
|
print("Verifique se o caminho está correto e se o arquivo não está corrompido.") |
|
exit() |
|
|
|
|
|
retriever = faiss_store.as_retriever(search_type="similarity", search_kwargs={"k": 10}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
custom_prompt_template = """ |
|
You are a useful chatbot for customer service. |
|
If you don't know the answer, just say that you don't know, don't try to make up an answer. |
|
ALWAYS RESPONDE IN THE SAME LANGUAGE AS THE INPUT. |
|
|
|
Use the following pieces of context to answer the user's question. |
|
{context} |
|
|
|
Question: {question} |
|
Helpful Answer:""" |
|
|
|
|
|
QA_CHAIN_PROMPT = PromptTemplate.from_template(custom_prompt_template) |
|
|
|
|
|
qa_chain = RetrievalQA.from_chain_type( |
|
llm=chat_model, |
|
chain_type="stuff", |
|
retriever=retriever, |
|
return_source_documents=True, |
|
chain_type_kwargs={"prompt": QA_CHAIN_PROMPT} |
|
) |
|
|
|
|
|
def chat_response(question: str, history: list): |
|
""" |
|
Gera a resposta do chatbot usando o modelo de QA e formata para exibição no Gradio. |
|
|
|
Args: |
|
question (str): A pergunta do usuário. |
|
history (list): Histórico de conversas (não usado diretamente aqui, mas necessário para a interface). |
|
|
|
Returns: |
|
str: A resposta formatada do chatbot, incluindo as fontes. |
|
""" |
|
print(f"Recebida pergunta: '{question}'") |
|
|
|
try: |
|
result = qa_chain.invoke({"query": question}) |
|
answer = result["result"] |
|
sources = result.get("source_documents", []) |
|
|
|
response_text = f"**Resposta:** {answer}\n\n" |
|
|
|
if sources: |
|
response_text += "**Saiba mais em:**\n" |
|
unique_sources = set() |
|
source_list_for_printing = [] |
|
|
|
for doc in sources: |
|
source_name = doc.metadata.get('source', 'Fonte desconhecida') |
|
if source_name not in unique_sources: |
|
unique_sources.add(source_name) |
|
source_list_for_printing.append(source_name) |
|
|
|
for i, source_name in enumerate(source_list_for_printing): |
|
response_text += f"- {i+1}. '{source_name}'\n" |
|
else: |
|
response_text += "Nenhuma fonte específica foi utilizada para esta resposta.\n" |
|
|
|
return response_text |
|
|
|
except Exception as e: |
|
error_message = f"Ocorreu um erro ao processar sua pergunta: {e}. Por favor, tente novamente." |
|
print(error_message) |
|
return error_message |
|
|
|
|
|
if __name__ == "__main__": |
|
print("Iniciando a interface Gradio...") |
|
demo = gr.ChatInterface( |
|
type="messages", |
|
fn=chat_response, |
|
title="CloudWalk Chatbot", |
|
description="Olá! Estou aqui para responder suas dúvidas.", |
|
submit_btn="Enviar Pergunta", |
|
examples=[ |
|
|
|
|
|
|
|
["Quais serviços a infinite pay oferece?"], |
|
["Quais as taxas da maquininha?"], |
|
["Como pedir uma maquininha?"], |
|
], |
|
chatbot=gr.Chatbot(type="messages") |
|
) |
|
demo.launch() |