leandroaraujodev commited on
Commit
3fbbebb
1 Parent(s): fa05654

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -69
app.py CHANGED
@@ -1,6 +1,16 @@
 
 
1
  import os
 
 
 
 
 
 
 
2
  import streamlit as st
3
- from llama_index.core import Settings, SimpleDirectoryReader, VectorStoreIndex, StorageContext
 
4
  from llama_index.core.storage.docstore import SimpleDocumentStore
5
  from llama_index.llms.ollama import Ollama
6
  from llama_index.embeddings.ollama import OllamaEmbedding
@@ -13,29 +23,16 @@ from llama_index.core.chat_engine import CondensePlusContextChatEngine
13
  from llama_index.retrievers.bm25 import BM25Retriever
14
  from llama_index.core.retrievers import QueryFusionRetriever
15
  from llama_index.vector_stores.chroma import ChromaVectorStore
16
- import chromadb
17
- import nest_asyncio
18
-
19
- import os
20
- from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
21
  from llama_index.llms.huggingface import HuggingFaceLLM
22
  from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
23
- from llama_index.core import Settings
24
- from typing import List, Optional
25
- from llama_index.core import PromptTemplate
26
- import torch
27
  from llama_index.embeddings.huggingface import HuggingFaceEmbedding
28
-
29
-
30
- import logging
31
- import sys
32
- from PIL import Image
33
-
34
  #Configuração da imagem da aba
35
-
36
  im = Image.open("pngegg.png")
37
  st.set_page_config(page_title = "Chatbot Carômetro", page_icon=im, layout = "wide")
38
-
39
  #Removido loop e adicionado os.makedirs
40
  os.makedirs("bm25_retriever", exist_ok=True)
41
  os.makedirs("chat_store", exist_ok=True)
@@ -43,18 +40,19 @@ os.makedirs("chroma_db", exist_ok=True)
43
  os.makedirs("documentos", exist_ok=True)
44
  os.makedirs("curadoria", exist_ok=True)
45
  os.makedirs("chroma_db_curadoria", exist_ok=True)
46
-
47
  # Configuração do Streamlit
48
  st.sidebar.title("Configuração de LLM")
49
  sidebar_option = st.sidebar.radio("Selecione o LLM", ["gpt-3.5-turbo", "NuExtract-1.5"])
 
50
  # logo_url = 'app\logos\logo-sicoob.jpg'
51
  # st.sidebar.image(logo_url)
52
  import base64
53
-
54
  #Configuração da imagem da sidebar
55
  with open("sicoob-logo.png", "rb") as f:
56
  data = base64.b64encode(f.read()).decode("utf-8")
57
-
58
  st.sidebar.markdown(
59
  f"""
60
  <div style="display:table;margin-top:-80%;margin-left:0%;">
@@ -63,8 +61,7 @@ with open("sicoob-logo.png", "rb") as f:
63
  """,
64
  unsafe_allow_html=True,
65
  )
66
-
67
-
68
  #if sidebar_option == "Ollama":
69
  # Settings.llm = Ollama(model="llama3.2:latest", request_timeout=500.0, num_gpu=1)
70
  # Settings.embed_model = OllamaEmbedding(model_name="nomic-embed-text:latest")
@@ -74,16 +71,15 @@ if sidebar_option == "gpt-3.5-turbo":
74
  Settings.llm = OpenAI(model="gpt-3.5-turbo")
75
  Settings.embed_model = OpenAIEmbedding(model_name="text-embedding-ada-002")
76
  elif sidebar_option == 'NuExtract-1.5':
77
-
78
  logging.basicConfig(stream=sys.stdout, level=logging.INFO)
79
  logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
80
-
81
  #Embedding do huggingface
82
  Settings.embed_model = HuggingFaceEmbedding(
83
- model_name="BAAI/bge-small-en-v1.5"
84
  )
85
  #Carregamento do modelo local, descomentar o modelo desejado
