Removed incomplete/wip Python samples

This commit is contained in:
Tracy Boehrer 2024-03-20 10:39:18 -05:00
Родитель b1e16992d8
Коммит 1e259b0d6d
90 изменённых файлов: 0 добавлений и 7380 удалений

Просмотреть файл

@ -1,216 +0,0 @@
# Setting up LUIS via CLI:
This README contains information on how to create and deploy a LUIS application. When the bot is ready to be deployed to production, we recommend creating a LUIS Endpoint Resource for usage with your LUIS App.
> _For instructions on how to create a LUIS Application via the LUIS portal, see these Quickstart steps:_
> 1. _[Quickstart: Create a new app in the LUIS portal][Quickstart-create]_
> 2. _[Quickstart: Deploy an app in the LUIS portal][Quickstart-deploy]_
[Quickstart-create]: https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-build-app
[Quickstart-deploy]:https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-deploy-app
## Table of Contents:
- [Prerequisites](#Prerequisites)
- [Import a new LUIS Application using a local LUIS application](#Import-a-new-LUIS-Application-using-a-local-LUIS-application)
- [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#How-to-create-a-LUIS-Endpoint-resource-in-Azure-and-pair-it-with-a-LUIS-Application)
___
## [Prerequisites](#Table-of-Contents):
#### Install Azure CLI >=2.0.61:
Visit the following page to find the correct installer for your OS:
- https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
#### Install LUIS CLI >=2.4.0:
Open a CLI of your choice and type the following:
```bash
npm i -g luis-apis@^2.4.0
```
#### LUIS portal account:
You should already have a LUIS account with either https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. To determine where to create a LUIS account, consider where you will deploy your LUIS applications, and then place them in [the corresponding region][LUIS-Authoring-Regions].
After you've created your account, you need your [Authoring Key][LUIS-AKey] and a LUIS application ID.
[LUIS-Authoring-Regions]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-reference-regions#luis-authoring-regions]
[LUIS-AKey]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-concept-keys#authoring-key
___
## [Import a new LUIS Application using a local LUIS application](#Table-of-Contents)
### 1. Import the local LUIS application to luis.ai
```bash
luis import application --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appName "FlightBooking" --in "./cognitiveModels/FlightBooking.json"
```
Outputs the following JSON:
```json
{
"id": "########-####-####-####-############",
"name": "FlightBooking",
"description": "A LUIS model that uses intent and entities.",
"culture": "en-us",
"usageScenario": "",
"domain": "",
"versionsCount": 1,
"createdDateTime": "2019-03-29T18:32:02Z",
"endpoints": {},
"endpointHitsCount": 0,
"activeVersion": "0.1",
"ownerEmail": "bot@contoso.com",
"tokenizerVersion": "1.0.0"
}
```
For the next step, you'll need the `"id"` value for `--appId` and the `"activeVersion"` value for `--versionId`.
### 2. Train the LUIS Application
```bash
luis train version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --wait
```
### 3. Publish the LUIS Application
```bash
luis publish version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --publishRegion "LuisAppPublishRegion"
```
> `--region` corresponds to the region you _author_ your application in. The regions available for this are "westus", "westeurope" and "australiaeast". <br/>
> These regions correspond to the three available portals, https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. <br/>
> `--publishRegion` corresponds to the region of the endpoint you're publishing to, (e.g. "westus", "southeastasia", "westeurope", "brazilsouth"). <br/>
> See the [reference docs][Endpoint-API] for a list of available publish/endpoint regions.
[Endpoint-API]: https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78
Outputs the following:
```json
{
"versionId": "0.1",
"isStaging": false,
"endpointUrl": "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/########-####-####-####-############",
"region": "westus",
"assignedEndpointKey": null,
"endpointRegion": "westus",
"failedRegions": "",
"publishedDateTime": "2019-03-29T18:40:32Z",
"directVersionPublish": false
}
```
To see how to create an LUIS Cognitive Service Resource in Azure, please see [the next README][README-LUIS]. This Resource should be used when you want to move your bot to production. The instructions will show you how to create and pair the resource with a LUIS Application.
[README-LUIS]: ./README-LUIS.md
___
## [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#Table-of-Contents)
### 1. Create a new LUIS Cognitive Services resource on Azure via Azure CLI
> _Note:_ <br/>
> _If you don't have a Resource Group in your Azure subscription, you can create one through the Azure portal or through using:_
> ```bash
> az group create --subscription "AzureSubscriptionGuid" --location "westus" --name "ResourceGroupName"
> ```
> _To see a list of valid locations, use `az account list-locations`_
```bash
# Use Azure CLI to create the LUIS Key resource on Azure
az cognitiveservices account create --kind "luis" --name "NewLuisResourceName" --sku "S0" --location "westus" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
The command will output a response similar to the JSON below:
```json
{
"endpoint": "https://westus.api.cognitive.microsoft.com/luis/v2.0",
"etag": "\"########-####-####-####-############\"",
"id": "/subscriptions/########-####-####-####-############/resourceGroups/ResourceGroupName/providers/Microsoft.CognitiveServices/accounts/NewLuisResourceName",
"internalId": "################################",
"kind": "luis",
"location": "westus",
"name": "NewLuisResourceName",
"provisioningState": "Succeeded",
"resourceGroup": "ResourceGroupName",
"sku": {
"name": "S0",
"tier": null
},
"tags": null,
"type": "Microsoft.CognitiveServices/accounts"
}
```
Take the output from the previous command and create a JSON file in the following format:
```json
{
"azureSubscriptionId": "00000000-0000-0000-0000-000000000000",
"resourceGroup": "ResourceGroupName",
"accountName": "NewLuisResourceName"
}
```
### 2. Retrieve ARM access token via Azure CLI
```bash
az account get-access-token --subscription "AzureSubscriptionGuid"
```
This will return an object that looks like this:
```json
{
"accessToken": "eyJ0eXAiOiJKVtokentokentokentokentokeng1dCI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyIsItokenI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUzODc3MTUwLCJuYmYiOjE1NTM4NzcxNTAsImV4cCI6MTU1Mzg4MTA1MCwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2ZmZTQyM2RkLWJhM2YtNDg0Ny04NjgyLWExNTI5MDA4MjM4Ny9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVZRQXEvOEtBQUFBeGVUc201NDlhVHg4RE1mMFlRVnhGZmxxOE9RSC9PODR3QktuSmRqV1FqTkkwbmxLYzB0bHJEZzMyMFZ5bWZGaVVBSFBvNUFFUTNHL0FZNDRjdk01T3M0SEt0OVJkcE5JZW9WU0dzd0kvSkk9IiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiNDhmNDVjNjEtMTg3Zi00MjUxLTlmZWItMTllZGFkZmMwMmE3IiwiZmFtaWx5X25hbWUiOiJHdW0iLCJnaXZlbl9uYW1lIjoiU3RldmVuIiwiaXBhZGRyIjoiMTY3LjIyMC4yLjU1IiwibmFtZSI6IlN0ZXZlbiBHdW0iLCJvaWQiOiJmZmU0MjNkZC1iYTNmLTQ4NDctODY4Mi1hMTUyOTAwODIzODciLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjEyNzUyMTE4NC0xNjA0MDEyOTIwLTE4ODc5Mjc1MjctMjYwOTgyODUiLCJwdWlkIjoiMTAwMzdGRkVBMDQ4NjlBNyIsInJoIjoiSSIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6Ik1rMGRNMWszN0U5ckJyMjhieUhZYjZLSU85LXVFQVVkZFVhNWpkSUd1Nk0iLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InN0Z3VtQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJzdGd1bUBtaWNyb3NvZnQuY29tIiwidXRpIjoiT2w2NGN0TXY4RVNEQzZZQWRqRUFtokenInZlciI6IjEuMCJ9.kFAsEilE0mlS1pcpqxf4rEnRKeYsehyk-gz-zJHUrE__oad3QjgDSBDPrR_ikLdweynxbj86pgG4QFaHURNCeE6SzrbaIrNKw-n9jrEtokenlosOxg_0l2g1LeEUOi5Q4gQREAU_zvSbl-RY6sAadpOgNHtGvz3Rc6FZRITfkckSLmsKAOFoh-aWC6tFKG8P52rtB0qVVRz9tovBeNqkMYL49s9ypduygbXNVwSQhm5JszeWDgrFuVFHBUP_iENCQYGQpEZf_KvjmX1Ur1F9Eh9nb4yI2gFlKncKNsQl-tokenK7-tokentokentokentokentokentokenatoken",
"expiresOn": "2200-12-31 23:59:59.999999",
"subscription": "AzureSubscriptionGuid",
"tenant": "tenant-guid",
"tokenType": "Bearer"
}
```
The value needed for the next step is the `"accessToken"`.
### 3. Use `luis add appazureaccount` to pair your LUIS resource with a LUIS Application
```bash
luis add appazureaccount --in "path/to/created/requestBody.json" --appId "LuisAppId" --authoringKey "LuisAuthoringKey" --armToken "accessToken"
```
If successful, it should yield a response like this:
```json
{
"code": "Success",
"message": "Operation Successful"
}
```
### 4. See the LUIS Cognitive Services' keys
```bash
az cognitiveservices account keys list --name "NewLuisResourceName" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
This will return an object that looks like this:
```json
{
"key1": "9a69####dc8f####8eb4####399f####",
"key2": "####f99e####4b1a####fb3b####6b9f"
}
```

Просмотреть файл

@ -1,60 +0,0 @@
# CoreBot
Bot Framework v4 core bot sample.
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities
- Implement a multi-turn conversation using Dialogs
- Handle user interruptions for such things as `Help` or `Cancel`
- Prompt for and validate requests for information from the user
## Prerequisites
This sample **requires** prerequisites in order to run.
### Overview
This bot uses [LUIS](https://www.luis.ai), an AI based cognitive service, to implement language understanding.
### Install Python 3.6
### Create a LUIS Application to enable language understanding
LUIS language model setup, training, and application configuration steps can be found [here](https://docs.microsoft.com/azure/bot-service/bot-builder-howto-v4-luis?view=azure-bot-service-4.0&tabs=cs).
If you wish to create a LUIS application via the CLI, these steps can be found in the [README-LUIS.md](README-LUIS.md).
### Configure your bot to use your LUIS app
Update config.py with your newly imported LUIS app id, LUIS API key from https://<LUIS portal>/user/settings, LUIS API host name, ie <your authoring region>.api.cognitive.microsoft.com. LUIS authoring region is listed on https://<LUIS portal>/user/settings.
## Testing the bot using Bot Framework Emulator
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
### Connect to the bot using Bot Framework Emulator
- Launch Bot Framework Emulator
- File -> Open Bot
- Enter a Bot URL of `http://localhost:3978/api/messages`
## Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Dialogs](https://docs.microsoft.com/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0)
- [Gathering Input Using Prompts](https://docs.microsoft.com/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0&tabs=csharp)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
- [Azure Portal](https://portal.azure.com)
- [Language Understanding using LUIS](https://docs.microsoft.com/azure/cognitive-services/luis/)
- [Channels and Bot Connector Service](https://docs.microsoft.com/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)

Просмотреть файл

@ -1,15 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Booking detail."""
class BookingDetails:
"""Booking detail implementation"""
def __init__(
self, destination: str = None, origin: str = None, travel_date: str = None
):
self.destination = destination
self.origin = origin
self.travel_date = travel_date

Просмотреть файл

@ -1,8 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""bots module."""
from .dialog_bot import DialogBot
from .dialog_and_welcome_bot import DialogAndWelcomeBot
__all__ = ["DialogBot", "DialogAndWelcomeBot"]

Просмотреть файл

@ -1,54 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
""" Bot initialization """
# pylint: disable=line-too-long
import sys
import asyncio
from django.apps import AppConfig
from botbuilder.core import (
BotFrameworkAdapter,
BotFrameworkAdapterSettings,
TurnContext,
ConversationState,
MemoryStorage,
UserState,
)
from dialogs import MainDialog
from bots import DialogAndWelcomeBot
import config
class BotConfig(AppConfig):
""" Bot initialization """
name = "bots"
appConfig = config.DefaultConfig
SETTINGS = BotFrameworkAdapterSettings(appConfig.APP_ID, appConfig.APP_PASSWORD)
ADAPTER = BotFrameworkAdapter(SETTINGS)
LOOP = asyncio.get_event_loop()
# Create MemoryStorage, UserState and ConversationState
memory = MemoryStorage()
user_state = UserState(memory)
conversation_state = ConversationState(memory)
dialog = MainDialog(appConfig)
bot = DialogAndWelcomeBot(conversation_state, user_state, dialog)
async def on_error(self, context: TurnContext, error: Exception):
"""
Catch-all for errors.
This check writes out errors to console log
NOTE: In production environment, you should consider logging this to Azure
application insights.
"""
print(f"\n [on_turn_error]: { error }", file=sys.stderr)
# Send a message to the user
await context.send_activity("Oops. Something went wrong!")
# Clear out state
await self.conversation_state.delete(context)
def ready(self):
self.ADAPTER.on_turn_error = self.on_error

Просмотреть файл

@ -1,44 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Main dialog to welcome users."""
import json
import os.path
from typing import List
from botbuilder.core import TurnContext
from botbuilder.schema import Activity, Attachment, ChannelAccount
from helpers.activity_helper import create_activity_reply
from .dialog_bot import DialogBot
class DialogAndWelcomeBot(DialogBot):
"""Main dialog to welcome users implementation."""
async def on_members_added_activity(
self, members_added: List[ChannelAccount], turn_context: TurnContext
):
for member in members_added:
# Greet anyone that was not the target (recipient) of this message.
# To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards
# for more details.
if member.id != turn_context.activity.recipient.id:
welcome_card = self.create_adaptive_card_attachment()
response = self.create_response(turn_context.activity, welcome_card)
await turn_context.send_activity(response)
def create_response(self, activity: Activity, attachment: Attachment):
"""Create an attachment message response."""
response = create_activity_reply(activity)
response.attachments = [attachment]
return response
# Load attachment from file.
def create_adaptive_card_attachment(self):
"""Create an adaptive card."""
relative_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(relative_path, "resources/welcomeCard.json")
with open(path) as card_file:
card = json.load(card_file)
return Attachment(
content_type="application/vnd.microsoft.card.adaptive", content=card
)

Просмотреть файл

@ -1,47 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Implements bot Activity handler."""
from botbuilder.core import ActivityHandler, ConversationState, UserState, TurnContext
from botbuilder.dialogs import Dialog
from helpers.dialog_helper import DialogHelper
class DialogBot(ActivityHandler):
"""Main activity handler for the bot."""
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
if conversation_state is None:
raise Exception(
"[DialogBot]: Missing parameter. conversation_state is required"
)
if user_state is None:
raise Exception("[DialogBot]: Missing parameter. user_state is required")
if dialog is None:
raise Exception("[DialogBot]: Missing parameter. dialog is required")
self.conversation_state = conversation_state
self.user_state = user_state
self.dialog = dialog
self.dialogState = self.conversation_state.create_property(
"DialogState"
) # pylint: disable=C0103
async def on_turn(self, turn_context: TurnContext):
await super().on_turn(turn_context)
# Save any state changes that might have occured during the turn.
await self.conversation_state.save_changes(turn_context, False)
await self.user_state.save_changes(turn_context, False)
async def on_message_activity(self, turn_context: TurnContext):
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
) # pylint: disable=C0103

Просмотреть файл

@ -1,46 +0,0 @@
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": "true",
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Get an overview",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
},
{
"type": "Action.OpenUrl",
"title": "Ask a question",
"url": "https://stackoverflow.com/questions/tagged/botframework"
},
{
"type": "Action.OpenUrl",
"title": "Learn how to deploy",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
}
]
}

Просмотреть файл

@ -1,118 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
Django settings for bots project.
Generated by 'django-admin startproject' using Django 2.2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "My Secret Key"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"bots.bots.BotConfig",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "bots.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
]
},
}
]
WSGI_APPLICATION = "bots.wsgi.application"
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = "/static/"

Просмотреть файл

@ -1,15 +0,0 @@
#!/usr/bin/env python
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
""" URL configuration for bot message handler """
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from . import views
# pylint:disable=invalid-name
urlpatterns = [
path("", views.home, name="home"),
path("api/messages", csrf_exempt(views.messages), name="messages"),
]

Просмотреть файл

@ -1,53 +0,0 @@
#!/usr/bin/env python
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
This sample shows how to create a bot that demonstrates the following:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities.
- Implement a multi-turn conversation using Dialogs.
- Handle user interruptions for such things as `Help` or `Cancel`.
- Prompt for and validate requests for information from the user.
"""
import asyncio
import json
from django.http import HttpResponse
from django.apps import apps
from botbuilder.schema import Activity
# pylint: disable=line-too-long
def home():
"""Default handler."""
return HttpResponse("Hello!")
def messages(request):
"""Main bot message handler."""
if "application/json" in request.headers["Content-Type"]:
body = json.loads(request.body.decode("utf-8"))
else:
return HttpResponse(status=415)
activity = Activity().deserialize(body)
auth_header = (
request.headers["Authorization"] if "Authorization" in request.headers else ""
)
bot_app = apps.get_app_config("bots")
bot = bot_app.bot
loop = bot_app.LOOP
adapter = bot_app.ADAPTER
async def aux_func(turn_context):
await bot.on_turn(turn_context)
try:
task = asyncio.ensure_future(
adapter.process_activity(activity, auth_header, aux_func), loop=loop
)
loop.run_until_complete(task)
return HttpResponse(status=201)
except Exception as exception:
raise exception
return HttpResponse("This is message processing!")

Просмотреть файл

@ -1,19 +0,0 @@
#!/usr/bin/env python
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
WSGI config for bots project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
# pylint:disable=invalid-name
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bots.settings")
application = get_wsgi_application()

Просмотреть файл

@ -1,226 +0,0 @@
{
"luis_schema_version": "3.2.0",
"versionId": "0.1",
"name": "Airline Reservation",
"desc": "A LUIS model that uses intent and entities.",
"culture": "en-us",
"tokenizerVersion": "1.0.0",
"intents": [
{
"name": "Book flight"
},
{
"name": "Cancel"
},
{
"name": "None"
}
],
"entities": [],
"composites": [
{
"name": "From",
"children": [
"Airport"
],
"roles": []
},
{
"name": "To",
"children": [
"Airport"
],
"roles": []
}
],
"closedLists": [
{
"name": "Airport",
"subLists": [
{
"canonicalForm": "Paris",
"list": [
"paris"
]
},
{
"canonicalForm": "London",
"list": [
"london"
]
},
{
"canonicalForm": "Berlin",
"list": [
"berlin"
]
},
{
"canonicalForm": "New York",
"list": [
"new york"
]
}
],
"roles": []
}
],
"patternAnyEntities": [],
"regex_entities": [],
"prebuiltEntities": [
{
"name": "datetimeV2",
"roles": []
}
],
"model_features": [],
"regex_features": [],
"patterns": [],
"utterances": [
{
"text": "book flight from london to paris on feb 14th",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 27,
"endPos": 31
},
{
"entity": "From",
"startPos": 17,
"endPos": 22
}
]
},
{
"text": "book flight to berlin on feb 14th",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 15,
"endPos": 20
}
]
},
{
"text": "book me a flight from london to paris",
"intent": "Book flight",
"entities": [
{
"entity": "From",
"startPos": 22,
"endPos": 27
},
{
"entity": "To",
"startPos": 32,
"endPos": 36
}
]
},
{
"text": "bye",
"intent": "Cancel",
"entities": []
},
{
"text": "cancel booking",
"intent": "Cancel",
"entities": []
},
{
"text": "exit",
"intent": "Cancel",
"entities": []
},
{
"text": "flight to paris",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
},
{
"text": "flight to paris from london on feb 14th",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
},
{
"entity": "From",
"startPos": 21,
"endPos": 26
}
]
},
{
"text": "fly from berlin to paris on may 5th",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 19,
"endPos": 23
},
{
"entity": "From",
"startPos": 9,
"endPos": 14
}
]
},
{
"text": "go to paris",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 6,
"endPos": 10
}
]
},
{
"text": "going from paris to berlin",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 20,
"endPos": 25
},
{
"entity": "From",
"startPos": 11,
"endPos": 15
}
]
},
{
"text": "ignore",
"intent": "Cancel",
"entities": []
},
{
"text": "travel to paris",
"intent": "Book flight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
}
],
"settings": []
}

Просмотреть файл

@ -1,19 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
""" Bot Configuration """
class DefaultConfig(object):
""" Bot Configuration """
PORT = 3978
APP_ID = ""
APP_PASSWORD = ""
LUIS_APP_ID = ""
# LUIS authoring key from LUIS portal or LUIS Cognitive Service subscription key
LUIS_API_KEY = ""
# LUIS endpoint host name, ie "https://westus.api.cognitive.microsoft.com"
LUIS_API_HOST_NAME = ""

Просмотреть файл

Просмотреть файл

@ -1,265 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"groupLocation": {
"type": "string",
"metadata": {
"description": "Specifies the location of the Resource Group."
}
},
"groupName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the Resource Group."
}
},
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"metadata": {
"description": "The name of the App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"newAppServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan. Defaults to \"westus\"."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"appServicePlanName": "[parameters('newAppServicePlanName')]",
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]"
},
"resources": [
{
"name": "[parameters('groupName')]",
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('groupLocation')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('groupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('appServicePlanName')]",
"apiVersion": "2018-02-01",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"location": "[variables('resourcesLocation')]",
"kind": "app,linux",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
],
"name": "[variables('webAppName')]",
"properties": {
"name": "[variables('webAppName')]",
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('appServicePlanName')]",
"siteConfig": {
"appSettings": [
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
},
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
]
}
],
"outputs": {}
}
}
}
]
}

Просмотреть файл

@ -1,243 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"defaultValue": "F0",
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the new App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"appServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan."
}
},
"existingAppServicePlan": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourcesLocation": "[parameters('appServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('servicePlanName')]",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('servicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppName')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
],
"kind": "app,linux",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]",
"reserved": true,
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"httpsOnly": false,
"siteConfig": {
"appSettings": [
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
]
}
]
}

Просмотреть файл

@ -1,9 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Dialogs module"""
from .booking_dialog import BookingDialog
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
from .main_dialog import MainDialog
__all__ = ["BookingDialog", "CancelAndHelpDialog", "DateResolverDialog", "MainDialog"]

Просмотреть файл

@ -1,119 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Flight booking dialog."""
from botbuilder.dialogs import WaterfallDialog, WaterfallStepContext, DialogTurnResult
from botbuilder.dialogs.prompts import ConfirmPrompt, TextPrompt, PromptOptions
from botbuilder.core import MessageFactory
from datatypes_date_time.timex import Timex
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
class BookingDialog(CancelAndHelpDialog):
"""Flight booking implementation."""
def __init__(self, dialog_id: str = None):
super(BookingDialog, self).__init__(dialog_id or BookingDialog.__name__)
self.add_dialog(TextPrompt(TextPrompt.__name__))
# self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
self.add_dialog(DateResolverDialog(DateResolverDialog.__name__))
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__,
[
self.destination_step,
self.origin_step,
self.travel_date_step,
# self.confirm_step,
self.final_step,
],
)
)
self.initial_dialog_id = WaterfallDialog.__name__
async def destination_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""Prompt for destination."""
booking_details = step_context.options
if booking_details.destination is None:
return await step_context.prompt(
TextPrompt.__name__,
PromptOptions(
prompt=MessageFactory.text("To what city would you like to travel?")
),
) # pylint: disable=line-too-long,bad-continuation
else:
return await step_context.next(booking_details.destination)
async def origin_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""Prompt for origin city."""
booking_details = step_context.options
# Capture the response to the previous step's prompt
booking_details.destination = step_context.result
if booking_details.origin is None:
return await step_context.prompt(
TextPrompt.__name__,
PromptOptions(
prompt=MessageFactory.text("From what city will you be travelling?")
),
) # pylint: disable=line-too-long,bad-continuation
else:
return await step_context.next(booking_details.origin)
async def travel_date_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""Prompt for travel date.
This will use the DATE_RESOLVER_DIALOG."""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.origin = step_context.result
if not booking_details.travel_date or self.is_ambiguous(
booking_details.travel_date
):
return await step_context.begin_dialog(
DateResolverDialog.__name__, booking_details.travel_date
) # pylint: disable=line-too-long
else:
return await step_context.next(booking_details.travel_date)
async def confirm_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""Confirm the information the user has provided."""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.travel_date = step_context.result
msg = (
f"Please confirm, I have you traveling to: { booking_details.destination }"
f" from: { booking_details.origin } on: { booking_details.travel_date}."
)
# Offer a YES/NO prompt.
return await step_context.prompt(
ConfirmPrompt.__name__, PromptOptions(prompt=MessageFactory.text(msg))
)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""Complete the interaction and end the dialog."""
if step_context.result:
booking_details = step_context.options
booking_details.travel_date = step_context.result
return await step_context.end_dialog(booking_details)
else:
return await step_context.end_dialog()
def is_ambiguous(self, timex: str) -> bool:
"""Ensure time is correct."""
timex_property = Timex(timex)
return "definite" not in timex_property.types

Просмотреть файл

@ -1,45 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Handle cancel and help intents."""
from botbuilder.dialogs import (
ComponentDialog,
DialogContext,
DialogTurnResult,
DialogTurnStatus,
)
from botbuilder.schema import ActivityTypes
class CancelAndHelpDialog(ComponentDialog):
"""Implementation of handling cancel and help."""
async def on_begin_dialog(
self, inner_dc: DialogContext, options: object
) -> DialogTurnResult:
result = await self.interrupt(inner_dc)
if result is not None:
return result
return await super(CancelAndHelpDialog, self).on_begin_dialog(inner_dc, options)
async def on_continue_dialog(self, inner_dc: DialogContext) -> DialogTurnResult:
result = await self.interrupt(inner_dc)
if result is not None:
return result
return await super(CancelAndHelpDialog, self).on_continue_dialog(inner_dc)
async def interrupt(self, inner_dc: DialogContext) -> DialogTurnResult:
"""Detect interruptions."""
if inner_dc.context.activity.type == ActivityTypes.message:
text = inner_dc.context.activity.text.lower()
if text == "help" or text == "?":
await inner_dc.context.send_activity("Show Help...")
return DialogTurnResult(DialogTurnStatus.Waiting)
if text == "cancel" or text == "quit":
await inner_dc.context.send_activity("Cancelling")
return await inner_dc.cancel_all_dialogs()
return None

Просмотреть файл

@ -1,82 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Handle date/time resolution for booking dialog."""
from botbuilder.core import MessageFactory
from botbuilder.dialogs import WaterfallDialog, DialogTurnResult, WaterfallStepContext
from botbuilder.dialogs.prompts import (
DateTimePrompt,
PromptValidatorContext,
PromptOptions,
DateTimeResolution,
)
from datatypes_date_time.timex import Timex
from .cancel_and_help_dialog import CancelAndHelpDialog
class DateResolverDialog(CancelAndHelpDialog):
"""Resolve the date"""
def __init__(self, dialog_id: str = None):
super(DateResolverDialog, self).__init__(
dialog_id or DateResolverDialog.__name__
)
self.add_dialog(
DateTimePrompt(
DateTimePrompt.__name__, DateResolverDialog.datetime_prompt_validator
)
)
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__ + "2", [self.initial_step, self.final_step]
)
)
self.initial_dialog_id = WaterfallDialog.__name__ + "2"
async def initial_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""Prompt for the date."""
timex = step_context.options
prompt_msg = "On what date would you like to travel?"
reprompt_msg = (
"I'm sorry, for best results, please enter your travel "
"date including the month, day and year."
)
if timex is None:
# We were not given any date at all so prompt the user.
return await step_context.prompt(
DateTimePrompt.__name__,
PromptOptions( # pylint: disable=bad-continuation
prompt=MessageFactory.text(prompt_msg),
retry_prompt=MessageFactory.text(reprompt_msg),
),
)
else:
# We have a Date we just need to check it is unambiguous.
if "definite" in Timex(timex).types:
# This is essentially a "reprompt" of the data we were given up front.
return await step_context.prompt(
DateTimePrompt.__name__, PromptOptions(prompt=reprompt_msg)
)
else:
return await step_context.next(DateTimeResolution(timex=timex))
async def final_step(self, step_context: WaterfallStepContext):
"""Cleanup - set final return value and end dialog."""
timex = step_context.result[0].timex
return await step_context.end_dialog(timex)
@staticmethod
async def datetime_prompt_validator(prompt_context: PromptValidatorContext) -> bool:
""" Validate the date provided is in proper form. """
if prompt_context.recognized.succeeded:
timex = prompt_context.recognized.value[0].timex.split("T")[0]
# TODO: Needs TimexProperty
return "definite" in Timex(timex).types
return False

Просмотреть файл

@ -1,83 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Main dialog. """
from botbuilder.dialogs import (
ComponentDialog,
WaterfallDialog,
WaterfallStepContext,
DialogTurnResult,
)
from botbuilder.dialogs.prompts import TextPrompt, PromptOptions
from botbuilder.core import MessageFactory
from booking_details import BookingDetails
from helpers.luis_helper import LuisHelper
from .booking_dialog import BookingDialog
class MainDialog(ComponentDialog):
"""Main dialog. """
def __init__(self, configuration: dict, dialog_id: str = None):
super(MainDialog, self).__init__(dialog_id or MainDialog.__name__)
self._configuration = configuration
self.add_dialog(TextPrompt(TextPrompt.__name__))
self.add_dialog(BookingDialog())
self.add_dialog(
WaterfallDialog(
"WFDialog", [self.intro_step, self.act_step, self.final_step]
)
)
self.initial_dialog_id = "WFDialog"
async def intro_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""Initial prompt."""
return await step_context.prompt(
TextPrompt.__name__,
PromptOptions(
prompt=MessageFactory.text("What can I help you with today?")
),
)
async def act_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""Use language understanding to gather details about booking."""
# In this sample we only have a single Intent we are concerned with.
# However, typically a scenario will have multiple different Intents
# each corresponding to starting a different child Dialog.
booking_details = (
await LuisHelper.execute_luis_query(
self._configuration, step_context.context
)
if step_context.result is not None
else BookingDetails()
)
# Run the BookingDialog giving it whatever details we have from the
# model. The dialog will prompt to find out the remaining details.
return await step_context.begin_dialog(BookingDialog.__name__, booking_details)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""Complete dialog.
At this step, with details from the user, display the completed
flight booking to the user.
"""
# If the child dialog ("BookingDialog") was cancelled or the user failed
# to confirm, the Result here will be null.
if step_context.result is not None:
result = step_context.result
# Now we have all the booking details call the booking service.
# If the call to the booking service was successful tell the user.
# time_property = Timex(result.travel_date)
# travel_date_msg = time_property.to_natural_language(datetime.now())
msg = (
f"I have you booked to {result.destination} from"
f" {result.origin} on {result.travel_date}."
)
await step_context.context.send_activity(MessageFactory.text(msg))
else:
await step_context.context.send_activity(MessageFactory.text("Thank you."))
return await step_context.end_dialog()

Просмотреть файл

@ -1,7 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Helpers module."""
from . import activity_helper, luis_helper, dialog_helper
__all__ = ["activity_helper", "dialog_helper", "luis_helper"]

