File size: 5,237 Bytes
0614e7d
6952db2
ffa0c53
 
9eab4dd
 
 
 
 
0614e7d
 
 
ffa0c53
78222a9
 
 
9eab4dd
78222a9
 
9eab4dd
ffa0c53
9eab4dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0614e7d
ffa0c53
9eab4dd
6952db2
 
 
 
 
78222a9
ffa0c53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78222a9
6952db2
 
 
78222a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ffa0c53
0614e7d
 
ffa0c53
 
0614e7d
 
 
 
 
ffa0c53
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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}