86
-
87
  llm = HuggingFaceLLM(
88
  context_window=2048,
89
  max_new_tokens=2048,
@@ -96,7 +92,6 @@ elif sidebar_option == 'NuExtract-1.5':
96
  # model_name="meta-llama/Meta-Llama-3-8B",
97
  model_name="numind/NuExtract-1.5",
98
  #model_name="meta-llama/Llama-3.2-3B",
99
-
100
  tokenizer_name="numind/NuExtract-1.5",
101
  device_map="auto",
102
  tokenizer_kwargs={"max_length": 512},
@@ -104,28 +99,22 @@ elif sidebar_option == 'NuExtract-1.5':
104
  model_kwargs={"torch_dtype": torch.bfloat16},
105
  )
106
  chat = [
107
-
108
- {"role": "user", "content": "Hello, how are you?"},
109
-
110
- {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
111
-
112
- {"role": "user", "content": "I'd like to show off how chat templating works!"},
113
-
114
  ]
115
-
116
  from transformers import AutoTokenizer
117
-
118
  tokenizer = AutoTokenizer.from_pretrained("numind/NuExtract-1.5")
119
-
120
  tokenizer.apply_chat_template(chat, tokenize=False)
121
-
122
-
123
  Settings.chunk_size = 512
124
  Settings.llm = llm
125
-
126
  else:
127
  raise Exception("Opção de LLM inválida!")
128
-
129
  # Diretórios configurados pelo usuário
130
  chat_store_path = os.path.join("chat_store", "chat_store.json")
131
  documents_path = os.path.join("documentos")
@@ -133,24 +122,129 @@ chroma_storage_path = os.path.join("chroma_db") # Diretório para persistência
133
  chroma_storage_path_curadoria = os.path.join("chroma_db_curadoria") # Diretório para 'curadoria'
134
  bm25_persist_path = os.path.join("bm25_retriever")
135
  curadoria_path = os.path.join("curadoria")
136
-
137
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  # Configuração de leitura de documentos
139
- documents = SimpleDirectoryReader(input_dir=documents_path).load_data()
140
-
 
 
 
 
 
 
 
141
  # Configuração do Chroma e BM25 com persistência
142
  docstore = SimpleDocumentStore()
143
  docstore.add_documents(documents)
144
-
145
  db = chromadb.PersistentClient(path=chroma_storage_path)
146
  chroma_collection = db.get_or_create_collection("dense_vectors")
147
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
148
-
149
  # Configuração do StorageContext
150
  storage_context = StorageContext.from_defaults(
151
  docstore=docstore, vector_store=vector_store
152
  )
153
-
154
  # Criação/Recarregamento do índice com embeddings
155
  if os.path.exists(chroma_storage_path):
156
  index = VectorStoreIndex.from_vector_store(vector_store)
@@ -159,10 +253,12 @@ else:
159
  RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
160
  )
161
  index = VectorStoreIndex.from_documents(
162
- documents, storage_context=storage_context, transformations=[splitter]
 
 
163
  )
164
  vector_store.persist()
165
-
166
  # Criação/Recarregamento do BM25 Retriever
167
  if os.path.exists(os.path.join(bm25_persist_path, "params.index.json")):
168
  bm25_retriever = BM25Retriever.from_persist_dir(bm25_persist_path)
@@ -174,22 +270,27 @@ else:
174
  )
175
  os.makedirs(bm25_persist_path, exist_ok=True)
176
  bm25_retriever.persist(bm25_persist_path)
177
-
178
  #Adicionado documentos na pasta curadoria, foi setado para 1200 o chunk pra receber pergunta, contexto e resposta
179
- curadoria_documents = SimpleDirectoryReader(input_dir=curadoria_path).load_data()
180
-
 
 
 
 
 
181
  curadoria_docstore = SimpleDocumentStore()
182
  curadoria_docstore.add_documents(curadoria_documents)
