healthtechbrasil commited on
Commit
ffa0c53
·
1 Parent(s): e357624

unicamp fix com json

Browse files
Files changed (4) hide show
  1. Dockerfile +5 -2
  2. app.py +60 -18
  3. index.html +15 -2
  4. requirements.txt +4 -4
Dockerfile CHANGED
@@ -4,6 +4,9 @@ WORKDIR /app
4
 
5
  COPY . /app
6
 
7
- RUN pip install --no-cache-dir -r requirements.txt
 
 
8
 
9
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
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
- # Carregando o modelo correto: ptt5 (text2text-generation)
 
 
 
 
7
  ptt5 = pipeline(
8
  "text2text-generation",
9
- model="unicamp-dl/ptt5-base-portuguese-text2text",
10
- tokenizer="unicamp-dl/ptt5-base-portuguese-text2text"
 
 
11
  )
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  @app.get("/generate")
14
  async def generate_question(theme: str, difficulty: str):
15
- prompt = (
16
- f"Gere uma questão de múltipla escolha sobre o tema '{theme}', "
17
- f"com dificuldade {difficulty}, no estilo da prova de residência médica da USP. "
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
- prompt = (
28
- "Gere uma questão de múltipla escolha sobre clínica médica, nível médio, "
29
- "no estilo da prova de residência da USP. "
30
- "Inclua: enunciado clínico, 4 alternativas (A, B, C, D), gabarito e explicação."
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><title>Simulado USP</title></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').innerHTML = data.simulado.map(q => `<p>${q.question}</p><ul><li>A)</li><li>B)</li><li>C)</li><li>D)</li></ul>`).join('');
 
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
- torch
 
1
+ fastapi==0.103.2
2
+ uvicorn==0.23.2
3
+ transformers==4.35.0
4
+ accelerate==0.21.0