-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
1,117 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
FROM python:3.8-slim-buster | ||
|
||
# Install the security updates. | ||
RUN apt-get update | ||
RUN apt-get -y upgrade | ||
|
||
# Dependencies to build requires packages | ||
RUN apt-get -y install gcc | ||
|
||
# Remove all cached file. Get a smaller image. | ||
RUN apt-get clean | ||
RUN rm -rf /var/lib/apt/lists/* | ||
|
||
EXPOSE 3978 | ||
|
||
# Copy the application. | ||
COPY . /opt/app | ||
WORKDIR /opt/app | ||
|
||
# Install the app librairies. | ||
RUN pip install -r requirements.txt | ||
|
||
# Install SpaCy small model | ||
RUN python -m spacy download en_core_web_sm | ||
|
||
# Start the app. | ||
ENTRYPOINT [ "python" ] | ||
CMD [ "main.py" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 Joffrey Bienvenu | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# chatbot | ||
|
||
|
||
|
||
|
||
|
||
## Cross-plateforme implementation | ||
|
||
|
||
## fonctionnalités du Bot : | ||
|
||
### Traitement des inputs "utilisateurs" | ||
|
||
- Bert ? | ||
|
||
### Possible réponses | ||
|
||
- Accueillire | ||
- Décrire les fonctionnalités du bot | ||
- Répondre | ||
- Donner les heures d'ouvertures | ||
- Afficher une liste d'objet, de produit | ||
|
||
### Nice to have | ||
|
||
- Réserver un service / un produit | ||
- Gérer un agenda | ||
- vérifier la disponibilité | ||
- | ||
- | ||
|
||
"**In English**, the bot should be able to :\n", | ||
"\n", | ||
"- Understand phrases related to a room reservation.\n", | ||
"Example that the bot will have to understand: \n", | ||
"\n", | ||
"\t\t> I wish to reserve a room for 2 people.\n", | ||
"\t\t> I wish to reserve a room for 4 days\n", | ||
"\t\t> Do you have rooms available from July 23rd?\n", | ||
"\t\t> I would like to reserve a room for two days and for two people\n", | ||
"\n", | ||
"- Understand phrases related to a table reservation for the restaurant. \n", | ||
"\n", | ||
"\t\t> I would like to make a reservation for tonight.\n", | ||
"\t\t> I'd like to reserve a table for four people.\n", | ||
"\n", | ||
"- Must ensure a continuous and ongoing conversation. Example of a complete conversation : \n", | ||
"\n", | ||
"\t\t> Customer : Hello !\n", | ||
"\t\t> Bot : Hello, how can I help you? \n", | ||
"\t\t> Customer: I would like to reserve a table for 4 people ? \n", | ||
"\t\t> Bot : For which date would you like to reserve your table?\n", | ||
"\t\t> Customer : Today at 7:00 pm\n", | ||
"\t\t> Bot : What name should I make the reservation under?\n", | ||
"\t\t> Customer : My name is Mr. Dupont! \n", | ||
"\t\t> Bot : Very well Mr Dupont, I confirm you the reservation of a table for 4 people tonight at 7:00 pm. \n", | ||
"\t\t> Bot : Can I help you with something else?\n", | ||
"\t\t> Customer : No thanks\n", | ||
"\t\t> Bot: Have a nice day. \n", | ||
"\n", | ||
"- Understand when the client is angry. In this case, the bot will indicate that it is transmitting the conversation to a human. \n", | ||
"\n", | ||
"\t\t> You're incompetent!\n", | ||
"\t\t> My room is dirty! This is outrageous!\n", | ||
"\t\t> I want to talk to a human. \n", | ||
"\n", | ||
"### Nice-to-have features\n", | ||
"- Create an API of your bot to make it cross-platform \n", | ||
"- Use Docker\n", | ||
|
||
|
||
|
||
|
||
## Hébergement du Bot | ||
|
||
Timeline: | ||
- Etablir l'objectif (déployer bot cross-plateforme + créer propre modele) | ||
- Trouver un framework >> MSBotFramework | ||
- Créer un dataset | ||
- Deployer dummy bot |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
from os import environ | ||
|
||
|
||
class Config: | ||
"""Bot configuration class.""" | ||
|
||
# Deployment | ||
PORT = int(environ.get("PORT", 3978)) | ||
|
||
# Azure deployment | ||
APP_ID = environ.get("MS_APP_ID", "") | ||
APP_PASSWORD = environ.get("MS_APP_PASSWORD", "") | ||
|
||
# Models | ||
MODEL_PREPROCESS = "en_core_web_sm" # SpaCy smallest model - For preprocess | ||
MODEL_MATCHING = "TF-IDF" # PolyFuzz lightest model - Optimized for matching | ||
MODEL_CLASSIFIER = "bert-base-uncased" # HuggingFace smallest BERT model - For tokenization and classifying | ||
|
||
# Remote files | ||
s3_base_url = environ.get("S3_BASE_URL", "") | ||
|
||
weight_file = "resa_BERT_model.pt" | ||
MODEL_WEIGHT_URL = f"{s3_base_url}/{weight_file}" # Fine-tuned weights for BERT model | ||
MODEL_WEIGHT_LOCAL_COPY = f"./assets/model/{weight_file}" | ||
|
||
classes_file = "labels.pickle" | ||
MODEL_CLASSES_URL = f"{s3_base_url}/{classes_file}" | ||
MODEL_CLASSES_LOCAL_COPY = f"./assets/model/{classes_file}" | ||
|
||
# Filters | ||
FILTERS_TOML = "./filters.toml" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# TOML document to store filters | ||
|
||
[longtalk_make_reservation] | ||
|
||
# Size of the room: How many people ? | ||
[longtalk_make_reservation.people] | ||
words = ["pearson", "people"] | ||
regex = '''(?P<people>\d)\W%s''' | ||
threshold = 0.85 | ||
|
||
# Duration of the book: How long ? | ||
[longtalk_make_reservation.duration] | ||
words = ["day", "night"] | ||
regex = '''(?P<duration>\d)\W%s''' | ||
threshold = 0.85 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
|
||
import sys | ||
import traceback | ||
from datetime import datetime | ||
from http import HTTPStatus | ||
|
||
from aiohttp import web | ||
from aiohttp.web import Request, Response, json_response | ||
from botbuilder.core import BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState | ||
from botbuilder.core.integration import aiohttp_error_middleware | ||
from botbuilder.schema import Activity, ActivityTypes | ||
|
||
from src.dialogs import MainDialog, BookingRoomDialog | ||
from src.nlu import NLU | ||
from src import Bot | ||
from config import Config | ||
|
||
# Load the config and create the bot | ||
config = Config() | ||
|
||
# Init a Bot adapter https://aka.ms/about-bot-adapter | ||
settings = BotFrameworkAdapterSettings(config.APP_ID, config.APP_PASSWORD) | ||
ADAPTER = BotFrameworkAdapter(settings) | ||
|
||
|
||
# Catch-all for errors | ||
async def on_error(context: TurnContext, error_: Exception): | ||
""" | ||
Catch-all functions to write out errors on console log. | ||
NOTE: In production environment, logging should be done | ||
to Azure application insights. | ||
""" | ||
|
||
# Print the error into the logs | ||
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.") | ||
|
||
# If the bot is run from the Bot Framework Emulator (dev environment), | ||
# print a more complete error log. | ||
if context.activity.channel_id == "emulator": | ||
|
||
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", | ||
) | ||
await context.send_activity(trace_activity) | ||
|
||
# Clear out state | ||
await CONVERSATION_STATE.delete(context) | ||
|
||
|
||
# Set the error handler on the Adapter. | ||
ADAPTER.on_turn_error = on_error | ||
|
||
# Create MemoryStorage, UserState and ConversationState | ||
MEMORY = MemoryStorage() | ||
CONVERSATION_STATE = ConversationState(MEMORY) | ||
USER_STATE = UserState(MEMORY) | ||
|
||
# Load the NLU recognizer | ||
nlu = NLU() | ||
|
||
# Create the dialogs | ||
dialog_room_reservation = BookingRoomDialog(nlu, USER_STATE) | ||
dialog_main = MainDialog(nlu, USER_STATE, dialog_room_reservation) | ||
|
||
# Create the bot | ||
bot = Bot(CONVERSATION_STATE, USER_STATE, dialog_main) | ||
|
||
|
||
# Direct message API | ||
async def messages(req: Request) -> Response: | ||
""" | ||
Main bot function: Listen for incoming API request. | ||
Route: '/api/messages'. | ||
""" | ||
|
||
# Filter only JSON requests | ||
if "application/json" in req.headers["Content-Type"]: | ||
body = await req.json() | ||
else: | ||
return Response(status=HTTPStatus.UNSUPPORTED_MEDIA_TYPE) | ||
|
||
# Deserialize the JSON | ||
activity = Activity().deserialize(body) | ||
|
||
# Retrieve the authorization code if sent | ||
auth_header = "" | ||
if "Authorization" in req.headers: | ||
auth_header = req.headers["Authorization"] | ||
|
||
# Call the bot and send back its response | ||
response = await ADAPTER.process_activity(activity, auth_header, bot.on_turn) | ||
if response: | ||
return json_response(data=response.body, status=response.status) | ||
|
||
# Return HTTP-200 if no response is send back | ||
return Response(status=HTTPStatus.OK) | ||
|
||
# Init and open routes for direct API call | ||
app = web.Application(middlewares=[aiohttp_error_middleware]) | ||
app.router.add_post("/api/messages", messages) | ||
|
||
|
||
if __name__ == "__main__": | ||
|
||
web.run_app(app, host="0.0.0.0", port=config.PORT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
|
||
# MS Bot Framework | ||
botbuilder-core==4.11.0 | ||
botbuilder-integration-aiohttp==4.11.0 | ||
botbuilder-schema==4.11.0 | ||
botframework-connector==4.11.0 | ||
botbuilder-dialogs==4.11.0 | ||
aiohttp==3.6.2 | ||
|
||
# Preprocessing | ||
beautifulsoup4==4.9.3 | ||
spacy==3.0.1 | ||
Unidecode==1.1.2 | ||
word2number==1.1 | ||
contractions==0.0.45 | ||
|
||
# Classification | ||
transformers==4.2.2 | ||
torch==1.7.1 | ||
requests==2.23.0 | ||
|
||
# Matching | ||
polyfuzz==0.2.2 | ||
toml==0.10.2 | ||
pandas==1.2.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
from .bot import Bot | ||
|
||
__all__ = ["Bot"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
from botbuilder.schema import ChannelAccount | ||
from botbuilder.core import ActivityHandler, TurnContext, ConversationState, UserState | ||
from botbuilder.dialogs import Dialog | ||
|
||
from .dialogs.utils import Emoji | ||
from .dialogs.helpers import DialogHelper | ||
|
||
|
||
class Bot(ActivityHandler): | ||
|
||
def __init__(self, conversation_state: ConversationState, user_state: UserState, dialog: Dialog): | ||
|
||
self.conversation_state = conversation_state | ||
self.user_state = user_state | ||
self.dialog = dialog | ||
|
||
async def on_members_added_activity(self, members_added: [ChannelAccount], turn_context: TurnContext): | ||
|
||
# Send an "Hello" to any new user connected to the bot | ||
for member in members_added: | ||
if member.id != turn_context.activity.recipient.id: | ||
await turn_context.send_activity(f"Hello {Emoji.WAVING_HAND.value}") | ||
|
||
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) | ||
await self.user_state.save_changes(turn_context) | ||
|
||
async def on_message_activity(self, turn_context: TurnContext): | ||
|
||
await DialogHelper.run_dialog( | ||
self.dialog, | ||
turn_context, | ||
self.conversation_state.create_property("DialogState"), | ||
) |
Oops, something went wrong.