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

Line Bot with Rasa Open Source

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Line Bot with Rasa Open Source

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

Avatar for Cheng-Lung Sung

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))], )