rasa-pro 3.12.4__py3-none-any.whl → 3.13.0.dev1__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.

Files changed (47) hide show
  1. rasa/cli/scaffold.py +1 -1
  2. rasa/core/actions/action.py +38 -28
  3. rasa/core/actions/action_run_slot_rejections.py +1 -1
  4. rasa/core/channels/studio_chat.py +16 -43
  5. rasa/core/information_retrieval/faiss.py +62 -6
  6. rasa/core/nlg/contextual_response_rephraser.py +7 -6
  7. rasa/core/nlg/generator.py +5 -21
  8. rasa/core/nlg/response.py +6 -43
  9. rasa/core/nlg/translate.py +0 -8
  10. rasa/core/policies/enterprise_search_policy.py +1 -0
  11. rasa/core/policies/intentless_policy.py +6 -59
  12. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
  13. rasa/dialogue_understanding/generator/_jinja_filters.py +9 -0
  14. rasa/dialogue_understanding/generator/constants.py +4 -0
  15. rasa/dialogue_understanding/generator/llm_based_command_generator.py +18 -3
  16. rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -1
  17. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +3 -3
  18. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +7 -4
  19. rasa/dialogue_understanding/processor/command_processor.py +20 -5
  20. rasa/dialogue_understanding/processor/command_processor_component.py +5 -2
  21. rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
  22. rasa/dialogue_understanding_test/command_metrics.py +38 -0
  23. rasa/dialogue_understanding_test/du_test_case.py +58 -25
  24. rasa/dialogue_understanding_test/du_test_result.py +228 -132
  25. rasa/dialogue_understanding_test/du_test_runner.py +10 -1
  26. rasa/dialogue_understanding_test/io.py +35 -8
  27. rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +1 -1
  28. rasa/engine/validation.py +36 -1
  29. rasa/model_manager/model_api.py +1 -1
  30. rasa/model_manager/socket_bridge.py +0 -7
  31. rasa/model_training.py +2 -1
  32. rasa/shared/constants.py +2 -0
  33. rasa/shared/core/policies/__init__.py +0 -0
  34. rasa/shared/core/policies/utils.py +87 -0
  35. rasa/shared/core/slot_mappings.py +12 -0
  36. rasa/shared/core/slots.py +1 -1
  37. rasa/shared/core/trackers.py +4 -10
  38. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
  39. rasa/tracing/instrumentation/attribute_extractors.py +38 -6
  40. rasa/version.py +1 -1
  41. {rasa_pro-3.12.4.dist-info → rasa_pro-3.13.0.dev1.dist-info}/METADATA +5 -6
  42. {rasa_pro-3.12.4.dist-info → rasa_pro-3.13.0.dev1.dist-info}/RECORD +45 -43
  43. {rasa_pro-3.12.4.dist-info → rasa_pro-3.13.0.dev1.dist-info}/WHEEL +1 -1
  44. README.md +0 -38
  45. rasa/keys +0 -1
  46. {rasa_pro-3.12.4.dist-info → rasa_pro-3.13.0.dev1.dist-info}/NOTICE +0 -0
  47. {rasa_pro-3.12.4.dist-info → rasa_pro-3.13.0.dev1.dist-info}/entry_points.txt +0 -0