183
-
184
  db_curadoria = chromadb.PersistentClient(path=chroma_storage_path_curadoria)
185
  chroma_collection_curadoria = db_curadoria.get_or_create_collection("dense_vectors_curadoria")
186
  vector_store_curadoria = ChromaVectorStore(chroma_collection=chroma_collection_curadoria)
187
-
188
  # Configuração do StorageContext para 'curadoria'
189
  storage_context_curadoria = StorageContext.from_defaults(
190
  docstore=curadoria_docstore, vector_store=vector_store_curadoria
191
  )
192
-
193
  # Criação/Recarregamento do índice com embeddings para 'curadoria'
194
  if os.path.exists(chroma_storage_path_curadoria):
195
  curadoria_index = VectorStoreIndex.from_vector_store(vector_store_curadoria)
@@ -201,15 +302,15 @@ else:
201
  curadoria_documents, storage_context=storage_context_curadoria, transformations=[curadoria_splitter]
202
  )
203
  vector_store_curadoria.persist()
204
-
205
  curadoria_retriever = curadoria_index.as_retriever(similarity_top_k=2)
206
-
207
  # Combinação de Retrievers (Embeddings + BM25)
208
  vector_retriever = index.as_retriever(similarity_top_k=2)
209
  retriever = QueryFusionRetriever(
210
  [vector_retriever, bm25_retriever, curadoria_retriever],
211
  similarity_top_k=2,
212
- #num_queries=0,
213
  mode="reciprocal_rerank",
214
  use_async=True,
215
  verbose=True,
@@ -222,7 +323,7 @@ retriever = QueryFusionRetriever(
222
  "Perguntas:\n"
223
  ),
224
  )
225
-
226
  # Configuração do chat engine
227
  nest_asyncio.apply()
228
  memory = ChatMemoryBuffer.from_defaults(token_limit=3900)
@@ -239,45 +340,45 @@ chat_engine = CondensePlusContextChatEngine.from_defaults(
239
  ),
240
  verbose=True,
241
  )
242
-
243
  # Armazenamento do chat
244
  chat_store = SimpleChatStore()
245
  if os.path.exists(chat_store_path):
246
  chat_store = SimpleChatStore.from_persist_path(persist_path=chat_store_path)
247
  else:
248
  chat_store.persist(persist_path=chat_store_path)
249
-
250
  # Interface do Chatbot
251
  st.title("Chatbot Carômetro")
252
  st.write("Este chatbot pode te ajudar a conseguir informações relevantes sobre os carômetros da Sicoob.")
253
-
254
  if 'chat_history' not in st.session_state:
255
  st.session_state.chat_history = []
256
-
257
  for message in st.session_state.chat_history:
258
  role, text = message.split(":", 1)
259
  with st.chat_message(role.strip().lower()):
260
  st.write(text.strip())
261
-
262
  user_input = st.chat_input("Digite sua pergunta")
263
  if user_input:
264
  # Exibir a mensagem do usuário e adicionar ao histórico
265
  with st.chat_message('user'):
266
  st.write(user_input)
267
  st.session_state.chat_history.append(f"user: {user_input}")
268
-
269
  # Placeholder para a mensagem do assistente
270
  with st.chat_message('assistant'):
271
  message_placeholder = st.empty()
272
  assistant_message = ''
273
-
274
  # Obter a resposta em streaming do chat_engine
275
  response = chat_engine.stream_chat(user_input)
276
  for token in response.response_gen:
277
  assistant_message += token
278
  # Atualizar o placeholder da mensagem
279
  message_placeholder.markdown(assistant_message + "▌")
280
-
281
  # Remover o cursor após a conclusão
282
  message_placeholder.markdown(assistant_message)
283
  st.session_state.chat_history.append(f"assistant: {assistant_message}")
 
1
+ import logging
2
+ import sys
3
  import os
