SmartApp Framework позволяет изменить поведение базовых классов путем наследования. Это необязательная опция, которая позволяет внести изменения в функциональность смартапа.
Для расширения фреймворка необходимо:
- Создать наследника от класса.
- Добавить новую функциональность, которой нет в базовом классе.
- Зарегистрировать новый класс в
app_config.
Ниже перечислены основные базовые классы, от которых можно создать наследника.
BaseMainLoop — цикл обработки сообщений
BaseMainLoop — является базовым классом, который реализует рабочий цикл обработки сообщений от пользователя. Создав наследника от этого класса, можно переопределить следующие методы:
def run(self)
Метод, в котором реализуется цикл работы смартапа.
def stop(self, signum, frame)
Метод для остановки выполнения метода run.
async def load_user(self, db_uid, message)
Асинхронный метод загрузки текущего состояния пользователя из используемой БД. В качестве результата ожидается получение экземпляра класса User или производной от этого класса.
Метод имеет следующие объекты:
db_uid— уникальный идентификатор, по которому хранится запись о состоянии пользователя в БД;message— входящее сообщение от пользователя. Объект класса FromMessage или наследника от него.
async 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)
resources— объект класса SmartAppResources;dialogue_manager_cls— объект класса DialogueManager;custom_settings— объект класса Settings.
@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-шаблона . Создав наследника от класса, можно переопределить следующие методы:
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, в котором можно обогатить новыми данными текущий словарь с параметрами.
LoggerMessageCreator — расширение параметров логирования
LoggerMessageCreator — класс, который используется для ведения логов смартапа. Переопределив методы класса можно указать какие параметры будут отображаться в логах.
Создав наследника от класса, можно переопределить следующие методы:
def update_user_params(cls, user, params)
Метод вызывается в make_message до маскирования и добавляет в сообщение лога параметры заданные в массиве ART_NAME. Переопределите метод, чтобы изменить список параметров.
user— объект класса User или производный от этого класса;
def update_other_params(cls, user, params, cls_name='', log_store_for=0)
Метод вызывается в make_message после маскирования и добавляет в сообщение лога дополнительные параметры. Переопределите метод, чтобы изменить или дополнить параметры сообщения лога.
user— объект класса User или производный от этого класса;
def make_message(cls, user=None, params=None, cls_name='', log_store_for=0)
Метод возвращает параметры, которые передаются в сообщении лога смартапа. Часть параметров маскируется, например, персональные данные пользователей.
user— объект класса User или производный от этого класса;
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.
Как подключить свои классы
После создания собственных классов необходимо добавить их в смартап. Для этого необходимо:
- Зарегистрировать собственные классы в
app_config.py. - C помощью конструкции
from ... importподключить класс. - Присвоить переменной соответствующий ей класс:
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