rmayormartins commited on
Commit
429cb96
1 Parent(s): 07f9d65
Files changed (1) hide show
  1. app.py +167 -139
app.py CHANGED
@@ -13,67 +13,80 @@ import torch
13
 
14
  class EnhancedRAGSystem:
15
  def __init__(self):
16
- self.chunk_size = 500
17
- self.chunk_overlap = 50
18
- self.k_documents = 4
19
-
20
- self.text_splitter = RecursiveCharacterTextSplitter(
21
- chunk_size=self.chunk_size,
22
- chunk_overlap=self.chunk_overlap,
23
- length_function=len
24
- )
25
-
26
- self.embedding_model_name = "intfloat/multilingual-e5-large"
27
- self.llm_model_name = "google/flan-t5-large"
28
-
29
- self.prompt_template = PromptTemplate(
30
- template="""Use the context below to answer the question.
31
- If the answer is not in the context, say "I don't have enough information in the context to answer this question."
32
 
33
- Context: {context}
34
- Question: {question}
 
 
 
35
 
36
- Detailed answer:""",
37
- input_variables=["context", "question"]
38
- )
39
-
40
- self.embeddings = HuggingFaceEmbeddings(
41
- model_name=self.embedding_model_name,
42
- model_kwargs={'device': 'cuda' if torch.cuda.is_available() else 'cpu'}
43
- )
44
-
45
- self.tokenizer = AutoTokenizer.from_pretrained(self.llm_model_name)
46
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.llm_model_name)
47
-
48
- self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
49
- self.model.to(self.device)
50
-
51
- self.pipe = pipeline(
52
- "text2text-generation",
53
- model=self.model,
54
- tokenizer=self.tokenizer,
55
- max_length=512,
56
- device=0 if torch.cuda.is_available() else -1,
57
- model_kwargs={"temperature": 0.7}
58
- )
59
-
60
- self.llm = HuggingFacePipeline(pipeline=self.pipe)
61
-
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  def process_documents(self, text: str) -> bool:
63
  try:
 
 
 
 
 
 
64
  texts = self.text_splitter.split_text(text)
65
 
 
66
  self.vectorstore = Chroma.from_texts(
67
  texts,
68
  self.embeddings,
69
- metadatas=[{"source": f"chunk_{i}", "text": t} for i, t in enumerate(texts)],
70
- collection_name="enhanced_rag_docs"
71
  )
72
 
 
73
  self.retriever = self.vectorstore.as_retriever(
74
  search_kwargs={"k": self.k_documents}
75
  )
76
 
 
77
  self.qa_chain = RetrievalQA.from_chain_type(
78
  llm=self.llm,
79
  chain_type="stuff",
@@ -81,13 +94,20 @@ class EnhancedRAGSystem:
81
  return_source_documents=True,
82
  chain_type_kwargs={"prompt": self.prompt_template}
83
  )
 
 
84
  return True
 
85
  except Exception as e:
86
- print(f"Processing error: {str(e)}")
87
  return False
88
 
89
  def answer_question(self, question: str) -> Tuple[str, str]:
90
  try:
 
 
 
 
91
  response = self.qa_chain({"query": question})
92
  answer = response["result"]
93
 
@@ -97,112 +117,120 @@ class EnhancedRAGSystem:
97
  sources.append(f"Excerpt {i}: {text_preview}")
98
 
99
  sources_text = "\n".join(sources)
 
100
  return answer, sources_text
 
101
  except Exception as e:
102
- return f"Error answering: {str(e)}", ""
 
103
 
104
  def create_enhanced_interface():
105
- rag_system = EnhancedRAGSystem()
106
-
107
- def process_and_answer(text: str, question: str) -> str:
108
- if not text.strip() or not question.strip():
109
- return "Please provide both text and question."
110
-
111
- if not rag_system.process_documents(text):
112
- return "Error processing the text."
113
 