4
+ import re
5
+ import base64
6
+ import nest_asyncio
7
+ import pandas as pd
8
+ from pathlib import Path
9
+ from typing import Any, Dict, List, Optional
10
+ from PIL import Image
11
  import streamlit as st
12
+ import torch
13
+ from llama_index.core import Settings, SimpleDirectoryReader, StorageContext, Document
14
  from llama_index.core.storage.docstore import SimpleDocumentStore
15
  from llama_index.llms.ollama import Ollama
16
  from llama_index.embeddings.ollama import OllamaEmbedding
 
23
  from llama_index.retrievers.bm25 import BM25Retriever
24
  from llama_index.core.retrievers import QueryFusionRetriever
25
  from llama_index.vector_stores.chroma import ChromaVectorStore
26
+ from llama_index.core import VectorStoreIndex
 
 
 
 
27
  from llama_index.llms.huggingface import HuggingFaceLLM
28
  from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
 
 
 
 
29
  from llama_index.embeddings.huggingface import HuggingFaceEmbedding
30
+ import chromadb
31
+
 
 
 
 
32
  #Configuração da imagem da aba
 
33
  im = Image.open("pngegg.png")
34
  st.set_page_config(page_title = "Chatbot Carômetro", page_icon=im, layout = "wide")
35
+
36
  #Removido loop e adicionado os.makedirs
37
  os.makedirs("bm25_retriever", exist_ok=True)
38
  os.makedirs("chat_store", exist_ok=True)
 
40
  os.makedirs("documentos", exist_ok=True)
41
  os.makedirs("curadoria", exist_ok=True)
42
  os.makedirs("chroma_db_curadoria", exist_ok=True)
43
+
44
  # Configuração do Streamlit
45
  st.sidebar.title("Configuração de LLM")
46
  sidebar_option = st.sidebar.radio("Selecione o LLM", ["gpt-3.5-turbo", "NuExtract-1.5"])
47
+
48
  # logo_url = 'app\logos\logo-sicoob.jpg'
49
  # st.sidebar.image(logo_url)
50
  import base64
51
+
52
  #Configuração da imagem da sidebar
53
  with open("sicoob-logo.png", "rb") as f:
54
  data = base64.b64encode(f.read()).decode("utf-8")
55
+
56
  st.sidebar.markdown(
57
  f"""
58
  <div style="display:table;margin-top:-80%;margin-left:0%;">
 
61
  """,
62
  unsafe_allow_html=True,
63
  )
64
+
 
65
  #if sidebar_option == "Ollama":
66
  # Settings.llm = Ollama(model="llama3.2:latest", request_timeout=500.0, num_gpu=1)
67
  # Settings.embed_model = OllamaEmbedding(model_name="nomic-embed-text:latest")
 
71
  Settings.llm = OpenAI(model="gpt-3.5-turbo")
72
  Settings.embed_model = OpenAIEmbedding(model_name="text-embedding-ada-002")
73
  elif sidebar_option == 'NuExtract-1.5':
 
74
  logging.basicConfig(stream=sys.stdout, level=logging.INFO)
75
  logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
76
+
77
  #Embedding do huggingface
78
  Settings.embed_model = HuggingFaceEmbedding(
79
+ model_name="BAAI/bge-small-en-v1.5"
80
  )
81
  #Carregamento do modelo local, descomentar o modelo desejado
82
+
83
  llm = HuggingFaceLLM(
84
  context_window=2048,
85
  max_new_tokens=2048,
 
92
  # model_name="meta-llama/Meta-Llama-3-8B",
93
  model_name="numind/NuExtract-1.5",
94
  #model_name="meta-llama/Llama-3.2-3B",
 
95
  tokenizer_name="numind/NuExtract-1.5",
96
  device_map="auto",
97
  tokenizer_kwargs={"max_length": 512},
 
99
  model_kwargs={"torch_dtype": torch.bfloat16},
100
  )
