diff --git a/.github/workflows/continous-integration.yml b/.github/workflows/continous-integration.yml index 8a8758a25e2c..0a046ede2f4f 100644 --- a/.github/workflows/continous-integration.yml +++ b/.github/workflows/continous-integration.yml @@ -136,6 +136,11 @@ jobs: with: poetry-version: ${{ env.POETRY_VERSION }} + - name: Inject setuptools into poetry's runtime environment + if: needs.changes.outputs.backend == 'true' + run: | + poetry self add setuptools + - name: Load Poetry Cached Libraries ⬇ id: cache-poetry if: needs.changes.outputs.backend == 'true' @@ -163,7 +168,7 @@ jobs: # This is a workaround for that issue run: | sudo apt-get -y install libpq-dev - make install-full || make install-full || make install-full + make install-full - name: Checkout target branch to be able to diff if: needs.changes.outputs.backend == 'true' && github.event_name == 'pull_request' @@ -277,6 +282,11 @@ jobs: with: poetry-version: ${{ env.POETRY_VERSION }} + - name: Inject setuptools into poetry's runtime environment + if: needs.changes.outputs.backend == 'true' + run: | + poetry self add setuptools + - name: Load Poetry Cached Libraries ⬇ id: cache-poetry if: needs.changes.outputs.backend == 'true' @@ -311,7 +321,7 @@ jobs: # This is a workaround for that issue run: | sudo apt-get -y install libpq-dev - make install-full | tee .output || make install-full | tee .output || make install-full | tee .output + make install-full | tee .output if grep 'The lock file is not up to date' .output; then exit 1; fi make prepare-tests-ubuntu @@ -330,7 +340,7 @@ jobs: Remove-Item -Force -Recurse $spacy_data_dir New-Item -Path $spacy_data_dir -Type Directory } - make install-full || make install-full || make install-full + make install-full make prepare-tests-windows-gha - name: Add github workflow problem matchers @@ -427,6 +437,11 @@ jobs: with: poetry-version: ${{ env.POETRY_VERSION }} + - name: Inject setuptools into poetry's runtime environment + if: needs.changes.outputs.backend == 'true' + run: | + poetry self add setuptools + - name: Load Poetry Cached Libraries ⬇ id: cache-poetry if: needs.changes.outputs.backend == 'true' diff --git a/changelog/12927.bugfix.md b/changelog/12927.bugfix.md new file mode 100644 index 000000000000..7b9ff9d69410 --- /dev/null +++ b/changelog/12927.bugfix.md @@ -0,0 +1 @@ +Fix wrong conflicts that occur when rasa validate stories is run with slots that have active_loop set to null in mapping conditions. \ No newline at end of file diff --git a/data/test/test_integration/data/nlu.yml b/data/test/test_integration/data/nlu.yml index 877f8f7c6975..ecb72d611556 100644 --- a/data/test/test_integration/data/nlu.yml +++ b/data/test/test_integration/data/nlu.yml @@ -89,3 +89,10 @@ nlu: - are you a human? - am I talking to a bot? - am I talking to a human? + + - intent: block + examples: | + - block my [checking](account_type) account + - i want to block my [savings](account_type) account + - i need to block an account + - i need to block my [credit](account_type) card diff --git a/data/test/test_integration/data/stories.yml b/data/test/test_integration/data/stories.yml index 8d67b0112b46..227609c1868e 100644 --- a/data/test/test_integration/data/stories.yml +++ b/data/test/test_integration/data/stories.yml @@ -28,3 +28,29 @@ stories: - action: utter_did_that_help - intent: deny - action: utter_goodbye + + - story: block savings + steps: + - intent: block + entities: + - account_type: savings + - action: utter_block_account + + - story: block checking + steps: + - intent: block + entities: + - account_type: checking + - action: utter_checking + + - story: block credit + steps: + - intent: block + entities: + - account_type: credit + - action: utter_credit + + - story: block no entities + steps: + - intent: block + - action: utter_nothing diff --git a/data/test/test_integration/domain.yml b/data/test/test_integration/domain.yml index d72dc536ad91..2118bb66fc1d 100644 --- a/data/test/test_integration/domain.yml +++ b/data/test/test_integration/domain.yml @@ -8,6 +8,7 @@ intents: - mood_great - mood_unhappy - bot_challenge + - block responses: utter_greet: @@ -29,6 +30,35 @@ responses: utter_iamabot: - text: "I am a bot, powered by Rasa." + utter_block_account: + - text: "your account has been blocked" + + utter_checking: + - text: "checking account" + + utter_credit: + - text: "credit account" + + utter_nothing: + - text: "no account type was specified" + +entities: + - account_type + +slots: + account_type: + type: categorical + influence_conversation: true + values: + - savings + - checking + - credit + mappings: + - type: from_entity + entity: account_type + conditions: + - active_loop: null + session_config: session_expiration_time: 60 carry_over_slots_to_new_session: true diff --git a/rasa/shared/core/domain.py b/rasa/shared/core/domain.py index e56540799091..8ec59cd6f111 100644 --- a/rasa/shared/core/domain.py +++ b/rasa/shared/core/domain.py @@ -43,6 +43,7 @@ SlotMappingType, MAPPING_TYPE, MAPPING_CONDITIONS, + ACTIVE_LOOP, ) from rasa.shared.exceptions import ( RasaException, @@ -1408,9 +1409,11 @@ def slots_for_entities(self, entities: List[Dict[Text, Any]]) -> List[SlotSet]: matching_entities = [] for mapping in slot.mappings: - if mapping[MAPPING_TYPE] != str( - SlotMappingType.FROM_ENTITY - ) or mapping.get(MAPPING_CONDITIONS): + mapping_conditions = mapping.get(MAPPING_CONDITIONS) + if mapping[MAPPING_TYPE] != str(SlotMappingType.FROM_ENTITY) or ( + mapping_conditions + and mapping_conditions[0].get(ACTIVE_LOOP) is not None + ): continue for entity in entities: diff --git a/tests/integration_tests/core/test_cli_response.py b/tests/integration_tests/core/test_cli_response.py index ffa78d9b6d10..35a0a4f4cfcb 100644 --- a/tests/integration_tests/core/test_cli_response.py +++ b/tests/integration_tests/core/test_cli_response.py @@ -148,3 +148,36 @@ def test_rasa_validate_quiet_no_errors( "you can use `rasa telemetry disable`." in output_text assert "To learn more, check out" "https://rasa.com/docs/rasa/telemetry/telemetry." in output_text + + +def test_rasa_validate_null_active_loop_no_errors( + run: Callable[..., RunResult], request: FixtureRequest +): + # Test captures the subprocess output for the command run + # and validates that the data in 'data/test/test_integration' throws no cli errors + + test_data_dir = Path(request.config.rootdir, "data", "test", "test_integration") + test_config_dir = Path(request.config.rootdir, "data", "test_config") + source_file = (test_data_dir / "data").absolute() + domain_file = (test_data_dir / "domain.yml").absolute() + config_file = (test_config_dir / "config_unique_assistant_id.yml").absolute() + result = run( + "data", + "validate", + "--data", + str(source_file), + "-d", + str(domain_file), + "-c", + str(config_file), + ) + assert result.ret == 0 + + stderr_text = str(result.stderr) + assert "INFO" in stderr_text + assert "Validating intents..." in stderr_text + assert "Validating utterances..." in stderr_text + assert "Story structure validation..." in stderr_text + assert "Validating utterances..." in stderr_text + assert "Considering all preceding turns for conflict analysis." in stderr_text + assert "No story structure conflicts found." in stderr_text diff --git a/tests/shared/core/test_domain.py b/tests/shared/core/test_domain.py index 0c5719ab8728..b8d20d774a98 100644 --- a/tests/shared/core/test_domain.py +++ b/tests/shared/core/test_domain.py @@ -1977,6 +1977,33 @@ def test_domain_slots_for_entities_with_mapping_conditions_no_slot_set(): assert len(events) == 0 +def test_domain_slots_for_entities_with_mapping_conditions_no_active_loop(): + domain = Domain.from_yaml( + textwrap.dedent( + f""" + version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}" + entities: + - city + slots: + location: + type: text + influence_conversation: false + mappings: + - type: from_entity + entity: city + conditions: + - active_loop: null + forms: + booking_form: + required_slots: + - location + """ + ) + ) + events = domain.slots_for_entities([{"entity": "city", "value": "Berlin"}]) + assert events == [SlotSet("location", "Berlin")] + + def test_domain_slots_for_entities_sets_valid_slot(): domain = Domain.from_yaml( textwrap.dedent(