114
- answer, sources = rag_system.answer_question(question)
115
-
116
- if sources:
117
- return f"""Answer: {answer}
 
 
 
 
 
 
 
 
 
118
 
119
  Relevant excerpts consulted:
120
  {sources}"""
121
- return answer
122
 
123
- # HTML para o cabeçalho
124
- custom_css = """
125
- .custom-description {
126
- margin-bottom: 20px;
127
- text-align: center;
128
- }
129
- .custom-description a {
130
- text-decoration: none;
131
- color: #007bff;
132
- margin: 0 5px;
133
- }
134
- .custom-description a:hover {
135
- text-decoration: underline;
136
- }
137
- """
138
 
139
- with gr.Blocks(css=custom_css) as interface:
140
- gr.HTML("""
141
- <div class="custom-description">
142
- <h1>Advanced RAG with Multilingual Support</h1>
143
- <p>Ramon Mayor Martins:
144
- <a href="https://rmayormartins.github.io/" target="_blank">Website</a> |
145
- <a href="https://huggingface.co/rmayormartins" target="_blank">Spaces</a> |
146
- <a href="https://github.com/rmayormartins" target="_blank">GitHub</a>
147
- </p>
148
- <p>This system uses Retrieval-Augmented Generation (RAG) to answer questions about your texts in multiple languages.
149
- Simply paste your text and ask questions in any language!</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
- </div>
152
- """)
153
-
154
- with gr.Row():
155
- with gr.Column():
156
- text_input = gr.Textbox(
157
- label="Base Text",
158
- placeholder="Paste here the text that will serve as knowledge base...",
159
- lines=10
160
- )
161
- question_input = gr.Textbox(
162
- label="Your Question",
163
- placeholder="What would you like to know about the text?"
164
- )
165
- submit_btn = gr.Button("Submit")
166
-
167
- with gr.Column():
168
- output = gr.Textbox(label="Answer")
169
 
170
- examples = [
171
- ["The Earth is the third planet from the Sun. It has one natural satellite called the Moon. It is the only known planet to harbor life.",
172
- "What is Earth's natural satellite?"],
173
-
174
- ["La Tierra es el tercer planeta del Sistema Solar. Tiene un satélite natural llamado Luna. Es el único planeta conocido que alberga vida.",
175
- "¿Cuál es el satélite natural de la Tierra?"],
176
-
177
- ["A Terra é o terceiro planeta do Sistema Solar. Tem um satélite natural chamado Lua. É o único planeta conhecido que abriga vida.",
178
- "Qual é o satélite natural da Terra?"],
179
-
180
- ["The Sun is a medium-sized star at the center of our Solar System. It provides light and heat to all planets.",
181
- "What is the Sun?"],
182
-
183
- ["El Sol es una estrella de tamaño medio en el centro de nuestro Sistema Solar. Proporciona luz y calor a todos los planetas.",
184
- "¿Qué es el Sol?"],
185
-
186
- ["O Sol é uma estrela de tamanho médio no centro do nosso Sistema Solar. Ele fornece luz e calor para todos os planetas.",
187
- "O que é o Sol?"]
188
- ]
189
 
190
- gr.Examples(
191
- examples=examples,
192
- inputs=[text_input, question_input],
193
- outputs=output,
194
- fn=process_and_answer,
195
- cache_examples=True
196
- )
197
 
198
- submit_btn.click(
199
- fn=process_and_answer,
200
- inputs=[text_input, question_input],
201
- outputs=output
202
- )
203
 
204
- return interface
 
 
 
 
 
205
 
206
  if __name__ == "__main__":
207
- demo = create_enhanced_interface()
208
- demo.launch()
 
 
 
 
 
13
 
14
  class EnhancedRAGSystem:
15
  def __init__(self):
16
+ try:
17
+ print("Initializing RAG System...")
18
+ self.chunk_size = 500
19
+ self.chunk_overlap = 50
20
+ self.k_documents = 4
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ self.text_splitter = RecursiveCharacterTextSplitter(
23
+ chunk_size=self.chunk_size,
24
+ chunk_overlap=self.chunk_overlap,
25
+ length_function=len
26
+ )
27
 
