rasa-pro 3.13.0rc2__py3-none-any.whl → 3.13.0rc3__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/core/channels/voice_stream/audiocodes.py +1 -1
- rasa/core/policies/enterprise_search_policy.py +159 -66
- rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +4 -1
- rasa/core/policies/flows/flow_executor.py +9 -3
- rasa/core/tracker_stores/redis_tracker_store.py +15 -5
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +5 -2
- rasa/dialogue_understanding/processor/command_processor.py +9 -7
- rasa/llm_fine_tuning/annotation_module.py +43 -11
- rasa/privacy/privacy_filter.py +57 -4
- rasa/privacy/privacy_manager.py +5 -5
- rasa/shared/core/constants.py +1 -0
- rasa/studio/pull/domains.py +14 -3
- rasa/version.py +1 -1
- {rasa_pro-3.13.0rc2.dist-info → rasa_pro-3.13.0rc3.dist-info}/METADATA +1 -1
- {rasa_pro-3.13.0rc2.dist-info → rasa_pro-3.13.0rc3.dist-info}/RECORD +18 -18
- {rasa_pro-3.13.0rc2.dist-info → rasa_pro-3.13.0rc3.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0rc2.dist-info → rasa_pro-3.13.0rc3.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0rc2.dist-info → rasa_pro-3.13.0rc3.dist-info}/entry_points.txt +0 -0
|
@@ -104,10 +104,10 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
|
|
|
104
104
|
|
|
105
105
|
def __init__(
|
|
106
106
|
self,
|
|
107
|
-
token: Optional[Text],
|
|
108
107
|
server_url: str,
|
|
109
108
|
asr_config: Dict,
|
|
110
109
|
tts_config: Dict,
|
|
110
|
+
token: Optional[Text] = None,
|
|
111
111
|
):
|
|
112
112
|
mark_as_beta_feature("Audiocodes (audiocodes_stream) Channel")
|
|
113
113
|
super().__init__(
|
|
@@ -4,7 +4,7 @@ import importlib.resources
|
|
|
4
4
|
import json
|
|
5
5
|
import os.path
|
|
6
6
|
import re
|
|
7
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple
|
|
8
8
|
|
|
9
9
|
import dotenv
|
|
10
10
|
import structlog
|
|
@@ -139,6 +139,8 @@ DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_RELEVANCY_CHECK_AND_CITATION_TEMPLATE = (
|
|
|
139
139
|
|
|
140
140
|
_ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN = re.compile(r"\[NO_RAG_ANSWER\]")
|
|
141
141
|
|
|
142
|
+
_ENTERPRISE_SEARCH_CITATION_PATTERN = re.compile(r"\[([^\]]+)\]")
|
|
143
|
+
|
|
142
144
|
|
|
143
145
|
class VectorStoreConnectionError(RasaException):
|
|
144
146
|
"""Exception raised for errors in connecting to the vector store."""
|
|
@@ -944,10 +946,18 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
944
946
|
|
|
945
947
|
@staticmethod
|
|
946
948
|
def post_process_citations(llm_answer: str) -> str:
|
|
947
|
-
"""Post-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
949
|
+
"""Post-processes the LLM answer to correctly number and sort citations and
|
|
950
|
+
sources.
|
|
951
|
+
|
|
952
|
+
- Handles both single `[1]` and grouped `[1, 3]` citations.
|
|
953
|
+
- Rewrites the numbers in square brackets in the answer text to start from 1
|
|
954
|
+
and be sorted within each group.
|
|
955
|
+
- Reorders the sources according to the order of their first appearance
|
|
956
|
+
in the text.
|
|
957
|
+
- Removes citations from the text that point to sources missing from
|
|
958
|
+
the source list.
|
|
959
|
+
- Keeps sources that are not cited in the text, placing them at the end
|
|
960
|
+
of the list.
|
|
951
961
|
|
|
952
962
|
Args:
|
|
953
963
|
llm_answer: The LLM answer.
|
|
@@ -961,77 +971,160 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
961
971
|
|
|
962
972
|
# Split llm_answer into answer and citations
|
|
963
973
|
try:
|
|
964
|
-
|
|
974
|
+
answer_part, sources_part = llm_answer.rsplit("Sources:", 1)
|
|
965
975
|
except ValueError:
|
|
966
|
-
# if there is no "Sources:"
|
|
967
|
-
return llm_answer
|
|
968
|
-
|
|
969
|
-
# Find all source references in the answer
|
|
970
|
-
pattern = r"\[\s*(\d+(?:\s*,\s*\d+)*)\s*\]"
|
|
971
|
-
matches = re.findall(pattern, answer)
|
|
972
|
-
old_source_indices = [
|
|
973
|
-
int(num.strip()) for match in matches for num in match.split(",")
|
|
974
|
-
]
|
|
976
|
+
# if there is no "Sources:" separator, return the original llm_answer
|
|
977
|
+
return llm_answer.strip()
|
|
975
978
|
|
|
976
|
-
#
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
for old_index in old_indices
|
|
995
|
-
if old_index in renumber_mapping
|
|
996
|
-
]
|
|
997
|
-
if not new_indices:
|
|
998
|
-
continue
|
|
999
|
-
|
|
1000
|
-
word = word.replace(
|
|
1001
|
-
match, f"{', '.join(map(str, new_indices))}"
|
|
1002
|
-
)
|
|
1003
|
-
else:
|
|
1004
|
-
old_index = int(match.strip("[].,:;?!"))
|
|
1005
|
-
new_index = renumber_mapping.get(old_index)
|
|
1006
|
-
if not new_index:
|
|
1007
|
-
continue
|
|
979
|
+
# Parse the sources block to extract valid sources and other lines
|
|
980
|
+
valid_sources, other_source_lines = EnterpriseSearchPolicy._parse_sources_block(
|
|
981
|
+
sources_part
|
|
982
|
+
)
|
|
983
|
+
|
|
984
|
+
# Find all unique, valid citations in the answer text in their order
|
|
985
|
+
# of appearance
|
|
986
|
+
cited_order = EnterpriseSearchPolicy._get_cited_order(
|
|
987
|
+
answer_part, valid_sources
|
|
988
|
+
)
|
|
989
|
+
|
|
990
|
+
# Create a mapping from the old source numbers to the new, sequential numbers.
|
|
991
|
+
# For example, if the citation order in the text was [3, 1, 2], this map
|
|
992
|
+
# becomes {3: 1, 1: 2, 2: 3}. This allows for a quick lookup when rewriting
|
|
993
|
+
# the citations
|
|
994
|
+
renumbering_map = {
|
|
995
|
+
old_num: new_num + 1 for new_num, old_num in enumerate(cited_order)
|
|
996
|
+
}
|
|
1008
997
|
|
|
1009
|
-
|
|
1010
|
-
|
|
998
|
+
# Rewrite the citations in the answer text based on the renumbering map
|
|
999
|
+
processed_answer = EnterpriseSearchPolicy._rewrite_answer_citations(
|
|
1000
|
+
answer_part, renumbering_map
|
|
1001
|
+
)
|
|
1002
|
+
|
|
1003
|
+
# Build the new list of sources
|
|
1004
|
+
new_sources_list = EnterpriseSearchPolicy._build_final_sources_list(
|
|
1005
|
+
cited_order,
|
|
1006
|
+
renumbering_map,
|
|
1007
|
+
valid_sources,
|
|
1008
|
+
other_source_lines,
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
if len(new_sources_list) > 0:
|
|
1012
|
+
processed_answer += "\nSources:\n" + "\n".join(new_sources_list)
|
|
1013
|
+
|
|
1014
|
+
return processed_answer
|
|
1015
|
+
|
|
1016
|
+
@staticmethod
|
|
1017
|
+
def _parse_sources_block(sources_part: str) -> Tuple[Dict[int, str], List[str]]:
|
|
1018
|
+
"""Parses the sources block from the LLM response.
|
|
1019
|
+
Returns a tuple containing:
|
|
1020
|
+
- A dictionary of valid sources matching the "[1] ..." format,
|
|
1021
|
+
where the key is the source number
|
|
1022
|
+
- A list of other source lines that do not match the specified format
|
|
1023
|
+
"""
|
|
1024
|
+
valid_sources: Dict[int, str] = {}
|
|
1025
|
+
other_source_lines: List[str] = []
|
|
1026
|
+
source_line_pattern = re.compile(r"^\s*\[(\d+)\](.*)")
|
|
1011
1027
|
|
|
1012
|
-
|
|
1013
|
-
joined_answer = " ".join(new_answer)
|
|
1014
|
-
joined_answer += "\nSources:\n"
|
|
1028
|
+
source_lines = sources_part.strip().split("\n")
|
|
1015
1029
|
|
|
1016
|
-
|
|
1030
|
+
for line in source_lines:
|
|
1031
|
+
line = line.strip()
|
|
1032
|
+
if not line:
|
|
1033
|
+
continue
|
|
1017
1034
|
|
|
1018
|
-
|
|
1019
|
-
pattern = r"(?<=\[)\d+"
|
|
1020
|
-
match = re.search(pattern, line)
|
|
1035
|
+
match = source_line_pattern.match(line)
|
|
1021
1036
|
if match:
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1037
|
+
num = int(match.group(1))
|
|
1038
|
+
valid_sources[num] = line
|
|
1039
|
+
else:
|
|
1040
|
+
other_source_lines.append(line)
|
|
1041
|
+
|
|
1042
|
+
return valid_sources, other_source_lines
|
|
1043
|
+
|
|
1044
|
+
@staticmethod
|
|
1045
|
+
def _get_cited_order(
|
|
1046
|
+
answer_part: str, available_sources: Dict[int, str]
|
|
1047
|
+
) -> List[int]:
|
|
1048
|
+
"""Find all unique, valid citations in the answer text in their order
|
|
1049
|
+
# of appearance
|
|
1050
|
+
"""
|
|
1051
|
+
cited_order: List[int] = []
|
|
1052
|
+
seen_indices = set()
|
|
1053
|
+
|
|
1054
|
+
for match in _ENTERPRISE_SEARCH_CITATION_PATTERN.finditer(answer_part):
|
|
1055
|
+
content = match.group(1)
|
|
1056
|
+
indices_str = [s.strip() for s in content.split(",")]
|
|
1057
|
+
for index_str in indices_str:
|
|
1058
|
+
if index_str.isdigit():
|
|
1059
|
+
index = int(index_str)
|
|
1060
|
+
if index in available_sources and index not in seen_indices:
|
|
1061
|
+
cited_order.append(index)
|
|
1062
|
+
seen_indices.add(index)
|
|
1063
|
+
|
|
1064
|
+
return cited_order
|
|
1065
|
+
|
|
1066
|
+
@staticmethod
|
|
1067
|
+
def _rewrite_answer_citations(
|
|
1068
|
+
answer_part: str, renumber_map: Dict[int, int]
|
|
1069
|
+
) -> str:
|
|
1070
|
+
"""Rewrites the citations in the answer text based on the renumbering map."""
|
|
1071
|
+
|
|
1072
|
+
def replacer(match: re.Match) -> str:
|
|
1073
|
+
content = match.group(1)
|
|
1074
|
+
old_indices_str = [s.strip() for s in content.split(",")]
|
|
1075
|
+
new_indices = [
|
|
1076
|
+
renumber_map[int(s)]
|
|
1077
|
+
for s in old_indices_str
|
|
1078
|
+
if s.isdigit() and int(s) in renumber_map
|
|
1079
|
+
]
|
|
1080
|
+
if not new_indices:
|
|
1081
|
+
return ""
|
|
1082
|
+
|
|
1083
|
+
return f"[{', '.join(map(str, sorted(list(set(new_indices)))))}]"
|
|
1084
|
+
|
|
1085
|
+
processed_answer = _ENTERPRISE_SEARCH_CITATION_PATTERN.sub(
|
|
1086
|
+
replacer, answer_part
|
|
1087
|
+
)
|
|
1088
|
+
|
|
1089
|
+
# Clean up formatting after replacements
|
|
1090
|
+
processed_answer = re.sub(r"\s+([,.?])", r"\1", processed_answer)
|
|
1091
|
+
processed_answer = processed_answer.replace("[]", " ")
|
|
1092
|
+
processed_answer = re.sub(r"\s+", " ", processed_answer)
|
|
1093
|
+
processed_answer = processed_answer.strip()
|
|
1094
|
+
|
|
1095
|
+
return processed_answer
|
|
1096
|
+
|
|
1097
|
+
@staticmethod
|
|
1098
|
+
def _build_final_sources_list(
|
|
1099
|
+
cited_order: List[int],
|
|
1100
|
+
renumbering_map: Dict[int, int],
|
|
1101
|
+
valid_sources: Dict[int, str],
|
|
1102
|
+
other_source_lines: List[str],
|
|
1103
|
+
) -> List[str]:
|
|
1104
|
+
"""Builds the final list of sources based on the cited order and
|
|
1105
|
+
renumbering map.
|
|
1106
|
+
"""
|
|
1107
|
+
new_sources_list: List[str] = []
|
|
1108
|
+
|
|
1109
|
+
# First, add the sorted, used sources
|
|
1110
|
+
for old_num in cited_order:
|
|
1111
|
+
new_num = renumbering_map[old_num]
|
|
1112
|
+
source_line = valid_sources[old_num]
|
|
1113
|
+
new_sources_list.append(
|
|
1114
|
+
source_line.replace(f"[{old_num}]", f"[{new_num}]", 1)
|
|
1115
|
+
)
|
|
1026
1116
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1117
|
+
# Then, add the unused but validly numbered sources
|
|
1118
|
+
used_source_nums = set(cited_order)
|
|
1119
|
+
# Sort by number to ensure a consistent order for uncited sources
|
|
1120
|
+
for num, line in sorted(valid_sources.items()):
|
|
1121
|
+
if num not in used_source_nums:
|
|
1122
|
+
new_sources_list.append(line)
|
|
1031
1123
|
|
|
1032
|
-
|
|
1124
|
+
# Finally, add any other source lines
|
|
1125
|
+
new_sources_list.extend(other_source_lines)
|
|
1033
1126
|
|
|
1034
|
-
return
|
|
1127
|
+
return new_sources_list
|
|
1035
1128
|
|
|
1036
1129
|
@classmethod
|
|
1037
1130
|
def _perform_health_checks(
|
rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
Based on the provided documents and the recent conversation context, answer the following question.
|
|
1
|
+
{% if check_relevancy %}Based on the provided documents and the recent conversation context, answer the following question.
|
|
2
2
|
Before responding, ensure the answer is directly supported by the documents or context.
|
|
3
3
|
Do not make assumptions or infer beyond the given information.
|
|
4
4
|
Only answer if you are more than 80% confident that the response is fully supported.
|
|
5
5
|
If the answer cannot be determined, respond with: [NO_RAG_ANSWER]
|
|
6
|
+
{% else %}Given the following information, please provide an answer based on the provided documents and the context of the recent conversation.
|
|
7
|
+
If the answer is not known or cannot be determined from the provided documents or context, please state that you do not know to the user.
|
|
8
|
+
{% endif %}
|
|
6
9
|
|
|
7
10
|
### Relevant Documents
|
|
8
11
|
Use the following documents to answer the question:
|
|
@@ -41,6 +41,7 @@ from rasa.dialogue_understanding.patterns.internal_error import (
|
|
|
41
41
|
InternalErrorPatternFlowStackFrame,
|
|
42
42
|
)
|
|
43
43
|
from rasa.dialogue_understanding.patterns.search import SearchPatternFlowStackFrame
|
|
44
|
+
from rasa.dialogue_understanding.patterns.user_silence import FLOW_PATTERN_USER_SILENCE
|
|
44
45
|
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
45
46
|
from rasa.dialogue_understanding.stack.frames import (
|
|
46
47
|
BaseFlowStackFrame,
|
|
@@ -590,9 +591,9 @@ def run_step(
|
|
|
590
591
|
initial_events.append(FlowStarted(flow.id, metadata=stack.current_context()))
|
|
591
592
|
|
|
592
593
|
# FLow does not start with collect step or we are not in collect information pattern
|
|
593
|
-
if _first_step_is_not_collect(
|
|
594
|
-
|
|
595
|
-
)
|
|
594
|
+
if _first_step_is_not_collect(step, previous_step_id) and not (
|
|
595
|
+
_in_collect_information_pattern(flow) or _in_pattern_user_silence(flow)
|
|
596
|
+
):
|
|
596
597
|
_append_global_silence_timeout_event(initial_events, tracker)
|
|
597
598
|
|
|
598
599
|
if isinstance(step, CollectInformationFlowStep):
|
|
@@ -650,6 +651,11 @@ def _in_collect_information_pattern(flow: Flow) -> bool:
|
|
|
650
651
|
return flow.id == FLOW_PATTERN_COLLECT_INFORMATION
|
|
651
652
|
|
|
652
653
|
|
|
654
|
+
def _in_pattern_user_silence(flow: Flow) -> bool:
|
|
655
|
+
"""Check if the current flow is a user silence pattern."""
|
|
656
|
+
return flow.id == FLOW_PATTERN_USER_SILENCE
|
|
657
|
+
|
|
658
|
+
|
|
653
659
|
def _run_end_step(
|
|
654
660
|
flow: Flow,
|
|
655
661
|
flows: FlowsList,
|
|
@@ -88,17 +88,21 @@ class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
|
88
88
|
if not timeout and self.record_exp:
|
|
89
89
|
timeout = self.record_exp
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
# if the sender_id starts with the key prefix, we remove it
|
|
92
|
+
# this is used to avoid storing the prefix twice
|
|
93
|
+
sender_id = tracker.sender_id
|
|
94
|
+
if sender_id.startswith(self.key_prefix):
|
|
95
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
96
|
+
|
|
97
|
+
stored = self.red.get(self.key_prefix + sender_id)
|
|
92
98
|
|
|
93
99
|
if stored is not None:
|
|
94
|
-
prior_tracker = self.deserialise_tracker(
|
|
100
|
+
prior_tracker = self.deserialise_tracker(sender_id, stored)
|
|
95
101
|
|
|
96
102
|
tracker = self._merge_trackers(prior_tracker, tracker)
|
|
97
103
|
|
|
98
104
|
serialised_tracker = self.serialise_tracker(tracker)
|
|
99
|
-
self.red.set(
|
|
100
|
-
self.key_prefix + tracker.sender_id, serialised_tracker, ex=timeout
|
|
101
|
-
)
|
|
105
|
+
self.red.set(self.key_prefix + sender_id, serialised_tracker, ex=timeout)
|
|
102
106
|
|
|
103
107
|
async def delete(self, sender_id: Text) -> None:
|
|
104
108
|
"""Delete tracker for the given sender_id.
|
|
@@ -113,6 +117,9 @@ class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
|
113
117
|
)
|
|
114
118
|
return None
|
|
115
119
|
|
|
120
|
+
if sender_id.startswith(self.key_prefix):
|
|
121
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
122
|
+
|
|
116
123
|
self.red.delete(self.key_prefix + sender_id)
|
|
117
124
|
structlogger.info(
|
|
118
125
|
"redis_tracker_store.delete.deleted_tracker",
|
|
@@ -156,6 +163,9 @@ class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
|
156
163
|
sender_id: Conversation ID to fetch the tracker for.
|
|
157
164
|
fetch_all_sessions: Whether to fetch all sessions or only the last one.
|
|
158
165
|
"""
|
|
166
|
+
if sender_id.startswith(self.key_prefix):
|
|
167
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
168
|
+
|
|
159
169
|
stored = self.red.get(self.key_prefix + sender_id)
|
|
160
170
|
if stored is None:
|
|
161
171
|
structlogger.debug(
|
|
@@ -139,7 +139,8 @@ flows:
|
|
|
139
139
|
steps:
|
|
140
140
|
- noop: true
|
|
141
141
|
next:
|
|
142
|
-
#
|
|
142
|
+
# Fallback for ChitChat command when IntentlessPolicy isn't set, but
|
|
143
|
+
# pattern_chitchat invokes action_trigger_chitchat
|
|
143
144
|
- if: context.reason is "cannot_handle_chitchat"
|
|
144
145
|
then:
|
|
145
146
|
- action: utter_cannot_handle
|
|
@@ -164,7 +165,9 @@ flows:
|
|
|
164
165
|
description: Conversation repair flow for off-topic interactions that won't disrupt the main conversation
|
|
165
166
|
name: pattern chitchat
|
|
166
167
|
steps:
|
|
167
|
-
- action:
|
|
168
|
+
- action: utter_cannot_handle
|
|
169
|
+
# To enable free-form response use:
|
|
170
|
+
# - action: utter_free_chitchat_response
|
|
168
171
|
|
|
169
172
|
pattern_clarification:
|
|
170
173
|
description: Conversation repair flow for handling ambiguous requests that could match multiple flows
|
|
@@ -64,12 +64,6 @@ from rasa.shared.nlu.constants import COMMANDS
|
|
|
64
64
|
|
|
65
65
|
structlogger = structlog.get_logger()
|
|
66
66
|
|
|
67
|
-
CANNOT_HANDLE_REASON = (
|
|
68
|
-
"A command generator attempted to set a slot "
|
|
69
|
-
"with a value extracted by an extractor "
|
|
70
|
-
"that is incompatible with the slot mapping type."
|
|
71
|
-
)
|
|
72
|
-
|
|
73
67
|
|
|
74
68
|
def contains_command(commands: List[Command], typ: Type[Command]) -> bool:
|
|
75
69
|
"""Check if a list of commands contains a command of a given type.
|
|
@@ -587,6 +581,11 @@ def clean_up_slot_command(
|
|
|
587
581
|
"command_processor.clean_up_slot_command.skip_command_slot_not_in_domain",
|
|
588
582
|
command=command,
|
|
589
583
|
)
|
|
584
|
+
resulting_commands.append(
|
|
585
|
+
CannotHandleCommand(
|
|
586
|
+
reason="The slot predicted by the LLM is not defined in the domain."
|
|
587
|
+
)
|
|
588
|
+
)
|
|
590
589
|
return resulting_commands
|
|
591
590
|
|
|
592
591
|
if not should_slot_be_set(slot, command, resulting_commands):
|
|
@@ -605,7 +604,10 @@ def clean_up_slot_command(
|
|
|
605
604
|
for command in resulting_commands
|
|
606
605
|
)
|
|
607
606
|
|
|
608
|
-
cannot_handle = CannotHandleCommand(
|
|
607
|
+
cannot_handle = CannotHandleCommand(
|
|
608
|
+
reason="A command generator attempted to set a slot with a value extracted "
|
|
609
|
+
"by an extractor that is incompatible with the slot mapping type."
|
|
610
|
+
)
|
|
609
611
|
if not slot_command_exists_already and cannot_handle not in resulting_commands:
|
|
610
612
|
resulting_commands.append(cannot_handle)
|
|
611
613
|
|
|
@@ -9,8 +9,8 @@ from rasa.e2e_test.e2e_test_case import ActualStepOutput, TestCase, TestStep, Te
|
|
|
9
9
|
from rasa.e2e_test.e2e_test_runner import TEST_TURNS_TYPE, E2ETestRunner
|
|
10
10
|
from rasa.llm_fine_tuning.conversations import Conversation, ConversationStep
|
|
11
11
|
from rasa.llm_fine_tuning.storage import StorageContext
|
|
12
|
-
from rasa.shared.core.constants import USER
|
|
13
|
-
from rasa.shared.core.events import UserUttered
|
|
12
|
+
from rasa.shared.core.constants import BOT, USER
|
|
13
|
+
from rasa.shared.core.events import BotUttered, UserUttered
|
|
14
14
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
15
15
|
from rasa.shared.exceptions import FinetuningDataPreparationException
|
|
16
16
|
from rasa.shared.nlu.constants import LLM_COMMANDS, LLM_PROMPT
|
|
@@ -83,16 +83,18 @@ def generate_conversation(
|
|
|
83
83
|
Conversation.
|
|
84
84
|
"""
|
|
85
85
|
steps = []
|
|
86
|
-
tracker_event_indices = [
|
|
87
|
-
i for i, event in enumerate(tracker.events) if isinstance(event, UserUttered)
|
|
88
|
-
]
|
|
89
|
-
|
|
90
|
-
if len(test_case.steps) != len(tracker_event_indices):
|
|
91
|
-
raise FinetuningDataPreparationException(
|
|
92
|
-
"Number of test case steps and tracker events do not match."
|
|
93
|
-
)
|
|
94
86
|
|
|
95
87
|
if assertions_used:
|
|
88
|
+
tracker_event_indices = [
|
|
89
|
+
i
|
|
90
|
+
for i, event in enumerate(tracker.events)
|
|
91
|
+
if isinstance(event, UserUttered)
|
|
92
|
+
]
|
|
93
|
+
if len(test_case.steps) != len(tracker_event_indices):
|
|
94
|
+
raise FinetuningDataPreparationException(
|
|
95
|
+
"Number of test case steps and tracker events do not match."
|
|
96
|
+
)
|
|
97
|
+
|
|
96
98
|
# we only have user steps, extract the bot response from the bot uttered
|
|
97
99
|
# events of the test turn
|
|
98
100
|
for i, (original_step, tracker_event_index) in enumerate(
|
|
@@ -110,8 +112,30 @@ def generate_conversation(
|
|
|
110
112
|
)
|
|
111
113
|
steps.extend(_create_bot_test_steps(test_turns[i]))
|
|
112
114
|
else:
|
|
115
|
+
tracker_event_indices = [
|
|
116
|
+
i
|
|
117
|
+
for i, event in enumerate(tracker.events)
|
|
118
|
+
if isinstance(event, UserUttered) or isinstance(event, BotUttered)
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
# Generally, we expect one or more bot response(s) for each user utterance
|
|
122
|
+
# in the test case, so that we can evaluate the actual bot response.
|
|
123
|
+
# If the test case ends with one or more user utterance(s) instead,
|
|
124
|
+
# we should thus trim those from the test case steps.
|
|
125
|
+
# This only applies to test cases that have at least one bot utterance;
|
|
126
|
+
# otherwise, all test case steps would be removed.
|
|
127
|
+
has_bot_utterance = any(step.actor == BOT for step in test_case.steps)
|
|
128
|
+
i = len(test_case.steps)
|
|
129
|
+
if has_bot_utterance:
|
|
130
|
+
while i > 0 and test_case.steps[i - 1].actor == USER:
|
|
131
|
+
i -= 1
|
|
132
|
+
test_case_steps = test_case.steps[:i]
|
|
133
|
+
|
|
134
|
+
# If the number of test case steps and tracker events differ,
|
|
135
|
+
# using zip ensures we only process pairs that exist in both lists.
|
|
136
|
+
# Prevents index errors and ensures we don't process unmatched steps or events.
|
|
113
137
|
for i, (original_step, tracker_event_index) in enumerate(
|
|
114
|
-
zip(
|
|
138
|
+
zip(test_case_steps, tracker_event_indices)
|
|
115
139
|
):
|
|
116
140
|
if original_step.actor == USER:
|
|
117
141
|
previous_turn = _get_previous_actual_step_output(test_turns, i)
|
|
@@ -127,6 +151,14 @@ def generate_conversation(
|
|
|
127
151
|
else:
|
|
128
152
|
steps.append(original_step)
|
|
129
153
|
|
|
154
|
+
# the tracker should only include events up to the last bot utterance
|
|
155
|
+
# so that the resulting transcript ends with the last bot utterance too
|
|
156
|
+
# only applies to test cases that have at least one bot utterance
|
|
157
|
+
if has_bot_utterance and test_case.steps and test_case.steps[-1].actor == USER:
|
|
158
|
+
event_to_go_to = tracker_event_indices[len(test_case_steps)] - 1
|
|
159
|
+
timestamp = tracker.events[event_to_go_to].timestamp
|
|
160
|
+
tracker = tracker.travel_back_in_time(timestamp)
|
|
161
|
+
|
|
130
162
|
# Some messages in an e2e test case could be mapped to commands via
|
|
131
163
|
# 'NLUCommandAdapter', e.g. the message will not be annotated with a prompt and
|
|
132
164
|
# commands pair. Only convert steps that have a prompt and commands present into a
|
rasa/privacy/privacy_filter.py
CHANGED
|
@@ -2,6 +2,7 @@ import copy
|
|
|
2
2
|
import datetime
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any, Dict, List, Optional
|
|
6
7
|
|
|
7
8
|
import structlog
|
|
@@ -60,8 +61,17 @@ class PrivacyFilter:
|
|
|
60
61
|
def _load_gliner_model() -> Optional[Any]:
|
|
61
62
|
"""Load the GLiNER model for PII detection."""
|
|
62
63
|
local_model_path = os.getenv(GLINER_MODEL_PATH_ENV_VAR_NAME)
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
cache_dir_env_value = os.getenv(HUGGINGFACE_CACHE_DIR_ENV_VAR_NAME)
|
|
65
|
+
cache_dir = Path(cache_dir_env_value).resolve() if cache_dir_env_value else None
|
|
66
|
+
model_path = (
|
|
67
|
+
Path(local_model_path).resolve() if local_model_path else DEFAULT_PII_MODEL
|
|
68
|
+
)
|
|
69
|
+
local_files_only = isinstance(model_path, Path) and model_path.exists()
|
|
70
|
+
|
|
71
|
+
structlogger.debug(
|
|
72
|
+
"rasa.privacy.privacy_filter.loading_gliner_model",
|
|
73
|
+
local_files_only=local_files_only,
|
|
74
|
+
)
|
|
65
75
|
|
|
66
76
|
try:
|
|
67
77
|
from gliner import GLiNER
|
|
@@ -69,6 +79,7 @@ class PrivacyFilter:
|
|
|
69
79
|
return GLiNER.from_pretrained(
|
|
70
80
|
model_path,
|
|
71
81
|
cache_dir=cache_dir,
|
|
82
|
+
local_files_only=local_files_only,
|
|
72
83
|
)
|
|
73
84
|
except ImportError:
|
|
74
85
|
structlogger.warning(
|
|
@@ -193,7 +204,9 @@ class PrivacyFilter:
|
|
|
193
204
|
|
|
194
205
|
for key, slot in anonymized_slots.items():
|
|
195
206
|
original_slot_value = key.split(":", 1)[1]
|
|
196
|
-
anonymized_text =
|
|
207
|
+
anonymized_text = self._smart_replace(
|
|
208
|
+
user_event.text, original_slot_value, slot.value
|
|
209
|
+
)
|
|
197
210
|
user_event.text = anonymized_text
|
|
198
211
|
|
|
199
212
|
anonymized_parse_data[TEXT_KEY] = anonymized_text
|
|
@@ -232,7 +245,9 @@ class PrivacyFilter:
|
|
|
232
245
|
|
|
233
246
|
for key, slot in anonymized_slots.items():
|
|
234
247
|
original_slot_value = key.split(":", 1)[1]
|
|
235
|
-
anonymized_text =
|
|
248
|
+
anonymized_text = self._smart_replace(
|
|
249
|
+
bot_event.text, original_slot_value, slot.value
|
|
250
|
+
)
|
|
236
251
|
bot_event.text = anonymized_text
|
|
237
252
|
|
|
238
253
|
bot_event.text = self._anonymize_edge_cases(bot_event.text, anonymized_slots)
|
|
@@ -338,3 +353,41 @@ class PrivacyFilter:
|
|
|
338
353
|
text = text.replace(entity_value, self._mask(entity[ENTITY_LABEL_KEY]))
|
|
339
354
|
|
|
340
355
|
return text
|
|
356
|
+
|
|
357
|
+
@staticmethod
|
|
358
|
+
def _smart_replace(text: str, original_value: str, replacement: str) -> str:
|
|
359
|
+
"""Replace original_value with replacement in text.
|
|
360
|
+
|
|
361
|
+
This method performs a string replacement in the text,
|
|
362
|
+
with special handling for floats.
|
|
363
|
+
If original_value is a float string like "24.0",
|
|
364
|
+
also tries replacing the integer version "24".
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
text (str): The text to perform replacements on
|
|
368
|
+
original_value (str): The value to replace
|
|
369
|
+
replacement (str): The replacement value
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
str: The text with replacements applied
|
|
373
|
+
"""
|
|
374
|
+
# First try the original replacement
|
|
375
|
+
result = text.replace(original_value, replacement)
|
|
376
|
+
if text != result:
|
|
377
|
+
return result
|
|
378
|
+
|
|
379
|
+
# If replacement didn't happen and it's a float,
|
|
380
|
+
# try replacing the integer version
|
|
381
|
+
if "." in original_value:
|
|
382
|
+
try:
|
|
383
|
+
float_val = float(original_value)
|
|
384
|
+
if float_val.is_integer():
|
|
385
|
+
int_version = str(int(float_val))
|
|
386
|
+
result = result.replace(int_version, replacement)
|
|
387
|
+
except ValueError:
|
|
388
|
+
structlogger.warning(
|
|
389
|
+
"rasa.privacy.privacy_filter.smart_replace_float_error",
|
|
390
|
+
event_info="Unable to anonymize float value.",
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
return result
|
rasa/privacy/privacy_manager.py
CHANGED
|
@@ -352,7 +352,7 @@ class BackgroundPrivacyManager:
|
|
|
352
352
|
if not full_tracker:
|
|
353
353
|
structlogger.debug(
|
|
354
354
|
"rasa.privacy_manager.no_tracker_found_for_sender_id",
|
|
355
|
-
|
|
355
|
+
sender_id=key,
|
|
356
356
|
)
|
|
357
357
|
continue
|
|
358
358
|
|
|
@@ -374,7 +374,7 @@ class BackgroundPrivacyManager:
|
|
|
374
374
|
|
|
375
375
|
structlogger.info(
|
|
376
376
|
"rasa.privacy_manager.save_tracker_after_deletion",
|
|
377
|
-
|
|
377
|
+
sender_id=key,
|
|
378
378
|
event_info="Saved tracker with events not scheduled "
|
|
379
379
|
"for deletion yet.",
|
|
380
380
|
)
|
|
@@ -523,7 +523,7 @@ class BackgroundPrivacyManager:
|
|
|
523
523
|
):
|
|
524
524
|
structlogger.info(
|
|
525
525
|
"rasa.privacy_manager.anonymizing_tracker_session",
|
|
526
|
-
|
|
526
|
+
sender_id=session.sender_id,
|
|
527
527
|
last_event_timestamp=last_event_timestamp,
|
|
528
528
|
triggered_by="anonymization_cron_job",
|
|
529
529
|
)
|
|
@@ -539,7 +539,7 @@ class BackgroundPrivacyManager:
|
|
|
539
539
|
uneligible_events.extend(events)
|
|
540
540
|
structlogger.debug(
|
|
541
541
|
"rasa.privacy_manager.session_not_valid_for_anonymization",
|
|
542
|
-
|
|
542
|
+
sender_id=session.sender_id,
|
|
543
543
|
session_id=session.sender_id,
|
|
544
544
|
last_event_timestamp=last_event_timestamp,
|
|
545
545
|
)
|
|
@@ -575,7 +575,7 @@ class BackgroundPrivacyManager:
|
|
|
575
575
|
|
|
576
576
|
structlogger.info(
|
|
577
577
|
"rasa.privacy_manager.tracker_session_scheduled_for_deletion",
|
|
578
|
-
|
|
578
|
+
sender_id=full_tracker.sender_id,
|
|
579
579
|
last_event_timestamp=last_event_timestamp,
|
|
580
580
|
triggered_by="deletion_cron_job",
|
|
581
581
|
)
|
rasa/shared/core/constants.py
CHANGED
|
@@ -182,6 +182,7 @@ class SetSlotExtractor(Enum):
|
|
|
182
182
|
# the keys for `State` (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
|
|
183
183
|
# represent the origin of a `SubState`
|
|
184
184
|
USER = "user"
|
|
185
|
+
BOT = "bot"
|
|
185
186
|
SLOTS = "slots"
|
|
186
187
|
|
|
187
188
|
USE_TEXT_FOR_FEATURIZATION = "use_text_for_featurization"
|
rasa/studio/pull/domains.py
CHANGED
|
@@ -15,8 +15,7 @@ def merge_domain(
|
|
|
15
15
|
data_local: TrainingDataImporter,
|
|
16
16
|
domain_path: Path,
|
|
17
17
|
) -> None:
|
|
18
|
-
"""
|
|
19
|
-
Merges the domain from Rasa Studio with the local domain.
|
|
18
|
+
"""Merges the domain from Rasa Studio with the local domain.
|
|
20
19
|
|
|
21
20
|
Args:
|
|
22
21
|
data_from_studio: The training data importer for the Rasa Studio domain.
|
|
@@ -29,10 +28,22 @@ def merge_domain(
|
|
|
29
28
|
else:
|
|
30
29
|
all_local_domain_files = data_local.get_domain_files([str(domain_path)])
|
|
31
30
|
|
|
31
|
+
studio_domain_file_path = domain_path / STUDIO_DOMAIN_FILENAME
|
|
32
|
+
|
|
32
33
|
# leftover_domain represents the items in the studio
|
|
33
34
|
# domain that are not in the local domain
|
|
34
35
|
leftover_domain = data_from_studio.get_user_domain()
|
|
35
36
|
for file_path in all_local_domain_files:
|
|
37
|
+
if file_path == str(studio_domain_file_path):
|
|
38
|
+
# we need to exclude the studio domain file from the merge,
|
|
39
|
+
# since we want to dump ALL the remaining items to this path
|
|
40
|
+
# after the merge. if we include it here, we will remove the existing
|
|
41
|
+
# items from the leftover domain and after this loop we will
|
|
42
|
+
# overwrite the studio domain file with the remaining items in
|
|
43
|
+
# the leftover domain - this means we loose the items that were
|
|
44
|
+
# in the studio domain file before we started the merge.
|
|
45
|
+
continue
|
|
46
|
+
|
|
36
47
|
# For each local domain file, we do a partial merge
|
|
37
48
|
local_domain = Domain.from_file(str(file_path))
|
|
38
49
|
updated_local_domain = local_domain.partial_merge(leftover_domain)
|
|
@@ -46,4 +57,4 @@ def merge_domain(
|
|
|
46
57
|
|
|
47
58
|
# If there are still items in leftover_domain, persist them
|
|
48
59
|
if not leftover_domain.is_empty():
|
|
49
|
-
leftover_domain.persist(
|
|
60
|
+
leftover_domain.persist(studio_domain_file_path)
|
rasa/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rasa-pro
|
|
3
|
-
Version: 3.13.
|
|
3
|
+
Version: 3.13.0rc3
|
|
4
4
|
Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
|
|
5
5
|
Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
|
|
6
6
|
Author: Rasa Technologies GmbH
|
|
@@ -270,7 +270,7 @@ rasa/core/channels/voice_stream/asr/asr_event.py,sha256=skPwrkRrcsptmeWXu9q68i4B
|
|
|
270
270
|
rasa/core/channels/voice_stream/asr/azure.py,sha256=dUFxtNVVwGM2D1VyqQ5FWeSpKwUQekMXUxWZv6tPJ7w,6114
|
|
271
271
|
rasa/core/channels/voice_stream/asr/deepgram.py,sha256=9cIqRuv9gWzOfEKxeDbhijGoT8EPUV7Oo493WXaHlBo,5682
|
|
272
272
|
rasa/core/channels/voice_stream/audio_bytes.py,sha256=3V0QQplPD-kVfebaaeVcKgV7pwIJyjnTenujVD3y3sY,340
|
|
273
|
-
rasa/core/channels/voice_stream/audiocodes.py,sha256=
|
|
273
|
+
rasa/core/channels/voice_stream/audiocodes.py,sha256=TbLC3iuupyA8d8xdxBHVCtljKidFT-ZzLH9LvMPsxEI,12349
|
|
274
274
|
rasa/core/channels/voice_stream/browser_audio.py,sha256=KDUexINUh1gElQ_2ccpAWltlH-pdakm-x1L6bvKffUY,3931
|
|
275
275
|
rasa/core/channels/voice_stream/call_state.py,sha256=fbwVbT0ddE7AjTYjx-Mq5jBMEGXanbug5wlBwstaews,899
|
|
276
276
|
rasa/core/channels/voice_stream/genesys.py,sha256=-PL1y0b2dJClM-S000loaDUWbm8qwcFSYwYaNaPG_9c,17708
|
|
@@ -320,15 +320,15 @@ rasa/core/nlg/translate.py,sha256=PBMTbIgdkhx8rhzqv6h0u5r9jqdfiVIh7u0qb363sJA,18
|
|
|
320
320
|
rasa/core/persistor.py,sha256=7LCZHAwCM-xrUI38aaJ5dkxJvLdJXWI1TEUKsBo4_EE,21295
|
|
321
321
|
rasa/core/policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
322
322
|
rasa/core/policies/ensemble.py,sha256=XoHxU0jcb_io_LBOpjJffylzqtGEB7CH9ivhRyO8pDc,12960
|
|
323
|
-
rasa/core/policies/enterprise_search_policy.py,sha256=
|
|
323
|
+
rasa/core/policies/enterprise_search_policy.py,sha256=QmphxTTLWKaKrVCwBYWuVhw4TraW1aCbugNrg2Qrbcg,46869
|
|
324
324
|
rasa/core/policies/enterprise_search_policy_config.py,sha256=rTIGBrfGfe_lvsYQW1cU20tza07p_-oxFfjXhw7-phc,8644
|
|
325
325
|
rasa/core/policies/enterprise_search_prompt_template.jinja2,sha256=dCS_seyBGxMQoMsOjjvPp0dd31OSzZCJSZeev1FJK5Q,1187
|
|
326
326
|
rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2,sha256=va9rpP97dN3PKoJZOVfyuISt3cPBlb10Pqyz25RwO_Q,3294
|
|
327
|
-
rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2,sha256=
|
|
327
|
+
rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2,sha256=b_8ZzK1ar0SvLZRFS8d9tHWvYS7Xb8xPJiBKg-UcyAM,3743
|
|
328
328
|
rasa/core/policies/flow_policy.py,sha256=Rvx5MIGDHi9sVxGazf-dXs6F-hFHSi3UoVjjSP8ATik,7470
|
|
329
329
|
rasa/core/policies/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
330
330
|
rasa/core/policies/flows/flow_exceptions.py,sha256=_FQuN-cerQDM1pivce9bz4zylh5UYkljvYS1gjDukHI,1527
|
|
331
|
-
rasa/core/policies/flows/flow_executor.py,sha256=
|
|
331
|
+
rasa/core/policies/flows/flow_executor.py,sha256=3T3uGzJsPflZrtOg2Gg5WFgOvmX3uRuacaESiOtvDXA,28601
|
|
332
332
|
rasa/core/policies/flows/flow_step_result.py,sha256=agjPrD6lahGSe2ViO5peBeoMdI9ngVGRSgtytgxmJmg,1360
|
|
333
333
|
rasa/core/policies/intentless_policy.py,sha256=1A7FSkI4PQdN3t1p3GQhSImmO-m6UVCUzzEsjxz4nKc,38040
|
|
334
334
|
rasa/core/policies/intentless_prompt_template.jinja2,sha256=KhIL3cruMmkxhrs5oVbqgSvK6ZiN_6TQ_jXrgtEB-ZY,677
|
|
@@ -350,7 +350,7 @@ rasa/core/tracker_stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
350
350
|
rasa/core/tracker_stores/auth_retry_tracker_store.py,sha256=eFW-uCRImTxouhHux4HVppQhbWNOaPzusbvaJ-U0N4Y,4826
|
|
351
351
|
rasa/core/tracker_stores/dynamo_tracker_store.py,sha256=opTSmFfNYKe3pKY5PL2JAKCc9uIur3pc5f_8SVW6g98,7906
|
|
352
352
|
rasa/core/tracker_stores/mongo_tracker_store.py,sha256=nuj-XkIC02dGv0l7Ie8801fHGrSN9SWlepenz3DZs78,7024
|
|
353
|
-
rasa/core/tracker_stores/redis_tracker_store.py,sha256=
|
|
353
|
+
rasa/core/tracker_stores/redis_tracker_store.py,sha256=cODH4DlUNij-GnKz6ns3nU2E-z_pXtsNA7LojmARZWg,7974
|
|
354
354
|
rasa/core/tracker_stores/sql_tracker_store.py,sha256=WZuo5c4TcBwOc6GwWlyNCv3LHNetgWTih0zEdMEvgYY,19879
|
|
355
355
|
rasa/core/tracker_stores/tracker_store.py,sha256=BrQFZXQGMncl-Ig3DDUrqpJfxshuy-pOmoVTVa1IMbw,28223
|
|
356
356
|
rasa/core/train.py,sha256=ESBhZ9vZySziZIG8fvshHO4AYApD0hywRFCmA9h1wFI,3521
|
|
@@ -431,7 +431,7 @@ rasa/dialogue_understanding/patterns/collect_information.py,sha256=8YWvhFTt8CJML
|
|
|
431
431
|
rasa/dialogue_understanding/patterns/completed.py,sha256=7qkyUj2d__2R3mpwWVmQpfwCCbJruBrjRZbmbDr3Zbo,1278
|
|
432
432
|
rasa/dialogue_understanding/patterns/continue_interrupted.py,sha256=OSTbe5l0B0ECNIYWpYB0pdzIeaqM3m3UZskNNjL5vrw,1682
|
|
433
433
|
rasa/dialogue_understanding/patterns/correction.py,sha256=7fQ02-JU1CGZiTjTi9YqmD1F4o-9Tv5WCAXnFgZlvtY,11380
|
|
434
|
-
rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml,sha256=
|
|
434
|
+
rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml,sha256=8zQQ1o9KQsT_wmNBUx4_iHZzYbzPHVLjFDorT60yvCs,11030
|
|
435
435
|
rasa/dialogue_understanding/patterns/domain_for_patterns.py,sha256=Zv_lCJn4nbkxeNYOPGsR0V8tmYAUsM_Ho_9to8hku-o,6493
|
|
436
436
|
rasa/dialogue_understanding/patterns/human_handoff.py,sha256=1hkSdL6kui42rZc7zERZ9R7nLyvRHi_tHgNU7FyrhAQ,1132
|
|
437
437
|
rasa/dialogue_understanding/patterns/internal_error.py,sha256=APCKVv16M6mSQ4upu4UwG0yIaaKTyr7uB2yV8ZtpMzo,1609
|
|
@@ -443,7 +443,7 @@ rasa/dialogue_understanding/patterns/skip_question.py,sha256=fJ1MC0WEEtS-BpnGJEf
|
|
|
443
443
|
rasa/dialogue_understanding/patterns/user_silence.py,sha256=xP-QMnd-MsybH5z4g01hBv4OLOHcw6m3rc26LQfe2zo,1140
|
|
444
444
|
rasa/dialogue_understanding/patterns/validate_slot.py,sha256=hqd5AEGT3M3HLNhMwuI9W9kZNCvgU6GyI-2xc2b4kz8,2085
|
|
445
445
|
rasa/dialogue_understanding/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
446
|
-
rasa/dialogue_understanding/processor/command_processor.py,sha256=
|
|
446
|
+
rasa/dialogue_understanding/processor/command_processor.py,sha256=d9LRwNzV4Jqe_6DOvGITgElwqDZfz4JvvuUpPJ4ceZI,30296
|
|
447
447
|
rasa/dialogue_understanding/processor/command_processor_component.py,sha256=rkErI_Uo7s3LsEojUSGSRbWGyGaX7GtGOYSJn0V-TI4,1650
|
|
448
448
|
rasa/dialogue_understanding/stack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
449
449
|
rasa/dialogue_understanding/stack/dialogue_stack.py,sha256=cYV6aQeh0EuOJHODDqK3biqXozYTX8baPgLwHhPxFqs,5244
|
|
@@ -542,7 +542,7 @@ rasa/hooks.py,sha256=HRWGfHIe_YG9nrV_Ly0ontfPSbcsyVVwA-8e8frr57U,2986
|
|
|
542
542
|
rasa/jupyter.py,sha256=TCYVD4QPQIMmfA6ZwDUBOBTAECwCwbU2XOkosodLO9k,1782
|
|
543
543
|
rasa/keys,sha256=2Stg1fstgJ203cOoW1B2gGMY29fhEnjIfTVxKv_fqPo,101
|
|
544
544
|
rasa/llm_fine_tuning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
545
|
-
rasa/llm_fine_tuning/annotation_module.py,sha256=
|
|
545
|
+
rasa/llm_fine_tuning/annotation_module.py,sha256=7vKwesRLvtKQAt9etHIT51HN8D21dSR3smNY7aIbGx4,11267
|
|
546
546
|
rasa/llm_fine_tuning/conversations.py,sha256=qzoTFQiwADmzL9mocqML4a-nAgEu6hlOSE3K87LvhM0,4272
|
|
547
547
|
rasa/llm_fine_tuning/llm_data_preparation_module.py,sha256=Vh6HHDvH1ueaNgBWnzIA7ymcTwHpqVvKxIPAnMKZtyY,7153
|
|
548
548
|
rasa/llm_fine_tuning/paraphrasing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -636,14 +636,14 @@ rasa/privacy/constants.py,sha256=PkmfLcQXKmRUnEJ-NzsG4bxbx1x0n5canE0Ab5DX2MM,212
|
|
|
636
636
|
rasa/privacy/event_broker_utils.py,sha256=K0ej9vRED5sJiG8YJq3_pynMRJEenCyKSjt6xOq2x84,2704
|
|
637
637
|
rasa/privacy/privacy_config.py,sha256=mctRStSliSUbbjHAl5ISTczJ2TgU7T5yjSfZvLmUtlI,9339
|
|
638
638
|
rasa/privacy/privacy_config_schema.json,sha256=kQVJCrlKljJMkOCL3WDzquVS8V1-KE6_XMEyVSuUkJw,1835
|
|
639
|
-
rasa/privacy/privacy_filter.py,sha256=
|
|
640
|
-
rasa/privacy/privacy_manager.py,sha256=
|
|
639
|
+
rasa/privacy/privacy_filter.py,sha256=s1LxnOeIoGh16vzTzxoM5vSDelk1P55Ay3bm0XRuINs,14988
|
|
640
|
+
rasa/privacy/privacy_manager.py,sha256=6tK1cLfJDfk_XbFZZNq1a9ImhtDh1_l8RC2GWHWRMfw,22386
|
|
641
641
|
rasa/server.py,sha256=prH4FVO5kd7VKgSJnP_dt7PhXlW0vf8KWf62ccK8mlw,60505
|
|
642
642
|
rasa/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
643
643
|
rasa/shared/constants.py,sha256=pYMlsFE9kao5BUOXd-8cHWLV9jMfUop7Mfm57mBPcxc,12856
|
|
644
644
|
rasa/shared/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
645
645
|
rasa/shared/core/command_payload_reader.py,sha256=aWmEe6NyGdGZ8qaCPxGZu1frLROv04SFbwPpZNrtj7Q,3741
|
|
646
|
-
rasa/shared/core/constants.py,sha256=
|
|
646
|
+
rasa/shared/core/constants.py,sha256=_YGXcxuIsgug7P-__KQJbrUjkK-gT_RfWjBESy9QZTo,6410
|
|
647
647
|
rasa/shared/core/conversation.py,sha256=0nUhcbQkPDnO3_Rig7oiinrWmPy5fsVQs_U6Fx1hG5c,1384
|
|
648
648
|
rasa/shared/core/domain.py,sha256=PTSwkm_m9E5hzuxUrIjoLVEtYTHk1gjul3ic6Q0tUg8,86791
|
|
649
649
|
rasa/shared/core/events.py,sha256=FAWCA0JXim89u4AcWLKCt4F9A0pkYDE5NhCIyiKwWTM,89973
|
|
@@ -793,7 +793,7 @@ rasa/studio/link.py,sha256=IB--VKX72ERL7OOLQ6SgfVuRSg8zWkq3RxmwxFzoA2I,6590
|
|
|
793
793
|
rasa/studio/prompts.py,sha256=KRQ6WmwyDyEiNFleZ1ftVOE6m6zBI6pWCHYfePJQjaM,6803
|
|
794
794
|
rasa/studio/pull/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
795
795
|
rasa/studio/pull/data.py,sha256=e5VJuOJ2W7Ni74PuDB5cODhjygUcjjxI-i4xA1MzdOc,7565
|
|
796
|
-
rasa/studio/pull/domains.py,sha256=
|
|
796
|
+
rasa/studio/pull/domains.py,sha256=qPClJkILTpZuLEic56f1vAgnoABv3hYWm6tduK1BXXM,2443
|
|
797
797
|
rasa/studio/pull/pull.py,sha256=Qr-Ms4pXNS04hvdciZCfbeC1hag6v2puwhHwhcFpA8Q,7750
|
|
798
798
|
rasa/studio/push.py,sha256=_EopU6RQnbQub33x0TVXOTWCYUfOQMDc6KdDNmltLMs,4279
|
|
799
799
|
rasa/studio/results_logger.py,sha256=lwKROoQjzzJVnFoceLQ-z-5Hg35TfHo-8R4MDrMLYHY,5126
|
|
@@ -846,9 +846,9 @@ rasa/utils/train_utils.py,sha256=ClJx-6x3-h3Vt6mskacgkcCUJTMXjFPe3zAcy_DfmaU,212
|
|
|
846
846
|
rasa/utils/url_tools.py,sha256=dZ1HGkVdWTJB7zYEdwoDIrEuyX9HE5WsxKKFVsXBLE0,1218
|
|
847
847
|
rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
|
|
848
848
|
rasa/validator.py,sha256=JXi8bz3SsTB2c1tbDRY3r3TkcfSbhxacoxs-rVx6a9s,82937
|
|
849
|
-
rasa/version.py,sha256
|
|
850
|
-
rasa_pro-3.13.
|
|
851
|
-
rasa_pro-3.13.
|
|
852
|
-
rasa_pro-3.13.
|
|
853
|
-
rasa_pro-3.13.
|
|
854
|
-
rasa_pro-3.13.
|
|
849
|
+
rasa/version.py,sha256=-KPJ9E-IAgMogu8pKWMj7VxcA8dbmX0UKuG-U9k-adc,120
|
|
850
|
+
rasa_pro-3.13.0rc3.dist-info/METADATA,sha256=5yPX5oyvTOwfwvysDX16kfh7toEmYoM6KUZSJqJjckY,10556
|
|
851
|
+
rasa_pro-3.13.0rc3.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
|
|
852
|
+
rasa_pro-3.13.0rc3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
853
|
+
rasa_pro-3.13.0rc3.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
|
|
854
|
+
rasa_pro-3.13.0rc3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|