Source code for intents.connectors._experimental.alexa.connector

"""
This is a connector that can export an :class:`Agent` to the **Alexa** format.

.. warning::

    Alexa connector is **experimental**, it is published mainly to study the case and gather
    feedback: expect relevant rough edges. Also,

    * `predict` and `trigger` are not implemented (you don't call Alexa, Alexa calls you)
    * Entities :class:`Sys.Email` and :class:`Sys.Url` are not available in Alexa (regex entites aren't supported either, which makes it difficult to work around this one)
    * Responses are managed with fulfillment, which is not implemented
    * Intent relations are not considered

Official Request/Response schemas:
https://github.com/alexa/alexa-apis-for-python/tree/master/ask-sdk-model/ask_sdk_model
"""
import os
import json
import shutil
import logging

from intents import Agent, Intent, Entity
from intents.language import entity_language
from intents.service_connector import Connector, ServiceEntityMappings
from intents.connectors._experimental.alexa.export import render
from intents.connectors._experimental.alexa.slot_types import ENTITY_MAPPINGS

logger = logging.getLogger(__name__)

[docs]class AlexaConnector(Connector): """ This is an implementation of :class:`Connector` that enables Agents to work as Alexa projects. .. warning:: This connector is **experimental**. Features may not be complete and behavior may change in next releases. At the moment, all you can do is to :meth:`export` an Agent in the Alexa format (note that contexts are not considered, and responses are not included; webhook fulfillment needs to be implemented for both). """ entity_mappings: ServiceEntityMappings = ENTITY_MAPPINGS invocation_name: str def __init__( self, agent_cls: type(Agent), invocation_name: str, default_session: str=None, default_language: str="en" ): super().__init__(agent_cls, default_session=default_session, default_language=default_language) self.invocation_name = invocation_name # TODO: model constraints
[docs] def export(self, destination: str): """ Export Agent in the given folder: .. code-block:: python from example_agent.agent import ExampleAgent from intents.connectors._experimental.alexa import AlexaConnector alexa = AlexaConnector(ExampleAgent, "any invocation") alexa.export("./TMP_ALEXA") The export will generate one JSON file per language, they can be imported from the Alexa console. Destination will be overwritten if already existing. """ rendered = render(self) if os.path.isdir(destination): logger.warning("Removing existing export folder: %s", destination) shutil.rmtree(destination) os.makedirs(destination) for lang, data in rendered.items(): with open(os.path.join(destination, f"agent.{lang.value}.json"), "w") as f: json.dump(data, f, indent=4)
[docs] def upload(self): """ *Not implemented* """ raise NotImplementedError()
[docs] def predict(self, message: str, session: str = None, language: str = None) -> Intent: """ *Not implemented* """ raise NotImplementedError()
[docs] def trigger(self, intent: Intent, session: str=None, language: str=None) -> Intent: """ *Not implemented* """ raise NotImplementedError()
[docs] def entity_value_id(self, entity_cls: type(Entity), entity_value: entity_language.EntityEntry): """ Entity entries in Alexa have IDs. This is a centralized function to compute them. """ return entity_cls.name + entity_value.value