28
+ print("Loading embedding model...")
29
+ self.embeddings = HuggingFaceEmbeddings(
30
+ model_name="sentence-transformers/all-MiniLM-L6-v2",
31
+ model_kwargs={'device': 'cpu'}
32
+ )
33
+
34
+ print("Loading language model...")
35
+ self.llm_model_name = "google/flan-t5-small"
36
+ self.tokenizer = AutoTokenizer.from_pretrained(self.llm_model_name)
37
+ self.model = AutoModelForSeq2SeqLM.from_pretrained(self.llm_model_name)
38
+
39
+ self.prompt_template = PromptTemplate(
40
+ template="""Use the context below to answer the question.
41
+ If the answer is not in the context, say "I don't have enough information in the context to answer this question."
42
+
43
+ Context: {context}
44
+ Question: {question}
45
+
46
+ Detailed answer:""",
47
+ input_variables=["context", "question"]
48
+ )
49
+
50
+ print("Setting up pipeline...")
51
+ self.pipe = pipeline(
52
+ "text2text-generation",
53
+ model=self.model,
54
+ tokenizer=self.tokenizer,
55
+ max_length=512,
56
+ device=-1,
57
+ model_kwargs={"temperature": 0.7}
58
+ )
59
+
60
+ self.llm = HuggingFacePipeline(pipeline=self.pipe)
61
+ print("RAG System initialized successfully!")
62
+
63
+ except Exception as e:
64
+ print(f"Error during initialization: {str(e)}")
65
+ raise
66
+
67
  def process_documents(self, text: str) -> bool:
68
  try:
69
+ print("Processing documents...")
70
+ if not text or len(text.strip()) < 10:
71
+ print("Text is too short or empty")
72
+ return False
73
+
74
+ print("Splitting text...")
75
  texts = self.text_splitter.split_text(text)
76
 
77
+ print("Creating vectorstore...")
78
  self.vectorstore = Chroma.from_texts(
79
  texts,
80
  self.embeddings,
81
+ metadatas=[{"source": f"chunk_{i}", "text": t} for i, t in enumerate(texts)]
 
82
  )
83
 
84
+ print("Setting up retriever...")
85
  self.retriever = self.vectorstore.as_retriever(
86
  search_kwargs={"k": self.k_documents}
87
  )
88
 
89
+ print("Creating QA chain...")
90
  self.qa_chain = RetrievalQA.from_chain_type(
91
  llm=self.llm,
92
  chain_type="stuff",
 
94
  return_source_documents=True,
95
  chain_type_kwargs={"prompt": self.prompt_template}
96
  )
97
+
98
+ print("Documents processed successfully!")
99
  return True
100
+
101
  except Exception as e:
102
+ print(f"Error processing documents: {str(e)}")
103
  return False
104
 
105
  def answer_question(self, question: str) -> Tuple[str, str]:
106
  try:
107
+ print(f"Answering question: {question}")
108
+ if not hasattr(self, 'qa_chain'):
109
+ return "Please process some documents first.", ""
110
+
111
  response = self.qa_chain({"query": question})
112
  answer = response["result"]
113
 
 
117
  sources.append(f"Excerpt {i}: {text_preview}")
118
 
119
  sources_text = "\n".join(sources)
120
+ print("Answer generated successfully!")
121
  return answer, sources_text
122
+
123
  except Exception as e:
124
+ print(f"Error generating answer: {str(e)}")
125
+ return f"Error generating answer: {str(e)}", ""
126
 
127
  def create_enhanced_interface():
128
+ try:
129
+ print("Creating interface...")
130
+ rag_system = EnhancedRAGSystem()
 
 
 
 
 
131
 
