caarleexx commited on
Commit
3654c3e
·
verified ·
1 Parent(s): 9456eeb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +23 -21
app.py CHANGED
@@ -2,7 +2,8 @@
2
 
3
  import streamlit as st
4
  import time
5
- import os # Importado para manipulação de arquivos temporários
 
6
 
7
  # --- IMPORTS GROQ ---
8
  from groq import Groq
@@ -11,7 +12,7 @@ from groq import Groq
11
  from langchain_community.document_loaders import TextLoader
12
  from langchain_community.document_loaders import PyPDFLoader
13
  from langchain_text_splitters import RecursiveCharacterTextSplitter
14
- from langchain_huggingface import HuggingFaceEmbeddings # Embeddings que rodam na CPU
15
  from langchain_community.vectorstores import FAISS
16
  from langchain.chains import RetrievalQA
17
  from langchain_groq import ChatGroq
@@ -43,7 +44,7 @@ st.markdown("""
43
  [data-testid="stChatMessage"] {
44
  padding-left: 0px;
45
  padding-right: 0px;
46
- gap: 0.0rem !important; /* Força a remoção do gap entre o avatar (agora zero) e o texto */
47
  }
48
 
49
  /* Mantém a justificação do texto e garante a largura total para o conteúdo da mensagem */
@@ -66,19 +67,16 @@ st.markdown("""
66
  """, unsafe_allow_html=True)
67
 
68
  st.title("Iza - Assistente com Groq RAG 🚀")
69
- st.caption("Um chatbot com memória, upload de arquivos e controle de velocidade. Integração com LangChain RAG.")
70
 
71
  # 3. Configuração do Cliente Groq
72
- # Cliente Groq padrão para chamadas com Tool Use
73
  client = Groq()
74
- # Cliente Groq para uso dentro do LangChain
75
  groq_llm = ChatGroq(model_name="mixtral-8x7b-32768", temperature=0.7)
76
 
77
  # 2. Barra Lateral e Lógica de Upload/Processamento RAG
78
  with st.sidebar:
79
  st.header("Opções")
80
 
81
- # Inicializa variáveis de sessão para RAG
82
  if 'retriever' not in st.session_state:
83
  st.session_state.retriever = None
84
  st.session_state.retriever_source = None
@@ -94,16 +92,16 @@ with st.sidebar:
94
  # Apenas processa se o arquivo for novo
95
  if st.session_state.retriever_source != uploaded_file.name:
96
 
97
- file_path = f"./temp_file_{uploaded_file.name.replace('/', '_')}"
 
 
 
98
 
99
  try:
100
- # 1. SALVAR/LER ARQUIVO TEMPORARIAMENTE
101
- bytes_data = uploaded_file.read()
102
- with open(file_path, "wb") as f:
103
- f.write(bytes_data)
104
-
105
  # 2. CONFIGURAÇÃO RAG (Processo de Embedding)
106
- with st.spinner(f"Processando '{uploaded_file.name}' com LangChain e HuggingFace Embeddings (CPU)..."):
 
 
107
 
108
  # Carregamento do Documento
109
  if uploaded_file.type == 'application/pdf':
@@ -114,11 +112,17 @@ with st.sidebar:
114
  raise ValueError("Tipo de arquivo não suportado após o upload.")
115
 
116
  documents = loader.load()
 
 
117
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
118
  texts = text_splitter.split_documents(documents)
119
 
120
  # HuggingFace Embeddings (Roda na CPU)
 
121
  embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
 
 
 
122
  vectorstore = FAISS.from_documents(texts, embeddings)
123
 
124
  # Armazenar na sessão
@@ -129,9 +133,9 @@ with st.sidebar:
129
  except Exception as e:
130
  # Tratamento de erro 403 e outros
131
  if "403" in str(e):
132
- st.error("Erro no upload (403 Forbidden). O servidor está rejeitando a requisição. Tente com um arquivo menor ou execute localmente.")
133
  else:
134
- st.error(f"Erro ao processar o arquivo com LangChain: {e}")
135
 
136
  st.session_state.retriever = None
137
  st.session_state.retriever_source = None
@@ -141,11 +145,9 @@ with st.sidebar:
141
  os.remove(file_path)
142
 
143
  else:
144
- # Se o arquivo já foi processado
145
  st.info(f"O arquivo '{st.session_state.retriever_source}' já foi processado e está ativo.")
146
 
147
  elif st.session_state.retriever_source is not None:
148
- # Limpa se o uploader foi esvaziado, mas o retriever estava ativo
149
  st.warning("O arquivo processado foi removido. A IA voltará a usar pesquisa web.")
150
  st.session_state.retriever = None
151
  st.session_state.retriever_source = None
@@ -191,7 +193,7 @@ if prompt := st.chat_input("Pergunte algo sobre o documento ou faça uma pesquis
191
  return_source_documents=False
192
  )
193
 
194
- # OBS: A resposta RAG vem completa (sem streaming simples)
195
  with st.spinner("Buscando no documento e gerando resposta..."):
196
  result = qa_chain.invoke({"query": prompt})
197
  full_response = result['result']
@@ -199,7 +201,7 @@ if prompt := st.chat_input("Pergunte algo sobre o documento ou faça uma pesquis
199
  else:
200
  # GROQ DIRETO: Caso NÃO haja arquivo (usa Tool Use para pesquisa web).
201
  stream = client.chat.completions.create(
202
- model="groq/compound", # Modelo com Compound para Tool Use
203
  messages=[
204
  {"role": m["role"], "content": m["content"]}
205
  for m in st.session_state.messages
@@ -216,7 +218,7 @@ if prompt := st.chat_input("Pergunte algo sobre o documento ou faça uma pesquis
216
  placeholder.markdown(full_response + "▌")
217
  time.sleep(0.005)
218
 
219
- # Exibe a resposta completa (do RAG ou do Streaming)
220
  placeholder.markdown(full_response)
221
 
222
  # 6c. Adiciona a resposta completa ao histórico
 
2
 
3
  import streamlit as st
4
  import time
5
+ import os
6
+ import tempfile # <--- NOVO: Para criar diretórios temporários seguros
7
 
8
  # --- IMPORTS GROQ ---
9
  from groq import Groq
 
12
  from langchain_community.document_loaders import TextLoader
13
  from langchain_community.document_loaders import PyPDFLoader
14
  from langchain_text_splitters import RecursiveCharacterTextSplitter
15
+ from langchain_huggingface import HuggingFaceEmbeddings
16
  from langchain_community.vectorstores import FAISS
17
  from langchain.chains import RetrievalQA
18
  from langchain_groq import ChatGroq
 
44
  [data-testid="stChatMessage"] {
45
  padding-left: 0px;
46
  padding-right: 0px;
47
+ gap: 0.0rem !important;
48
  }
49
 
50
  /* Mantém a justificação do texto e garante a largura total para o conteúdo da mensagem */
 
67
  """, unsafe_allow_html=True)
