rasa-pro 3.13.0.dev2__py3-none-any.whl → 3.13.0.dev3__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/cli/run.py +10 -6
- rasa/cli/utils.py +7 -0
- rasa/core/channels/channel.py +30 -0
- rasa/core/channels/voice_ready/jambonz.py +25 -5
- rasa/core/channels/voice_ready/jambonz_protocol.py +4 -0
- rasa/core/information_retrieval/faiss.py +7 -68
- rasa/core/information_retrieval/information_retrieval.py +2 -40
- rasa/core/information_retrieval/milvus.py +2 -7
- rasa/core/information_retrieval/qdrant.py +2 -7
- rasa/core/nlg/contextual_response_rephraser.py +3 -0
- rasa/core/policies/enterprise_search_policy.py +310 -61
- rasa/core/policies/intentless_policy.py +3 -0
- rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
- rasa/dialogue_understanding/generator/command_parser.py +1 -1
- rasa/dialogue_understanding/generator/flow_retrieval.py +1 -4
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -2
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +13 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +2 -24
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +22 -17
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +27 -12
- rasa/dialogue_understanding_test/io.py +8 -13
- rasa/e2e_test/utils/validation.py +3 -3
- rasa/engine/recipes/default_components.py +0 -2
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +3 -0
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/llm.py +70 -24
- rasa/tracing/instrumentation/attribute_extractors.py +7 -10
- rasa/tracing/instrumentation/instrumentation.py +12 -12
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev2.dist-info → rasa_pro-3.13.0.dev3.dist-info}/METADATA +2 -2
- {rasa_pro-3.13.0.dev2.dist-info → rasa_pro-3.13.0.dev3.dist-info}/RECORD +37 -48
- rasa/document_retrieval/__init__.py +0 -0
- rasa/document_retrieval/constants.py +0 -32
- rasa/document_retrieval/document_post_processor.py +0 -351
- rasa/document_retrieval/document_post_processor_prompt_template.jinja2 +0 -0
- rasa/document_retrieval/document_retriever.py +0 -333
- rasa/document_retrieval/knowledge_base_connectors/__init__.py +0 -0
- rasa/document_retrieval/knowledge_base_connectors/api_connector.py +0 -39
- rasa/document_retrieval/knowledge_base_connectors/knowledge_base_connector.py +0 -34
- rasa/document_retrieval/knowledge_base_connectors/vector_store_connector.py +0 -226
- rasa/document_retrieval/query_rewriter.py +0 -234
- rasa/document_retrieval/query_rewriter_prompt_template.jinja2 +0 -8
- {rasa_pro-3.13.0.dev2.dist-info → rasa_pro-3.13.0.dev3.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev2.dist-info → rasa_pro-3.13.0.dev3.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev2.dist-info → rasa_pro-3.13.0.dev3.dist-info}/entry_points.txt +0 -0
|
@@ -52,6 +52,10 @@ from rasa.shared.exceptions import ProviderClientAPIException
|
|
|
52
52
|
from rasa.shared.nlu.constants import TEXT
|
|
53
53
|
from rasa.shared.nlu.training_data.message import Message
|
|
54
54
|
from rasa.shared.providers.llm.llm_response import LLMResponse
|
|
55
|
+
from rasa.shared.utils.constants import (
|
|
56
|
+
LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
|
|
57
|
+
LOG_COMPONENT_SOURCE_METHOD_INIT,
|
|
58
|
+
)
|
|
55
59
|
from rasa.shared.utils.io import deep_container_fingerprint, raise_deprecation_warning
|
|
56
60
|
from rasa.shared.utils.llm import (
|
|
57
61
|
allowed_values_for_slot,
|
|
@@ -330,6 +334,8 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
330
334
|
return get_prompt_template(
|
|
331
335
|
config.get("prompt_templates", {}).get(key, {}).get(FILE_PATH_KEY),
|
|
332
336
|
default_value,
|
|
337
|
+
log_source_component=MultiStepLLMCommandGenerator.__name__,
|
|
338
|
+
log_source_method=LOG_COMPONENT_SOURCE_METHOD_INIT,
|
|
333
339
|
)
|
|
334
340
|
|
|
335
341
|
@classmethod
|
|
@@ -786,17 +792,24 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
786
792
|
@classmethod
|
|
787
793
|
def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
|
|
788
794
|
"""Add a fingerprint for the graph."""
|
|
795
|
+
get_prompt_template_log_params = {
|
|
796
|
+
"log_source_component": MultiStepLLMCommandGenerator.__name__,
|
|
797
|
+
"log_source_method": LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
|
|
798
|
+
}
|
|
799
|
+
|
|
789
800
|
handle_flows_template = get_prompt_template(
|
|
790
801
|
config.get("prompt_templates", {})
|
|
791
802
|
.get(HANDLE_FLOWS_KEY, {})
|
|
792
803
|
.get(FILE_PATH_KEY),
|
|
793
804
|
DEFAULT_HANDLE_FLOWS_TEMPLATE,
|
|
805
|
+
**get_prompt_template_log_params,
|
|
794
806
|
)
|
|
795
807
|
fill_slots_template = get_prompt_template(
|
|
796
808
|
config.get("prompt_templates", {})
|
|
797
809
|
.get(FILL_SLOTS_KEY, {})
|
|
798
810
|
.get(FILE_PATH_KEY),
|
|
799
811
|
DEFAULT_FILL_SLOTS_TEMPLATE,
|
|
812
|
+
**get_prompt_template_log_params,
|
|
800
813
|
)
|
|
801
814
|
|
|
802
815
|
llm_config = resolve_model_client_config(
|
|
@@ -8,7 +8,7 @@ Your task is to analyze the current conversation context and generate a list of
|
|
|
8
8
|
* `set slot slot_name slot_value`: Slot setting. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
|
|
9
9
|
* `cancel flow`: Cancelling the current flow.
|
|
10
10
|
* `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: Disambiguate which flow should be started when user input is ambiguous by listing the potential flows as options. For example, `disambiguate flows list_contacts add_contact remove_contact ...` if the user just wrote "contacts".
|
|
11
|
-
* `
|
|
11
|
+
* `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
|
|
12
12
|
* `offtopic reply`: Responding to casual or social user messages that are unrelated to any flows, engaging in friendly conversation and addressing off-topic remarks.
|
|
13
13
|
* `hand over`: Handing over to a human, in case the user seems frustrated or explicitly asks to speak to one.
|
|
14
14
|
|
|
@@ -16,9 +16,7 @@ Use the following structured data:
|
|
|
16
16
|
* `set slot slot_name slot_value`: Slot setting. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
|
|
17
17
|
* `cancel flow`: Cancelling the current flow.
|
|
18
18
|
* `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: Disambiguate which flow should be started when user input is ambiguous by listing the potential flows as options. For example, `disambiguate flows list_contacts add_contact remove_contact ...` if the user just wrote "contacts".
|
|
19
|
-
|
|
20
|
-
* `search and reply`: Responding to the user's message by using the relevant FAQs (included in this prompt) retrieved from the knowledge base.
|
|
21
|
-
{%- endif %}
|
|
19
|
+
* `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
|
|
22
20
|
* `offtopic reply`: Responding to casual or social user messages that are unrelated to any flows, engaging in friendly conversation and addressing off-topic remarks.
|
|
23
21
|
* `hand over`: Handing over to a human, in case the user seems frustrated or explicitly asks to speak to one.
|
|
24
22
|
|
|
@@ -29,36 +27,16 @@ Use the following structured data:
|
|
|
29
27
|
* For categorical slots try to match the user message with allowed slot values. Use "other" if you cannot match it.
|
|
30
28
|
* Set the boolean slots based on the user response. Map positive responses to `True`, and negative to `False`.
|
|
31
29
|
* Extract text slot values exactly as provided by the user. Avoid assumptions, format changes, or partial extractions.
|
|
32
|
-
* Use clarification in ambiguous cases.
|
|
33
|
-
* Use `disambiguate flows` only when multiple flows could fit the same message (e.g., "card" could mean `block_card` or `replace_card`).
|
|
34
|
-
{%- if relevant_documents.results %}
|
|
35
|
-
* A user asking a question does not automatically imply that they want `search and reply`. The objective is to help them complete a business process if its possible to do so via a flow.
|
|
36
|
-
* **Flow Priority**: If a user message can be addressed by starting a flow (even if it looks like a general question), ALWAYS start the flow first. Example: If the user says "How do I activate my card?", use `start flow activate_card` instead of `search and reply`. Only use `search and reply` if no flow matches the request.
|
|
37
|
-
{%- endif %}
|
|
38
30
|
* Only use information provided by the user.
|
|
31
|
+
* Use clarification in ambiguous cases.
|
|
39
32
|
* Multiple flows can be started. If a user wants to digress into a second flow, you do not need to cancel the current flow.
|
|
40
33
|
* Do not cancel the flow unless the user explicitly requests it.
|
|
41
34
|
* Strictly adhere to the provided action format.
|
|
42
35
|
* Focus on the last message and take it one step at a time.
|
|
43
36
|
* Use the previous conversation steps only to aid understanding.
|
|
44
37
|
|
|
45
|
-
{%- if relevant_documents.results %}
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## Relevant FAQs from the knowledge base
|
|
50
|
-
```json
|
|
51
|
-
{"documents":[{% for document in relevant_documents.results %}{"Q":"{{ document.text }}","A":"{{ document.metadata.answer }}"},{% endfor %}]}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
{% else %}
|
|
57
|
-
|
|
58
38
|
---
|
|
59
39
|
|
|
60
|
-
{% endif -%}
|
|
61
|
-
|
|
62
40
|
## Current State
|
|
63
41
|
{% if current_flow != None %}Use the following structured data:
|
|
64
42
|
```json
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import copy
|
|
2
|
-
from typing import Any, Dict, List, Optional, Text
|
|
2
|
+
from typing import Any, Dict, List, Literal, Optional, Text
|
|
3
3
|
|
|
4
4
|
import structlog
|
|
5
5
|
|
|
6
6
|
import rasa.shared.utils.io
|
|
7
|
-
from rasa.core.information_retrieval import SearchResultList
|
|
8
7
|
from rasa.dialogue_understanding.commands import (
|
|
9
8
|
CannotHandleCommand,
|
|
10
9
|
Command,
|
|
@@ -39,7 +38,6 @@ from rasa.dialogue_understanding.utils import (
|
|
|
39
38
|
add_commands_to_message_parse_data,
|
|
40
39
|
add_prompt_to_message_parse_data,
|
|
41
40
|
)
|
|
42
|
-
from rasa.document_retrieval.constants import POST_PROCESSED_DOCUMENTS_KEY
|
|
43
41
|
from rasa.engine.graph import ExecutionContext
|
|
44
42
|
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
|
|
45
43
|
from rasa.engine.storage.resource import Resource
|
|
@@ -60,6 +58,10 @@ from rasa.shared.exceptions import ProviderClientAPIException
|
|
|
60
58
|
from rasa.shared.nlu.constants import LLM_COMMANDS, LLM_PROMPT, TEXT
|
|
61
59
|
from rasa.shared.nlu.training_data.message import Message
|
|
62
60
|
from rasa.shared.providers.llm.llm_response import LLMResponse
|
|
61
|
+
from rasa.shared.utils.constants import (
|
|
62
|
+
LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
|
|
63
|
+
LOG_COMPONENT_SOURCE_METHOD_INIT,
|
|
64
|
+
)
|
|
63
65
|
from rasa.shared.utils.io import deep_container_fingerprint
|
|
64
66
|
from rasa.shared.utils.llm import (
|
|
65
67
|
allowed_values_for_slot,
|
|
@@ -189,8 +191,8 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
189
191
|
)
|
|
190
192
|
|
|
191
193
|
# Get the prompt template from the config or the default prompt template.
|
|
192
|
-
self.prompt_template = self.
|
|
193
|
-
self.config, prompt_template
|
|
194
|
+
self.prompt_template = self._resolve_component_prompt_template(
|
|
195
|
+
self.config, prompt_template, log_context=LOG_COMPONENT_SOURCE_METHOD_INIT
|
|
194
196
|
)
|
|
195
197
|
|
|
196
198
|
# Set the command syntax version to v2
|
|
@@ -495,10 +497,6 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
495
497
|
latest_user_message = sanitize_message_for_prompt(message.get(TEXT))
|
|
496
498
|
current_conversation += f"\nUSER: {latest_user_message}"
|
|
497
499
|
|
|
498
|
-
relevant_documents = SearchResultList.from_dict(
|
|
499
|
-
message.get(POST_PROCESSED_DOCUMENTS_KEY, [])
|
|
500
|
-
)
|
|
501
|
-
|
|
502
500
|
inputs = {
|
|
503
501
|
"available_flows": self.prepare_flows_for_template(
|
|
504
502
|
startable_flows, tracker
|
|
@@ -512,7 +510,6 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
512
510
|
"current_slot_allowed_values": current_slot_allowed_values,
|
|
513
511
|
"user_message": latest_user_message,
|
|
514
512
|
"is_repeat_command_enabled": self.repeat_command_enabled,
|
|
515
|
-
"relevant_documents": relevant_documents,
|
|
516
513
|
}
|
|
517
514
|
|
|
518
515
|
return self.compile_template(self.prompt_template).render(**inputs)
|
|
@@ -546,7 +543,9 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
546
543
|
# and update the llm config with the resolved llm config.
|
|
547
544
|
_config_copy = copy.deepcopy(config)
|
|
548
545
|
_config_copy[LLM_CONFIG_KEY] = llm_config
|
|
549
|
-
prompt_template = cls.
|
|
546
|
+
prompt_template = cls._resolve_component_prompt_template(
|
|
547
|
+
_config_copy, log_context=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
|
|
548
|
+
)
|
|
550
549
|
|
|
551
550
|
return deep_container_fingerprint(
|
|
552
551
|
[prompt_template, llm_config, embedding_config]
|
|
@@ -562,20 +561,26 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
562
561
|
return CommandSyntaxVersion.v2
|
|
563
562
|
|
|
564
563
|
@staticmethod
|
|
565
|
-
def
|
|
566
|
-
config: Dict[str, Any],
|
|
564
|
+
def _resolve_component_prompt_template(
|
|
565
|
+
config: Dict[str, Any],
|
|
566
|
+
prompt_template: Optional[str] = None,
|
|
567
|
+
log_context: Optional[Literal["init", "fingerprint_addon"]] = None,
|
|
567
568
|
) -> Optional[str]:
|
|
568
569
|
"""Get the prompt template from the config or the default prompt template."""
|
|
569
570
|
# Get the default prompt template based on the model name.
|
|
570
571
|
default_command_prompt_template = get_default_prompt_template_based_on_model(
|
|
571
|
-
config.get(LLM_CONFIG_KEY, {}) or {},
|
|
572
|
-
MODEL_PROMPT_MAPPER,
|
|
573
|
-
DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME,
|
|
574
|
-
FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME,
|
|
572
|
+
llm_config=config.get(LLM_CONFIG_KEY, {}) or {},
|
|
573
|
+
model_prompt_mapping=MODEL_PROMPT_MAPPER,
|
|
574
|
+
default_prompt_path=DEFAULT_COMMAND_PROMPT_TEMPLATE_FILE_NAME,
|
|
575
|
+
fallback_prompt_path=FALLBACK_COMMAND_PROMPT_TEMPLATE_FILE_NAME,
|
|
576
|
+
log_source_component=CompactLLMCommandGenerator.__name__,
|
|
577
|
+
log_source_method=log_context,
|
|
575
578
|
)
|
|
576
579
|
|
|
577
580
|
# Return the prompt template either from the config or the default prompt.
|
|
578
581
|
return prompt_template or get_prompt_template(
|
|
579
582
|
config.get(PROMPT_TEMPLATE_CONFIG_KEY),
|
|
580
583
|
default_command_prompt_template,
|
|
584
|
+
log_source_component=CompactLLMCommandGenerator.__name__,
|
|
585
|
+
log_source_method=log_context,
|
|
581
586
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import importlib.resources
|
|
2
|
-
from typing import Any, Dict, Optional, Text
|
|
2
|
+
from typing import Any, Dict, Literal, Optional, Text
|
|
3
3
|
|
|
4
4
|
import structlog
|
|
5
5
|
|
|
@@ -25,8 +25,12 @@ from rasa.shared.constants import (
|
|
|
25
25
|
PROMPT_CONFIG_KEY,
|
|
26
26
|
PROMPT_TEMPLATE_CONFIG_KEY,
|
|
27
27
|
)
|
|
28
|
+
from rasa.shared.utils.constants import LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
|
|
28
29
|
from rasa.shared.utils.io import deep_container_fingerprint
|
|
29
|
-
from rasa.shared.utils.llm import
|
|
30
|
+
from rasa.shared.utils.llm import (
|
|
31
|
+
get_prompt_template,
|
|
32
|
+
resolve_model_client_config,
|
|
33
|
+
)
|
|
30
34
|
|
|
31
35
|
DEFAULT_COMMAND_PROMPT_TEMPLATE = importlib.resources.read_text(
|
|
32
36
|
"rasa.dialogue_understanding.generator.prompt_templates",
|
|
@@ -72,9 +76,6 @@ class SingleStepLLMCommandGenerator(CompactLLMCommandGenerator):
|
|
|
72
76
|
"Please use the config parameter 'prompt_template' instead. "
|
|
73
77
|
),
|
|
74
78
|
)
|
|
75
|
-
self.prompt_template = self.resolve_component_prompt_template(
|
|
76
|
-
config, prompt_template
|
|
77
|
-
)
|
|
78
79
|
|
|
79
80
|
# Set the command syntax version to v1
|
|
80
81
|
CommandSyntaxManager.set_syntax_version(
|
|
@@ -95,7 +96,9 @@ class SingleStepLLMCommandGenerator(CompactLLMCommandGenerator):
|
|
|
95
96
|
@classmethod
|
|
96
97
|
def fingerprint_addon(cls: Any, config: Dict[str, Any]) -> Optional[str]:
|
|
97
98
|
"""Add a fingerprint for the graph."""
|
|
98
|
-
prompt_template = cls.
|
|
99
|
+
prompt_template = cls._resolve_component_prompt_template(
|
|
100
|
+
config, log_context=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
|
|
101
|
+
)
|
|
99
102
|
llm_config = resolve_model_client_config(
|
|
100
103
|
config.get(LLM_CONFIG_KEY), SingleStepLLMCommandGenerator.__name__
|
|
101
104
|
)
|
|
@@ -117,17 +120,29 @@ class SingleStepLLMCommandGenerator(CompactLLMCommandGenerator):
|
|
|
117
120
|
return CommandSyntaxVersion.v1
|
|
118
121
|
|
|
119
122
|
@staticmethod
|
|
120
|
-
def
|
|
121
|
-
config: Dict[str, Any],
|
|
123
|
+
def _resolve_component_prompt_template(
|
|
124
|
+
config: Dict[str, Any],
|
|
125
|
+
prompt_template: Optional[str] = None,
|
|
126
|
+
log_context: Optional[Literal["init", "fingerprint_addon"]] = None,
|
|
122
127
|
) -> Optional[str]:
|
|
123
128
|
"""Get the prompt template from the config or the default prompt template."""
|
|
124
|
-
#
|
|
125
|
-
|
|
129
|
+
# Case when model is being loaded
|
|
130
|
+
if prompt_template is not None:
|
|
131
|
+
return prompt_template
|
|
132
|
+
|
|
133
|
+
# The prompt can be configured in the config via the "prompt" (deprecated) or
|
|
134
|
+
# "prompt_template" properties
|
|
135
|
+
prompt_template_path = (
|
|
126
136
|
config.get(PROMPT_CONFIG_KEY)
|
|
127
137
|
or config.get(PROMPT_TEMPLATE_CONFIG_KEY)
|
|
128
138
|
or None
|
|
129
139
|
)
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
|
|
141
|
+
# Try to load the template from the given path or fallback to the default for
|
|
142
|
+
# the component
|
|
143
|
+
return get_prompt_template(
|
|
144
|
+
prompt_template_path,
|
|
132
145
|
DEFAULT_COMMAND_PROMPT_TEMPLATE,
|
|
146
|
+
log_source_component=SingleStepLLMCommandGenerator.__name__,
|
|
147
|
+
log_source_method=log_context,
|
|
133
148
|
)
|
|
@@ -329,19 +329,14 @@ def print_prompt(step: FailedTestStep) -> None:
|
|
|
329
329
|
rich.print(
|
|
330
330
|
f"[bold] prompt name [/bold]: {prompt_data[KEY_PROMPT_NAME]}"
|
|
331
331
|
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
if KEY_LATENCY in prompt_data:
|
|
342
|
-
rich.print(
|
|
343
|
-
f"[bold] latency [/bold]: {prompt_data[KEY_LATENCY]}"
|
|
344
|
-
)
|
|
332
|
+
rich.print(
|
|
333
|
+
f"[bold] prompt tokens [/bold]: {prompt_data[KEY_PROMPT_TOKENS]}"
|
|
334
|
+
)
|
|
335
|
+
rich.print(
|
|
336
|
+
f"[bold] completion tokens[/bold]: "
|
|
337
|
+
f"{prompt_data[KEY_COMPLETION_TOKENS]}"
|
|
338
|
+
)
|
|
339
|
+
rich.print(f"[bold] latency [/bold]: {prompt_data[KEY_LATENCY]}")
|
|
345
340
|
if KEY_SYSTEM_PROMPT in prompt_data:
|
|
346
341
|
rich.print(
|
|
347
342
|
f"[bold] system prompt [/bold]: "
|
|
@@ -7,6 +7,7 @@ import structlog
|
|
|
7
7
|
import rasa.shared.utils.io
|
|
8
8
|
from rasa.e2e_test.constants import SCHEMA_FILE_PATH
|
|
9
9
|
from rasa.e2e_test.e2e_test_case import Fixture, Metadata
|
|
10
|
+
from rasa.exceptions import ModelNotFound
|
|
10
11
|
from rasa.shared.utils.yaml import read_schema_file
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING:
|
|
@@ -152,10 +153,9 @@ def validate_model_path(model_path: Optional[str], parameter: str, default: str)
|
|
|
152
153
|
return model_path
|
|
153
154
|
|
|
154
155
|
if model_path and not Path(model_path).exists():
|
|
155
|
-
|
|
156
|
+
raise ModelNotFound(
|
|
156
157
|
f"The provided model path '{model_path}' could not be found. "
|
|
157
|
-
|
|
158
|
-
UserWarning,
|
|
158
|
+
"Provide an existing model path."
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
elif model_path is None:
|
|
@@ -13,7 +13,6 @@ from rasa.dialogue_understanding.generator import (
|
|
|
13
13
|
LLMCommandGenerator,
|
|
14
14
|
)
|
|
15
15
|
from rasa.dialogue_understanding.generator.nlu_command_adapter import NLUCommandAdapter
|
|
16
|
-
from rasa.document_retrieval.document_retriever import DocumentRetriever
|
|
17
16
|
from rasa.nlu.classifiers.diet_classifier import DIETClassifier
|
|
18
17
|
from rasa.nlu.classifiers.fallback_classifier import FallbackClassifier
|
|
19
18
|
from rasa.nlu.classifiers.keyword_intent_classifier import KeywordIntentClassifier
|
|
@@ -93,5 +92,4 @@ DEFAULT_COMPONENTS = [
|
|
|
93
92
|
FlowPolicy,
|
|
94
93
|
EnterpriseSearchPolicy,
|
|
95
94
|
IntentlessPolicy,
|
|
96
|
-
DocumentRetriever,
|
|
97
95
|
]
|
|
@@ -19,6 +19,7 @@ from rasa.shared.constants import (
|
|
|
19
19
|
)
|
|
20
20
|
from rasa.shared.exceptions import ProviderClientAPIException
|
|
21
21
|
from rasa.shared.providers.mappings import OPENAI_PROVIDER
|
|
22
|
+
from rasa.shared.utils.constants import LOG_COMPONENT_SOURCE_METHOD_INIT
|
|
22
23
|
from rasa.shared.utils.llm import (
|
|
23
24
|
USER,
|
|
24
25
|
get_prompt_template,
|
|
@@ -54,6 +55,8 @@ class ConversationRephraser:
|
|
|
54
55
|
self.prompt_template = get_prompt_template(
|
|
55
56
|
self.config.get(PROMPT_TEMPLATE_CONFIG_KEY),
|
|
56
57
|
DEFAULT_REPHRASING_PROMPT_TEMPLATE,
|
|
58
|
+
log_source_component=ConversationRephraser.__name__,
|
|
59
|
+
log_source_method=LOG_COMPONENT_SOURCE_METHOD_INIT,
|
|
57
60
|
)
|
|
58
61
|
|
|
59
62
|
@staticmethod
|
rasa/shared/utils/constants.py
CHANGED
|
@@ -5,3 +5,6 @@ DEFAULT_READ_YAML_FILE_CACHE_MAXSIZE = 256
|
|
|
5
5
|
RASA_PRO_BETA_PREDICATES_IN_RESPONSE_CONDITIONS_ENV_VAR_NAME = (
|
|
6
6
|
"RASA_PRO_BETA_PREDICATES_IN_RESPONSE_CONDITIONS"
|
|
7
7
|
)
|
|
8
|
+
|
|
9
|
+
LOG_COMPONENT_SOURCE_METHOD_INIT = "init"
|
|
10
|
+
LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON = "fingerprint_addon"
|
rasa/shared/utils/llm.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import importlib.resources
|
|
2
2
|
import json
|
|
3
|
+
import logging
|
|
3
4
|
from copy import deepcopy
|
|
4
5
|
from functools import wraps
|
|
5
6
|
from typing import (
|
|
@@ -7,6 +8,7 @@ from typing import (
|
|
|
7
8
|
Any,
|
|
8
9
|
Callable,
|
|
9
10
|
Dict,
|
|
11
|
+
Literal,
|
|
10
12
|
Optional,
|
|
11
13
|
Text,
|
|
12
14
|
Type,
|
|
@@ -59,6 +61,7 @@ from rasa.shared.providers.mappings import (
|
|
|
59
61
|
get_embedding_client_from_provider,
|
|
60
62
|
get_llm_client_from_provider,
|
|
61
63
|
)
|
|
64
|
+
from rasa.shared.utils.constants import LOG_COMPONENT_SOURCE_METHOD_INIT
|
|
62
65
|
|
|
63
66
|
if TYPE_CHECKING:
|
|
64
67
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -654,35 +657,59 @@ def embedder_client_factory(
|
|
|
654
657
|
|
|
655
658
|
|
|
656
659
|
def get_prompt_template(
|
|
657
|
-
jinja_file_path: Optional[Text],
|
|
660
|
+
jinja_file_path: Optional[Text],
|
|
661
|
+
default_prompt_template: Text,
|
|
662
|
+
*,
|
|
663
|
+
log_source_component: Optional[Text] = None,
|
|
664
|
+
log_source_method: Optional[Literal["init", "fingerprint_addon"]] = None,
|
|
658
665
|
) -> Text:
|
|
659
666
|
"""Returns the jinja template.
|
|
660
667
|
|
|
661
668
|
Args:
|
|
662
|
-
jinja_file_path:
|
|
663
|
-
|
|
669
|
+
jinja_file_path: The path to the jinja template file. If not provided, the
|
|
670
|
+
default template will be used.
|
|
671
|
+
default_prompt_template: The fallback prompt template to use if no file is
|
|
672
|
+
found or specified.
|
|
673
|
+
log_source_component: The name of the component emitting the log, used to
|
|
674
|
+
identify the source in structured logging.
|
|
675
|
+
log_source_method: The name of the method or function emitting the log for
|
|
676
|
+
better traceability.
|
|
664
677
|
|
|
665
678
|
Returns:
|
|
666
679
|
The prompt template.
|
|
667
680
|
"""
|
|
681
|
+
|
|
668
682
|
try:
|
|
669
683
|
if jinja_file_path is not None:
|
|
670
684
|
prompt_template = rasa.shared.utils.io.read_file(jinja_file_path)
|
|
671
|
-
|
|
672
|
-
|
|
685
|
+
|
|
686
|
+
log_level = (
|
|
687
|
+
logging.INFO
|
|
688
|
+
if log_source_method == LOG_COMPONENT_SOURCE_METHOD_INIT
|
|
689
|
+
else logging.DEBUG
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
structlogger.log(
|
|
693
|
+
log_level,
|
|
694
|
+
"utils.llm.get_prompt_template"
|
|
695
|
+
".custom_prompt_template_read_successfully",
|
|
673
696
|
event_info=(
|
|
674
697
|
f"Custom prompt template read successfully from "
|
|
675
698
|
f"`{jinja_file_path}`."
|
|
676
699
|
),
|
|
677
700
|
prompt_file_path=jinja_file_path,
|
|
701
|
+
log_source_component=log_source_component,
|
|
702
|
+
log_source_method=log_source_method,
|
|
678
703
|
)
|
|
679
704
|
return prompt_template
|
|
680
705
|
except (FileIOException, FileNotFoundException):
|
|
681
706
|
structlogger.warning(
|
|
682
|
-
"utils.llm.get_prompt_template.failed_to_read_custom_prompt_template",
|
|
707
|
+
"utils.llm.get_prompt_template" ".failed_to_read_custom_prompt_template",
|
|
683
708
|
event_info=(
|
|
684
709
|
"Failed to read custom prompt template. Using default template instead."
|
|
685
710
|
),
|
|
711
|
+
log_source_component=log_source_component,
|
|
712
|
+
log_source_method=log_source_method,
|
|
686
713
|
)
|
|
687
714
|
return default_prompt_template
|
|
688
715
|
|
|
@@ -692,50 +719,66 @@ def get_default_prompt_template_based_on_model(
|
|
|
692
719
|
model_prompt_mapping: Dict[str, Any],
|
|
693
720
|
default_prompt_path: str,
|
|
694
721
|
fallback_prompt_path: str,
|
|
722
|
+
*,
|
|
723
|
+
log_source_component: Optional[Text] = None,
|
|
724
|
+
log_source_method: Optional[Literal["init", "fingerprint_addon"]] = None,
|
|
695
725
|
) -> Text:
|
|
696
726
|
"""Returns the default prompt template based on the model name.
|
|
697
727
|
|
|
698
728
|
Args:
|
|
699
729
|
llm_config: The model config.
|
|
700
|
-
model_prompt_mapping: The
|
|
701
|
-
default_prompt_path: The default prompt
|
|
702
|
-
fallback_prompt_path: The fallback prompt path for all other models
|
|
703
|
-
|
|
730
|
+
model_prompt_mapping: The model name -> prompt template mapping.
|
|
731
|
+
default_prompt_path: The path to the default prompt template for the component.
|
|
732
|
+
fallback_prompt_path: The fallback prompt path for all other models that do not
|
|
733
|
+
have a mapping in the model_prompt_mapping.
|
|
734
|
+
log_source_component: The name of the component emitting the log, used to
|
|
735
|
+
identify the source in structured logging.
|
|
736
|
+
log_source_method: The name of the method or function emitting the log for
|
|
737
|
+
better traceability.
|
|
704
738
|
|
|
705
739
|
Returns:
|
|
706
740
|
The default prompt template.
|
|
707
741
|
"""
|
|
742
|
+
# Extract the provider and model name information from the configuration
|
|
708
743
|
_llm_config = deepcopy(llm_config)
|
|
709
744
|
if MODELS_CONFIG_KEY in _llm_config:
|
|
710
745
|
_llm_config = _llm_config[MODELS_CONFIG_KEY][0]
|
|
711
746
|
provider = _llm_config.get(PROVIDER_CONFIG_KEY)
|
|
712
747
|
model = _llm_config.get(MODEL_CONFIG_KEY)
|
|
748
|
+
|
|
749
|
+
# If the model is not defined, we default to the default prompt template.
|
|
713
750
|
if not model:
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
"
|
|
751
|
+
structlogger.debug(
|
|
752
|
+
"utils.llm.get_default_prompt_template_based_on_model"
|
|
753
|
+
".using_default_prompt_template",
|
|
717
754
|
event_info=(
|
|
718
755
|
f"Model not defined in the config. Default prompt template read from"
|
|
719
756
|
f" - `{default_prompt_path}`."
|
|
720
757
|
),
|
|
721
758
|
default_prompt_path=default_prompt_path,
|
|
759
|
+
log_source_component=log_source_component,
|
|
760
|
+
log_source_method=log_source_method,
|
|
722
761
|
)
|
|
723
762
|
return importlib.resources.read_text(
|
|
724
763
|
DEFAULT_PROMPT_PACKAGE_NAME, default_prompt_path
|
|
725
764
|
)
|
|
726
765
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
766
|
+
full_model_name = model if provider and provider in model else f"{provider}/{model}"
|
|
767
|
+
|
|
768
|
+
# If the model is found in the mapping, we use the model-specific prompt
|
|
769
|
+
# template.
|
|
770
|
+
if prompt_file_path := model_prompt_mapping.get(full_model_name):
|
|
771
|
+
structlogger.debug(
|
|
772
|
+
"utils.llm.get_default_prompt_template_based_on_model"
|
|
773
|
+
".using_model_specific_prompt_template",
|
|
733
774
|
event_info=(
|
|
734
775
|
f"Using model-specific default prompt template. Default prompt "
|
|
735
776
|
f"template read from - `{prompt_file_path}`."
|
|
736
777
|
),
|
|
737
778
|
default_prompt_path=prompt_file_path,
|
|
738
|
-
model_name=
|
|
779
|
+
model_name=full_model_name,
|
|
780
|
+
log_source_component=log_source_component,
|
|
781
|
+
log_source_method=log_source_method,
|
|
739
782
|
)
|
|
740
783
|
return importlib.resources.read_text(
|
|
741
784
|
DEFAULT_PROMPT_PACKAGE_NAME, prompt_file_path
|
|
@@ -743,14 +786,17 @@ def get_default_prompt_template_based_on_model(
|
|
|
743
786
|
|
|
744
787
|
# If the model is not found in the mapping, we default to the fallback prompt
|
|
745
788
|
# template.
|
|
746
|
-
structlogger.
|
|
747
|
-
"utils.llm.get_default_prompt_template_based_on_model
|
|
789
|
+
structlogger.debug(
|
|
790
|
+
"utils.llm.get_default_prompt_template_based_on_model"
|
|
791
|
+
".using_fallback_prompt_template",
|
|
748
792
|
event_info=(
|
|
749
793
|
f"Model not found in the model prompt mapping. Fallback prompt template "
|
|
750
794
|
f"read from - `{fallback_prompt_path}`."
|
|
751
795
|
),
|
|
752
796
|
fallback_prompt_path=fallback_prompt_path,
|
|
753
|
-
model_name=
|
|
797
|
+
model_name=full_model_name,
|
|
798
|
+
log_source_component=log_source_component,
|
|
799
|
+
log_source_method=log_source_method,
|
|
754
800
|
)
|
|
755
801
|
return importlib.resources.read_text(
|
|
756
802
|
DEFAULT_PROMPT_PACKAGE_NAME, fallback_prompt_path
|
|
@@ -762,7 +808,7 @@ def allowed_values_for_slot(slot: Slot) -> Union[str, None]:
|
|
|
762
808
|
if isinstance(slot, BooleanSlot):
|
|
763
809
|
return str([True, False])
|
|
764
810
|
if isinstance(slot, CategoricalSlot):
|
|
765
|
-
return str([v for v in slot.values if v != "__other__"]
|
|
811
|
+
return str([v for v in slot.values if v != "__other__"])
|
|
766
812
|
else:
|
|
767
813
|
return None
|
|
768
814
|
|
|
@@ -326,7 +326,7 @@ def extract_attrs_for_command(
|
|
|
326
326
|
def extract_llm_config(
|
|
327
327
|
self: Any,
|
|
328
328
|
default_llm_config: Dict[str, Any],
|
|
329
|
-
default_embeddings_config:
|
|
329
|
+
default_embeddings_config: Dict[str, Any],
|
|
330
330
|
) -> Dict[str, Any]:
|
|
331
331
|
if isinstance(self, ContextualResponseRephraser):
|
|
332
332
|
# ContextualResponseRephraser is not a graph component, so it's
|
|
@@ -346,12 +346,8 @@ def extract_llm_config(
|
|
|
346
346
|
default_embeddings_config,
|
|
347
347
|
)
|
|
348
348
|
else:
|
|
349
|
-
embeddings_property = (
|
|
350
|
-
|
|
351
|
-
config.get(EMBEDDINGS_CONFIG_KEY), default_embeddings_config
|
|
352
|
-
)
|
|
353
|
-
if default_embeddings_config is not None
|
|
354
|
-
else {}
|
|
349
|
+
embeddings_property = combine_custom_and_default_config(
|
|
350
|
+
config.get(EMBEDDINGS_CONFIG_KEY), default_embeddings_config
|
|
355
351
|
)
|
|
356
352
|
|
|
357
353
|
attributes = {
|
|
@@ -406,7 +402,7 @@ def extract_attrs_for_contextual_response_rephraser(
|
|
|
406
402
|
self,
|
|
407
403
|
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
408
404
|
# rephraser is not using embeddings
|
|
409
|
-
default_embeddings_config=
|
|
405
|
+
default_embeddings_config={},
|
|
410
406
|
)
|
|
411
407
|
|
|
412
408
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|
|
@@ -422,7 +418,7 @@ def extract_attrs_for_create_history(
|
|
|
422
418
|
self,
|
|
423
419
|
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
424
420
|
# rephraser is not using embeddings
|
|
425
|
-
default_embeddings_config=
|
|
421
|
+
default_embeddings_config={},
|
|
426
422
|
)
|
|
427
423
|
|
|
428
424
|
|
|
@@ -775,13 +771,14 @@ def extract_attrs_for_enterprise_search_generate_llm_answer(
|
|
|
775
771
|
self: "EnterpriseSearchPolicy", llm: "BaseLLM", prompt: str
|
|
776
772
|
) -> Dict[str, Any]:
|
|
777
773
|
from rasa.core.policies.enterprise_search_policy import (
|
|
774
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
778
775
|
DEFAULT_LLM_CONFIG,
|
|
779
776
|
)
|
|
780
777
|
|
|
781
778
|
attributes = extract_llm_config(
|
|
782
779
|
self,
|
|
783
780
|
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
784
|
-
default_embeddings_config=
|
|
781
|
+
default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
|
|
785
782
|
)
|
|
786
783
|
|
|
787
784
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|