Files
wehub-resource-sync dc6079821b
CI Github Actions / Run Tests (push) Waiting to run
Automatic PR Merger / mergepal (push) Waiting to run
Semgrep / Semgrep Workflow Security Scan (push) Waiting to run
Docs Tests / Check for file changes (push) Has been cancelled
Docs Tests / Test Documentation (push) Has been cancelled
Docs Tests / Documentation Linting Checks (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.9) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.9) (push) Has been cancelled
Continuous Integration / Check for file changes (push) Has been cancelled
Continuous Integration / Wait for docs tests (push) Has been cancelled
Continuous Integration / Code Quality (push) Has been cancelled
Continuous Integration / Check for changelog (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Upload coverage reports to codeclimate (push) Has been cancelled
Continuous Integration / Run Non-Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Run Broker Integration Tests (push) Has been cancelled
Continuous Integration / Run Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Build Docker base images and setup environment (push) Has been cancelled
Continuous Integration / Build Docker (default) (push) Has been cancelled
Continuous Integration / Build Docker (full) (push) Has been cancelled
Continuous Integration / Build Docker (mitie-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-de) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-it) (push) Has been cancelled
Continuous Integration / Deploy to PyPI (push) Has been cancelled
Continuous Integration / Notify Slack & Publish Release Notes (push) Has been cancelled
Publish Documentation / Evaluate release tag (push) Has been cancelled
Publish Documentation / Prebuild Docs (push) Has been cancelled
Publish Documentation / Preview Docs (push) Has been cancelled
Publish Documentation / Check for file changes (push) Has been cancelled
Publish Documentation / Publish Docs (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:24:47 +08:00

393 lines
12 KiB
Python

import json
import argparse
import logging
import os
import sys
import time
from types import FrameType
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Text, Union, overload
import randomname
import rasa.shared.utils.cli
import rasa.shared.utils.io
from rasa.shared.importers.importer import TrainingDataImporter
from rasa.shared.constants import (
ASSISTANT_ID_DEFAULT_VALUE,
ASSISTANT_ID_KEY,
DEFAULT_CONFIG_PATH,
)
from rasa.shared.utils.cli import print_error
from rasa import telemetry
if TYPE_CHECKING:
from pathlib import Path
from questionary import Question
from typing_extensions import Literal
from rasa.validator import Validator
logger = logging.getLogger(__name__)
FREE_TEXT_INPUT_PROMPT = "Type out your own message..."
@overload
def get_validated_path(
current: Optional[Union["Path", Text]],
parameter: Text,
default: Optional[Union["Path", Text]] = ...,
none_is_valid: "Literal[False]" = ...,
) -> Union["Path", Text]:
...
@overload
def get_validated_path(
current: Optional[Union["Path", Text]],
parameter: Text,
default: Optional[Union["Path", Text]] = ...,
none_is_valid: "Literal[True]" = ...,
) -> Optional[Union["Path", Text]]:
...
def get_validated_path(
current: Optional[Union["Path", Text]],
parameter: Text,
default: Optional[Union["Path", Text]] = None,
none_is_valid: bool = False,
) -> Optional[Union["Path", Text]]:
"""Checks whether a file path or its default value is valid and returns it.
Args:
current: The parsed value.
parameter: The name of the parameter.
default: The default value of the parameter.
none_is_valid: `True` if `None` is valid value for the path,
else `False``
Returns:
The current value if it was valid, else the default value of the
argument if it is valid, else `None`.
"""
if current is None or current is not None and not os.path.exists(current):
if default is not None and os.path.exists(default):
reason_str = f"'{current}' not found."
if current is None:
reason_str = f"Parameter '{parameter}' not set."
else:
rasa.shared.utils.io.raise_warning(
f"The path '{current}' does not seem to exist. Using the "
f"default value '{default}' instead."
)
logger.debug(f"{reason_str} Using default location '{default}' instead.")
current = default
elif none_is_valid:
current = None
else:
cancel_cause_not_found(current, parameter, default)
return current
def missing_config_keys(
path: Union["Path", Text], mandatory_keys: List[Text]
) -> List[Text]:
"""Checks whether the config file at `path` contains the `mandatory_keys`.
Args:
path: The path to the config file.
mandatory_keys: A list of mandatory config keys.
Returns:
The list of missing config keys.
"""
import rasa.utils.io
if not os.path.exists(path):
return mandatory_keys
config_data = rasa.shared.utils.io.read_config_file(path)
return [k for k in mandatory_keys if k not in config_data or config_data[k] is None]
def validate_assistant_id_in_config(config_file: Union["Path", Text]) -> None:
"""Verifies that the assistant_id key exists and has a unique value in config.
Issues a warning if the key does not exist or has the default value and replaces it
with a pseudo-random string value.
"""
config_data = rasa.shared.utils.io.read_config_file(
config_file, reader_type=["safe", "rt"]
)
assistant_id = config_data.get(ASSISTANT_ID_KEY)
if assistant_id is None or assistant_id == ASSISTANT_ID_DEFAULT_VALUE:
rasa.shared.utils.io.raise_warning(
f"The config file '{str(config_file)}' is missing a unique value for the "
f"'{ASSISTANT_ID_KEY}' mandatory key. Proceeding with generating a random "
f"value and overwriting the '{ASSISTANT_ID_KEY}' in the config file."
)
# add random value for assistant id, overwrite config file
time_format = "%Y%m%d-%H%M%S"
config_data[
ASSISTANT_ID_KEY
] = f"{time.strftime(time_format)}-{randomname.get_name()}"
rasa.shared.utils.io.write_yaml(
data=config_data, target=config_file, should_preserve_key_order=True
)
return
def validate_config_path(
config: Optional[Union[Text, "Path"]],
default_config: Text = DEFAULT_CONFIG_PATH,
) -> Text:
"""Verifies that the config path exists.
Exit if the config file does not exist.
Args:
config: Path to the config file.
default_config: default config to use if the file at `config` doesn't exist.
Returns: The path to the config file.
"""
config = rasa.cli.utils.get_validated_path(config, "config", default_config)
if not config or not os.path.exists(config):
print_error(
"The config file '{}' does not exist. Use '--config' to specify a "
"valid config file."
"".format(config)
)
sys.exit(1)
return str(config)
def validate_mandatory_config_keys(
config: Union[Text, "Path"],
mandatory_keys: List[Text],
) -> Text:
"""Get a config from a config file and check if it is valid.
Exit if the config isn't valid.
Args:
config: Path to the config file.
mandatory_keys: The keys that have to be specified in the config file.
Returns: The path to the config file if the config is valid.
"""
missing_keys = set(rasa.cli.utils.missing_config_keys(config, mandatory_keys))
if missing_keys:
print_error(
"The config file '{}' is missing mandatory parameters: "
"'{}'. Add missing parameters to config file and try again."
"".format(config, "', '".join(missing_keys))
)
sys.exit(1)
return str(config)
def get_validated_config(
config: Optional[Union[Text, "Path"]],
mandatory_keys: List[Text],
default_config: Text = DEFAULT_CONFIG_PATH,
) -> Text:
"""Validates config and returns path to validated config file."""
config = validate_config_path(config, default_config)
validate_assistant_id_in_config(config)
config = validate_mandatory_config_keys(config, mandatory_keys)
return config
def validate_files(
fail_on_warnings: bool,
max_history: Optional[int],
importer: TrainingDataImporter,
stories_only: bool = False,
) -> None:
"""Validates either the story structure or the entire project.
Args:
fail_on_warnings: `True` if the process should exit with a non-zero status
max_history: The max history to use when validating the story structure.
importer: The `TrainingDataImporter` to use to load the training data.
stories_only: If `True`, only the story structure is validated.
"""
from rasa.validator import Validator
validator = Validator.from_importer(importer)
if stories_only:
all_good = _validate_story_structure(validator, max_history, fail_on_warnings)
else:
if importer.get_domain().is_empty():
rasa.shared.utils.cli.print_error_and_exit(
"Encountered empty domain during validation."
)
valid_domain = _validate_domain(validator)
valid_nlu = _validate_nlu(validator, fail_on_warnings)
valid_stories = _validate_story_structure(
validator, max_history, fail_on_warnings
)
all_good = valid_domain and valid_nlu and valid_stories
validator.warn_if_config_mandatory_keys_are_not_set()
telemetry.track_validate_files(all_good)
if not all_good:
rasa.shared.utils.cli.print_error_and_exit(
"Project validation completed with errors."
)
def _validate_domain(validator: "Validator") -> bool:
valid_domain_validity = validator.verify_domain_validity()
valid_actions_in_stories_rules = validator.verify_actions_in_stories_rules()
valid_forms_in_stories_rules = validator.verify_forms_in_stories_rules()
valid_form_slots = validator.verify_form_slots()
valid_slot_mappings = validator.verify_slot_mappings()
return (
valid_domain_validity
and valid_actions_in_stories_rules
and valid_forms_in_stories_rules
and valid_form_slots
and valid_slot_mappings
)
def _validate_nlu(validator: "Validator", fail_on_warnings: bool) -> bool:
return validator.verify_nlu(not fail_on_warnings)
def _validate_story_structure(
validator: "Validator", max_history: Optional[int], fail_on_warnings: bool
) -> bool:
# Check if a valid setting for `max_history` was given
if isinstance(max_history, int) and max_history < 1:
raise argparse.ArgumentTypeError(
f"The value of `--max-history {max_history}` " f"is not a positive integer."
)
return validator.verify_story_structure(
not fail_on_warnings, max_history=max_history
)
def cancel_cause_not_found(
current: Optional[Union["Path", Text]],
parameter: Text,
default: Optional[Union["Path", Text]],
) -> None:
"""Exits with an error because the given path was not valid.
Args:
current: The path given by the user.
parameter: The name of the parameter.
default: The default value of the parameter.
"""
default_clause = ""
if default:
default_clause = f"use the default location ('{default}') or "
rasa.shared.utils.cli.print_error(
"The path '{}' does not exist. Please make sure to {}specify it"
" with '--{}'.".format(current, default_clause, parameter)
)
sys.exit(1)
def parse_last_positional_argument_as_model_path() -> None:
"""Fixes the parsing of a potential positional model path argument."""
if (
len(sys.argv) >= 2
# support relevant commands ...
and sys.argv[1] in ["run", "shell", "interactive"]
# but avoid interpreting subparser commands as model paths
and sys.argv[1:] != ["run", "actions"]
and not sys.argv[-2].startswith("-")
and os.path.exists(sys.argv[-1])
):
sys.argv.append(sys.argv[-1])
sys.argv[-2] = "--model"
def button_to_string(button: Dict[Text, Any], idx: int = 0) -> Text:
"""Create a string representation of a button."""
title = button.pop("title", "")
if "payload" in button:
payload = " ({})".format(button.pop("payload"))
else:
payload = ""
# if there are any additional attributes, we append them to the output
if button:
details = " - {}".format(json.dumps(button, sort_keys=True))
else:
details = ""
button_string = "{idx}: {title}{payload}{details}".format(
idx=idx + 1, title=title, payload=payload, details=details
)
return button_string
def element_to_string(element: Dict[Text, Any], idx: int = 0) -> Text:
"""Create a string representation of an element."""
title = element.pop("title", "")
element_string = "{idx}: {title} - {element}".format(
idx=idx + 1, title=title, element=json.dumps(element, sort_keys=True)
)
return element_string
def button_choices_from_message_data(
message: Dict[Text, Any], allow_free_text_input: bool = True
) -> List[Text]:
"""Return list of choices to present to the user.
If allow_free_text_input is True, an additional option is added
at the end along with the response buttons that allows the user
to type in free text.
"""
choices = [
button_to_string(button, idx)
for idx, button in enumerate(message.get("buttons"))
]
if allow_free_text_input:
choices.append(FREE_TEXT_INPUT_PROMPT)
return choices
async def payload_from_button_question(button_question: "Question") -> Text:
"""Prompt user with a button question and returns the nlu payload."""
response = await button_question.ask_async()
if response != FREE_TEXT_INPUT_PROMPT:
# Extract intent slash command if it's a button
response = response[response.rfind("(") + 1 : response.rfind(")")]
return response
def signal_handler(_: int, __: FrameType) -> None:
"""Kills Rasa when OS signal is received."""
print("Goodbye 👋")
sys.exit(0)