Ejemplo n.º 1
0
from flight_booking_recognizer import FlightBookingRecognizer

relative_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(relative_path, "config.yaml")
with open(path, "r") as ymlfile:
    cfg = yaml.safe_load(ymlfile)

PORT = cfg["Settings"]["Port"]
SETTINGS = BotFrameworkAdapterSettings(cfg["Settings"]["AppId"],
                                       cfg["Settings"]["AppPassword"])

# Create MemoryStorage, UserState and ConversationState
memory = MemoryStorage()

user_state = UserState(memory)
conversation_state = ConversationState(memory)

ADAPTER = AdapterWithErrorHandler(SETTINGS, conversation_state)
RECOGNIZER = FlightBookingRecognizer(cfg["Settings"])
BOOKING_DIALOG = BookingDialog()

dialog = MainDialog(RECOGNIZER, BOOKING_DIALOG)
bot = DialogAndWelcomeBot(conversation_state, user_state, dialog)


async def messages(req: web.Request) -> web.Response:
    body = await req.json()
    activity = Activity().deserialize(body)
    auth_header = req.headers[
        "Authorization"] if "Authorization" in req.headers else ""
Ejemplo n.º 2
0
        )
        # Send a trace activity, which will be displayed in Bot Framework Emulator
        await context.send_activity(trace_activity)

    # Clear out state
    await CONVERSATION_STATE.delete(context)


# Set the error handler on the Adapter.
# In this case, we want an unbound method, so MethodType is not needed.
ADAPTER.on_turn_error = on_error

# Create MemoryStorage, UserState and ConversationState
MEMORY = MemoryStorage()
USER_STATE = UserState(MEMORY)
CONVERSATION_STATE = ConversationState(MEMORY)

# Create telemetry client
INSTRUMENTATION_KEY = APP.config["APPINSIGHTS_INSTRUMENTATION_KEY"]
TELEMETRY_CLIENT = ApplicationInsightsTelemetryClient(INSTRUMENTATION_KEY)

# Create dialog and Bot
DIALOG = MainDialog(APP.config, telemetry_client=TELEMETRY_CLIENT)
BOT = DialogAndWelcomeBot(CONVERSATION_STATE, USER_STATE, DIALOG,
                          TELEMETRY_CLIENT)


# Listen for incoming requests on /api/messages.
@APP.route("/api/messages", methods=["POST"])
def messages():
    # Main bot message handler.
Ejemplo n.º 3
0
CONFIG = DefaultConfig()
SKILL_CONFIG = SkillConfiguration()

# Whitelist skills from SKILL_CONFIG
AUTH_CONFIG = AuthenticationConfiguration(
    claims_validator=AllowedSkillsClaimsValidator(CONFIG).claims_validator)
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = BotFrameworkAdapterSettings(
    app_id=CONFIG.APP_ID,
    app_password=CONFIG.APP_PASSWORD,
    auth_configuration=AUTH_CONFIG,
)

STORAGE = MemoryStorage()
CONVERSATION_STATE = ConversationState(STORAGE)

ID_FACTORY = SkillConversationIdFactory(STORAGE)
CREDENTIAL_PROVIDER = SimpleCredentialProvider(CONFIG.APP_ID,
                                               CONFIG.APP_PASSWORD)
CLIENT = SkillHttpClient(CREDENTIAL_PROVIDER, ID_FACTORY)

ADAPTER = AdapterWithErrorHandler(SETTINGS, CONFIG, CONVERSATION_STATE, CLIENT,
                                  SKILL_CONFIG)

# Create the Bot
DIALOG = SetupDialog(CONVERSATION_STATE, SKILL_CONFIG)
BOT = HostBot(CONVERSATION_STATE, SKILL_CONFIG, CLIENT, CONFIG, DIALOG)

