rasa-pro 3.12.5__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 (35) 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/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
  12. rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -2
  13. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +1 -1
  14. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +5 -2
  15. rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
  16. rasa/dialogue_understanding_test/command_metrics.py +38 -0
  17. rasa/dialogue_understanding_test/du_test_case.py +58 -25
  18. rasa/dialogue_understanding_test/du_test_result.py +228 -132
  19. rasa/dialogue_understanding_test/du_test_runner.py +10 -1
  20. rasa/dialogue_understanding_test/io.py +35 -8
  21. rasa/model_manager/model_api.py +1 -1
  22. rasa/model_manager/socket_bridge.py +0 -7
  23. rasa/shared/core/slot_mappings.py +12 -0
  24. rasa/shared/core/slots.py +1 -1
  25. rasa/shared/core/trackers.py +4 -10
  26. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
  27. rasa/tracing/instrumentation/attribute_extractors.py +36 -6
  28. rasa/version.py +1 -1
  29. {rasa_pro-3.12.5.dist-info → rasa_pro-3.13.0.dev1.dist-info}/METADATA +5 -6
  30. {rasa_pro-3.12.5.dist-info → rasa_pro-3.13.0.dev1.dist-info}/RECORD +33 -34
  31. {rasa_pro-3.12.5.dist-info → rasa_pro-3.13.0.dev1.dist-info}/WHEEL +1 -1
  32. README.md +0 -38
  33. rasa/keys +0 -1
  34. {rasa_pro-3.12.5.dist-info → rasa_pro-3.13.0.dev1.dist-info}/NOTICE +0 -0
  35. {rasa_pro-3.12.5.dist-info → rasa_pro-3.13.0.dev1.dist-info}/entry_points.txt +0 -0
@@ -1,54 +1,21 @@
1
+ import typing
1
2
  from collections import defaultdict
2
3
  from typing import Dict, List
3
4
 
4
- from pydantic import BaseModel
5
-
6
5
  from rasa.dialogue_understanding.commands import Command
7
6
  from rasa.dialogue_understanding_test.command_comparison import (
8
7
  is_command_present_in_list,
9
8
  )
10
- from rasa.dialogue_understanding_test.du_test_result import (
11
- DialogueUnderstandingTestResult,
12
- )
13
-
14
-
15
- class CommandMetrics(BaseModel):
16
- tp: int
17
- fp: int
18
- fn: int
19
- total_count: int
20
-
21
- @staticmethod
22
- def _safe_divide(numerator: float, denominator: float) -> float:
23
- """Safely perform division, returning 0.0 if the denominator is zero."""
24
- return numerator / denominator if denominator > 0 else 0.0
9
+ from rasa.dialogue_understanding_test.command_metrics import CommandMetrics
25
10
 
26
- def get_precision(self) -> float:
27
- return self._safe_divide(self.tp, self.tp + self.fp)
28
-
29
- def get_recall(self) -> float:
30
- return self._safe_divide(self.tp, self.tp + self.fn)
31
-
32
- def get_f1_score(self) -> float:
33
- precision = self.get_precision()
34
- recall = self.get_recall()
35
-
36
- return self._safe_divide(2 * precision * recall, precision + recall)
37
-
38
- def as_dict(self) -> Dict[str, float]:
39
- return {
40
- "tp": self.tp,
41
- "fp": self.fp,
42
- "fn": self.fn,
43
- "precision": self.get_precision(),
44
- "recall": self.get_recall(),
45
- "f1_score": self.get_f1_score(),
46
- "total_count": self.total_count,
47
- }
11
+ if typing.TYPE_CHECKING:
12
+ from rasa.dialogue_understanding_test.du_test_result import (
13
+ DialogueUnderstandingTestResult,
14
+ )
48
15
 
49
16
 