101
  chat = [
102
+ {"role": "user", "content": "Hello, how are you?"},
103
+ {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
104
+ {"role": "user", "content": "I'd like to show off how chat templating works!"},
 
 
 
 
105
  ]
106
+
107
  from transformers import AutoTokenizer
108
+
109
  tokenizer = AutoTokenizer.from_pretrained("numind/NuExtract-1.5")
 
110
  tokenizer.apply_chat_template(chat, tokenize=False)
111
+
 
112
  Settings.chunk_size = 512
113
  Settings.llm = llm
114
+
115
  else:
116
  raise Exception("Opção de LLM inválida!")
117
+
118
  # Diretórios configurados pelo usuário
119
  chat_store_path = os.path.join("chat_store", "chat_store.json")
120
  documents_path = os.path.join("documentos")
 
122
  chroma_storage_path_curadoria = os.path.join("chroma_db_curadoria") # Diretório para 'curadoria'
123
  bm25_persist_path = os.path.join("bm25_retriever")
124
  curadoria_path = os.path.join("curadoria")
125
+
126
+ # Classe CSV Customizada (novo código)
127
+ class CustomPandasCSVReader:
128
+ """PandasCSVReader modificado para incluir cabeçalhos nos documentos."""
129
+ def __init__(
130
+ self,
131
+ *args: Any,
132
+ concat_rows: bool = True,
133
+ col_joiner: str = ", ",
134
+ row_joiner: str = "\n",
135
+ pandas_config: dict = {},
136
+ **kwargs: Any
137
+ ) -> None:
138
+ self._concat_rows = concat_rows
139
+ self._col_joiner = col_joiner
140
+ self._row_joiner = row_joiner
141
+ self._pandas_config = pandas_config
142
+
143
+ def load_data(
144
+ self,
145
+ file: Path,
146
+ extra_info: Optional[Dict] = None,
147
+ ) -> List[Document]:
148
+ df = pd.read_csv(file, **self._pandas_config)
149
+ text_list = [" ".join(df.columns.astype(str))]
150
+ text_list += (
151
+ df.astype(str)
152
+ .apply(lambda row: self._col_joiner.join(row.values), axis=1)
153
+ .tolist()
154
+ )
155
+
156
+ metadata = {"filename": file.name, "extension": file.suffix}
157
+ if extra_info:
158
+ metadata.update(extra_info)
159
+
160
+ if self._concat_rows:
161
+ return [Document(text=self._row_joiner.join(text_list), metadata=metadata)]
162
+ else:
163
+ return [
164
+ Document(text=text, metadata=metadata)
165
+ for text in text_list
166
+ ]
167
+
168
+ def clean_documents(documents):
169
+ """Remove caracteres não desejados diretamente nos textos dos documentos."""
170
+ cleaned_documents = []
171
+ for doc in documents:
172
+ cleaned_text = re.sub(r"[^0-9A-Za-zÀ-ÿ ]", "", doc.get_content())
173
+ doc.text = cleaned_text
174
+ cleaned_documents.append(doc)
175
+ return cleaned_documents
176
+
177
+ from llama_index.readers.google import GoogleDriveReader
178
+
179
+ credentials_path = "path_to_credentials.json" # Ajuste o caminho para seu arquivo de credenciais
180
+ google_drive_reader = GoogleDriveReader(credentials_path=credentials_path)
181
+ google_drive_reader._creds = google_drive_reader._get_credentials()
182
+
183
+ def are_docs_downloaded(directory_path: str) -> bool:
184
+ return os.path.isdir(directory_path) and any(os.scandir(directory_path))
185
+
186
+ def download_original_files_from_folder(greader: GoogleDriveReader, pasta_documentos_drive: str, local_path: str):
187
+ os.makedirs(local_path, exist_ok=True)
188
+ files_meta = greader._get_fileids_meta(folder_id=pasta_documentos_drive)
189
+ if not files_meta:
190
+ logging.info("Nenhum arquivo encontrado na pasta especificada.")
191
+ return
192
+ for fmeta in files_meta:
193
+ file_id = fmeta[0]
194
+ file_name = os.path.basename(fmeta[2])
195
+ local_file_path = os.path.join(local_path, file_name)
196
+
197
+ if os.path.exists(local_file_path):
198
+ logging.info(f"Arquivo '{file_name}' já existe localmente, ignorando download.")
199
+ continue
200
+
201
+ downloaded_file_path = greader._download_file(file_id, local_file_path)
202
+ if downloaded_file_path:
203
+ logging.info(f"Arquivo '{file_name}' baixado com sucesso em: {downloaded_file_path}")
204
+ else:
205
+ logging.warning(f"Não foi possível baixar '{file_name}'")
206
+
207
+ #DADOS/QA_database/Documentos CSV/documentos
208
+ pasta_documentos_drive = "1xVzo8s1D0blzR5ZB3m5k4dVWHuRmKUu-"
209
+ #DADOS/QA_database/Documentos CSV/curadoria
210
+ pasta_curadoria_drive = "1LRrdOkZy9p0FA3MQAyz-Ssj3ktKTWAwE"
211
+
212
+ # Verifica e baixa arquivos se necessário (novo código)
213
+ if not are_docs_downloaded(documents_path):
214
+ logging.info("Baixando arquivos originais do Drive para 'documentos'...")
215
+ download_original_files_from_folder(google_drive_reader, pasta_documentos_drive, documents_path)
216
+ else:
217
+ logging.info("'documentos' já contém arquivos, ignorando download.")
218
+
219
+ if not are_docs_downloaded(curadoria_path):
220
+ logging.info("Baixando arquivos originais do Drive para 'curadoria'...")
221
+ download_original_files_from_folder(google_drive_reader, pasta_curadoria_drive, curadoria_path)
222
+ else:
223
+ logging.info("'curadoria' já contém arquivos, ignorando download.")
224
+
225
  # Configuração de leitura de documentos
226
+ file_extractor = {".csv": CustomPandasCSVReader()}
227
+ documents = SimpleDirectoryReader(
228
+ input_dir=documents_path,
229
+ file_extractor=file_extractor,
230
+ filename_as_id=True
231
+ ).load_data()
232
+
233
+ documents = clean_documents(documents)
234
+
235
  # Configuração do Chroma e BM25 com persistência
236
  docstore = SimpleDocumentStore()
237
  docstore.add_documents(documents)
238
+
239
  db = chromadb.PersistentClient(path=chroma_storage_path)
240
  chroma_collection = db.get_or_create_collection("dense_vectors")
241
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
242
+
243
  # Configuração do StorageContext
244
  storage_context = StorageContext.from_defaults(
245
  docstore=docstore, vector_store=vector_store
246
  )
247
+
248
  # Criação/Recarregamento do índice com embeddings
249
  if os.path.exists(chroma_storage_path):
250
  index = VectorStoreIndex.from_vector_store(vector_store)
 
253
  RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
254
  )
