Базовые классы

SmartApp Framework позволяет изменить поведение базовых классов путем наследования. Это необязательная опция, которая позволяет внести изменения в функциональность смартапа.

Для расширения фреймворка необходимо:

  1. Создать наследника от класса.
  2. Добавить новую функциональность, которой нет в базовом классе.
  3. Зарегистрировать новый класс в app_config.

Ниже перечислены основные базовые классы, от которых можно создать наследника.

BaseMainLoop - цикл обработки сообщений

BaseMainLoop - является базовым классом, который реализует рабочий цикл обработки сообщений от пользователя. Создав наследника от этого класса, можно переопределить следующие методы:

def run(self)

Метод, в котором реализуется цикл работы смартапа.

def stop(self, signum, frame)

Метод для остановки выполнения метода run.

def load_user(self, db_uid, message)

Метод загрузки текущего состояния пользователя из используемой БД. В качестве результата ожидается получение экземпляра класса User или производной от этого класса.

Метод имеет следующие объекты:

  • db_uid - уникальный идентификатор, по которому хранится запись о состоянии пользователя в БД;
  • message - входящее сообщение от пользователя. Объект класса FromMessage или наследника от него.
def save_user(self, db_uid, user, message)

Метод сохранения состояния пользователя в БД. В качестве результата ожидается получение bool флага, который отражает, произошла ли коллизия записи в БД (т.е. при сохранении обнаружено, что данные уже были кем-то изменены).

Метод имеет следующие объекты:

  • db_uid - уникальный идентификатор, по которому хранится запись о состоянии пользователя в БД;
  • user - объект класса User или производный от этого класса;
  • message - входящее сообщение от пользователя. Объект класса FromMessage или наследника от него.
def _generate_answers(self, user, commands, message, **kwargs)

Метод для создания объектов ответов от смартапа к пользователю. Используется внутри MainLoop для дополнительной работы объектов Command. Предполагается, что внутри будут созданы объекты класса SmartKitKafkaReqeust / RestRequest или другой пользовательский тип запроса. На основании объектов Command, message, request будет создан объект класса SmartAppToMessage. В качестве результата ожидается получение списка объектов класса SmartAppToMessage.

Метод имеет следующие объекты:

  • user - объект класса User или производный от этого класса;
  • commands - list объектов класса Command (например, обогащение, изменение, удаление полей);
  • message - входящее сообщение от пользователя. Объект класса FromMessage или наследника от него;
  • **kwargs - дополнительные именованные аргументы.

SmartAppModel - обработка сообщения

SmartAppModel - является базовым классом, который обрабатывает входящее сообщение и возвращает ответ на него обратно в MainLoop.

Внутри конструктора можно переопределить маппинг MessageName:Handler, за который отвечает переменная self._handlers. Сейчас в этой переменной определяются обработчики сообщений следующего типа:

  • MESSAGE_TO_SKILL,
  • RUN_APP,
  • LOCAL_TIMEOUT,
  • SERVER_ACTION,
  • CLOSE_APP.

Создав наследника от класса SmartAppModel, можно переопределить следующие методы:

def __init__(self, resources: SmartAppResources, dialogue_manager_cls, custom_settings, **kwargs)
@exc_handler(on_error_obj_method_name="on_answer_error")

Декоратор для ошибок во время обработки входящего сообщения внутри метода answer.

def answer(self, message, user)

Метод, в котором выбирается и вызывается обработчик в зависимости от типа входящего сообщения. В качестве результата ожидается list объектов класса Command, которые в дальнейшем будут использоваться в методе _generate_answers внутри MainLoop.

Метод имеет следующие объекты:

  • message - входящее сообщение от пользователя. Объект класса FromMessage или наследника от него;
  • user - объект класса User или производный от этого класса.
def on_answer_error(self, message, user)

Метод, который вызывается в случае ошибки внутри метода answer.

Метод имеет следующие объекты:

  • message - входящее сообщение от пользователя. Объект класса FromMessage или наследника от него;
  • user - объект класса User или производный от этого класса.
def get_handler(self, message_type)

Логика выбора обработчика для сообщения в зависимости от типа сообщения. Тип входящего сообщения передается в message_type. В качестве результата ожидается объект класса HandlerBase или его наследник.

HandlerBase - обработка сообщений по типам

HandlerBase - базовый класс для обработчиков, в которых реализована различная логика обработки определенного типа сообщения. Создав наследника от класса HandlerBase, можно переопределить следующие методы:

