rasa-pro 3.8.17__py3-none-any.whl → 3.9.14__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.
- README.md +5 -5
- rasa/__main__.py +14 -9
- rasa/anonymization/anonymization_pipeline.py +0 -1
- rasa/anonymization/anonymization_rule_executor.py +3 -3
- rasa/anonymization/utils.py +4 -3
- rasa/api.py +2 -2
- rasa/cli/arguments/default_arguments.py +1 -1
- rasa/cli/arguments/run.py +2 -2
- rasa/cli/arguments/test.py +1 -1
- rasa/cli/arguments/train.py +10 -10
- rasa/cli/e2e_test.py +27 -7
- rasa/cli/export.py +0 -1
- rasa/cli/license.py +3 -3
- rasa/cli/project_templates/calm/actions/action_template.py +1 -1
- rasa/cli/project_templates/calm/config.yml +1 -1
- rasa/cli/project_templates/calm/credentials.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/add_contact.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/remove_contact.yml +1 -1
- rasa/cli/project_templates/calm/domain/add_contact.yml +8 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +3 -0
- rasa/cli/project_templates/calm/domain/remove_contact.yml +9 -2
- rasa/cli/project_templates/calm/domain/shared.yml +5 -0
- rasa/cli/project_templates/calm/endpoints.yml +4 -4
- rasa/cli/project_templates/default/actions/actions.py +1 -1
- rasa/cli/project_templates/default/config.yml +5 -5
- rasa/cli/project_templates/default/credentials.yml +1 -1
- rasa/cli/project_templates/default/endpoints.yml +4 -4
- rasa/cli/project_templates/default/tests/test_stories.yml +1 -1
- rasa/cli/project_templates/tutorial/config.yml +1 -1
- rasa/cli/project_templates/tutorial/credentials.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
- rasa/cli/project_templates/tutorial/domain.yml +4 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +6 -6
- rasa/cli/run.py +0 -1
- rasa/cli/scaffold.py +3 -2
- rasa/cli/studio/download.py +11 -0
- rasa/cli/studio/studio.py +180 -24
- rasa/cli/studio/upload.py +0 -8
- rasa/cli/telemetry.py +18 -6
- rasa/cli/utils.py +21 -10
- rasa/cli/x.py +3 -2
- rasa/core/actions/action.py +90 -315
- rasa/core/actions/action_exceptions.py +24 -0
- rasa/core/actions/constants.py +3 -0
- rasa/core/actions/custom_action_executor.py +188 -0
- rasa/core/actions/forms.py +11 -7
- rasa/core/actions/grpc_custom_action_executor.py +251 -0
- rasa/core/actions/http_custom_action_executor.py +140 -0
- rasa/core/actions/loops.py +3 -0
- rasa/core/actions/two_stage_fallback.py +1 -1
- rasa/core/agent.py +2 -4
- rasa/core/brokers/pika.py +1 -2
- rasa/core/channels/audiocodes.py +1 -1
- rasa/core/channels/botframework.py +0 -1
- rasa/core/channels/callback.py +0 -1
- rasa/core/channels/console.py +6 -8
- rasa/core/channels/development_inspector.py +1 -1
- rasa/core/channels/facebook.py +0 -3
- rasa/core/channels/hangouts.py +0 -6
- rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
- rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
- rasa/core/channels/rest.py +36 -21
- rasa/core/channels/rocketchat.py +0 -1
- rasa/core/channels/socketio.py +1 -1
- rasa/core/channels/telegram.py +3 -3
- rasa/core/channels/webexteams.py +0 -1
- rasa/core/concurrent_lock_store.py +1 -1
- rasa/core/evaluation/marker_base.py +1 -3
- rasa/core/evaluation/marker_stats.py +1 -2
- rasa/core/featurizers/single_state_featurizer.py +2 -4
- rasa/core/featurizers/tracker_featurizers.py +0 -7
- rasa/core/information_retrieval/__init__.py +7 -0
- rasa/core/information_retrieval/faiss.py +9 -4
- rasa/core/information_retrieval/information_retrieval.py +64 -7
- rasa/core/information_retrieval/milvus.py +7 -14
- rasa/core/information_retrieval/qdrant.py +8 -15
- rasa/core/lock_store.py +0 -1
- rasa/core/migrate.py +1 -2
- rasa/core/nlg/callback.py +3 -4
- rasa/core/policies/enterprise_search_policy.py +86 -22
- rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
- rasa/core/policies/flows/flow_executor.py +104 -2
- rasa/core/policies/intentless_policy.py +7 -9
- rasa/core/policies/memoization.py +3 -3
- rasa/core/policies/policy.py +18 -9
- rasa/core/policies/rule_policy.py +8 -11
- rasa/core/policies/ted_policy.py +28 -30
- rasa/core/policies/unexpected_intent_policy.py +1 -2
- rasa/core/processor.py +136 -47
- rasa/core/run.py +41 -25
- rasa/core/secrets_manager/endpoints.py +2 -2
- rasa/core/secrets_manager/vault.py +6 -8
- rasa/core/test.py +3 -5
- rasa/core/tracker_store.py +49 -14
- rasa/core/train.py +1 -3
- rasa/core/training/interactive.py +9 -6
- rasa/core/utils.py +5 -10
- rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
- rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
- rasa/dialogue_understanding/commands/__init__.py +4 -0
- rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/clarify_command.py +9 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
- rasa/dialogue_understanding/commands/error_command.py +12 -0
- rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/noop_command.py +9 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +34 -3
- rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
- rasa/dialogue_understanding/generator/__init__.py +16 -1
- rasa/dialogue_understanding/generator/command_generator.py +92 -6
- rasa/dialogue_understanding/generator/constants.py +18 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
- rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
- rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
- rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
- rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +44 -39
- rasa/dialogue_understanding/processor/command_processor.py +111 -3
- rasa/e2e_test/constants.py +1 -0
- rasa/e2e_test/e2e_test_case.py +44 -0
- rasa/e2e_test/e2e_test_runner.py +114 -11
- rasa/e2e_test/e2e_test_schema.yml +18 -0
- rasa/engine/caching.py +0 -1
- rasa/engine/graph.py +18 -6
- rasa/engine/recipes/config_files/default_config.yml +3 -3
- rasa/engine/recipes/default_components.py +1 -1
- rasa/engine/recipes/default_recipe.py +4 -5
- rasa/engine/recipes/recipe.py +1 -1
- rasa/engine/runner/dask.py +3 -9
- rasa/engine/storage/local_model_storage.py +0 -2
- rasa/engine/validation.py +179 -145
- rasa/exceptions.py +2 -2
- rasa/graph_components/validators/default_recipe_validator.py +3 -5
- rasa/hooks.py +0 -1
- rasa/model.py +1 -1
- rasa/model_training.py +1 -0
- rasa/nlu/classifiers/diet_classifier.py +8 -14
- rasa/nlu/extractors/crf_entity_extractor.py +4 -4
- rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
- rasa/nlu/featurizers/featurizer.py +1 -1
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +2 -4
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +9 -12
- rasa/nlu/persistor.py +68 -26
- rasa/nlu/selectors/response_selector.py +7 -10
- rasa/nlu/test.py +0 -3
- rasa/nlu/utils/hugging_face/registry.py +1 -1
- rasa/nlu/utils/spacy_utils.py +1 -3
- rasa/server.py +22 -7
- rasa/shared/constants.py +12 -1
- rasa/shared/core/command_payload_reader.py +109 -0
- rasa/shared/core/constants.py +4 -5
- rasa/shared/core/domain.py +57 -56
- rasa/shared/core/events.py +4 -7
- rasa/shared/core/flows/flow.py +9 -0
- rasa/shared/core/flows/flows_list.py +12 -0
- rasa/shared/core/flows/steps/action.py +7 -2
- rasa/shared/core/generator.py +12 -11
- rasa/shared/core/slot_mappings.py +315 -24
- rasa/shared/core/slots.py +4 -2
- rasa/shared/core/trackers.py +32 -14
- rasa/shared/core/training_data/loading.py +0 -1
- rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
- rasa/shared/core/training_data/structures.py +1 -1
- rasa/shared/core/training_data/visualization.py +1 -1
- rasa/shared/data.py +58 -1
- rasa/shared/exceptions.py +36 -2
- rasa/shared/importers/importer.py +1 -2
- rasa/shared/importers/rasa.py +0 -1
- rasa/shared/nlu/constants.py +2 -0
- rasa/shared/nlu/training_data/entities_parser.py +1 -2
- rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
- rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
- rasa/shared/nlu/training_data/message.py +13 -0
- rasa/shared/nlu/training_data/training_data.py +0 -2
- rasa/shared/providers/openai/session_handler.py +2 -2
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/io.py +11 -0
- rasa/shared/utils/llm.py +1 -2
- rasa/shared/utils/pykwalify_extensions.py +1 -0
- rasa/shared/utils/schemas/domain.yml +3 -0
- rasa/shared/utils/yaml.py +44 -35
- rasa/studio/auth.py +26 -10
- rasa/studio/constants.py +2 -0
- rasa/studio/data_handler.py +114 -107
- rasa/studio/download.py +160 -27
- rasa/studio/results_logger.py +137 -0
- rasa/studio/train.py +6 -7
- rasa/studio/upload.py +159 -134
- rasa/telemetry.py +188 -34
- rasa/tracing/config.py +18 -3
- rasa/tracing/constants.py +26 -2
- rasa/tracing/instrumentation/attribute_extractors.py +50 -41
- rasa/tracing/instrumentation/instrumentation.py +290 -44
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
- rasa/tracing/instrumentation/metrics.py +109 -21
- rasa/tracing/metric_instrument_provider.py +83 -3
- rasa/utils/cli.py +2 -1
- rasa/utils/common.py +1 -1
- rasa/utils/endpoints.py +1 -2
- rasa/utils/io.py +6 -6
- rasa/utils/licensing.py +246 -31
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/tensorflow/data_generator.py +1 -1
- rasa/utils/tensorflow/environment.py +1 -1
- rasa/utils/tensorflow/model_data.py +9 -11
- rasa/utils/tensorflow/model_data_utils.py +499 -500
- rasa/utils/tensorflow/models.py +5 -6
- rasa/utils/tensorflow/rasa_layers.py +15 -15
- rasa/utils/train_utils.py +1 -1
- rasa/utils/url_tools.py +53 -0
- rasa/validator.py +305 -3
- rasa/version.py +1 -1
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/METADATA +22 -22
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/RECORD +271 -253
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
- /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/NOTICE +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/WHEEL +0 -0
- {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Text, Any, Dict
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
from langchain.vectorstores.qdrant import Qdrant
|
|
@@ -6,15 +6,12 @@ from pydantic import ValidationError
|
|
|
6
6
|
from qdrant_client import QdrantClient
|
|
7
7
|
from rasa.utils.endpoints import EndpointConfig
|
|
8
8
|
|
|
9
|
-
from rasa.core.information_retrieval
|
|
9
|
+
from rasa.core.information_retrieval import (
|
|
10
|
+
SearchResultList,
|
|
10
11
|
InformationRetrieval,
|
|
11
12
|
InformationRetrievalException,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from langchain.schema import Document
|
|
16
|
-
from langchain.schema.embeddings import Embeddings
|
|
17
|
-
|
|
18
15
|
logger = structlog.get_logger()
|
|
19
16
|
|
|
20
17
|
|
|
@@ -41,12 +38,6 @@ class QdrantInformationRetrievalException(InformationRetrievalException):
|
|
|
41
38
|
|
|
42
39
|
|
|
43
40
|
class Qdrant_Store(InformationRetrieval):
|
|
44
|
-
def __init__(
|
|
45
|
-
self,
|
|
46
|
-
embeddings: "Embeddings",
|
|
47
|
-
) -> None:
|
|
48
|
-
self.embeddings = embeddings
|
|
49
|
-
|
|
50
41
|
def connect(
|
|
51
42
|
self,
|
|
52
43
|
config: EndpointConfig,
|
|
@@ -73,7 +64,9 @@ class Qdrant_Store(InformationRetrieval):
|
|
|
73
64
|
metadata_payload_key=params.get("metadata_payload_key", "metadata"),
|
|
74
65
|
)
|
|
75
66
|
|
|
76
|
-
async def search(
|
|
67
|
+
async def search(
|
|
68
|
+
self, query: Text, tracker_state: Dict[str, Any], threshold: float = 0.0
|
|
69
|
+
) -> SearchResultList:
|
|
77
70
|
"""Search for a document in the Qdrant vector store.
|
|
78
71
|
|
|
79
72
|
Args:
|
|
@@ -83,7 +76,7 @@ class Qdrant_Store(InformationRetrieval):
|
|
|
83
76
|
Returns:
|
|
84
77
|
A list of documents that match the query.
|
|
85
78
|
"""
|
|
86
|
-
logger.
|
|
79
|
+
logger.debug("information_retrieval.qdrant_store.search", query=query)
|
|
87
80
|
try:
|
|
88
81
|
hits = await self.client.asimilarity_search(
|
|
89
82
|
query, k=4, score_threshold=threshold
|
|
@@ -99,4 +92,4 @@ class Qdrant_Store(InformationRetrieval):
|
|
|
99
92
|
raise QdrantInformationRetrievalException(
|
|
100
93
|
f"Failed to search the Qdrant vector store. Encountered error: {e}"
|
|
101
94
|
) from e
|
|
102
|
-
return hits
|
|
95
|
+
return SearchResultList.from_document_list(hits)
|
rasa/core/lock_store.py
CHANGED
rasa/core/migrate.py
CHANGED
|
@@ -84,7 +84,7 @@ def _get_updated_or_new_mappings(
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
def _migrate_form_slots(
|
|
87
|
-
domain: Dict[Text, Any]
|
|
87
|
+
domain: Dict[Text, Any],
|
|
88
88
|
) -> Tuple[Dict[Any, Dict[str, Any]], Optional[Any]]:
|
|
89
89
|
updated_slots = domain.get(KEY_SLOTS, {})
|
|
90
90
|
forms = domain.get(KEY_FORMS, {})
|
|
@@ -228,7 +228,6 @@ def _migrate_domain_files(
|
|
|
228
228
|
)
|
|
229
229
|
|
|
230
230
|
for file in domain_files:
|
|
231
|
-
|
|
232
231
|
backup = backup_location / file.name
|
|
233
232
|
original_content = _create_back_up(file, backup)
|
|
234
233
|
|
rasa/core/nlg/callback.py
CHANGED
|
@@ -62,7 +62,6 @@ class CallbackNaturalLanguageGenerator(NaturalLanguageGenerator):
|
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
64
|
def __init__(self, endpoint_config: EndpointConfig) -> None:
|
|
65
|
-
|
|
66
65
|
self.nlg_endpoint = endpoint_config
|
|
67
66
|
|
|
68
67
|
async def generate(
|
|
@@ -82,9 +81,9 @@ class CallbackNaturalLanguageGenerator(NaturalLanguageGenerator):
|
|
|
82
81
|
body = nlg_request_format(utter_action, tracker, output_channel, **kwargs)
|
|
83
82
|
|
|
84
83
|
logger.debug(
|
|
85
|
-
"Requesting NLG for {} from {}."
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
"Requesting NLG for {} from {}. The request body is {}.".format(
|
|
85
|
+
utter_action, self.nlg_endpoint.url, json.dumps(body)
|
|
86
|
+
)
|
|
88
87
|
)
|
|
89
88
|
|
|
90
89
|
response = await self.nlg_endpoint.request(
|
|
@@ -4,10 +4,16 @@ import re
|
|
|
4
4
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text
|
|
5
5
|
|
|
6
6
|
import dotenv
|
|
7
|
-
import rasa.shared.utils.io
|
|
8
7
|
import structlog
|
|
9
8
|
from jinja2 import Template
|
|
10
|
-
from pydantic
|
|
9
|
+
from pydantic import ValidationError
|
|
10
|
+
|
|
11
|
+
import rasa.shared.utils.io
|
|
12
|
+
from rasa.telemetry import (
|
|
13
|
+
track_enterprise_search_policy_predict,
|
|
14
|
+
track_enterprise_search_policy_train_completed,
|
|
15
|
+
track_enterprise_search_policy_train_started,
|
|
16
|
+
)
|
|
11
17
|
from rasa.shared.exceptions import RasaException
|
|
12
18
|
from rasa.core.constants import (
|
|
13
19
|
POLICY_MAX_HISTORY,
|
|
@@ -41,7 +47,7 @@ from rasa.shared.core.constants import (
|
|
|
41
47
|
from rasa.shared.core.domain import Domain
|
|
42
48
|
from rasa.shared.core.events import Event
|
|
43
49
|
from rasa.shared.core.generator import TrackerWithCachedStates
|
|
44
|
-
from rasa.shared.core.trackers import DialogueStateTracker
|
|
50
|
+
from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
|
|
45
51
|
from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
46
52
|
from rasa.shared.utils.cli import print_error_and_exit
|
|
47
53
|
from rasa.shared.utils.io import deep_container_fingerprint
|
|
@@ -54,16 +60,15 @@ from rasa.shared.utils.llm import (
|
|
|
54
60
|
sanitize_message_for_prompt,
|
|
55
61
|
tracker_as_readable_transcript,
|
|
56
62
|
)
|
|
57
|
-
|
|
58
63
|
from rasa.core.information_retrieval.faiss import FAISS_Store
|
|
59
|
-
from rasa.core.information_retrieval
|
|
64
|
+
from rasa.core.information_retrieval import (
|
|
60
65
|
InformationRetrieval,
|
|
66
|
+
SearchResult,
|
|
61
67
|
InformationRetrievalException,
|
|
62
68
|
create_from_endpoint_config,
|
|
63
69
|
)
|
|
64
70
|
|
|
65
71
|
if TYPE_CHECKING:
|
|
66
|
-
from langchain.schema import Document
|
|
67
72
|
from langchain.schema.embeddings import Embeddings
|
|
68
73
|
from langchain.llms.base import BaseLLM
|
|
69
74
|
from rasa.core.featurizers.tracker_featurizers import TrackerFeaturizer
|
|
@@ -78,6 +83,9 @@ SOURCE_PROPERTY = "source"
|
|
|
78
83
|
VECTOR_STORE_TYPE_PROPERTY = "type"
|
|
79
84
|
VECTOR_STORE_PROPERTY = "vector_store"
|
|
80
85
|
VECTOR_STORE_THRESHOLD_PROPERTY = "threshold"
|
|
86
|
+
TRACE_TOKENS_PROPERTY = "trace_prompt_tokens"
|
|
87
|
+
CITATION_ENABLED_PROPERTY = "citation_enabled"
|
|
88
|
+
USE_LLM_PROPERTY = "use_generative_llm"
|
|
81
89
|
|
|
82
90
|
DEFAULT_VECTOR_STORE_TYPE = "faiss"
|
|
83
91
|
DEFAULT_VECTOR_STORE_THRESHOLD = 0.0
|
|
@@ -109,6 +117,10 @@ DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE = importlib.resources.read_text(
|
|
|
109
117
|
"rasa.core.policies", "enterprise_search_prompt_template.jinja2"
|
|
110
118
|
)
|
|
111
119
|
|
|
120
|
+
DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE = importlib.resources.read_text(
|
|
121
|
+
"rasa.core.policies", "enterprise_search_prompt_with_citation_template.jinja2"
|
|
122
|
+
)
|
|
123
|
+
|
|
112
124
|
|
|
113
125
|
class VectorStoreConnectionError(RasaException):
|
|
114
126
|
"""Exception raised for errors in connecting to the vector store."""
|
|
@@ -171,13 +183,24 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
171
183
|
self.vector_store_config = config.get(
|
|
172
184
|
VECTOR_STORE_PROPERTY, DEFAULT_VECTOR_STORE
|
|
173
185
|
)
|
|
186
|
+
self.llm_config = self.config.get(LLM_CONFIG_KEY, DEFAULT_LLM_CONFIG)
|
|
187
|
+
self.embeddings_config = self.config.get(
|
|
188
|
+
EMBEDDINGS_CONFIG_KEY, DEFAULT_EMBEDDINGS_CONFIG
|
|
189
|
+
)
|
|
174
190
|
self.max_history = self.config.get(POLICY_MAX_HISTORY)
|
|
175
191
|
self.prompt_template = prompt_template or get_prompt_template(
|
|
176
192
|
self.config.get("prompt"),
|
|
177
193
|
DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE,
|
|
178
194
|
)
|
|
179
|
-
self.trace_prompt_tokens = self.config.get(
|
|
180
|
-
self.
|
|
195
|
+
self.trace_prompt_tokens = self.config.get(TRACE_TOKENS_PROPERTY, False)
|
|
196
|
+
self.use_llm = self.config.get(USE_LLM_PROPERTY, True)
|
|
197
|
+
self.citation_enabled = self.config.get(CITATION_ENABLED_PROPERTY, False)
|
|
198
|
+
self.citation_prompt_template = get_prompt_template(
|
|
199
|
+
self.config.get("prompt"),
|
|
200
|
+
DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE,
|
|
201
|
+
)
|
|
202
|
+
if self.citation_enabled:
|
|
203
|
+
self.prompt_template = self.citation_prompt_template
|
|
181
204
|
|
|
182
205
|
@classmethod
|
|
183
206
|
def _create_plain_embedder(cls, config: Dict[Text, Any]) -> "Embeddings":
|
|
@@ -216,6 +239,9 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
216
239
|
"""
|
|
217
240
|
store_type = self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY)
|
|
218
241
|
|
|
242
|
+
# telemetry call to track training start
|
|
243
|
+
track_enterprise_search_policy_train_started()
|
|
244
|
+
|
|
219
245
|
# validate embedding configuration
|
|
220
246
|
try:
|
|
221
247
|
embeddings = self._create_plain_embedder(self.config)
|
|
@@ -246,6 +272,16 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
246
272
|
else:
|
|
247
273
|
logger.info("enterprise_search_policy.train.custom", store_type=store_type)
|
|
248
274
|
|
|
275
|
+
# telemetry call to track training completion
|
|
276
|
+
track_enterprise_search_policy_train_completed(
|
|
277
|
+
vector_store_type=store_type,
|
|
278
|
+
embeddings_type=self.embeddings_config.get("_type"),
|
|
279
|
+
embeddings_model=self.embeddings_config.get("model")
|
|
280
|
+
or self.embeddings_config.get("model_name"),
|
|
281
|
+
llm_type=self.llm_config.get("_type"),
|
|
282
|
+
llm_model=self.llm_config.get("model") or self.llm_config.get("model_name"),
|
|
283
|
+
citation_enabled=self.citation_enabled,
|
|
284
|
+
)
|
|
249
285
|
self.persist()
|
|
250
286
|
return self._resource
|
|
251
287
|
|
|
@@ -353,7 +389,9 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
353
389
|
VECTOR_STORE_THRESHOLD_PROPERTY, DEFAULT_VECTOR_STORE_THRESHOLD
|
|
354
390
|
)
|
|
355
391
|
llm = llm_factory(self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG)
|
|
356
|
-
if not self.supports_current_stack_frame(
|
|
392
|
+
if not self.supports_current_stack_frame(
|
|
393
|
+
tracker, False, False
|
|
394
|
+
) or self.should_abstain_in_coexistence(tracker, True):
|
|
357
395
|
return self._prediction(self._default_predictions(domain))
|
|
358
396
|
|
|
359
397
|
if not self.vector_store:
|
|
@@ -367,48 +405,74 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
367
405
|
return self._create_prediction_internal_error(domain, tracker)
|
|
368
406
|
|
|
369
407
|
search_query = self._get_last_user_message(tracker)
|
|
408
|
+
tracker_state = tracker.current_state(EventVerbosity.AFTER_RESTART)
|
|
370
409
|
|
|
371
410
|
try:
|
|
372
411
|
documents = await self.vector_store.search(
|
|
373
412
|
query=search_query,
|
|
413
|
+
tracker_state=tracker_state,
|
|
374
414
|
threshold=vector_search_threshold,
|
|
375
415
|
)
|
|
376
416
|
except InformationRetrievalException as e:
|
|
377
417
|
logger.error(f"{logger_key}.search_error", error=e)
|
|
378
418
|
return self._create_prediction_internal_error(domain, tracker)
|
|
379
419
|
|
|
380
|
-
if not documents:
|
|
420
|
+
if not documents.results:
|
|
381
421
|
logger.info(f"{logger_key}.no_documents")
|
|
382
422
|
return self._create_prediction_cannot_handle(domain, tracker)
|
|
383
423
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if llm_answer is None:
|
|
388
|
-
return self._create_prediction_internal_error(domain, tracker)
|
|
424
|
+
if self.use_llm:
|
|
425
|
+
prompt = self._render_prompt(tracker, documents.results)
|
|
426
|
+
llm_answer = await self._generate_llm_answer(llm, prompt)
|
|
389
427
|
|
|
390
|
-
|
|
391
|
-
|
|
428
|
+
if self.citation_enabled:
|
|
429
|
+
llm_answer = self.post_process_citations(llm_answer)
|
|
430
|
+
|
|
431
|
+
logger.debug(f"{logger_key}.llm_answer", llm_answer=llm_answer)
|
|
432
|
+
response = llm_answer
|
|
433
|
+
else:
|
|
434
|
+
response = documents.results[0].metadata.get("answer", None)
|
|
435
|
+
if not response:
|
|
436
|
+
logger.error(
|
|
437
|
+
f"{logger_key}.answer_key_missing_in_metadata",
|
|
438
|
+
search_results=documents.results,
|
|
439
|
+
)
|
|
440
|
+
logger.debug(
|
|
441
|
+
"enterprise_search_policy.predict_action_probabilities.no_llm",
|
|
442
|
+
search_results=documents,
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
if response is None:
|
|
446
|
+
return self._create_prediction_internal_error(domain, tracker)
|
|
392
447
|
|
|
393
|
-
logger.debug(f"{logger_key}.llm_answer", llm_answer=llm_answer)
|
|
394
448
|
action_metadata = {
|
|
395
449
|
"message": {
|
|
396
|
-
"text":
|
|
450
|
+
"text": response,
|
|
397
451
|
}
|
|
398
452
|
}
|
|
399
453
|
|
|
454
|
+
# telemetry call to track policy prediction
|
|
455
|
+
track_enterprise_search_policy_predict(
|
|
456
|
+
vector_store_type=self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY),
|
|
457
|
+
embeddings_type=self.embeddings_config.get("_type"),
|
|
458
|
+
embeddings_model=self.embeddings_config.get("model")
|
|
459
|
+
or self.embeddings_config.get("model_name"),
|
|
460
|
+
llm_type=self.llm_config.get("_type"),
|
|
461
|
+
llm_model=self.llm_config.get("model") or self.llm_config.get("model_name"),
|
|
462
|
+
citation_enabled=self.citation_enabled,
|
|
463
|
+
)
|
|
400
464
|
return self._create_prediction(
|
|
401
465
|
domain=domain, tracker=tracker, action_metadata=action_metadata
|
|
402
466
|
)
|
|
403
467
|
|
|
404
468
|
def _render_prompt(
|
|
405
|
-
self, tracker: DialogueStateTracker, documents: List[
|
|
469
|
+
self, tracker: DialogueStateTracker, documents: List[SearchResult]
|
|
406
470
|
) -> Text:
|
|
407
471
|
"""Renders the prompt from the template.
|
|
408
472
|
|
|
409
473
|
Args:
|
|
410
474
|
tracker: The tracker containing the conversation history up to now.
|
|
411
|
-
documents: The documents retrieved from
|
|
475
|
+
documents: The documents retrieved from search
|
|
412
476
|
|
|
413
477
|
Returns:
|
|
414
478
|
The rendered prompt.
|
|
@@ -529,7 +593,7 @@ class EnterpriseSearchPolicy(Policy):
|
|
|
529
593
|
"""
|
|
530
594
|
result = self._default_predictions(domain)
|
|
531
595
|
if action_name:
|
|
532
|
-
result[domain.index_for_action(action_name)] = score # type: ignore[assignment]
|
|
596
|
+
result[domain.index_for_action(action_name)] = score # type: ignore[assignment]
|
|
533
597
|
return result
|
|
534
598
|
|
|
535
599
|
@classmethod
|
|
@@ -4,39 +4,10 @@ If the answer is not known or cannot be determined from the provided documents o
|
|
|
4
4
|
### Relevant Documents
|
|
5
5
|
Use the following documents to answer the question:
|
|
6
6
|
{% for doc in docs %}
|
|
7
|
-
{{ loop.
|
|
8
|
-
{{ doc.
|
|
7
|
+
{{ loop.index }}. {{ doc.metadata }}
|
|
8
|
+
{{ doc.text }}
|
|
9
9
|
{% endfor %}
|
|
10
10
|
|
|
11
|
-
{% if citation_enabled %}
|
|
12
|
-
### Citing Sources
|
|
13
|
-
Find the sources from the documents that are most relevant to answering the question.
|
|
14
|
-
The sources must be extracted from the given document metadata source property and not from the conversation context.
|
|
15
|
-
If there are no relevant sources, write "No relevant sources" instead.
|
|
16
|
-
|
|
17
|
-
For each source you cite, follow a 1-based numbering system for citations.
|
|
18
|
-
Start with [1] for the first source you refer to, regardless of its index in the provided list of documents.
|
|
19
|
-
If you cite another source, use the next number in sequence, [2], and so on.
|
|
20
|
-
Ensure each source is only assigned one number, even if referenced multiple times.
|
|
21
|
-
If you refer back to a previously cited source, use its originally assigned number.
|
|
22
|
-
|
|
23
|
-
For example, if you first cite the third source in the list, refer to it as [1].
|
|
24
|
-
If you then cite the first source in the list, refer to it as [2].
|
|
25
|
-
If you mention the third source again, still refer to it as [1].
|
|
26
|
-
|
|
27
|
-
Don't say "According to Source [1]" when answering. Instead, make references to sources relevant to each section of the answer solely by adding the bracketed number at the end of the relevant sentence.
|
|
28
|
-
#### Formatting
|
|
29
|
-
First print the answer with in-text citations which follow a numbered order starting with index 1, then add the sources section.
|
|
30
|
-
The format of your overall answer must look like what's shown between the <example></example> tags.
|
|
31
|
-
Make sure to follow the formatting exactly and remove any line breaks or whitespaces between the answer and the Sources section.
|
|
32
|
-
<example>
|
|
33
|
-
You can use flows to model business logic in Rasa assistants. [1] You can use the Enterprise Search Policy to search vector stores for relevant knowledge base documents. [2]
|
|
34
|
-
Sources:
|
|
35
|
-
[1] https://rasa.com/docs/rasa-pro/concepts/flows
|
|
36
|
-
[2] https://rasa.com/docs/rasa-pro/concepts/policies/enterprise-search-policy
|
|
37
|
-
</example>
|
|
38
|
-
{% endif %}
|
|
39
|
-
|
|
40
11
|
{% if slots|length > 0 %}
|
|
41
12
|
### Slots or Variables
|
|
42
13
|
Here are the variables of the currently active conversation which may be used to answer the question:
|
|
@@ -49,14 +20,6 @@ Here are the variables of the currently active conversation which may be used to
|
|
|
49
20
|
Transcript of the current conversation, use it to determine the context of the question:
|
|
50
21
|
{{ current_conversation }}
|
|
51
22
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Based on the above sections, please formulate an answer to the question or request in the user's last message.
|
|
55
|
-
It is important that you ensure the answer is grounded in the provided documents and conversation context.
|
|
23
|
+
Based on the above, please formulate an answer to the question or request in the user's last message.
|
|
24
|
+
It is important that you ensure the answer is grounded in the provided documents and conversation context.
|
|
56
25
|
Avoid speculating or making assumptions beyond the given information and keep your answers short, 2 to 3 sentences at most.
|
|
57
|
-
|
|
58
|
-
{% if citation_enabled %}
|
|
59
|
-
If you are unable to find an answer in the given relevant documents, do not cite sources from elsewhere in the conversation context.
|
|
60
|
-
{% endif %}
|
|
61
|
-
|
|
62
|
-
Your answer:
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
Given the following information, please provide an answer based on the provided documents and the context of the recent conversation.
|
|
2
|
+
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.
|
|
3
|
+
### Relevant Documents
|
|
4
|
+
Use the following documents to answer the question:
|
|
5
|
+
{% for doc in docs %}
|
|
6
|
+
{{ loop.cycle("*")}}. {{ doc.metadata }}
|
|
7
|
+
{{ doc.page_content }}
|
|
8
|
+
{% endfor %}
|
|
9
|
+
|
|
10
|
+
{% if citation_enabled %}
|
|
11
|
+
### Citing Sources
|
|
12
|
+
Find the sources from the documents that are most relevant to answering the question.
|
|
13
|
+
The sources must be extracted from the given document metadata source property and not from the conversation context.
|
|
14
|
+
If there are no relevant sources, write "No relevant sources" instead.
|
|
15
|
+
|
|
16
|
+
For each source you cite, follow a 1-based numbering system for citations.
|
|
17
|
+
Start with [1] for the first source you refer to, regardless of its index in the provided list of documents.
|
|
18
|
+
If you cite another source, use the next number in sequence, [2], and so on.
|
|
19
|
+
Ensure each source is only assigned one number, even if referenced multiple times.
|
|
20
|
+
If you refer back to a previously cited source, use its originally assigned number.
|
|
21
|
+
|
|
22
|
+
For example, if you first cite the third source in the list, refer to it as [1].
|
|
23
|
+
If you then cite the first source in the list, refer to it as [2].
|
|
24
|
+
If you mention the third source again, still refer to it as [1].
|
|
25
|
+
|
|
26
|
+
Don't say "According to Source [1]" when answering. Instead, make references to sources relevant to each section of the answer solely by adding the bracketed number at the end of the relevant sentence.
|
|
27
|
+
#### Formatting
|
|
28
|
+
First print the answer with in-text citations which follow a numbered order starting with index 1, then add the sources section.
|
|
29
|
+
The format of your overall answer must look like what's shown between the <example></example> tags.
|
|
30
|
+
Make sure to follow the formatting exactly and remove any line breaks or whitespaces between the answer and the Sources section.
|
|
31
|
+
<example>
|
|
32
|
+
You can use flows to model business logic in Rasa assistants. [1] You can use the Enterprise Search Policy to search vector stores for relevant knowledge base documents. [2]
|
|
33
|
+
Sources:
|
|
34
|
+
[1] https://rasa.com/docs/rasa-pro/concepts/flows
|
|
35
|
+
[2] https://rasa.com/docs/rasa-pro/concepts/policies/enterprise-search-policy
|
|
36
|
+
</example>
|
|
37
|
+
{% endif %}
|
|
38
|
+
|
|
39
|
+
{% if slots|length > 0 %}
|
|
40
|
+
### Slots or Variables
|
|
41
|
+
Here are the variables of the currently active conversation which may be used to answer the question:
|
|
42
|
+
{% for slot in slots -%}
|
|
43
|
+
- name: {{ slot.name }}, value: {{ slot.value }}, type: {{ slot.type }}
|
|
44
|
+
{% endfor %}
|
|
45
|
+
{% endif %}
|
|
46
|
+
### Current Conversation
|
|
47
|
+
Transcript of the current conversation, use it to determine the context of the question:
|
|
48
|
+
{{ current_conversation }}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## Answering the Question
|
|
52
|
+
Based on the above sections, please formulate an answer to the question or request in the user's last message.
|
|
53
|
+
It is important that you ensure the answer is grounded in the provided documents and conversation context.
|
|
54
|
+
Avoid speculating or making assumptions beyond the given information and keep your answers short, 2 to 3 sentences at most.
|
|
55
|
+
|
|
56
|
+
{% if citation_enabled %}
|
|
57
|
+
If you are unable to find an answer in the given relevant documents, do not cite sources from elsewhere in the conversation context.
|
|
58
|
+
{% endif %}
|
|
59
|
+
|
|
60
|
+
Your answer:
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Any, Dict, Text, List, Optional
|
|
4
4
|
|
|
5
5
|
from jinja2 import Template
|
|
6
|
+
from rasa.dialogue_understanding.commands import CancelFlowCommand
|
|
7
|
+
from rasa.dialogue_understanding.patterns.cancel import CancelPatternFlowStackFrame
|
|
6
8
|
from structlog.contextvars import (
|
|
7
9
|
bound_contextvars,
|
|
8
10
|
)
|
|
@@ -17,6 +19,9 @@ from rasa.core.policies.flows.flow_step_result import (
|
|
|
17
19
|
FlowStepResult,
|
|
18
20
|
PauseFlowReturnPrediction,
|
|
19
21
|
)
|
|
22
|
+
from rasa.dialogue_understanding.patterns.internal_error import (
|
|
23
|
+
InternalErrorPatternFlowStackFrame,
|
|
24
|
+
)
|
|
20
25
|
from rasa.dialogue_understanding.patterns.search import SearchPatternFlowStackFrame
|
|
21
26
|
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
22
27
|
from rasa.dialogue_understanding.stack.frames import (
|
|
@@ -42,7 +47,7 @@ from rasa.dialogue_understanding.stack.utils import (
|
|
|
42
47
|
|
|
43
48
|
from pypred import Predicate
|
|
44
49
|
|
|
45
|
-
from rasa.shared.core.constants import ACTION_LISTEN_NAME
|
|
50
|
+
from rasa.shared.core.constants import ACTION_LISTEN_NAME, SlotMappingType
|
|
46
51
|
from rasa.shared.core.events import (
|
|
47
52
|
Event,
|
|
48
53
|
FlowCompleted,
|
|
@@ -72,6 +77,7 @@ from rasa.shared.core.flows.flow import (
|
|
|
72
77
|
FlowStep,
|
|
73
78
|
)
|
|
74
79
|
from rasa.shared.core.flows.steps.collect import SlotRejection
|
|
80
|
+
from rasa.shared.core.slots import Slot
|
|
75
81
|
from rasa.shared.core.trackers import (
|
|
76
82
|
DialogueStateTracker,
|
|
77
83
|
)
|
|
@@ -397,7 +403,6 @@ def advance_flows_until_next_action(
|
|
|
397
403
|
number_of_steps_taken = 0
|
|
398
404
|
|
|
399
405
|
while isinstance(step_result, ContinueFlowWithNextStep):
|
|
400
|
-
|
|
401
406
|
number_of_steps_taken += 1
|
|
402
407
|
if number_of_steps_taken > MAX_NUMBER_OF_STEPS:
|
|
403
408
|
raise FlowCircuitBreakerTrippedException(
|
|
@@ -467,6 +472,87 @@ def advance_flows_until_next_action(
|
|
|
467
472
|
return FlowActionPrediction(None, 0.0, events=gathered_events)
|
|
468
473
|
|
|
469
474
|
|
|
475
|
+
def validate_collect_step(
|
|
476
|
+
step: CollectInformationFlowStep,
|
|
477
|
+
stack: DialogueStack,
|
|
478
|
+
available_actions: List[str],
|
|
479
|
+
slots: Dict[Text, Slot],
|
|
480
|
+
) -> bool:
|
|
481
|
+
"""Validate that a collect step can be executed.
|
|
482
|
+
|
|
483
|
+
A collect step can be executed if either the `utter_ask` or the `action_ask` is
|
|
484
|
+
defined in the domain. If neither is defined, the collect step can still be
|
|
485
|
+
executed if the slot has an initial value defined in the domain, which would cause
|
|
486
|
+
the step to be skipped."""
|
|
487
|
+
slot = slots.get(step.collect)
|
|
488
|
+
slot_has_initial_value_defined = slot and slot.initial_value is not None
|
|
489
|
+
if (
|
|
490
|
+
slot_has_initial_value_defined
|
|
491
|
+
or step.utter in available_actions
|
|
492
|
+
or step.collect_action in available_actions
|
|
493
|
+
):
|
|
494
|
+
return True
|
|
495
|
+
|
|
496
|
+
structlogger.error(
|
|
497
|
+
"flow.step.run.collect_missing_utter_or_collect_action",
|
|
498
|
+
slot_name=step.collect,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
cancel_flow_and_push_internal_error(stack)
|
|
502
|
+
|
|
503
|
+
return False
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def cancel_flow_and_push_internal_error(stack: DialogueStack) -> None:
|
|
507
|
+
"""Cancel the top user flow and push the internal error pattern."""
|
|
508
|
+
top_frame = stack.top()
|
|
509
|
+
|
|
510
|
+
if isinstance(top_frame, BaseFlowStackFrame):
|
|
511
|
+
# we need to first cancel the top user flow
|
|
512
|
+
# because we cannot collect one of its slots
|
|
513
|
+
# and therefore should not proceed with the flow
|
|
514
|
+
# after triggering pattern_internal_error
|
|
515
|
+
canceled_frames = CancelFlowCommand.select_canceled_frames(stack)
|
|
516
|
+
stack.push(
|
|
517
|
+
CancelPatternFlowStackFrame(
|
|
518
|
+
canceled_name=top_frame.flow_id,
|
|
519
|
+
canceled_frames=canceled_frames,
|
|
520
|
+
)
|
|
521
|
+
)
|
|
522
|
+
stack.push(InternalErrorPatternFlowStackFrame())
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def validate_custom_slot_mappings(
|
|
526
|
+
step: CollectInformationFlowStep,
|
|
527
|
+
stack: DialogueStack,
|
|
528
|
+
tracker: DialogueStateTracker,
|
|
529
|
+
available_actions: List[str],
|
|
530
|
+
) -> bool:
|
|
531
|
+
"""Validate a slot with custom mappings.
|
|
532
|
+
|
|
533
|
+
If invalid, trigger pattern_internal_error and return False.
|
|
534
|
+
"""
|
|
535
|
+
slot = tracker.slots.get(step.collect, None)
|
|
536
|
+
slot_mappings = slot.mappings if slot else []
|
|
537
|
+
for mapping in slot_mappings:
|
|
538
|
+
if (
|
|
539
|
+
mapping.get("type") == SlotMappingType.CUSTOM.value
|
|
540
|
+
and mapping.get("action") is None
|
|
541
|
+
):
|
|
542
|
+
# this is a slot that must be filled by a custom action
|
|
543
|
+
# check if collect_action exists
|
|
544
|
+
if step.collect_action not in available_actions:
|
|
545
|
+
structlogger.error(
|
|
546
|
+
"flow.step.run.collect_action_not_found_for_custom_slot_mapping",
|
|
547
|
+
action=step.collect_action,
|
|
548
|
+
collect=step.collect,
|
|
549
|
+
)
|
|
550
|
+
cancel_flow_and_push_internal_error(stack)
|
|
551
|
+
return False
|
|
552
|
+
|
|
553
|
+
return True
|
|
554
|
+
|
|
555
|
+
|
|
470
556
|
def run_step(
|
|
471
557
|
step: FlowStep,
|
|
472
558
|
flow: Flow,
|
|
@@ -500,6 +586,22 @@ def run_step(
|
|
|
500
586
|
initial_events.append(FlowStarted(flow.id))
|
|
501
587
|
|
|
502
588
|
if isinstance(step, CollectInformationFlowStep):
|
|
589
|
+
is_step_valid = validate_collect_step(
|
|
590
|
+
step, stack, available_actions, tracker.slots
|
|
591
|
+
)
|
|
592
|
+
if not is_step_valid:
|
|
593
|
+
# if we return any other FlowStepResult, the assistant will stay silent
|
|
594
|
+
# instead of triggering the internal error pattern
|
|
595
|
+
return ContinueFlowWithNextStep(events=initial_events)
|
|
596
|
+
|
|
597
|
+
is_mapping_valid = validate_custom_slot_mappings(
|
|
598
|
+
step, stack, tracker, available_actions
|
|
599
|
+
)
|
|
600
|
+
if not is_mapping_valid:
|
|
601
|
+
# if we return any other FlowStepResult, the assistant will stay silent
|
|
602
|
+
# instead of triggering the internal error pattern
|
|
603
|
+
return ContinueFlowWithNextStep(events=initial_events)
|
|
604
|
+
|
|
503
605
|
structlogger.debug("flow.step.run.collect")
|
|
504
606
|
trigger_pattern_ask_collect_information(
|
|
505
607
|
step.collect, stack, step.rejections, step.utter, step.collect_action
|
|
@@ -3,7 +3,6 @@ import math
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Text, Tuple
|
|
5
5
|
|
|
6
|
-
import rasa.shared.utils.io
|
|
7
6
|
import structlog
|
|
8
7
|
import tiktoken
|
|
9
8
|
from jinja2 import Template
|
|
@@ -11,6 +10,7 @@ from langchain.docstore.document import Document
|
|
|
11
10
|
from langchain.schema.embeddings import Embeddings
|
|
12
11
|
from langchain.vectorstores import FAISS
|
|
13
12
|
|
|
13
|
+
import rasa.shared.utils.io
|
|
14
14
|
from rasa import telemetry
|
|
15
15
|
from rasa.core.constants import (
|
|
16
16
|
CHAT_POLICY_PRIORITY,
|
|
@@ -56,7 +56,6 @@ from rasa.shared.utils.llm import (
|
|
|
56
56
|
sanitize_message_for_prompt,
|
|
57
57
|
tracker_as_readable_transcript,
|
|
58
58
|
)
|
|
59
|
-
|
|
60
59
|
from rasa.utils.ml_utils import (
|
|
61
60
|
extract_ai_response_examples,
|
|
62
61
|
extract_participant_messages_from_transcript,
|
|
@@ -65,7 +64,6 @@ from rasa.utils.ml_utils import (
|
|
|
65
64
|
persist_faiss_vector_store,
|
|
66
65
|
response_for_template,
|
|
67
66
|
)
|
|
68
|
-
|
|
69
67
|
from rasa.utils.log_utils import log_llm
|
|
70
68
|
|
|
71
69
|
if TYPE_CHECKING:
|
|
@@ -543,7 +541,9 @@ class IntentlessPolicy(Policy):
|
|
|
543
541
|
Returns:
|
|
544
542
|
The prediction.
|
|
545
543
|
"""
|
|
546
|
-
if not self.supports_current_stack_frame(
|
|
544
|
+
if not self.supports_current_stack_frame(
|
|
545
|
+
tracker
|
|
546
|
+
) or self.should_abstain_in_coexistence(tracker, True):
|
|
547
547
|
return self._prediction(self._default_predictions(domain))
|
|
548
548
|
|
|
549
549
|
if tracker.has_bot_message_after_latest_user_message():
|
|
@@ -670,7 +670,7 @@ class IntentlessPolicy(Policy):
|
|
|
670
670
|
if tracker.latest_message.text.startswith("/"):
|
|
671
671
|
# we don't want to generate a response if the user is trying to
|
|
672
672
|
# execute a "command" - this should be handled by the regex
|
|
673
|
-
# intent classifier in rasa
|
|
673
|
+
# intent classifier in rasa pro.
|
|
674
674
|
structlogger.debug("intentless_policy.prediction.skip_slash")
|
|
675
675
|
return None, 0.0
|
|
676
676
|
|
|
@@ -863,7 +863,7 @@ class IntentlessPolicy(Policy):
|
|
|
863
863
|
"""
|
|
864
864
|
result = self._default_predictions(domain)
|
|
865
865
|
if action_name:
|
|
866
|
-
result[domain.index_for_action(action_name)] = score # type: ignore[assignment]
|
|
866
|
+
result[domain.index_for_action(action_name)] = score # type: ignore[assignment]
|
|
867
867
|
return result
|
|
868
868
|
|
|
869
869
|
@classmethod
|
|
@@ -892,9 +892,7 @@ class IntentlessPolicy(Policy):
|
|
|
892
892
|
# normalized. unfortunatley langchain doesn't persist / load
|
|
893
893
|
# this parameter.
|
|
894
894
|
if responses_docsearch:
|
|
895
|
-
responses_docsearch._normalize_L2 =
|
|
896
|
-
True # pylint: disable=protected-access
|
|
897
|
-
)
|
|
895
|
+
responses_docsearch._normalize_L2 = True # pylint: disable=protected-access
|
|
898
896
|
prompt_template = rasa.shared.utils.io.read_file(
|
|
899
897
|
path / INTENTLESS_PROMPT_TEMPLATE_FILE_NAME
|
|
900
898
|
)
|