255
  index = VectorStoreIndex.from_documents(
256
+ documents,
257
+ storage_context=storage_context,
258
+ transformations=[splitter]
259
  )
260
  vector_store.persist()
261
+
262
  # Criação/Recarregamento do BM25 Retriever
263
  if os.path.exists(os.path.join(bm25_persist_path, "params.index.json")):
264
  bm25_retriever = BM25Retriever.from_persist_dir(bm25_persist_path)
 
270
  )
271
  os.makedirs(bm25_persist_path, exist_ok=True)
272
  bm25_retriever.persist(bm25_persist_path)
273
+
274
  #Adicionado documentos na pasta curadoria, foi setado para 1200 o chunk pra receber pergunta, contexto e resposta
275
+ curadoria_documents = SimpleDirectoryReader(
276
+ input_dir=curadoria_path,
277
+ file_extractor=file_extractor,
278
+ filename_as_id=True
279
+ ).load_data()
280
+
281
+ curadoria_documents = clean_documents(curadoria_documents)
282
  curadoria_docstore = SimpleDocumentStore()
283
  curadoria_docstore.add_documents(curadoria_documents)
284
+
285
  db_curadoria = chromadb.PersistentClient(path=chroma_storage_path_curadoria)
286
  chroma_collection_curadoria = db_curadoria.get_or_create_collection("dense_vectors_curadoria")
