def test_pushing_event(rasa_app: SanicTestClient, event: Event): sender_id = str(uuid.uuid1()) conversation = f"/conversations/{sender_id}" serialized_event = event.as_dict() # Remove timestamp so that a new one is assigned on the server serialized_event.pop("timestamp") time_before_adding_events = time.time() _, response = rasa_app.post( f"{conversation}/tracker/events", json=serialized_event, headers={"Content-Type": "application/json"}, ) assert response.json is not None assert response.status == 200 _, tracker_response = rasa_app.get(f"/conversations/{sender_id}/tracker") tracker = tracker_response.json assert tracker is not None assert len(tracker.get("events")) == 1 evt = tracker.get("events")[0] deserialised_event = Event.from_parameters(evt) assert deserialised_event == event assert deserialised_event.timestamp > time_before_adding_events
def update(self, event: Event) -> None: """Modify the state of the tracker according to an ``Event``. """ if not isinstance(event, Event): # pragma: no cover raise ValueError( "event to log must be an instance of a subclass of Event.") self.events.append(event) event.apply_to(self)
def update(self, event: Event, domain: Optional[Domain] = None) -> None: """Modify the state of the tracker according to an ``Event``. """ if not isinstance(event, Event): # pragma: no cover raise ValueError("event to log must be an instance of a subclass of Event.") self.events.append(event) event.apply_to(self) if domain and isinstance(event, UserUttered): # store all entities as slots for e in domain.slots_for_entities(event.parse_data["entities"]): self.update(e)
def update(self, event: Event, domain: Optional[Domain] = None) -> None: """Modify the state of the tracker according to an ``Event``. """ if not isinstance(event, Event): # pragma: no cover raise ValueError( "event to log must be an instance of a subclass of Event.") self.events.append(event) event.apply_to(self) if domain and isinstance(event, UserUttered): logger.debug("UserUttered event!") self.trigger_followup_action(ACTION_CHANGE_FRAME_NAME)
def test_json_parse_user(): # DOCS MARKER UserUttered evt = \ { 'event': 'user', 'text': 'Hey', 'parse_data': { 'intent': {'name': 'greet', 'confidence': 0.9}, 'entities': [] } } # DOCS END assert Event.from_parameters(evt) == UserUttered("Hey", intent={ "name": "greet", "confidence": 0.9 }, entities=[], parse_data={ "intent": { "name": "greet", "confidence": 0.9 }, "entities": [] })
def test_json_parse_user(): # fmt: off # DOCS MARKER UserUttered evt = { "event": "user", "text": "Hey", "parse_data": { "intent": { "name": "greet", "confidence": 0.9 }, "entities": [] }, "metadata": {}, } # DOCS END # fmt: on assert Event.from_parameters(evt) == UserUttered( "Hey", intent={ "name": "greet", "confidence": 0.9 }, entities=[], parse_data={ "intent": { "name": "greet", "confidence": 0.9 }, "entities": [] }, metadata={}, )
async def append_event(request: Request, sender_id: Text): """Append a list of events to the state of a conversation""" request_params = request.json evt = Event.from_parameters(request_params) tracker = app.agent.tracker_store.get_or_create_tracker(sender_id) verbosity = event_verbosity_parameter(request, EventVerbosity.AFTER_RESTART) if evt: tracker.update(evt) app.agent.tracker_store.save(tracker) return response.json(tracker.current_state(verbosity)) else: logger.warning( "Append event called, but could not extract a " "valid event. Request JSON: {}".format(request_params)) raise ErrorResponse( 400, "InvalidParameter", "Couldn't extract a proper event from the request body.", { "parameter": "", "in": "body" }, )
def test_pushing_event(app, event): cid = str(uuid.uuid1()) conversation = "/conversations/{}".format(cid) data = json.dumps({"query": "/greet"}) _, response = app.post("{}/respond".format(conversation), data=data, headers={"Content-Type": "application/json"}) assert response.json is not None assert response.status == 200 data = json.dumps(event.as_dict()) _, response = app.post("{}/tracker/events".format(conversation), data=data, headers={"Content-Type": "application/json"}) assert (response.json is not None) assert response.status == 200 _, tracker_response = app.get("/conversations/{}/tracker" "".format(cid)) tracker = tracker_response.json assert tracker is not None assert len(tracker.get("events")) == 6 evt = tracker.get("events")[5] assert Event.from_parameters(evt) == event
async def add_chitchat_to_story(self, story, domain: Domain, indexes: List, interpreter: "NaturalLanguageInterpreter" = RegexInterpreter()): # Delete Indexes, if they greater then the length of the story or lower 0 indexes = sorted(set(indexes)) indexes = [i for i in indexes if i >= 0 and i < len(story.events)] to_add = 0 for index in indexes: index += to_add # get last Utter last_utter = None if index - 1 >= 0: last_utter = story.events[index - 1] # Intent intent = 'asdfwe' parse_data = await interpreter.parse(intent) utterance = UserUttered( intent, parse_data.get("intent"), parse_data.get("entities"), parse_data ) intent_name = utterance.intent.get("name") if domain and intent_name not in domain.intents: raise_warning( f"Found unknown intent '{intent_name}'. " "Please, make sure that all intents are " "listed in your domain yaml.", UserWarning, ) # Utter # Copyied at dsl.py # def add_event(self, event_name, parameters): parameters = {} event_name = "utter_asdfwe" # add 'name' only if event is not a SlotSet, # because there might be a slot with slot_key='name' parameters["name"] = event_name parsed_events = Event.from_story_string( event_name, parameters, default=ActionExecuted ) if parsed_events is None: raise StoryParseError( "Unknown event '{}'. It is Neither an event " "nor an action).".format(event_name) ) # Add to Story story.events.insert(index, utterance) index += 1 to_add += 1 for parsed_event in parsed_events: story.events.insert(index, parsed_event) index += 1 to_add += 1 if last_utter and self.helper.get_param('consultation', False): story.events.insert(index, last_utter) return story
def test_json_parse_reset(): # DOCS MARKER AllSlotsReset evt = \ { 'event': 'reset_slots' } # DOCS END assert Event.from_parameters(evt) == AllSlotsReset()
def test_json_parse_rewind(): # DOCS MARKER UserUtteranceReverted evt = \ { 'event': 'rewind' } # DOCS END assert Event.from_parameters(evt) == UserUtteranceReverted()
def test_json_parse_restarted(): # DOCS MARKER Restarted evt = \ { 'event': 'restart' } # DOCS END assert Event.from_parameters(evt) == Restarted()
def test_json_parse_resume(): # DOCS MARKER ConversationResumed evt = \ { 'event': 'resume', } # DOCS END assert Event.from_parameters(evt) == ConversationResumed()
def test_json_parse_pause(): # DOCS MARKER ConversationPaused evt = \ { 'event': 'pause', } # DOCS END assert Event.from_parameters(evt) == ConversationPaused()
def test_json_parse_export(): # DOCS MARKER StoryExported evt = \ { 'event': 'export', } # DOCS END assert Event.from_parameters(evt) == StoryExported()
def test_json_parse_undo(): # DOCS MARKER ActionReverted evt = \ { 'event': 'undo', } # DOCS END assert Event.from_parameters(evt) == ActionReverted()
def test_json_parse_action(): # DOCS MARKER ActionExecuted evt = \ { 'event': 'action', 'name': 'my_action' } # DOCS END assert Event.from_parameters(evt) == ActionExecuted("my_action")
def test_json_parse_agent(): # DOCS MARKER AgentUttered evt = \ { 'event': 'agent', 'text': 'Hey, how are you?' } # DOCS END assert Event.from_parameters(evt) == AgentUttered("Hey, how are you?")
def test_json_parse_followup(): # DOCS MARKER FollowupAction evt = \ { 'event': 'followup', 'name': 'my_action' } # DOCS END assert Event.from_parameters(evt) == FollowupAction("my_action")
def test_json_parse_bot(): # DOCS MARKER BotUttered evt = \ { 'event': 'bot', 'text': 'Hey there!', 'data': {} } # DOCS END assert Event.from_parameters(evt) == BotUttered("Hey there!", {})
def _save_nlu_log(logs_service: LogsService, event_data: Dict, event_id: int) -> None: try: event = Event.from_parameters(event_data) if isinstance(event, UserUttered): log = logs_service.create_log_from_parse_data( event.parse_data, created_from_model=False, event_id=event_id) except Exception as e: logger.exception("Could not persist event '{}' to NLU logs:\n" "{}".format(event_data, e))
def test_json_parse_setslot(): # DOCS MARKER SetSlot evt = \ { 'event': 'slot', 'name': 'departure_airport', 'value': 'BER', } # DOCS END assert Event.from_parameters(evt) == SlotSet("departure_airport", "BER")
async def append_events(request: Request, conversation_id: Text): """Append a list of events to the state of a conversation""" validate_request_body( request, "You must provide events in the request body in order to append them" "to the state of a conversation.", ) request_id = request.args.get("request_id", UserMessage.DEFAULT_REQUEST_ID) user_id = request.args.get("user_id", UserMessage.DEFAULT_USER_ID) events = request.json if not isinstance(events, list): events = [events] events = [Event.from_parameters(event) for event in events] events = [event for event in events if event] if not events: logger.warning( "Append event called, but could not extract a valid event. " "Request JSON: {}".format(request.json)) raise ErrorResponse( 400, "BadRequest", "Couldn't extract a proper event from the request body.", { "parameter": "", "in": "body" }, ) verbosity = event_verbosity_parameter(request, EventVerbosity.AFTER_RESTART) tracker = obtain_tracker_store(app.agent, conversation_id, request_id, user_id) try: for event in events: tracker.update(event, app.agent.domain) app.agent.tracker_store.save(tracker) return response.json(tracker.current_state(verbosity)) except Exception as e: logger.debug(traceback.format_exc()) raise ErrorResponse( 500, "ConversationError", "An unexpected error occurred. Error: {}".format(e), )
def test_event_metadata_dict(event_class: Type[Event]): metadata = {"foo": "bar", "quux": 42} # Create the event from a `dict` that will be accepted by the # `_from_parameters` method of any `Event` subclass (the values themselves # are not important). event = Event.from_parameters({ "metadata": metadata, "event": event_class.type_name, "parse_data": {}, "date_time": "2019-11-20T16:09:16Z", }) assert event.as_dict()["metadata"] == metadata
def save_nlu_logs_from_event( self, event_data: Union[Text, bytes], event_id: Optional[int] = None) -> Optional[int]: try: event = Event.from_parameters(json.loads(event_data)) if isinstance(event, UserUttered): log = self.create_log_from_parse_data(event.parse_data, event_id=event_id) return log["id"] except ValueError as e: logger.exception( f"Could not persist event '{e}' to NLU logs:\n {e}")
def test_json_parse_reminder(): evt = { "event": "reminder", "intent": "my_intent", "entities": {"entity1": "value1", "entity2": "value2"}, "date_time": "2018-09-03T11:41:10.128172", "name": "my_reminder", "kill_on_user_msg": True, } assert Event.from_parameters(evt) == ReminderScheduled( "my_intent", parser.parse("2018-09-03T11:41:10.128172"), name="my_reminder", kill_on_user_message=True, )
def test_file_broker_logs_to_file(tmpdir): fname = tmpdir.join("events.log").strpath actual = EventBroker.create(EndpointConfig(**{"type": "file", "path": fname})) for e in TEST_EVENTS: actual.publish(e.as_dict()) # reading the events from the file one event per line recovered = [] with open(fname, "r") as f: for l in f: recovered.append(Event.from_parameters(json.loads(l))) assert recovered == TEST_EVENTS
def test_event_default_metadata(event_class: Type[Event]): # Create an event without metadata. When converting the `Event` to a # `dict`, it should not include a `metadata` property - unless it's a # `UserUttered` or a `BotUttered` event (or subclasses of them), in which # case the metadata should be included with a default value of {}. event = Event.from_parameters({ "event": event_class.type_name, "parse_data": {}, "date_time": "2019-11-20T16:09:16Z", }) if isinstance(event, BotUttered) or isinstance(event, UserUttered): assert event.as_dict()["metadata"] == {} else: assert "metadata" not in event.as_dict()
def from_parameters(cls, parameters: Dict[Text, Any]) -> "Dialogue": """Create `Dialogue` from parameters. Args: parameters: Serialised dialogue, should contain keys 'name' and 'events'. Returns: Deserialised `Dialogue`. """ return cls( parameters.get("name"), [Event.from_parameters(evt) for evt in parameters.get("events")], )
def test_file_broker_properly_logs_newlines(tmpdir): fname = tmpdir.join("events.log").strpath actual = EventBroker.create(EndpointConfig(**{"type": "file", "path": fname})) event_with_newline = UserUttered("hello \n there") actual.publish(event_with_newline.as_dict()) # reading the events from the file one event per line recovered = [] with open(fname, "r") as f: for l in f: recovered.append(Event.from_parameters(json.loads(l))) assert recovered == [event_with_newline]