reichaves commited on
Commit
907f0e0
1 Parent(s): 3c67db5

Add files via upload

Browse files
Files changed (2) hide show
  1. app.py +194 -0
  2. requirements.txt +0 -0
app.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8
2
+ # Reinaldo Chaves (reichaves@gmail.com)
3
+ # Este projeto implementa um sistema de Recuperação de Informações Aumentada por Geração (RAG) conversacional
4
+ # usando Streamlit, LangChain, e modelos de linguagem de grande escala - para entrevistar PDFs
5
+ # Geração de respostas usando o modelo Gemma2-9b-It da Groq
6
+ # Embeddings de texto usando o modelo all-MiniLM-L6-v2 do Hugging Face
7
+ #
8
+
9
+ import streamlit as st
10
+ from langchain.chains import create_history_aware_retriever, create_retrieval_chain
11
+ from langchain.chains.combine_documents import create_stuff_documents_chain
12
+ from langchain_chroma import Chroma
13
+ from langchain_community.chat_message_histories import ChatMessageHistory
14
+ from langchain_core.chat_history import BaseChatMessageHistory
15
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
16
+ from langchain_groq import ChatGroq
17
+ from langchain_core.runnables.history import RunnableWithMessageHistory
18
+ from langchain_huggingface import HuggingFaceEmbeddings
19
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
20
+ from langchain_community.document_loaders import PyPDFLoader
21
+ import os
22
+ import chromadb
23
+ import tempfile
24
+
25
+ # Configurar o tema para dark
26
+ st.set_page_config(page_title="RAG Q&A Conversacional", layout="wide", initial_sidebar_state="expanded", page_icon="🤖", menu_items=None)
27
+
28
+ # Aplicar o tema dark
29
+ st.markdown("""
30
+ <style>
31
+ .stApp {
32
+ background-color: #0e1117;
33
+ color: #fafafa;
34
+ }
35
+ .stSidebar {
36
+ background-color: #262730;
37
+ }
38
+ .stButton>button {
39
+ color: #4F8BF9;
40
+ border-radius: 20px;
41
+ height: 3em;
42
+ width: 200px;
43
+ }
44
+ .stTextInput>div>div>input {
45
+ color: #4F8BF9;
46
+ }
47
+ </style>
48
+ """, unsafe_allow_html=True)
49
+
50
+ # Sidebar com orientações
51
+ st.sidebar.title("Menu")
52
+ st.sidebar.markdown("""
53
+ * Se encontrar erros de processamento, reinicie com F5. Utilize arquivos .PDF com textos não digitalizados como imagens.
54
+ * Para recomeçar uma nova sessão pressione F5.
55
+
56
+ **Atenção:** Os documentos que você compartilhar com o modelo de IA generativa podem ser usados pelo Gemini para treinar o sistema. Portanto, evite compartilhar documentos PDF que contenham:
57
+ 1. Dados bancários e financeiros
58
+ 2. Dados de sua própria empresa
59
+ 3. Informações pessoais
60
+ 4. Informações de propriedade intelectual
61
+ 5. Conteúdos autorais
62
+
63
+ E não use IA para escrever um texto inteiro! O auxílio é melhor para gerar resumos, filtrar informações ou auxiliar a entender contextos - que depois devem ser checados. Inteligência Artificial comete erros (alucinações, viés, baixa qualidade, problemas éticos)!
64
+
65
+ Este projeto não se responsabiliza pelos conteúdos criados a partir deste site.
66
+
67
+ **Sobre este app**
68
+
69
+ Este aplicativo foi desenvolvido por Reinaldo Chaves. Para mais informações, contribuições e feedback, visite o [repositório do projeto no GitHub](https://github.com/seu_usuario/seu_repositorio).
70
+ """)
71
+
72
+ st.title("RAG conversacional com upload em PDF e histórico de bate-papo")
73
+ st.write("Carregue PDFs e converse com o conteúdo deles - aqui é usado o modelo de LLM Gemma2-9b-It e a plataforma de embeddings é all-MiniLM-L6-v2")
74
+
75
+ # Solicitar as chaves de API
76
+ groq_api_key = st.text_input("Insira sua chave de API Groq:", type="password")
77
+ huggingface_api_token = st.text_input("Insira seu token de API Hugging Face:", type="password")
78
+
79
+ if groq_api_key and huggingface_api_token:
80
+ # Configurar o token da API do Hugging Face
81
+ os.environ["HUGGINGFACEHUB_API_TOKEN"] = huggingface_api_token
82
+
83
+ # Inicializar o modelo de linguagem e embeddings
84
+ llm = ChatGroq(groq_api_key=groq_api_key, model_name="Gemma2-9b-It")
85
+ embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
86
+
87
+ session_id = st.text_input("Session ID", value="default_session")
88
+
89
+ if 'store' not in st.session_state:
90
+ st.session_state.store = {}
91
+
92
+ uploaded_files = st.file_uploader("Faça o upload de um ou mais arquivos PDF: ", type="pdf", accept_multiple_files=True)
93
+
94
+ if uploaded_files:
95
+ documents = []
96
+ for uploaded_file in uploaded_files:
97
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
98
+ temp_file.write(uploaded_file.getvalue())
99
+ temp_file_path = temp_file.name
100
+
101
+ loader = PyPDFLoader(temp_file_path)
102
+ docs = loader.load()
103
+ documents.extend(docs)
104
+ os.unlink(temp_file_path) # Remove temporary file
105
+
106
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
107
+ splits = text_splitter.split_documents(documents)
108
+
109
+ # Create Chroma vector store in batches
110
+ batch_size = 100 # Adjust this value if needed
111
+
112
+ # Initialize Chroma client with persistence
113
+ chroma_client = chromadb.PersistentClient(path="./chroma_db")
114
+
115
+ # Create or get the collection
116
+ collection_name = "pdf_collection"
117
+ collection = chroma_client.get_or_create_collection(name=collection_name)
118
+
119
+ # Create Chroma vector store
120
+ vectorstore = Chroma(
121
+ client=chroma_client,
122
+ collection_name=collection_name,
123
+ embedding_function=embeddings
124
+ )
125
+
126
+ # Add documents in batches
127
+ for i in range(0, len(splits), batch_size):
128
+ batch = splits[i:i+batch_size]
129
+ vectorstore.add_documents(batch)
130
+
131
+ st.success(f"Processed {len(splits)} document chunks.")
132
+
133
+ retriever = vectorstore.as_retriever()
134
+
135
+ contextualize_q_system_prompt = (
136
+ "Given a chat history and the latest user question "
137
+ "which might reference context in the chat history, "
138
+ "formulate a standalone question which can be understood "
139
+ "without the chat history. Do NOT answer the question, "
140
+ "just reformulate it if needed and otherwise return it as is."
141
+ )
142
+ contextualize_q_prompt = ChatPromptTemplate.from_messages([
143
+ ("system", contextualize_q_system_prompt),
144
+ MessagesPlaceholder("chat_history"),
145
+ ("human", "{input}"),
146
+ ])
147
+
148
+ history_aware_retriever = create_history_aware_retriever(llm, retriever, contextualize_q_prompt)
149
+
150
+ system_prompt = (
151
+ "Você é um assistente para tarefas de resposta a perguntas. Responda em Português do Brasil a menos que seja pedido outro idioma"
152
+ "Use os seguintes pedaços de contexto recuperado para responder "
153
+ "à pergunta. Se você não sabe a resposta, diga que "
154
+ "não sabe. Use no máximo três frases e mantenha a "
155
+ "resposta concisa."
156
+ "\n\n"
157
+ "{context}"
158
+ )
159
+ qa_prompt = ChatPromptTemplate.from_messages([
160
+ ("system", system_prompt),
161
+ MessagesPlaceholder("chat_history"),
162
+ ("human", "{input}"),
163
+ ])
164
+
165
+ question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
166
+ rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
167
+
168
+ def get_session_history(session: str) -> BaseChatMessageHistory:
169
+ if session not in st.session_state.store:
170
+ st.session_state.store[session] = ChatMessageHistory()
171
+ return st.session_state.store[session]
172
+
173
+ conversational_rag_chain = RunnableWithMessageHistory(
174
+ rag_chain, get_session_history,
175
+ input_messages_key="input",
176
+ history_messages_key="chat_history",
177
+ output_messages_key="answer"
178
+ )
179
+
180
+ user_input = st.text_input("Sua pergunta:")
181
+ if user_input:
182
+ with st.spinner("Processando sua pergunta..."):
183
+ session_history = get_session_history(session_id)
184
+ response = conversational_rag_chain.invoke(
185
+ {"input": user_input},
186
+ config={"configurable": {"session_id": session_id}},
187
+ )
188
+ st.write("Assistante:", response['answer'])
189
+
190
+ with st.expander("Ver histórico do chat"):
191
+ for message in session_history.messages:
192
+ st.write(f"**{message.type}:** {message.content}")
193
+ else:
194
+ st.warning("Por favor, insira tanto a chave da API do Groq quanto o token da API do Hugging Face.")
requirements.txt ADDED
Binary file (6.26 kB). View file