Código-fonte para aibox.nlp.features.portuguese.orthography

"""Características relacionadas com ortografia."""

import re
from dataclasses import dataclass

import spacy

from aibox.nlp.core import FeatureExtractor
from aibox.nlp.features.utils import DataclassFeatureSet
from aibox.nlp.lazy_loading import lazy_import

langtool = lazy_import("language_tool_python")


[documentos] @dataclass(frozen=True) class OrtographyFeatures(DataclassFeatureSet): """Características de domínio ortográfico. Para mais informações sobre as características, acessar as referências. Referências: `[1] <https://doi.org/10.5753/wapla.2023.236084>`_: Silva Filho, M. W. da, Nascimento, A. C. A., Miranda, P., Rodrigues, L., Cordeiro, T., Isotani, S., Bittencourt, I. I., & Mello, R. F. (2023). Automated Formal Register Scoring of Student Narrative Essays Written in Portuguese. In Anais do II Workshop de Aplicações Práticas de Learning Analytics em Instituições de Ensino no Brasil (WAPLA 2023) (pp. 1–11). Workshop de Aplicações Práticas de Learning Analytics em Instituições de Ensino no Brasil. Sociedade Brasileira de Computação. """ ortography_score: float
[documentos] class OrthographyExtractor(FeatureExtractor): """Extrator de características ortográficas. :param tool: instância do LanguageTool. Exemplo de uso em :py:class:`~aibox.nlp.core.feature_extractor.FeatureExtractor` """ def __init__(self, tool: langtool.LanguageTool = None): self._tool = tool self._tokenizer_pattern = re.compile(r"\s+") self._tokenizer = spacy.tokenizer.Tokenizer( spacy.blank("pt").vocab, token_match=self._tokenizer_pattern.match ) self._rules = { "Encontrado possível erro de ortografia.", "Palavras estrangeiras com diacríticos", "Uso de apóstrofe para palavras no plural", "Femininos irregulares", "Erro ortográfico: Abreviaturas da internet", "Palavras raras facilmente confundidas", "Palavras raras: Capitalização de nomes geográficos", } @property def feature_set(self) -> type[OrtographyFeatures]: return OrtographyFeatures
[documentos] def extract(self, text: str, **kwargs) -> OrtographyFeatures: del kwargs self._maybe_load_models() # Limpeza do texto (pontuação, whitespace, etc) text = self._cleaner(text) # Obter tokens (palavras) tokens = [token.text for token in self._tokenizer(text)] # Inicializando features score = 0.0 # Calcular os erros ortográficos presentes no texto errors = self._check(text) score = 1.0 - (len(errors) / len(tokens)) return OrtographyFeatures(ortography_score=score)
def _check(self, text: str) -> list[dict[str, str]]: # Realizar uma checagem no texto utilizando o LanguageTool matches = self._tool.check(text) # Lista dos erros errors = [] for match in matches: # Caso sejam encontrados erros de ortografia: if match.message in self._rules: error_dict = {} correct_token = "" # Obter token/palavra original errôneo offset = match.offset length = match.errorLength token = text[offset : offset + length] # Buscar se existe um candidato à substituição if len(match.replacements) > 0: correct_token = match.replacements[0] # Adicionar informações no dicionário para esse erro error_dict["token"] = token error_dict["correct_token"] = correct_token # Adicionar esse erro na lista errors.append(error_dict) return errors def _maybe_load_models(self): if self._tool is None: self._tool = langtool.LanguageTool("pt-BR") def __getstate__(self) -> dict: d = self.__dict__.copy() for k in {"_tool"}: d[k] = None return d @staticmethod def _cleaner(text: str): text = text.strip() text = re.sub(r"[!\.,—]", "", text) text = re.sub(r"\s+", " ", text) return text[0].upper() + text[1:]