Просмотреть файл

@ -1,38 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Helper to create reply object."""
from datetime import datetime
from botbuilder.schema import (
Activity,
ActivityTypes,
ChannelAccount,
ConversationAccount,
)
def create_activity_reply(activity: Activity, text: str = None, locale: str = None):
"""Helper to create reply object."""
return Activity(
type=ActivityTypes.message,
timestamp=datetime.utcnow(),
from_property=ChannelAccount(
id=getattr(activity.recipient, "id", None),
name=getattr(activity.recipient, "name", None),
),
recipient=ChannelAccount(
id=activity.from_property.id, name=activity.from_property.name
),
reply_to_id=activity.id,
service_url=activity.service_url,
channel_id=activity.channel_id,
conversation=ConversationAccount(
is_group=activity.conversation.is_group,
id=activity.conversation.id,
name=activity.conversation.name,
),
text=text or "",
locale=locale or "",
attachments=[],
entities=[],
)

Просмотреть файл

@ -1,22 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Utility to run dialogs."""
from botbuilder.core import StatePropertyAccessor, TurnContext
from botbuilder.dialogs import Dialog, DialogSet, DialogTurnStatus
class DialogHelper:
"""Dialog Helper implementation."""
@staticmethod
async def run_dialog(
dialog: Dialog, turn_context: TurnContext, accessor: StatePropertyAccessor
): # pylint: disable=line-too-long
"""Run dialog."""
dialog_set = DialogSet(accessor)
dialog_set.add(dialog)
dialog_context = await dialog_set.create_context(turn_context)
results = await dialog_context.continue_dialog()
if results.status == DialogTurnStatus.Empty:
await dialog_context.begin_dialog(dialog.id)

