diff --git a/Guia3/src/alternativa.py b/Guia3/src/alternativa.py index 4dde61f..3dc1efc 100644 --- a/Guia3/src/alternativa.py +++ b/Guia3/src/alternativa.py @@ -1,4 +1,10 @@ from typing import List, Tuple, Dict class Alternativa: - pass \ No newline at end of file + def __init__(self, texto: str, correta: bool, explicacao=None): + self.texto = texto + self.correta = correta + self.explicacao = explicacao + + + \ No newline at end of file diff --git a/Guia3/src/pergunta.py b/Guia3/src/pergunta.py index 5b3763d..2266612 100644 --- a/Guia3/src/pergunta.py +++ b/Guia3/src/pergunta.py @@ -1,4 +1,17 @@ from typing import List, Tuple, Dict +from abc import ABC, abstractmethod +class Pergunta(ABC): + def __init__(self, texto, explicacao_geral=None): + self.__texto = texto + self.__explicacao_geral = explicacao_geral -class Pergunta: - pass \ No newline at end of file + @abstractmethod + def validar_resposta(self, resposta) -> bool: + pass + + def get_explicacao(self): + return self.__explicacao_geral + + @abstractmethod + def get_tipo(self) -> str: + pass \ No newline at end of file diff --git a/Guia3/src/perguntadiscursiva.py b/Guia3/src/perguntadiscursiva.py index f4c26af..46e4294 100644 --- a/Guia3/src/perguntadiscursiva.py +++ b/Guia3/src/perguntadiscursiva.py @@ -1,4 +1,21 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta -class PerguntaDiscursiva: - pass \ No newline at end of file +class PerguntaDiscursiva(Pergunta): + def __init__(self, texto, explicacao_geral=None, resposta_esperada=None): + super().__init__(texto, explicacao_geral) + self.resposta_esperada = resposta_esperada + + def validar_resposta(self, resposta) -> bool: + if self.resposta_esperada is None or resposta is None: + return False + + return resposta.lower() == self.resposta_esperada.lower() + + def get_tipo(self) -> str: + return "discursiva" + + + + + diff --git a/Guia3/src/perguntamultiplaescolha.py b/Guia3/src/perguntamultiplaescolha.py index bcbe94d..b60cc68 100644 --- a/Guia3/src/perguntamultiplaescolha.py +++ b/Guia3/src/perguntamultiplaescolha.py @@ -1,4 +1,26 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta +from .alternativa import Alternativa -class PerguntaMultiplaEscolha: - pass \ No newline at end of file +class PerguntaMultiplaEscolha(Pergunta): + def __init__(self, texto, alternativas, explicacao_geral=None): + super().__init__(texto, explicacao_geral) + self.alternativas = alternativas or [] + + def validar_resposta(self, indice: int) -> bool: + if indice is None or indice < 0 or indice >= len(self.alternativas): + return False + + return self.alternativas[indice] == self.get_alternativa_correta() + + def get_alternativa_correta(self) -> Alternativa: + for alternativa in self.alternativas: + if alternativa.correta == True: + return alternativa + return None + + def get_tipo(self) -> str: + return "multipla_escolha" + + + diff --git a/Guia3/src/questionario.py b/Guia3/src/questionario.py index 7525582..09760a5 100644 --- a/Guia3/src/questionario.py +++ b/Guia3/src/questionario.py @@ -1,4 +1,19 @@ from typing import List, Tuple, Dict +from .tentativaquestionario import TentativaQuestionario class Questionario: - pass + def __init__(self, titulo: str): + self.perguntas = [] + self.__titulo = titulo + + def registrar_resposta(self, indice_pergunta, valor): + pass + + def adicionar_pergunta(self, p): + self.perguntas.append(p) + + def criar_attempt(self, usuario): + tentativa = TentativaQuestionario(self, usuario) + return tentativa + + diff --git a/Guia3/src/resposta.py b/Guia3/src/resposta.py index 846d771..b1ba1df 100644 --- a/Guia3/src/resposta.py +++ b/Guia3/src/resposta.py @@ -1,4 +1,11 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta +from abc import ABC, abstractmethod +class Resposta(ABC): + def __init__(self, pergunta: Pergunta, esta_correta: bool, pontuacao_obtida=None): + self.__pergunta = pergunta + self.esta_correta = esta_correta + self.pontuacao_obtida = pontuacao_obtida -class Resposta: - pass \ No newline at end of file + + \ No newline at end of file diff --git a/Guia3/src/respostadiscursiva.py b/Guia3/src/respostadiscursiva.py index 4ea6dbb..12ad20f 100644 --- a/Guia3/src/respostadiscursiva.py +++ b/Guia3/src/respostadiscursiva.py @@ -1,4 +1,14 @@ from typing import List, Tuple, Dict +from .resposta import Resposta -class RespostaDiscursiva: - pass \ No newline at end of file +class RespostaDiscursiva(Resposta): + def __init__(self, pergunta, texto_resposta, pontuacao_obtida=None): + self.texto_resposta = texto_resposta + esta_correta = pergunta.validar_resposta(texto_resposta) + super().__init__(pergunta, esta_correta, pontuacao_obtida) + + def calcular_pontuacao(self): + if self.esta_correta: + return 1.0 + else: + return 0.0 \ No newline at end of file diff --git a/Guia3/src/respostaobjetiva.py b/Guia3/src/respostaobjetiva.py index 72ed2d0..a03dbb5 100644 --- a/Guia3/src/respostaobjetiva.py +++ b/Guia3/src/respostaobjetiva.py @@ -1,4 +1,15 @@ from typing import List, Tuple, Dict +from .resposta import Resposta +class RespostaObjetiva(Resposta): + def __init__(self, pergunta, indice_escolhido, pontuacao_obtida=None): + self.indice_escolhido = indice_escolhido + esta_correta = pergunta.validar_resposta(indice_escolhido) + super().__init__(pergunta, esta_correta, pontuacao_obtida) -class RespostaObjetiva: - pass \ No newline at end of file + def calcular_pontuacao(self): + if self.esta_correta: + return 1.0 + else: + return 0.0 + + \ No newline at end of file diff --git a/Guia3/src/tentativaquestionario.py b/Guia3/src/tentativaquestionario.py index 9947dd1..9a0f684 100644 --- a/Guia3/src/tentativaquestionario.py +++ b/Guia3/src/tentativaquestionario.py @@ -1,4 +1,43 @@ from typing import List, Tuple, Dict +from .perguntamultiplaescolha import PerguntaMultiplaEscolha +from .respostaobjetiva import RespostaObjetiva +from .respostadiscursiva import RespostaDiscursiva class TentativaQuestionario: - pass \ No newline at end of file + def __init__(self, questionario, usuario, data_inicio=None, data_fim=None): + self.__questionario = questionario + self.usuario = usuario + self.__data_inicio = data_inicio + self.__data_fim = data_fim + self.respostas = [] + self.__finalizado = False + + def registrar_resposta(self, indice_pergunta, valor): + pergunta = self.__questionario.perguntas[indice_pergunta] + + if isinstance(pergunta, PerguntaMultiplaEscolha): + resposta = RespostaObjetiva(pergunta=pergunta, indice_escolhido=valor) + else: + resposta = RespostaDiscursiva(pergunta=pergunta, texto_resposta=valor) + + self.respostas.append(resposta) + return resposta + + def adicionar_pergunta(self, p): + self.__questionario.adicionar_pergunta(p) + + def finalizar(self): + self.__finalizado = True + pontuacao = self.calcular_pontuacao() + feedback = f"Pontuação final: {pontuacao}" + return pontuacao, feedback + + def calcular_pontuacao(self): + return sum( + resposta.calcular_pontuacao() + for resposta in self.respostas + ) + + def is_finalizado(self): + return self.__finalizado + diff --git a/Guia4/src/alternativa.py b/Guia4/src/alternativa.py index 4dde61f..3dc1efc 100644 --- a/Guia4/src/alternativa.py +++ b/Guia4/src/alternativa.py @@ -1,4 +1,10 @@ from typing import List, Tuple, Dict class Alternativa: - pass \ No newline at end of file + def __init__(self, texto: str, correta: bool, explicacao=None): + self.texto = texto + self.correta = correta + self.explicacao = explicacao + + + \ No newline at end of file diff --git a/Guia4/src/correcao.py b/Guia4/src/correcao.py index bdf2fa4..2174430 100644 --- a/Guia4/src/correcao.py +++ b/Guia4/src/correcao.py @@ -1,4 +1,23 @@ -from typing import List, Tuple, Dict +from typing import Dict +from llmservice import LLMService +from perguntadiscursiva import PerguntaDiscursiva + class Correcao: - pass \ No newline at end of file + def corrigir_discursiva(self, pergunta: PerguntaDiscursiva, resposta_aluno: str, service: LLMService = None) -> Dict: + if service is None: + service = LLMService() + return service.corrigir_resposta(pergunta, resposta_aluno) + + def criar_prompt_correcao(self, pergunta: PerguntaDiscursiva, resposta_aluno: str) -> str: + if pergunta is None: + return "" + + return ( + "Você é um corretor de respostas para perguntas discursivas. " + "Avalie a resposta do aluno e responda em JSON.\n" + f"Pergunta: {getattr(pergunta, '_Pergunta__texto', None) or getattr(pergunta, 'texto', None) or ''}\n" + f"Resposta esperada: {getattr(pergunta, 'resposta_esperada', None) or ''}\n" + f"Resposta do aluno: {resposta_aluno}\n" + f"Explicacao geral: {pergunta.get_explicacao() or ''}\n" + ) \ No newline at end of file diff --git a/Guia4/src/llmservice.py b/Guia4/src/llmservice.py index e6e91b5..ba0a964 100644 --- a/Guia4/src/llmservice.py +++ b/Guia4/src/llmservice.py @@ -1,4 +1,50 @@ -from typing import List, Tuple, Dict +from typing import Dict +from perguntadiscursiva import PerguntaDiscursiva +from perguntadiscursiva import PerguntaDiscursiva +from groq import Groq class LLMService: - pass \ No newline at end of file + def __init__(self, api_key: str = None, model: str = "llama3-70b-8192"): + self.__api_key = api_key + self.__model = model + self.__base_url + + def corrigir_resposta(self, pergunta: PerguntaDiscursiva, resposta_aluno: str) -> Dict: + if pergunta is None or resposta_aluno is None: + return {"correta": False, "pontuacao": 0.0, "feedback": "Resposta inválida.", "explicacao": ""} + + if pergunta.validar_resposta(resposta_aluno): + return {"correta": True, "pontuacao": 1.0, "feedback": "Resposta correta.", "explicacao": pergunta.get_explicacao() or ""} + + prompt = ( + "Você é um corretor de respostas para perguntas discursivas. " + "Responda apenas em JSON com as chaves correta, pontuacao, feedback e explicacao.\n" + f"Pergunta: {getattr(pergunta, '_Pergunta__texto', None) or getattr(pergunta, 'texto', None) or ''}\n" + f"Resposta esperada: {getattr(pergunta, 'resposta_esperada', None) or ''}\n" + f"Resposta do aluno: {resposta_aluno}\n" + f"Explicacao geral: {pergunta.get_explicacao() or ''}\n" + ) + resposta_api = self._fazer_chamada_api(prompt) + + if not resposta_api: + return {"correta": False, "pontuacao": 0.0, "feedback": "Falha na correção automática.", "explicacao": pergunta.get_explicacao() or ""} + + + def _fazer_chamada_api(self, prompt: str) -> str: + if not self.__api_key: + return "" + + try: + llm = Groq(api_key=self.__api_key) + completion = llm.chat.completions.create( + model=self.__model, + messages=[{"role": "user", "content": prompt}], + temperature=0.2, + ) + return getattr(completion.choices[0].message, "content", "") + except Exception as e: + self._tratar_erro(e) + return "" + + def _tratar_erro(self, e: Exception) -> None: + print(e) diff --git a/Guia4/src/pergunta.py b/Guia4/src/pergunta.py index 5b3763d..2266612 100644 --- a/Guia4/src/pergunta.py +++ b/Guia4/src/pergunta.py @@ -1,4 +1,17 @@ from typing import List, Tuple, Dict +from abc import ABC, abstractmethod +class Pergunta(ABC): + def __init__(self, texto, explicacao_geral=None): + self.__texto = texto + self.__explicacao_geral = explicacao_geral -class Pergunta: - pass \ No newline at end of file + @abstractmethod + def validar_resposta(self, resposta) -> bool: + pass + + def get_explicacao(self): + return self.__explicacao_geral + + @abstractmethod + def get_tipo(self) -> str: + pass \ No newline at end of file diff --git a/Guia4/src/perguntadiscursiva.py b/Guia4/src/perguntadiscursiva.py index f4c26af..46e4294 100644 --- a/Guia4/src/perguntadiscursiva.py +++ b/Guia4/src/perguntadiscursiva.py @@ -1,4 +1,21 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta -class PerguntaDiscursiva: - pass \ No newline at end of file +class PerguntaDiscursiva(Pergunta): + def __init__(self, texto, explicacao_geral=None, resposta_esperada=None): + super().__init__(texto, explicacao_geral) + self.resposta_esperada = resposta_esperada + + def validar_resposta(self, resposta) -> bool: + if self.resposta_esperada is None or resposta is None: + return False + + return resposta.lower() == self.resposta_esperada.lower() + + def get_tipo(self) -> str: + return "discursiva" + + + + + diff --git a/Guia4/src/perguntamultiplaescolha.py b/Guia4/src/perguntamultiplaescolha.py index bcbe94d..b60cc68 100644 --- a/Guia4/src/perguntamultiplaescolha.py +++ b/Guia4/src/perguntamultiplaescolha.py @@ -1,4 +1,26 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta +from .alternativa import Alternativa -class PerguntaMultiplaEscolha: - pass \ No newline at end of file +class PerguntaMultiplaEscolha(Pergunta): + def __init__(self, texto, alternativas, explicacao_geral=None): + super().__init__(texto, explicacao_geral) + self.alternativas = alternativas or [] + + def validar_resposta(self, indice: int) -> bool: + if indice is None or indice < 0 or indice >= len(self.alternativas): + return False + + return self.alternativas[indice] == self.get_alternativa_correta() + + def get_alternativa_correta(self) -> Alternativa: + for alternativa in self.alternativas: + if alternativa.correta == True: + return alternativa + return None + + def get_tipo(self) -> str: + return "multipla_escolha" + + + diff --git a/Guia4/src/questionario.py b/Guia4/src/questionario.py index 7525582..09760a5 100644 --- a/Guia4/src/questionario.py +++ b/Guia4/src/questionario.py @@ -1,4 +1,19 @@ from typing import List, Tuple, Dict +from .tentativaquestionario import TentativaQuestionario class Questionario: - pass + def __init__(self, titulo: str): + self.perguntas = [] + self.__titulo = titulo + + def registrar_resposta(self, indice_pergunta, valor): + pass + + def adicionar_pergunta(self, p): + self.perguntas.append(p) + + def criar_attempt(self, usuario): + tentativa = TentativaQuestionario(self, usuario) + return tentativa + + diff --git a/Guia4/src/resposta.py b/Guia4/src/resposta.py index 846d771..b1ba1df 100644 --- a/Guia4/src/resposta.py +++ b/Guia4/src/resposta.py @@ -1,4 +1,11 @@ from typing import List, Tuple, Dict +from .pergunta import Pergunta +from abc import ABC, abstractmethod +class Resposta(ABC): + def __init__(self, pergunta: Pergunta, esta_correta: bool, pontuacao_obtida=None): + self.__pergunta = pergunta + self.esta_correta = esta_correta + self.pontuacao_obtida = pontuacao_obtida -class Resposta: - pass \ No newline at end of file + + \ No newline at end of file diff --git a/Guia4/src/respostadiscursiva.py b/Guia4/src/respostadiscursiva.py index 4ea6dbb..12ad20f 100644 --- a/Guia4/src/respostadiscursiva.py +++ b/Guia4/src/respostadiscursiva.py @@ -1,4 +1,14 @@ from typing import List, Tuple, Dict +from .resposta import Resposta -class RespostaDiscursiva: - pass \ No newline at end of file +class RespostaDiscursiva(Resposta): + def __init__(self, pergunta, texto_resposta, pontuacao_obtida=None): + self.texto_resposta = texto_resposta + esta_correta = pergunta.validar_resposta(texto_resposta) + super().__init__(pergunta, esta_correta, pontuacao_obtida) + + def calcular_pontuacao(self): + if self.esta_correta: + return 1.0 + else: + return 0.0 \ No newline at end of file diff --git a/Guia4/src/respostaobjetiva.py b/Guia4/src/respostaobjetiva.py index 72ed2d0..a03dbb5 100644 --- a/Guia4/src/respostaobjetiva.py +++ b/Guia4/src/respostaobjetiva.py @@ -1,4 +1,15 @@ from typing import List, Tuple, Dict +from .resposta import Resposta +class RespostaObjetiva(Resposta): + def __init__(self, pergunta, indice_escolhido, pontuacao_obtida=None): + self.indice_escolhido = indice_escolhido + esta_correta = pergunta.validar_resposta(indice_escolhido) + super().__init__(pergunta, esta_correta, pontuacao_obtida) -class RespostaObjetiva: - pass \ No newline at end of file + def calcular_pontuacao(self): + if self.esta_correta: + return 1.0 + else: + return 0.0 + + \ No newline at end of file diff --git a/Guia4/src/tentativaquestionario.py b/Guia4/src/tentativaquestionario.py index 9947dd1..9a0f684 100644 --- a/Guia4/src/tentativaquestionario.py +++ b/Guia4/src/tentativaquestionario.py @@ -1,4 +1,43 @@ from typing import List, Tuple, Dict +from .perguntamultiplaescolha import PerguntaMultiplaEscolha +from .respostaobjetiva import RespostaObjetiva +from .respostadiscursiva import RespostaDiscursiva class TentativaQuestionario: - pass \ No newline at end of file + def __init__(self, questionario, usuario, data_inicio=None, data_fim=None): + self.__questionario = questionario + self.usuario = usuario + self.__data_inicio = data_inicio + self.__data_fim = data_fim + self.respostas = [] + self.__finalizado = False + + def registrar_resposta(self, indice_pergunta, valor): + pergunta = self.__questionario.perguntas[indice_pergunta] + + if isinstance(pergunta, PerguntaMultiplaEscolha): + resposta = RespostaObjetiva(pergunta=pergunta, indice_escolhido=valor) + else: + resposta = RespostaDiscursiva(pergunta=pergunta, texto_resposta=valor) + + self.respostas.append(resposta) + return resposta + + def adicionar_pergunta(self, p): + self.__questionario.adicionar_pergunta(p) + + def finalizar(self): + self.__finalizado = True + pontuacao = self.calcular_pontuacao() + feedback = f"Pontuação final: {pontuacao}" + return pontuacao, feedback + + def calcular_pontuacao(self): + return sum( + resposta.calcular_pontuacao() + for resposta in self.respostas + ) + + def is_finalizado(self): + return self.__finalizado +