ProvaObjetiva / app.py
healthtechbrasil's picture
force cpu usage
9eab4dd
raw
history blame
5.24 kB
from fastapi import FastAPI
from transformers import AutoTokenizer, T5ForConditionalGeneration
import json
import os
import logging
# Configura logging para capturar mais detalhes
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
# Carrega o arquivo questions.json
try:
with open("questions.json", "r", encoding="utf-8") as f:
examples = json.load(f)
logger.info("questions.json carregado com sucesso.")
except FileNotFoundError:
examples = []
logger.warning("questions.json não encontrado, usando lista vazia.")
# Função para carregar o modelo e tokenizer sob demanda
def get_model():
if not hasattr(get_model, "model_data"):
logger.info("Carregando modelo e tokenizer pela primeira vez...")
try:
tokenizer = AutoTokenizer.from_pretrained(
"unicamp-dl/ptt5-base-portuguese-vocab",
legacy=False,
clean_up_tokenization_spaces=True
)
logger.info("Tokenizer carregado com sucesso.")
model = T5ForConditionalGeneration.from_pretrained(
"unicamp-dl/ptt5-base-portuguese-vocab",
device_map="cpu" # Força uso da CPU
)
logger.info("Modelo carregado com sucesso.")
get_model.model_data = {"tokenizer": tokenizer, "model": model}
except Exception as e:
logger.error(f"Erro ao carregar modelo ou tokenizer: {e}")
get_model.model_data = None
return get_model.model_data
def generate_question_from_prompt(theme, difficulty, example_question=None):
model_data = get_model()
if not model_data or not model_data["tokenizer"] or not model_data["model"]:
return {"question": "Erro: Modelo ou tokenizer não carregado.", "options": [], "answer": "", "explanation": "Por favor, verifique os logs."}
tokenizer = model_data["tokenizer"]
model = model_data["model"]
if example_question:
example_text = (
f"Enunciado clínico: {example_question['question'].split('Considerando')[-1].strip()} "
f"Alternativas: {', '.join(example_question['options'])} "
f"Gabarito: {example_question['answer']} "
f"Explicação: {example_question['explanation']}"
)
prompt = (
f"Baseado no exemplo: '{example_text}', gere uma nova questão de múltipla escolha "
f"sobre o tema '{theme}', com dificuldade {difficulty}, no estilo da prova de residência médica da USP. "
"Use o formato: 'Enunciado clínico: [texto detalhado com dados do paciente, exames e pergunta]. "
"Alternativas: A) [opção], B) [opção], C) [opção], D) [opção]. Gabarito: [letra]. "
"Explicação: [texto].'"
)
else:
prompt = (
f"Gere uma questão de múltipla escolha sobre o tema '{theme}', "
f"com dificuldade {difficulty}, no estilo da prova de residência médica da USP. "
"Use o formato: 'Enunciado clínico: [texto detalhado com dados do paciente, exames e pergunta]. "
"Alternativas: A) [opção], B) [opção], C) [opção], D) [opção]. Gabarito: [letra]. "
"Explicação: [texto].'"
)
try:
inputs = tokenizer(prompt, return_tensors="pt", padding=True, truncation=True, max_length=512)
outputs = model.generate(**inputs, max_new_tokens=512, temperature=0.7, top_p=0.9)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
parts = response.split("Alternativas:")
if len(parts) > 1:
question_part = parts[0].replace("Enunciado clínico:", "").strip()
options_part = parts[1].split("Gabarito:")[0].strip()
answer_part = parts[1].split("Gabarito:")[1].split("Explicação:")[0].strip()
explanation_part = parts[1].split("Explicação:")[1].strip() if "Explicação:" in parts[1] else "Explicação padrão"
options = [opt.strip() for opt in options_part.split(",")]
if len(options) >= 4:
return {
"question": f"Enunciado clínico: {question_part}",
"options": [f"A) {options[0]}", f"B) {options[1]}", f"C) {options[2]}", f"D) {options[3]}"],
"answer": answer_part,
"explanation": explanation_part
}
return {"question": response, "options": [], "answer": "", "explanation": "Explicação padrão"}
except Exception as e:
return {"question": f"Erro na geração: {e}", "options": [], "answer": "", "explanation": "Tente novamente."}
@app.get("/generate")
async def generate_question(theme: str, difficulty: str):
example = examples[0] if examples else None
return generate_question_from_prompt(theme, difficulty, example)
@app.get("/simulado")
async def get_simulado(num_questions: int = 5):
simulado = []
for _ in range(num_questions):
example = examples[_ % len(examples)] if examples else None
question_data = generate_question_from_prompt("clinica medica", "medio", example)
simulado.append(question_data)
return {"simulado": simulado}