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.", ) 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: warnings.warn( f"Append event called, but could not extract a valid event. " f"Request JSON: {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) try: async with app.agent.lock_store.lock(conversation_id): tracker = await get_tracker( app.agent.create_processor(), conversation_id ) 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", f"An unexpected error occurred. Error: {e}" )
def test_file_broker_logs_to_file(tmpdir): log_file_path = tmpdir.join("events.log").strpath actual = EventBroker.create( EndpointConfig(**{ "type": "file", "path": log_file_path })) for e in TEST_EVENTS: actual.publish(e.as_dict()) # reading the events from the file one event per line recovered = [] with open(log_file_path, "r") as log_file: for line in log_file: recovered.append(Event.from_parameters(json.loads(line))) assert recovered == TEST_EVENTS
def test_file_broker_logs_to_file(tmpdir): fname = tmpdir.join("events.log").strpath actual = broker.from_endpoint_config( 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): # 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 test_pushing_event(rasa_app, event): cid = str(uuid.uuid1()) conversation = "/conversations/{}".format(cid) _, response = rasa_app.post( "{}/tracker/events".format(conversation), json=event.as_dict(), headers={"Content-Type": "application/json"}, ) assert response.json is not None assert response.status == 200 _, tracker_response = rasa_app.get("/conversations/{}/tracker".format(cid)) tracker = tracker_response.json assert tracker is not None assert len(tracker.get("events")) == 2 evt = tracker.get("events")[1] assert Event.from_parameters(evt) == event
def test_json_parse_reminder_cancelled(): evt = { "event": "cancel_reminder", "name": "my_reminder", "intent": "my_intent", "entities": [ {"entity": "entity1", "value": "value1"}, {"entity": "entity2", "value": "value2"}, ], "date_time": "2018-09-03T11:41:10.128172", } assert Event.from_parameters(evt) == ReminderCancelled( name="my_reminder", intent="my_intent", entities=[ {"entity": "entity1", "value": "value1"}, {"entity": "entity2", "value": "value2"}, ], timestamp=parser.parse("2018-09-03T11:41:10.128172"), )
def test_file_broker_properly_logs_newlines(tmp_path): log_file_path = str(tmp_path / "events.log") actual = EventBroker.create( EndpointConfig(**{ "type": "file", "path": log_file_path })) 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(log_file_path, "r") as log_file: for line in log_file: recovered.append(Event.from_parameters(json.loads(line))) assert recovered == [event_with_newline]
def test_file_broker_properly_logs_newlines(tmpdir): fname = tmpdir.join("events.log").strpath actual = broker.from_endpoint_config( 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]
async def append_event(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.", ) evt = Event.from_parameters(request.json) verbosity = event_verbosity_parameter(request, EventVerbosity.AFTER_RESTART) tracker = obtain_tracker_store(app.agent, conversation_id) if evt: try: tracker.update(evt) 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), ) 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" }, )
def _get_events_from_request_body(request: Request) -> List[Event]: 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: common_utils.raise_warning( f"Append event called, but could not extract a valid event. " f"Request JSON: {request.json}" ) raise ErrorResponse( 400, "BadRequest", "Couldn't extract a proper event from the request body.", {"parameter": "", "in": "body"}, ) return events
def test_json_parse_reminder(): # fmt: off # DOCS MARKER ReminderScheduled 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, } # DOCS END # fmt: on assert Event.from_parameters(evt) == ReminderScheduled( "my_intent", parser.parse("2018-09-03T11:41:10.128172"), name="my_reminder", kill_on_user_message=True, )
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_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={}, )
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
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_dict_serialisation(one_event): evt_dict = one_event.as_dict() recovered_event = Event.from_parameters(evt_dict) assert hash(one_event) == hash(recovered_event)
def test_bot_output_format(): message = { "event": "bot", "text": "Hello!", "data": { "image": "http://example.com/myimage.png", "attachment": "My Attachment", "buttons": [ { "title": "yes", "payload": "/yes" }, { "title": "no", "payload": "/no", "extra": "extra" }, ], "elements": [ { "title": "element1", "buttons": [{ "title": "button1", "payload": "/button1" }], }, { "title": "element2", "buttons": [{ "title": "button2", "payload": "/button2" }], }, ], "quick_replies": [ { "title": "quick_reply1", "buttons": [{ "title": "button3", "payload": "/button3" }], }, { "title": "quick_reply2", "buttons": [{ "title": "button4", "payload": "/button4" }], }, ], }, } from rasa.core.events import Event bot_event = Event.from_parameters(message) assert isinstance(bot_event, BotUttered) formatted = interactive.format_bot_output(bot_event) assert formatted == ("Hello!\n" "Image: http://example.com/myimage.png\n" "Attachment: My Attachment\n" "Buttons:\n" "1: yes (/yes)\n" '2: no (/no) - {"extra": "extra"}\n' "Type out your own message...\n" "Elements:\n" '1: element1 - {"buttons": ' '[{"payload": "/button1", "title": "button1"}]' '}\n2: element2 - {"buttons": ' '[{"payload": "/button2", "title": "button2"}]' "}\nQuick replies:\n" '1: quick_reply1 - {"buttons": ' '[{"payload": "/button3", "title": "button3"}' ']}\n2: quick_reply2 - {"buttons": ' '[{"payload": "/button4", "title": "button4"}' "]}")
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")
def test_json_parse_restarted(): # DOCS MARKER Restarted evt = {"event": "restart"} # DOCS END assert Event.from_parameters(evt) == Restarted()
def test_json_parse_session_started(): # DOCS MARKER SessionStarted evt = {"event": "session_started"} # DOCS END assert Event.from_parameters(evt) == SessionStarted()
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_action(): # DOCS MARKER ActionExecuted evt = {"event": "action", "name": "my_action"} # DOCS END assert Event.from_parameters(evt) == ActionExecuted("my_action")
def test_json_parse_resume(): # DOCS MARKER ConversationResumed evt = {"event": "resume"} # DOCS END assert Event.from_parameters(evt) == ConversationResumed()
def test_json_parse_reset(): # DOCS MARKER AllSlotsReset evt = {"event": "reset_slots"} # DOCS END assert Event.from_parameters(evt) == AllSlotsReset()
from rasa.core.events import Event, UserUttered, SlotSet, BotUttered from rasa.core.trackers import DialogueStateTracker from rasa.model import unpack_model from rasa.utils.endpoints import EndpointConfig from sanic import Sanic from sanic.testing import SanicTestClient from tests.nlu.utilities import ResponseTest # a couple of event instances that we can use for testing test_events = [ Event.from_parameters({ "event": UserUttered.type_name, "text": "/goodbye", "parse_data": { "intent": { "confidence": 1.0, "name": "greet" }, "entities": [], }, }), BotUttered("Welcome!", {"test": True}), SlotSet("cuisine", 34), SlotSet("cuisine", "34"), SlotSet("location", None), SlotSet("location", [34, "34", None]), ] @pytest.fixture def rasa_app_without_api(rasa_server_without_api: Sanic) -> SanicTestClient:
def test_json_parse_export(): # DOCS MARKER StoryExported evt = {"event": "export"} # DOCS END assert Event.from_parameters(evt) == StoryExported()
def test_json_parse_rewind(): # DOCS MARKER UserUtteranceReverted evt = {"event": "rewind"} # DOCS END assert Event.from_parameters(evt) == UserUtteranceReverted()
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 test_json_parse_undo(): # DOCS MARKER ActionReverted evt = {"event": "undo"} # DOCS END assert Event.from_parameters(evt) == ActionReverted()
def test_json_parse_pause(): # DOCS MARKER ConversationPaused evt = {"event": "pause"} # DOCS END assert Event.from_parameters(evt) == ConversationPaused()