def __init__(self, app_name)

app_name - название созданного смартапа. Используется внутри HandlerBase для мониторинга.

def run(self, payload, user)

В качестве результата работы метода ожидается list объектов класса Command, которые в дальнейшем будут использоваться в методе _generate_answers внутри MainLoop.

Метод имеет следующие объекты:

  • payload - поле payload, которое можно получить из объекта класса FromMessage - message.payload;
  • user - объект класса User или производный от этого класса.

DialogueManager - работа со сценариями

DialogueManager - базовый класс, который на основании интента из message.payload выбирает и запускает новый сценарий или продолжает работу текущего. Создав наследника от класса DialogueManager, можно переопределить следующие методы:

def __init__(self, scenario_descriptions, app_name, **kwargs)
  • scenario_descriptions - json-файлы, загруженные в память из папки referenses: сценарии, формы, actions, requirements и т.д. Метод нужен для получения актуального списка сценариев;
  • app_name - название созданного смартапа. Используется внутри DialogueManager для мониторинга;
  • **kwargs - дополнительные именованные аргументы.
def _nothing_found_action(self)

Метод выполняется, когда входящее сообщение не подходит текущему запущенному сценарию. Например, пользователь спросил что-то другое.

В этом случае, если на основе входящего сообщения ни одно поле формы не может быть заполнено, срабатывает NOTHING_FOUND action, который возвращает соответствующее сообщение ассистенту. Как результат работы, ожидается объект класса Action.

def run(self, text_preprocessing_result, user)

Метод запуска работы сценария на основе интента из входящего сообщения. Предполагается, что внутри этого метода будет выбран сценарий и запущен метод run_scenario для обработки выбранного сценария.

Метод имеет следующие объекты:

  • text_preprocessing_result - объект класса TextPreprocessingResult, который получается на основе поля payload.message из входящего сообщения;
  • user - объект класса User или производный от этого класса.
def run_scenario(self, scen_id, text_preprocessing_result, user)

Метод запуска и получения результатов от выбранного сценария на основе входящего сообщения. В качестве результата работы методы ожидается list объектов класса Command, которые в дальнейшем будут использоваться в методе _generate_answers внутри MainLoop. Список может быть пустой.

Метод имеет следующие объекты:

  • scen_id - id сценария из коллекции scenario_descriptions['scenarios'];
  • text_preprocessing_result - объект класса TextPreprocessingResult, который получается на основе поля payload.message из входящего сообщения;
  • user - объект класса User или производный от этого класса.

SmartAppResources - регистрация сущностей

SmartAppResources - класс, который используется для загрузки ресурсов из json и регистрации базовых сущностей: actions, requirements, fillers и т.д. в соответствующих фабриках. Создав наследника от класса SmartAppResources, можно переопределить следующие методы:

def _subfolder(self)

Свойство для указания папки, из которой будут загружаться ресурсы.

def override_repositories(self, repositories: list)

Метод предназначен для добавления новых репозиториев в дочерних классах. На выходе ожидается дополненный список repositories с новыми сущностями, которые характерны для конкретного смартапа.

Метод имеет следующие объекты:

  • repositories - список репозиториев класса SmartAppResources.
def init(self)

Метод, в котором подряд запускаются методы для добавления новых сущностей в соответствующие фабрики.

def init_field_filler_description(self)

Метод регистрации новых филлеров. Например:

import scenarios.scenario_models.field.field_filler_description as ffd

def init_field_filler_description(self):
  super(CustomAppResourses, self).init_field_filler_description()

где ffd.field_filler_description - фабрика филлеров.

def init_actions(self)

Метод регистрации новых actions. Например:

from core.basic_models.actions.basic_actions import actions

def init_actions(self):
  super(CustomAppResourses, self).init_actions()
  actions["simple_action"] = SamlpeAction

где actions - фабрика actions.

def init_requirements(self)

Метод регистрации новых requirements. Например:

from core.basic_models.requirement.basic_requirements import requirements

def init_requirements(self):
  super(CustomAppResourses, self).init_requirements()
  requirements["sample_requirement"] = SampleRequirement

где requirements - фабрика requirements.

def init_db_adapters(self)

Методы регистрации новых адаптеров для БД. Например:

from core.db_adapter.db_adapter import db_adapters

def init_db_adapters(self):

  super(CustomAppResourses, self).init_db_adapters()
  db_adapters["custom_db_adapter"] = CustomDBAdapter

