rasa-pro 3.14.0.dev20250922__py3-none-any.whl → 3.14.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/__main__.py +15 -3
- rasa/agents/__init__.py +0 -0
- rasa/agents/agent_factory.py +122 -0
- rasa/agents/agent_manager.py +211 -0
- rasa/agents/constants.py +43 -0
- rasa/agents/core/__init__.py +0 -0
- rasa/agents/core/agent_protocol.py +107 -0
- rasa/agents/core/types.py +81 -0
- rasa/agents/exceptions.py +38 -0
- rasa/agents/protocol/__init__.py +5 -0
- rasa/agents/protocol/a2a/__init__.py +0 -0
- rasa/agents/protocol/a2a/a2a_agent.py +879 -0
- rasa/agents/protocol/mcp/__init__.py +0 -0
- rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
- rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
- rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
- rasa/agents/schemas/__init__.py +13 -0
- rasa/agents/schemas/agent_input.py +38 -0
- rasa/agents/schemas/agent_output.py +26 -0
- rasa/agents/schemas/agent_tool_result.py +65 -0
- rasa/agents/schemas/agent_tool_schema.py +186 -0
- rasa/agents/templates/__init__.py +0 -0
- rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
- rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
- rasa/agents/utils.py +206 -0
- rasa/agents/validation.py +485 -0
- rasa/api.py +24 -9
- rasa/builder/config.py +6 -2
- rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
- rasa/builder/guardrails/constants.py +3 -0
- rasa/builder/guardrails/models.py +45 -10
- rasa/builder/guardrails/policy_checker.py +324 -0
- rasa/builder/guardrails/utils.py +42 -276
- rasa/builder/llm_service.py +32 -5
- rasa/builder/models.py +1 -0
- rasa/builder/project_generator.py +6 -1
- rasa/builder/service.py +16 -13
- rasa/builder/training_service.py +18 -24
- rasa/builder/validation_service.py +1 -1
- rasa/cli/arguments/default_arguments.py +12 -0
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/data.py +10 -8
- rasa/cli/dialogue_understanding_test.py +10 -7
- rasa/cli/e2e_test.py +9 -6
- rasa/cli/evaluate.py +4 -2
- rasa/cli/export.py +5 -2
- rasa/cli/inspect.py +8 -4
- rasa/cli/interactive.py +5 -4
- rasa/cli/llm_fine_tuning.py +11 -6
- rasa/cli/project_templates/tutorial/credentials.yml +10 -0
- rasa/cli/run.py +12 -10
- rasa/cli/scaffold.py +4 -4
- rasa/cli/shell.py +9 -5
- rasa/cli/studio/studio.py +1 -1
- rasa/cli/test.py +34 -14
- rasa/cli/train.py +41 -28
- rasa/cli/utils.py +1 -393
- rasa/cli/validation/__init__.py +0 -0
- rasa/cli/validation/bot_config.py +223 -0
- rasa/cli/validation/config_path_validation.py +257 -0
- rasa/cli/x.py +8 -4
- rasa/constants.py +7 -1
- rasa/core/actions/action.py +51 -10
- rasa/core/actions/grpc_custom_action_executor.py +1 -1
- rasa/core/agent.py +19 -2
- rasa/core/available_agents.py +229 -0
- rasa/core/channels/__init__.py +82 -35
- rasa/core/channels/development_inspector.py +3 -3
- rasa/core/channels/inspector/README.md +25 -13
- rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +18 -18
- rasa/core/channels/inspector/src/App.tsx +29 -4
- rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
- rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
- rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
- rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
- rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
- rasa/core/channels/inspector/src/types.ts +21 -0
- rasa/core/channels/inspector/yarn.lock +336 -189
- rasa/core/channels/studio_chat.py +6 -6
- rasa/core/channels/telegram.py +4 -9
- rasa/core/channels/voice_stream/genesys.py +1 -1
- rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
- rasa/core/channels/voice_stream/voice_channel.py +3 -0
- rasa/core/config/__init__.py +0 -0
- rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
- rasa/core/config/configuration.py +260 -0
- rasa/core/config/credentials.py +19 -0
- rasa/core/config/message_procesing_config.py +34 -0
- rasa/core/constants.py +4 -0
- rasa/core/policies/enterprise_search_policy.py +5 -3
- rasa/core/policies/flow_policy.py +4 -4
- rasa/core/policies/flows/agent_executor.py +632 -0
- rasa/core/policies/flows/flow_executor.py +136 -75
- rasa/core/policies/flows/mcp_tool_executor.py +298 -0
- rasa/core/policies/intentless_policy.py +1 -1
- rasa/core/policies/ted_policy.py +20 -12
- rasa/core/policies/unexpected_intent_policy.py +6 -0
- rasa/core/processor.py +68 -44
- rasa/core/run.py +37 -8
- rasa/core/test.py +4 -0
- rasa/core/tracker_stores/tracker_store.py +3 -7
- rasa/core/train.py +1 -1
- rasa/core/training/interactive.py +20 -18
- rasa/core/training/story_conflict.py +5 -5
- rasa/core/utils.py +22 -23
- rasa/dialogue_understanding/commands/__init__.py +8 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/clarify_command.py +20 -2
- rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
- rasa/dialogue_understanding/commands/utils.py +124 -2
- rasa/dialogue_understanding/generator/command_parser.py +4 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
- rasa/dialogue_understanding/patterns/cancel.py +27 -6
- rasa/dialogue_understanding/patterns/clarify.py +3 -14
- rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
- rasa/dialogue_understanding/processor/command_processor.py +136 -15
- rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
- rasa/dialogue_understanding/stack/utils.py +57 -3
- rasa/dialogue_understanding/utils.py +24 -4
- rasa/dialogue_understanding_test/du_test_runner.py +8 -3
- rasa/e2e_test/e2e_test_runner.py +13 -3
- rasa/engine/caching.py +2 -2
- rasa/engine/constants.py +1 -1
- rasa/engine/recipes/default_components.py +138 -49
- rasa/engine/recipes/default_recipe.py +108 -11
- rasa/engine/runner/dask.py +8 -5
- rasa/engine/validation.py +19 -6
- rasa/graph_components/validators/default_recipe_validator.py +86 -28
- rasa/hooks.py +5 -5
- rasa/llm_fine_tuning/utils.py +2 -2
- rasa/model_training.py +60 -47
- rasa/nlu/classifiers/diet_classifier.py +198 -98
- rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
- rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
- rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
- rasa/nlu/extractors/crf_entity_extractor.py +9 -10
- rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
- rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
- rasa/nlu/selectors/response_selector.py +10 -2
- rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
- rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
- rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
- rasa/nlu/utils/mitie_utils.py +3 -0
- rasa/nlu/utils/spacy_utils.py +3 -2
- rasa/plugin.py +8 -8
- rasa/privacy/privacy_manager.py +12 -3
- rasa/server.py +15 -3
- rasa/shared/agents/__init__.py +0 -0
- rasa/shared/agents/auth/__init__.py +0 -0
- rasa/shared/agents/auth/agent_auth_factory.py +105 -0
- rasa/shared/agents/auth/agent_auth_manager.py +92 -0
- rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
- rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
- rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
- rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
- rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
- rasa/shared/agents/auth/constants.py +12 -0
- rasa/shared/agents/auth/types.py +12 -0
- rasa/shared/agents/utils.py +35 -0
- rasa/shared/constants.py +8 -0
- rasa/shared/core/constants.py +16 -1
- rasa/shared/core/domain.py +0 -7
- rasa/shared/core/events.py +327 -0
- rasa/shared/core/flows/constants.py +5 -0
- rasa/shared/core/flows/flows_list.py +21 -5
- rasa/shared/core/flows/flows_yaml_schema.json +119 -184
- rasa/shared/core/flows/steps/call.py +49 -5
- rasa/shared/core/flows/steps/collect.py +98 -13
- rasa/shared/core/flows/validation.py +372 -8
- rasa/shared/core/flows/yaml_flows_io.py +3 -2
- rasa/shared/core/slots.py +2 -2
- rasa/shared/core/trackers.py +5 -2
- rasa/shared/exceptions.py +16 -0
- rasa/shared/importers/rasa.py +1 -1
- rasa/shared/importers/utils.py +9 -3
- rasa/shared/providers/llm/_base_litellm_client.py +41 -9
- rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
- rasa/shared/providers/llm/llm_client.py +7 -3
- rasa/shared/providers/llm/llm_response.py +66 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
- rasa/shared/utils/common.py +24 -0
- rasa/shared/utils/health_check/health_check.py +7 -3
- rasa/shared/utils/llm.py +39 -16
- rasa/shared/utils/mcp/__init__.py +0 -0
- rasa/shared/utils/mcp/server_connection.py +247 -0
- rasa/shared/utils/mcp/utils.py +20 -0
- rasa/shared/utils/schemas/events.py +42 -0
- rasa/shared/utils/yaml.py +3 -1
- rasa/studio/pull/pull.py +3 -2
- rasa/studio/train.py +8 -7
- rasa/studio/upload.py +3 -6
- rasa/telemetry.py +69 -5
- rasa/tracing/config.py +45 -12
- rasa/tracing/constants.py +14 -0
- rasa/tracing/instrumentation/attribute_extractors.py +142 -9
- rasa/tracing/instrumentation/instrumentation.py +626 -21
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
- rasa/tracing/instrumentation/metrics.py +32 -0
- rasa/tracing/metric_instrument_provider.py +68 -0
- rasa/utils/common.py +92 -1
- rasa/utils/endpoints.py +11 -2
- rasa/utils/log_utils.py +96 -5
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/tensorflow/__init__.py +7 -0
- rasa/utils/tensorflow/callback.py +136 -101
- rasa/utils/tensorflow/crf.py +1 -1
- rasa/utils/tensorflow/data_generator.py +21 -8
- rasa/utils/tensorflow/layers.py +21 -11
- rasa/utils/tensorflow/metrics.py +7 -3
- rasa/utils/tensorflow/models.py +56 -8
- rasa/utils/tensorflow/rasa_layers.py +8 -6
- rasa/utils/tensorflow/transformer.py +2 -3
- rasa/utils/train_utils.py +54 -24
- rasa/validator.py +5 -5
- rasa/version.py +1 -1
- {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/METADATA +46 -41
- {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/RECORD +285 -226
- rasa/builder/scrape_rasa_docs.py +0 -97
- rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
- {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/entry_points.txt +0 -0
|
@@ -2,111 +2,146 @@ import logging
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Any, Dict, Optional, Text
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
from rasa.utils.tensorflow import TENSORFLOW_AVAILABLE
|
|
6
|
+
|
|
7
|
+
if TENSORFLOW_AVAILABLE:
|
|
8
|
+
import tensorflow as tf
|
|
9
|
+
from tqdm import tqdm
|
|
10
|
+
else:
|
|
11
|
+
# Placeholder values when TensorFlow is not available
|
|
12
|
+
tf = None
|
|
13
|
+
tqdm = None
|
|
7
14
|
|
|
8
15
|
import rasa.shared.utils.io
|
|
9
16
|
|
|
10
17
|
logger = logging.getLogger(__name__)
|
|
11
18
|
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
epoch:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
20
|
+
if TENSORFLOW_AVAILABLE:
|
|
21
|
+
|
|
22
|
+
class RasaTrainingLogger(tf.keras.callbacks.Callback):
|
|
23
|
+
"""Callback for logging the status of training."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, epochs: int, silent: bool) -> None:
|
|
26
|
+
"""Initializes the callback.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
epochs: Total number of epochs.
|
|
30
|
+
silent: If 'True' the entire progressbar wrapper is disabled.
|
|
31
|
+
"""
|
|
32
|
+
super().__init__()
|
|
33
|
+
|
|
34
|
+
disable = silent or rasa.shared.utils.io.is_logging_disabled()
|
|
35
|
+
self.progress_bar = tqdm(range(epochs), desc="Epochs", disable=disable)
|
|
36
|
+
|
|
37
|
+
def on_epoch_end(
|
|
38
|
+
self, epoch: int, logs: Optional[Dict[Text, Any]] = None
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Updates the logging output on every epoch end.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
epoch: The current epoch.
|
|
44
|
+
logs: The training metrics.
|
|
45
|
+
"""
|
|
46
|
+
self.progress_bar.update(1)
|
|
47
|
+
self.progress_bar.set_postfix(logs)
|
|
48
|
+
|
|
49
|
+
def on_train_end(self, logs: Optional[Dict[Text, Any]] = None) -> None:
|
|
50
|
+
"""Closes the progress bar after training.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
logs: The training metrics.
|
|
54
|
+
"""
|
|
55
|
+
self.progress_bar.close()
|
|
56
|
+
|
|
57
|
+
class RasaModelCheckpoint(tf.keras.callbacks.Callback):
|
|
58
|
+
"""Callback for saving intermediate model checkpoints."""
|
|
59
|
+
|
|
60
|
+
def __init__(self, checkpoint_dir: Path) -> None:
|
|
61
|
+
"""Initializes the callback.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
checkpoint_dir: Directory to store checkpoints to.
|
|
65
|
+
"""
|
|
66
|
+
super().__init__()
|
|
67
|
+
|
|
68
|
+
self.checkpoint_file = checkpoint_dir / "checkpoint.weights.h5"
|
|
69
|
+
self.best_metrics_so_far: Dict[Text, Any] = {}
|
|
70
|
+
|
|
71
|
+
def on_epoch_end(
|
|
72
|
+
self, epoch: int, logs: Optional[Dict[Text, Any]] = None
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Save the model on epoch end if the model has improved.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
epoch: The current epoch.
|
|
78
|
+
logs: The training metrics.
|
|
79
|
+
"""
|
|
80
|
+
if self._does_model_improve(logs):
|
|
81
|
+
logger.debug(f"Creating model checkpoint at epoch={epoch + 1} ...")
|
|
82
|
+
# Ensure model is built before saving weights
|
|
83
|
+
if not self.model.built:
|
|
84
|
+
# Build the model with dummy data to ensure it's built
|
|
85
|
+
import tensorflow as tf
|
|
86
|
+
|
|
87
|
+
dummy_input = tf.zeros((1, 1))
|
|
88
|
+
_ = self.model(dummy_input)
|
|
89
|
+
|
|
90
|
+
# Ensure the directory exists before saving
|
|
91
|
+
import os
|
|
92
|
+
|
|
93
|
+
os.makedirs(os.path.dirname(self.checkpoint_file), exist_ok=True)
|
|
94
|
+
self.model.save_weights(self.checkpoint_file, overwrite=True)
|
|
95
|
+
|
|
96
|
+
def _does_model_improve(self, curr_results: Dict[Text, Any]) -> bool:
|
|
97
|
+
"""Checks whether the current results are better than the best so far.
|
|
98
|
+
|
|
99
|
+
Results are considered better if each metric is
|
|
100
|
+
equal or better than the best so far, and at least one is better.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
curr_results: The training metrics for this epoch.
|
|
104
|
+
"""
|
|
105
|
+
curr_metric_names = [
|
|
106
|
+
k
|
|
107
|
+
for k in curr_results.keys()
|
|
108
|
+
if k.startswith("val") and (k.endswith("_acc") or k.endswith("_f1"))
|
|
109
|
+
]
|
|
110
|
+
# the "val" prefix is prepended to metrics in fit
|
|
111
|
+
# if _should_eval returns true
|
|
112
|
+
# for this particular epoch
|
|
113
|
+
if len(curr_metric_names) == 0:
|
|
114
|
+
# the metrics are not validation metrics
|
|
104
115
|
return False
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
# initialize best_metrics_so_far with the first results
|
|
117
|
+
if not self.best_metrics_so_far:
|
|
118
|
+
for metric_name in curr_metric_names:
|
|
119
|
+
self.best_metrics_so_far[metric_name] = float(
|
|
120
|
+
curr_results[metric_name]
|
|
121
|
+
)
|
|
122
|
+
return True
|
|
123
|
+
|
|
124
|
+
at_least_one_improved = False
|
|
125
|
+
improved_metrics = {}
|
|
126
|
+
for metric_name in self.best_metrics_so_far.keys():
|
|
127
|
+
if (
|
|
128
|
+
float(curr_results[metric_name])
|
|
129
|
+
< self.best_metrics_so_far[metric_name]
|
|
130
|
+
):
|
|
131
|
+
# at least one of the values is worse
|
|
132
|
+
return False
|
|
133
|
+
if (
|
|
134
|
+
float(curr_results[metric_name])
|
|
135
|
+
> self.best_metrics_so_far[metric_name]
|
|
136
|
+
):
|
|
137
|
+
at_least_one_improved = True
|
|
138
|
+
improved_metrics[metric_name] = float(curr_results[metric_name])
|
|
139
|
+
|
|
140
|
+
# all current values >= previous best and at least one is better
|
|
141
|
+
if at_least_one_improved:
|
|
142
|
+
self.best_metrics_so_far.update(improved_metrics)
|
|
143
|
+
return at_least_one_improved
|
|
144
|
+
else:
|
|
145
|
+
# Placeholder classes when TensorFlow is not available
|
|
146
|
+
RasaTrainingLogger = None # type: ignore
|
|
147
|
+
RasaModelCheckpoint = None # type: ignore
|
rasa/utils/tensorflow/crf.py
CHANGED
|
@@ -9,7 +9,7 @@ from tensorflow.types.experimental import TensorLike
|
|
|
9
9
|
# (modified to our neeeds)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class CrfDecodeForwardRnnCell(tf.keras.layers.
|
|
12
|
+
class CrfDecodeForwardRnnCell(tf.keras.layers.Layer):
|
|
13
13
|
"""Computes the forward decoding in a linear-chain CRF."""
|
|
14
14
|
|
|
15
15
|
def __init__(self, transition_params: TensorLike, **kwargs: Any) -> None:
|
|
@@ -71,13 +71,22 @@ class RasaDataGenerator(Sequence):
|
|
|
71
71
|
# balancing on the next epoch
|
|
72
72
|
return data
|
|
73
73
|
|
|
74
|
+
@staticmethod
|
|
75
|
+
def _create_default_array() -> np.ndarray:
|
|
76
|
+
"""Create a default empty array for missing features.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
A default empty array with shape (0, 1) and dtype float32.
|
|
80
|
+
"""
|
|
81
|
+
return np.zeros((0, 1), dtype=np.float32)
|
|
82
|
+
|
|
74
83
|
@staticmethod
|
|
75
84
|
def prepare_batch(
|
|
76
85
|
data: Data,
|
|
77
86
|
start: Optional[int] = None,
|
|
78
87
|
end: Optional[int] = None,
|
|
79
88
|
tuple_sizes: Optional[Dict[Text, int]] = None,
|
|
80
|
-
) -> Tuple[
|
|
89
|
+
) -> Tuple[np.ndarray, ...]:
|
|
81
90
|
"""Slices model data into batch using given start and end value.
|
|
82
91
|
|
|
83
92
|
Args:
|
|
@@ -85,8 +94,8 @@ class RasaDataGenerator(Sequence):
|
|
|
85
94
|
start: The start index of the batch
|
|
86
95
|
end: The end index of the batch
|
|
87
96
|
tuple_sizes: In case the feature is not present we propagate the batch with
|
|
88
|
-
|
|
89
|
-
what kind of feature.
|
|
97
|
+
default arrays. Tuple sizes contains the number of how many default values
|
|
98
|
+
to add for what kind of feature.
|
|
90
99
|
|
|
91
100
|
Returns:
|
|
92
101
|
The features of the batch.
|
|
@@ -95,12 +104,14 @@ class RasaDataGenerator(Sequence):
|
|
|
95
104
|
|
|
96
105
|
for key, attribute_data in data.items():
|
|
97
106
|
for sub_key, f_data in attribute_data.items():
|
|
98
|
-
# add
|
|
107
|
+
# add default arrays for not present values during processing
|
|
99
108
|
if not f_data:
|
|
100
109
|
if tuple_sizes:
|
|
101
|
-
batch_data += [
|
|
110
|
+
batch_data += [
|
|
111
|
+
RasaDataGenerator._create_default_array()
|
|
112
|
+
] * tuple_sizes[key]
|
|
102
113
|
else:
|
|
103
|
-
batch_data.append(
|
|
114
|
+
batch_data.append(RasaDataGenerator._create_default_array())
|
|
104
115
|
continue
|
|
105
116
|
|
|
106
117
|
for v in f_data:
|
|
@@ -409,8 +420,10 @@ class RasaBatchDataGenerator(RasaDataGenerator):
|
|
|
409
420
|
end = start + self._current_batch_size
|
|
410
421
|
|
|
411
422
|
# return input and target data, as our target data is inside the input
|
|
412
|
-
# data return
|
|
413
|
-
return self.prepare_batch(
|
|
423
|
+
# data return default array for the target data
|
|
424
|
+
return self.prepare_batch(
|
|
425
|
+
self._data, start, end
|
|
426
|
+
), RasaDataGenerator._create_default_array()
|
|
414
427
|
|
|
415
428
|
def on_epoch_end(self) -> None:
|
|
416
429
|
"""Update the data after every epoch."""
|
rasa/utils/tensorflow/layers.py
CHANGED
|
@@ -3,9 +3,7 @@ from typing import Any, Callable, List, Optional, Text, Tuple, Union
|
|
|
3
3
|
|
|
4
4
|
import tensorflow as tf
|
|
5
5
|
import tensorflow.keras.backend as K
|
|
6
|
-
|
|
7
|
-
# TODO: The following is not (yet) available via tf.keras
|
|
8
|
-
from keras.src.utils.control_flow_util import smart_cond
|
|
6
|
+
from tensorflow.python.keras.utils.control_flow_util import smart_cond
|
|
9
7
|
|
|
10
8
|
import rasa.utils.tensorflow.crf
|
|
11
9
|
import rasa.utils.tensorflow.layers_utils as layers_utils
|
|
@@ -278,6 +276,7 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
|
|
|
278
276
|
kernel_constraint: Constraint function applied to
|
|
279
277
|
the `kernel` weights matrix.
|
|
280
278
|
bias_constraint: Constraint function applied to the bias vector.
|
|
279
|
+
**kwargs: Additional keyword arguments passed to the parent class.
|
|
281
280
|
"""
|
|
282
281
|
super().__init__(**kwargs)
|
|
283
282
|
|
|
@@ -298,16 +297,19 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
|
|
|
298
297
|
self.kernel_mask = None
|
|
299
298
|
return
|
|
300
299
|
|
|
301
|
-
#
|
|
302
|
-
|
|
303
|
-
|
|
300
|
+
# Use callable initializer for TensorFlow 2.19.1 compatibility
|
|
301
|
+
def kernel_mask_initializer() -> tf.Tensor:
|
|
302
|
+
# Construct mask with given density and guarantee that every output is
|
|
303
|
+
# connected to at least one input
|
|
304
|
+
kernel_mask = self._minimal_mask() + self._random_mask()
|
|
304
305
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
# We might accidently have added a random connection on top of
|
|
307
|
+
# a fixed connection
|
|
308
|
+
kernel_mask = tf.clip_by_value(kernel_mask, 0, 1)
|
|
309
|
+
return kernel_mask
|
|
308
310
|
|
|
309
311
|
self.kernel_mask = tf.Variable(
|
|
310
|
-
initial_value=
|
|
312
|
+
initial_value=kernel_mask_initializer, trainable=False, name="kernel_mask"
|
|
311
313
|
)
|
|
312
314
|
|
|
313
315
|
def _random_mask(self) -> tf.Tensor:
|
|
@@ -367,7 +369,12 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
|
|
|
367
369
|
Returns:
|
|
368
370
|
The processed inputs.
|
|
369
371
|
"""
|
|
370
|
-
if
|
|
372
|
+
# Apply kernel masking if needed (Keras 3.x compatibility check)
|
|
373
|
+
if (
|
|
374
|
+
self.density < 1.0
|
|
375
|
+
and hasattr(self, "kernel_mask")
|
|
376
|
+
and self.kernel_mask is not None
|
|
377
|
+
):
|
|
371
378
|
# Set fraction of the `kernel` weights to zero according to precomputed mask
|
|
372
379
|
self.kernel.assign(self.kernel * self.kernel_mask)
|
|
373
380
|
return super().call(inputs)
|
|
@@ -724,6 +731,7 @@ class DotProductLoss(tf.keras.layers.Layer):
|
|
|
724
731
|
Currently, the only possible value is `SOFTMAX`.
|
|
725
732
|
similarity_type: Similarity measure to use, either `cosine` or `inner`.
|
|
726
733
|
name: Optional name of the layer.
|
|
734
|
+
**kwargs: Additional keyword arguments passed to the parent class.
|
|
727
735
|
|
|
728
736
|
Raises:
|
|
729
737
|
TFLayerConfigException: When `similarity_type` is not one of `COSINE` or
|
|
@@ -883,6 +891,7 @@ class SingleLabelDotProductLoss(DotProductLoss):
|
|
|
883
891
|
values are approximately bounded.
|
|
884
892
|
model_confidence: Normalization of confidence values during inference.
|
|
885
893
|
Currently, the only possible value is `SOFTMAX`.
|
|
894
|
+
**kwargs: Additional keyword arguments passed to the parent class.
|
|
886
895
|
"""
|
|
887
896
|
super().__init__(
|
|
888
897
|
num_candidates,
|
|
@@ -1244,6 +1253,7 @@ class MultiLabelDotProductLoss(DotProductLoss):
|
|
|
1244
1253
|
Used inside _loss_cross_entropy() only.
|
|
1245
1254
|
model_confidence: Normalization of confidence values during inference.
|
|
1246
1255
|
Currently, the only possible value is `SOFTMAX`.
|
|
1256
|
+
**kwargs: Additional keyword arguments passed to the parent class.
|
|
1247
1257
|
"""
|
|
1248
1258
|
super().__init__(
|
|
1249
1259
|
num_candidates,
|
rasa/utils/tensorflow/metrics.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional
|
|
2
2
|
|
|
3
3
|
import tensorflow as tf
|
|
4
|
-
from tensorflow.keras import backend as K
|
|
5
4
|
from tensorflow.types.experimental import TensorLike
|
|
6
5
|
|
|
7
6
|
# original code taken from
|
|
@@ -118,7 +117,7 @@ class FBetaScore(tf.keras.metrics.Metric):
|
|
|
118
117
|
|
|
119
118
|
def _zero_wt_init(name: Any) -> Any:
|
|
120
119
|
return self.add_weight(
|
|
121
|
-
name, shape=self.init_shape, initializer="zeros", dtype=self.dtype
|
|
120
|
+
name=name, shape=self.init_shape, initializer="zeros", dtype=self.dtype
|
|
122
121
|
)
|
|
123
122
|
|
|
124
123
|
self.true_positives = _zero_wt_init("true_positives")
|
|
@@ -197,7 +196,12 @@ class FBetaScore(tf.keras.metrics.Metric):
|
|
|
197
196
|
|
|
198
197
|
def reset_state(self) -> None:
|
|
199
198
|
reset_value = tf.zeros(self.init_shape, dtype=self.dtype)
|
|
200
|
-
|
|
199
|
+
# In Keras 3.x, self.variables contains string names, not variable objects,
|
|
200
|
+
# so each metric variable is reset using assign() instead of K.batch_set_value()
|
|
201
|
+
self.true_positives.assign(reset_value)
|
|
202
|
+
self.false_positives.assign(reset_value)
|
|
203
|
+
self.false_negatives.assign(reset_value)
|
|
204
|
+
self.weights_intermediate.assign(reset_value)
|
|
201
205
|
|
|
202
206
|
def reset_states(self) -> None:
|
|
203
207
|
# Backwards compatibility alias of `reset_state`. New classes should
|
rasa/utils/tensorflow/models.py
CHANGED
|
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, Union
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
import tensorflow as tf
|
|
10
10
|
from keras import Model
|
|
11
|
-
from keras.src.utils import tf_utils
|
|
12
11
|
|
|
13
12
|
import rasa.utils.train_utils
|
|
14
13
|
from rasa.shared.constants import DIAGNOSTIC_DATA
|
|
@@ -78,6 +77,7 @@ class RasaModel(Model):
|
|
|
78
77
|
|
|
79
78
|
Args:
|
|
80
79
|
random_seed: set the random seed to get reproducible results
|
|
80
|
+
**kwargs: Additional keyword arguments passed to the parent class
|
|
81
81
|
"""
|
|
82
82
|
# make sure that keras releases resources from previously trained model
|
|
83
83
|
tf.keras.backend.clear_session()
|
|
@@ -273,7 +273,8 @@ class RasaModel(Model):
|
|
|
273
273
|
if self._run_eagerly:
|
|
274
274
|
# Once we take advantage of TF's distributed training, this is where
|
|
275
275
|
# scheduled functions will be forced to execute and return actual values.
|
|
276
|
-
|
|
276
|
+
step_output = self.predict_step(batch_in)
|
|
277
|
+
outputs = self._convert_tensors_to_numpy(step_output)
|
|
277
278
|
if DIAGNOSTIC_DATA in outputs:
|
|
278
279
|
outputs[DIAGNOSTIC_DATA] = self._empty_lists_to_none_in_dict(
|
|
279
280
|
outputs[DIAGNOSTIC_DATA]
|
|
@@ -287,9 +288,8 @@ class RasaModel(Model):
|
|
|
287
288
|
|
|
288
289
|
# Once we take advantage of TF's distributed training, this is where
|
|
289
290
|
# scheduled functions will be forced to execute and return actual values.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
)
|
|
291
|
+
step_output = self._tf_predict_step(list(batch_in))
|
|
292
|
+
outputs = self._convert_tensors_to_numpy(step_output)
|
|
293
293
|
if DIAGNOSTIC_DATA in outputs:
|
|
294
294
|
outputs[DIAGNOSTIC_DATA] = self._empty_lists_to_none_in_dict(
|
|
295
295
|
outputs[DIAGNOSTIC_DATA]
|
|
@@ -388,6 +388,35 @@ class RasaModel(Model):
|
|
|
388
388
|
|
|
389
389
|
return {k: _recurse(v) for k, v in input_dict.items()}
|
|
390
390
|
|
|
391
|
+
def _convert_tensors_to_numpy(
|
|
392
|
+
self, step_output: Dict[Text, Any]
|
|
393
|
+
) -> Dict[Text, Any]:
|
|
394
|
+
""" "Recursively convert TensorFlow tensors to numpy arrays for Keras 3.x
|
|
395
|
+
compatibility.
|
|
396
|
+
Replaces the deprecated tf_utils.sync_to_numpy_or_python_type() function.
|
|
397
|
+
Converts tensors (objects with 'numpy' method) to numpy arrays,
|
|
398
|
+
leaves others unchanged.
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
def to_numpy(obj: Any) -> Any:
|
|
402
|
+
if hasattr(obj, "numpy"):
|
|
403
|
+
try:
|
|
404
|
+
return obj.numpy()
|
|
405
|
+
except Exception:
|
|
406
|
+
# Fallback: return as-is if not convertible
|
|
407
|
+
return obj
|
|
408
|
+
# Dict: recurse into values
|
|
409
|
+
if isinstance(obj, dict):
|
|
410
|
+
return {k: to_numpy(v) for k, v in obj.items()}
|
|
411
|
+
# List/Tuple: recurse preserving type
|
|
412
|
+
if isinstance(obj, list):
|
|
413
|
+
return [to_numpy(v) for v in obj]
|
|
414
|
+
if isinstance(obj, tuple):
|
|
415
|
+
return tuple(to_numpy(v) for v in obj)
|
|
416
|
+
return obj
|
|
417
|
+
|
|
418
|
+
return {key: to_numpy(value) for key, value in step_output.items()}
|
|
419
|
+
|
|
391
420
|
def _get_metric_results(self, prefix: Optional[Text] = "") -> Dict[Text, float]:
|
|
392
421
|
return {
|
|
393
422
|
f"{prefix}{metric.name}": metric.result()
|
|
@@ -403,7 +432,21 @@ class RasaModel(Model):
|
|
|
403
432
|
overwrite: If 'True' an already existing model with the same file name will
|
|
404
433
|
be overwritten.
|
|
405
434
|
"""
|
|
406
|
-
|
|
435
|
+
# Ensure filename ends with .weights.h5 and model is built for Keras 3.x
|
|
436
|
+
# compatibility
|
|
437
|
+
model_file_name = str(model_file_name)
|
|
438
|
+
if not model_file_name.endswith(".weights.h5"):
|
|
439
|
+
model_file_name += ".weights.h5"
|
|
440
|
+
|
|
441
|
+
if not self.built:
|
|
442
|
+
import tensorflow as tf
|
|
443
|
+
|
|
444
|
+
_ = self(tf.zeros((1, 1)))
|
|
445
|
+
|
|
446
|
+
# TensorFlow 2.19: save weights with different file extension
|
|
447
|
+
if not model_file_name.endswith(".weights.h5"):
|
|
448
|
+
model_file_name += ".weights.h5"
|
|
449
|
+
self.save_weights(model_file_name, overwrite=overwrite)
|
|
407
450
|
|
|
408
451
|
@classmethod
|
|
409
452
|
def load(
|
|
@@ -438,18 +481,23 @@ class RasaModel(Model):
|
|
|
438
481
|
learning_rate = kwargs.get("config", {}).get(LEARNING_RATE, 0.001)
|
|
439
482
|
run_eagerly = kwargs.get("config", {}).get(RUN_EAGERLY)
|
|
440
483
|
|
|
441
|
-
# need to train on 1 example to build weights of the correct size
|
|
442
484
|
model.compile(
|
|
443
485
|
optimizer=tf.keras.optimizers.Adam(learning_rate), run_eagerly=run_eagerly
|
|
444
486
|
)
|
|
445
487
|
data_generator = RasaBatchDataGenerator(model_data_example, batch_size=1)
|
|
446
488
|
model.fit(data_generator, verbose=False)
|
|
489
|
+
|
|
490
|
+
# Ensure model is built before loading weights
|
|
491
|
+
if not model.built:
|
|
492
|
+
sample_batch = next(iter(data_generator))
|
|
493
|
+
_ = model(sample_batch)
|
|
494
|
+
|
|
447
495
|
# load trained weights
|
|
448
496
|
model.load_weights(model_file_name)
|
|
449
497
|
|
|
450
498
|
# predict on one data example to speed up prediction during inference
|
|
451
499
|
# the first prediction always takes a bit longer to trace tf function
|
|
452
|
-
if
|
|
500
|
+
if predict_data_example:
|
|
453
501
|
model.run_inference(predict_data_example)
|
|
454
502
|
|
|
455
503
|
logger.debug("Finished loading the model.")
|
|
@@ -291,7 +291,7 @@ class ConcatenateSparseDenseFeatures(RasaCustomLayer):
|
|
|
291
291
|
[
|
|
292
292
|
config[DENSE_DIMENSION][attribute]
|
|
293
293
|
if signature.is_sparse
|
|
294
|
-
else signature.units
|
|
294
|
+
else (signature.units or 0)
|
|
295
295
|
for signature in feature_type_signature
|
|
296
296
|
]
|
|
297
297
|
)
|
|
@@ -301,12 +301,12 @@ class ConcatenateSparseDenseFeatures(RasaCustomLayer):
|
|
|
301
301
|
) -> tf.Tensor:
|
|
302
302
|
"""Turns sparse tensor into dense, possibly adds dropout before and/or after."""
|
|
303
303
|
if self.SPARSE_DROPOUT in self._tf_layers:
|
|
304
|
-
feature = self._tf_layers[self.SPARSE_DROPOUT](feature, training)
|
|
304
|
+
feature = self._tf_layers[self.SPARSE_DROPOUT](feature, training=training)
|
|
305
305
|
|
|
306
306
|
feature = self._tf_layers[self.SPARSE_TO_DENSE](feature)
|
|
307
307
|
|
|
308
308
|
if self.DENSE_DROPOUT in self._tf_layers:
|
|
309
|
-
feature = self._tf_layers[self.DENSE_DROPOUT](feature, training)
|
|
309
|
+
feature = self._tf_layers[self.DENSE_DROPOUT](feature, training=training)
|
|
310
310
|
|
|
311
311
|
return feature
|
|
312
312
|
|
|
@@ -944,7 +944,7 @@ class RasaSequenceLayer(RasaCustomLayer):
|
|
|
944
944
|
# Note that only sequence-level features are masked, nothing happens to the
|
|
945
945
|
# sentence-level features in the combined features tensor.
|
|
946
946
|
seq_sent_features, mlm_boolean_mask = self._tf_layers[self.MLM_INPUT_MASK](
|
|
947
|
-
seq_sent_features, mask_sequence, training
|
|
947
|
+
seq_sent_features, mask_sequence, training=training
|
|
948
948
|
)
|
|
949
949
|
|
|
950
950
|
return seq_sent_features, token_ids, mlm_boolean_mask
|
|
@@ -1002,7 +1002,9 @@ class RasaSequenceLayer(RasaCustomLayer):
|
|
|
1002
1002
|
]((sequence_features, sentence_features, sequence_feature_lengths))
|
|
1003
1003
|
|
|
1004
1004
|
# Apply one or more dense layers.
|
|
1005
|
-
seq_sent_features = self._tf_layers[self.FFNN](
|
|
1005
|
+
seq_sent_features = self._tf_layers[self.FFNN](
|
|
1006
|
+
seq_sent_features, training=training
|
|
1007
|
+
)
|
|
1006
1008
|
|
|
1007
1009
|
# If using masked language modeling, mask the transformer inputs and get labels
|
|
1008
1010
|
# for the masked tokens and a boolean mask. Note that TED does not use MLM loss,
|
|
@@ -1031,7 +1033,7 @@ class RasaSequenceLayer(RasaCustomLayer):
|
|
|
1031
1033
|
if self._has_transformer:
|
|
1032
1034
|
mask_padding = 1 - mask_combined_sequence_sentence
|
|
1033
1035
|
outputs, attention_weights = self._tf_layers[self.TRANSFORMER](
|
|
1034
|
-
seq_sent_features_masked, mask_padding, training
|
|
1036
|
+
seq_sent_features_masked, mask_padding, training=training
|
|
1035
1037
|
)
|
|
1036
1038
|
outputs = tf.nn.gelu(outputs)
|
|
1037
1039
|
else:
|
|
@@ -2,10 +2,8 @@ from typing import Optional, Text, Tuple, Union
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import tensorflow as tf
|
|
5
|
-
|
|
6
|
-
# TODO: The following is not (yet) available via tf.keras
|
|
7
|
-
from keras.src.utils.control_flow_util import smart_cond
|
|
8
5
|
from tensorflow.keras import backend as K
|
|
6
|
+
from tensorflow.python.keras.utils.control_flow_util import smart_cond
|
|
9
7
|
|
|
10
8
|
from rasa.utils.tensorflow.exceptions import TFLayerConfigException
|
|
11
9
|
from rasa.utils.tensorflow.layers import RandomlyConnectedDense
|
|
@@ -280,6 +278,7 @@ class MultiHeadAttention(tf.keras.layers.Layer):
|
|
|
280
278
|
value: A tensor with shape (..., length, depth).
|
|
281
279
|
pad_mask: Float tensor with shape broadcastable
|
|
282
280
|
to (..., length, length). Defaults to None.
|
|
281
|
+
training: A tensor
|
|
283
282
|
|
|
284
283
|
Returns:
|
|
285
284
|
output: A tensor with shape (..., length, depth).
|