Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Line Bot with Rasa Open Source

Line Bot with Rasa Open Source

介紹在沒有使用大廠雲端 NLP 服務如 Google Dialogflow、Azure LUIS 的情況下,如何利用 open source framework RASA 來開發對話式服務。

Cheng-Lung Sung

July 22, 2020
Tweet

More Decks by Cheng-Lung Sung

Other Decks in How-to & DIY

Transcript

  1. Outline • Conversational (AI) Service • Natural Language Understanding (NLU)

    • Rasa Introduction • Rasa Open Source • Rasa X • Chat bot example: line/line-bot-sdk-python • Weather • Some thoughts on chatbot development…
  2. About.Me/clsung • AIRD Department, DRD Division, CTBC Bank • Computational

    Linguistics • Computer Vision • Data Governance • Director of Product Development, HTC Health Care • Open Source contributor google://中國信託 AI
  3. 我們希望使⽤者照著說明書⾛ examples/flask-kitchensink @handler.add(MessageEvent, message=TextMessage) def handle_text_message(event): text = event.message.text if

    text == 'profile': if isinstance(event.source, SourceUser): profile = line_bot_api.get_profile(event.source.user_id) line_bot_api.reply_message( event.reply_token, [ TextSendMessage(text='Display name: ' + profile.display_name), TextSendMessage(text='Status message: ' + str(profile.status_message)) ] )
  4. NLU NLU in Conversational Service • Intent Classification • Entity

    Extraction 請問明天台北的天氣? intent: - ask_weather entities: - location: 台北 - time: 明天
  5. $ rasa init Welcome to Rasa! 烙 To get started

    quickly, an initial project will be created. If you need some help, check out the documentation at https://rasa.com/docs/rasa. Now let's start! ? Please enter a path where the project will be created [default: current directory] . Created project directory at '/git/nlpbot'. Finished creating project structure. ? Do you want to train an initial model? Yes Training an initial model... Training Core model... Processed Story Blocks: 100%|███████████████████████████████████████████████████████| 5/5 [00:00<00:00, 3953.16it/s, # trackers=1] Processed Story Blocks: 100%|███████████████████████████████████████████████████████| 5/5 [00:00<00:00, 1734.47it/s, # trackers=5] Processed Story Blocks: 100%|███████████████████████████████████████████████████████| 5/5 [00:00<00:00, 442.75it/s, # trackers=20] Processed Story Blocks: 100%|███████████████████████████████████████████████████████| 5/5 [00:00<00:00, 313.09it/s, # trackers=24] Processed trackers: 100%|███████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 1920.82it/s, # actions=16] Processed actions: 16it [00:00, 12336.19it/s, # examples=16] Processed trackers: 100%|███████████████████████████████████████████████████████| 231/231 [00:00<00:00, 733.18it/s, # actions=126] Epochs: 100%|██████████████████████████████████████████████| 100/100 [00:06<00:00, 14.29it/s, t_loss=0.074, loss=0.001, acc=1.000] 2020-07-21 13:18:06 INFO rasa.utils.tensorflow.models - Finished training. 2020-07-21 13:18:06 INFO rasa.core.agent - Persisted model to '/var/folders/tq/T/tmphttlwy6_/core' Core model training completed. Training NLU model... 2020-07-21 13:18:06 INFO rasa.nlu.training_data.training_data - Training data stats: 2020-07-21 13:18:06 INFO rasa.nlu.training_data.training_data - Number of intent examples: 43 (7 distinct intents) 2020-07-21 13:18:06 INFO rasa.nlu.training_data.training_data - Found intents: 'goodbye', 'affirm', 'deny', 'mood_unhappy', 'mood_great', 'bot_challenge', 'greet' 2020-07-21 13:18:06 INFO rasa.nlu.training_data.training_data - Number of response examples: 0 (0 distinct responses) 2020-07-21 13:18:06 INFO rasa.nlu.training_data.training_data - Number of entity examples: 0 (0 distinct entities) 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component WhitespaceTokenizer 2020-07-21 13:18:06 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component RegexFeaturizer 2020-07-21 13:18:06 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component LexicalSyntacticFeaturizer 2020-07-21 13:18:06 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component CountVectorsFeaturizer 2020-07-21 13:18:06 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component CountVectorsFeaturizer 2020-07-21 13:18:06 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:06 INFO rasa.nlu.model - Starting to train component DIETClassifier Epochs: 100%|██████████████████████████████████████████| 100/100 [00:07<00:00, 14.26it/s, t_loss=1.466, i_loss=0.083, i_acc=1.000] 2020-07-21 13:18:18 INFO rasa.utils.tensorflow.models - Finished training. 2020-07-21 13:18:18 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:18 INFO rasa.nlu.model - Starting to train component EntitySynonymMapper 2020-07-21 13:18:18 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:18 INFO rasa.nlu.model - Starting to train component ResponseSelector 2020-07-21 13:18:18 INFO rasa.nlu.selectors.response_selector - Retrieval intent parameter was left to its default value. This response selector will be trained on training examples combining all retrieval intents. 2020-07-21 13:18:18 INFO rasa.nlu.model - Finished training component. 2020-07-21 13:18:18 INFO rasa.nlu.model - Successfully saved model into '/var/folders/tq/T/tmphttlwy6_/nlu' NLU model training completed. Your Rasa model is trained and saved at '/git/nlpbot/models/20200721-131751.tar.gz'.
  6. data/nlu.md ## intent:greet - hey - hello - hi -

    good morning - good evening - hey there ## intent:goodbye - bye - goodbye - see you around - see you later ## intent:affirm - yes - indeed - of course - that sounds good - correct
  7. domain.yml intents: - greet - goodbye - affirm - deny

    - mood_great - mood_unhappy - bot_challenge responses: utter_greet: - text: "Hey! How are you?" utter_cheer_up: - text: "Here is something to cheer y image: "https://i.imgur.com/nGF1K8f utter_did_that_help: - text: "Did that help you?" utter_happy: - text: "Great, carry on!"
  8. data/stories.md ## happy path * greet - utter_greet * mood_great

    - utter_happy ## sad path 1 * greet - utter_greet * mood_unhappy - utter_cheer_up - utter_did_that_help * affirm - utter_happy ## say goodbye * goodbye - utter_goodbye
  9. credentials.yml rest: # # you don't need to provide anything

    here - this channel doesn't # # require any credentials #facebook: # verify: "<verify>" # secret: "<your secret>" # page-access-token: "<your page access token>" #slack: # slack_token: "<your slack token>" # slack_channel: "<the slack channel>" #socketio: # user_message_evt: <event name for user message> # bot_message_evt: <event name for but messages> # session_persistence: <true/false> # This entry is needed if you are using Rasa X. The entry represents credentials # for the Rasa X "channel", i.e. Talk to your bot and Share with guest testers. rasa: url: "http://localhost:5002/api"
  10. config.yml # Configuration for Rasa NLU. # https://rasa.com/docs/rasa/nlu/components/ language: en

    pipeline: - name: WhitespaceTokenizer - name: RegexFeaturizer - name: LexicalSyntacticFeaturizer - name: CountVectorsFeaturizer - name: CountVectorsFeaturizer analyzer: "char_wb" min_ngram: 1 max_ngram: 4 - name: DIETClassifier epochs: 100 - name: EntitySynonymMapper - name: ResponseSelector epochs: 100 # Configuration for Rasa Core. # https://rasa.com/docs/rasa/core/policies/ policies: - name: MemoizationPolicy - name: TEDPolicy max_history: 5 epochs: 100 - name: MappingPolicy Core
  11. language: zh pipeline: - name: JiebaTokenizer dictionary_path: "data/jieba" ## intent:ask_weather

    - 請問[今天](time)[台北](location)的天氣 - 請問[後天](time)[南投](location)的天氣 - 你知道[明天](time)[宜蘭](location)天氣情況嗎 - 我想問[台南](location)[後天](time)的天氣
  12. Rasa Action 2020-XX-YY 20:22:09 ERROR rasa.core.actions.action - The model predicted

    the custom action 'action_location_weather', but you didn't configure an endpoint to run this custom action. Please take a look at the docs and set an endpoint configuration via the --endpoints flag. https://rasa.com/docs/rasa/core/actions 2020-XX-YY 20:22:09 ERROR rasa.core.processor - Encountered an exception while running action 'action_location_weather'. Bot will continue, but the actions events are lost. Please check the logs of your action server for more information. w/o Action Server $ rasa run actions
  13. Customized actions (actions.py) class ActionLocationWeather(Action): def name(self) -> Text: return

    "action_location_weather" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: loc = tracker.get_slot('location') when = tracker.get_slot('time') response = """你要問的是 {} {} 的天氣~""".format(when, loc) dispatcher.utter_message(text=response) return []
  14. ⼆種使⽤ Rasa 的⽅法 • Webhook API (channel, rest…) • Agent

    from rasa.core.agent import Agent import requests
  15. With Agent import asyncio from rasa.core.agent import Agent from rasa.core.interpreter

    import RasaNLUInterpreter from rasa.core.utils import EndpointConfig nlu_interpreter = RasaNLUInterpreter('models/nlu-20200721-200450.tar.gz') action_endpoint = EndpointConfig(url="http://localhost:5055/webhook") agent = Agent.load( './models/20200721-220524.tar.gz', interpreter=nlu_interpreter, action_endpoint=action_endpoint) @handler.add(MessageEvent, message=TextMessage) def message_text(event): sender = event.source.user_id responses = asyncio.run(agent.handle_message( event.message.text, sender_id=sender)) nlu = asyncio.run(agent.parse_message_using_nlu_interpreter(event.message.text)) line_bot_api.reply_message( event.reply_token, [TextSendMessage(text=responses[0]['text']), TextSendMessage(text=str(nlu))], )
  16. With API import requests class RasaClient(object): def __init__(self, url): self._base_url

    = url self._sess = requests.Session() def _post_rasa(self, path, data): url = "{}/{}".format(self._base_url, path) resp = self._sess.post(url, json=data) resp.raise_for_status() # catch this! return resp.json() def post_nlu(self, message): data = {"text": message} return self._post_rasa("model/parse", data) def post_action(self, message, sender="default"): data = {"message": message, "sender": sender} return self._post_rasa("webhooks/rest/webhook", data) @handler.add(MessageEvent, message=TextMessage) def message_text(event): rasa = RasaClient('http://localhost:5005') sender = event.source.user_id responses = rasa.post_action(event.message.text) nlu = rasa.post_nlu(event.message.text) line_bot_api.reply_message( event.reply_token, [TextSendMessage(text=responses[0]['text']), TextSendMessage(text=str(nlu))], )