68
 
69
  st.title("Iza - Assistente com Groq RAG 🚀")
70
+ st.caption("Um chatbot com memória, upload de arquivos, LangChain RAG e controle de velocidade.")
71
 
72
  # 3. Configuração do Cliente Groq
 
73
  client = Groq()
 
74
  groq_llm = ChatGroq(model_name="mixtral-8x7b-32768", temperature=0.7)
75
 
76
  # 2. Barra Lateral e Lógica de Upload/Processamento RAG
77
  with st.sidebar:
78
  st.header("Opções")
79
 
 
80
  if 'retriever' not in st.session_state:
81
  st.session_state.retriever = None
82
  st.session_state.retriever_source = None
 
92
  # Apenas processa se o arquivo for novo
93
  if st.session_state.retriever_source != uploaded_file.name:
94
 
95
+ # --- USO DO DIRETÓRIO TEMPORÁRIO ---
96
+ with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{uploaded_file.name}") as tmp_file:
97
+ tmp_file.write(uploaded_file.read())
98
+ file_path = tmp_file.name
99
 
100
  try:
 
 
 
 
 
101
  # 2. CONFIGURAÇÃO RAG (Processo de Embedding)
102
+ with st.spinner(f"Processando '{uploaded_file.name}' com LangChain..."):
103
+
104
+ st.info("Passo 1/4: Salvando arquivo temporariamente.")
105
 
106
  # Carregamento do Documento
107
  if uploaded_file.type == 'application/pdf':
 
112
  raise ValueError("Tipo de arquivo não suportado após o upload.")
113
 
114
  documents = loader.load()
115
+ st.info("Passo 2/4: Fragmentando o texto do documento.")
116
+
117
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
118
  texts = text_splitter.split_documents(documents)
119
 
120
  # HuggingFace Embeddings (Roda na CPU)
121
+ st.info("Passo 3/4: Criando Embeddings (vetores) com HuggingFace.")
122
  embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
123
+
124
+ # Criar o Vector Store (FAISS)
125
+ st.info("Passo 4/4: Criando o Vector Store (FAISS) para busca rápida.")
126
  vectorstore = FAISS.from_documents(texts, embeddings)
127
 
128
  # Armazenar na sessão
 
133
  except Exception as e:
134
  # Tratamento de erro 403 e outros
135
  if "403" in str(e):
136
+ st.error("Erro no upload (403 Forbidden). O servidor de deploy está rejeitando a requisição.")
137
  else:
138
+ st.error(f"Erro ao processar o arquivo: {e}")
139
 
140
  st.session_state.retriever = None
141
  st.session_state.retriever_source = None
 
145
  os.remove(file_path)
146
 
147
  else:
 
148
  st.info(f"O arquivo '{st.session_state.retriever_source}' já foi processado e está ativo.")
149
 
150
  elif st.session_state.retriever_source is not None:
 
151
  st.warning("O arquivo processado foi removido. A IA voltará a usar pesquisa web.")
152
  st.session_state.retriever = None
153
  st.session_state.retriever_source = None
 
193
  return_source_documents=False
194
  )
195
 
196
+ # Resposta RAG
197
  with st.spinner("Buscando no documento e gerando resposta..."):
198
  result = qa_chain.invoke({"query": prompt})
199
  full_response = result['result']
 
201
  else:
202
  # GROQ DIRETO: Caso NÃO haja arquivo (usa Tool Use para pesquisa web).
203
  stream = client.chat.completions.create(
204
+ model="groq/compound",
205
  messages=[
206
  {"role": m["role"], "content": m["content"]}
207
  for m in st.session_state.messages
 
218
  placeholder.markdown(full_response + "▌")
219
  time.sleep(0.005)
220
 
221
+ # Exibe a resposta completa
222
  placeholder.markdown(full_response)
223
 
224
  # 6c. Adiciona a resposta completa ao histórico