50
17
  def calculate_command_metrics(
51
- test_results: List[DialogueUnderstandingTestResult],
18
+ test_results: List["DialogueUnderstandingTestResult"],
52
19
  ) -> Dict[str, CommandMetrics]:
53
20
  """Calculate the command metrics for the test result."""
54
21
  metrics: Dict[str, CommandMetrics] = defaultdict(
@@ -0,0 +1,38 @@
1
+ from typing import Dict
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class CommandMetrics(BaseModel):
7
+ tp: int
8
+ fp: int
9
+ fn: int
10
+ total_count: int
11
+
12
+ @staticmethod
13
+ def _safe_divide(numerator: float, denominator: float) -> float:
14
+ """Safely perform division, returning 0.0 if the denominator is zero."""
15
+ return numerator / denominator if denominator > 0 else 0.0
16
+
17
+ def get_precision(self) -> float:
18
+ return self._safe_divide(self.tp, self.tp + self.fp)
19
+
20
+ def get_recall(self) -> float:
21
+ return self._safe_divide(self.tp, self.tp + self.fn)
22
+
23
+ def get_f1_score(self) -> float:
24
+ precision = self.get_precision()
25
+ recall = self.get_recall()
26
+
27
+ return self._safe_divide(2 * precision * recall, precision + recall)
28
+
29
+ def as_dict(self) -> Dict[str, float]:
30
+ return {
31
+ "tp": self.tp,
32
+ "fp": self.fp,
33
+ "fn": self.fn,
34
+ "precision": self.get_precision(),
35
+ "recall": self.get_recall(),
36
+ "f1_score": self.get_f1_score(),
37
+ "total_count": self.total_count,
38
+ }
@@ -1,7 +1,11 @@
1
+ from collections import defaultdict
1
2
  from typing import Any, Dict, Iterator, List, Optional, Tuple
2
3
 
3
4
  from pydantic import BaseModel, Field
4
5
 
6
+ from rasa.core import IntentlessPolicy
7
+ from rasa.core.nlg.contextual_response_rephraser import ContextualResponseRephraser
8
+ from rasa.core.policies.enterprise_search_policy import EnterpriseSearchPolicy
5
9
  from rasa.dialogue_understanding.commands.prompt_command import PromptCommand
6
10
  from rasa.dialogue_understanding.generator.command_parser import parse_commands
7
11
  from rasa.dialogue_understanding_test.command_comparison import are_command_lists_equal
@@ -69,6 +73,8 @@ class DialogueUnderstandingOutput(BaseModel):
69
73
  commands: Dict[str, List[PromptCommand]]
70
74
  # List of prompts
71
75
  prompts: Optional[List[Dict[str, Any]]] = None
76
+ # Latency of the full message roundtrip
77
+ latency: Optional[float] = None
72
78
 
73
79
  class Config:
74
80
  """Skip validation for PromptCommand protocol as pydantic does not know how to
@@ -88,27 +94,41 @@ class DialogueUnderstandingOutput(BaseModel):
88
94
  def get_component_names_that_predicted_commands_or_have_llm_response(
89
95
  self,
90
96
  ) -> List[str]:
91
- """Get all component names that have predicted commands or recieved
97
+ """Get all relevant component names.
98
+
99
+ Components are relevant if they have predicted commands or received a
92
100
  non-empty response from LLM.
93
101
  """
102
+ # Exclude components that are not related to Dialogue Understanding
103
+ component_names_to_exclude = [
104
+ EnterpriseSearchPolicy.__name__,
105
+ IntentlessPolicy.__name__,
106
+ ContextualResponseRephraser.__name__,
107
+ ]
108
+
94
109
  component_names_that_predicted_commands = (
95
110
  [
96
111
  component_name
97
112
  for component_name, predicted_commands in self.commands.items()
98
113
  if predicted_commands
114
+ and component_name not in component_names_to_exclude
99
115
  ]
100
116
  if self.commands
101
117
  else []
102
118
  )
119
+
103
120
  components_with_prompts = (
104
121
  [
105
122
  str(prompt.get(KEY_COMPONENT_NAME, None))
106
123
  for prompt in self.prompts
107
124
  if prompt.get(KEY_LLM_RESPONSE_METADATA, None)
125
+ and prompt.get(KEY_COMPONENT_NAME, None)
126
+ not in component_names_to_exclude
108
127
  ]
109
128
  if self.prompts
110
129
  else []
111
130
  )
131
+
112
132
  return list(
113
133
  set(component_names_that_predicted_commands + components_with_prompts)
114
134
  )
@@ -290,41 +310,54 @@ class DialogueUnderstandingTestStep(BaseModel):
290
310
 
291
311
  return ""
292
312
 
293
- def get_latencies(self) -> List[float]:
313
+ def get_latencies(self) -> Dict[str, List[float]]:
294
314
  if self.dialogue_understanding_output is None:
295
- return []
315
+ return {}
296
316
 
297
- prompts = self.dialogue_understanding_output.get_component_name_to_prompt_info()
317
+ component_name_to_prompt_info = (
318
+ self.dialogue_understanding_output.get_component_name_to_prompt_info()
319
+ )
298
320
 
299
- return [
300
- prompt_data.get(KEY_LATENCY, 0.0)
301
- for prompt in prompts.values()
302
- for prompt_data in prompt
303
- ]
321
+ latencies = defaultdict(list)
322
+ for component_name, prompt_info_list in component_name_to_prompt_info.items():
323
+ for prompt_info in prompt_info_list:
324
+ latencies[component_name].append(prompt_info.get(KEY_LATENCY, 0.0))
304
325
 
305
- def get_completion_tokens(self) -> List[int]:
326
+ return latencies
327
+
328
+ def get_completion_tokens(self) -> Dict[str, List[float]]:
306
329
  if self.dialogue_understanding_output is None:
307
- return []
330
+ return {}
308
331
 
309
- prompts = self.dialogue_understanding_output.get_component_name_to_prompt_info()
332
+ component_name_to_prompt_info = (
333
+ self.dialogue_understanding_output.get_component_name_to_prompt_info()
334
+ )
310
335
 
311
- return [
312
- prompt_data.get(KEY_COMPLETION_TOKENS, 0)
313
- for prompt in prompts.values()
314
- for prompt_data in prompt
315
- ]
336
+ completion_tokens = defaultdict(list)
337
+ for component_name, prompt_info_list in component_name_to_prompt_info.items():
338
+ for prompt_info in prompt_info_list:
339
+ completion_tokens[component_name].append(
340
+ prompt_info.get(KEY_COMPLETION_TOKENS, 0.0)
341
+ )
342
+
343
+ return completion_tokens
316
344
 
317
- def get_prompt_tokens(self) -> List[int]:
345
+ def get_prompt_tokens(self) -> Dict[str, List[float]]:
318
346
  if self.dialogue_understanding_output is None:
319
- return []
347
+ return {}
320
348
 
321
- prompts = self.dialogue_understanding_output.get_component_name_to_prompt_info()
349
+ component_name_to_prompt_info = (
350
+ self.dialogue_understanding_output.get_component_name_to_prompt_info()
351
+ )
322
352
 
323
- return [
324
- prompt_data.get(KEY_PROMPT_TOKENS, 0)
325
- for prompt in prompts.values()
326
- for prompt_data in prompt
327
- ]
353
+ prompt_tokens = defaultdict(list)
354
+ for component_name, prompt_info_list in component_name_to_prompt_info.items():
355
+ for prompt_info in prompt_info_list:
356
+ prompt_tokens[component_name].append(
357
+ prompt_info.get(KEY_PROMPT_TOKENS, 0.0)
358
+ )
359
+
360
+ return prompt_tokens
328
361
 
329
362
 
330
363
  class DialogueUnderstandingTestCase(BaseModel):