SKILL_HANDLER = SkillHandler(ADAPTER, BOT, ID_FACTORY, CREDENTIAL_PROVIDER,
                             AUTH_CONFIG)
    async def test_should_handle_invoke_activities(self):
        activity_sent = None
        from_bot_id_sent = None
        to_bot_id_sent = None
        to_url_sent = None

        async def capture(
            from_bot_id: str,
            to_bot_id: str,
            to_url: str,
            service_url: str,  # pylint: disable=unused-argument
            conversation_id: str,  # pylint: disable=unused-argument
            activity: Activity,
        ):
            nonlocal from_bot_id_sent, to_bot_id_sent, to_url_sent, activity_sent
            from_bot_id_sent = from_bot_id
            to_bot_id_sent = to_bot_id
            to_url_sent = to_url
            activity_sent = activity

        mock_skill_client = self._create_mock_skill_client(capture)

        conversation_state = ConversationState(MemoryStorage())
        dialog_options = SkillDialogTests.create_skill_dialog_options(
            conversation_state, mock_skill_client)

        sut = SkillDialog(dialog_options, "dialog_id")
        activity_to_send = Activity(
            type=ActivityTypes.invoke,
            name=str(uuid.uuid4()),
        )

        client = DialogTestClient(
            "test",
            sut,
            BeginSkillDialogOptions(activity=activity_to_send),
            conversation_state=conversation_state,
        )

        # Send something to the dialog to start it
        await client.send_activity(MessageFactory.text("irrelevant"))

        # Assert results and data sent to the SkillClient for fist turn
        assert dialog_options.bot_id == from_bot_id_sent
        assert dialog_options.skill.app_id == to_bot_id_sent
        assert dialog_options.skill.skill_endpoint == to_url_sent
        assert activity_to_send.text == activity_sent.text
        assert DialogTurnStatus.Waiting == client.dialog_turn_result.status

        # Send a second message to continue the dialog
        await client.send_activity(MessageFactory.text("Second message"))

        # Assert results for second turn
        assert activity_sent.text == "Second message"
        assert DialogTurnStatus.Waiting == client.dialog_turn_result.status

        # Send EndOfConversation to the dialog
        await client.send_activity(
            Activity(type=ActivityTypes.end_of_conversation))

        # Assert we are done.
        assert DialogTurnStatus.Complete == client.dialog_turn_result.status
Ejemplo n.º 5
0
 def test_waterfall_nested(self):
     convo_state = ConversationState(MemoryStorage())
     adapter = TestAdapter()
Ejemplo n.º 6
0
 def test_datetimeprompt_first_invalid_then_valid_input(self):
     convo_state = ConversationState(MemoryStorage())
     adapter = TestAdapter()
    async def proceeds_through_waterfall(storage) -> bool:
        convo_state = ConversationState(storage)

        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        async def exec_test(turn_context: TurnContext) -> None:
            dialog_context = await dialogs.create_context(turn_context)

            await dialog_context.continue_dialog()
            if not turn_context.responded:
                await dialog_context.begin_dialog(WaterfallDialog.__name__)
            await convo_state.save_changes(turn_context)

        adapter = TestAdapter(exec_test)

        async def prompt_validator(prompt_context: PromptValidatorContext):
            result = prompt_context.recognized.value
            if len(result) > 3:
                succeeded_message = MessageFactory.text(
                    f"You got it at the {prompt_context.options.number_of_attempts}rd try!"
                )
                await prompt_context.context.send_activity(succeeded_message)
                return True

            reply = MessageFactory.text(
                f"Please send a name that is longer than 3 characters. {prompt_context.options.number_of_attempts}"
            )
            await prompt_context.context.send_activity(reply)
            return False

        async def step_1(
                step_context: WaterfallStepContext) -> DialogTurnStatus:
            assert isinstance(step_context.active_dialog.state["stepIndex"],
                              int)
            await step_context.context.send_activity("step1")
            return Dialog.end_of_turn

        async def step_2(step_context: WaterfallStepContext) -> None:
            assert isinstance(step_context.active_dialog.state["stepIndex"],
                              int)
            await step_context.prompt(
                TextPrompt.__name__,
                PromptOptions(
                    prompt=MessageFactory.text("Please type your name")),
            )

        async def step_3(
                step_context: WaterfallStepContext) -> DialogTurnStatus:
            assert isinstance(step_context.active_dialog.state["stepIndex"],
                              int)
            await step_context.context.send_activity("step3")
            return Dialog.end_of_turn

        steps = [step_1, step_2, step_3]

        dialogs.add(WaterfallDialog(WaterfallDialog.__name__, steps))

        dialogs.add(TextPrompt(TextPrompt.__name__, prompt_validator))

        step1 = await adapter.send("hello")
        step2 = await step1.assert_reply("step1")
        step3 = await step2.send("hello")
        step4 = await step3.assert_reply("Please type your name")  # None
        step5 = await step4.send("hi")
        step6 = await step5.assert_reply(
            "Please send a name that is longer than 3 characters. 0")
        step7 = await step6.send("hi")
        step8 = await step7.assert_reply(
            "Please send a name that is longer than 3 characters. 1")
        step9 = await step8.send("hi")
        step10 = await step9.assert_reply(
            "Please send a name that is longer than 3 characters. 2")
        step11 = await step10.send("Kyle")
        step12 = await step11.assert_reply("You got it at the 3rd try!")
        await step12.assert_reply("step3")

        return True