Просмотреть файл

@ -1,63 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Helper to call LUIS service."""
from botbuilder.ai.luis import LuisRecognizer, LuisApplication
from botbuilder.core import TurnContext
from booking_details import BookingDetails
# pylint: disable=line-too-long
class LuisHelper:
"""LUIS helper implementation."""
@staticmethod
async def execute_luis_query(
configuration, turn_context: TurnContext
) -> BookingDetails:
"""Invoke LUIS service to perform prediction/evaluation of utterance."""
booking_details = BookingDetails()
# pylint:disable=broad-except
try:
luis_application = LuisApplication(
configuration.LUIS_APP_ID,
configuration.LUIS_API_KEY,
configuration.LUIS_API_HOST_NAME,
)
recognizer = LuisRecognizer(luis_application)
recognizer_result = await recognizer.recognize(turn_context)
if recognizer_result.intents:
intent = sorted(
recognizer_result.intents,
key=recognizer_result.intents.get,
reverse=True,
)[:1][0]
if intent == "Book_flight":
# We need to get the result from the LUIS JSON which at every level returns an array.
to_entities = recognizer_result.entities.get("$instance", {}).get(
"To", []
)
if to_entities:
booking_details.destination = to_entities[0]["text"]
from_entities = recognizer_result.entities.get("$instance", {}).get(
"From", []
)
if from_entities:
booking_details.origin = from_entities[0]["text"]
# This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
# TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
date_entities = recognizer_result.entities.get("$instance", {}).get(
"datetime", []
)
if date_entities:
booking_details.travel_date = (
None
) # Set when we get a timex format
except Exception as exception:
print(exception)
return booking_details

Просмотреть файл

@ -1,28 +0,0 @@
#!/usr/bin/env python
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""Django's command-line utility for administrative tasks."""
import os
import sys
from django.core.management.commands.runserver import Command as runserver
import config
def main():
"""Django's command-line utility for administrative tasks."""
runserver.default_port = config.DefaultConfig.PORT
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bots.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()

Просмотреть файл

@ -1,10 +0,0 @@
# Django 2.2 before 2.2.10 has a security vulnerability.
Django~=2.2.24
requests==2.23.0
botframework-connector>=4.4.0.b1
botbuilder-schema>=4.4.0.b1
botbuilder-core>=4.4.0.b1
botbuilder-dialogs>=4.4.0.b1
botbuilder-ai>=4.4.0.b1
datatypes-date-time>=1.0.0.a1
azure-cognitiveservices-language-luis>=0.2.0

Просмотреть файл

@ -1,30 +0,0 @@
# EchoBot
Bot Framework v4 echo bot sample.
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a simple bot that accepts input from the user and echoes it back.
## Running the sample
- Clone the repository
```bash
git clone https://github.com/Microsoft/botbuilder-python.git
```
- Activate your desired virtual environment
- Bring up a terminal, navigate to `botbuilder-python\samples\02.echo-bot` folder
- In the terminal, type `pip install -r requirements.txt`
- In the terminal, type `python app.py`
## Testing the bot using Bot Framework Emulator
[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
### Connect to bot using Bot Framework Emulator
- Launch Bot Framework Emulator
- Paste this URL in the emulator window - http://localhost:3978/api/messages
## Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)

Просмотреть файл

@ -1,77 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import sys
from datetime import datetime
from quart import Quart, request, Response
from botbuilder.core import BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter
from botbuilder.schema import Activity, ActivityTypes
from bots import EchoBot
# Create the loop and Quart APP
APP = Quart(__name__, instance_relative_config=True)
APP.config.from_object("config.DefaultConfig")
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = BotFrameworkAdapterSettings(APP.config["APP_ID"], APP.config["APP_PASSWORD"])
ADAPTER = BotFrameworkAdapter(SETTINGS)
# Catch-all for errors.
async def on_error(context: TurnContext, error: Exception):
# This check writes out errors to console log .vs. APP insights.
# NOTE: In production environment, you should consider logging this to Azure
# application insights.
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
# Send a message to the user
await context.send_activity("The bot encountered an error or bug.")
await context.send_activity("To continue to run this bot, please fix the bot source code.")
# Send a trace activity if we're talking to the Bot Framework Emulator
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
# Create the Bot
BOT = EchoBot()
# Listen for incoming requests on /api/messages
@APP.route("/api/messages", methods=["POST"])
async def messages():
# Main bot message handler.
if "application/json" in request.headers["Content-Type"]:
body = await request.json
else:
return Response("", status=415)
activity = Activity().deserialize(body)
auth_header = (
request.headers["Authorization"] if "Authorization" in request.headers else ""
)
try:
await ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
return Response("", status=201)
except Exception as exception:
raise exception
if __name__ == "__main__":
try:
APP.run(debug=False, port=APP.config["PORT"]) # nosec debug
except Exception as exception:
raise exception

Просмотреть файл

@ -1,6 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .echo_bot import EchoBot
__all__ = ["EchoBot"]

Просмотреть файл

@ -1,17 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import ActivityHandler, MessageFactory, TurnContext
from botbuilder.schema import ChannelAccount
class EchoBot(ActivityHandler):
async def on_members_added_activity(
self, members_added: [ChannelAccount], turn_context: TurnContext
):
for member in members_added:
if member.id != turn_context.activity.recipient.id:
await turn_context.send_activity("Hello and welcome!")
async def on_message_activity(self, turn_context: TurnContext):
return await turn_context.send_activity(MessageFactory.text(f"Echo: {turn_context.activity.text}"))

Просмотреть файл

@ -1,15 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import os
""" Bot Configuration """
class DefaultConfig:
""" Bot Configuration """
PORT = 3978
APP_ID = os.environ.get("MicrosoftAppId", "")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "")

Просмотреть файл

@ -1,265 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"groupLocation": {
"type": "string",
"metadata": {
"description": "Specifies the location of the Resource Group."
}
},
"groupName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the Resource Group."
}
},
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"metadata": {
"description": "The name of the App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"newAppServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan. Defaults to \"westus\"."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"appServicePlanName": "[parameters('newAppServicePlanName')]",
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]"
},
"resources": [
{
"name": "[parameters('groupName')]",
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('groupLocation')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('groupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('appServicePlanName')]",
"apiVersion": "2018-02-01",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"location": "[variables('resourcesLocation')]",
"kind": "app,linux",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
],
"name": "[variables('webAppName')]",
"properties": {
"name": "[variables('webAppName')]",
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('appServicePlanName')]",
"siteConfig": {
"appSettings": [
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
},
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
]
}
],
"outputs": {}
}
}
}
]
}

Просмотреть файл

@ -1,243 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"defaultValue": "F0",
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the new App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"appServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan."
}
},
"existingAppServicePlan": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourcesLocation": "[parameters('appServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('servicePlanName')]",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('servicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppName')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
],
"kind": "app,linux",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]",
"reserved": true,
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"httpsOnly": false,
"siteConfig": {
"appSettings": [
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
]
}
]
}

Просмотреть файл

@ -1,2 +0,0 @@
botbuilder-core>=4.4.0b1
quart>=0.10.0

Просмотреть файл

