From 0d58385db2ce20ceca50f3904af982e712ef00fa Mon Sep 17 00:00:00 2001 From: Jamie MacDonald Date: Wed, 12 Jul 2023 17:06:49 +0100 Subject: [PATCH 01/19] Remove Snyk jobs from CI scanning --- .github/workflows/security-scans.yml | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/.github/workflows/security-scans.yml b/.github/workflows/security-scans.yml index 7348db48311f..a421295f4ab5 100644 --- a/.github/workflows/security-scans.yml +++ b/.github/workflows/security-scans.yml @@ -128,25 +128,4 @@ jobs: - name: Run Bandit 🔪 if: needs.changes.outputs.backend == 'true' - run: make lint-security - - snyk: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - name: Run Snyk Open Source to check for Python vulnerabilities - uses: snyk/actions/python-3.8@master - continue-on-error: true - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - with: - command: monitor - args: --all-projects --org=rasa --skip-unresolved - - name: Run Snyk Open Source to check for JS vulnerabilities - uses: snyk/actions/node@master - continue-on-error: true - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - with: - command: monitor - args: --org=rasa --yarn-workspaces --strict-out-of-sync=false --prune-repeated-subdependencies + run: make lint-security \ No newline at end of file From dc6f00de718dbcf244e800fe90912f0dfd6c45f8 Mon Sep 17 00:00:00 2001 From: Jamie MacDonald Date: Wed, 12 Jul 2023 17:10:28 +0100 Subject: [PATCH 02/19] Fix line formatting --- .github/workflows/security-scans.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scans.yml b/.github/workflows/security-scans.yml index a421295f4ab5..b4cbf69cc92f 100644 --- a/.github/workflows/security-scans.yml +++ b/.github/workflows/security-scans.yml @@ -128,4 +128,4 @@ jobs: - name: Run Bandit 🔪 if: needs.changes.outputs.backend == 'true' - run: make lint-security \ No newline at end of file + run: make lint-security From 58e122fe459fe3a21441fc44f9a1082d490eb9f2 Mon Sep 17 00:00:00 2001 From: Thomas Werkmeister Date: Thu, 16 Nov 2023 10:06:17 +0100 Subject: [PATCH 03/19] Made use of drop-small-last-batch logic only possible in DIET and configurable (#12948) * Made use of drop-small-last-batch logic only possible in DIET and configurable --- changelog/12948.bugfix.md | 1 + rasa/nlu/classifiers/diet_classifier.py | 5 +++ rasa/utils/tensorflow/constants.py | 1 + rasa/utils/tensorflow/data_generator.py | 19 ++++++--- rasa/utils/train_utils.py | 5 +++ tests/nlu/classifiers/test_diet_classifier.py | 41 +++++++++++++------ 6 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 changelog/12948.bugfix.md diff --git a/changelog/12948.bugfix.md b/changelog/12948.bugfix.md new file mode 100644 index 000000000000..7479161831be --- /dev/null +++ b/changelog/12948.bugfix.md @@ -0,0 +1 @@ +Fixed UnexpecTEDIntentlessPolicy training errors that resulted from a change to batching behavior. Changed the batching behavior back to the original for all components. Made the changed batching behavior accessible in DietClassifier using `drop_small_last_batch: True`. diff --git a/rasa/nlu/classifiers/diet_classifier.py b/rasa/nlu/classifiers/diet_classifier.py index 1cc65c89b3c9..bea4735da6fe 100644 --- a/rasa/nlu/classifiers/diet_classifier.py +++ b/rasa/nlu/classifiers/diet_classifier.py @@ -50,6 +50,7 @@ from rasa.shared.nlu.training_data.training_data import TrainingData from rasa.shared.nlu.training_data.message import Message from rasa.utils.tensorflow.constants import ( + DROP_SMALL_LAST_BATCH, LABEL, IDS, HIDDEN_LAYERS_SIZES, @@ -288,6 +289,9 @@ def get_default_config() -> Dict[Text, Any]: # a few steps, as the compilation of the graph tends to take more time than # running it. It is recommended to not adjust the optimization parameter. RUN_EAGERLY: False, + # Determines whether the last batch should be dropped if it contains fewer + # than half a batch size of examples + DROP_SMALL_LAST_BATCH: False, } def __init__( @@ -931,6 +935,7 @@ def train(self, training_data: TrainingData) -> Resource: self.component_config[BATCH_STRATEGY], self.component_config[EVAL_NUM_EXAMPLES], self.component_config[RANDOM_SEED], + drop_small_last_batch=self.component_config[DROP_SMALL_LAST_BATCH], ) callbacks = train_utils.create_common_callbacks( self.component_config[EPOCHS], diff --git a/rasa/utils/tensorflow/constants.py b/rasa/utils/tensorflow/constants.py index 047db9878c67..39d5ea6d0560 100644 --- a/rasa/utils/tensorflow/constants.py +++ b/rasa/utils/tensorflow/constants.py @@ -113,3 +113,4 @@ USE_GPU = "use_gpu" RUN_EAGERLY = "run_eagerly" +DROP_SMALL_LAST_BATCH = "drop_small_last_batch" diff --git a/rasa/utils/tensorflow/data_generator.py b/rasa/utils/tensorflow/data_generator.py index a696f607c026..e54b95dad335 100644 --- a/rasa/utils/tensorflow/data_generator.py +++ b/rasa/utils/tensorflow/data_generator.py @@ -344,6 +344,7 @@ def __init__( epochs: int = 1, batch_strategy: Text = SEQUENCE, shuffle: bool = True, + drop_small_last_batch: bool = False, ): """Initializes the increasing batch size data generator. @@ -353,6 +354,8 @@ def __init__( epochs: The total number of epochs. batch_strategy: The batch strategy. shuffle: If 'True', data will be shuffled. + drop_small_last_batch: if 'True', the last batch in an epoch will be dropped + if it has less examples than half the batch size """ super().__init__(model_data, batch_size, batch_strategy, shuffle) @@ -370,6 +373,7 @@ def __init__( self._current_batch_size = 0 # create separate data variable that will store modified data for each batch self._data: Data = {} + self.drop_small_last_batch = drop_small_last_batch self.on_epoch_end() def __len__(self) -> int: @@ -381,11 +385,16 @@ def __len__(self) -> int: # data was rebalanced, so need to recalculate number of examples num_examples = self.model_data.number_of_examples(self._data) batch_size = self._current_batch_size - # keep last batch only if it has at least half a batch size of examples - last_batch_half_full = num_examples % batch_size >= math.ceil(batch_size / 2) - num_batches = num_examples // batch_size + int(last_batch_half_full) - # Return at least 1 if there is an example - return max(num_batches, int(num_examples > 0)) + if self.drop_small_last_batch: + # keep last batch only if it has at least half a batch size of examples + last_batch_half_full = num_examples % batch_size >= math.ceil( + batch_size / 2 + ) + num_batches = num_examples // batch_size + int(last_batch_half_full) + # Return at least 1 if there is an example + return max(num_batches, int(num_examples > 0)) + else: + return num_examples // batch_size + int(num_examples % batch_size > 0) def __getitem__(self, index: int) -> Tuple[Any, Any]: """Gets batch at position `index`. diff --git a/rasa/utils/train_utils.py b/rasa/utils/train_utils.py index 36de0370d210..764507d7e39d 100644 --- a/rasa/utils/train_utils.py +++ b/rasa/utils/train_utils.py @@ -302,6 +302,7 @@ def create_data_generators( eval_num_examples: int = 0, random_seed: Optional[int] = None, shuffle: bool = True, + drop_small_last_batch: bool = False, ) -> Tuple[RasaBatchDataGenerator, Optional[RasaBatchDataGenerator]]: """Create data generators for train and optional validation data. @@ -313,6 +314,8 @@ def create_data_generators( eval_num_examples: Number of examples to use for validation data. random_seed: The random seed. shuffle: Whether to shuffle data inside the data generator. + drop_small_last_batch: whether to drop the last batch if it has fewer than half + a batch size of examples Returns: The training data generator and optional validation data generator. @@ -328,6 +331,7 @@ def create_data_generators( epochs=epochs, batch_strategy=batch_strategy, shuffle=shuffle, + drop_small_last_batch=drop_small_last_batch, ) data_generator = RasaBatchDataGenerator( @@ -336,6 +340,7 @@ def create_data_generators( epochs=epochs, batch_strategy=batch_strategy, shuffle=shuffle, + drop_small_last_batch=drop_small_last_batch, ) return data_generator, validation_data_generator diff --git a/tests/nlu/classifiers/test_diet_classifier.py b/tests/nlu/classifiers/test_diet_classifier.py index 1f0c37a85faa..1fd84fdac47d 100644 --- a/tests/nlu/classifiers/test_diet_classifier.py +++ b/tests/nlu/classifiers/test_diet_classifier.py @@ -971,24 +971,35 @@ async def test_no_bilou_when_entity_recognition_off( @pytest.mark.timeout(120, func_only=True) @pytest.mark.parametrize( - "batch_size, expected_num_batches", + "batch_size, expected_num_batches, drop_small_last_batch", # the training dataset has 48 NLU examples [ - (1, 48), - (8, 6), - (15, 3), - (16, 3), - (18, 3), - (20, 2), - (32, 2), - (64, 1), - (128, 1), - (256, 1), + (1, 48, True), + (8, 6, True), + (15, 3, True), + (16, 3, True), + (18, 3, True), + (20, 2, True), + (32, 2, True), + (64, 1, True), + (128, 1, True), + (256, 1, True), + (1, 48, False), + (8, 6, False), + (15, 4, False), + (16, 3, False), + (18, 3, False), + (20, 3, False), + (32, 2, False), + (64, 1, False), + (128, 1, False), + (256, 1, False), ], ) async def test_dropping_of_last_partial_batch( batch_size: int, expected_num_batches: int, + drop_small_last_batch: bool, create_diet: Callable[..., DIETClassifier], train_and_preprocess: Callable[..., Tuple[TrainingData, List[GraphComponent]]], ): @@ -1012,7 +1023,9 @@ async def test_dropping_of_last_partial_batch( ) model_data = diet.preprocess_train_data(training_data) - data_generator, _ = train_utils.create_data_generators(model_data, batch_size, 1) + data_generator, _ = train_utils.create_data_generators( + model_data, batch_size, 1, drop_small_last_batch=drop_small_last_batch + ) assert len(data_generator) == expected_num_batches @@ -1041,6 +1054,8 @@ async def test_dropping_of_last_partial_batch_empty_data( ) model_data = diet.preprocess_train_data(training_data) - data_generator, _ = train_utils.create_data_generators(model_data, 64, 1) + data_generator, _ = train_utils.create_data_generators( + model_data, 64, 1, drop_small_last_batch=True + ) assert len(data_generator) == 0 From 048dc805b1781535a0b10705e4b104faec066abb Mon Sep 17 00:00:00 2001 From: Thomas Werkmeister Date: Fri, 17 Nov 2023 15:11:59 +0100 Subject: [PATCH 04/19] adjusted release script to work with public remote (#12953) --- scripts/release.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/release.py b/scripts/release.py index d1ac98325f80..068bd14e5fd2 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -30,6 +30,10 @@ RELEASE_BRANCH_PATTERN = re.compile(r"^\d+\.\d+\.x$") +PUBLIC_REMOTE = "public" +DEFAULT_REMOTE = "origin" +FIRST_CALM_VERSION = "3.7.0" + def create_argument_parser() -> argparse.ArgumentParser: """Parse all the command line arguments for the release script.""" @@ -247,9 +251,9 @@ def create_commit(version: Version) -> None: check_call(["git", "commit", "-m", f"prepared release of version {version}"]) -def push_changes() -> None: - """Pushes the current branch to origin.""" - check_call(["git", "push", "origin", "HEAD"]) +def push_changes(remote: str = DEFAULT_REMOTE) -> None: + """Pushes the current branch to the specified remote.""" + check_call(["git", "push", remote, "HEAD"]) def ensure_clean_git() -> None: @@ -337,10 +341,11 @@ def main(args: argparse.Namespace) -> None: # never update changelog on a prerelease version generate_changelog(version) + remote = PUBLIC_REMOTE if str(version) < FIRST_CALM_VERSION else DEFAULT_REMOTE # alpha workflow on feature branch when a version bump is required if version.is_alpha and not git_current_branch_is_main_or_release(): create_commit(version) - push_changes() + push_changes(remote) print_done_message_same_branch(version) else: @@ -348,7 +353,7 @@ def main(args: argparse.Namespace) -> None: branch = create_release_branch(version) create_commit(version) - push_changes() + push_changes(remote) print_done_message(branch, base, version) From 241bf28342cb8b56e3d395d6136587286debbe9c Mon Sep 17 00:00:00 2001 From: Thomas Werkmeister Date: Mon, 20 Nov 2023 10:10:11 +0100 Subject: [PATCH 05/19] Prepare release 3.6.14 (#12956) * prepared release of version 3.6.14 --- CHANGELOG.mdx | 7 +++++++ changelog/12948.bugfix.md | 1 - pyproject.toml | 2 +- rasa/version.py | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) delete mode 100644 changelog/12948.bugfix.md diff --git a/CHANGELOG.mdx b/CHANGELOG.mdx index 9a6177e3632c..b574a76b1b96 100644 --- a/CHANGELOG.mdx +++ b/CHANGELOG.mdx @@ -16,6 +16,13 @@ https://github.com/RasaHQ/rasa/tree/main/changelog/ . --> +## [3.6.14] - 2023-11-17 + +Rasa 3.6.14 (2023-11-17) +### Bugfixes +- [#12948](https://github.com/rasahq/rasa/issues/12948): Fixed UnexpecTEDIntentlessPolicy training errors that resulted from a change to batching behavior. Changed the batching behavior back to the original for all components. Made the changed batching behavior accessible in DietClassifier using `drop_small_last_batch: True`. + + ## [3.6.13] - 2023-10-23 Rasa 3.6.13 (2023-10-23) diff --git a/changelog/12948.bugfix.md b/changelog/12948.bugfix.md deleted file mode 100644 index 7479161831be..000000000000 --- a/changelog/12948.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Fixed UnexpecTEDIntentlessPolicy training errors that resulted from a change to batching behavior. Changed the batching behavior back to the original for all components. Made the changed batching behavior accessible in DietClassifier using `drop_small_last_batch: True`. diff --git a/pyproject.toml b/pyproject.toml index c3809092b5c2..4bf33f2a32d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ exclude = "((.eggs | .git | .pytest_cache | build | dist))" [tool.poetry] name = "rasa" -version = "3.6.13" +version = "3.6.14" description = "Open source machine learning framework to automate text- and voice-based conversations: NLU, dialogue management, connect to Slack, Facebook, and more - Create chatbots and voice assistants" authors = [ "Rasa Technologies GmbH ",] maintainers = [ "Tom Bocklisch ",] diff --git a/rasa/version.py b/rasa/version.py index 7f4d3334548b..e4512ce41043 100644 --- a/rasa/version.py +++ b/rasa/version.py @@ -1,3 +1,3 @@ # this file will automatically be changed, # do not add anything but the version number here! -__version__ = "3.6.13" +__version__ = "3.6.14" From 609287ec3cdaa3151f867753878e4ffeb9344da9 Mon Sep 17 00:00:00 2001 From: Varun Shankar S Date: Thu, 30 Nov 2023 13:26:52 +0100 Subject: [PATCH 06/19] Port "connection timeout to action server" changes to 3.6.x - [ENG 689] (#12965) * Merge pull request #106 from RasaHQ/ENG-680-DEFAULT_KEEP_ALIVE_TIMEOUT Fix connection to action server - [ENG 680] --------- Co-authored-by: Tom Bocklisch --- rasa/core/agent.py | 96 +++++++++++++++++++---------------- rasa/core/constants.py | 2 + rasa/core/run.py | 82 ++++++++++++++---------------- rasa/utils/endpoints.py | 68 ++++++++++++++----------- tests/core/test_run.py | 3 -- tests/utils/test_endpoints.py | 42 +++------------ 6 files changed, 136 insertions(+), 157 deletions(-) diff --git a/rasa/core/agent.py b/rasa/core/agent.py index bf3d42236e70..47e3360f6a5b 100644 --- a/rasa/core/agent.py +++ b/rasa/core/agent.py @@ -112,53 +112,59 @@ async def _pull_model_and_fingerprint( logger.debug(f"Requesting model from server {model_server.url}...") - try: - params = model_server.combine_parameters() - async with model_server.session.request( - "GET", - model_server.url, - timeout=DEFAULT_REQUEST_TIMEOUT, - headers=headers, - params=params, - ) as resp: - if resp.status in [204, 304]: - logger.debug( - "Model server returned {} status code, " - "indicating that no new model is available. " - "Current fingerprint: {}" - "".format(resp.status, fingerprint) - ) - return None - elif resp.status == 404: - logger.debug( - "Model server could not find a model at the requested " - "endpoint '{}'. It's possible that no model has been " - "trained, or that the requested tag hasn't been " - "assigned.".format(model_server.url) - ) - return None - elif resp.status != 200: - logger.debug( - "Tried to fetch model from server, but server response " - "status code is {}. We'll retry later..." - "".format(resp.status) + async with model_server.session() as session: + try: + params = model_server.combine_parameters() + async with session.request( + "GET", + model_server.url, + timeout=DEFAULT_REQUEST_TIMEOUT, + headers=headers, + params=params, + ) as resp: + + if resp.status in [204, 304]: + logger.debug( + "Model server returned {} status code, " + "indicating that no new model is available. " + "Current fingerprint: {}" + "".format(resp.status, fingerprint) + ) + return None + elif resp.status == 404: + logger.debug( + "Model server could not find a model at the requested " + "endpoint '{}'. It's possible that no model has been " + "trained, or that the requested tag hasn't been " + "assigned.".format(model_server.url) + ) + return None + elif resp.status != 200: + logger.debug( + "Tried to fetch model from server, but server response " + "status code is {}. We'll retry later..." + "".format(resp.status) + ) + return None + + model_path = Path(model_directory) / resp.headers.get( + "filename", "model.tar.gz" ) - return None - model_path = Path(model_directory) / resp.headers.get( - "filename", "model.tar.gz" + with open(model_path, "wb") as file: + file.write(await resp.read()) + + logger.debug("Saved model to '{}'".format(os.path.abspath(model_path))) + + # return the new fingerprint + return resp.headers.get("ETag") + + except aiohttp.ClientError as e: + logger.debug( + "Tried to fetch model from server, but " + "couldn't reach server. We'll retry later... " + "Error: {}.".format(e) ) - with open(model_path, "wb") as file: - file.write(await resp.read()) - logger.debug("Saved model to '{}'".format(os.path.abspath(model_path))) - # return the new fingerprint - return resp.headers.get("ETag") - except aiohttp.ClientError as e: - logger.debug( - "Tried to fetch model from server, but " - "couldn't reach server. We'll retry later... " - "Error: {}.".format(e) - ) - return None + return None async def _run_model_pulling_worker(model_server: EndpointConfig, agent: Agent) -> None: diff --git a/rasa/core/constants.py b/rasa/core/constants.py index 973e4e7b3a99..40d65c3299bb 100644 --- a/rasa/core/constants.py +++ b/rasa/core/constants.py @@ -24,6 +24,8 @@ DEFAULT_LOCK_LIFETIME = 60 # in seconds +DEFAULT_KEEP_ALIVE_TIMEOUT = 120 # in seconds + BEARER_TOKEN_PREFIX = "Bearer " # The lowest priority is intended to be used by machine learning policies. diff --git a/rasa/core/run.py b/rasa/core/run.py index 5270162809dd..3a8133613c3f 100644 --- a/rasa/core/run.py +++ b/rasa/core/run.py @@ -1,9 +1,19 @@ import asyncio import logging import uuid +import platform import os from functools import partial -from typing import Any, List, Optional, TYPE_CHECKING, Text, Union, Dict +from typing import ( + Any, + Callable, + List, + Optional, + Text, + Tuple, + Union, + Dict, +) import rasa.core.utils from rasa.plugin import plugin_manager @@ -23,8 +33,6 @@ from sanic import Sanic from asyncio import AbstractEventLoop -if TYPE_CHECKING: - from aiohttp import ClientSession logger = logging.getLogger() # get the root logger @@ -80,6 +88,14 @@ def _create_app_without_api(cors: Optional[Union[Text, List[Text]]] = None) -> S return app +def _is_apple_silicon_system() -> bool: + # check if the system is MacOS + if platform.system().lower() != "darwin": + return False + # check for arm architecture, indicating apple silicon + return platform.machine().startswith("arm") or os.uname().machine.startswith("arm") + + def configure_app( input_channels: Optional[List["InputChannel"]] = None, cors: Optional[Union[Text, List[Text], None]] = None, @@ -99,6 +115,9 @@ def configure_app( syslog_port: Optional[int] = None, syslog_protocol: Optional[Text] = None, request_timeout: Optional[int] = None, + server_listeners: Optional[List[Tuple[Callable, Text]]] = None, + use_uvloop: Optional[bool] = True, + keep_alive_timeout: int = constants.DEFAULT_KEEP_ALIVE_TIMEOUT, ) -> Sanic: """Run the agent.""" rasa.core.utils.configure_file_logging( @@ -118,6 +137,14 @@ def configure_app( else: app = _create_app_without_api(cors) + app.config.KEEP_ALIVE_TIMEOUT = keep_alive_timeout + if _is_apple_silicon_system() or not use_uvloop: + app.config.USE_UVLOOP = False + # some library still sets the loop to uvloop, even if disabled for sanic + # using uvloop leads to breakingio errors, see + # https://rasahq.atlassian.net/browse/ENG-667 + asyncio.set_event_loop_policy(None) + if input_channels: channels.channel.register(input_channels, app, route=route) else: @@ -150,6 +177,10 @@ async def run_cmdline_io(running_app: Sanic) -> None: app.add_task(run_cmdline_io) + if server_listeners: + for (listener, event) in server_listeners: + app.register_listener(listener, event) + return app @@ -179,6 +210,7 @@ def serve_application( syslog_port: Optional[int] = None, syslog_protocol: Optional[Text] = None, request_timeout: Optional[int] = None, + server_listeners: Optional[List[Tuple[Callable, Text]]] = None, ) -> None: """Run the API entrypoint.""" if not channel and not credentials: @@ -204,6 +236,7 @@ def serve_application( syslog_port=syslog_port, syslog_protocol=syslog_protocol, request_timeout=request_timeout, + server_listeners=server_listeners, ) ssl_context = server.create_ssl_context( @@ -217,7 +250,7 @@ def serve_application( partial(load_agent_on_start, model_path, endpoints, remote_storage), "before_server_start", ) - app.register_listener(create_connection_pools, "after_server_start") + app.register_listener(close_resources, "after_server_stop") number_of_workers = rasa.core.utils.number_of_sanic_workers( @@ -279,44 +312,3 @@ async def close_resources(app: Sanic, _: AbstractEventLoop) -> None: event_broker = current_agent.tracker_store.event_broker if event_broker: await event_broker.close() - - action_endpoint = current_agent.action_endpoint - if action_endpoint: - await action_endpoint.session.close() - - model_server = current_agent.model_server - if model_server: - await model_server.session.close() - - -async def create_connection_pools(app: Sanic, _: AbstractEventLoop) -> None: - """Create connection pools for the agent's action server and model server.""" - current_agent = getattr(app.ctx, "agent", None) - if not current_agent: - logger.debug("No agent found after server start.") - return None - - create_action_endpoint_connection_pool(current_agent) - create_model_server_connection_pool(current_agent) - - return None - - -def create_action_endpoint_connection_pool(agent: Agent) -> Optional["ClientSession"]: - """Create a connection pool for the action endpoint.""" - action_endpoint = agent.action_endpoint - if not action_endpoint: - logger.debug("No action endpoint found after server start.") - return None - - return action_endpoint.session - - -def create_model_server_connection_pool(agent: Agent) -> Optional["ClientSession"]: - """Create a connection pool for the model server.""" - model_server = agent.model_server - if not model_server: - logger.debug("No model server endpoint found after server start.") - return None - - return model_server.session diff --git a/rasa/utils/endpoints.py b/rasa/utils/endpoints.py index 5e1032778e6b..31d1ea7228bc 100644 --- a/rasa/utils/endpoints.py +++ b/rasa/utils/endpoints.py @@ -1,8 +1,6 @@ import ssl -from functools import cached_property import aiohttp -import logging import os from aiohttp.client_exceptions import ContentTypeError from sanic.request import Request @@ -11,10 +9,11 @@ from rasa.shared.exceptions import FileNotFoundException import rasa.shared.utils.io import rasa.utils.io +import structlog from rasa.core.constants import DEFAULT_REQUEST_TIMEOUT -logger = logging.getLogger(__name__) +structlogger = structlog.get_logger() def read_endpoint_config( @@ -32,9 +31,13 @@ def read_endpoint_config( return EndpointConfig.from_dict(content[endpoint_type]) except FileNotFoundError: - logger.error( - "Failed to read endpoint configuration " - "from {}. No such file.".format(os.path.abspath(filename)) + structlogger.error( + "endpoint.read.failed_no_such_file", + filename=os.path.abspath(filename), + event_info=( + "Failed to read endpoint configuration file - " + "the file was not found." + ), ) return None @@ -56,9 +59,13 @@ def concat_url(base: Text, subpath: Optional[Text]) -> Text: """ if not subpath: if base.endswith("/"): - logger.debug( - f"The URL '{base}' has a trailing slash. Please make sure the " - f"target server supports trailing slashes for this endpoint." + structlogger.debug( + "endpoint.concat_url.trailing_slash", + url=base, + event_info=( + "The URL has a trailing slash. Please make sure the " + "target server supports trailing slashes for this endpoint." + ), ) return base @@ -95,7 +102,6 @@ def __init__( self.cafile = cafile self.kwargs = kwargs - @cached_property def session(self) -> aiohttp.ClientSession: """Creates and returns a configured aiohttp client session.""" # create authentication parameters @@ -164,23 +170,26 @@ async def request( f"'{os.path.abspath(self.cafile)}' does not exist." ) from e - async with self.session.request( - method, - url, - headers=headers, - params=self.combine_parameters(kwargs), - compress=compress, - ssl=sslcontext, - **kwargs, - ) as response: - if response.status >= 400: - raise ClientResponseError( - response.status, response.reason, await response.content.read() - ) - try: - return await response.json() - except ContentTypeError: - return None + async with self.session() as session: + async with session.request( + method, + url, + headers=headers, + params=self.combine_parameters(kwargs), + compress=compress, + ssl=sslcontext, + **kwargs, + ) as response: + if response.status >= 400: + raise ClientResponseError( + response.status, + response.reason, + await response.content.read(), + ) + try: + return await response.json() + except ContentTypeError: + return None @classmethod def from_dict(cls, data: Dict[Text, Any]) -> "EndpointConfig": @@ -263,7 +272,7 @@ def float_arg( try: return float(str(arg)) except (ValueError, TypeError): - logger.warning(f"Failed to convert '{arg}' to float.") + structlogger.warning("endpoint.float_arg.convert_failed", arg=arg, key=key) return default @@ -291,5 +300,6 @@ def int_arg( try: return int(str(arg)) except (ValueError, TypeError): - logger.warning(f"Failed to convert '{arg}' to int.") + + structlogger.warning("endpoint.int_arg.convert_failed", arg=arg, key=key) return default diff --git a/tests/core/test_run.py b/tests/core/test_run.py index 1ac276d43772..8eda15058c0d 100644 --- a/tests/core/test_run.py +++ b/tests/core/test_run.py @@ -1,7 +1,6 @@ import warnings from unittest.mock import Mock -import aiohttp import pytest from typing import Text @@ -84,8 +83,6 @@ async def test_close_resources(loop: AbstractEventLoop): broker = SQLEventBroker() app = Mock() app.ctx.agent.tracker_store.event_broker = broker - app.ctx.agent.action_endpoint.session = aiohttp.ClientSession() - app.ctx.agent.model_server.session = aiohttp.ClientSession() with warnings.catch_warnings() as record: await run.close_resources(app, loop) diff --git a/tests/utils/test_endpoints.py b/tests/utils/test_endpoints.py index 071e54ee9318..711f2fd25faa 100644 --- a/tests/utils/test_endpoints.py +++ b/tests/utils/test_endpoints.py @@ -1,4 +1,4 @@ -import logging +import structlog from pathlib import Path from typing import Text, Optional, Union from unittest.mock import Mock @@ -35,13 +35,14 @@ def test_concat_url(base, subpath, expected_result): assert endpoint_utils.concat_url(base, subpath) == expected_result -def test_warning_for_base_paths_with_trailing_slash(caplog): +def test_warning_for_base_paths_with_trailing_slash(): test_path = "base/" - - with caplog.at_level(logging.DEBUG, logger="rasa.utils.endpoints"): + with structlog.testing.capture_logs() as caplog: assert endpoint_utils.concat_url(test_path, None) == test_path - assert len(caplog.records) == 1 + assert len(caplog) == 1 + assert caplog[0]["event"] == "endpoint.concat_url.trailing_slash" + assert caplog[0]["log_level"] == "debug" async def test_endpoint_config(): @@ -88,7 +89,7 @@ async def test_endpoint_config(): # unfortunately, the mock library won't report any headers stored on # the session object, so we need to verify them separately - async with endpoint.session as s: + async with endpoint.session() as s: assert s._default_headers.get("X-Powered-By") == "Rasa" assert s._default_auth.login == "user" assert s._default_auth.password == "pass" @@ -231,32 +232,3 @@ def test_int_arg(value: Optional[Union[int, str]], default: int, expected_result if value is not None: request.args = {"key": value} assert endpoint_utils.int_arg(request, "key", default) == expected_result - - -async def test_endpoint_config_caches_session() -> None: - """Test that the EndpointConfig session is cached. - - Assert identity of the session object, which should not be recreated when calling - the property `session` multiple times. - """ - endpoint = endpoint_utils.EndpointConfig("https://example.com/") - session = endpoint.session - - assert endpoint.session is session - - # teardown - await endpoint.session.close() - - -async def test_endpoint_config_constructor_does_not_create_session_cached_property() -> None: # noqa: E501 - """Test that the instantiation of EndpointConfig does not create the session cached property.""" # noqa: E501 - endpoint = endpoint_utils.EndpointConfig("https://example.com/") - - assert endpoint.__dict__.get("url") == "https://example.com/" - assert endpoint.__dict__.get("session") is None - - # the property is created when it is accessed - async with endpoint.session as session: - assert session is not None - - assert endpoint.__dict__.get("session") is session From 7cfc7d07e3f5502ed7333ad1910d5d85891eb473 Mon Sep 17 00:00:00 2001 From: Varun Shankar S Date: Thu, 30 Nov 2023 19:51:17 +0100 Subject: [PATCH 07/19] prepared release of version 3.6.15 (#12967) * prepared release of version 3.6.15 --- CHANGELOG.mdx | 7 +++++++ Makefile | 2 +- pyproject.toml | 2 +- rasa/version.py | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.mdx b/CHANGELOG.mdx index b574a76b1b96..fce125567d98 100644 --- a/CHANGELOG.mdx +++ b/CHANGELOG.mdx @@ -16,6 +16,13 @@ https://github.com/RasaHQ/rasa/tree/main/changelog/ . --> +## [3.6.15] - 2023-11-30 + +Rasa 3.6.15 (2023-11-30) +### Bugfixes +- [#12965](https://github.com/rasahq/rasa/issues/12965): Fixed connection timeout to action server by setting KEEP_ALIVE_TIMEOUT to 120, and reverting changes introduced in #12886. + + ## [3.6.14] - 2023-11-17 Rasa 3.6.14 (2023-11-17) diff --git a/Makefile b/Makefile index f3ebb6135e25..23b5799e1d5f 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ prepare-tests-windows: # It will retry the installation 5 times if it fails # See: https://github.com/actions/virtual-environments/blob/main/images/win/scripts/ImageHelpers/ChocoHelpers.ps1 prepare-tests-windows-gha: - powershell -command "Choco-Install wget graphviz" + powershell -command "Install-ChocoPackage wget graphviz" test: clean # OMP_NUM_THREADS can improve overall performance using one thread by process (on tensorflow), avoiding overload diff --git a/pyproject.toml b/pyproject.toml index 4bf33f2a32d5..92d55359da8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ exclude = "((.eggs | .git | .pytest_cache | build | dist))" [tool.poetry] name = "rasa" -version = "3.6.14" +version = "3.6.15" description = "Open source machine learning framework to automate text- and voice-based conversations: NLU, dialogue management, connect to Slack, Facebook, and more - Create chatbots and voice assistants" authors = [ "Rasa Technologies GmbH ",] maintainers = [ "Tom Bocklisch ",] diff --git a/rasa/version.py b/rasa/version.py index e4512ce41043..3d8e9f0ee007 100644 --- a/rasa/version.py +++ b/rasa/version.py @@ -1,3 +1,3 @@ # this file will automatically be changed, # do not add anything but the version number here! -__version__ = "3.6.14" +__version__ = "3.6.15" From 865902f3c576a4a66b9b9492f3e8234261c14e17 Mon Sep 17 00:00:00 2001 From: sancharigr Date: Mon, 11 Dec 2023 10:29:05 +0100 Subject: [PATCH 08/19] Additional load testing recommendations --- .../monitoring/load-testing-guidelines.mdx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/docs/monitoring/load-testing-guidelines.mdx b/docs/docs/monitoring/load-testing-guidelines.mdx index ff40486853b5..23b104917177 100644 --- a/docs/docs/monitoring/load-testing-guidelines.mdx +++ b/docs/docs/monitoring/load-testing-guidelines.mdx @@ -17,6 +17,29 @@ In our tests we used the Rasa [HTTP-API](https://rasa.com/docs/rasa/pages/http-a | Up to 50,000 | 6vCPU | 16 GB | | Up to 80,000 | 6vCPU, with almost 90% CPU usage | 16 GB | +:::info This is the most optimal AWS setup tested on EKS with + +ec2: c5.2xlarge - 9.2rps/node throughput +ec2: c5.4xlarge - 19.5rps/node throughput +You can always choose a bigger compute efficient instance like c5.4xlarge with more CPU per node to maximize throughput per node + +::: + +| AWS | RasaPro | Rasa Action Server | +|--------------------------|----------------------------------------------|-------------------------------------------| +| EC2: C52xlarge | 3vCPU, 10Gb Memory, 3 Sanic Threads | 3vCPU, 2Gb Memory, 3 Sanic Threads | +| EC2: C54xlarge | 7vCPU, 16Gb Memory, 7 Sanic Threads | 7vCPU, 12Gb Memory, 7 Sanic Threads | + +### Some recommendations to improve latency +- Running action as a sidecar, saves about ~100ms on average trips from the action server on the concluded tests. Results may vary depending on the number of calls made to the action server. +- Sanic Workers must be mapped 1:1 to CPU for both Rasa Pro and Rasa Action Server +- Create `async` actions to avoid any blocking I/O +- Use KEDA for pre-emptive autoscaling of rasa pods in production based on http requests +- `enable_selective_domain: true` : Domain is only sent for actions that needs it. This massively trims the payload between the two pods. +- Consider using c5n.nxlarge machines which are more compute optimized and support better parallelization on http requests. + However, as they are low on memory, models need to be trained lightweight. + Not suitable if you want to run transformers + ### Debugging bot related issues while scaling up From ecdd8bee99f69fcf5a285abda6fa3ab2ecc11ed0 Mon Sep 17 00:00:00 2001 From: Tanja Date: Thu, 21 Dec 2023 10:20:13 +0100 Subject: [PATCH 09/19] [ENG-712] Fix dependency install failures on windows (#150) * prevent race condition in poetry build * update makefile --- .github/workflows/continous-integration.yml | 6 ++++++ Makefile | 2 +- changelog/712.misc.md | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 changelog/712.misc.md diff --git a/.github/workflows/continous-integration.yml b/.github/workflows/continous-integration.yml index ea3d194566a3..b50753b1dffb 100644 --- a/.github/workflows/continous-integration.yml +++ b/.github/workflows/continous-integration.yml @@ -287,6 +287,12 @@ jobs: run: | poetry self add setuptools + - name: Prevent race condition in poetry build + # More context about race condition during poetry build can be found here: + # https://github.com/python-poetry/poetry/issues/7611#issuecomment-1747836233 + run: | + poetry config installer.max-workers 1 + - name: Load Poetry Cached Libraries ⬇ id: cache-poetry if: needs.changes.outputs.backend == 'true' diff --git a/Makefile b/Makefile index f3ebb6135e25..23b5799e1d5f 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ prepare-tests-windows: # It will retry the installation 5 times if it fails # See: https://github.com/actions/virtual-environments/blob/main/images/win/scripts/ImageHelpers/ChocoHelpers.ps1 prepare-tests-windows-gha: - powershell -command "Choco-Install wget graphviz" + powershell -command "Install-ChocoPackage wget graphviz" test: clean # OMP_NUM_THREADS can improve overall performance using one thread by process (on tensorflow), avoiding overload diff --git a/changelog/712.misc.md b/changelog/712.misc.md new file mode 100644 index 000000000000..020a19afe7f1 --- /dev/null +++ b/changelog/712.misc.md @@ -0,0 +1 @@ +Prevent race condition in poetry build to fix dependency install failures on windows. From 96eead79cce0aa7936dfd4827fc2dba5a56ed901 Mon Sep 17 00:00:00 2001 From: Tawakalt Date: Fri, 29 Dec 2023 22:49:27 +0100 Subject: [PATCH 10/19] update cryptography --- poetry.lock | 50 +++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/poetry.lock b/poetry.lock index b347db8c13bf..0f266f79a5ae 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1090,35 +1090,35 @@ yaml = ["PyYAML (>=3.10)"] [[package]] name = "cryptography" -version = "41.0.3" +version = "41.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, - {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, - {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, - {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, + {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, + {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, + {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, ] [package.dependencies] @@ -7231,4 +7231,4 @@ transformers = ["sentencepiece", "transformers"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.11" -content-hash = "71bfb81a213fc85cbf7fe0ac10a9ac16363fd14c18647e1f0ee26b35e73e0747" +content-hash = "d38a12f16b69e12490c4ad2cebda4f8b8a9bdb45f6cdd883b44b4754dbf424c5" diff --git a/pyproject.toml b/pyproject.toml index 904736791eeb..efa2bce4abc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,7 +154,7 @@ structlog-sentry = "^2.0.2" dnspython = "2.3.0" wheel = ">=0.38.1" certifi = ">=2023.7.22" -cryptography = ">=41.0.2" +cryptography = ">=41.0.7" [[tool.poetry.dependencies.tensorflow-io-gcs-filesystem]] version = "==0.31" markers = "sys_platform == 'win32'" From 45cbefd0a901160376af4ceef83583ad8244ccc2 Mon Sep 17 00:00:00 2001 From: Tawakalt Date: Tue, 2 Jan 2024 11:34:22 +0100 Subject: [PATCH 11/19] add changelog --- changelog/12983.bugfix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/12983.bugfix.md diff --git a/changelog/12983.bugfix.md b/changelog/12983.bugfix.md new file mode 100644 index 000000000000..5de8934cfe59 --- /dev/null +++ b/changelog/12983.bugfix.md @@ -0,0 +1 @@ +Upgrade Cryptography to fix improper certificate validation. \ No newline at end of file From 652c1756ab695b55eb0c199ebe3a190482fdb29c Mon Sep 17 00:00:00 2001 From: sancharigr Date: Thu, 4 Jan 2024 20:25:20 +0530 Subject: [PATCH 12/19] Review changes made --- .../monitoring/load-testing-guidelines.mdx | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/docs/docs/monitoring/load-testing-guidelines.mdx b/docs/docs/monitoring/load-testing-guidelines.mdx index 23b104917177..a794d73639da 100644 --- a/docs/docs/monitoring/load-testing-guidelines.mdx +++ b/docs/docs/monitoring/load-testing-guidelines.mdx @@ -12,33 +12,24 @@ In order to gather metrics on our system's ability to handle increased loads and In each test case we spawned the following number of concurrent users at peak concurrency using a [spawn rate](https://docs.locust.io/en/1.5.0/configuration.html#all-available-configuration-options) of 1000 users per second. In our tests we used the Rasa [HTTP-API](https://rasa.com/docs/rasa/pages/http-api) and the [Locust](https://locust.io/) open source load testing tool. + | Users | CPU | Memory | |--------------------------|----------------------------------------------|---------------| | Up to 50,000 | 6vCPU | 16 GB | | Up to 80,000 | 6vCPU, with almost 90% CPU usage | 16 GB | -:::info This is the most optimal AWS setup tested on EKS with - -ec2: c5.2xlarge - 9.2rps/node throughput -ec2: c5.4xlarge - 19.5rps/node throughput -You can always choose a bigger compute efficient instance like c5.4xlarge with more CPU per node to maximize throughput per node - -::: - -| AWS | RasaPro | Rasa Action Server | -|--------------------------|----------------------------------------------|-------------------------------------------| -| EC2: C52xlarge | 3vCPU, 10Gb Memory, 3 Sanic Threads | 3vCPU, 2Gb Memory, 3 Sanic Threads | -| EC2: C54xlarge | 7vCPU, 16Gb Memory, 7 Sanic Threads | 7vCPU, 12Gb Memory, 7 Sanic Threads | ### Some recommendations to improve latency -- Running action as a sidecar, saves about ~100ms on average trips from the action server on the concluded tests. Results may vary depending on the number of calls made to the action server. - Sanic Workers must be mapped 1:1 to CPU for both Rasa Pro and Rasa Action Server - Create `async` actions to avoid any blocking I/O -- Use KEDA for pre-emptive autoscaling of rasa pods in production based on http requests - `enable_selective_domain: true` : Domain is only sent for actions that needs it. This massively trims the payload between the two pods. -- Consider using c5n.nxlarge machines which are more compute optimized and support better parallelization on http requests. +- Consider using compute efficient machines on cloud which are optimized for high performance computing such as the C5 instances on AWS. However, as they are low on memory, models need to be trained lightweight. - Not suitable if you want to run transformers + + +| Machine | RasaPro | Rasa Action Server | +|--------------------------------|------------------------------------------------|--------------------------------------------------| +| AWS C5 or Azure F or Gcloud C2 | 3-7vCPU, 10-16Gb Memory, 3-7 Sanic Threads | 3-7vCPU, 2-12Gb Memory, 3-7 Sanic Threads | ### Debugging bot related issues while scaling up From 64546fcf70be2754e75550016c9e8916e898aa09 Mon Sep 17 00:00:00 2001 From: sancharigr Date: Fri, 5 Jan 2024 11:28:01 +0530 Subject: [PATCH 13/19] Add missing CI step condition --- .github/workflows/continous-integration.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/continous-integration.yml b/.github/workflows/continous-integration.yml index b50753b1dffb..587ad2ad26e4 100644 --- a/.github/workflows/continous-integration.yml +++ b/.github/workflows/continous-integration.yml @@ -290,6 +290,7 @@ jobs: - name: Prevent race condition in poetry build # More context about race condition during poetry build can be found here: # https://github.com/python-poetry/poetry/issues/7611#issuecomment-1747836233 + if: needs.changes.outputs.backend == 'true' run: | poetry config installer.max-workers 1 From 8f916e94faf43e4a9d5a240b29634afe701c6a30 Mon Sep 17 00:00:00 2001 From: sancharigr Date: Thu, 11 Jan 2024 18:32:19 +0530 Subject: [PATCH 14/19] Edit docs workflow to release docs for 3.6.x --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 3e1a31913f6d..076f44d0c612 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -82,7 +82,7 @@ jobs: echo "build_docs=true" >> $GITHUB_OUTPUT else # Get latest tagged Rasa version - git fetch --depth=1 origin "+refs/tags/*:refs/tags/*" + git describe --tags --match="3.6.[0-9]*" --abbrev=0 HEAD # Fetch branch history TAG_NAME=${GITHUB_REF#refs/tags/} git fetch --prune --unshallow From e970b3a721ed87186edfb6e38069a49e971bea22 Mon Sep 17 00:00:00 2001 From: m-vdb Date: Tue, 16 Jan 2024 08:47:09 +0100 Subject: [PATCH 15/19] update changelog with entries from 3.5.x releases --- CHANGELOG.mdx | 113 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.mdx b/CHANGELOG.mdx index fce125567d98..60752d9d683d 100644 --- a/CHANGELOG.mdx +++ b/CHANGELOG.mdx @@ -17,37 +17,37 @@ https://github.com/RasaHQ/rasa/tree/main/changelog/ . --> ## [3.6.15] - 2023-11-30 - -Rasa 3.6.15 (2023-11-30) + +Rasa 3.6.15 (2023-11-30) ### Bugfixes - [#12965](https://github.com/rasahq/rasa/issues/12965): Fixed connection timeout to action server by setting KEEP_ALIVE_TIMEOUT to 120, and reverting changes introduced in #12886. ## [3.6.14] - 2023-11-17 - -Rasa 3.6.14 (2023-11-17) + +Rasa 3.6.14 (2023-11-17) ### Bugfixes - [#12948](https://github.com/rasahq/rasa/issues/12948): Fixed UnexpecTEDIntentlessPolicy training errors that resulted from a change to batching behavior. Changed the batching behavior back to the original for all components. Made the changed batching behavior accessible in DietClassifier using `drop_small_last_batch: True`. ## [3.6.13] - 2023-10-23 - -Rasa 3.6.13 (2023-10-23) + +Rasa 3.6.13 (2023-10-23) ### Bugfixes - [#12927](https://github.com/rasahq/rasa/issues/12927): Fix wrong conflicts that occur when rasa validate stories is run with slots that have active_loop set to null in mapping conditions. ## [3.6.12] - 2023-10-10 - -Rasa 3.6.12 (2023-10-10) + +Rasa 3.6.12 (2023-10-10) ### Bugfixes - [#12904](https://github.com/rasahq/rasa/issues/12904): Refresh headers used in requests (e.g. action server requests) made by `EndpointConfig` using its `headers` attribute. - [#12906](https://github.com/rasahq/rasa/issues/12906): Upgrade `pillow` to `10.0.1` to address security vulnerability CVE-2023-4863 found in `10.0.0` version. ## [3.6.11] - 2023-10-05 - -Rasa 3.6.11 (2023-10-05) + +Rasa 3.6.11 (2023-10-05) ### Bugfixes - [#12722](https://github.com/rasahq/rasa/issues/12722): Intent names will not be falsely abbreviated in interactive training (fixes OSS-413). @@ -59,8 +59,8 @@ Rasa 3.6.11 (2023-10-05) ## [3.6.10] - 2023-09-26 - -Rasa 3.6.10 (2023-09-26) + +Rasa 3.6.10 (2023-09-26) ### Improvements - [#12827](https://github.com/rasahq/rasa/issues/12827): Improved handling of last batch during DIET and TED training. The last batch is discarded if it contains less than half a batch size of data. - [#12852](https://github.com/rasahq/rasa/issues/12852): Added `username` to the connection parameters for `RedisLockStore` and `RedisTrackerStore` @@ -71,8 +71,8 @@ Rasa 3.6.10 (2023-09-26) ## [3.6.9] - 2023-09-15 - -Rasa 3.6.9 (2023-09-15) + +Rasa 3.6.9 (2023-09-15) ### Improvements - [#12778](https://github.com/rasahq/rasa/issues/12778): Added additional method `fingerprint_addon` to the `GraphComponent` interface to allow inclusion of external data into the fingerprint calculation of a component @@ -81,29 +81,29 @@ Rasa 3.6.9 (2023-09-15) ## [3.6.8] - 2023-08-30 - -Rasa 3.6.8 (2023-08-30) + +Rasa 3.6.8 (2023-08-30) No significant changes. ## [3.6.7] - 2023-08-29 - -Rasa 3.6.7 (2023-08-29) + +Rasa 3.6.7 (2023-08-29) ### Bugfixes - [#12768](https://github.com/rasahq/rasa/issues/12768): Updated certifi, cryptography, and scipy packages to address security vulnerabilities. ## [3.6.6] - 2023-08-23 - -Rasa 3.6.6 (2023-08-23) + +Rasa 3.6.6 (2023-08-23) ### Bugfixes - [#12755](https://github.com/rasahq/rasa/issues/12755): Updated setuptools and wheel to address security vulnerabilities. ## [3.6.5] - 2023-08-17 - -Rasa 3.6.5 (2023-08-17) + +Rasa 3.6.5 (2023-08-17) ### Improvements - [#12696](https://github.com/rasahq/rasa/issues/12696): Use the same session across requests in `RasaNLUHttpInterpreter` @@ -116,8 +116,8 @@ Rasa 3.6.5 (2023-08-17) ## [3.6.4] - 2023-07-21 - -Rasa 3.6.4 (2023-07-21) + +Rasa 3.6.4 (2023-07-21) ### Bugfixes - [#12575](https://github.com/rasahq/rasa/issues/12575): Extract conditional response variation and channel variation filtering logic into a separate component. Enable usage of this component in the NaturalLanguageGenerator subclasses (e.g. CallbackNaturalLanguageGenerator, TemplatedNaturalLanguageGenerator). @@ -128,8 +128,8 @@ Rasa 3.6.4 (2023-07-21) ## [3.6.3] - 2023-07-20 - -Rasa 3.6.3 (2023-07-20) + +Rasa 3.6.3 (2023-07-20) ### Improvements - [#12637](https://github.com/rasahq/rasa/issues/12637): Added a human readable component to structlog using the `event_info` key and made it the default rendered key if present. @@ -144,15 +144,15 @@ Rasa 3.6.3 (2023-07-20) ## [3.6.2] - 2023-07-06 - -Rasa 3.6.2 (2023-07-06) + +Rasa 3.6.2 (2023-07-06) ### Bugfixes - [#12602](https://github.com/rasahq/rasa/issues/12602): Resolves the issue of importing TensorFlow on Docker for ARM64 architecture. ## [3.6.1] - 2023-07-03 - -Rasa 3.6.1 (2023-07-03) + +Rasa 3.6.1 (2023-07-03) ### Improvements - [#12533](https://github.com/rasahq/rasa/issues/12533): Add building multi-platform Docker image (amd64/arm64) - [#12543](https://github.com/rasahq/rasa/issues/12543): Switch struct log to `FilteringBoundLogger` in order to retain log level set in the config. @@ -174,8 +174,8 @@ Rasa 3.6.1 (2023-07-03) ## [3.6.0] - 2023-06-14 - -Rasa 3.6.0 (2023-06-14) + +Rasa 3.6.0 (2023-06-14) ### Deprecations and Removals - [#12355](https://github.com/rasahq/rasa/issues/12355): Removed Python 3.7 support as [it reaches its end of life in June 2023](https://devguide.python.org/versions/) @@ -219,6 +219,55 @@ Rasa 3.6.0 (2023-06-14) ### Miscellaneous internal changes - [#12291](https://github.com/rasahq/rasa/issues/12291), [#12329](https://github.com/rasahq/rasa/issues/12329), [#12332](https://github.com/rasahq/rasa/issues/12332), [#12365](https://github.com/rasahq/rasa/issues/12365), [#12372](https://github.com/rasahq/rasa/issues/12372), [#12386](https://github.com/rasahq/rasa/issues/12386), [#12492](https://github.com/rasahq/rasa/issues/12492) +## [3.5.17] - 2023-12-05 + +Rasa 3.5.17 (2023-12-05) +### Improvements +- [#12851](https://github.com/rasahq/rasa/issues/12851): Added `username` to the connection parameters for `RedisLockStore` and `RedisTrackerStore` +- [#1493](https://github.com/rasahq/rasa/issues/1493): Telemetry data is only send for licensed users. + + +## [3.5.16] - 2023-08-30 + +Rasa 3.5.16 (2023-08-30) + +No significant changes. + + +## [3.5.15] - 2023-07-21 + +Rasa 3.5.15 (2023-07-21) + +No significant changes. + + +## [3.5.14] - 2023-07-12 + +Rasa 3.5.14 (2023-07-12) +### Bugfixes +- [#12639](https://github.com/rasahq/rasa/issues/12639): Fix the issue with the most recent model not being selected if the owner or permissions where modified on the model file. + +### Miscellaneous internal changes +- [#12649](https://github.com/rasahq/rasa/issues/12649) + + +## [3.5.13] - 2023-07-05 + +Rasa 3.5.13 (2023-07-05) +### Bugfixes +- [#12549](https://github.com/rasahq/rasa/issues/12549): Introduce a validation step in `rasa data validate` command to identify non-existent paths and empty domains. + + +## [3.5.12] - 2023-06-23 + +Rasa 3.5.12 (2023-06-23) +### Bugfixes +- [#12534](https://github.com/rasahq/rasa/issues/12534): Rich responses containing buttons with parentheses characters are now correctly parsed. + Previously any characters found between the first identified pair of `()` in response button took precedence. + +### Miscellaneous internal changes +- [#12512](https://github.com/rasahq/rasa/issues/12512) + ## [3.5.11] - 2023-06-08 From ce1f5d2a31e55723fde1f522a5338eb51b840385 Mon Sep 17 00:00:00 2001 From: Shailendra Paliwal Date: Fri, 19 Jan 2024 11:56:21 +0100 Subject: [PATCH 16/19] Get Full Retrieval Intent Name (#12998) * update full retrieval intent name * format * add test for test_update_full_retrieval_intent * fix linting * fix the structure of dict --- rasa/core/processor.py | 22 +++++++++++++ tests/core/test_processor.py | 64 +++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/rasa/core/processor.py b/rasa/core/processor.py index ec6ef1260a3e..fc628c7a7247 100644 --- a/rasa/core/processor.py +++ b/rasa/core/processor.py @@ -66,7 +66,11 @@ ENTITIES, INTENT, INTENT_NAME_KEY, + INTENT_RESPONSE_KEY, PREDICTED_CONFIDENCE_KEY, + FULL_RETRIEVAL_INTENT_NAME_KEY, + RESPONSE_SELECTOR, + RESPONSE, TEXT, ) from rasa.utils.endpoints import EndpointConfig @@ -721,6 +725,7 @@ async def parse_message( message, tracker, only_output_properties ) + self._update_full_retrieval_intent(parse_data) structlogger.debug( "processor.message.parse", parse_data_text=copy.deepcopy(parse_data["text"]), @@ -732,6 +737,23 @@ async def parse_message( return parse_data + def _update_full_retrieval_intent(self, parse_data: Dict[Text, Any]) -> None: + """Update the parse data with the full retrieval intent. + + Args: + parse_data: Message parse data to update. + """ + intent_name = parse_data.get(INTENT, {}).get(INTENT_NAME_KEY) + response_selector = parse_data.get(RESPONSE_SELECTOR, {}) + all_retrieval_intents = response_selector.get("all_retrieval_intents", []) + if intent_name and intent_name in all_retrieval_intents: + retrieval_intent = ( + response_selector.get(intent_name, {}) + .get(RESPONSE, {}) + .get(INTENT_RESPONSE_KEY) + ) + parse_data[INTENT][FULL_RETRIEVAL_INTENT_NAME_KEY] = retrieval_intent + def _parse_message_with_graph( self, message: UserMessage, diff --git a/tests/core/test_processor.py b/tests/core/test_processor.py index 392d85c29745..d0581b1800ef 100644 --- a/tests/core/test_processor.py +++ b/tests/core/test_processor.py @@ -70,7 +70,12 @@ from rasa.core.http_interpreter import RasaNLUHttpInterpreter from rasa.core.processor import MessageProcessor from rasa.shared.core.trackers import DialogueStateTracker -from rasa.shared.nlu.constants import INTENT_NAME_KEY, METADATA_MODEL_ID +from rasa.shared.nlu.constants import ( + INTENT, + INTENT_NAME_KEY, + FULL_RETRIEVAL_INTENT_NAME_KEY, + METADATA_MODEL_ID, +) from rasa.shared.nlu.training_data.message import Message from rasa.utils.endpoints import EndpointConfig from rasa.shared.core.constants import ( @@ -1928,3 +1933,60 @@ async def test_run_anonymization_pipeline_mocked_pipeline( await processor.run_anonymization_pipeline(tracker) event_diff.assert_called_once() + + +async def test_update_full_retrieval_intent( + default_processor: MessageProcessor, +) -> None: + parse_data = { + "text": "I like sunny days in berlin", + "intent": {"name": "chitchat", "confidence": 0.9}, + "entities": [], + "response_selector": { + "all_retrieval_intents": ["faq", "chitchat"], + "faq": { + "response": { + "responses": [{"text": "Our return policy lasts 30 days."}], + "confidence": 1.0, + "intent_response_key": "faq/what_is_return_policy", + "utter_action": "utter_faq/what_is_return_policy", + }, + "ranking": [ + { + "confidence": 1.0, + "intent_response_key": "faq/what_is_return_policy", + }, + { + "confidence": 2.3378809862799945e-19, + "intent_response_key": "faq/how_can_i_track_my_order", + }, + ], + }, + "chitchat": { + "response": { + "responses": [ + { + "text": "The sun is out today! Isn't that great?", + }, + ], + "confidence": 1.0, + "intent_response_key": "chitchat/ask_weather", + "utter_action": "utter_chitchat/ask_weather", + }, + "ranking": [ + { + "confidence": 1.0, + "intent_response_key": "chitchat/ask_weather", + }, + {"confidence": 0.0, "intent_response_key": "chitchat/ask_name"}, + ], + }, + }, + } + + default_processor._update_full_retrieval_intent(parse_data) + + assert parse_data[INTENT][INTENT_NAME_KEY] == "chitchat" + # assert that parse_data["intent"] has a key called response + assert FULL_RETRIEVAL_INTENT_NAME_KEY in parse_data[INTENT] + assert parse_data[INTENT][FULL_RETRIEVAL_INTENT_NAME_KEY] == "chitchat/ask_weather" From 5339fae00c1cb527ba778916fd8b5e5d785b7d50 Mon Sep 17 00:00:00 2001 From: Shailendra Paliwal Date: Fri, 19 Jan 2024 12:23:27 +0100 Subject: [PATCH 17/19] add changelog (#13000) --- changelog/12998.bugfix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/12998.bugfix.md diff --git a/changelog/12998.bugfix.md b/changelog/12998.bugfix.md new file mode 100644 index 000000000000..63280d49c42d --- /dev/null +++ b/changelog/12998.bugfix.md @@ -0,0 +1 @@ +Fixes a bug that caused the `full_retrieval_intent_name` key to be missing in the published event. Rasa Analytics makes use of this key to get the Retrieval Intent Name \ No newline at end of file From 26210847931f4df166896f6ce4eb0334e093e23c Mon Sep 17 00:00:00 2001 From: Shailendra Paliwal Date: Fri, 19 Jan 2024 14:06:31 +0100 Subject: [PATCH 18/19] prepared release of version 3.6.16 (#13003) --- CHANGELOG.mdx | 11 +++++++++++ changelog/12983.bugfix.md | 1 - changelog/12998.bugfix.md | 1 - changelog/712.misc.md | 1 - pyproject.toml | 2 +- rasa/version.py | 2 +- 6 files changed, 13 insertions(+), 5 deletions(-) delete mode 100644 changelog/12983.bugfix.md delete mode 100644 changelog/12998.bugfix.md delete mode 100644 changelog/712.misc.md diff --git a/CHANGELOG.mdx b/CHANGELOG.mdx index 60752d9d683d..b3411889c069 100644 --- a/CHANGELOG.mdx +++ b/CHANGELOG.mdx @@ -16,6 +16,17 @@ https://github.com/RasaHQ/rasa/tree/main/changelog/ . --> +## [3.6.16] - 2024-01-19 + +Rasa 3.6.16 (2024-01-19) +### Bugfixes +- [#12983](https://github.com/rasahq/rasa/issues/12983): Upgrade Cryptography to fix improper certificate validation. +- [#12998](https://github.com/rasahq/rasa/issues/12998): Fixes a bug that caused the `full_retrieval_intent_name` key to be missing in the published event. Rasa Analytics makes use of this key to get the Retrieval Intent Name + +### Miscellaneous internal changes +- [#712](https://github.com/rasahq/rasa/issues/712) + + ## [3.6.15] - 2023-11-30 Rasa 3.6.15 (2023-11-30) diff --git a/changelog/12983.bugfix.md b/changelog/12983.bugfix.md deleted file mode 100644 index 5de8934cfe59..000000000000 --- a/changelog/12983.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Upgrade Cryptography to fix improper certificate validation. \ No newline at end of file diff --git a/changelog/12998.bugfix.md b/changelog/12998.bugfix.md deleted file mode 100644 index 63280d49c42d..000000000000 --- a/changelog/12998.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Fixes a bug that caused the `full_retrieval_intent_name` key to be missing in the published event. Rasa Analytics makes use of this key to get the Retrieval Intent Name \ No newline at end of file diff --git a/changelog/712.misc.md b/changelog/712.misc.md deleted file mode 100644 index 020a19afe7f1..000000000000 --- a/changelog/712.misc.md +++ /dev/null @@ -1 +0,0 @@ -Prevent race condition in poetry build to fix dependency install failures on windows. diff --git a/pyproject.toml b/pyproject.toml index bd34f9e7ec4b..7b695117b412 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ exclude = "((.eggs | .git | .pytest_cache | build | dist))" [tool.poetry] name = "rasa" -version = "3.6.15" +version = "3.6.16" description = "Open source machine learning framework to automate text- and voice-based conversations: NLU, dialogue management, connect to Slack, Facebook, and more - Create chatbots and voice assistants" authors = [ "Rasa Technologies GmbH ",] maintainers = [ "Tom Bocklisch ",] diff --git a/rasa/version.py b/rasa/version.py index 3d8e9f0ee007..fc234e58601b 100644 --- a/rasa/version.py +++ b/rasa/version.py @@ -1,3 +1,3 @@ # this file will automatically be changed, # do not add anything but the version number here! -__version__ = "3.6.15" +__version__ = "3.6.16" From 6049b2b3b7c46b7083ddff4f46c24861d04b4dbb Mon Sep 17 00:00:00 2001 From: vcidst Date: Mon, 5 Feb 2024 10:39:54 +0100 Subject: [PATCH 19/19] add newline --- rasa/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rasa/version.py b/rasa/version.py index 5f3b63749434..fc234e58601b 100644 --- a/rasa/version.py +++ b/rasa/version.py @@ -1,3 +1,3 @@ # this file will automatically be changed, # do not add anything but the version number here! -__version__ = "3.6.16" \ No newline at end of file +__version__ = "3.6.16"