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 ""
) # 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.
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
def test_waterfall_nested(self): convo_state = ConversationState(MemoryStorage()) adapter = TestAdapter()
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
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)
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)
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__
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