@ -1,216 +0,0 @@
# Setting up LUIS via CLI:
This README contains information on how to create and deploy a LUIS application. When the bot is ready to be deployed to production, we recommend creating a LUIS Endpoint Resource for usage with your LUIS App.
> _For instructions on how to create a LUIS Application via the LUIS portal, see these Quickstart steps:_
> 1. _[Quickstart: Create a new app in the LUIS portal][Quickstart-create]_
> 2. _[Quickstart: Deploy an app in the LUIS portal][Quickstart-deploy]_
[Quickstart-create]: https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-build-app
[Quickstart-deploy]:https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-deploy-app
## Table of Contents:
- [Prerequisites](#Prerequisites)
- [Import a new LUIS Application using a local LUIS application](#Import-a-new-LUIS-Application-using-a-local-LUIS-application)
- [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#How-to-create-a-LUIS-Endpoint-resource-in-Azure-and-pair-it-with-a-LUIS-Application)
___
## [Prerequisites](#Table-of-Contents):
#### Install Azure CLI >=2.0.61:
Visit the following page to find the correct installer for your OS:
- https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
#### Install LUIS CLI >=2.4.0:
Open a CLI of your choice and type the following:
```bash
npm i -g luis-apis@^2.4.0
```
#### LUIS portal account:
You should already have a LUIS account with either https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. To determine where to create a LUIS account, consider where you will deploy your LUIS applications, and then place them in [the corresponding region][LUIS-Authoring-Regions].
After you've created your account, you need your [Authoring Key][LUIS-AKey] and a LUIS application ID.
[LUIS-Authoring-Regions]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-reference-regions#luis-authoring-regions]
[LUIS-AKey]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-concept-keys#authoring-key
___
## [Import a new LUIS Application using a local LUIS application](#Table-of-Contents)
### 1. Import the local LUIS application to luis.ai
```bash
luis import application --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appName "FlightBooking" --in "./cognitiveModels/FlightBooking.json"
```
Outputs the following JSON:
```json
{
"id": "########-####-####-####-############",
"name": "FlightBooking",
"description": "A LUIS model that uses intent and entities.",
"culture": "en-us",
"usageScenario": "",
"domain": "",
"versionsCount": 1,
"createdDateTime": "2019-03-29T18:32:02Z",
"endpoints": {},
"endpointHitsCount": 0,
"activeVersion": "0.1",
"ownerEmail": "bot@contoso.com",
"tokenizerVersion": "1.0.0"
}
```
For the next step, you'll need the `"id"` value for `--appId` and the `"activeVersion"` value for `--versionId`.
### 2. Train the LUIS Application
```bash
luis train version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --wait
```
### 3. Publish the LUIS Application
```bash
luis publish version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --publishRegion "LuisAppPublishRegion"
```
> `--region` corresponds to the region you _author_ your application in. The regions available for this are "westus", "westeurope" and "australiaeast". <br/>
> These regions correspond to the three available portals, https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. <br/>
> `--publishRegion` corresponds to the region of the endpoint you're publishing to, (e.g. "westus", "southeastasia", "westeurope", "brazilsouth"). <br/>
> See the [reference docs][Endpoint-API] for a list of available publish/endpoint regions.
[Endpoint-API]: https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78
Outputs the following:
```json
{
"versionId": "0.1",
"isStaging": false,
"endpointUrl": "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/########-####-####-####-############",
"region": "westus",
"assignedEndpointKey": null,
"endpointRegion": "westus",
"failedRegions": "",
"publishedDateTime": "2019-03-29T18:40:32Z",
"directVersionPublish": false
}
```
To see how to create an LUIS Cognitive Service Resource in Azure, please see [the next README][README-LUIS]. This Resource should be used when you want to move your bot to production. The instructions will show you how to create and pair the resource with a LUIS Application.
[README-LUIS]: ./README-LUIS.md
___
## [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#Table-of-Contents)
### 1. Create a new LUIS Cognitive Services resource on Azure via Azure CLI
> _Note:_ <br/>
> _If you don't have a Resource Group in your Azure subscription, you can create one through the Azure portal or through using:_
> ```bash
> az group create --subscription "AzureSubscriptionGuid" --location "westus" --name "ResourceGroupName"
> ```
> _To see a list of valid locations, use `az account list-locations`_
```bash
# Use Azure CLI to create the LUIS Key resource on Azure
az cognitiveservices account create --kind "luis" --name "NewLuisResourceName" --sku "S0" --location "westus" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
The command will output a response similar to the JSON below:
```json
{
"endpoint": "https://westus.api.cognitive.microsoft.com/luis/v2.0",
"etag": "\"########-####-####-####-############\"",
"id": "/subscriptions/########-####-####-####-############/resourceGroups/ResourceGroupName/providers/Microsoft.CognitiveServices/accounts/NewLuisResourceName",
"internalId": "################################",
"kind": "luis",
"location": "westus",
"name": "NewLuisResourceName",
"provisioningState": "Succeeded",
"resourceGroup": "ResourceGroupName",
"sku": {
"name": "S0",
"tier": null
},
"tags": null,
"type": "Microsoft.CognitiveServices/accounts"
}
```
Take the output from the previous command and create a JSON file in the following format:
```json
{
"azureSubscriptionId": "00000000-0000-0000-0000-000000000000",
"resourceGroup": "ResourceGroupName",
"accountName": "NewLuisResourceName"
}
```
### 2. Retrieve ARM access token via Azure CLI
```bash
az account get-access-token --subscription "AzureSubscriptionGuid"
```
This will return an object that looks like this:
```json
{
"accessToken": "eyJ0eXAiOiJKVtokentokentokentokentokeng1dCI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyIsItokenI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUzODc3MTUwLCJuYmYiOjE1NTM4NzcxNTAsImV4cCI6MTU1Mzg4MTA1MCwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2ZmZTQyM2RkLWJhM2YtNDg0Ny04NjgyLWExNTI5MDA4MjM4Ny9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVZRQXEvOEtBQUFBeGVUc201NDlhVHg4RE1mMFlRVnhGZmxxOE9RSC9PODR3QktuSmRqV1FqTkkwbmxLYzB0bHJEZzMyMFZ5bWZGaVVBSFBvNUFFUTNHL0FZNDRjdk01T3M0SEt0OVJkcE5JZW9WU0dzd0kvSkk9IiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiNDhmNDVjNjEtMTg3Zi00MjUxLTlmZWItMTllZGFkZmMwMmE3IiwiZmFtaWx5X25hbWUiOiJHdW0iLCJnaXZlbl9uYW1lIjoiU3RldmVuIiwiaXBhZGRyIjoiMTY3LjIyMC4yLjU1IiwibmFtZSI6IlN0ZXZlbiBHdW0iLCJvaWQiOiJmZmU0MjNkZC1iYTNmLTQ4NDctODY4Mi1hMTUyOTAwODIzODciLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjEyNzUyMTE4NC0xNjA0MDEyOTIwLTE4ODc5Mjc1MjctMjYwOTgyODUiLCJwdWlkIjoiMTAwMzdGRkVBMDQ4NjlBNyIsInJoIjoiSSIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6Ik1rMGRNMWszN0U5ckJyMjhieUhZYjZLSU85LXVFQVVkZFVhNWpkSUd1Nk0iLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InN0Z3VtQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJzdGd1bUBtaWNyb3NvZnQuY29tIiwidXRpIjoiT2w2NGN0TXY4RVNEQzZZQWRqRUFtokenInZlciI6IjEuMCJ9.kFAsEilE0mlS1pcpqxf4rEnRKeYsehyk-gz-zJHUrE__oad3QjgDSBDPrR_ikLdweynxbj86pgG4QFaHURNCeE6SzrbaIrNKw-n9jrEtokenlosOxg_0l2g1LeEUOi5Q4gQREAU_zvSbl-RY6sAadpOgNHtGvz3Rc6FZRITfkckSLmsKAOFoh-aWC6tFKG8P52rtB0qVVRz9tovBeNqkMYL49s9ypduygbXNVwSQhm5JszeWDgrFuVFHBUP_iENCQYGQpEZf_KvjmX1Ur1F9Eh9nb4yI2gFlKncKNsQl-tokenK7-tokentokentokentokentokentokenatoken",
"expiresOn": "2200-12-31 23:59:59.999999",
"subscription": "AzureSubscriptionGuid",
"tenant": "tenant-guid",
"tokenType": "Bearer"
}
```
The value needed for the next step is the `"accessToken"`.
### 3. Use `luis add appazureaccount` to pair your LUIS resource with a LUIS Application
```bash
luis add appazureaccount --in "path/to/created/requestBody.json" --appId "LuisAppId" --authoringKey "LuisAuthoringKey" --armToken "accessToken"
```
If successful, it should yield a response like this:
```json
{
"code": "Success",
"message": "Operation Successful"
}
```
### 4. See the LUIS Cognitive Services' keys
```bash
az cognitiveservices account keys list --name "NewLuisResourceName" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
This will return an object that looks like this:
```json
{
"key1": "9a69####dc8f####8eb4####399f####",
"key2": "####f99e####4b1a####fb3b####6b9f"
}
```

Просмотреть файл

@ -1,64 +0,0 @@
# CoreBot
Bot Framework v4 core bot sample.
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities
- Implement a multi-turn conversation using Dialogs
- Handle user interruptions for such things as `Help` or `Cancel`
- Prompt for and validate requests for information from the user
## Prerequisites
This sample **requires** prerequisites in order to run.
### Overview
This bot uses [LUIS](https://www.luis.ai), an AI based cognitive service, to implement language understanding.
### Install Python 3.7
### Create a LUIS Application to enable language understanding
LUIS language model setup, training, and application configuration steps can be found [here](https://docs.microsoft.com/azure/bot-service/bot-builder-howto-v4-luis?view=azure-bot-service-4.0&tabs=cs).
If you wish to create a LUIS application via the CLI, these steps can be found in the [README-LUIS.md](README-LUIS.md).
## Running the sample
- Bring up a terminal, navigate to `botbuilder-samples\samples\python\13.core-bot` folder
- Activate your desired virtual environment
- Run `pip install -r requirements.txt` to install all dependencies
- Update LuisAppId, LuisAPIKey and LuisAPIHostName in `config.py` with the information retrieved from the [LUIS portal](https://www.luis.ai)
- Run your bot with `python app.py`
## Testing the bot using Bot Framework Emulator
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
### Connect to the bot using Bot Framework Emulator
- Launch Bot Framework Emulator
- Enter a Bot URL of `http://localhost:3978/api/messages`
## Deploy the bot to Azure
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
# Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Dialogs](https://docs.microsoft.com/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0)
- [Gathering Input Using Prompts](https://docs.microsoft.com/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0&tabs=csharp)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
- [Azure Portal](https://portal.azure.com)
- [Language Understanding using LUIS](https://docs.microsoft.com/azure/cognitive-services/luis/)
- [Channels and Bot Connector Service](https://docs.microsoft.com/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)

Просмотреть файл

@ -1,56 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import sys
import traceback
from datetime import datetime
from botbuilder.core import (
BotFrameworkAdapter,
BotFrameworkAdapterSettings,
ConversationState,
TurnContext,
)
from botbuilder.schema import ActivityTypes, Activity
class AdapterWithErrorHandler(BotFrameworkAdapter):
def __init__(
self,
settings: BotFrameworkAdapterSettings,
conversation_state: ConversationState,
):
super().__init__(settings)
self._conversation_state = conversation_state
# Catch-all for errors.
async def on_error(context: TurnContext, error: Exception):
# This check writes out errors to console log
# NOTE: In production environment, you should consider logging this to Azure
# application insights.
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
traceback.print_exc()
# Send a message to the user
await context.send_activity("The bot encountered an error or bug.")
await context.send_activity(
"To continue to run this bot, please fix the bot source code."
)
# Send a trace activity if we're talking to the Bot Framework Emulator
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)
# Clear out state
nonlocal self
await self._conversation_state.delete(context)
self.on_turn_error = on_error

Просмотреть файл

@ -1,75 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
This sample shows how to create a bot that demonstrates the following:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities.
- Implement a multi-turn conversation using Dialogs.
- Handle user interruptions for such things as `Help` or `Cancel`.
- Prompt for and validate requests for information from the user.
"""
from quart import Quart, request, Response
from botbuilder.core import (
BotFrameworkAdapterSettings,
ConversationState,
MemoryStorage,
UserState,
)
from botbuilder.schema import Activity
from dialogs import MainDialog, BookingDialog
from bots import DialogAndWelcomeBot
from adapter_with_error_handler import AdapterWithErrorHandler
from flight_booking_recognizer import FlightBookingRecognizer
APP = Quart(__name__, instance_relative_config=True)
APP.config.from_object("config.DefaultConfig")
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = BotFrameworkAdapterSettings(APP.config["APP_ID"], APP.config["APP_PASSWORD"])
# Create MemoryStorage, UserState and ConversationState
MEMORY = MemoryStorage()
USER_STATE = UserState(MEMORY)
CONVERSATION_STATE = ConversationState(MEMORY)
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
ADAPTER = AdapterWithErrorHandler(SETTINGS, CONVERSATION_STATE)
# Create dialogs and Bot
RECOGNIZER = FlightBookingRecognizer(APP.config)
BOOKING_DIALOG = BookingDialog()
DIALOG = MainDialog(RECOGNIZER, BOOKING_DIALOG)
BOT = DialogAndWelcomeBot(CONVERSATION_STATE, USER_STATE, DIALOG)
# Listen for incoming requests on /api/messages
@APP.route("/api/messages", methods=["POST"])
async def messages():
# Main bot message handler.
if "application/json" in request.headers["Content-Type"]:
body = await request.json
else:
return Response("", status=415)
activity = Activity().deserialize(body)
auth_header = (
request.headers["Authorization"] if "Authorization" in request.headers else ""
)
try:
await ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
return Response("", status=201)
except Exception as exception:
raise exception
if __name__ == "__main__":
try:
APP.run(debug=False, port=APP.config["PORT"]) # nosec debug
except Exception as exception:
raise exception

Просмотреть файл

@ -1,18 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
class BookingDetails:
def __init__(
self,
destination: str = None,
origin: str = None,
travel_date: str = None,
unsupported_airports=None,
):
if unsupported_airports is None:
unsupported_airports = []
self.destination = destination
self.origin = origin
self.travel_date = travel_date
self.unsupported_airports = unsupported_airports

Просмотреть файл

@ -1,7 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .dialog_bot import DialogBot
from .dialog_and_welcome_bot import DialogAndWelcomeBot
__all__ = ["DialogBot", "DialogAndWelcomeBot"]

Просмотреть файл

@ -1,57 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import json
import os.path
from typing import List
from botbuilder.core import (
ConversationState,
MessageFactory,
UserState,
TurnContext,
)
from botbuilder.dialogs import Dialog
from botbuilder.schema import Attachment, ChannelAccount
from helpers.dialog_helper import DialogHelper
from .dialog_bot import DialogBot
class DialogAndWelcomeBot(DialogBot):
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
super(DialogAndWelcomeBot, self).__init__(
conversation_state, user_state, dialog
)
async def on_members_added_activity(
self, members_added: List[ChannelAccount], turn_context: TurnContext
):
for member in members_added:
# Greet anyone that was not the target (recipient) of this message.
# To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
if member.id != turn_context.activity.recipient.id:
welcome_card = self.create_adaptive_card_attachment()
response = MessageFactory.attachment(welcome_card)
await turn_context.send_activity(response)
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
)
# Load attachment from file.
def create_adaptive_card_attachment(self):
relative_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(relative_path, "../cards/welcomeCard.json")
with open(path) as in_file:
card = json.load(in_file)
return Attachment(
content_type="application/vnd.microsoft.card.adaptive", content=card
)

Просмотреть файл

@ -1,41 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import ActivityHandler, ConversationState, UserState, TurnContext
from botbuilder.dialogs import Dialog
from helpers.dialog_helper import DialogHelper
class DialogBot(ActivityHandler):
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
if conversation_state is None:
raise Exception(
"[DialogBot]: Missing parameter. conversation_state is required"
)
if user_state is None:
raise Exception("[DialogBot]: Missing parameter. user_state is required")
if dialog is None:
raise Exception("[DialogBot]: Missing parameter. dialog is required")
self.conversation_state = conversation_state
self.user_state = user_state
self.dialog = dialog
async def on_turn(self, turn_context: TurnContext):
await super().on_turn(turn_context)
# Save any state changes that might have occurred during the turn.
await self.conversation_state.save_changes(turn_context, False)
await self.user_state.save_changes(turn_context, False)
async def on_message_activity(self, turn_context: TurnContext):
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
)

Просмотреть файл

@ -1,46 +0,0 @@
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": "true",
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Get an overview",
"url": "https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0"
},
{
"type": "Action.OpenUrl",
"title": "Ask a question",
"url": "https://stackoverflow.com/questions/tagged/botframework"
},
{
"type": "Action.OpenUrl",
"title": "Learn how to deploy",
"url": "https://docs.microsoft.com/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
}
]
}

Просмотреть файл

@ -1,339 +0,0 @@
{
"luis_schema_version": "3.2.0",
"versionId": "0.1",
"name": "FlightBooking",
"desc": "Luis Model for CoreBot",
"culture": "en-us",
"tokenizerVersion": "1.0.0",
"intents": [
{
"name": "BookFlight"
},
{
"name": "Cancel"
},
{
"name": "GetWeather"
},
{
"name": "None"
}
],
"entities": [],
"composites": [
{
"name": "From",
"children": [
"Airport"
],
"roles": []
},
{
"name": "To",
"children": [
"Airport"
],
"roles": []
}
],
"closedLists": [
{
"name": "Airport",
"subLists": [
{
"canonicalForm": "Paris",
"list": [
"paris",
"cdg"
]
},
{
"canonicalForm": "London",
"list": [
"london",
"lhr"
]
},
{
"canonicalForm": "Berlin",
"list": [
"berlin",
"txl"
]
},
{
"canonicalForm": "New York",
"list": [
"new york",
"jfk"
]
},
{
"canonicalForm": "Seattle",
"list": [
"seattle",
"sea"
]
}
],
"roles": []
}
],
"patternAnyEntities": [],
"regex_entities": [],
"prebuiltEntities": [
{
"name": "datetimeV2",
"roles": []
}
],
"model_features": [],
"regex_features": [],
"patterns": [],
"utterances": [
{
"text": "book a flight",
"intent": "BookFlight",
"entities": []
},
{
"text": "book a flight from new york",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 19,
"endPos": 26
}
]
},
{
"text": "book a flight from seattle",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 19,
"endPos": 25
}
]
},
{
"text": "book a hotel in new york",
"intent": "None",
"entities": []
},
{
"text": "book a restaurant",
"intent": "None",
"entities": []
},
{
"text": "book flight from london to paris on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 17,
"endPos": 22
},
{
"entity": "To",
"startPos": 27,
"endPos": 31
}
]
},
{
"text": "book flight to berlin on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 15,
"endPos": 20
}
]
},
{
"text": "book me a flight from london to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 22,
"endPos": 27
},
{
"entity": "To",
"startPos": 32,
"endPos": 36
}
]
},
{
"text": "bye",
"intent": "Cancel",
"entities": []
},
{
"text": "cancel booking",
"intent": "Cancel",
"entities": []
},
{
"text": "exit",
"intent": "Cancel",
"entities": []
},
{
"text": "find an airport near me",
"intent": "None",
"entities": []
},
{
"text": "flight to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
},
{
"text": "flight to paris from london on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
},
{
"entity": "From",
"startPos": 21,
"endPos": 26
}
]
},
{
"text": "fly from berlin to paris on may 5th",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 9,
"endPos": 14
},
{
"entity": "To",
"startPos": 19,
"endPos": 23
}
]
},
{
"text": "go to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 6,
"endPos": 10
}
]
},
{
"text": "going from paris to berlin",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 11,
"endPos": 15
},
{
"entity": "To",
"startPos": 20,
"endPos": 25
}
]
},
{
"text": "i'd like to rent a car",
"intent": "None",
"entities": []
},
{
"text": "ignore",
"intent": "Cancel",
"entities": []
},
{
"text": "travel from new york to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 12,
"endPos": 19
},
{
"entity": "To",
"startPos": 24,
"endPos": 28
}
]
},
{
"text": "travel to new york",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 17
}
]
},
{
"text": "travel to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
},
{
"text": "what's the forecast for this friday?",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like for tomorrow",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like in new york",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like?",
"intent": "GetWeather",
"entities": []
},
{
"text": "winter is coming",
"intent": "None",
"entities": []
}
],
"settings": []
}

Просмотреть файл

@ -1,19 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import os
""" Bot Configuration """
class DefaultConfig:
""" Bot Configuration """
PORT = 3978
APP_ID = os.environ.get("MicrosoftAppId", "")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "")
LUIS_APP_ID = os.environ.get("LuisAppId", "")
LUIS_API_KEY = os.environ.get("LuisAPIKey", "")
# LUIS endpoint host name, ie "westus.api.cognitive.microsoft.com"
LUIS_API_HOST_NAME = os.environ.get("LuisAPIHostName", "")

Просмотреть файл

@ -1,265 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"groupLocation": {
"type": "string",
"metadata": {
"description": "Specifies the location of the Resource Group."
}
},
"groupName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the Resource Group."
}
},
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"metadata": {
"description": "The name of the App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"newAppServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan. Defaults to \"westus\"."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"appServicePlanName": "[parameters('newAppServicePlanName')]",
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]"
},
"resources": [
{
"name": "[parameters('groupName')]",
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('groupLocation')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('groupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('appServicePlanName')]",
"apiVersion": "2018-02-01",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"location": "[variables('resourcesLocation')]",
"kind": "app,linux",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
],
"name": "[variables('webAppName')]",
"properties": {
"name": "[variables('webAppName')]",
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('appServicePlanName')]",
"siteConfig": {
"appSettings": [
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
},
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
]
}
],
"outputs": {}
}
}
}
]
}

Просмотреть файл

@ -1,243 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"defaultValue": "F0",
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the new App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"appServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan."
}
},
"existingAppServicePlan": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourcesLocation": "[parameters('appServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('servicePlanName')]",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('servicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppName')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
],
"kind": "app,linux",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]",
"reserved": true,
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"httpsOnly": false,
"siteConfig": {
"appSettings": [
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
]
}
]
}

Просмотреть файл

@ -1,9 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .booking_dialog import BookingDialog
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
from .main_dialog import MainDialog
__all__ = ["BookingDialog", "CancelAndHelpDialog", "DateResolverDialog", "MainDialog"]

Просмотреть файл

@ -1,136 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datatypes_date_time.timex import Timex
from botbuilder.dialogs import WaterfallDialog, WaterfallStepContext, DialogTurnResult
from botbuilder.dialogs.prompts import ConfirmPrompt, TextPrompt, PromptOptions
from botbuilder.core import MessageFactory
from botbuilder.schema import InputHints
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
class BookingDialog(CancelAndHelpDialog):
def __init__(self, dialog_id: str = None):
super(BookingDialog, self).__init__(dialog_id or BookingDialog.__name__)
self.add_dialog(TextPrompt(TextPrompt.__name__))
self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
self.add_dialog(DateResolverDialog(DateResolverDialog.__name__))
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__,
[
self.destination_step,
self.origin_step,
self.travel_date_step,
self.confirm_step,
self.final_step,
],
)
)
self.initial_dialog_id = WaterfallDialog.__name__
async def destination_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
If a destination city has not been provided, prompt for one.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
if booking_details.destination is None:
message_text = "Where would you like to travel to?"
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
return await step_context.next(booking_details.destination)
async def origin_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""
If an origin city has not been provided, prompt for one.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the response to the previous step's prompt
booking_details.destination = step_context.result
if booking_details.origin is None:
message_text = "From what city will you be travelling?"
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
return await step_context.next(booking_details.origin)
async def travel_date_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
If a travel date has not been provided, prompt for one.
This will use the DATE_RESOLVER_DIALOG.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.origin = step_context.result
if not booking_details.travel_date or self.is_ambiguous(
booking_details.travel_date
):
return await step_context.begin_dialog(
DateResolverDialog.__name__, booking_details.travel_date
)
return await step_context.next(booking_details.travel_date)
async def confirm_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
Confirm the information the user has provided.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.travel_date = step_context.result
message_text = (
f"Please confirm, I have you traveling to: { booking_details.destination } from: "
f"{ booking_details.origin } on: { booking_details.travel_date}."
)
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
# Offer a YES/NO prompt.
return await step_context.prompt(
ConfirmPrompt.__name__, PromptOptions(prompt=prompt_message)
)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""
Complete the interaction and end the dialog.
:param step_context:
:return DialogTurnResult:
"""
if step_context.result:
booking_details = step_context.options
return await step_context.end_dialog(booking_details)
return await step_context.end_dialog()
def is_ambiguous(self, timex: str) -> bool:
timex_property = Timex(timex)
return "definite" not in timex_property.types

Просмотреть файл

@ -1,47 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.dialogs import (
ComponentDialog,
DialogContext,
DialogTurnResult,
DialogTurnStatus,
)
from botbuilder.schema import ActivityTypes, InputHints
from botbuilder.core import MessageFactory
class CancelAndHelpDialog(ComponentDialog):
def __init__(self, dialog_id: str):
super(CancelAndHelpDialog, self).__init__(dialog_id)
async def on_continue_dialog(self, inner_dc: DialogContext) -> DialogTurnResult:
result = await self.interrupt(inner_dc)
if result is not None:
return result
return await super(CancelAndHelpDialog, self).on_continue_dialog(inner_dc)
async def interrupt(self, inner_dc: DialogContext) -> DialogTurnResult:
if inner_dc.context.activity.type == ActivityTypes.message:
text = inner_dc.context.activity.text.lower()
help_message_text = "Show Help..."
help_message = MessageFactory.text(
help_message_text, help_message_text, InputHints.expecting_input
)
if text in ("help", "?"):
await inner_dc.context.send_activity(help_message)
return DialogTurnResult(DialogTurnStatus.Waiting)
cancel_message_text = "Cancelling"
cancel_message = MessageFactory.text(
cancel_message_text, cancel_message_text, InputHints.ignoring_input
)
if text in ("cancel", "quit"):
await inner_dc.context.send_activity(cancel_message)
return await inner_dc.cancel_all_dialogs()
return None

Просмотреть файл

@ -1,80 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datatypes_date_time.timex import Timex
from botbuilder.core import MessageFactory
from botbuilder.dialogs import WaterfallDialog, DialogTurnResult, WaterfallStepContext
from botbuilder.dialogs.prompts import (
DateTimePrompt,
PromptValidatorContext,
PromptOptions,
DateTimeResolution,
)
from botbuilder.schema import InputHints
from .cancel_and_help_dialog import CancelAndHelpDialog
class DateResolverDialog(CancelAndHelpDialog):
def __init__(self, dialog_id: str = None):
super(DateResolverDialog, self).__init__(
dialog_id or DateResolverDialog.__name__
)
self.add_dialog(
DateTimePrompt(
DateTimePrompt.__name__, DateResolverDialog.datetime_prompt_validator
)
)
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__ + "2", [self.initial_step, self.final_step]
)
)
self.initial_dialog_id = WaterfallDialog.__name__ + "2"
async def initial_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
timex = step_context.options
prompt_msg_text = "On what date would you like to travel?"
prompt_msg = MessageFactory.text(
prompt_msg_text, prompt_msg_text, InputHints.expecting_input
)
reprompt_msg_text = "I'm sorry, for best results, please enter your travel date including the month, " \
"day and year. "
reprompt_msg = MessageFactory.text(
reprompt_msg_text, reprompt_msg_text, InputHints.expecting_input
)
if timex is None:
# We were not given any date at all so prompt the user.
return await step_context.prompt(
DateTimePrompt.__name__,
PromptOptions(prompt=prompt_msg, retry_prompt=reprompt_msg),
)
# We have a Date we just need to check it is unambiguous.
if "definite" not in Timex(timex).types:
# This is essentially a "reprompt" of the data we were given up front.
return await step_context.prompt(
DateTimePrompt.__name__, PromptOptions(prompt=reprompt_msg)
)
return await step_context.next(DateTimeResolution(timex=timex))
async def final_step(self, step_context: WaterfallStepContext):
timex = step_context.result[0].timex
return await step_context.end_dialog(timex)
@staticmethod
async def datetime_prompt_validator(prompt_context: PromptValidatorContext) -> bool:
if prompt_context.recognized.succeeded:
timex = prompt_context.recognized.value[0].timex.split("T")[0]
# TODO: Needs TimexProperty
return "definite" in Timex(timex).types
return False

Просмотреть файл

@ -1,132 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.dialogs import (
ComponentDialog,
WaterfallDialog,
WaterfallStepContext,
DialogTurnResult,
)
from botbuilder.dialogs.prompts import TextPrompt, PromptOptions
from botbuilder.core import MessageFactory, TurnContext
from botbuilder.schema import InputHints
from booking_details import BookingDetails
from flight_booking_recognizer import FlightBookingRecognizer
from helpers.luis_helper import LuisHelper, Intent
from .booking_dialog import BookingDialog
class MainDialog(ComponentDialog):
def __init__(
self, luis_recognizer: FlightBookingRecognizer, booking_dialog: BookingDialog
):
super(MainDialog, self).__init__(MainDialog.__name__)
self._luis_recognizer = luis_recognizer
self._booking_dialog_id = booking_dialog.id
self.add_dialog(TextPrompt(TextPrompt.__name__))
self.add_dialog(booking_dialog)
self.add_dialog(
WaterfallDialog(
"WFDialog", [self.intro_step, self.act_step, self.final_step]
)
)
self.initial_dialog_id = "WFDialog"
async def intro_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
if not self._luis_recognizer.is_configured:
await step_context.context.send_activity(
MessageFactory.text(
"NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and "
"'LuisAPIHostName' to the appsettings.json file.",
input_hint=InputHints.ignoring_input,
)
)
return await step_context.next(None)
message_text = (
str(step_context.options)
if step_context.options
else "What can I help you with today?"
)
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
async def act_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
if not self._luis_recognizer.is_configured:
# LUIS is not configured, we just run the BookingDialog path with an empty BookingDetailsInstance.
return await step_context.begin_dialog(
self._booking_dialog_id, BookingDetails()
)
# Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
intent, luis_result = await LuisHelper.execute_luis_query(
self._luis_recognizer, step_context.context
)
if intent == Intent.BOOK_FLIGHT.value and luis_result:
# Show a warning for Origin and Destination if we can't resolve them.
await MainDialog._show_warning_for_unsupported_cities(
step_context.context, luis_result
)
# Run the BookingDialog giving it whatever details we have from the LUIS call.
return await step_context.begin_dialog(self._booking_dialog_id, luis_result)
if intent == Intent.GET_WEATHER.value:
get_weather_text = "TODO: get weather flow here"
get_weather_message = MessageFactory.text(
get_weather_text, get_weather_text, InputHints.ignoring_input
)
await step_context.context.send_activity(get_weather_message)
else:
didnt_understand_text = (
"Sorry, I didn't get that. Please try asking in a different way"
)
didnt_understand_message = MessageFactory.text(
didnt_understand_text, didnt_understand_text, InputHints.ignoring_input
)
await step_context.context.send_activity(didnt_understand_message)
return await step_context.next(None)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
# If the child dialog ("BookingDialog") was cancelled or the user failed to confirm,
# the Result here will be null.
if step_context.result is not None:
result = step_context.result
# Now we have all the booking details call the booking service.
# If the call to the booking service was successful tell the user.
# time_property = Timex(result.travel_date)
# travel_date_msg = time_property.to_natural_language(datetime.now())
msg_txt = f"I have you booked to {result.destination} from {result.origin} on {result.travel_date}"
message = MessageFactory.text(msg_txt, msg_txt, InputHints.ignoring_input)
await step_context.context.send_activity(message)
prompt_message = "What else can I do for you?"
return await step_context.replace_dialog(self.id, prompt_message)
@staticmethod
async def _show_warning_for_unsupported_cities(
context: TurnContext, luis_result: BookingDetails
) -> None:
if luis_result.unsupported_airports:
message_text = (
f"Sorry but the following airports are not supported:"
f" {', '.join(luis_result.unsupported_airports)}"
)
message = MessageFactory.text(
message_text, message_text, InputHints.ignoring_input
)
await context.send_activity(message)

Просмотреть файл

@ -1,34 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from typing import Dict
from botbuilder.ai.luis import LuisApplication, LuisRecognizer
from botbuilder.core import Recognizer, RecognizerResult, TurnContext
class FlightBookingRecognizer(Recognizer):
def __init__(self, configuration: Dict):
self._recognizer = None
luis_is_configured = (
configuration["LUIS_APP_ID"]
and configuration["LUIS_API_KEY"]
and configuration["LUIS_API_HOST_NAME"]
)
if luis_is_configured:
luis_application = LuisApplication(
configuration["LUIS_APP_ID"],
configuration["LUIS_API_KEY"],
"https://" + configuration["LUIS_API_HOST_NAME"],
)
self._recognizer = LuisRecognizer(luis_application)
@property
def is_configured(self) -> bool:
# Returns true if luis is configured in the config.py and initialized.
return self._recognizer is not None
async def recognize(self, turn_context: TurnContext) -> RecognizerResult:
return await self._recognizer.recognize(turn_context)

Просмотреть файл

@ -1,6 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from . import activity_helper, luis_helper, dialog_helper
__all__ = ["activity_helper", "dialog_helper", "luis_helper"]

Просмотреть файл

@ -1,37 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datetime import datetime
from botbuilder.schema import (
Activity,
ActivityTypes,
ChannelAccount,
ConversationAccount,
)
def create_activity_reply(activity: Activity, text: str = None, locale: str = None):
return Activity(
type=ActivityTypes.message,
timestamp=datetime.utcnow(),
from_property=ChannelAccount(
id=getattr(activity.recipient, "id", None),
name=getattr(activity.recipient, "name", None),
),
recipient=ChannelAccount(
id=activity.from_property.id, name=activity.from_property.name
),
reply_to_id=activity.id,
service_url=activity.service_url,
channel_id=activity.channel_id,
conversation=ConversationAccount(
is_group=activity.conversation.is_group,
id=activity.conversation.id,
name=activity.conversation.name,
),
text=text or "",
locale=locale or "",
attachments=[],
entities=[],
)

Просмотреть файл

@ -1,19 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import StatePropertyAccessor, TurnContext
from botbuilder.dialogs import Dialog, DialogSet, DialogTurnStatus
class DialogHelper:
@staticmethod
async def run_dialog(
dialog: Dialog, turn_context: TurnContext, accessor: StatePropertyAccessor
):
dialog_set = DialogSet(accessor)
dialog_set.add(dialog)
dialog_context = await dialog_set.create_context(turn_context)
results = await dialog_context.continue_dialog()
if results.status == DialogTurnStatus.Empty:
await dialog_context.begin_dialog(dialog.id)

Просмотреть файл

@ -1,102 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from enum import Enum
from typing import Dict
from botbuilder.ai.luis import LuisRecognizer
from botbuilder.core import IntentScore, TopIntent, TurnContext
from booking_details import BookingDetails
class Intent(Enum):
BOOK_FLIGHT = "BookFlight"
CANCEL = "Cancel"
GET_WEATHER = "GetWeather"
NONE_INTENT = "NoneIntent"
def top_intent(intents: Dict[Intent, dict]) -> TopIntent:
max_intent = Intent.NONE_INTENT
max_value = 0.0
for intent, value in intents:
intent_score = IntentScore(value)
if intent_score.score > max_value:
max_intent, max_value = intent, intent_score.score
return TopIntent(max_intent, max_value)
class LuisHelper:
@staticmethod
async def execute_luis_query(
luis_recognizer: LuisRecognizer, turn_context: TurnContext
) -> (Intent, object):
"""
Returns an object with preformatted LUIS results for the bot's dialogs to consume.
"""
result = None
intent = None
try:
recognizer_result = await luis_recognizer.recognize(turn_context)
intent = (
sorted(
recognizer_result.intents,
key=recognizer_result.intents.get,
reverse=True,
)[:1][0]
if recognizer_result.intents
else None
)
if intent == Intent.BOOK_FLIGHT.value:
result = BookingDetails()
# We need to get the result from the LUIS JSON which at every level returns an array.
to_entities = recognizer_result.entities.get("$instance", {}).get(
"To", []
)
if len(to_entities) > 0:
if recognizer_result.entities.get("To", [{"$instance": {}}])[0][
"$instance"
]:
result.destination = to_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
to_entities[0]["text"].capitalize()
)
from_entities = recognizer_result.entities.get("$instance", {}).get(
"From", []
)
if len(from_entities) > 0:
if recognizer_result.entities.get("From", [{"$instance": {}}])[0][
"$instance"
]:
result.origin = from_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
from_entities[0]["text"].capitalize()
)
# This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop
# the Time part. TIMEX is a format that represents DateTime expressions that include some ambiguity.
# e.g. missing a Year.
date_entities = recognizer_result.entities.get("datetime", [])
if date_entities:
timex = date_entities[0]["timex"]
if timex:
datetime = timex[0].split("T")[0]
result.travel_date = datetime
else:
result.travel_date = None
except Exception as exception:
print(exception)
return intent, result

Просмотреть файл

@ -1,5 +0,0 @@
quart>=0.10.0
botbuilder-dialogs>=4.14.0
botbuilder-ai>=4.14.0
datatypes-date-time>=1.0.0.a2

Просмотреть файл

@ -1,30 +0,0 @@
# EchoBot
Bot Framework v4 echo bot sample.
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a simple bot that accepts input from the user and echoes it back.
## Running the sample
- Clone the repository
```bash
git clone https://github.com/Microsoft/botbuilder-python.git
```
- Activate your desired virtual environment
- Bring up a terminal, navigate to `botbuilder-python\samples\02.echo-bot` folder
- In the terminal, type `pip install -r requirements.txt`
- In the terminal, type `python app.py`
## Testing the bot using Bot Framework Emulator
[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
### Connect to bot using Bot Framework Emulator
- Launch Bot Framework Emulator
- Paste this URL in the emulator window - http://localhost:3978/api/messages
## Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)

Просмотреть файл

@ -1,92 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import os
import sys
from datetime import datetime
import tornado.ioloop
import tornado.web
import tornado.escape
from tornado.options import define, parse_command_line, options
from botbuilder.core import BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter
from botbuilder.schema import Activity, ActivityTypes
from bots import EchoBot
define("port", default=3978, help="Application port")
define("app_id", default=os.environ.get("MicrosoftAppId", ""), help="Application id from Azure")
define(
"app_password", default=os.environ.get("MicrosoftAppPassword", ""),
help="Application password from Azure"
)
define("debug", default=True, help="run in debug mode")
class MessageHandler(tornado.web.RequestHandler):
def initialize(self, adapter: BotFrameworkAdapter, bot: EchoBot):
self.adapter = adapter
self.bot = bot
async def post(self):
# Main bot message handler.
if "application/json" in self.request.headers["Content-Type"]:
body = tornado.escape.json_decode(self.request.body)
else:
self.set_status(415)
return
activity = Activity().from_dict(body)
auth_header = (
self.request.headers["Authorization"] if "Authorization" in self.request.headers else ""
)
try:
await self.adapter.process_activity(activity, auth_header, self.bot.on_turn)
self.set_status(201)
return
except Exception as exception:
raise exception
parse_command_line()
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = BotFrameworkAdapterSettings(options.app_id, options.app_password)
ADAPTER = BotFrameworkAdapter(SETTINGS)
# Catch-all for errors.
async def on_error(context: TurnContext, error: Exception):
# This check writes out errors to console log .vs. app insights.
# NOTE: In production environment, you should consider logging this to Azure
# application insights.
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
# Send a message to the user
await context.send_activity("The bot encountered an error or bug.")
await context.send_activity("To continue to run this bot, please fix the bot source code.")
# Send a trace activity if we're talking to the Bot Framework Emulator
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
BOT = EchoBot()
APP = tornado.web.Application(
[
(r"/api/messages", MessageHandler, dict(adapter=ADAPTER, bot=BOT)),
],
debug=options.debug,
)
APP.listen(options.port)
tornado.ioloop.IOLoop.current().start()

Просмотреть файл

@ -1,6 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .echo_bot import EchoBot
__all__ = ["EchoBot"]

Просмотреть файл

@ -1,17 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import ActivityHandler, MessageFactory, TurnContext
from botbuilder.schema import ChannelAccount
class EchoBot(ActivityHandler):
async def on_members_added_activity(
self, members_added: [ChannelAccount], turn_context: TurnContext
):
for member in members_added:
if member.id != turn_context.activity.recipient.id:
await turn_context.send_activity("Hello and welcome!")
async def on_message_activity(self, turn_context: TurnContext):
return await turn_context.send_activity(MessageFactory.text(f"Echo: {turn_context.activity.text}"))

Просмотреть файл

@ -1,265 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"groupLocation": {
"type": "string",
"metadata": {
"description": "Specifies the location of the Resource Group."
}
},
"groupName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the Resource Group."
}
},
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"metadata": {
"description": "The name of the App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"newAppServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan. Defaults to \"westus\"."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"appServicePlanName": "[parameters('newAppServicePlanName')]",
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]"
},
"resources": [
{
"name": "[parameters('groupName')]",
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('groupLocation')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('groupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('appServicePlanName')]",
"apiVersion": "2018-02-01",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"location": "[variables('resourcesLocation')]",
"kind": "app,linux",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
],
"name": "[variables('webAppName')]",
"properties": {
"name": "[variables('webAppName')]",
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('appServicePlanName')]",
"siteConfig": {
"appSettings": [
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
},
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
]
}
],
"outputs": {}
}
}
}
]
}

