Skip to content

Commit 3c9fdce

Browse files
committed
feat: valida unicidade das perguntas e aprimora validacoes do quiz
1 parent cb31d9c commit 3c9fdce

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

backend/app/schemas/quiz_schemas.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from pydantic import BaseModel, ConfigDict, Field
1+
from pydantic import BaseModel, ConfigDict, Field, field_validator
22

33

44
class CreateQuizSchema(BaseModel):
@@ -36,4 +36,17 @@ class QuizResponseSchema(BaseModel):
3636
model_config = ConfigDict(populate_by_name=True)
3737

3838
questions: list[QuestionSchema] = Field(alias="perguntas")
39+
40+
@field_validator('questions')
41+
@classmethod
42+
def validate_unique_questions(cls, v):
43+
if not v:
44+
raise ValueError("Lista de questões não pode estar vazia")
45+
46+
# Verificar se há questões duplicadas
47+
questions_text = [q.question.strip().lower() for q in v]
48+
if len(questions_text) != len(set(questions_text)):
49+
raise ValueError("Questões duplicadas detectadas")
50+
51+
return v
3952

backend/app/services/llm/agente_quiz.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,37 @@ def create_quiz(self, num_questions: int = 5, num_alternatives: int = 4):
4444
response_text = response_text.split("```")[1].split("```")[0].strip()
4545

4646
try:
47-
return json.loads(response_text)
47+
parsed_response = json.loads(response_text)
48+
49+
# Validar estrutura básica
50+
if "perguntas" not in parsed_response:
51+
raise ValueError("Resposta não contém campo 'perguntas'")
52+
53+
questions = parsed_response["perguntas"]
54+
55+
# Validar número de questões
56+
if len(questions) != num_questions:
57+
raise ValueError(f"Esperado {num_questions} questões, mas recebeu {len(questions)}")
58+
59+
# Validar questões únicas
60+
questions_text = [q.get("pergunta", "").strip().lower() for q in questions]
61+
if len(questions_text) != len(set(questions_text)):
62+
raise ValueError("Questões duplicadas detectadas na resposta do LLM")
63+
64+
# Validar número de alternativas por questão
65+
for i, question in enumerate(questions):
66+
if "alternativas" not in question:
67+
raise ValueError(f"Questão {i+1} não contém alternativas")
68+
69+
alternatives = question["alternativas"]
70+
if len(alternatives) != num_alternatives:
71+
raise ValueError(f"Questão {i+1}: esperado {num_alternatives} alternativas, mas recebeu {len(alternatives)}")
72+
73+
# Verificar se há exatamente uma alternativa correta
74+
correct_count = sum(1 for alt in alternatives if alt.get("correta", False))
75+
if correct_count != 1:
76+
raise ValueError(f"Questão {i+1}: deve ter exatamente 1 alternativa correta, mas tem {correct_count}")
77+
78+
return parsed_response
4879
except json.JSONDecodeError:
4980
raise ValueError(f"Error parsing response: {response_text}")

backend/app/services/llm/prompts/promtps.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
TEXTO:
44
{text}
55
6-
INSTRUÇÕES:
7-
1. Crie {num_questions} perguntas baseadas no texto acima.
8-
2. Crie {num_alternatives} alternativas para cada pergunta.
6+
INSTRUÇÕES CRÍTICAS:
7+
1. Crie EXATAMENTE {num_questions} perguntas ÚNICAS e DIFERENTES baseadas no texto acima.
8+
2. Crie EXATAMENTE {num_alternatives} alternativas para cada pergunta.
99
3. Cada pergunta deve ter exatamente {num_alternatives} alternativas.
1010
4. Apenas uma alternativa deve estar correta para cada pergunta.
11-
5. Indique qual alternativa é a correta para cada pergunta.
12-
6. Para cada alternativa, inclua um campo "explicacao" que explique brevemente:
11+
5. NUNCA repita perguntas - cada pergunta deve ser única e abordar aspectos diferentes do texto.
12+
6. NUNCA duplique o conteúdo - retorne apenas uma vez cada pergunta.
13+
7. Indique qual alternativa é a correta para cada pergunta.
14+
8. Para cada alternativa, inclua um campo "explicacao" que explique brevemente:
1315
- Para a alternativa correta: por que ela está correta
1416
- Para as alternativas incorretas: por que estão incorretas
15-
7. Retorne os dados em formato JSON exatamente como no exemplo a seguir, sem texto adicional:
17+
9. Retorne os dados em formato JSON exatamente como no exemplo a seguir, sem texto adicional:
1618
1719
```json
1820
{{
@@ -51,6 +53,12 @@
5153
}}
5254
```
5355
54-
Importante: As explicações devem ser concisas (curta) e baseadas nas informações do texto. Para alternativas corretas, explique por que estão certas; para incorretas, explique por que estão erradas seja curto mas detalhado ter uma boa explicação.
56+
IMPORTANTE:
57+
- As explicações devem ser concisas e baseadas nas informações do texto
58+
- Para alternativas corretas, explique por que estão certas
59+
- Para incorretas, explique por que estão erradas
60+
- RETORNE EXATAMENTE {num_questions} perguntas, nem mais nem menos
61+
- NUNCA duplique perguntas ou conteúdo
62+
- Cada pergunta deve ser única e diferente das outras
5563
5664
"""

0 commit comments

Comments
 (0)