def generate_model_data(self, model_seed, path, max_dist): """ A partir de una model_seed, crea los archivos de configuración para modificar el tokenizer de un modelo de spacy. :model_seed: [Dict] - Semilla para la creación del modelo. :base_path: [String] - Directorio base del modelo. :max_dist: [int] - Distancia de demerau levenshtein máxima para las deformaciones a los token. """ base_path = build_path(TOKEN_RULES_GEN_TMP_ROOT_PATH, path) if check_dir_existence(base_path): ErrorHandler.raise_error('E-0027') Logger.log('L-0003') create_dir_if_not_exist(base_path) self.__save_model_seed(model_seed, base_path) nouns_path = build_path(base_path, TOKEN_RULES_GEN_TYPE_NOUN) create_dir_if_not_exist(nouns_path) verbs_path = build_path(base_path, TOKEN_RULES_GEN_TYPE_VERB) create_dir_if_not_exist(verbs_path) self.__generate_noun_rules(model_seed['nouns'], max_dist, nouns_path) self.__generate_verb_rules(model_seed['verbs'], max_dist, verbs_path) Logger.log('L-0004') return get_absoulute_path(base_path)
def edit_model_data(self, model_id, new_model_name=None, new_description=None): """ Edita los datos de un modelo existente. Si el modelo no existe u ocurre algún error durante la edición de sus datos devolverá false. :model_id: [String] - Nombre actual del modelo. :new_model_name: [String] - Nuevo nombre a asignar al modelo. :new_description: [String] - Nueva descripción para el modelo. """ Logger.log('L-0074') current_model = self.__model_manager.get_model(model_id) if current_model is None: ErrorHandler.raise_error('E-0074') current_model_name = current_model.get_model_name() edited_model_name = new_model_name current_description = current_model.get_description() edited_description = new_description if new_model_name is None or new_model_name == '': edited_model_name = current_model_name if new_description is None or new_description == '': edited_description = current_description if edited_model_name == current_model_name and edited_description == current_description: ErrorHandler.raise_error('E-0075') self.__model_manager.edit_model(model_id, edited_model_name, edited_description)
def import_model(self, model_id, source=None): """ Importa un modelo existente desde el repositorio de modelos. No debe existir un modelo local con dicho id y, además, el módelo debe existir en el repositorio remoto de modelos. :model_id: [String] - Id del modelo a importar. :source: [Dict] - Fuente de donde obtener el modelo, puede ser un repositorio git o un directorio local. """ Logger.log('L-0116') model = self.get_model(model_id) if model: ErrorHandler.raise_error('E-0118') if not source: source = REMOTE_MODEL_SOURCE cfg = ModelLoader.import_model(model_id, source) analyzer_exceptions_set_data = cfg['analyzer_exceptions_set'] Logger.log('L-0179') ModelDataManager.save_model_data(model_id, cfg['model_name'], cfg['description'], cfg['author'], model_id, cfg['analyzer_rules_set']) remote_model = Model(model_id, cfg['model_name'], cfg['description'], cfg['author'], model_id, cfg['analyzer_rules_set'], []) self.__models.append(remote_model) for exception in analyzer_exceptions_set_data: self.add_analyzer_exception(model_id, exception['base_form'], exception['token_text'], exception['enabled']) Logger.log('L-0188') Logger.log('L-0197')
def update_word_processor_config_theme(self, module_key, theme_name, config_mod, irregular_groups_mod=None): """ Modifica un tema de configuración con los datos provistos. El tema debe existir y no ser el tema por defecto. Se modificarse el tema activo actual el comportamiento del modulo se adaptará inmediatamente. :module_key: [String] - Nombre del submodule del modulo de procesamiento a modificar. :theme_name: [String] - Nombre del tema a modificar. :config_mod: [Dict] - Opciones actualizadas de la configuración general (no es necesario incluir las que no tienen cambio alguno). :irregular_groups_mod: [Dict] - Opciones actualizadas de los grupos de verbos irregulares (no es necesario incluir los grupos que no tienen cambios). """ if module_key == WORD_PROCESSOR_MODULE_KEY_CONJUGATOR: self.__word_processor.update_conjugator_configs(theme_name, config_mod, irregular_groups_mod) return if module_key == WORD_PROCESSOR_MODULE_KEY_FUZZY_GEN: self.__word_processor.update_fuzzy_gen_config(theme_name, config_mod) return if module_key == WORD_PROCESSOR_MODULE_KEY_NOUN_CONV: self.__word_processor.update_noun_conversor_config(theme_name, config_mod) return ErrorHandler.raise_error('E-0049')
def get_examples_history(self, model_id): """ Retorna un listado con todos los ejemplos, sin importar su estado, para un determinado modelo. :model_id: [String] - Id del modelo. :return: [List] - Listado de todos los ejemplos para el modelo solicitado. """ if not self.__find_model(model_id): ErrorHandler.raise_error('E-0082') results = list([]) Logger.log('L-0326') examples_data = db_get_items(TRAIN_MANAGER_DB, TRAIN_DATA_EXAMPLES_COLLECTION, {'model_id': model_id}) Logger.log('L-0327') Logger.log('L-0328') for example_data in examples_data: example = TrainExample(example_data['example_id'], example_data['sentence'], example_data['tags'], example_data['type'], example_data['status']) results.append(example) Logger.log('L-0329') return results
def generate_model(self, model_id, model_name, description, author, tokenizer_exceptions, max_dist): """ Crea un nuevo modelo a partir de los datos provistos. El modelo no debe existir previamente. :model_id: [String] - Id. del modelo. :model_name: [String] - Nombre del modelo (actua como Id). :model_path: [String] - Directorio base para el modelo. :descripcion: [String] - Descripcion del modelo. :author: [String] - Nombre del autor del modelo. :tokenizer_exceptions: [Dict] - Conjunto de excepciones a agregar al tokenizer del nuevo modelo. """ Logger.log('L-0001') if self.__model_manager.get_model(model_id): ErrorHandler.raise_error('E-0025') if not validate_model_seed(tokenizer_exceptions): ErrorHandler.raise_error('E-0026') tokenizer_exceptions_path = self.__tokenizer_rules_generator.generate_model_data(tokenizer_exceptions, model_id, max_dist) analyzer_rule_set = self.__analyzer_rules_generator.create_analyzer_rule_set(tokenizer_exceptions) self.__model_manager.create_model(model_id, model_name, description, author, tokenizer_exceptions_path, analyzer_rule_set) Logger.log('L-0034') if remove_dir(tokenizer_exceptions_path, True): Logger.log('L-0035')
def save_model(model, path, tmp_files_path, new_model): """ Guarda el modelo en el path solicitado. :model: [SpacyModelRef] - Referencia a un modelo de spacy. :path: [String] - Ruta en la cual guardar el modelo. :tmp_files_path: [String] - Ruta donde se encuentran los archivos temporales del modelo. :new_model: [Model] - Objeto que representa el nuevo modelo. """ Logger.log('L-0030') base_path = build_path(MODEL_MANAGER_ROOT_DIR, path) if check_dir_existence(base_path): ErrorHandler.raise_error('E-0030') model_storage_path = get_absoulute_path(base_path) model.to_disk(model_storage_path) custom_model_files_path = build_path(base_path, MODEL_MANAGER_CUSTOM_FILES_DIR) create_dir_if_not_exist(custom_model_files_path) model_seed_path = build_path(tmp_files_path, TOKEN_RULES_GEN_MODEL_SEED_FILENAME) model_seed_copy_path = build_path(custom_model_files_path, TOKEN_RULES_GEN_MODEL_SEED_FILENAME, add_absolute_root=True) copy_file(model_seed_path, model_seed_copy_path, is_absolute_path=True) cfg_file_path = build_path(model_storage_path, MODEL_CONFIG_FILE_NAME) dictionary_to_disk(cfg_file_path, { 'model_name': new_model.get_model_name(), 'description': new_model.get_description(), 'author': new_model.get_author(), 'analyzer_rule_set': new_model.get_analyser_rules_set() }, True) Logger.log('L-0032')
def db_update_many(db_name, col_name, query, updated_item): try: search_query = query if query is not None else {} col = get_collection(db_name, col_name) return col.update_many(search_query, {'$set': updated_item}) except: ErrorHandler.raise_error('E-0008')
def import_model(model_id, source): """ Obtiene los archivos de modelo, los descomprime y obtiene el diccionario de configuración del modelo remoto solicitado. :model_id: [String] - Id del modelo a importar. :return: [Dict] - Dicionario con la configuración del modelo. """ try: local_path = '%s/%s/%s' % (CURRENT_BASE_PATH, MODEL_MANAGER_ROOT_DIR, model_id) model_cfg_file = '%s/%s' % (local_path, MODEL_CONFIG_FILE_NAME) if source['remote']: remote_repo_url = '%s/%s%s' % (source['path'], model_id, MODEL_IMPORT_EXT) Logger.log('L-0134', [{'text': remote_repo_url, 'color': HIGHLIGHT_COLOR}]) Repo.clone_from(remote_repo_url, local_path) else: Logger.log('L-0140', [{'text': source['path'], 'color': HIGHLIGHT_COLOR}]) copy_dir(source['path'], local_path) Logger.log('L-0147') Logger.log('L-0154') unzip_model(local_path, model_id) remove_files(local_path, '%s%s' % (model_id, MODEL_PACKAGING_EXTENSION)) remove_files(local_path, '%s' % MODEL_TMP_JOINT_FILE_NAME) Logger.log('L-0161') return load_json_file(model_cfg_file) except Exception as e: ErrorHandler.raise_error('E-0119', [{'text': e, 'color': ERROR_COLOR}])
def save_model_data(model_id, model_name, description, author, path, analyser_rules_set): """ Guarda información de un modelo. :model_id: [String] - Id del modelo. :model_name: [String] - Nombre del modelo (actua como id). :description: [String] - Descripción del modelo. :author: [String] - Nombre del creador del modelo. :path: [String] - Ruta relativa para encontrar el modelo. :analyser_rules_set: [List(Dict)] - Lista de reglas para el analizador """ Logger.log('L-0026') if ModelDataManager.check_existing_model(model_id): ErrorHandler.raise_error('E-0029') data_dict = { 'model_id': model_id, 'model_name': model_name, 'description': description, 'author': author, 'path': path, 'analyzer_rules_set': analyser_rules_set } db_insert_item(MODEL_MANAGER_DB, MODEL_MANAGER_MODELS_COLLECTION, data_dict) Logger.log('L-0029')
def task_init_hook(self): """ Método hook para completar el template de inicializadion en el padre. """ try: adminModule = AdminModuleController() adminModule.load_model(self.__model_id) for file in self.__files: if not validate_file(file): ErrorHandler.raise_error('E-0096') file_text = file.read() analysis_task = TextAnalysisTask(-1, self.__model_id, file_text, self.__only_positives) analysis_task.add_observer(self) self.__analysis_tasks.append({ 'file': get_file_name(file), 'task': analysis_task }) analysis_task.init() while not self.__check_task_finalized(): time.sleep(5) self.set_results(self.__build_results()) except Exception as e: error = ErrorHandler.get_error_dict(e) self.set_error_data(error)
def db_get_autoincremental_id(col_name): try: col = get_collection(DB_GENERAL_SETTINGS_DB, DB_AUTOINCREMENTAL_ID_COL) next_entry = col.find_and_modify({'collection': col_name}, {'$inc': { 'next_id': 1 }}, True) return next_entry['next_id'] if next_entry else 1 except Exception as e: ErrorHandler.raise_error('E-0117', [{'text': e, 'color': ERROR_COLOR}])
def initiate_default_model(): """ Inicializa un instancia del modelo por defecto. :return: [SpacyModelRef] - Referencia al modelo de spacy """ try: default_nlp_model = spacy.load(MODEL_MANAGER_DEFAULT_BASE_MODEL) return default_nlp_model except: ErrorHandler.raise_error('E-0028')
def train_model(self, model, examples): """ Aplica un set de ejemplos de entrenamiento a un modelo. :model: [Model] - Id del modelo sobre el cual aplicar el set de ejemplos. :examples: [List] - Lista de ejemplos de entrenamiento """ if not model: ErrorHandler.raise_error('E-0090') annotations = self.__build_annotations(examples) model.train_model(annotations)
def get_approved_examples(self, model_id): """ Retorna un listado con todos los ejemplos aprobados para un determinado modelo. :model_id: [String] - Id del modelo. :return: [List] - Lista de los ejemplos aprobados. """ model_train_data = self.__find_model(model_id) if not model_train_data: ErrorHandler.raise_error('E-0081') return model_train_data.get_approved_examples()
def get_task_status(self, task_id): """ Devuelve el status de una tarea, la misma debe existir en la cola de tareas. :task_id: [int] - Id de la tarea a buscar :return: [Dict] - Diccionario con el estado de la tarea. """ founded_task = self.__get_task(task_id) if founded_task is None: ErrorHandler.raise_error('E-0097') return founded_task.get_task_status_data()
def get_pending_examples(self, model_id): """ Retorna un listado con todos los ejemplos que tienen su aprobación / rechazo aún pendiente para un determinado modelo. :model_id: [String] - Id del modelo. :return: [List] - Lista de los ejemplos pendientes de una decisión. """ model_train_data = self.__find_model(model_id) if not model_train_data: ErrorHandler.raise_error('E-0083') return model_train_data.get_pending_examples()
def __validate_examples(self, examples): """ Valida un ejemplo de entrenamiento. :example: [List] - Ejemplo de entrenamiento a validar. """ for example in examples: if not validate_data(TRAIN_MANAGER_SCHEMAS['TRAIN_DATA'], example): ErrorHandler.raise_error('E-0086') for tag in example['tags']: tag_entity = tag['entity'] if not self.__custom_entity_manager.validate_tag(tag_entity): ErrorHandler.raise_error('E-0087')
def sanitize_text_for_analysis(text=''): """ Elimina los caracteres no deseados que pueda tener un texto. :text: [String] - Texto a preparar. :return: [String] - Texto prepatado para el análisis. """ if not isinstance(text, str): ErrorHandler.raise_error('E-0094') sanitized_text = text.replace('\n', ' ') sanitized_text = sanitized_text.replace('\t', ' ') return sanitized_text
def load_model(path): """ Carga el modelo a partir del path. :path: [String] - Ruta para acceder al modelo. :return: [SpacyModelRef] - Referencia al modelo de spacy, None si no se pdo cargar el modelo. """ try: full_path = build_path(MODEL_MANAGER_ROOT_DIR, path, add_absolute_root=True) nlp_model = spacy.load(full_path) return nlp_model except: ErrorHandler.raise_error('E-0092')
def overwrite_json_file(path_from_root, content): """ Sobreescribe el archivo indicado con el contenido del diccionario recibido. :path_from_root: cadena con la ruta relativa a la raíz. :content: diccionario con el contenido a escribir en el archivo. """ try: absolute_path = get_absoulute_path(path_from_root) file = open(absolute_path, 'w') file.write(content) file.close() except Exception as e: ErrorHandler.raise_error('E-0014', [{'text': e, 'color': ERROR_COLOR}])
def remove_model_data(model_id): """ Elimina la entrada para un modelo. :model_id: [String] - Id del modelo a eliminar. """ Logger.log('L-0066') model_delete_count = db_delete_item(MODEL_MANAGER_DB, MODEL_MANAGER_MODELS_COLLECTION, { 'model_id': model_id }).deleted_count if model_delete_count <= 0: ErrorHandler.raise_error('E-0072') db_delete_items(MODEL_MANAGER_DB, ANALYZER_EXCEPTIONS_COLLECTION, {'model_id': model_id})
def remove_dir(path_from_root, is_absolute_path=False): """ Elimina el directorio indicado en path del disco. :path_from_root: [String] - Ruta relativa al directorio. :return: [boolean] - True si el borrado se realizo con exito, False en caso contrario. """ try: if not is_absolute_path: absolute_path = get_absoulute_path(path_from_root) shutil.rmtree(absolute_path) else: shutil.rmtree(path_from_root) except Exception as e: ErrorHandler.raise_error('E-0015', [{'text': e, 'color': ERROR_COLOR}])
def unzip_model(model_path, model_id): """ Descomprime un modelo importado a partir del directorio donde se encuentra descargado. :model_path: [String] - Directorio donde se encuentran los archivos de modelo. """ try: join_zip_model(model_path, model_id) model_main_file = '%s%s%s' % (model_path, DIR_PATH_SEPARATOR, MODEL_TMP_JOINT_FILE_NAME) zip_ref = ZipFile(model_main_file, 'r') zip_ref.extractall(model_path) zip_ref.close() except Exception as e: ErrorHandler.raise_error('E-0120', [{'text': e, 'color': ERROR_COLOR}])
def load_json_file(path_from_root): """ Lee el contenido de un archivo a partir de la ruta relativa a la raíz y devuelve su contenido como un diccionario. :path_from_root: cadena con la ruta relativa a la raíz. :return: diccionario conteniendo el contenido del archivo json """ try: with open(path_from_root) as f: parsedDict = json.loads(f.read()) f.close() return parsedDict except Exception as e: ErrorHandler.raise_error('E-0013', [{'text': e, 'color': ERROR_COLOR}])
def add_training_examples(self, model_id, examples_list): """ Agrega una lista de ejemplos de entrenamiento. Para que la operación sea exitosa todos los ejemplos deben poder ser validados correctamente, en caso contrario no se añadirá ninguno. :model_id: [String] - Id del modelo al cual se aplicará el ejemplo. :examples_list: [List(Dict)] - Listado de ejemplos de entrenamiento. """ Logger.log('L-0292') model = self.__model_manager.get_model(model_id) if model is None: ErrorHandler.raise_error('E-0084') self.__train_data_manager.add_training_examples( model_id, examples_list) Logger.log('L-0295')
def __init(self, available_models): """ Inicializa el modulo. """ try: Logger.log('L-0247') Logger.log('L-0248') for model in available_models: model_train_data = ModelTrainData(model, []) self.__models.append(model_train_data) Logger.log('L-0249') Logger.log('L-0250') examples_query = { '$and': [{ 'status': { '$ne': TRAIN_EXAMPLE_STATUS_APPLIED } }, { 'status': { '$ne': TRAIN_EXAMPLE_STATUS_REJECTED } }] } training_examples = db_get_items(TRAIN_MANAGER_DB, TRAIN_DATA_EXAMPLES_COLLECTION, examples_query) Logger.log('L-0251') Logger.log('L-0252') for training_example in training_examples: model_id = training_example['model_id'] model_train_data = self.__find_model(model_id) if model_train_data is not None: model_train_data.add_training_example(training_example) Logger.log('L-0253') self.__custom_entity_manager = CustomEntityTagManager() if self.__custom_entity_manager.is_ready(): Logger.log('L-0254') self.__init_success = True return Logger.log('L-0255') except Exception as e: self.__init_success = False ErrorHandler.raise_error('E-0023', [{ 'text': e, 'color': ERROR_COLOR }])
def dictionary_to_disk(path_from_root, dictionary, is_absolute_path=False): """ Guarda un diccionario a un archivo en disco. :path_from_root: ruta absoluta o relativa al archivo a crear. :dictionary: diccionario a guardar. """ try: absolute_path = path_from_root if not is_absolute_path: absolute_path = get_absoulute_path(path_from_root) arch = open(absolute_path, 'w') arch.write(json.dumps(dictionary)) arch.close() except Exception as e: ErrorHandler.raise_error('E-0016', [{'text': e, 'color': ERROR_COLOR}])
def get_submitted_training_examples(self, model_id, status): """ Obtiene un listado de los ejemplos de un modelo para un estado particular. Los estados posibles son: submitted, approved, historic. :model_id: [String] - Id del modelo. :status: [String] - Estado de los ejemplos. :return: [List(Dict)] - Listado de los ejemplos """ if status == TRAIN_EXAMPLE_STATUS_APPROVED: return self.__train_manager.get_approved_training_examples(model_id) if status == TRAIN_EXAMPLE_STATUS_HISTORIC: return self.__train_manager.get_training_examples_history(model_id) if status == TRAIN_EXAMPLE_STATUS_SUBMITTED: return self.__train_manager.get_pending_training_examples(model_id) ErrorHandler.raise_error('E-0080')
def db_batch_operation(db_name, operations): db = connect()[db_name] try: for operation in operations: col_name = operation['col_name'] data = None query = None if 'data' in operation.keys(): data = operation['data'] if 'query' in operation.keys(): query = operation['query'] if operation['type'] in transaction_operation_types: transaction_operation_types[operation['type']](db, col_name, data=data, query=query) except Exception as e: ErrorHandler.raise_error('E-0012', [{'text': e, 'color': ERROR_COLOR}])