Ejemplo n.º 8
0
from flask import Flask, request, Response
from botbuilder.core import BotFrameworkAdapter, BotFrameworkAdapterSettings, TurnContext, ConversationState, MemoryStorage
from botbuilder.schema import Activity
import asyncio
from qnabot import QnaBot

app = Flask(__name__)
loop = asyncio.get_event_loop()

botsettings = BotFrameworkAdapterSettings("", "")
botadapter = BotFrameworkAdapter(botsettings)

CONMEMORY = ConversationState(MemoryStorage())
botdialog = QnaBot()


@app.route("/api/messages", methods=["POST"])
def messages():
    if "application/json" in request.headers["content-type"]:
        body = request.json
    else:
        return Response(status=415)

    activity = Activity().deserialize(body)

    auth_header = (request.headers["Authorization"]
                   if "Authorization" in request.headers else "")

    async def call_fun(turncontext):
        await botdialog.on_turn(turncontext)
Ejemplo n.º 9
0
    if context.activity.channel_id == "emulator":
        # Create a trace activity that contains the error object
        trace_activity = Activity(
            label="TurnError",
            name="on_turn_error Trace",
            timestamp=datetime.utcnow(),
            type=ActivityTypes.trace,
            value=f"{error}",
            value_type="https://www.botframework.com/schemas/error",
        )
        # Send a trace activity, which will be displayed in Bot Framework Emulator
        await context.send_activity(trace_activity)


ADAPTER.on_turn_error = on_error
constate = ConversationState(MemoryStorage())
# Create the Bot
BOT = BotDialog(constate)