rasa/engine/validation.py CHANGED
@@ -86,7 +86,9 @@ from rasa.shared.constants import (
86
86
  from rasa.shared.core.constants import ACTION_RESET_ROUTING, ACTION_TRIGGER_CHITCHAT
87
87
  from rasa.shared.core.domain import Domain
88
88
  from rasa.shared.core.flows import Flow, FlowsList
89
+ from rasa.shared.core.policies.utils import contains_intentless_policy_responses
89
90
  from rasa.shared.core.slots import Slot
91
+ from rasa.shared.core.training_data.structures import StoryGraph
90
92
  from rasa.shared.exceptions import RasaException
91
93
  from rasa.shared.nlu.training_data.message import Message
92
94
  from rasa.shared.utils.common import display_research_study_prompt
@@ -642,11 +644,18 @@ def _recursively_check_required_components(
642
644
 
643
645
 
644
646
  def validate_flow_component_dependencies(
645
- flows: FlowsList, model_configuration: GraphModelConfiguration
647
+ flows: FlowsList,
648
+ domain: Domain,
649
+ story_graph: StoryGraph,
650
+ model_configuration: GraphModelConfiguration,
646
651
  ) -> None:
647
652
  if (pattern_chitchat := flows.flow_by_id(FLOW_PATTERN_CHITCHAT)) is not None:
648
653
  _validate_chitchat_dependencies(pattern_chitchat, model_configuration)
649
654
 
655
+ _validate_intentless_policy_responses(
656
+ flows, domain, story_graph, model_configuration
657
+ )
658
+
650
659
 
651
660
  def _validate_chitchat_dependencies(
652
661
  pattern_chitchat: Flow, model_configuration: GraphModelConfiguration
@@ -674,6 +683,32 @@ def _validate_chitchat_dependencies(
674
683
  )
675
684
 
676
685
 
686
+ def _validate_intentless_policy_responses(
687
+ flows: FlowsList,
688
+ domain: Domain,
689
+ story_graph: StoryGraph,
690
+ model_configuration: GraphModelConfiguration,
691
+ ) -> None:
692
+ """If IntentlessPolicy is configured, validate that it has responses to use:
693
+ either responses from the domain that are not part of any flow, or from
694
+ end-to-end stories.
695
+ """
696
+ if not model_configuration.predict_schema.has_node(IntentlessPolicy):
697
+ return
698
+
699
+ if not contains_intentless_policy_responses(flows, domain, story_graph):
700
+ structlogger.error(
701
+ "validation.intentless_policy.no_applicable_responses_found",
702
+ event_info=(
703
+ "IntentlessPolicy is configured, but no applicable responses are "
704
+ "found. Please make sure that there are responses defined in the "
705
+ "domain that are not part of any flow, or that there are "
706
+ "end-to-end stories in the training data."
707
+ ),
708
+ )
709
+ sys.exit(1)
710
+
711
+
677
712
  def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
678
713
  """Extracts the index of a component of the given class in the schema.
679
714
  This function assumes that each component's node name is stored in a way
@@ -483,7 +483,7 @@ def external_blueprint() -> Blueprint:
483
483
  """Create a blueprint for the model manager API."""
484
484
  from rasa.core.channels.socketio import SocketBlueprint
485
485
 
486
- sio = AsyncServer(async_mode="sanic", cors_allowed_origins="*")
486
+ sio = AsyncServer(async_mode="sanic", cors_allowed_origins=[])
487
487
  bp = SocketBlueprint(sio, "", "model_api_external")
488
488
 
489
489
  create_bridge_server(sio, running_bots)
@@ -131,13 +131,6 @@ async def create_bridge_client(
131
131
  structlogger.debug("model_runner.bot_message", deployment_id=deployment_id)
132
132
  await sio.emit("bot_message", data, room=sid)
133
133
 
134
- @client.event # type: ignore[misc]
135
- async def error(data: Dict[str, Any]) -> None:
136
- structlogger.debug(
137
- "model_runner.bot_error", deployment_id=deployment_id, data=data
138
- )
139
- await sio.emit("error", data, room=sid)
140
-
141
134
  @client.event # type: ignore[misc]
142
135
  async def tracker(data: Dict[str, Any]) -> None:
143
136
  await sio.emit("tracker", json.loads(data), room=sid)
rasa/model_training.py CHANGED
@@ -315,6 +315,7 @@ async def _train_graph(
315
315
  )
316
316
  flows = file_importer.get_flows()
317
317
  domain = file_importer.get_domain()
318
+ story_graph = file_importer.get_stories()
318
319
  model_configuration = recipe.graph_config_for_recipe(
319
320
  config,
320
321
  kwargs,
@@ -330,7 +331,7 @@ async def _train_graph(
330
331
  config
331
332
  )
332
333
  rasa.engine.validation.validate_flow_component_dependencies(
333
- flows, model_configuration
334
+ flows, domain, story_graph, model_configuration
334
335
  )
335
336
  rasa.engine.validation.validate_command_generator_setup(model_configuration)
336
337
 
rasa/shared/constants.py CHANGED
@@ -99,6 +99,8 @@ UTTER_ASK_PREFIX = "utter_ask_"
99
99
  ACTION_ASK_PREFIX = "action_ask_"
100
100
  FLOW_PREFIX = "flow_"
101
101
 
102
+ UTTER_FREE_CHITCHAT_RESPONSE = "utter_free_chitchat_response"
103
+
102
104
  ASSISTANT_ID_KEY = "assistant_id"
103
105
  ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
104
106
 
File without changes
@@ -0,0 +1,87 @@
1
+ from typing import Set, Text
2
+
3
+ from rasa.dialogue_understanding.patterns.chitchat import FLOW_PATTERN_CHITCHAT
4
+ from rasa.graph_components.providers.forms_provider import Forms
5
+ from rasa.graph_components.providers.responses_provider import Responses
6
+ from rasa.shared.constants import (
7
+ REQUIRED_SLOTS_KEY,
8
+ UTTER_ASK_PREFIX,
9
+ UTTER_FREE_CHITCHAT_RESPONSE,
10
+ )
11
+ from rasa.shared.core.constants import ACTION_TRIGGER_CHITCHAT
12
+ from rasa.shared.core.domain import Domain
13
+ from rasa.shared.core.flows import FlowsList
14
+ from rasa.shared.core.training_data.structures import StoryGraph
15
+
16
+
17
+ def collect_form_responses(forms: Forms) -> Set[Text]:
18
+ """Collect responses that belong the requested slots in forms.
19
+
20
+ Args:
21
+ forms: the forms from the domain
22
+ Returns:
23
+ all utterances used in forms
24
+ """
25
+ form_responses = set()
26
+ for _, form_info in forms.data.items():
27
+ for required_slot in form_info.get(REQUIRED_SLOTS_KEY, []):
28
+ form_responses.add(f"{UTTER_ASK_PREFIX}{required_slot}")
29
+ return form_responses
30
+
31
+
32
+ def filter_responses_for_intentless_policy(
33
+ responses: Responses, forms: Forms, flows: FlowsList
34
+ ) -> Responses:
35
+ """Filters out responses that are unwanted for the intentless policy.
36
+
37
+ This includes utterances used in flows and forms.
38
+
39
+ Args:
40
+ responses: the responses from the domain
41
+ forms: the forms from the domain
42
+ flows: all flows
43
+ Returns:
44
+ The remaining, relevant responses for the intentless policy.
45
+ """
46
+ form_responses = collect_form_responses(forms)
47
+ flow_responses = flows.utterances
48
+ combined_responses = form_responses | flow_responses
49
+ filtered_responses = {
50
+ name: variants
51
+ for name, variants in responses.data.items()
52
+ if name not in combined_responses
53
+ }
54
+
55
+ pattern_chitchat = flows.flow_by_id(FLOW_PATTERN_CHITCHAT)
56
+
57
+ # The following condition is highly unlikely, but mypy requires the case
58
+ # of pattern_chitchat == None to be addressed
59
+ if not pattern_chitchat:
60
+ return Responses(data=filtered_responses)
61
+
62
+ # if action_trigger_chitchat, filter out "utter_free_chitchat_response"
63
+ has_action_trigger_chitchat = pattern_chitchat.has_action_step(
64
+ ACTION_TRIGGER_CHITCHAT
65
+ )
66
+ if has_action_trigger_chitchat:
67
+ filtered_responses.pop(UTTER_FREE_CHITCHAT_RESPONSE, None)
68
+
69
+ return Responses(data=filtered_responses)
70
+
71
+
72
+ def contains_intentless_policy_responses(
73
+ flows: FlowsList, domain: Domain, story_graph: StoryGraph
74
+ ) -> bool:
75
+ """Checks if IntentlessPolicy has applicable responses: either responses in the
76
+ domain that are not part of any flow, or if there are e2e stories.
77
+ """
78
+ responses = filter_responses_for_intentless_policy(
79
+ Responses(data=domain.responses), Forms(data=domain.forms), flows
80
+ )
81
+
82
+ has_applicable_responses = bool(
83
+ responses and responses.data and len(responses.data) > 0
84
+ )
85
+ has_e2e_stories = bool(story_graph and story_graph.has_e2e_stories())
86
+
87
+ return has_applicable_responses or has_e2e_stories
@@ -115,6 +115,18 @@ class SlotMapping(BaseModel):
115
115
  )
116
116
  data_copy[KEY_RUN_ACTION_EVERY_TURN] = deprecated_action
117
117
 
118
+ structlogger.warning(
119
+ "slot_mapping.deprecated_action_key_replaced_with_run_action_every_turn",
120
+ slot_name=slot_name,
121
+ event_info=f"The `{KEY_ACTION}` key in slot mappings "
122
+ f"has been replaced with "
123
+ f"the `{KEY_RUN_ACTION_EVERY_TURN}` key. "
124
+ f"This will result in the custom action "
125
+ f"being executed at every conversation turn "
126
+ f"automatically. Remove the key "
127
+ f"to avoid this behavior.",
128
+ )
129
+
118
130
  run_action_every_turn = data_copy.pop(KEY_RUN_ACTION_EVERY_TURN, None)
119
131
 
120
132
  coexistence_system = data_copy.pop(KEY_COEXISTENCE_SYSTEM, None)
rasa/shared/core/slots.py CHANGED
@@ -787,7 +787,7 @@ class StrictCategoricalSlot(CategoricalSlot):
787
787
  def coerce_value(self, value: Any) -> Any:
788
788
  """Coerce the value to one of the allowed ones or raise an error if invalid."""
789
789
  if value is None:
790
- return self.initial_value
790
+ return value
791
791
 
792
792
  for allowed_value in self.values:
793
793
  # Allowed values are always stored as strings, so we can use casefold().
@@ -1123,16 +1123,10 @@ class DialogueStateTracker:
1123
1123
  f"Please update the slot configuration accordingly."
1124
1124
  )
1125
1125
 
1126
- supported_languages = []
1127
- for language_code in language_slot.values:
1128
- is_default = language_code == language_slot.initial_value
1129
- language = Language.from_language_code(
1130
- language_code=language_code,
1131
- is_default=is_default,
1132
- )
1133
- supported_languages.append(language)
1134
-
1135
- return supported_languages
1126
+ return [
1127
+ Language.from_language_code(language_code)
1128
+ for language_code in language_slot.values
1129
+ ]
1136
1130
 
1137
1131
  @property
1138
1132
  def current_language(self) -> Optional[Language]:
@@ -101,11 +101,11 @@ class DefaultLiteLLMClient(_BaseLiteLLMClient):
101
101
  # SageMaker) in Rasa by allowing AWS secrets to be provided as extra
102
102
  # parameters without triggering validation errors due to missing AWS
103
103
  # environment variables.
104
- if self.provider.lower() in [
104
+ if self.provider.lower() in {
105
105
  AWS_BEDROCK_PROVIDER,
106
106
  AWS_SAGEMAKER_PROVIDER,
107
107
  AWS_SAGEMAKER_CHAT_PROVIDER,
108
- ]:
108
+ }:
109
109
  validate_aws_setup_for_litellm_clients(
110
110
  self._litellm_model_name,
111
111
  self._litellm_extra_parameters,
@@ -22,8 +22,14 @@ from rasa.dialogue_understanding.generator import LLMBasedCommandGenerator
22
22
  from rasa.dialogue_understanding.generator.constants import FLOW_RETRIEVAL_KEY
23
23
  from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
24
24
  from rasa.dialogue_understanding_test.du_test_result import (
25
+ KEY_COMMANDS_F1_MACRO,
26
+ KEY_COMMANDS_F1_MICRO,
27
+ KEY_COMMANDS_F1_WEIGHTED,
25
28
  KEY_TEST_CASES_ACCURACY,
26
29
  KEY_USER_UTTERANCES_ACCURACY,
30
+ OUTPUT_COMMANDS_F1_MACRO_INSTRUMENTATION_ATTR,
31
+ OUTPUT_COMMANDS_F1_MICRO_INSTRUMENTATION_ATTR,
32
+ OUTPUT_COMMANDS_F1_WEIGHTED_INSTRUMENTATION_ATTR,
27
33
  OUTPUT_COMPLETION_TOKEN_METRICS,
28
34
  OUTPUT_LATENCY_METRICS,
29
35
  OUTPUT_NAMES_OF_FAILED_TESTS,
@@ -454,6 +460,7 @@ def extract_attrs_for_execute_commands(
454
460
  all_flows: FlowsList,
455
461
  execution_context: ExecutionContext,
456
462
  story_graph: Optional[StoryGraph] = None,
463
+ domain: Optional[Domain] = None,
457
464
  ) -> Dict[str, Any]:
458
465
  return {
459
466
  "number_of_events": len(tracker.events),
@@ -497,6 +504,7 @@ def extract_attrs_for_clean_up_commands(
497
504
  all_flows: FlowsList,
498
505
  execution_context: ExecutionContext,
499
506
  story_graph: Optional[StoryGraph] = None,
507
+ domain: Optional[Domain] = None,
500
508
  ) -> Dict[str, Any]:
501
509
  commands_list = []
502
510
 
@@ -612,6 +620,15 @@ def extract_attrs_for_du_print_test_results(
612
620
  OUTPUT_NAMES_OF_FAILED_TESTS: json.dumps(
613
621
  test_suite_result.names_of_failed_tests
614
622
  ),
623
+ OUTPUT_COMMANDS_F1_MACRO_INSTRUMENTATION_ATTR: (
624
+ test_suite_result.f1_score[KEY_COMMANDS_F1_MACRO]
625
+ ),
626
+ OUTPUT_COMMANDS_F1_MICRO_INSTRUMENTATION_ATTR: (
627
+ test_suite_result.f1_score[KEY_COMMANDS_F1_MICRO]
628
+ ),
629
+ OUTPUT_COMMANDS_F1_WEIGHTED_INSTRUMENTATION_ATTR: (
630
+ test_suite_result.f1_score[KEY_COMMANDS_F1_WEIGHTED]
631
+ ),
615
632
  }
616
633
  if test_suite_result.command_metrics:
617
634
  for (
@@ -636,12 +653,27 @@ def extract_attrs_for_du_print_test_results(
636
653
  for key, value in test_suite_result.llm_config.items():
637
654
  attributes_dict[f"llm_config_0_{key}"] = value
638
655
 
639
- for key, value in test_suite_result.latency_metrics.items():
640
- attributes_dict[f"{OUTPUT_LATENCY_METRICS}_{key}"] = value
641
- for key, value in test_suite_result.prompt_token_metrics.items():
642
- attributes_dict[f"{OUTPUT_PROMPT_TOKEN_METRICS}_{key}"] = value
643
- for key, value in test_suite_result.completion_token_metrics.items():
644
- attributes_dict[f"{OUTPUT_COMPLETION_TOKEN_METRICS}_{key}"] = value
656
+ for component_name, latency_metric in test_suite_result.latency_metrics.items():
657
+ for metric_name, metric_value in latency_metric.items():
658
+ attributes_dict[
659
+ f"{OUTPUT_LATENCY_METRICS}_{component_name}_{metric_name}"
660
+ ] = metric_value
661
+ for (
662
+ component_name,
663
+ prompt_token_metric,
664
+ ) in test_suite_result.prompt_token_metrics.items():
665
+ for metric_name, metric_value in prompt_token_metric.items():
666
+ attributes_dict[
667
+ f"{OUTPUT_PROMPT_TOKEN_METRICS}_{component_name}_{metric_name}"
668
+ ] = metric_value
669
+ for (
670
+ component_name,
671
+ completion_token_metric,
672
+ ) in test_suite_result.completion_token_metrics.items():
673
+ for metric_name, metric_value in completion_token_metric.items():
674
+ attributes_dict[
675
+ f"{OUTPUT_COMPLETION_TOKEN_METRICS}_{component_name}_{metric_name}"
676
+ ] = metric_value
645
677
 
646
678
  return attributes_dict
647
679
 
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.12.4"
3
+ __version__ = "3.13.0.dev1"
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.12.4
3
+ Version: 3.13.0.dev1
4
4
  Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
5
- Home-page: https://rasa.com
6
5
  Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
7
6
  Author: Rasa Technologies GmbH
8
7
  Author-email: hi@rasa.com
@@ -86,7 +85,6 @@ Requires-Dist: protobuf (>=4.23.3,<4.25.4)
86
85
  Requires-Dist: psutil (>=5.9.5,<6.0.0)
87
86
  Requires-Dist: psycopg2-binary (>=2.9.9,<2.10.0)
88
87
  Requires-Dist: pycountry (>=22.3.5,<23.0.0)
89
- Requires-Dist: pydantic (>=2.0,<3.0)
90
88
  Requires-Dist: pydot (>=1.4,<1.5)
91
89
  Requires-Dist: pykwalify (>=1.8,<1.9)
92
90
  Requires-Dist: pymilvus (>=2.4.1,<2.4.2)
@@ -102,7 +100,7 @@ Requires-Dist: pyyaml (>=6.0)
102
100
  Requires-Dist: qdrant-client (>=1.9.1,<1.10.0)
103
101
  Requires-Dist: questionary (>=1.10.0,<2.1.0)
104
102
  Requires-Dist: randomname (>=0.2.1,<0.3.0)
105
- Requires-Dist: rasa-sdk (==3.12.0)
103
+ Requires-Dist: rasa-sdk (==3.13.0.dev1)
106
104
  Requires-Dist: redis (>=4.6.0,<6.0)
107
105
  Requires-Dist: regex (>=2024.7.24,<2024.8.0)
108
106
  Requires-Dist: requests (>=2.32.3,<2.33.0)
@@ -135,7 +133,7 @@ Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "darwin"
135
133
  Requires-Dist: tensorflow-io-gcs-filesystem (==0.34) ; sys_platform == "linux"
136
134
  Requires-Dist: tensorflow-macos (==2.14.1) ; sys_platform == "darwin" and platform_machine == "arm64"
137
135
  Requires-Dist: tensorflow-metal (==1.1.0) ; (sys_platform == "darwin" and platform_machine == "arm64") and (extra == "metal")
138
- Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and (platform_machine != "arm64" and platform_machine != "aarch64")
136
+ Requires-Dist: tensorflow-text (==2.14.0) ; sys_platform != "win32" and platform_machine != "arm64" and platform_machine != "aarch64"
139
137
  Requires-Dist: tensorflow_hub (>=0.13.0,<0.14.0)
140
138
  Requires-Dist: terminaltables (>=3.1.10,<3.2.0)
141
139
  Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
@@ -150,6 +148,7 @@ Requires-Dist: webexteamssdk (>=1.6.1,<1.7.0)
150
148
  Requires-Dist: websockets (>=10.4,<11.0)
151
149
  Requires-Dist: wheel (>=0.40.0)
152
150
  Project-URL: Documentation, https://rasa.com/docs
151
+ Project-URL: Homepage, https://rasa.com
153
152
  Project-URL: Repository, https://github.com/rasahq/rasa
154
153
  Description-Content-Type: text/markdown
155
154