Update app.py
Browse files
app.py
CHANGED
|
@@ -231,10 +231,12 @@ class TextProcessor:
|
|
| 231 |
|
| 232 |
class ModelManager:
|
| 233 |
"""Gerencia o modelo de IA e processamento de perguntas"""
|
| 234 |
-
|
| 235 |
def __init__(self):
|
| 236 |
self.model_name = "deepset/roberta-base-squad2"
|
| 237 |
self.device = 0 if torch.cuda.is_available() else -1
|
|
|
|
|
|
|
| 238 |
self.load_model()
|
| 239 |
|
| 240 |
def load_model(self):
|
|
@@ -243,9 +245,9 @@ class ModelManager:
|
|
| 243 |
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
|
| 244 |
self.model = AutoModelForQuestionAnswering.from_pretrained(self.model_name)
|
| 245 |
self.nlp = pipeline('question-answering',
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
logger.info(f"Modelo {self.model_name} carregado com sucesso")
|
| 250 |
except Exception as e:
|
| 251 |
logger.error(f"Erro ao carregar modelo: {e}")
|
|
@@ -254,7 +256,11 @@ class ModelManager:
|
|
| 254 |
def get_answer(self, question: str, context: str) -> Dict:
|
| 255 |
"""Processa uma única pergunta/contexto"""
|
| 256 |
try:
|
| 257 |
-
return self.nlp(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
except Exception as e:
|
| 259 |
logger.error(f"Erro ao processar resposta: {e}")
|
| 260 |
return {
|
|
@@ -278,13 +284,12 @@ class ModelManager:
|
|
| 278 |
|
| 279 |
answers = []
|
| 280 |
with ThreadPoolExecutor() as executor:
|
| 281 |
-
futures = [executor.submit(self.get_answer, question, chunk)
|
| 282 |
-
for chunk in chunks]
|
| 283 |
answers = [future.result() for future in futures]
|
| 284 |
|
| 285 |
# Filtrar respostas vazias
|
| 286 |
answers = [ans for ans in answers if ans['answer'].strip()]
|
| 287 |
-
|
| 288 |
if not answers:
|
| 289 |
return {
|
| 290 |
'answer': "Não foi possível encontrar uma resposta.",
|
|
@@ -295,18 +300,25 @@ class ModelManager:
|
|
| 295 |
}
|
| 296 |
|
| 297 |
best_answer = max(answers, key=lambda x: x['score'])
|
| 298 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
return {
|
| 300 |
'answer': best_answer['answer'],
|
| 301 |
'score': best_answer['score'],
|
| 302 |
'confidence': f"{best_answer['score']*100:.2f}%",
|
| 303 |
-
'context':
|
| 304 |
-
'page_number': None #
|
| 305 |
}
|
| 306 |
except Exception as e:
|
| 307 |
-
logger.error(f"Erro ao
|
| 308 |
return {
|
| 309 |
-
'answer': "Erro ao processar
|
| 310 |
'score': 0,
|
| 311 |
'confidence': "0%",
|
| 312 |
'context': "",
|
|
|
|
| 231 |
|
| 232 |
class ModelManager:
|
| 233 |
"""Gerencia o modelo de IA e processamento de perguntas"""
|
| 234 |
+
|
| 235 |
def __init__(self):
|
| 236 |
self.model_name = "deepset/roberta-base-squad2"
|
| 237 |
self.device = 0 if torch.cuda.is_available() else -1
|
| 238 |
+
self.max_tokens_answer = 50 # Máximo de tokens na resposta
|
| 239 |
+
self.max_tokens_context = 300 # Máximo de tokens no contexto exibido
|
| 240 |
self.load_model()
|
| 241 |
|
| 242 |
def load_model(self):
|
|
|
|
| 245 |
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
|
| 246 |
self.model = AutoModelForQuestionAnswering.from_pretrained(self.model_name)
|
| 247 |
self.nlp = pipeline('question-answering',
|
| 248 |
+
model=self.model,
|
| 249 |
+
tokenizer=self.tokenizer,
|
| 250 |
+
device=self.device)
|
| 251 |
logger.info(f"Modelo {self.model_name} carregado com sucesso")
|
| 252 |
except Exception as e:
|
| 253 |
logger.error(f"Erro ao carregar modelo: {e}")
|
|
|
|
| 256 |
def get_answer(self, question: str, context: str) -> Dict:
|
| 257 |
"""Processa uma única pergunta/contexto"""
|
| 258 |
try:
|
| 259 |
+
return self.nlp(
|
| 260 |
+
question=question,
|
| 261 |
+
context=context,
|
| 262 |
+
max_answer_len=self.max_tokens_answer # Limitar resposta
|
| 263 |
+
)
|
| 264 |
except Exception as e:
|
| 265 |
logger.error(f"Erro ao processar resposta: {e}")
|
| 266 |
return {
|
|
|
|
| 284 |
|
| 285 |
answers = []
|
| 286 |
with ThreadPoolExecutor() as executor:
|
| 287 |
+
futures = [executor.submit(self.get_answer, question, chunk) for chunk in chunks]
|
|
|
|
| 288 |
answers = [future.result() for future in futures]
|
| 289 |
|
| 290 |
# Filtrar respostas vazias
|
| 291 |
answers = [ans for ans in answers if ans['answer'].strip()]
|
| 292 |
+
|
| 293 |
if not answers:
|
| 294 |
return {
|
| 295 |
'answer': "Não foi possível encontrar uma resposta.",
|
|
|
|
| 300 |
}
|
| 301 |
|
| 302 |
best_answer = max(answers, key=lambda x: x['score'])
|
| 303 |
+
|
| 304 |
+
# Limitar contexto para o máximo de tokens configurado
|
| 305 |
+
limited_context = " ".join(
|
| 306 |
+
self.tokenizer.convert_ids_to_tokens(
|
| 307 |
+
self.tokenizer.encode(best_answer.get('context', ""), add_special_tokens=False)[:self.max_tokens_context]
|
| 308 |
+
)
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
return {
|
| 312 |
'answer': best_answer['answer'],
|
| 313 |
'score': best_answer['score'],
|
| 314 |
'confidence': f"{best_answer['score']*100:.2f}%",
|
| 315 |
+
'context': limited_context,
|
| 316 |
+
'page_number': None # Adapte conforme necessário
|
| 317 |
}
|
| 318 |
except Exception as e:
|
| 319 |
+
logger.error(f"Erro ao obter melhor resposta: {e}")
|
| 320 |
return {
|
| 321 |
+
'answer': "Erro ao processar o documento.",
|
| 322 |
'score': 0,
|
| 323 |
'confidence': "0%",
|
| 324 |
'context': "",
|