# Listen for incoming requests on /api/messages
async def messages(req: Request) -> Response:
    # Main bot message handler.
    if "application/json" in req.headers["Content-Type"]:
        body = await req.json()
    else:
        return Response(status=415)

    activity = Activity().deserialize(body)
    auth_header = req.headers["Authorization"] if "Authorization" in req.headers else ""
    async def test_should_recognize_and_use_custom_locale_dict(self, ):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Please choose a color."),
                    choices=_color_choices,
                )
                await dialog_context.prompt("prompt", options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)

            await convo_state.save_changes(turn_context)

        async def validator(prompt: PromptValidatorContext) -> bool:
            assert prompt

            if not prompt.recognized.succeeded:
                await prompt.context.send_activity("Bad input.")

            return prompt.recognized.succeeded

        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        culture = PromptCultureModel(
            locale="custom-locale",
            no_in_language="customNo",
            yes_in_language="customYes",
            separator="customSeparator",
            inline_or="customInlineOr",
            inline_or_more="customInlineOrMore",
        )

        custom_dict = {
            culture.locale:
            ChoiceFactoryOptions(
                inline_or=culture.inline_or,
                inline_or_more=culture.inline_or_more,
                inline_separator=culture.separator,
                include_numbers=True,
            )
        }

        choice_prompt = ChoicePrompt("prompt",
                                     validator,
                                     choice_defaults=custom_dict)
        dialogs.add(choice_prompt)

        step1 = await adapter.send(
            Activity(type=ActivityTypes.message,
                     text="Hello",
                     locale=culture.locale))
        await step1.assert_reply(
            "Please choose a color. (1) redcustomSeparator(2) greencustomInlineOrMore(3) blue"
        )
        async def exec_test_for_locale(valid_locale: str,
                                       locale_variations: List):
            # Hold the correct answer from when a valid locale is used
            expected_answer = None

            def inspector(activity: Activity, description: str):
                nonlocal expected_answer

                assert not description

                if valid_locale == test_locale:
                    expected_answer = activity.text
                else:
                    # Ensure we're actually testing a variation.
                    assert activity.locale != valid_locale

                assert activity.text == expected_answer
                return True

            async def exec_test(turn_context: TurnContext):
                dialog_context = await dialogs.create_context(turn_context)

                results: DialogTurnResult = await dialog_context.continue_dialog(
                )

                if results.status == DialogTurnStatus.Empty:
                    options = PromptOptions(
                        prompt=Activity(type=ActivityTypes.message,
                                        text="Please choose a color."),
                        choices=_color_choices,
                    )
                    await dialog_context.prompt("prompt", options)
                elif results.status == DialogTurnStatus.Complete:
                    selected_choice = results.result
                    await turn_context.send_activity(selected_choice.value)

                await convo_state.save_changes(turn_context)

            async def validator(prompt: PromptValidatorContext) -> bool:
                assert prompt

                if not prompt.recognized.succeeded:
                    await prompt.context.send_activity("Bad input.")

                return prompt.recognized.succeeded

            test_locale = None
            for test_locale in locale_variations:
                adapter = TestAdapter(exec_test)

                convo_state = ConversationState(MemoryStorage())
                dialog_state = convo_state.create_property("dialogState")
                dialogs = DialogSet(dialog_state)

                choice_prompt = ChoicePrompt("prompt", validator)
                dialogs.add(choice_prompt)

                step1 = await adapter.send(
                    Activity(type=ActivityTypes.message,
                             text="Hello",
                             locale=test_locale))
                await step1.assert_reply(inspector)
Ejemplo n.º 12
0
    def __init__(
        self,
        conversation_state: ConversationState,
        conversation_id_factory: ConversationIdFactoryBase,
        skill_client: SkillHttpClient,
        skills_config: SkillConfiguration,
        configuration: DefaultConfig,
    ):
        super(MainDialog, self).__init__(MainDialog.__name__)

        # Constants used for selecting actions on the skill.
        self._skill_action_book_flight = "BookFlight"
        self._skill_action_book_flight_with_input_parameters = (
            "BookFlight with input parameters")
        self._skill_action_get_weather = "GetWeather"
        self._skill_action_message = "Message"

        self._selected_skill_key = (
            f"{MainDialog.__module__}.{MainDialog.__name__}.SelectedSkillKey")

        bot_id = configuration.APP_ID
        if not bot_id:
            raise TypeError("App Id is not in configuration")

        self._skills_config = skills_config
        if not self._skills_config:
            raise TypeError("Skills configuration cannot be None")

        if not skill_client:
            raise TypeError("skill_client cannot be None")

        if not conversation_state:
            raise TypeError("conversation_state cannot be None")

        # Use helper method to add SkillDialog instances for the configured skills.
        self._add_skill_dialogs(
            conversation_state,
            conversation_id_factory,
            skill_client,
            skills_config,
            bot_id,
        )

        # Add ChoicePrompt to render available skills.
        self.add_dialog(ChoicePrompt("SkillPrompt"))

        # Add ChoicePrompt to render skill actions.
        self.add_dialog(
            ChoicePrompt("SkillActionPrompt",
                         self._skill_action_prompt_validator))

        # Add main waterfall dialog for this bot.
        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self._select_skill_step,
                    self._select_skill_action_step,
                    self._call_skill_action_step,
                    self._final_step,
                ],
            ))

        # Create state property to track the active skill.
        self._active_skill_property = conversation_state.create_property(
            MainDialog.ACTIVE_SKILL_PROPERTY_NAME)

        # The initial child Dialog to run.
        self.initial_dialog_id = WaterfallDialog.__name__
Ejemplo n.º 13
0
 def test_dialogset_constructor_valid(self):
     convo_state = ConversationState(MemoryStorage())
     dialog_state_property = convo_state.create_property("dialogstate")
     ds = DialogSet(dialog_state_property)
     assert ds is not None