287
  vector_store_curadoria = ChromaVectorStore(chroma_collection=chroma_collection_curadoria)
288
+
289
  # Configuração do StorageContext para 'curadoria'
290
  storage_context_curadoria = StorageContext.from_defaults(
291
  docstore=curadoria_docstore, vector_store=vector_store_curadoria
292
  )
293
+
294
  # Criação/Recarregamento do índice com embeddings para 'curadoria'
295
  if os.path.exists(chroma_storage_path_curadoria):
296
  curadoria_index = VectorStoreIndex.from_vector_store(vector_store_curadoria)
 
302
  curadoria_documents, storage_context=storage_context_curadoria, transformations=[curadoria_splitter]
303
  )
304
  vector_store_curadoria.persist()
305
+
306
  curadoria_retriever = curadoria_index.as_retriever(similarity_top_k=2)
307
+
308
  # Combinação de Retrievers (Embeddings + BM25)
309
  vector_retriever = index.as_retriever(similarity_top_k=2)
310
  retriever = QueryFusionRetriever(
311
  [vector_retriever, bm25_retriever, curadoria_retriever],
312
  similarity_top_k=2,
313
+ num_queries=0,
314
  mode="reciprocal_rerank",
315
  use_async=True,
316
  verbose=True,
 
323
  "Perguntas:\n"
324
  ),
325
  )
326
+
327
  # Configuração do chat engine
328
  nest_asyncio.apply()
329
  memory = ChatMemoryBuffer.from_defaults(token_limit=3900)
 
340
  ),
341
  verbose=True,
342
  )
343
+
344
  # Armazenamento do chat
345
  chat_store = SimpleChatStore()
346
  if os.path.exists(chat_store_path):
347
  chat_store = SimpleChatStore.from_persist_path(persist_path=chat_store_path)
348
  else:
349
  chat_store.persist(persist_path=chat_store_path)
350
+
351
  # Interface do Chatbot
352
  st.title("Chatbot Carômetro")
353
  st.write("Este chatbot pode te ajudar a conseguir informações relevantes sobre os carômetros da Sicoob.")
354
+
355
  if 'chat_history' not in st.session_state:
356
  st.session_state.chat_history = []
357
+
358
  for message in st.session_state.chat_history:
359
  role, text = message.split(":", 1)
360
  with st.chat_message(role.strip().lower()):
361
  st.write(text.strip())
362
+
363
  user_input = st.chat_input("Digite sua pergunta")
364
  if user_input:
365
  # Exibir a mensagem do usuário e adicionar ao histórico
366
  with st.chat_message('user'):
367
  st.write(user_input)
368
  st.session_state.chat_history.append(f"user: {user_input}")
369
+
370
  # Placeholder para a mensagem do assistente
371
  with st.chat_message('assistant'):
372
  message_placeholder = st.empty()
373
  assistant_message = ''
374
+
375
  # Obter a resposta em streaming do chat_engine
376
  response = chat_engine.stream_chat(user_input)
377
  for token in response.response_gen:
378
  assistant_message += token
379
  # Atualizar o placeholder da mensagem
380
  message_placeholder.markdown(assistant_message + "▌")
381
+
382
  # Remover o cursor após a conclusão
383
  message_placeholder.markdown(assistant_message)
384
  st.session_state.chat_history.append(f"assistant: {assistant_message}")