где db_adapters - фабрика адаптеров.

BaseUser - состояние пользователя

В SmartApp Framework реализован класс BaseUser и его наследник User, которые описывают состояние пользователя:

  • Если есть необходимость иметь максимально собственный класс для хранения состояний пользователя, без использования полей для корректной работы сценарной логики, то рекомендуется делать наследника от класса BaseUser.
  • Если нужна сценарная логика и нужно добавить новые поля, то рекомендуется делать наследника от класса User.  Создав наследника от класса, можно переопределить следующие методы:
@lazy
def parametrizer(self)

Свойство, которое возвращает объект класса BasicParametrizer или его наследников.

@property
def fields(self)

Свойство, которое возвращает список объектов класса Field, являющиеся свойствами пользователя

@property
def raw(self)

Свойство, которое возвращает словарь типа {field.name: {"field.attr1":..}, ...}

@property
def raw_str(self)

Свойство, которое возвращает json представление словаря из метода raw. Используется для сохранения пользователя в БД.

def expire(self)

Метод, в котором последовательно вызываются expire от Field класса User. Используется для очистки данных, которые уже потеряли со временем свою актуальность для пользователя.

BasicParametrizer - сборка словаря

BasicParametrizer - класс, который собирает словарь из различных доступных объектов системы: User, Settings, Forms и т.д., чтобы использовать данные при рендеренге jinja template. Создав наследника от класса, можно переопределить следующие методы:

def collect(self, text_preprocessing_result=None, filter_params=None)

Метод сборки данных из доступных объектов системы. Метод имеет следующие объекты:

  • text_preprocessing_result - объект класса TextPreprocessingResult, который получается на основе поля payload.message из входящего сообщения;
  • filter_params - параметры, которые будут удалены при создании словаря.
def _get_user_data(self, text_preprocessing_result=None)

Метод, в котором задается набор данных, возвращаемый из метода collect. Метод имеет следующий объект:

  • text_preprocessing_result - объект класса TextPreprocessingResult, который получается на основе поля payload.message из входящего сообщения.
@lazy
def filter(self)

Свойство, которое возвращает объект класса Filter.

def filter_out(self, data, filter_params=None)

Метод, который отфильтровывает данные из созданного словаря в методе _get_user_data. Метод имеет следующие объекты:

  • data - словарь, созданный в методе _get_user_data;
  • filter_params - параметры, которые нужно удалить из словаря.

В большинстве случаев при создании смартапа достаточно переопределить в классе наследника метод _get_user_data, в котором можно обогатить новыми данными текущий словарь с параметрами.

Settings - загрузка конфигов

Settings - класс, который загружает конфиги смартапа. Например: template_config.yml, kafka_config.yml, ceph_config.yml. Создав наследника от класса, можно переопределить следующие методы:

def override_repositories(self, repositories: list)

Метод предназначен для добавления новых репозиториев в дочерних классах. Метод принимает объект repositories - список репозиториев класса SmartAppResources. На выходе ожидается дополненный список repositories новыми сущностями, характерными для конкретного смартапа.

def get_source(self)

Метод определяет, каким адаптером будут загружены конфиги:

  • OSAdapter - используется по умолчанию. Адаптер ищет файлы локально.
  • CephAdapter - позволяет загружать файлы из s3 хранилища

Как результат работы ожидается объект наследник от класса DBAdapter.

Как подключить свои классы

После создания собственных классов необходимо добавить их в смартап. Для этого необходимо:

  1. Зарегистрировать собственные классы в app_config.py.
  2. C помощью конструкции from ... import подключить класс.
  3. Присвоить переменной соответствующий ей класс: LOCAL_TESTING - наследник от класса CLInterface; RESOURCES - наследник от класса SmartAppResources; USER - наследник от класса BaseUser; MAIN_LOOP - наследник от класса MainLoop; PARAMETRIZER - наследник от класса BasicParametrizer; MODEL - наследник от класса SmartAppModel; DIALOG_MANAGER - наследник от класса DialogManager; SETTINGS - наследник от класса Settings.

Например:

from app.local_testing.custom_local_testing import CustomLocalTesting
from app.resources.custom_app_resourses import CustomAppResourses

LOCAL_TESTING = CustomLocalTesting
RESOURCES = CustomAppResourses

Заметили ошибку?

Выделите текст и нажмите Ctrl + Enter, чтобы сообщить нам о ней