132
+ def process_and_answer(text: str, question: str) -> str:
133
+ print("Processing new request...")
134
+ if not text.strip() or not question.strip():
135
+ return "Please provide both text and question."
136
+
137
+ success = rag_system.process_documents(text)
138
+ if not success:
139
+ return "Error processing the text. Please check if the text is valid and try again."
140
+
141
+ answer, sources = rag_system.answer_question(question)
142
+
143
+ if sources:
144
+ return f"""Answer: {answer}
145
 
146
  Relevant excerpts consulted:
147
  {sources}"""
148
+ return answer
149
 
150
+ custom_css = """
151
+ .custom-description {
152
+ margin-bottom: 20px;
153
+ text-align: center;
154
+ }
155
+ .custom-description a {
156
+ text-decoration: none;
157
+ color: #007bff;
158
+ margin: 0 5px;
159
+ }
160
+ .custom-description a:hover {
161
+ text-decoration: underline;
162
+ }
163
+ """
 
164
 
165
+ with gr.Blocks(css=custom_css) as interface:
166
+ gr.HTML("""
167
+ <div class="custom-description">
168
+ <h1>Advanced RAG with Multilingual Support</h1>
169
+ <p>Ramon Mayor Martins:
170
+ <a href="https://rmayormartins.github.io/" target="_blank">Website</a> |
171
+ <a href="https://huggingface.co/rmayormartins" target="_blank">Spaces</a> |
172
+ <a href="https://github.com/rmayormartins" target="_blank">GitHub</a>
173
+ </p>
174
+ <p>This system uses Retrieval-Augmented Generation (RAG) to answer questions about your texts in multiple languages.
175
+ Simply paste your text and ask questions in any language!</p>
176
+ </div>
177
+ """)
178
+
179
+ with gr.Row():
180
+ with gr.Column():
181
+ text_input = gr.Textbox(
182
+ label="Base Text",
183
+ placeholder="Paste here the text that will serve as knowledge base...",
184
+ lines=10
185
+ )
186
+ question_input = gr.Textbox(
187
+ label="Your Question",
188
+ placeholder="What would you like to know about the text?"
189
+ )
190
+ submit_btn = gr.Button("Submit")
191
 
192
+ with gr.Column():
193
+ output = gr.Textbox(label="Answer")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ examples = [
196
+ # English example
197
+ ["The solar system consists of the Sun and the celestial bodies that orbit it. These include eight planets (Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune), their moons, asteroids, comets, and other objects.",
198
+ "How many planets are in the solar system?"],
199
+
200
+ # Spanish example
201
+ ["El sistema solar está formado por el Sol y los cuerpos celestes que orbitan a su alrededor. Estos incluyen ocho planetas (Mercurio, Venus, Tierra, Marte, Júpiter, Saturno, Urano y Neptuno), sus lunas, asteroides, cometas y otros objetos.",
202
+ "¿Cuántos planetas hay en el sistema solar?"],
203
+
204
+ # Portuguese example
205
+ ["O sistema solar é composto pelo Sol e pelos corpos celestes que orbitam ao seu redor. Isso inclui oito planetas (Mercúrio, Vênus, Terra, Marte, Júpiter, Saturno, Urano e Netuno), suas luas, asteroides, cometas e outros objetos.",
206
+ "Quantos planetas existem no sistema solar?"]
207
+ ]
 
 
 
 
 
 
208
 
209
+ gr.Examples(
210
+ examples=examples,
211
+ inputs=[text_input, question_input],
212
+ outputs=output,
213
+ fn=process_and_answer,
214
+ cache_examples=True
215
+ )
216
 
217
+ submit_btn.click(
218
+ fn=process_and_answer,
219
+ inputs=[text_input, question_input],
220
+ outputs=output
221
+ )
222
 
223
+ print("Interface created successfully!")
224
+ return interface
225
+
226
+ except Exception as e:
227
+ print(f"Error creating interface: {str(e)}")
228
+ raise
229
 
230
  if __name__ == "__main__":
231
+ print("Starting application...")
232
+ try:
233
+ demo = create_enhanced_interface()
234
+ demo.launch()
235
+ except Exception as e:
236
+ print(f"Application failed to start: {str(e)}")