Просмотреть файл

@ -1,243 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"defaultValue": "F0",
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the new App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"appServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan."
}
},
"existingAppServicePlan": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourcesLocation": "[parameters('appServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('servicePlanName')]",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('servicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppName')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
],
"kind": "app,linux",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]",
"reserved": true,
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"httpsOnly": false,
"siteConfig": {
"appSettings": [
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
]
}
]
}

Просмотреть файл

@ -1,2 +0,0 @@
botbuilder-core>=4.4.0b1
flask>=1.0.3

Просмотреть файл

@ -1,216 +0,0 @@
# Setting up LUIS via CLI:
This README contains information on how to create and deploy a LUIS application. When the bot is ready to be deployed to production, we recommend creating a LUIS Endpoint Resource for usage with your LUIS App.
> _For instructions on how to create a LUIS Application via the LUIS portal, see these Quickstart steps:_
> 1. _[Quickstart: Create a new app in the LUIS portal][Quickstart-create]_
> 2. _[Quickstart: Deploy an app in the LUIS portal][Quickstart-deploy]_
[Quickstart-create]: https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-build-app
[Quickstart-deploy]:https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-deploy-app
## Table of Contents:
- [Prerequisites](#Prerequisites)
- [Import a new LUIS Application using a local LUIS application](#Import-a-new-LUIS-Application-using-a-local-LUIS-application)
- [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#How-to-create-a-LUIS-Endpoint-resource-in-Azure-and-pair-it-with-a-LUIS-Application)
___
## [Prerequisites](#Table-of-Contents):
#### Install Azure CLI >=2.0.61:
Visit the following page to find the correct installer for your OS:
- https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
#### Install LUIS CLI >=2.4.0:
Open a CLI of your choice and type the following:
```bash
npm i -g luis-apis@^2.4.0
```
#### LUIS portal account:
You should already have a LUIS account with either https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. To determine where to create a LUIS account, consider where you will deploy your LUIS applications, and then place them in [the corresponding region][LUIS-Authoring-Regions].
After you've created your account, you need your [Authoring Key][LUIS-AKey] and a LUIS application ID.
[LUIS-Authoring-Regions]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-reference-regions#luis-authoring-regions]
[LUIS-AKey]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-concept-keys#authoring-key
___
## [Import a new LUIS Application using a local LUIS application](#Table-of-Contents)
### 1. Import the local LUIS application to luis.ai
```bash
luis import application --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appName "FlightBooking" --in "./cognitiveModels/FlightBooking.json"
```
Outputs the following JSON:
```json
{
"id": "########-####-####-####-############",
"name": "FlightBooking",
"description": "A LUIS model that uses intent and entities.",
"culture": "en-us",
"usageScenario": "",
"domain": "",
"versionsCount": 1,
"createdDateTime": "2019-03-29T18:32:02Z",
"endpoints": {},
"endpointHitsCount": 0,
"activeVersion": "0.1",
"ownerEmail": "bot@contoso.com",
"tokenizerVersion": "1.0.0"
}
```
For the next step, you'll need the `"id"` value for `--appId` and the `"activeVersion"` value for `--versionId`.
### 2. Train the LUIS Application
```bash
luis train version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --wait
```
### 3. Publish the LUIS Application
```bash
luis publish version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --publishRegion "LuisAppPublishRegion"
```
> `--region` corresponds to the region you _author_ your application in. The regions available for this are "westus", "westeurope" and "australiaeast". <br/>
> These regions correspond to the three available portals, https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. <br/>
> `--publishRegion` corresponds to the region of the endpoint you're publishing to, (e.g. "westus", "southeastasia", "westeurope", "brazilsouth"). <br/>
> See the [reference docs][Endpoint-API] for a list of available publish/endpoint regions.
[Endpoint-API]: https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78
Outputs the following:
```json
{
"versionId": "0.1",
"isStaging": false,
"endpointUrl": "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/########-####-####-####-############",
"region": "westus",
"assignedEndpointKey": null,
"endpointRegion": "westus",
"failedRegions": "",
"publishedDateTime": "2019-03-29T18:40:32Z",
"directVersionPublish": false
}
```
To see how to create an LUIS Cognitive Service Resource in Azure, please see [the next README][README-LUIS]. This Resource should be used when you want to move your bot to production. The instructions will show you how to create and pair the resource with a LUIS Application.
[README-LUIS]: ./README-LUIS.md
___
## [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#Table-of-Contents)
### 1. Create a new LUIS Cognitive Services resource on Azure via Azure CLI
> _Note:_ <br/>
> _If you don't have a Resource Group in your Azure subscription, you can create one through the Azure portal or through using:_
> ```bash
> az group create --subscription "AzureSubscriptionGuid" --location "westus" --name "ResourceGroupName"
> ```
> _To see a list of valid locations, use `az account list-locations`_
```bash
# Use Azure CLI to create the LUIS Key resource on Azure
az cognitiveservices account create --kind "luis" --name "NewLuisResourceName" --sku "S0" --location "westus" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
The command will output a response similar to the JSON below:
```json
{
"endpoint": "https://westus.api.cognitive.microsoft.com/luis/v2.0",
"etag": "\"########-####-####-####-############\"",
"id": "/subscriptions/########-####-####-####-############/resourceGroups/ResourceGroupName/providers/Microsoft.CognitiveServices/accounts/NewLuisResourceName",
"internalId": "################################",
"kind": "luis",
"location": "westus",
"name": "NewLuisResourceName",
"provisioningState": "Succeeded",
"resourceGroup": "ResourceGroupName",
"sku": {
"name": "S0",
"tier": null
},
"tags": null,
"type": "Microsoft.CognitiveServices/accounts"
}
```
Take the output from the previous command and create a JSON file in the following format:
```json
{
"azureSubscriptionId": "00000000-0000-0000-0000-000000000000",
"resourceGroup": "ResourceGroupName",
"accountName": "NewLuisResourceName"
}
```
### 2. Retrieve ARM access token via Azure CLI
```bash
az account get-access-token --subscription "AzureSubscriptionGuid"
```
This will return an object that looks like this:
```json
{
"accessToken": "eyJ0eXAiOiJKVtokentokentokentokentokeng1dCI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyIsItokenI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUzODc3MTUwLCJuYmYiOjE1NTM4NzcxNTAsImV4cCI6MTU1Mzg4MTA1MCwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2ZmZTQyM2RkLWJhM2YtNDg0Ny04NjgyLWExNTI5MDA4MjM4Ny9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVZRQXEvOEtBQUFBeGVUc201NDlhVHg4RE1mMFlRVnhGZmxxOE9RSC9PODR3QktuSmRqV1FqTkkwbmxLYzB0bHJEZzMyMFZ5bWZGaVVBSFBvNUFFUTNHL0FZNDRjdk01T3M0SEt0OVJkcE5JZW9WU0dzd0kvSkk9IiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiNDhmNDVjNjEtMTg3Zi00MjUxLTlmZWItMTllZGFkZmMwMmE3IiwiZmFtaWx5X25hbWUiOiJHdW0iLCJnaXZlbl9uYW1lIjoiU3RldmVuIiwiaXBhZGRyIjoiMTY3LjIyMC4yLjU1IiwibmFtZSI6IlN0ZXZlbiBHdW0iLCJvaWQiOiJmZmU0MjNkZC1iYTNmLTQ4NDctODY4Mi1hMTUyOTAwODIzODciLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjEyNzUyMTE4NC0xNjA0MDEyOTIwLTE4ODc5Mjc1MjctMjYwOTgyODUiLCJwdWlkIjoiMTAwMzdGRkVBMDQ4NjlBNyIsInJoIjoiSSIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6Ik1rMGRNMWszN0U5ckJyMjhieUhZYjZLSU85LXVFQVVkZFVhNWpkSUd1Nk0iLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InN0Z3VtQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJzdGd1bUBtaWNyb3NvZnQuY29tIiwidXRpIjoiT2w2NGN0TXY4RVNEQzZZQWRqRUFtokenInZlciI6IjEuMCJ9.kFAsEilE0mlS1pcpqxf4rEnRKeYsehyk-gz-zJHUrE__oad3QjgDSBDPrR_ikLdweynxbj86pgG4QFaHURNCeE6SzrbaIrNKw-n9jrEtokenlosOxg_0l2g1LeEUOi5Q4gQREAU_zvSbl-RY6sAadpOgNHtGvz3Rc6FZRITfkckSLmsKAOFoh-aWC6tFKG8P52rtB0qVVRz9tovBeNqkMYL49s9ypduygbXNVwSQhm5JszeWDgrFuVFHBUP_iENCQYGQpEZf_KvjmX1Ur1F9Eh9nb4yI2gFlKncKNsQl-tokenK7-tokentokentokentokentokentokenatoken",
"expiresOn": "2200-12-31 23:59:59.999999",
"subscription": "AzureSubscriptionGuid",
"tenant": "tenant-guid",
"tokenType": "Bearer"
}
```
The value needed for the next step is the `"accessToken"`.
### 3. Use `luis add appazureaccount` to pair your LUIS resource with a LUIS Application
```bash
luis add appazureaccount --in "path/to/created/requestBody.json" --appId "LuisAppId" --authoringKey "LuisAuthoringKey" --armToken "accessToken"
```
If successful, it should yield a response like this:
```json
{
"code": "Success",
"message": "Operation Successful"
}
```
### 4. See the LUIS Cognitive Services' keys
```bash
az cognitiveservices account keys list --name "NewLuisResourceName" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
```
This will return an object that looks like this:
```json
{
"key1": "9a69####dc8f####8eb4####399f####",
"key2": "####f99e####4b1a####fb3b####6b9f"
}
```

Просмотреть файл

@ -1,64 +0,0 @@
# CoreBot
Bot Framework v4 core bot sample.
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities
- Implement a multi-turn conversation using Dialogs
- Handle user interruptions for such things as `Help` or `Cancel`
- Prompt for and validate requests for information from the user
## Prerequisites
This sample **requires** prerequisites in order to run.
### Overview
This bot uses [LUIS](https://www.luis.ai), an AI based cognitive service, to implement language understanding.
### Install Python 3.7
### Create a LUIS Application to enable language understanding
LUIS language model setup, training, and application configuration steps can be found [here](https://docs.microsoft.com/azure/bot-service/bot-builder-howto-v4-luis?view=azure-bot-service-4.0&tabs=cs).
If you wish to create a LUIS application via the CLI, these steps can be found in the [README-LUIS.md](README-LUIS.md).
## Running the sample
- Bring up a terminal, navigate to `botbuilder-samples\samples\python\13.core-bot` folder
- Activate your desired virtual environment
- Run `pip install -r requirements.txt` to install all dependencies
- Update LuisAppId, LuisAPIKey and LuisAPIHostName in `config.py` with the information retrieved from the [LUIS portal](https://www.luis.ai)
- Run your bot with `python app.py`
## Testing the bot using Bot Framework Emulator
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
### Connect to the bot using Bot Framework Emulator
- Launch Bot Framework Emulator
- Enter a Bot URL of `http://localhost:3978/api/messages`
## Deploy the bot to Azure
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
# Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Dialogs](https://docs.microsoft.com/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0)
- [Gathering Input Using Prompts](https://docs.microsoft.com/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0&tabs=csharp)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
- [Azure Portal](https://portal.azure.com)
- [Language Understanding using LUIS](https://docs.microsoft.com/azure/cognitive-services/luis/)
- [Channels and Bot Connector Service](https://docs.microsoft.com/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)

Просмотреть файл

@ -1,56 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import sys
import traceback
from datetime import datetime
from botbuilder.core import (
BotFrameworkAdapter,
BotFrameworkAdapterSettings,
ConversationState,
TurnContext,
)
from botbuilder.schema import ActivityTypes, Activity
class AdapterWithErrorHandler(BotFrameworkAdapter):
def __init__(
self,
settings: BotFrameworkAdapterSettings,
conversation_state: ConversationState,
):
super().__init__(settings)
self._conversation_state = conversation_state
# Catch-all for errors.
async def on_error(context: TurnContext, error: Exception):
# This check writes out errors to console log
# NOTE: In production environment, you should consider logging this to Azure
# application insights.
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
traceback.print_exc()
# Send a message to the user
await context.send_activity("The bot encountered an error or bug.")
await context.send_activity(
"To continue to run this bot, please fix the bot source code."
)
# Send a trace activity if we're talking to the Bot Framework Emulator
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)
# Clear out state
nonlocal self
await self._conversation_state.delete(context)
self.on_turn_error = on_error

Просмотреть файл

@ -1,107 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
This sample shows how to create a bot that demonstrates the following:
- Use [LUIS](https://www.luis.ai) to implement core AI capabilities.
- Implement a multi-turn conversation using Dialogs.
- Handle user interruptions for such things as `Help` or `Cancel`.
- Prompt for and validate requests for information from the user.
"""
import os
import tornado.ioloop
import tornado.web
import tornado.escape
from tornado.options import define, parse_command_line, options
from botbuilder.core import (
BotFrameworkAdapterSettings,
ConversationState,
MemoryStorage,
UserState,
)
from botbuilder.schema import Activity
from dialogs import MainDialog, BookingDialog
from bots import DialogAndWelcomeBot
from adapter_with_error_handler import AdapterWithErrorHandler
from flight_booking_recognizer import FlightBookingRecognizer
define("port", default=3978, help="Application port")
define("app_id", default=os.environ.get("MicrosoftAppId", ""), help="Application id from Azure")
define(
"app_password",
default=os.environ.get("MicrosoftAppPassword", ""),
help="Application password from Azure"
)
define("luis_app_id", default=os.environ.get("LuisAppId", ""), help="Application id for Luis")
define("luis_api_key", default=os.environ.get("LuisApiKey", ""), help="Api key for Luis")
define(
"luis_api_host_name",
default=os.environ.get("LuisAppId", ""),
help="LUIS endpoint host name, ie 'westus.api.cognitive.microsoft.com')"
)
define("debug", default=True, help="run in debug mode")
class MessageHandler(tornado.web.RequestHandler):
def initialize(self, adapter: AdapterWithErrorHandler, bot: DialogAndWelcomeBot):
self.adapter = adapter
self.bot = bot
async def post(self):
# Main bot message handler.
if "application/json" in self.request.headers["Content-Type"]:
body = tornado.escape.json_decode(self.request.body)
else:
self.set_status(415)
return
activity = Activity().from_dict(body)
auth_header = (
self.request.headers["Authorization"] if "Authorization" in self.request.headers else ""
)
try:
await self.adapter.process_activity(activity, auth_header, self.bot.on_turn)
self.set_status(201)
return
except Exception as exception:
raise exception
def main():
parse_command_line()
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
settings = BotFrameworkAdapterSettings(options.app_id, options.app_password)
# Create MemoryStorage, UserState and ConversationState
memory = MemoryStorage()
user_state = UserState(memory)
conversation_state = ConversationState(memory)
# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
adapter = AdapterWithErrorHandler(settings, conversation_state)
# Create dialogs and Bot
recognizer = FlightBookingRecognizer(options)
booking_dialog = BookingDialog()
dialog = MainDialog(recognizer, booking_dialog)
bot = DialogAndWelcomeBot(conversation_state, user_state, dialog)
app = tornado.web.Application(
[
(r"/api/messages", MessageHandler, dict(adapter=adapter, bot=bot)),
],
debug=options.debug,
)
app.listen(options.port)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()

Просмотреть файл

@ -1,18 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
class BookingDetails:
def __init__(
self,
destination: str = None,
origin: str = None,
travel_date: str = None,
unsupported_airports=None,
):
if unsupported_airports is None:
unsupported_airports = []
self.destination = destination
self.origin = origin
self.travel_date = travel_date
self.unsupported_airports = unsupported_airports

Просмотреть файл

@ -1,7 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .dialog_bot import DialogBot
from .dialog_and_welcome_bot import DialogAndWelcomeBot
__all__ = ["DialogBot", "DialogAndWelcomeBot"]

Просмотреть файл

@ -1,57 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import json
import os.path
from typing import List
from botbuilder.core import (
ConversationState,
MessageFactory,
UserState,
TurnContext,
)
from botbuilder.dialogs import Dialog
from botbuilder.schema import Attachment, ChannelAccount
from helpers.dialog_helper import DialogHelper
from .dialog_bot import DialogBot
class DialogAndWelcomeBot(DialogBot):
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
super(DialogAndWelcomeBot, self).__init__(
conversation_state, user_state, dialog
)
async def on_members_added_activity(
self, members_added: List[ChannelAccount], turn_context: TurnContext
):
for member in members_added:
# Greet anyone that was not the target (recipient) of this message.
# To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
if member.id != turn_context.activity.recipient.id:
welcome_card = self.create_adaptive_card_attachment()
response = MessageFactory.attachment(welcome_card)
await turn_context.send_activity(response)
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
)
# Load attachment from file.
def create_adaptive_card_attachment(self):
relative_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(relative_path, "../cards/welcomeCard.json")
with open(path) as in_file:
card = json.load(in_file)
return Attachment(
content_type="application/vnd.microsoft.card.adaptive", content=card
)

Просмотреть файл

@ -1,41 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import ActivityHandler, ConversationState, UserState, TurnContext
from botbuilder.dialogs import Dialog
from helpers.dialog_helper import DialogHelper
class DialogBot(ActivityHandler):
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
if conversation_state is None:
raise Exception(
"[DialogBot]: Missing parameter. conversation_state is required"
)
if user_state is None:
raise Exception("[DialogBot]: Missing parameter. user_state is required")
if dialog is None:
raise Exception("[DialogBot]: Missing parameter. dialog is required")
self.conversation_state = conversation_state
self.user_state = user_state
self.dialog = dialog
async def on_turn(self, turn_context: TurnContext):
await super().on_turn(turn_context)
# Save any state changes that might have occurred during the turn.
await self.conversation_state.save_changes(turn_context, False)
await self.user_state.save_changes(turn_context, False)
async def on_message_activity(self, turn_context: TurnContext):
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
)

Просмотреть файл

@ -1,46 +0,0 @@
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": "true",
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Get an overview",
"url": "https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0"
},
{
"type": "Action.OpenUrl",
"title": "Ask a question",
"url": "https://stackoverflow.com/questions/tagged/botframework"
},
{
"type": "Action.OpenUrl",
"title": "Learn how to deploy",
"url": "https://docs.microsoft.com/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
}
]
}

Просмотреть файл

@ -1,339 +0,0 @@
{
"luis_schema_version": "3.2.0",
"versionId": "0.1",
"name": "FlightBooking",
"desc": "Luis Model for CoreBot",
"culture": "en-us",
"tokenizerVersion": "1.0.0",
"intents": [
{
"name": "BookFlight"
},
{
"name": "Cancel"
},
{
"name": "GetWeather"
},
{
"name": "None"
}
],
"entities": [],
"composites": [
{
"name": "From",
"children": [
"Airport"
],
"roles": []
},
{
"name": "To",
"children": [
"Airport"
],
"roles": []
}
],
"closedLists": [
{
"name": "Airport",
"subLists": [
{
"canonicalForm": "Paris",
"list": [
"paris",
"cdg"
]
},
{
"canonicalForm": "London",
"list": [
"london",
"lhr"
]
},
{
"canonicalForm": "Berlin",
"list": [
"berlin",
"txl"
]
},
{
"canonicalForm": "New York",
"list": [
"new york",
"jfk"
]
},
{
"canonicalForm": "Seattle",
"list": [
"seattle",
"sea"
]
}
],
"roles": []
}
],
"patternAnyEntities": [],
"regex_entities": [],
"prebuiltEntities": [
{
"name": "datetimeV2",
"roles": []
}
],
"model_features": [],
"regex_features": [],
"patterns": [],
"utterances": [
{
"text": "book a flight",
"intent": "BookFlight",
"entities": []
},
{
"text": "book a flight from new york",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 19,
"endPos": 26
}
]
},
{
"text": "book a flight from seattle",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 19,
"endPos": 25
}
]
},
{
"text": "book a hotel in new york",
"intent": "None",
"entities": []
},
{
"text": "book a restaurant",
"intent": "None",
"entities": []
},
{
"text": "book flight from london to paris on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 17,
"endPos": 22
},
{
"entity": "To",
"startPos": 27,
"endPos": 31
}
]
},
{
"text": "book flight to berlin on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 15,
"endPos": 20
}
]
},
{
"text": "book me a flight from london to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 22,
"endPos": 27
},
{
"entity": "To",
"startPos": 32,
"endPos": 36
}
]
},
{
"text": "bye",
"intent": "Cancel",
"entities": []
},
{
"text": "cancel booking",
"intent": "Cancel",
"entities": []
},
{
"text": "exit",
"intent": "Cancel",
"entities": []
},
{
"text": "find an airport near me",
"intent": "None",
"entities": []
},
{
"text": "flight to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
},
{
"text": "flight to paris from london on feb 14th",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
},
{
"entity": "From",
"startPos": 21,
"endPos": 26
}
]
},
{
"text": "fly from berlin to paris on may 5th",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 9,
"endPos": 14
},
{
"entity": "To",
"startPos": 19,
"endPos": 23
}
]
},
{
"text": "go to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 6,
"endPos": 10
}
]
},
{
"text": "going from paris to berlin",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 11,
"endPos": 15
},
{
"entity": "To",
"startPos": 20,
"endPos": 25
}
]
},
{
"text": "i'd like to rent a car",
"intent": "None",
"entities": []
},
{
"text": "ignore",
"intent": "Cancel",
"entities": []
},
{
"text": "travel from new york to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "From",
"startPos": 12,
"endPos": 19
},
{
"entity": "To",
"startPos": 24,
"endPos": 28
}
]
},
{
"text": "travel to new york",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 17
}
]
},
{
"text": "travel to paris",
"intent": "BookFlight",
"entities": [
{
"entity": "To",
"startPos": 10,
"endPos": 14
}
]
},
{
"text": "what's the forecast for this friday?",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like for tomorrow",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like in new york",
"intent": "GetWeather",
"entities": []
},
{
"text": "what's the weather like?",
"intent": "GetWeather",
"entities": []
},
{
"text": "winter is coming",
"intent": "None",
"entities": []
}
],
"settings": []
}

Просмотреть файл

@ -1,265 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"groupLocation": {
"type": "string",
"metadata": {
"description": "Specifies the location of the Resource Group."
}
},
"groupName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the Resource Group."
}
},
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"metadata": {
"description": "The name of the App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"newAppServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan. Defaults to \"westus\"."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"appServicePlanName": "[parameters('newAppServicePlanName')]",
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]"
},
"resources": [
{
"name": "[parameters('groupName')]",
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('groupLocation')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('groupName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('appServicePlanName')]",
"apiVersion": "2018-02-01",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"location": "[variables('resourcesLocation')]",
"kind": "app,linux",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
],
"name": "[variables('webAppName')]",
"properties": {
"name": "[variables('webAppName')]",
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('appServicePlanName')]",
"siteConfig": {
"appSettings": [
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
},
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/sites/', variables('webAppName'))]"
]
}
],
"outputs": {}
}
}
}
]
}

Просмотреть файл

@ -1,243 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appId": {
"type": "string",
"metadata": {
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
}
},
"appSecret": {
"type": "string",
"metadata": {
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
}
},
"botId": {
"type": "string",
"metadata": {
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
}
},
"botSku": {
"defaultValue": "F0",
"type": "string",
"metadata": {
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
}
},
"newAppServicePlanName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the new App Service Plan."
}
},
"newAppServicePlanSku": {
"type": "object",
"defaultValue": {
"name": "S1",
"tier": "Standard",
"size": "S1",
"family": "S",
"capacity": 1
},
"metadata": {
"description": "The SKU of the App Service Plan. Defaults to Standard values."
}
},
"appServicePlanLocation": {
"type": "string",
"metadata": {
"description": "The location of the App Service Plan."
}
},
"existingAppServicePlan": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
}
},
"newWebAppName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
}
}
},
"variables": {
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
"publishingUsername": "[concat('$', parameters('newWebAppName'))]",
"resourcesLocation": "[parameters('appServicePlanLocation')]",
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
},
"resources": [
{
"comments": "Create a new Linux App Service Plan if no existing App Service Plan name was passed in.",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('servicePlanName')]",
"location": "[variables('resourcesLocation')]",
"sku": "[parameters('newAppServicePlanSku')]",
"kind": "linux",
"properties": {
"name": "[variables('servicePlanName')]",
"perSiteScaling": false,
"reserved": true,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "Create a Web App using a Linux App Service Plan",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppName')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
],
"kind": "app,linux",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(parameters('newWebAppName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(parameters('newWebAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]",
"reserved": true,
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"httpsOnly": false,
"siteConfig": {
"appSettings": [
{
"name": "MicrosoftAppId",
"value": "[parameters('appId')]"
},
{
"name": "MicrosoftAppPassword",
"value": "[parameters('appSecret')]"
},
{
"name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
"value": "true"
}
],
"cors": {
"allowedOrigins": [
"https://botservice.hosting.portal.azure.net",
"https://hosting.onecloud.azure-test.net/"
]
}
}
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2016-08-01",
"name": "[concat(variables('webAppName'), '/web')]",
"location": "[variables('resourcesLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "PYTHON|3.7",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2017",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[variables('publishingUsername')]",
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"appCommandLine": "gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:APP",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetName": "",
"minTlsVersion": "1.2",
"ftpsState": "AllAllowed",
"reservedInstanceCount": 0
}
},
{
"apiVersion": "2021-03-01",
"type": "Microsoft.BotService/botServices",
"name": "[parameters('botId')]",
"location": "global",
"kind": "azurebot",
"sku": {
"name": "[parameters('botSku')]"
},
"properties": {
"name": "[parameters('botId')]",
"displayName": "[parameters('botId')]",
"iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
"endpoint": "[variables('botEndpoint')]",
"msaAppId": "[parameters('appId')]",
"luisAppIds": [],
"schemaTransformationVersion": "1.3",
"isCmekEnabled": false,
"isIsolated": false
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
]
}
]
}

Просмотреть файл

@ -1,9 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from .booking_dialog import BookingDialog
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
from .main_dialog import MainDialog
__all__ = ["BookingDialog", "CancelAndHelpDialog", "DateResolverDialog", "MainDialog"]

Просмотреть файл

@ -1,136 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datatypes_date_time.timex import Timex
from botbuilder.dialogs import WaterfallDialog, WaterfallStepContext, DialogTurnResult
from botbuilder.dialogs.prompts import ConfirmPrompt, TextPrompt, PromptOptions
from botbuilder.core import MessageFactory
from botbuilder.schema import InputHints
from .cancel_and_help_dialog import CancelAndHelpDialog
from .date_resolver_dialog import DateResolverDialog
class BookingDialog(CancelAndHelpDialog):
def __init__(self, dialog_id: str = None):
super(BookingDialog, self).__init__(dialog_id or BookingDialog.__name__)
self.add_dialog(TextPrompt(TextPrompt.__name__))
self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
self.add_dialog(DateResolverDialog(DateResolverDialog.__name__))
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__,
[
self.destination_step,
self.origin_step,
self.travel_date_step,
self.confirm_step,
self.final_step,
],
)
)
self.initial_dialog_id = WaterfallDialog.__name__
async def destination_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
If a destination city has not been provided, prompt for one.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
if booking_details.destination is None:
message_text = "Where would you like to travel to?"
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
return await step_context.next(booking_details.destination)
async def origin_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""
If an origin city has not been provided, prompt for one.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the response to the previous step's prompt
booking_details.destination = step_context.result
if booking_details.origin is None:
message_text = "From what city will you be travelling?"
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
return await step_context.next(booking_details.origin)
async def travel_date_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
If a travel date has not been provided, prompt for one.
This will use the DATE_RESOLVER_DIALOG.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.origin = step_context.result
if not booking_details.travel_date or self.is_ambiguous(
booking_details.travel_date
):
return await step_context.begin_dialog(
DateResolverDialog.__name__, booking_details.travel_date
)
return await step_context.next(booking_details.travel_date)
async def confirm_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
"""
Confirm the information the user has provided.
:param step_context:
:return DialogTurnResult:
"""
booking_details = step_context.options
# Capture the results of the previous step
booking_details.travel_date = step_context.result
message_text = (
f"Please confirm, I have you traveling to: { booking_details.destination } from: "
f"{ booking_details.origin } on: { booking_details.travel_date}."
)
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
# Offer a YES/NO prompt.
return await step_context.prompt(
ConfirmPrompt.__name__, PromptOptions(prompt=prompt_message)
)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
"""
Complete the interaction and end the dialog.
:param step_context:
:return DialogTurnResult:
"""
if step_context.result:
booking_details = step_context.options
return await step_context.end_dialog(booking_details)
return await step_context.end_dialog()
def is_ambiguous(self, timex: str) -> bool:
timex_property = Timex(timex)
return "definite" not in timex_property.types

Просмотреть файл

@ -1,47 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.dialogs import (
ComponentDialog,
DialogContext,
DialogTurnResult,
DialogTurnStatus,
)
from botbuilder.schema import ActivityTypes, InputHints
from botbuilder.core import MessageFactory
class CancelAndHelpDialog(ComponentDialog):
def __init__(self, dialog_id: str):
super(CancelAndHelpDialog, self).__init__(dialog_id)
async def on_continue_dialog(self, inner_dc: DialogContext) -> DialogTurnResult:
result = await self.interrupt(inner_dc)
if result is not None:
return result
return await super(CancelAndHelpDialog, self).on_continue_dialog(inner_dc)
async def interrupt(self, inner_dc: DialogContext) -> DialogTurnResult:
if inner_dc.context.activity.type == ActivityTypes.message:
text = inner_dc.context.activity.text.lower()
help_message_text = "Show Help..."
help_message = MessageFactory.text(
help_message_text, help_message_text, InputHints.expecting_input
)
if text in ("help", "?"):
await inner_dc.context.send_activity(help_message)
return DialogTurnResult(DialogTurnStatus.Waiting)
cancel_message_text = "Cancelling"
cancel_message = MessageFactory.text(
cancel_message_text, cancel_message_text, InputHints.ignoring_input
)
if text in ("cancel", "quit"):
await inner_dc.context.send_activity(cancel_message)
return await inner_dc.cancel_all_dialogs()
return None

Просмотреть файл

@ -1,80 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datatypes_date_time.timex import Timex
from botbuilder.core import MessageFactory
from botbuilder.dialogs import WaterfallDialog, DialogTurnResult, WaterfallStepContext
from botbuilder.dialogs.prompts import (
DateTimePrompt,
PromptValidatorContext,
PromptOptions,
DateTimeResolution,
)
from botbuilder.schema import InputHints
from .cancel_and_help_dialog import CancelAndHelpDialog
class DateResolverDialog(CancelAndHelpDialog):
def __init__(self, dialog_id: str = None):
super(DateResolverDialog, self).__init__(
dialog_id or DateResolverDialog.__name__
)
self.add_dialog(
DateTimePrompt(
DateTimePrompt.__name__, DateResolverDialog.datetime_prompt_validator
)
)
self.add_dialog(
WaterfallDialog(
WaterfallDialog.__name__ + "2", [self.initial_step, self.final_step]
)
)
self.initial_dialog_id = WaterfallDialog.__name__ + "2"
async def initial_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
timex = step_context.options
prompt_msg_text = "On what date would you like to travel?"
prompt_msg = MessageFactory.text(
prompt_msg_text, prompt_msg_text, InputHints.expecting_input
)
reprompt_msg_text = "I'm sorry, for best results, please enter your travel date including the month, " \
"day and year. "
reprompt_msg = MessageFactory.text(
reprompt_msg_text, reprompt_msg_text, InputHints.expecting_input
)
if timex is None:
# We were not given any date at all so prompt the user.
return await step_context.prompt(
DateTimePrompt.__name__,
PromptOptions(prompt=prompt_msg, retry_prompt=reprompt_msg),
)
# We have a Date we just need to check it is unambiguous.
if "definite" not in Timex(timex).types:
# This is essentially a "reprompt" of the data we were given up front.
return await step_context.prompt(
DateTimePrompt.__name__, PromptOptions(prompt=reprompt_msg)
)
return await step_context.next(DateTimeResolution(timex=timex))
async def final_step(self, step_context: WaterfallStepContext):
timex = step_context.result[0].timex
return await step_context.end_dialog(timex)
@staticmethod
async def datetime_prompt_validator(prompt_context: PromptValidatorContext) -> bool:
if prompt_context.recognized.succeeded:
timex = prompt_context.recognized.value[0].timex.split("T")[0]
# TODO: Needs TimexProperty
return "definite" in Timex(timex).types
return False

Просмотреть файл

@ -1,132 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.dialogs import (
ComponentDialog,
WaterfallDialog,
WaterfallStepContext,
DialogTurnResult,
)
from botbuilder.dialogs.prompts import TextPrompt, PromptOptions
from botbuilder.core import MessageFactory, TurnContext
from botbuilder.schema import InputHints
from booking_details import BookingDetails
from flight_booking_recognizer import FlightBookingRecognizer
from helpers.luis_helper import LuisHelper, Intent
from .booking_dialog import BookingDialog
class MainDialog(ComponentDialog):
def __init__(
self, luis_recognizer: FlightBookingRecognizer, booking_dialog: BookingDialog
):
super(MainDialog, self).__init__(MainDialog.__name__)
self._luis_recognizer = luis_recognizer
self._booking_dialog_id = booking_dialog.id
self.add_dialog(TextPrompt(TextPrompt.__name__))
self.add_dialog(booking_dialog)
self.add_dialog(
WaterfallDialog(
"WFDialog", [self.intro_step, self.act_step, self.final_step]
)
)
self.initial_dialog_id = "WFDialog"
async def intro_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
if not self._luis_recognizer.is_configured:
await step_context.context.send_activity(
MessageFactory.text(
"NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and "
"'LuisAPIHostName' to the appsettings.json file.",
input_hint=InputHints.ignoring_input,
)
)
return await step_context.next(None)
message_text = (
str(step_context.options)
if step_context.options
else "What can I help you with today?"
)
prompt_message = MessageFactory.text(
message_text, message_text, InputHints.expecting_input
)
return await step_context.prompt(
TextPrompt.__name__, PromptOptions(prompt=prompt_message)
)
async def act_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
if not self._luis_recognizer.is_configured:
# LUIS is not configured, we just run the BookingDialog path with an empty BookingDetailsInstance.
return await step_context.begin_dialog(
self._booking_dialog_id, BookingDetails()
)
# Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
intent, luis_result = await LuisHelper.execute_luis_query(
self._luis_recognizer, step_context.context
)
if intent == Intent.BOOK_FLIGHT.value and luis_result:
# Show a warning for Origin and Destination if we can't resolve them.
await MainDialog._show_warning_for_unsupported_cities(
step_context.context, luis_result
)
# Run the BookingDialog giving it whatever details we have from the LUIS call.
return await step_context.begin_dialog(self._booking_dialog_id, luis_result)
if intent == Intent.GET_WEATHER.value:
get_weather_text = "TODO: get weather flow here"
get_weather_message = MessageFactory.text(
get_weather_text, get_weather_text, InputHints.ignoring_input
)
await step_context.context.send_activity(get_weather_message)
else:
didnt_understand_text = (
"Sorry, I didn't get that. Please try asking in a different way"
)
didnt_understand_message = MessageFactory.text(
didnt_understand_text, didnt_understand_text, InputHints.ignoring_input
)
await step_context.context.send_activity(didnt_understand_message)
return await step_context.next(None)
async def final_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
# If the child dialog ("BookingDialog") was cancelled or the user failed to confirm,
# the Result here will be null.
if step_context.result is not None:
result = step_context.result
# Now we have all the booking details call the booking service.
# If the call to the booking service was successful tell the user.
# time_property = Timex(result.travel_date)
# travel_date_msg = time_property.to_natural_language(datetime.now())
msg_txt = f"I have you booked to {result.destination} from {result.origin} on {result.travel_date}"
message = MessageFactory.text(msg_txt, msg_txt, InputHints.ignoring_input)
await step_context.context.send_activity(message)
prompt_message = "What else can I do for you?"
return await step_context.replace_dialog(self.id, prompt_message)
@staticmethod
async def _show_warning_for_unsupported_cities(
context: TurnContext, luis_result: BookingDetails
) -> None:
if luis_result.unsupported_airports:
message_text = (
f"Sorry but the following airports are not supported:"
f" {', '.join(luis_result.unsupported_airports)}"
)
message = MessageFactory.text(
message_text, message_text, InputHints.ignoring_input
)
await context.send_activity(message)

Просмотреть файл

@ -1,32 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.ai.luis import LuisApplication, LuisRecognizer
from botbuilder.core import Recognizer, RecognizerResult, TurnContext
class FlightBookingRecognizer(Recognizer):
def __init__(self, configuration: object):
self._recognizer = None
luis_is_configured = (
configuration.luis_app_id
and configuration.luis_api_key
and configuration.luis_api_host_name
)
if luis_is_configured:
luis_application = LuisApplication(
configuration.luis_app_id,
configuration.luis_api_key,
"https://" + configuration.luis_api_host_name,
)
self._recognizer = LuisRecognizer(luis_application)
@property
def is_configured(self) -> bool:
# Returns true if luis is configured in the config.py and initialized.
return self._recognizer is not None
async def recognize(self, turn_context: TurnContext) -> RecognizerResult:
return await self._recognizer.recognize(turn_context)

Просмотреть файл

@ -1,6 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from . import activity_helper, luis_helper, dialog_helper
__all__ = ["activity_helper", "dialog_helper", "luis_helper"]

Просмотреть файл

@ -1,37 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from datetime import datetime
from botbuilder.schema import (
Activity,
ActivityTypes,
ChannelAccount,
ConversationAccount,
)
def create_activity_reply(activity: Activity, text: str = None, locale: str = None):
return Activity(
type=ActivityTypes.message,
timestamp=datetime.utcnow(),
from_property=ChannelAccount(
id=getattr(activity.recipient, "id", None),
name=getattr(activity.recipient, "name", None),
),
recipient=ChannelAccount(
id=activity.from_property.id, name=activity.from_property.name
),
reply_to_id=activity.id,
service_url=activity.service_url,
channel_id=activity.channel_id,
conversation=ConversationAccount(
is_group=activity.conversation.is_group,
id=activity.conversation.id,
name=activity.conversation.name,
),
text=text or "",
locale=locale or "",
attachments=[],
entities=[],
)

Просмотреть файл

@ -1,19 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from botbuilder.core import StatePropertyAccessor, TurnContext
from botbuilder.dialogs import Dialog, DialogSet, DialogTurnStatus
class DialogHelper:
@staticmethod
async def run_dialog(
dialog: Dialog, turn_context: TurnContext, accessor: StatePropertyAccessor
):
dialog_set = DialogSet(accessor)
dialog_set.add(dialog)
dialog_context = await dialog_set.create_context(turn_context)
results = await dialog_context.continue_dialog()
if results.status == DialogTurnStatus.Empty:
await dialog_context.begin_dialog(dialog.id)

Просмотреть файл

@ -1,102 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from enum import Enum
from typing import Dict
from botbuilder.ai.luis import LuisRecognizer
from botbuilder.core import IntentScore, TopIntent, TurnContext
from booking_details import BookingDetails
class Intent(Enum):
BOOK_FLIGHT = "BookFlight"
CANCEL = "Cancel"
GET_WEATHER = "GetWeather"
NONE_INTENT = "NoneIntent"
def top_intent(intents: Dict[Intent, dict]) -> TopIntent:
max_intent = Intent.NONE_INTENT
max_value = 0.0
for intent, value in intents:
intent_score = IntentScore(value)
if intent_score.score > max_value:
max_intent, max_value = intent, intent_score.score
return TopIntent(max_intent, max_value)
class LuisHelper:
@staticmethod
async def execute_luis_query(
luis_recognizer: LuisRecognizer, turn_context: TurnContext
) -> (Intent, object):
"""
Returns an object with preformatted LUIS results for the bot's dialogs to consume.
"""
result = None
intent = None
try:
recognizer_result = await luis_recognizer.recognize(turn_context)
intent = (
sorted(
recognizer_result.intents,
key=recognizer_result.intents.get,
reverse=True,
)[:1][0]
if recognizer_result.intents
else None
)
if intent == Intent.BOOK_FLIGHT.value:
result = BookingDetails()
# We need to get the result from the LUIS JSON which at every level returns an array.
to_entities = recognizer_result.entities.get("$instance", {}).get(
"To", []
)
if len(to_entities) > 0:
if recognizer_result.entities.get("To", [{"$instance": {}}])[0][
"$instance"
]:
result.destination = to_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
to_entities[0]["text"].capitalize()
)
from_entities = recognizer_result.entities.get("$instance", {}).get(
"From", []
)
if len(from_entities) > 0:
if recognizer_result.entities.get("From", [{"$instance": {}}])[0][
"$instance"
]:
result.origin = from_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
from_entities[0]["text"].capitalize()
)
# This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop
# the Time part. TIMEX is a format that represents DateTime expressions that include some ambiguity.
# e.g. missing a Year.
date_entities = recognizer_result.entities.get("datetime", [])
if date_entities:
timex = date_entities[0]["timex"]
if timex:
datetime = timex[0].split("T")[0]
result.travel_date = datetime
else:
result.travel_date = None
except Exception as exception:
print(exception)
return intent, result

Просмотреть файл

@ -1,4 +0,0 @@
tornado>=6.0.3
botbuilder-dialogs>=4.14.0
botbuilder-ai>=4.14.0
datatypes-date-time>=1.0.0.a2