Spaces:
Runtime error
Runtime error
Commit
·
ffa0c53
1
Parent(s):
e357624
unicamp fix com json
Browse files- Dockerfile +5 -2
- app.py +60 -18
- index.html +15 -2
- requirements.txt +4 -4
Dockerfile
CHANGED
@@ -4,6 +4,9 @@ WORKDIR /app
|
|
4 |
|
5 |
COPY . /app
|
6 |
|
7 |
-
|
|
|
|
|
8 |
|
9 |
-
|
|
|
|
4 |
|
5 |
COPY . /app
|
6 |
|
7 |
+
# Instala dependências otimizadas
|
8 |
+
RUN pip install --no-cache-dir -r requirements.txt \
|
9 |
+
&& pip install --no-cache-dir transformers accelerate
|
10 |
|
11 |
+
# Define o comando de execução
|
12 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
app.py
CHANGED
@@ -1,34 +1,76 @@
|
|
1 |
from fastapi import FastAPI
|
2 |
from transformers import pipeline
|
|
|
|
|
3 |
|
4 |
app = FastAPI()
|
5 |
|
6 |
-
#
|
|
|
|
|
|
|
|
|
7 |
ptt5 = pipeline(
|
8 |
"text2text-generation",
|
9 |
-
model="unicamp-dl/ptt5-base-portuguese-
|
10 |
-
tokenizer="unicamp-dl/ptt5-base-portuguese-
|
|
|
|
|
11 |
)
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
@app.get("/generate")
|
14 |
async def generate_question(theme: str, difficulty: str):
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
"Inclua: enunciado clínico, 4 alternativas (A, B, C, D), gabarito e explicação."
|
19 |
-
)
|
20 |
-
response = ptt5(prompt, max_new_tokens=512, temperature=0.7, top_p=0.9)[0]['generated_text']
|
21 |
-
return {"question": response}
|
22 |
|
23 |
@app.get("/simulado")
|
24 |
async def get_simulado(num_questions: int = 5):
|
25 |
simulado = []
|
26 |
for _ in range(num_questions):
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
result = ptt5(prompt, max_new_tokens=512, temperature=0.7, top_p=0.9)[0]['generated_text']
|
33 |
-
simulado.append({"question": result})
|
34 |
-
return {"simulado": simulado}
|
|
|
1 |
from fastapi import FastAPI
|
2 |
from transformers import pipeline
|
3 |
+
import json
|
4 |
+
import os
|
5 |
|
6 |
app = FastAPI()
|
7 |
|
8 |
+
# Carrega o arquivo questions.json
|
9 |
+
with open("questions.json", "r", encoding="utf-8") as f:
|
10 |
+
examples = json.load(f)
|
11 |
+
|
12 |
+
# Configuração do modelo PTT5
|
13 |
ptt5 = pipeline(
|
14 |
"text2text-generation",
|
15 |
+
model="unicamp-dl/ptt5-base-portuguese-vocab",
|
16 |
+
tokenizer="unicamp-dl/ptt5-base-portuguese-vocab",
|
17 |
+
device_map="auto" if os.getenv("HF_TOKEN") else None,
|
18 |
+
model_kwargs={"load_in_8bit": True if os.getenv("HF_TOKEN") else False}
|
19 |
)
|
20 |
|
21 |
+
def generate_question_from_prompt(theme, difficulty, example_question=None):
|
22 |
+
if example_question:
|
23 |
+
example_text = (
|
24 |
+
f"Enunciado clínico: {example_question['question'].split('Considerando')[-1].strip()} "
|
25 |
+
f"Alternativas: {', '.join(example_question['options'])} "
|
26 |
+
f"Gabarito: {example_question['answer']} "
|
27 |
+
f"Explicação: {example_question['explanation']}"
|
28 |
+
)
|
29 |
+
prompt = (
|
30 |
+
f"Baseado no exemplo: '{example_text}', gere uma nova questão de múltipla escolha "
|
31 |
+
f"sobre o tema '{theme}', com dificuldade {difficulty}, no estilo da prova de residência médica da USP. "
|
32 |
+
"Use o formato: 'Enunciado clínico: [texto detalhado com dados do paciente, exames e pergunta]. "
|
33 |
+
"Alternativas: A) [opção], B) [opção], C) [opção], D) [opção]. Gabarito: [letra]. "
|
34 |
+
"Explicação: [texto].'"
|
35 |
+
)
|
36 |
+
else:
|
37 |
+
prompt = (
|
38 |
+
f"Gere uma questão de múltipla escolha sobre o tema '{theme}', "
|
39 |
+
f"com dificuldade {difficulty}, no estilo da prova de residência médica da USP. "
|
40 |
+
"Use o formato: 'Enunciado clínico: [texto detalhado com dados do paciente, exames e pergunta]. "
|
41 |
+
"Alternativas: A) [opção], B) [opção], C) [opção], D) [opção]. Gabarito: [letra]. "
|
42 |
+
"Explicação: [texto].'"
|
43 |
+
)
|
44 |
+
response = ptt5(prompt, max_new_tokens=512, temperature=0.7, top_p=0.9)[0]['generated_text']
|
45 |
+
# Parseia a resposta para extrair os componentes
|
46 |
+
parts = response.split("Alternativas:")
|
47 |
+
if len(parts) > 1:
|
48 |
+
question_part = parts[0].replace("Enunciado clínico:", "").strip()
|
49 |
+
options_part = parts[1].split("Gabarito:")[0].strip()
|
50 |
+
answer_part = parts[1].split("Gabarito:")[1].split("Explicação:")[0].strip()
|
51 |
+
explanation_part = parts[1].split("Explicação:")[1].strip() if "Explicação:" in parts[1] else "Explicação padrão"
|
52 |
+
options = [opt.strip() for opt in options_part.split(",")]
|
53 |
+
if len(options) >= 4:
|
54 |
+
return {
|
55 |
+
"question": f"Enunciado clínico: {question_part}",
|
56 |
+
"options": [f"A) {options[0]}", f"B) {options[1]}", f"C) {options[2]}", f"D) {options[3]}"],
|
57 |
+
"answer": answer_part,
|
58 |
+
"explanation": explanation_part
|
59 |
+
}
|
60 |
+
return {"question": response, "options": [], "answer": "", "explanation": "Explicação padrão"}
|
61 |
+
|
62 |
@app.get("/generate")
|
63 |
async def generate_question(theme: str, difficulty: str):
|
64 |
+
# Usa o primeiro exemplo como base
|
65 |
+
example = examples[0] if examples else None
|
66 |
+
return generate_question_from_prompt(theme, difficulty, example)
|
|
|
|
|
|
|
|
|
67 |
|
68 |
@app.get("/simulado")
|
69 |
async def get_simulado(num_questions: int = 5):
|
70 |
simulado = []
|
71 |
for _ in range(num_questions):
|
72 |
+
# Alterna entre exemplos para diversificar
|
73 |
+
example = examples[_ % len(examples)] if examples else None
|
74 |
+
question_data = generate_question_from_prompt("clinica medica", "medio", example)
|
75 |
+
simulado.append(question_data)
|
76 |
+
return {"simulado": simulado}
|
|
|
|
|
|
index.html
CHANGED
@@ -1,6 +1,18 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="pt-br">
|
3 |
-
<head
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
<body>
|
5 |
<h1>Simulado</h1>
|
6 |
<button onclick="loadSimulado()">Carregar</button>
|
@@ -9,7 +21,8 @@
|
|
9 |
async function loadSimulado() {
|
10 |
const response = await fetch('/simulado?num_questions=5');
|
11 |
const data = await response.json();
|
12 |
-
document.getElementById('questions')
|
|
|
13 |
}
|
14 |
</script>
|
15 |
</body>
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="pt-br">
|
3 |
+
<head>
|
4 |
+
<title>Simulado USP</title>
|
5 |
+
<style>
|
6 |
+
body { font-family: Arial, sans-serif; margin: 20px; }
|
7 |
+
h1 { color: #2c3e50; }
|
8 |
+
button { padding: 10px 20px; background: #3498db; color: white; border: none; cursor: pointer; }
|
9 |
+
button:hover { background: #2980b9; }
|
10 |
+
#questions { margin-top: 20px; }
|
11 |
+
ul { list-style-type: upper-alpha; padding-left: 20px; }
|
12 |
+
li { margin-bottom: 5px; }
|
13 |
+
.question { border-bottom: 1px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 10px; }
|
14 |
+
</style>
|
15 |
+
</head>
|
16 |
<body>
|
17 |
<h1>Simulado</h1>
|
18 |
<button onclick="loadSimulado()">Carregar</button>
|
|
|
21 |
async function loadSimulado() {
|
22 |
const response = await fetch('/simulado?num_questions=5');
|
23 |
const data = await response.json();
|
24 |
+
const questionsDiv = document.getElementById('questions');
|
25 |
+
questionsDiv.innerHTML = data.simulado.map(q => `<div class="question">${q.question.replace(/\n/g, '<br>')}</div>`).join('');
|
26 |
}
|
27 |
</script>
|
28 |
</body>
|
requirements.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
fastapi
|
2 |
-
uvicorn
|
3 |
-
transformers
|
4 |
-
|
|
|
1 |
+
fastapi==0.103.2
|
2 |
+
uvicorn==0.23.2
|
3 |
+
transformers==4.35.0
|
4 |
+
accelerate==0.21.0
|